changeset 0:9c0607679772

init
author Ritor1
date Sat, 12 Jan 2013 09:45:18 +0600
parents
children 98b091cbabf7
files .hgignore AIL.cpp AIL.h Actor.cpp Actor.h Allocator.cpp Allocator.h Arcomage.cpp Arcomage.h AudioPlayer.cpp AudioPlayer.h Autonotes.h Awards.h BSPModel.cpp BSPModel.h Bink_Smacker.cpp Bink_Smacker.h CShow.h Chest.cpp Chest.h Debug/AIL.obj Debug/Actor.obj Debug/Allocator.obj Debug/Arcomage.obj Debug/AudioPlayer.obj Debug/BSPModel.obj Debug/Bink_Smacker.obj Debug/CL.read.1.tlog Debug/CL.write.1.tlog Debug/Chest.obj Debug/DecalBuilder.obj Debug/Events.obj Debug/FrameTableInc.obj Debug/GUIButton.obj Debug/GUIFont.obj Debug/GUIProgressBar.obj Debug/GUIWindow.obj Debug/Game.obj Debug/GameUIs.obj Debug/GammaControl.obj Debug/Indoor.obj Debug/IndoorCamera.obj Debug/IndoorCameraD3D.obj Debug/Items.obj Debug/Keyboard.obj Debug/LOD.obj Debug/LayingItem.obj Debug/LightmapBuilder.obj Debug/LightsStack.obj Debug/Log.obj Debug/MM7.exe Debug/MM7.exe.embed.manifest Debug/MM7.exe.embed.manifest.res Debug/MM7.exe.intermediate.manifest Debug/MM7.ilk Debug/MM7.lastbuildstate Debug/MM7.log Debug/MM7.pdb Debug/MM7_manifest.rc Debug/Might and Magic Trilogy.res Debug/Monsters.obj Debug/Mouse.obj Debug/OSAPI.obj Debug/Outdoor.obj Debug/Overlays.obj Debug/PaletteManager.obj Debug/ParticleEngine.obj Debug/Party.obj Debug/Player.obj Debug/RCa04864 Debug/Random.obj Debug/Render.obj Debug/SaveLoad.obj Debug/Spells.obj Debug/Sprites.obj Debug/Texture.obj Debug/TileFrameTable.obj Debug/Time.obj Debug/VideoPlayer.obj Debug/Vis.obj Debug/Weather.obj Debug/cl.command.1.tlog Debug/lib/zlib/adler32.obj Debug/lib/zlib/compress.obj Debug/lib/zlib/crc32.obj Debug/lib/zlib/deflate.obj Debug/lib/zlib/infblock.obj Debug/lib/zlib/infcodes.obj Debug/lib/zlib/inffast.obj Debug/lib/zlib/inflate.obj Debug/lib/zlib/inftrees.obj Debug/lib/zlib/infutil.obj Debug/lib/zlib/trees.obj Debug/lib/zlib/uncompr.obj Debug/lib/zlib/zutil.obj Debug/link-cvtres.read.1.tlog Debug/link-cvtres.write.1.tlog Debug/link.command.1.tlog Debug/link.read.1.tlog Debug/link.write.1.tlog Debug/mm6text.cas Debug/mm6text.non Debug/mm7_1.obj Debug/mm7_2.obj Debug/mm7_3.obj Debug/mm7_4.obj Debug/mm7_5.obj Debug/mm7_6.obj Debug/mm7_data.obj Debug/mt.command.1.tlog Debug/mt.read.1.tlog Debug/mt.write.1.tlog Debug/rc.command.1.tlog Debug/rc.read.1.tlog Debug/rc.write.1.tlog Debug/stru10.obj Debug/stru6.obj Debug/stru9.obj Debug/vc100.idb Debug/vc100.pdb DecalBuilder.cpp DecalBuilder.h DecorationList.h Events.cpp Events.h Events2D.h FactionTable.h FrameTableInc.cpp FrameTableInc.h GUIButton.cpp GUIButton.h GUIFont.cpp GUIFont.h GUIProgressBar.cpp GUIProgressBar.h GUIWindow.cpp GUIWindow.h Game.cpp Game.h GameUIs.cpp GammaControl.cpp GammaControl.h IconFrameTable.h Indoor.cpp Indoor.h IndoorCamera.cpp IndoorCamera.h IndoorCameraD3D.cpp IndoorCameraD3D.h Indoor_stuff.h Items.cpp Items.h Keyboard.cpp Keyboard.h LOD.cpp LOD.h LayingItem.cpp LayingItem.h LightmapBuilder.cpp LightmapBuilder.h Lights.h LightsStack.cpp Log.cpp Log.h MM7.h MM7.sdf MM7.sln MM7.suo MM7.vcxproj MM7.vcxproj.filters MM7.vcxproj.user MM7_manifest.rc MapInfo.h Math.h Might and Magic Trilogy.rc Monsters.cpp Monsters.h Mouse.cpp Mouse.h NPC.h OSAPI.cpp OSAPI.h OSInfo.h ObjectList.h Outdoor.cpp Outdoor.h OutdoorCamera.h Outdoor_stuff.h Overlays.cpp Overlays.h PaletteManager.cpp PaletteManager.h ParticleEngine.cpp ParticleEngine.h Party.cpp Party.h Player.cpp Player.h PlayerFrameTable.h Random.cpp Random.h Render.cpp Render.h SaveLoad.cpp SaveLoad.h Spells.cpp Spells.h Sprites.cpp Sprites.h StorylineTextTable.h Texture.cpp Texture.h TileFrameTable.h Time.cpp Time.h TurnEngine.h VectorTypes.h VideoPlayer.cpp VideoPlayer.h Viewport.h Vis.cpp Vis.h Weather.cpp Weather.h ipch/mm7-91968f84/mm7-c5fbce5d.ipch lib/legacy_dx/d3d.h lib/legacy_dx/d3dcaps.h lib/legacy_dx/d3drm.h lib/legacy_dx/d3drmdef.h lib/legacy_dx/d3drmobj.h lib/legacy_dx/d3drmwin.h lib/legacy_dx/d3dtypes.h lib/legacy_dx/d3dvec.inl lib/legacy_dx/ddraw.h lib/legacy_dx/dinput.h lib/legacy_dx/dinputd.h lib/legacy_dx/dmdls.h lib/legacy_dx/dmerror.h lib/legacy_dx/dmksctrl.h lib/legacy_dx/dmplugin.h lib/legacy_dx/dmusbuff.h lib/legacy_dx/dmusicc.h lib/legacy_dx/dmusicf.h lib/legacy_dx/dmusici.h lib/legacy_dx/dmusics.h lib/legacy_dx/dsconf.h lib/legacy_dx/dsound.h lib/legacy_dx/dvoice.h lib/legacy_dx/lib/.svn/all-wcprops lib/legacy_dx/lib/.svn/entries lib/legacy_dx/lib/.svn/prop-base/d3dxof.lib.svn-base lib/legacy_dx/lib/.svn/prop-base/ddraw.lib.svn-base lib/legacy_dx/lib/.svn/prop-base/dinput.lib.svn-base lib/legacy_dx/lib/.svn/prop-base/dinput8.lib.svn-base lib/legacy_dx/lib/.svn/prop-base/dxguid.lib.svn-base lib/legacy_dx/lib/.svn/text-base/d3dxof.lib.svn-base lib/legacy_dx/lib/.svn/text-base/ddraw.lib.svn-base lib/legacy_dx/lib/.svn/text-base/dinput.lib.svn-base lib/legacy_dx/lib/.svn/text-base/dinput8.lib.svn-base lib/legacy_dx/lib/.svn/text-base/dxguid.lib.svn-base lib/legacy_dx/lib/d3dxof.lib lib/legacy_dx/lib/ddraw.lib lib/legacy_dx/lib/dinput.lib lib/legacy_dx/lib/dinput8.lib lib/legacy_dx/lib/dxguid.lib lib/legacy_dx/multimon.h lib/legacy_dx/rmxfguid.h lib/legacy_dx/rmxftmpl.h lib/legacy_dx/strsafe.h lib/zlib/adler32.c lib/zlib/compress.c lib/zlib/crc32.c lib/zlib/deflate.c lib/zlib/deflate.h lib/zlib/infblock.c lib/zlib/infblock.h lib/zlib/infcodes.c lib/zlib/infcodes.h lib/zlib/inffast.c lib/zlib/inffast.h lib/zlib/inffixed.h lib/zlib/inflate.c lib/zlib/inftrees.c lib/zlib/inftrees.h lib/zlib/infutil.c lib/zlib/infutil.h lib/zlib/trees.c lib/zlib/trees.h lib/zlib/uncompr.c lib/zlib/zconf.h lib/zlib/zlib.h lib/zlib/zutil.c lib/zlib/zutil.h mm7_1.cpp mm7_2.cpp mm7_3.cpp mm7_4.cpp mm7_5.cpp mm7_6.cpp mm7_data.cpp mm7_data.h resource.h stru10.cpp stru10.h stru11.h stru12.h stru123.h stru157.h stru159.h stru160.h stru176.h stru179.h stru220.h stru272.h stru277.h stru279.h stru287.h stru298.h stru314.h stru351.h stru6.cpp stru6.h stru9.cpp stru9.h
diffstat 323 files changed, 225347 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AIL.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,394 @@
+#include "AIL.h"
+
+
+
+
+int (__stdcall *mss32_AIL_startup)() = 0;
+HREDBOOK (__stdcall *mss32_AIL_redbook_open_drive)(long) = 0;
+int (__stdcall *mss32_AIL_set_preference)(unsigned int, int) = 0;
+int (__stdcall *mss32_AIL_waveOutOpen)(HDIGDRIVER *, HWAVEOUT *, int, WAVEFORMAT *) = 0;
+int (__stdcall *mss32_AIL_get_preference)(unsigned int) = 0;
+int (__stdcall *mss32_AIL_digital_configuration)(HDIGDRIVER, int *, int *, char *) = 0;
+HSAMPLE (__stdcall *mss32_AIL_allocate_sample_handle)(HDIGDRIVER) = 0;
+unsigned int (__stdcall *mss32_AIL_redbook_tracks)(HREDBOOK) = 0;
+int (__stdcall *mss32_AIL_redbook_volume)(HREDBOOK) = 0;
+unsigned int (__stdcall *mss32_AIL_redbook_stop)(HREDBOOK) = 0;
+void (__stdcall *mss32_AIL_set_digital_master_volume)(HDIGDRIVER, float) = 0;
+int (__stdcall *mss32_AIL_redbook_set_volume)(HREDBOOK, int) = 0;
+unsigned int (__stdcall *mss32_AIL_redbook_pause)(HREDBOOK) = 0;
+void (__stdcall *mss32_AIL_redbook_track_info)(HREDBOOK, unsigned int, unsigned int *, unsigned int *) = 0;
+unsigned int (__stdcall *mss32_AIL_redbook_play)(HREDBOOK, unsigned int, unsigned int) = 0;
+unsigned int (__stdcall *mss32_AIL_redbook_resume)(HREDBOOK) = 0;
+AIL::Sample::Status (__stdcall *mss32_AIL_sample_status)(HSAMPLE) = 0;
+int (__stdcall *mss32_AIL_sample_volume)(HSAMPLE) = 0;
+int (__stdcall *mss32_AIL_enumerate_3D_providers)(int *, HPROVIDER *, char **) = 0;
+DWORD (__stdcall *mss32_AIL_open_3D_provider)(HPROVIDER) = 0;
+int (__stdcall *mss32_AIL_end_sample)(HSAMPLE) = 0;
+int (__stdcall *mss32_AIL_set_sample_volume)(HSAMPLE, long) = 0;
+int (__stdcall *mss32_AIL_set_sample_pan)(HSAMPLE, long) = 0;
+void (__stdcall *mss32_AIL_end_sequence)(HSEQUENCE) = 0;
+void (__stdcall *mss32_AIL_pause_stream)(HSTREAM, int) = 0;
+void (__stdcall *mss32_AIL_init_sample)(HSAMPLE) = 0;
+int (__stdcall *mss32_AIL_set_sample_file)(HSAMPLE, const void *, int) = 0;
+void (__stdcall *mss32_AIL_set_sample_loop_count)(HSAMPLE, int) = 0;
+void (__stdcall *mss32_AIL_set_sample_playback_rate)(HSAMPLE, int) = 0;
+void (__stdcall *mss32_AIL_sample_ms_position)(HSAMPLE, int *, int *) = 0;
+void (__stdcall *mss32_AIL_start_sample)(HSAMPLE) = 0;
+AILFILETYPE (__stdcall *mss32_AIL_file_type)(void *, int) = 0;
+int (__stdcall *mss32_AIL_WAV_info)(void *, AILSOUNDINFO *) = 0;
+int (__stdcall *mss32_AIL_decompress_ADPCM)(AILSOUNDINFO *, void *, void *) = 0;
+HREDBOOK (__stdcall *mss32_AIL_redbook_open)(int) = 0;
+void MSS32_DLL_Initialize()
+{
+ HMODULE pDll = LoadLibraryW(L"mss32.dll");
+
+ mss32_AIL_startup = (int (__stdcall *)())GetProcAddress(pDll, "_AIL_startup@0");
+ mss32_AIL_redbook_open_drive = (HREDBOOK (__stdcall *)(long))GetProcAddress(pDll, "_AIL_redbook_open_drive@4");
+ mss32_AIL_set_preference = (int (__stdcall *)(unsigned int, int))GetProcAddress(pDll, "_AIL_set_preference@8");
+ mss32_AIL_waveOutOpen = (int (__stdcall *)(HDIGDRIVER *, HWAVEOUT *, int, WAVEFORMAT *))GetProcAddress(pDll, "_AIL_waveOutOpen@16");
+ mss32_AIL_get_preference = (int (__stdcall *)(unsigned int))GetProcAddress(pDll, "_AIL_get_preference@4");
+ mss32_AIL_digital_configuration = (int (__stdcall *)(HDIGDRIVER, int *, int *, char *))GetProcAddress(pDll, "_AIL_digital_configuration@16");
+ mss32_AIL_allocate_sample_handle = (HSAMPLE (__stdcall *)(HDIGDRIVER))GetProcAddress(pDll, "_AIL_allocate_sample_handle@4");
+ mss32_AIL_redbook_tracks = (unsigned int (__stdcall *)(HREDBOOK))GetProcAddress(pDll, "_AIL_redbook_tracks@4");
+ mss32_AIL_redbook_volume = (int (__stdcall *)(HREDBOOK))GetProcAddress(pDll, "_AIL_redbook_volume@4");
+ mss32_AIL_redbook_stop = (unsigned int (__stdcall *)(HREDBOOK))GetProcAddress(pDll, "_AIL_redbook_stop@4");
+ mss32_AIL_set_digital_master_volume = (void (__stdcall *)(HDIGDRIVER, float))GetProcAddress(pDll, "_AIL_set_digital_master_volume@8");
+ mss32_AIL_redbook_set_volume = (int (__stdcall *)(HREDBOOK, int))GetProcAddress(pDll, "_AIL_redbook_set_volume@8");
+ mss32_AIL_redbook_pause = (unsigned int (__stdcall *)(HREDBOOK))GetProcAddress(pDll, "_AIL_redbook_pause@4");
+ mss32_AIL_redbook_track_info = (void (__stdcall *)(HREDBOOK, unsigned int, unsigned int *, unsigned int *))GetProcAddress(pDll, "_AIL_redbook_track_info@16");
+ mss32_AIL_redbook_play = (unsigned int (__stdcall *)(HREDBOOK, unsigned int, unsigned int))GetProcAddress(pDll, "_AIL_redbook_play@12");
+ mss32_AIL_redbook_resume = (unsigned int (__stdcall *)(HREDBOOK))GetProcAddress(pDll, "_AIL_redbook_resume@4");
+ mss32_AIL_sample_status = (AIL::Sample::Status (__stdcall *)(HSAMPLE))GetProcAddress(pDll, "_AIL_sample_status@4");
+ mss32_AIL_sample_volume = (int (__stdcall *)(HSAMPLE))GetProcAddress(pDll, "_AIL_sample_volume@4");
+ mss32_AIL_enumerate_3D_providers = (int (__stdcall *)(int *, HPROVIDER *, char **))GetProcAddress(pDll, "_AIL_enumerate_3D_providers@12");
+ mss32_AIL_open_3D_provider = (DWORD (__stdcall *)(HPROVIDER))GetProcAddress(pDll, "_AIL_open_3D_provider@4");
+ mss32_AIL_end_sample = (int (__stdcall *)(HSAMPLE))GetProcAddress(pDll, "_AIL_end_sample@4");
+ mss32_AIL_set_sample_volume = (int (__stdcall *)(HSAMPLE, long))GetProcAddress(pDll, "_AIL_set_sample_volume@8");
+ mss32_AIL_set_sample_pan = (int (__stdcall *)(HSAMPLE, long))GetProcAddress(pDll, "_AIL_set_sample_pan@8");
+ mss32_AIL_end_sequence = (void (__stdcall *)(HSEQUENCE))GetProcAddress(pDll, "_AIL_end_sequence@4");
+ mss32_AIL_pause_stream = (void (__stdcall *)(HSTREAM, int))GetProcAddress(pDll, "_AIL_pause_stream@8");
+ mss32_AIL_init_sample = (void (__stdcall *)(HSAMPLE))GetProcAddress(pDll, "_AIL_init_sample@4");
+ mss32_AIL_set_sample_file = (int (__stdcall *)(HSAMPLE, const void *, int))GetProcAddress(pDll, "_AIL_set_sample_file@12");
+ mss32_AIL_set_sample_loop_count = (void (__stdcall *)(HSAMPLE, int))GetProcAddress(pDll, "_AIL_set_sample_loop_count@8");
+ mss32_AIL_set_sample_playback_rate = (void (__stdcall *)(HSAMPLE, int))GetProcAddress(pDll, "_AIL_set_sample_playback_rate@8");
+ mss32_AIL_sample_ms_position = (void (__stdcall *)(HSAMPLE, int *, int *))GetProcAddress(pDll, "_AIL_sample_ms_position@12");
+ mss32_AIL_start_sample = (void (__stdcall *)(HSAMPLE))GetProcAddress(pDll, "_AIL_start_sample@4");
+ mss32_AIL_file_type = (AILFILETYPE (__stdcall *)(void *, int))GetProcAddress(pDll, "_AIL_file_type@8");
+ mss32_AIL_WAV_info = (int (__stdcall *)(void *, AILSOUNDINFO *))GetProcAddress(pDll, "_AIL_WAV_info@8");
+ mss32_AIL_decompress_ADPCM = (int (__stdcall *)(AILSOUNDINFO *, void *, void *))GetProcAddress(pDll, "_AIL_decompress_ADPCM@12");
+ mss32_AIL_redbook_open = (HREDBOOK (__stdcall *)(int))GetProcAddress(pDll, "_AIL_redbook_open@4");
+}
+
+
+
+unsigned int __stdcall AIL_redbook_play(HREDBOOK hRedbook, unsigned int uStartMS, unsigned int uEndMS)
+{
+ return (mss32_AIL_redbook_play)(hRedbook, uStartMS, uEndMS);
+}
+
+void __stdcall AIL_redbook_track_info(HREDBOOK hRedbook, unsigned int uTrackNum, unsigned int *pStartMS, unsigned int *pEndMS)
+{
+ (mss32_AIL_redbook_track_info)(hRedbook, uTrackNum, pStartMS, pEndMS);
+}
+
+unsigned int __stdcall AIL_redbook_resume(HREDBOOK hRedbook)
+{
+ return (mss32_AIL_redbook_resume)(hRedbook);
+}
+
+int __stdcall AIL_enumerate_3D_providers(int *a1, HPROVIDER *pOutProv, char **pOutName)
+{
+ return (mss32_AIL_enumerate_3D_providers)(a1, pOutProv, pOutName);
+}
+HREDBOOK __stdcall AIL_redbook_open(int w)
+{
+ return (mss32_AIL_redbook_open)(w);
+}
+
+
+int __stdcall AIL_sample_volume(HSAMPLE s)
+{
+ return (mss32_AIL_sample_volume)(s);
+}
+
+AIL::Sample::Status __stdcall AIL_sample_status(HSAMPLE a1)
+{
+ return (mss32_AIL_sample_status)(a1);
+}
+
+// sub_4D8304: using guessed type int __stdcall AIL_set_digital_master_volume(_DWORD, _DWORD);
+void __stdcall AIL_set_digital_master_volume(HDIGDRIVER hDrv, float master_volume)
+{
+ (mss32_AIL_set_digital_master_volume)(hDrv, master_volume);
+}
+
+// sub_4D8370: using guessed type int __stdcall AIL_allocate_sample_handle(_DWORD);
+HSAMPLE __stdcall AIL_allocate_sample_handle(HDIGDRIVER hDrv)
+{
+ return (mss32_AIL_allocate_sample_handle)(hDrv);
+}
+
+// sub_4D8308: using guessed type int __fastcall AIL_redbook_set_volume(_DWORD, _DWORD, _DWORD, _DWORD);
+int __stdcall AIL_redbook_set_volume(HREDBOOK hRedbook, int volume)
+{
+ return (mss32_AIL_redbook_set_volume)(hRedbook, volume);
+}
+
+// sub_4D8324: using guessed type int __stdcall AIL_redbook_stop(_DWORD);
+unsigned int __stdcall AIL_redbook_stop(HREDBOOK hRedbook)
+{
+ return (mss32_AIL_redbook_stop)(hRedbook);
+}
+
+// sub_4D835C: using guessed type int __stdcall AIL_startup();
+int __stdcall AIL_startup()
+{
+ return (mss32_AIL_startup)();
+}
+
+// sub_4D8360: using guessed type int __stdcall AIL_redbook_open_drive(_DWORD);
+HREDBOOK __stdcall AIL_redbook_open_drive(long drive)
+{
+ return (mss32_AIL_redbook_open_drive)(drive);
+}
+
+// sub_4D834C: using guessed type int __stdcall AIL_waveOutOpen(_DWORD, _DWORD, _DWORD, _DWORD);
+int __stdcall AIL_waveOutOpen(HDIGDRIVER *drv, HWAVEOUT *phWaveOut, int wDeviceID, WAVEFORMAT *pFormat)
+{
+ return (mss32_AIL_waveOutOpen)(drv, phWaveOut, wDeviceID, pFormat);
+}
+
+
+DWORD __stdcall AIL_open_3D_provider(HPROVIDER a2)
+{
+ return (mss32_AIL_open_3D_provider)(a2);
+}
+
+int __stdcall AIL_3D_provider_attribute(HPROVIDER a1, const char *a2, int *a3)
+{
+ __asm int 3
+ return 0;
+}
+
+// sub_4D8374: using guessed type int __stdcall AIL_redbook_tracks(_DWORD);
+unsigned int __stdcall AIL_redbook_tracks(HREDBOOK hRedbook)
+{
+ return (mss32_AIL_redbook_tracks)(hRedbook);
+}
+
+// sub_4D83B0: using guessed type int __stdcall AIL_redbook_volume(_DWORD);
+int __stdcall AIL_redbook_volume(HREDBOOK hRedbook)
+{
+ return (mss32_AIL_redbook_volume)(hRedbook);
+}
+
+// sub_4D8348: using guessed type int __stdcall AIL_set_preference(_DWORD, _DWORD);
+int __stdcall AIL_set_preference(unsigned int number, int value)
+{
+ return (mss32_AIL_set_preference)(number, value);
+}
+
+// sub_4D8350: using guessed type int __stdcall AIL_digital_configuration(_DWORD, _DWORD, _DWORD, _DWORD);
+int __stdcall AIL_digital_configuration(HDIGDRIVER drv, int *rate, int *format, char *string)
+{
+ return (mss32_AIL_digital_configuration)(drv, rate, format, string);
+}
+
+// sub_4D8354: using guessed type int __stdcall AIL_get_preference(_DWORD);
+int __stdcall AIL_get_preference(unsigned int number)
+{
+ return (mss32_AIL_get_preference)(number);
+}
+
+int __stdcall AIL_waveOutClose(_DIG_DRIVER *)
+{
+ __asm int 3
+ return 0;
+}
+
+// sub_4D8320: using guessed type int __stdcall AIL_redbook_pause(_DWORD);
+unsigned int __stdcall AIL_redbook_pause(HREDBOOK hRedbook)
+{
+ return (mss32_AIL_redbook_pause)(hRedbook);
+}
+
+int __stdcall AIL_set_3D_provider_preference(HPROVIDER a1, const char *a2, int *a3)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_allocate_3D_sample_handle(HPROVIDER)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_set_3D_sample_float_distances(void *a1, long a2, long a3, long a4, long a5)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_set_3D_sample_volume(void *a1, long a2)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_release_sample_handle(void *a1)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_release_3D_sample_handle(void *a1)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_close_3D_provider(HPROVIDER)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_redbook_close(HREDBOOK a1)
+{
+ __asm int 3
+ return 0;
+}
+
+// sub_4D8344: using guessed type int __stdcall AIL_shutdown();
+int __stdcall AIL_shutdown()
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_end_sample(HSAMPLE a1)
+{
+ return (mss32_AIL_end_sample)(a1);
+}
+
+int __stdcall AIL_end_3D_sample(void *a1)
+{
+ __debugbreak();
+ return 0;
+}
+
+
+void __stdcall AIL_end_sequence(HSEQUENCE a1)
+{
+ (mss32_AIL_end_sequence)(a1);
+}
+
+void __stdcall AIL_pause_stream(HSTREAM a1, int onoff)
+{
+ (mss32_AIL_pause_stream)(a1, onoff);
+}
+
+int __stdcall AIL_set_sample_file(HSAMPLE s, const void *file_image, int block)
+{
+ return (mss32_AIL_set_sample_file)(s, file_image, block);
+}
+
+void __stdcall AIL_start_sample(HSAMPLE s)
+{
+ (mss32_AIL_start_sample)(s);
+}
+
+void __stdcall AIL_set_sample_playback_rate(HSAMPLE s, int rate)
+{
+ (mss32_AIL_set_sample_playback_rate)(s, rate);
+}
+
+void __stdcall AIL_sample_ms_position(HSAMPLE s, int *pTotalMS, int *pCurrentMS)
+{
+ (mss32_AIL_sample_ms_position)(s, pTotalMS, pCurrentMS);
+}
+
+int __stdcall AIL_3D_sample_status(void *a1)
+{
+ __asm int 3
+ return 0;
+}
+
+void __stdcall AIL_set_sample_loop_count(HSAMPLE s, int num)
+{
+ (mss32_AIL_set_sample_loop_count)(s, num);
+}
+
+int __stdcall AIL_set_sample_volume(HSAMPLE a1, long a2)
+{
+ return (mss32_AIL_set_sample_volume)(a1, a2);
+}
+
+int __stdcall AIL_3D_position(void *a1, int *a2, float *a3, long *a4)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_set_3D_sample_file(long a1, void *a2)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_set_3D_sample_loop_count(long a1, long a2)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_start_3D_sample(long a1)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_set_3D_position(void *hSample, long a2, long a3, long a4)
+{
+ __asm int 3
+ return 0;
+}
+
+int __stdcall AIL_set_3D_orientation(void *hSample, long a2, long a3, long a4, long a5, long a6, long a7)
+{
+ __asm int 3
+ return 0;
+}
+
+void __stdcall AIL_init_sample(HSAMPLE a1)
+{
+ (mss32_AIL_init_sample)(a1);
+}
+
+int __stdcall AIL_set_sample_pan(HSAMPLE a1, long a2)
+{
+ return (mss32_AIL_set_sample_pan)(a1, a2);
+}
+
+
+AILFILETYPE __stdcall AIL_file_type(void *pSoundBytes, int numBytes)
+{
+  return (mss32_AIL_file_type)(pSoundBytes, numBytes);
+}
+
+int __stdcall AIL_WAV_info(void *pSoundBytes, AILSOUNDINFO *pInfo)
+{
+  return (mss32_AIL_WAV_info)(pSoundBytes, pInfo);
+}
+
+int __stdcall AIL_decompress_ADPCM(AILSOUNDINFO *pInfo, void *a2, void *a3)
+{
+  return (mss32_AIL_decompress_ADPCM)(pInfo, a2, a3);
+}
+
+int __stdcall AIL_mem_free_lock(void *a1)
+{
+ __asm int 3
+ return 0;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AIL.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,318 @@
+#pragma once
+#include "OSAPI.h"
+
+
+
+/*  252 */
+enum AILFILETYPE : __int32
+{
+  AILFILETYPE_UNKNOWN = 0x0,
+  AILFILETYPE_PCM_WAV = 0x1,
+  AILFILETYPE_ADPCM_WAV = 0x2,
+  AILFILETYPE_OTHER_WAV = 0x3,
+  AILFILETYPE_VOC = 0x4,
+  AILFILETYPE_MIDI = 0x5,
+  AILFILETYPE_XMIDI = 0x6,
+  AILFILETYPE_7 = 0x7,
+  AILFILETYPE_XMIDI_MLS = 0x8,
+  AILFILETYPE_DLS = 0x9,
+  AILFILETYPE_MLS = 0xA,
+  AILFILETYPE_MPEG_L1_AUDIO = 0xB,
+  AILFILETYPE_MPEG_L2_AUDIO = 0xC,
+  AILFILETYPE_MPEG_L3_AUDIO = 0xD,
+  AILFILETYPE_OTHER_ASI_WAV = 0xE,
+  AILFILETYPE_OTHER_ASI_F = 0xF,
+};
+
+
+
+/*  253 */
+#pragma pack(push, 1)
+struct AILSOUNDINFO
+{
+  int uFormat;
+  void *pData;
+  unsigned int uDataSize;
+  unsigned int uRate;
+  int uBits;
+  int uChannels;
+  unsigned int uSamples;
+  unsigned int uBlockSize;
+  void *pInitial;
+};
+#pragma pack(pop)
+
+
+
+
+//Bink
+typedef struct _BINK    *HBINK;
+typedef struct _BINKBUF *HBINKBUF;
+//Smacker & AIL types
+typedef struct _DIG_DRIVER *HDIGDRIVER;
+typedef struct _SMACK      *HSMACK;
+typedef struct _SMACKBLIT  *HSMACKBLIT;
+typedef struct _SMACKBUF   *HSMACKBUF;
+//AIL
+typedef struct _REDBOOK    *HREDBOOK;
+typedef struct _SAMPLE     *HSAMPLE;
+typedef struct _PROVIDER   *HPROVIDER;
+typedef struct _SEQUENCE   *HSEQUENCE;
+typedef struct _STREAM     *HSTREAM;
+typedef __int32             HATTRIB;
+typedef __int32             HASISTREAM; // Handle to stream being managed by ASI codec
+
+
+
+void MSS32_DLL_Initialize();
+
+#define AILCALL __stdcall
+#define AILCALLBACK __stdcall
+
+
+typedef __int32 (AILCALLBACK FAR * AILASIFETCHCB) (unsigned __int32		user,			// User value passed to ASI_open_stream()
+												void FAR *dest,			// Location to which stream data should be copied by app
+												__int32		bytes_requested, // # of bytes requested by ASI codec
+												__int32		offset);		 // If not -1, application should seek to this point in stream
+
+typedef HASISTREAM (AILCALL FAR *ASI_STREAM_OPEN) (unsigned __int32			user,				// User value passed to fetch callback
+													AILASIFETCHCB fetch_CB,			// Source data fetch handler
+													unsigned __int32			total_size);		// Total size for %-done calculations (0=unknown)
+typedef __int32	(AILCALL FAR *ASI_STREAM_PROCESS) (HASISTREAM	stream,				// Handle of stream
+												void FAR	*buffer,				// Destination for processed data
+												__int32		 buffer_size);		// # of bytes to return in buffer
+typedef __int32 (AILCALL FAR *ASI_STREAM_SEEK)	(HASISTREAM stream,
+													 __int32		stream_offset);
+typedef __int32 (AILCALL FAR *ASI_STREAM_CLOSE) (HASISTREAM stream);
+typedef __int32 (AILCALL FAR *ASI_STREAM_ATTRIBUTE) (HASISTREAM stream,
+												 HATTRIB	attrib);
+typedef __int32 (AILCALL FAR *ASI_STREAM_SET_PREFERENCE) (HASISTREAM stream,
+														HATTRIB	preference,
+														void const FAR	*	value);
+
+typedef struct
+	{
+	ASI_STREAM_OPEN			ASI_stream_open;
+	ASI_STREAM_PROCESS		ASI_stream_process;
+	ASI_STREAM_SEEK			ASI_stream_seek;
+	ASI_STREAM_CLOSE			ASI_stream_close;
+	ASI_STREAM_ATTRIBUTE		ASI_stream_attribute;
+	ASI_STREAM_SET_PREFERENCE ASI_stream_set_preference;
+
+	HATTRIB INPUT_BIT_RATE;
+	HATTRIB INPUT_SAMPLE_RATE;
+	HATTRIB INPUT_BITS;
+	HATTRIB INPUT_CHANNELS;
+	HATTRIB OUTPUT_BIT_RATE;
+	HATTRIB OUTPUT_SAMPLE_RATE;
+	HATTRIB OUTPUT_BITS;
+	HATTRIB OUTPUT_CHANNELS;
+	HATTRIB POSITION;
+	HATTRIB PERCENT_DONE;
+	HATTRIB MIN_INPUT_BLOCK_SIZE;
+	HATTRIB RAW_RATE;
+	HATTRIB RAW_BITS;
+	HATTRIB RAW_CHANNELS;
+	HATTRIB REQUESTED_RATE;
+	HATTRIB REQUESTED_BITS;
+	HATTRIB REQUESTED_CHANS;
+
+	HASISTREAM stream;
+	}
+ASISTAGE;
+
+
+
+
+typedef void (AILCALLBACK FAR* AILSTREAMCB)(HSTREAM stream);
+typedef struct _STREAM {
+
+	__int32 block_oriented; // 1 if this is an ADPCM or ASI-compressed stream
+	__int32 using_ASI;		// 1 if using ASI decoder to uncompress stream data
+	ASISTAGE FAR *ASI;	// handy pointer to our ASI coded
+
+	HSAMPLE samp;		// the sample handle
+
+	unsigned __int32 fileh;			// the open file handle
+
+	unsigned __int8 FAR* bufs[3];	// the data buffers
+	unsigned __int32 bufsizes[3];	// the size of each buffer
+	__int32 reset_ASI[3];	// should we reset the ASI at the end of the buffer?
+	__int32 bufstart[3];	// offset of where this buffer started
+	void FAR* asyncs[3];// async read structures
+
+	__int32 loadedbufstart[2]; // offset of where the loaded buffer started
+	__int32 loadedorder[2]; // order of the buffers as they were loaded
+	__int32 loadorder;		// incremented as each buffer is loaded
+
+	__int32 bufsize;		// size of each buffer
+	__int32 readsize;		// size of each read block
+
+	unsigned __int32 buf1;			// 0,1,2 (current buffer that we are reading into)
+	__int32 size1;			// holds the current amount of data read
+
+	unsigned __int32 buf2;			// 0,1,2 (the next buffer that we are reading into)
+	__int32 size2;			// next buffer loaded up to
+
+	unsigned __int32 buf3;			// 0,1,2 (the next buffer that we are reading into)
+	__int32 size3;			// next buffer loaded up to
+
+	unsigned __int32 datarate;		// datarate in bytes per second
+	__int32 filerate;		// original datarate of the file
+	__int32 filetype;		// file format type
+	unsigned __int32 fileflags;		// file format flags (signed or unsigned)
+	__int32 totallen;		// total length of the sound data
+
+	__int32 substart;		// subblock loop start
+	__int32 sublen;		 // subblock loop len
+	__int32 subpadding;	 // amount to pad the final block
+
+	unsigned __int32 blocksize;		// ADPCM block size
+	__int32 padding;		// padding to be done
+	__int32 padded;		 // padding done
+
+	__int32 loadedsome;	 // have we done any loads?
+
+	unsigned __int32 startpos;		// point that the sound data begins
+	unsigned __int32 totalread;		// total bytes read from the disk
+
+	unsigned __int32 loopsleft;		// how many loops are left
+
+	unsigned __int32 error;			// read error has occurred
+
+	__int32 preload;		// preload the file into the first buffer
+	unsigned __int32 preloadpos;	 // position to use in preload
+	__int32 noback;		 // no background processing
+	__int32 alldone;		// alldone
+	__int32 primeamount;	// amount to load after a seek
+	__int32 readatleast;	// forced amount to read on next service
+
+	__int32 playcontrol;	// control: 0=stopped, 1=started, |8=paused, |16=sample paused
+
+	AILSTREAMCB callback;	// end of stream callback
+
+	__int32 user_data[8];	// Miscellaneous user data
+	void FAR* next;	 // pointer to next stream
+
+#if defined(IS_WINDOWS) || defined(IS_MAC)
+	__int32 autostreaming;	// are we autostreaming this stream
+#endif
+
+#ifdef IS_WINDOWS
+	__int32 cb_IsWin32s;	// Is the callback win32s?
+#endif
+	__int32 docallback;	 // set when it time to poll for a callback
+#ifdef IS_MAC
+	IOParam	stream_param;
+	__int32		donext;
+	__int32		donext1;
+	unsigned __int32		fillup;
+	unsigned __int32		session;
+	unsigned __int32		tamt;
+	unsigned __int32		buf;
+	__int32*	 size;
+	__int32*	 done;
+	__int32		done1;
+	__int32		done2;
+	__int32		done3;
+	Boolean	force_quit;
+#endif
+
+} MSTREAM_TYPE;
+
+
+
+
+
+
+
+
+int __stdcall AIL_startup();
+HREDBOOK __stdcall AIL_redbook_open_drive(long drive);
+HREDBOOK __stdcall AIL_redbook_open(int);
+int __stdcall AIL_set_preference(unsigned int number, int value);
+int __stdcall AIL_waveOutOpen(HDIGDRIVER *drv, HWAVEOUT *phWaveOut, int wDeviceID, WAVEFORMAT *pFormat);
+int __stdcall AIL_get_preference(unsigned int number);
+int __stdcall AIL_digital_configuration(HDIGDRIVER drv, int *rate, int *format, char *string);
+HSAMPLE __stdcall AIL_allocate_sample_handle(HDIGDRIVER hDrv);
+unsigned int __stdcall AIL_redbook_tracks(HREDBOOK hRedbook);
+int __stdcall AIL_redbook_volume(HREDBOOK hRedbook);
+unsigned int __stdcall AIL_redbook_stop(HREDBOOK hRedbook);
+void __stdcall AIL_set_digital_master_volume(HDIGDRIVER hDrv, float master_volume);
+int __stdcall AIL_redbook_set_volume(HREDBOOK hRedbook, int volume);
+unsigned int __stdcall AIL_redbook_pause(HREDBOOK hRedbook);
+void __stdcall AIL_redbook_track_info(HREDBOOK hRedbook, unsigned int uTrackNum, unsigned int *pStartMS, unsigned int *pEndMS);
+unsigned int __stdcall AIL_redbook_play(HREDBOOK hRedbook, unsigned int uStartMS, unsigned int uEndMS);  	
+unsigned int __stdcall AIL_redbook_resume(HREDBOOK);
+int __stdcall AIL_enumerate_3D_providers(int *a1, HPROVIDER *pOutProv, char **pOutName);
+DWORD __stdcall AIL_open_3D_provider(HPROVIDER a2);
+int __stdcall AIL_3D_provider_attribute(HPROVIDER a1, const char *a2, int *a3);
+int __stdcall AIL_set_3D_provider_preference(HPROVIDER a1, const char *a2, int *a3);
+int __stdcall AIL_waveOutClose(_DIG_DRIVER *);
+int __stdcall AIL_allocate_3D_sample_handle(HPROVIDER);
+int __stdcall AIL_set_3D_sample_float_distances(void *a1, long a2, long a3, long a4, long a5);
+int __stdcall AIL_set_3D_sample_volume(void *a1, long a2);
+int __stdcall AIL_release_sample_handle(void *a1);
+int __stdcall AIL_3D_position(void *a1, int *a2, float *a3, long *a4);
+int __stdcall AIL_set_3D_sample_file(long a1, void *a2);
+int __stdcall AIL_set_3D_sample_loop_count(long a1, long a2);
+int __stdcall AIL_start_3D_sample(long a1);
+int __stdcall AIL_set_3D_position(void *hSample, long a2, long a3, long a4);
+int __stdcall AIL_set_3D_orientation(void *hSample, long a2, long a3, long a4, long a5, long a6, long a7);
+int __stdcall AIL_release_3D_sample_handle(void *hHandle);
+
+int __stdcall AIL_close_3D_provider(HPROVIDER);
+int __stdcall AIL_redbook_close(HREDBOOK);
+
+// sub_4D8344: using guessed type int __stdcall AIL_shutdown();
+int __stdcall AIL_shutdown();
+
+int __stdcall AIL_end_sample(HSAMPLE a1);
+int __stdcall AIL_end_3D_sample(void *a1);
+void __stdcall AIL_end_sequence(HSEQUENCE a1);
+void __stdcall AIL_pause_stream(HSTREAM a1, int onoff);
+int __stdcall AIL_set_sample_file(HSAMPLE, const void *file_image, int block);
+void __stdcall AIL_start_sample(HSAMPLE);
+void __stdcall AIL_set_sample_playback_rate(HSAMPLE, int rate);
+void __stdcall AIL_sample_ms_position(HSAMPLE, int *pTotalMS, int *pCurrentMS);
+int __stdcall AIL_3D_sample_status(void *a1);
+
+
+namespace AIL
+{
+ namespace Sample
+ {
+  enum Status
+  {
+   Free = 1,               // Sample is available for allocation
+   Done = 2,               // Sample has finished playing, or has never been started
+   Playing = 4,            // Sample is playing
+   Stopped = 8,            // Sample has been stopped
+   PlayingButReleased = 16 // Sample is playing, but digital handle has been temporarily released
+  };
+ };
+};
+AIL::Sample::Status __stdcall AIL_sample_status(HSAMPLE a1);
+
+
+void __stdcall AIL_set_sample_loop_count(HSAMPLE, int);
+int __stdcall AIL_set_sample_volume(HSAMPLE a1, long a2);
+
+
+int __stdcall AIL_sample_volume(HSAMPLE);
+void __stdcall AIL_init_sample(HSAMPLE);
+int __stdcall AIL_set_sample_pan(HSAMPLE, long a2);
+AILFILETYPE __stdcall AIL_file_type(void *pSoundBytes, int numBytes);
+int __stdcall AIL_WAV_info(void *pSoundBytes, AILSOUNDINFO *pInfo);
+int __stdcall AIL_decompress_ADPCM(AILSOUNDINFO *pInfo, void *a2, void *a3);
+int __stdcall AIL_mem_free_lock(void *a1);
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Actor.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,4236 @@
+#include "Actor.h"
+#include "LayingItem.h"
+#include "Math.h"
+#include "Party.h"
+#include "Outdoor.h"
+#include "AudioPlayer.h"
+#include "Game.h"
+#include "ObjectList.h"
+#include "Overlays.h"
+#include "Events.h"
+#include "IndoorCamera.h"
+#include "FactionTable.h"
+#include "TurnEngine.h"
+#include "MapInfo.h"
+#include "stru277.h"
+#include "Time.h"
+#include "LOD.h"
+#include "Party.h"
+#include "GUIWindow.h"
+#include "GUIFont.h"
+
+
+
+
+Actor pActors[500];
+size_t uNumActors;
+
+stru319 stru_50C198; // idb
+
+
+
+
+
+//----- (00448518) --------------------------------------------------------
+void __fastcall sub_448518_npc_set_item(int npc, unsigned int item, int a3)
+{
+  signed int v3; // eax@1
+  int *v4; // edi@2
+  signed int v5; // eax@6
+  char *v6; // ecx@6
+  char *v7; // eax@11
+  ItemGen *v8; // ecx@15
+
+  v3 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v4 = (int *)&pActors[0].uNPC_ID;
+    while ( *(short *)v4 != npc )
+    {
+      ++v3;
+      v4 += 209;
+      if ( v3 >= (signed int)uNumActors )
+        return;
+    }
+    v5 = v3;
+    v6 = (char *)&pActors[v5].uCarriedItemID;
+    if ( a3 )
+    {
+      if ( *(short *)v6 )
+      {
+        if ( pActors[v5].array_000234[0].uItemID )
+        {
+          v7 = (char *)&pActors[v5].array_000234[1];
+          if ( !*(int *)v7 )
+            *(int *)v7 = item;
+        }
+        else
+        {
+          pActors[v5].array_000234[0].uItemID = item;
+        }
+      }
+      else
+      {
+        *(short *)v6 = item;
+      }
+    }
+    else
+    {
+      if ( *(short *)v6 == item )
+      {
+        *(short *)v6 = 0;
+      }
+      else
+      {
+        v8 = pActors[v5].array_000234;
+        if ( pActors[v5].array_000234[0].uItemID == item
+          || (v8 = &pActors[v5].array_000234[1], pActors[v5].array_000234[1].uItemID == item) )
+          v8->Reset();
+      }
+    }
+  }
+}
+
+//----- (004485A7) --------------------------------------------------------
+void Actor::GiveItem(unsigned int uActorID, unsigned int uItemID, unsigned int bGive)
+{
+  unsigned int v3; // eax@3
+  char *v4; // ecx@3
+  unsigned int *v5; // eax@8
+  ItemGen *v6; // ecx@12
+
+  if ( (uActorID & 0x80000000u) == 0 && (signed int)uActorID <= (signed int)(uNumActors - 1) )
+  {
+    v3 = uActorID;
+    v4 = (char *)&pActors[uActorID].uCarriedItemID;
+    if ( bGive )
+    {
+      if ( *(short *)v4 )
+      {
+        if ( pActors[v3].array_000234[0].uItemID )
+        {
+          v5 = &pActors[v3].array_000234[1].uItemID;
+          if ( !*v5 )
+            *v5 = uItemID;
+        }
+        else
+        {
+          pActors[v3].array_000234[0].uItemID = uItemID;
+        }
+      }
+      else
+      {
+        *(short *)v4 = uItemID;
+      }
+    }
+    else
+    {
+      if ( *(short *)v4 == uItemID )
+      {
+        *(short *)v4 = 0;
+      }
+      else
+      {
+        v6 = pActors[v3].array_000234;
+        if ( pActors[v3].array_000234[0].uItemID == uItemID
+          || (v6 = &pActors[v3].array_000234[1], pActors[v3].array_000234[1].uItemID == uItemID) )
+          v6->Reset();
+      }
+    }
+  }
+}
+
+
+//----- (00445D4A) --------------------------------------------------------
+void Actor::InitializeDialogue(int bPlayerSaysHello)
+{
+  Actor *v2; // esi@1
+  unsigned int v3; // ecx@1
+  NPCData *v4; // eax@1
+  NPCData *v5; // ebp@1
+  unsigned int v6; // eax@1
+  signed int v7; // eax@3
+  unsigned int v8; // eax@8
+  int v9; // esi@8
+  int v10; // eax@11
+  GUIWindow *v11; // ecx@19
+  signed int v12; // eax@21
+  int v13; // [sp-8h] [bp-44h]@34
+  const char *v14; // [sp-4h] [bp-40h]@4
+  int v15; // [sp-4h] [bp-40h]@34
+  signed int v16; // [sp-4h] [bp-40h]@35
+  int v17; // [sp+10h] [bp-2Ch]@1
+  char pContainer[32]; // [sp+14h] [bp-28h]@3
+
+  auto a1 = this;
+  v2 = a1;
+  v17 = bPlayerSaysHello;
+  dword_A74CDC = -1;
+  dword_AE336C = -1;
+  pEventTimer->Pause();
+  pMiscTimer->Pause();
+  pAudioPlayer->StopChannels(-1, -1);
+  uDialogueType = 0;
+  v3 = v2->uNPC_ID;
+  uDialogue_SpeakingActorNPC_ID = v2->uNPC_ID;
+  pDialogue_SpeakingActor = v2;
+  v4 = GetNPCData(v3);
+  v5 = v4;
+  v6 = v4->uFlags;
+  if ( (v6 & 3) != 2 )
+    v5->uFlags = v6 + 1;
+  v7 = const_2();
+  sprintf(pContainer, "evt%02d", v7);
+  if ( !pParty->uAlignment )
+  {
+    v14 = "-b";
+LABEL_7:
+    strcat(pContainer, v14);
+    goto LABEL_8;
+  }
+  if ( pParty->uAlignment == 2 )
+  {
+    v14 = "-c";
+    goto LABEL_7;
+  }
+LABEL_8:
+  v8 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+  array_5913D8[6] = 0;
+  uNumDialogueNPCPortraits = 1;
+  pTexture_Dialogue_Background = &pIcons_LOD->pTextures[v8];
+  sprintf(pContainer, "npc%03u", v5->uPortraitID);
+  v9 = 0;
+  pDialogueNPCPortraits[0] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE)];
+  dword_591084 = areWeLoadingTexture;
+  uTextureID_507B04 = uTextureID_right_panel;
+  if ( !(v5->uFlags & 0x80) && v5->house >= 0 )
+  {
+    if ( (signed int)pParty->GetPartyFame() <= v5->fame
+      || (v10 = v5->uFlags & 0xFFFFFF7F, (v5->uFlags & 0xFFFFFF7F & 0x80000000u) != 0) )
+    {
+LABEL_16:
+      v9 = 1;
+      goto LABEL_17;
+    }
+    if ( v10 > 1 )
+    {
+      if ( v10 == 2 )
+      {
+        v16 = 3;
+        goto LABEL_36;
+      }
+      if ( v10 != 3 )
+      {
+        if ( v10 == 4 )
+          goto LABEL_17;
+        goto LABEL_16;
+      }
+LABEL_35:
+      v16 = 2;
+LABEL_36:
+      v9 = v16;
+      goto LABEL_17;
+    }
+    if ( v5->rep )
+      goto LABEL_35;
+  }
+LABEL_17:
+  if ( (uDialogue_SpeakingActorNPC_ID & 0x80000000u) != 0 )
+    v9 = 4;
+  v11 = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)10, v9, 0);
+  pDialogueWindow = v11;
+  if ( v5->uFlags & 0x80 )
+  {
+    if ( !v5->bHasUsedTheAbility )
+    {
+      v12 = v5->uProfession;
+      if ( v12 >= 10 )
+      {
+        if ( v12 <= 12 || v12 > 32 && (v12 <= 34 || v12 > 38 && (v12 <= 43 || v12 == 52)) )
+        {
+          v11->CreateButton(
+            0x1E0u,
+            0xFAu,
+            0x8Cu,
+            LOBYTE(pFontArrus->uFontHeight) - 3,
+            1,
+            0,
+            0x88u,
+            9u,
+            0,
+            "",
+            0);
+          pDialogueWindow->_41D08F(4, 1, 0, 1);
+        }
+      }
+    }
+  }
+  pDialogueWindow->CreateButton(61u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+  pDialogueWindow->CreateButton(177u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+  pDialogueWindow->CreateButton(292u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+  pDialogueWindow->CreateButton(407u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+  if ( v17 && uActiveCharacter && !(v5->uFlags & 0x80) )
+  {
+    if ( pParty->uCurrentHour < 5 || pParty->uCurrentHour > 0x15 )
+    {
+      v15 = 0;
+      v13 = 23;
+    }
+    else
+    {
+      v15 = 0;
+      v13 = 22;
+    }
+    pPlayers[uActiveCharacter]->PlaySound(v13, v15);
+  }
+}
+
+
+//----- (0040894B) --------------------------------------------------------
+bool Actor::CanAct()
+{
+  signed int v1; // esi@1
+  bool v2; // edi@2
+  unsigned __int16 v3; // ax@6
+
+  v1 = 0;
+  v2 = (signed __int64)this->pActorBuffs[5].uExpireTime > 0;// stoned
+  if ( (signed __int64)this->pActorBuffs[6].uExpireTime > 0 )// paralyzed
+    v1 = 1;
+  v3 = this->uAIState;
+  return (v2 | v1 | v3 == Dying | v3 == Dead | v3 == Removed | v3 == Summoned | v3 == Disabled) == 0;
+}
+
+//----- (004089C7) --------------------------------------------------------
+bool Actor::IsAlive()
+{
+  signed int v1; // esi@1
+  unsigned __int16 v2; // ax@3
+
+  v1 = 0;
+  if ( (signed __int64)this->pActorBuffs[5].uExpireTime > 0 )
+    v1 = 1;
+  v2 = this->uAIState;
+  return (v1 | (v2 == Dying) | (v2 == Dead) | (v2 == Removed) | (v2 == Summoned) | (v2 == Disabled)) != 0;
+}
+
+//----- (004086E9) --------------------------------------------------------
+void Actor::SetRandomGoldIfTheresNoItem()
+{
+  Actor *v1; // esi@1
+  int v2; // edi@1
+  signed int v3; // ebx@2
+  unsigned __int8 v4; // al@7
+
+  v1 = this;
+  v2 = 0;
+  if ( !this->array_000234[3].uItemID )
+  {
+    v3 = 0;
+    if ( this->pMonsterInfo.uTreasureDiceRolls )
+    {
+      do
+      {
+        ++v3;
+        v2 += rand() % v1->pMonsterInfo.uTreasureDiceSides + 1;
+      }
+      while ( v3 < v1->pMonsterInfo.uTreasureDiceRolls );
+      if ( v2 )
+      {
+        v1->array_000234[3].uItemID = 197;
+        v1->array_000234[3].uAdditionalValue = v2;
+      }
+    }
+  }
+  if ( rand() % 100 < v1->pMonsterInfo.uTreasureDropChance )
+  {
+    v4 = v1->pMonsterInfo.uTreasureLevel;
+    if ( v4 )
+      pItemsTable->GenerateItem(v4, v1->pMonsterInfo.uTreasureType, &v1->array_000234[2]);
+  }
+  v1->uAttributes |= 0x800000;
+}
+
+//----- (00404AC7) --------------------------------------------------------
+void __fastcall Actor::_404AC7(unsigned int uActorID, AIDirection *pDir, int spellnum, int a4, unsigned int uSkillLevel)
+{
+  Actor *v5; // esi@1
+  unsigned int v6; // edi@1
+  unsigned int v7; // eax@1
+  int v8; // edi@16
+  int v9; // edi@17
+  signed int v10; // ecx@22
+  signed int v11; // eax@29
+  __int16 *v12; // edi@30
+  int v13; // ecx@34
+  int v14; // edx@34
+  int v15; // eax@34
+  AIDirection *v16; // esi@34
+  unsigned __int16 v17; // di@34
+  int v18; // eax@34
+  int v19; // edi@34
+  int v20; // eax@35
+  int v21; // eax@39
+  SoundID v22; // eax@39
+  signed int v23; // eax@41
+  double v24; // st7@49
+  float v25; // ST5C_4@50
+  int v26; // eax@50
+  double v27; // st7@50
+  double v28; // st6@50
+  float v29; // ST4C_4@51
+  int v30; // esi@50
+  int v31; // ST3C_4@51
+  unsigned int v32; // edi@51
+  char *v33; // eax@54
+  unsigned __int16 v34; // ax@57
+  signed int v35; // ecx@58
+  signed int v36; // eax@67
+  signed int v37; // eax@68
+  signed __int64 v38; // qtt@69
+  int v39; // ecx@75
+  int v40; // eax@79
+  int v41; // ecx@90
+  int v42; // ecx@91
+  int v43; // eax@95
+  int v44; // ecx@100
+  int v45; // ecx@101
+  int v46; // eax@105
+  unsigned int v47; // ebx@106
+  int v48; // ecx@110
+  char v49; // zf@123
+  int v50; // eax@127
+  int v51; // ecx@130
+  int v52; // eax@132
+  int v53; // ecx@137
+  int v54; // ecx@138
+  int v55; // eax@142
+  SpellBuff *v56; // esi@143
+  Player **v57; // esi@145
+  int v58; // eax@146
+  int v59; // edi@146
+  int v60; // eax@146
+  int v61; // edi@146
+  int v62; // eax@146
+  signed int v63; // edi@146
+  signed int v64; // edi@147
+  int v65; // eax@151
+  char *v66; // eax@160
+  int v67; // edi@167
+  int v68; // edi@168
+  int v69; // eax@171
+  signed int v70; // ecx@172
+  signed int v71; // eax@179
+  __int16 *v72; // edi@180
+  int v73; // ecx@184
+  int v74; // edx@184
+  int v75; // eax@184
+  AIDirection *v76; // esi@184
+  unsigned __int16 v77; // di@184
+  int v78; // eax@184
+  int v79; // edx@185
+  int v80; // eax@185
+  int v81; // eax@189
+  unsigned __int16 v82; // ax@190
+  int v83; // ecx@192
+  int v84; // edx@192
+  int v85; // eax@192
+  AIDirection *v86; // esi@192
+  unsigned __int16 v87; // di@192
+  __int16 v88; // ax@192
+  signed int v89; // ecx@192
+  int v90; // eax@192
+  signed int v91; // eax@200
+  int v92; // eax@201
+  int v93; // ecx@207
+  int v94; // ecx@208
+  int v95; // eax@212
+  int v96; // ecx@217
+  int v97; // eax@221
+  SoundID v98; // [sp-18h] [bp-E8h]@79
+  signed int v99; // [sp-14h] [bp-E4h]@39
+  unsigned int v100; // [sp-10h] [bp-E0h]@39
+  signed int v101; // [sp-Ch] [bp-DCh]@39
+  signed int v102; // [sp-8h] [bp-D8h]@39
+  int v103; // [sp-4h] [bp-D4h]@39
+  unsigned int v104; // [sp+0h] [bp-D0h]@39
+  signed int v105; // [sp+4h] [bp-CCh]@23
+  int v106; // [sp+4h] [bp-CCh]@39
+  signed int v107; // [sp+4h] [bp-CCh]@42
+  signed int v108; // [sp+4h] [bp-CCh]@173
+  int pitch; // [sp+2Ch] [bp-A4h]@51
+  float v110; // [sp+30h] [bp-A0h]@50
+  int v111; // [sp+38h] [bp-98h]@41
+  float v112; // [sp+3Ch] [bp-94h]@49
+  int v113; // [sp+40h] [bp-90h]@41
+  int v114; // [sp+48h] [bp-88h]@41
+  LayingItem a1; // [sp+4Ch] [bp-84h]@1
+  int v116; // [sp+BCh] [bp-14h]@49
+  AIDirection *v117; // [sp+C0h] [bp-10h]@1
+  int v118; // [sp+C4h] [bp-Ch]@29
+  float v119; // [sp+C8h] [bp-8h]@48
+  float v120; // [sp+CCh] [bp-4h]@1
+  int spellnuma; // [sp+D8h] [bp+8h]@29
+  int spellnumb; // [sp+D8h] [bp+8h]@48
+  float spellnumc; // [sp+D8h] [bp+8h]@50
+  signed int spellnumd; // [sp+D8h] [bp+8h]@53
+  int spellnume; // [sp+D8h] [bp+8h]@179
+  int a1a; // [sp+E0h] [bp+10h]@34
+  signed int a1b; // [sp+E0h] [bp+10h]@145
+  int a1c; // [sp+E0h] [bp+10h]@184
+
+  LODWORD(v120) = uActorID;
+  v5 = &pActors[uActorID];
+  v117 = pDir;
+  v6 = uSkillLevel & 0x3F;
+  v7 = SkillToMastery(uSkillLevel);
+  if ( spellnum <= 47 )
+  {
+    if ( spellnum != 47 )
+    {
+      if ( spellnum <= 18 )
+      {
+        if ( spellnum == 18 || spellnum == 2 )
+          goto LABEL_159;
+        if ( spellnum != 5 )
+        {
+          if ( spellnum == 6 )
+            goto LABEL_159;
+          if ( spellnum != 9 )
+          {
+            if ( spellnum != 11 )
+            {
+              if ( spellnum != 15 )
+              {
+                if ( spellnum != 17 )
+                  return;
+                if ( (signed int)v7 <= 0 )
+                  goto LABEL_20;
+                if ( (signed int)v7 <= 2 )
+                {
+                  v9 = 300 * v6;
+                }
+                else
+                {
+                  if ( v7 != 3 )
+                  {
+                    if ( v7 == 4 )
+                    {
+                      v8 = 3600 * (v6 + 64);
+LABEL_21:
+                      v5->pActorBuffs[15].Apply(
+                        pParty->uTimePlayed + (signed int)(signed __int64)((double)(v8 << 7) * 0.033333335),
+                        v7,
+                        0,
+                        0,
+                        0);
+                      return;
+                    }
+LABEL_20:
+                    v8 = 0;
+                    goto LABEL_21;
+                  }
+                  v9 = 900 * v6;
+                }
+                v8 = v9 + 3840;
+                goto LABEL_21;
+              }
+              v10 = 3;
+              if ( uSkillLevel & 0x0100 )
+              {
+                v105 = 9;
+              }
+              else
+              {
+                if ( (uSkillLevel & 0x80u) == 0 )
+                {
+                  if ( !(uSkillLevel & 0x40) )
+                    goto LABEL_29;
+                  v105 = 5;
+                }
+                else
+                {
+                  v105 = 7;
+                }
+              }
+              v10 = v105;
+LABEL_29:
+              spellnuma = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
+              a1.uItemType = stru_4E3ACC[15].uItemType;
+              v118 = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360 / (v10 - 1);
+              v11 = 0;
+              if ( (signed int)pObjectList->uNumObjects <= 0 )
+              {
+LABEL_33:
+                LOWORD(v11) = 0;
+              }
+              else
+              {
+                v12 = &pObjectList->pObjects->uObjectID;
+                while ( stru_4E3ACC[15].uItemType != *v12 )
+                {
+                  ++v11;
+                  v12 += 28;
+                  if ( v11 >= (signed int)pObjectList->uNumObjects )
+                    goto LABEL_33;
+                }
+              }
+              a1.uObjectDescID = v11;
+              a1.stru_24.Reset();
+              a1.field_48 = 15;
+              v13 = v5->vPosition.x;
+              v14 = v5->vPosition.y;
+              a1.field_4C = uSkillLevel;
+              a1.vPosition.x = v13;
+              v15 = v5->vPosition.z + ((signed int)v5->uActorHeight >> 1);
+              v16 = v117;
+              v17 = LOWORD(v117->uYawAngle);
+              a1.field_50 = 0;
+              a1.vPosition.y = v14;
+              a1.vPosition.z = v15;
+              a1.uFacing = v17;
+              a1.uSoundID = 0;
+              a1.uAttributes = 0;
+              a1.uSectorID = pIndoor->GetSector(v13, v14, v15);
+              v18 = 8 * LODWORD(v120);
+              LOBYTE(v18) = 8 * LOBYTE(v120) | AI_OBJECT_ACTOR;
+              a1.field_58 = v18;
+              a1.uSpriteFrameID = 0;
+              a1.field_5C = 0;
+              a1.field_60_distance_related_prolly_lod = 3;
+              v19 = spellnuma / -2;
+              a1a = spellnuma / 2;
+              if ( spellnuma / -2 > spellnuma / 2 )
+              {
+                v20 = spellnuma / 2;
+              }
+              else
+              {
+                do
+                {
+                  a1.uFacing = v19 + LOWORD(v16->uYawAngle);
+                  v20 = a1.Create(
+                          (signed __int16)a1.uFacing,
+                          v16->uPitchAngle,
+                          pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                          0);
+                  v19 += v118;
+                }
+                while ( v19 <= a1a );
+              }
+              if ( v20 != -1 )
+              {
+                v106 = 0;
+                v104 = 0;
+                v103 = 0;
+                v102 = 0;
+                v21 = 8 * v20;
+                v101 = -1;
+                LOBYTE(v21) = v21 | 2;
+                v100 = 0;
+                v99 = v21;
+                v22 = (SoundID)word_4EE088_sound_ids[15];
+LABEL_202:
+                v98 = v22;
+                goto LABEL_222;
+              }
+              return;
+            }
+LABEL_159:
+            a1.uItemType = stru_4E3ACC[spellnum].uItemType;
+            v119 = 0.0;
+            if ( (signed int)pObjectList->uNumObjects <= 0 )
+            {
+LABEL_191:
+              v82 = 0;
+            }
+            else
+            {
+              v66 = (char *)&pObjectList->pObjects->uObjectID;
+              while ( (short)a1.uItemType != *(short *)v66 )
+              {
+                ++LODWORD(v119);
+                v66 += 56;
+                if ( SLODWORD(v119) >= (signed int)pObjectList->uNumObjects )
+                  goto LABEL_191;
+              }
+              v82 = LOWORD(v119);
+            }
+            a1.uObjectDescID = v82;
+            a1.stru_24.Reset();
+            a1.field_48 = spellnum;
+            v83 = v5->vPosition.x;
+            v84 = v5->vPosition.y;
+            a1.field_4C = uSkillLevel;
+            a1.vPosition.x = v83;
+            v85 = v5->vPosition.z + ((signed int)v5->uActorHeight >> 1);
+            v86 = v117;
+            v87 = LOWORD(v117->uYawAngle);
+            a1.field_50 = 0;
+            a1.vPosition.y = v84;
+            a1.vPosition.z = v85;
+            a1.uFacing = v87;
+            a1.uSoundID = 0;
+            a1.uAttributes = 0;
+            v88 = pIndoor->GetSector(v83, v84, v85);
+            v89 = v86->uDistance;
+            a1.uSectorID = v88;
+            LODWORD(v119) = v89;
+            v90 = 8 * LODWORD(v120);
+            LOBYTE(v90) = 8 * LOBYTE(v120) | 3;
+            a1.uSpriteFrameID = 0;
+            a1.field_58 = v90;
+            a1.field_5C = 0;
+            a1.field_60_distance_related_prolly_lod = 3;
+            if ( (double)v89 >= 307.2 )
+            {
+              if ( v89 >= 1024 )
+              {
+                if ( v89 >= 2560 )
+                {
+                  if ( v89 < 5120 )
+                    a1.field_60_distance_related_prolly_lod = 3;
+                }
+                else
+                {
+                  a1.field_60_distance_related_prolly_lod = 2;
+                }
+              }
+              else
+              {
+                a1.field_60_distance_related_prolly_lod = 1;
+              }
+            }
+            else
+            {
+              a1.field_60_distance_related_prolly_lod = 0;
+            }
+            a1.field_61 = 2;
+            v91 = a1.Create(
+                    v86->uYawAngle,
+                    v86->uPitchAngle,
+                    pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                    0);
+            if ( v91 != -1 )
+            {
+              v106 = 0;
+              v104 = 0;
+              v103 = 0;
+              v102 = 0;
+              v92 = 8 * v91;
+              v101 = -1;
+              LOBYTE(v92) = v92 | 2;
+              v100 = 0;
+              v99 = v92;
+              v22 = (SoundID)word_4EE088_sound_ids[spellnum];
+              goto LABEL_202;
+            }
+            return;
+          }
+          if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+            return;
+          v118 = pParty->vPosition.z;
+          v111 = pParty->vPosition.x;
+          v114 = pParty->vPosition.z + 2500;
+          v113 = pParty->vPosition.y;
+          v23 = 8;
+          if ( uSkillLevel & 0x0100 )
+          {
+            v107 = 14;
+          }
+          else
+          {
+            if ( (uSkillLevel & 0x80u) == 0 )
+            {
+              if ( !(uSkillLevel & 0x40) )
+                goto LABEL_48;
+              v107 = 10;
+            }
+            else
+            {
+              v107 = 12;
+            }
+          }
+          v23 = v107;
+LABEL_48:
+          v119 = 0.0;
+          spellnumb = 0;
+          if ( v23 > 0 )
+          {
+            v24 = (double)v118;
+            v118 = v23;
+            v112 = v24;
+            v116 = 8 * LODWORD(v120) | 3;
+            do
+            {
+              v26 = rand();
+              v27 = (double)spellnumb;
+              v110 = v27;
+              v28 = (double)SLODWORD(v119);
+              v30 = v26 % 1000;
+              v25 = (double)v114;
+              spellnumc = (double)(v26 % 1000) + v112 - v25;
+              v120 = v28 * v28;
+              v119 = v27 * v27;
+              if ( sqrt(spellnumc * spellnumc + v119 + v120) <= 1.0 )
+              {
+                v32 = 0;
+                pitch = 0;
+              }
+              else
+              {
+                v31 = (signed __int64)sqrt(v119 + v120);
+                v29 = v28;
+                v32 = stru_5C6E00->Atan2((signed __int64)v110, (signed __int64)v29);
+                pitch = stru_5C6E00->Atan2(v31, (signed __int64)spellnumc);
+              }
+              a1.stru_24.Reset();
+              a1.uItemType = stru_4E3ACC[9].uItemType;
+              spellnumd = 0;
+              if ( (signed int)pObjectList->uNumObjects <= 0 )
+              {
+LABEL_57:
+                v34 = 0;
+              }
+              else
+              {
+                v33 = (char *)&pObjectList->pObjects->uObjectID;
+                while ( (short)a1.uItemType != *(short *)v33 )
+                {
+                  ++spellnumd;
+                  v33 += 56;
+                  if ( spellnumd >= (signed int)pObjectList->uNumObjects )
+                    goto LABEL_57;
+                }
+                v34 = spellnumd;
+              }
+              a1.uObjectDescID = v34;
+              a1.field_4C = uSkillLevel;
+              a1.vPosition.x = v111;
+              a1.vPosition.y = v113;
+              a1.vPosition.z = v30 + v114;
+              a1.field_48 = 9;
+              a1.field_50 = 0;
+              a1.uAttributes = 0;
+              a1.uSectorID = 0;
+              a1.uSpriteFrameID = 0;
+              a1.field_58 = v116;
+              a1.field_5C = 0;
+              a1.field_60_distance_related_prolly_lod = stru_50C198._427546(v30 + 2500);
+              a1.uFacing = v32;
+              a1.uSoundID = 0;
+              v35 = v117->uDistance;
+              LODWORD(v119) = v117->uDistance;
+              if ( (double)SLODWORD(v119) >= 307.2 )
+              {
+                if ( v35 >= 1024 )
+                {
+                  if ( v35 >= 2560 )
+                  {
+                    if ( v35 < 5120 )
+                      a1.field_60_distance_related_prolly_lod = 3;
+                  }
+                  else
+                  {
+                    a1.field_60_distance_related_prolly_lod = 2;
+                  }
+                }
+                else
+                {
+                  a1.field_60_distance_related_prolly_lod = 1;
+                }
+              }
+              else
+              {
+                a1.field_60_distance_related_prolly_lod = 0;
+              }
+              a1.field_61 = 2;
+              v36 = a1.Create(
+                      v32,
+                      pitch,
+                      pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                      0);
+              if ( v36 != -1 )
+              {
+                v37 = 8 * v36;
+                LOBYTE(v37) = v37 | 2;
+                pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[9], v37, 0, -1, 0, 0, 0, 0);
+              }
+              spellnumb = rand() % 1024 - 512;
+              v38 = rand();
+              v49 = v118-- == 1;
+              LODWORD(v119) = (unsigned __int64)(v38 % 1024) - 512;
+            }
+            while ( !v49 );
+          }
+          return;
+        }
+        if ( (signed int)v7 > 0 )
+        {
+          if ( (signed int)v7 <= 2 )
+          {
+            v39 = 60 * (v6 + 60);
+            goto LABEL_79;
+          }
+          if ( v7 == 3 )
+          {
+            v39 = 180 * (v6 + 20);
+            goto LABEL_79;
+          }
+          if ( v7 == 4 )
+          {
+            v39 = 240 * (v6 + 15);
+LABEL_79:
+            v5->pActorBuffs[19].Apply(
+              pParty->uTimePlayed + (signed int)(signed __int64)((double)(v39 << 7) * 0.033333335),
+              v7,
+              0,
+              0,
+              0);
+            pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(v5, 0xFF3C1Eu);
+            v106 = 0;
+            v104 = 0;
+            v103 = 0;
+            v102 = 0;
+            v40 = 8 * LODWORD(v120);
+            v101 = -1;
+            LOBYTE(v40) = 8 * LOBYTE(v120) | 3;
+            v100 = 0;
+            v99 = v40;
+            v98 = (SoundID)10040;
+LABEL_222:
+            pAudioPlayer->PlaySound(v98, v99, v100, v101, v102, v103, v104, v106);
+            return;
+          }
+        }
+        v39 = 0;
+        goto LABEL_79;
+      }
+      if ( spellnum == 26 || spellnum == 29 )
+        goto LABEL_159;
+      if ( spellnum != 38 )
+      {
+        if ( spellnum == 39 || spellnum == 41 )
+          goto LABEL_159;
+        if ( spellnum != 46 )
+          return;
+        if ( (signed int)v7 > 0 )
+        {
+          if ( (signed int)v7 <= 2 )
+          {
+            v41 = 300 * v6;
+            goto LABEL_91;
+          }
+          if ( v7 == 3 )
+          {
+            v41 = 900 * v6;
+            goto LABEL_91;
+          }
+          if ( v7 == 4 )
+          {
+            v41 = 1200 * v6;
+LABEL_91:
+            v42 = v41 + 3840;
+LABEL_95:
+            v5->pActorBuffs[17].Apply(
+              pParty->uTimePlayed + (signed int)(signed __int64)((double)(v42 << 7) * 0.033333335),
+              v7,
+              v6 + 5,
+              0,
+              0);
+            pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(
+              v5,
+              (unsigned int)((char *)&pDecalBuilder->std__vector_pDecals[557].pVertices[57].vWorldPosition.x + 1));
+            v106 = 0;
+            v104 = 0;
+            v103 = 0;
+            v102 = 0;
+            v43 = 8 * LODWORD(v120);
+            v101 = -1;
+            LOBYTE(v43) = 8 * LOBYTE(v120) | 3;
+            v100 = 0;
+            v99 = v43;
+            v98 = (SoundID)14010;
+            goto LABEL_222;
+          }
+        }
+        v42 = 0;
+        goto LABEL_95;
+      }
+      if ( (signed int)v7 <= 0 )
+        goto LABEL_104;
+      if ( (signed int)v7 <= 2 )
+      {
+        v45 = 300 * v6;
+      }
+      else
+      {
+        if ( v7 != 3 )
+        {
+          if ( v7 == 4 )
+          {
+            v44 = 3600 * (v6 + 64);
+LABEL_105:
+            v5->pActorBuffs[16].Apply(
+              pParty->uTimePlayed + (signed int)(signed __int64)((double)(v44 << 7) * 0.033333335),
+              v7,
+              v6 + 5,
+              0,
+              0);
+            pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(
+              v5,
+              (unsigned int)((char *)&pLevelEVT_Events[4335].uEventID + 2));
+            v106 = 0;
+            v104 = 0;
+            v103 = 0;
+            v102 = 0;
+            v46 = 8 * LODWORD(v120);
+            v101 = -1;
+            LOBYTE(v46) = 8 * LOBYTE(v120) | 3;
+            v100 = 0;
+            v99 = v46;
+            v98 = (SoundID)13040;
+            goto LABEL_222;
+          }
+LABEL_104:
+          v44 = 0;
+          goto LABEL_105;
+        }
+        v45 = 900 * v6;
+      }
+      v44 = v45 + 3840;
+      goto LABEL_105;
+    }
+    v47 = 0;
+    if ( (signed int)v7 > 0 )
+    {
+      if ( (signed int)v7 <= 2 )
+      {
+        v48 = 2 * v6 + 40;
+        goto LABEL_114;
+      }
+      if ( v7 == 3 )
+      {
+        v48 = 3 * v6 + 60;
+        goto LABEL_114;
+      }
+      if ( v7 == 4 )
+      {
+        LOWORD(v48) = 2 * (3 * v6 + 60);
+LABEL_114:
+        v5->pActorBuffs[11].Apply(pParty->uTimePlayed + 1280, v7, v48, 0, 0);
+        pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(
+          v5,
+          (unsigned int)((char *)&pDecalBuilder->std__vector_pDecals[557].pVertices[57].vWorldPosition.x + 1));
+LABEL_127:
+        v106 = v47;
+        v104 = v47;
+        v103 = v47;
+        v50 = 8 * LODWORD(v120);
+        v102 = v47;
+        v101 = -1;
+        LOBYTE(v50) = 8 * LOBYTE(v120) | 3;
+        v100 = v47;
+        v99 = v50;
+        v98 = (SoundID)14020;
+        goto LABEL_222;
+      }
+    }
+    LOWORD(v48) = 0;
+    goto LABEL_114;
+  }
+  if ( spellnum <= 80 )
+  {
+    if ( spellnum == 80 )
+    {
+      v56 = pParty->pPartyBuffs;
+      do
+      {
+        v56->Reset();
+        ++v56;
+      }
+      while ( (signed int)v56 < (signed int)pParty->pPlayers );
+      a1b = 1;
+      v57 = &pPlayers[1];
+      do
+      {
+        v58 = (*v57)->GetActualWillpower();
+        v59 = (*v57)->_48EA1B_get_static_effect(v58);
+        v60 = (*v57)->GetActualIntelligence();
+        v61 = ((*v57)->_48EA1B_get_static_effect(v60) + v59) >> 1;
+        v62 = (*v57)->GetActualLuck();
+        v63 = v61 + (*v57)->_48EA1B_get_static_effect(v62) + 30;
+        if ( rand() % v63 < 30 )
+        {
+          v64 = 6048;
+          do
+          {
+            ((SpellBuff *)((char *)*v57 + v64))->Reset();
+            v64 += 16;
+          }
+          while ( v64 < 6432 );
+          pOtherOverlayList->_4418B1(11210, a1b + 99, 0, 65536);
+        }
+        ++a1b;
+        ++v57;
+      }
+      while ( (signed int)v57 <= (signed int)&pPlayers[4] );
+      v106 = 0;
+      v104 = 0;
+      v103 = 0;
+      v65 = 8 * LODWORD(v120);
+      v102 = 0;
+      v101 = -1;
+      LOBYTE(v65) = 8 * LOBYTE(v120) | 3;
+      v100 = 0;
+      v99 = v65;
+      v22 = (SoundID)word_4EE088_sound_ids[80];
+      goto LABEL_202;
+    }
+    if ( spellnum != 51 )
+    {
+      if ( spellnum == 57 || spellnum == 65 || spellnum == 70 )
+        goto LABEL_159;
+      if ( spellnum == 73 )
+      {
+        if ( (signed int)v7 <= 0 || (signed int)v7 > 4 )
+          v51 = 0;
+        else
+          v51 = 3600 * v6;
+        v5->pActorBuffs[21].Apply(
+          pParty->uTimePlayed + (signed int)(signed __int64)((double)(v51 << 7) * 0.033333335),
+          v7,
+          v6,
+          0,
+          0);
+        pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(v5, 0xA81376u);
+        v106 = 0;
+        v104 = 0;
+        v103 = 0;
+        v102 = 0;
+        v52 = 8 * LODWORD(v120);
+        v101 = -1;
+        LOBYTE(v52) = 8 * LOBYTE(v120) | 3;
+        v100 = 0;
+        v99 = v52;
+        v98 = (SoundID)16060;
+        goto LABEL_222;
+      }
+      if ( spellnum == 77 )
+      {
+        v5->sCurrentHP += 5 * v6 + 10;
+        if ( v5->sCurrentHP >= (signed int)v5->pMonsterInfo.uHP )
+          v5->sCurrentHP = LOWORD(v5->pMonsterInfo.uHP);
+        pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(v5, 0xA81376u);
+        v47 = 0;
+        goto LABEL_127;
+      }
+      v49 = spellnum == 78;
+LABEL_158:
+      if ( !v49 )
+        return;
+      goto LABEL_159;
+    }
+    if ( (signed int)v7 > 0 )
+    {
+      if ( (signed int)v7 <= 2 )
+      {
+        v53 = 300 * v6;
+        goto LABEL_138;
+      }
+      if ( v7 == 3 )
+      {
+        v53 = 900 * v6;
+        goto LABEL_138;
+      }
+      if ( v7 == 4 )
+      {
+        v53 = 1200 * v6;
+LABEL_138:
+        v54 = v53 + 3840;
+LABEL_142:
+        v5->pActorBuffs[18].Apply(
+          pParty->uTimePlayed + (signed int)(signed __int64)((double)(v54 << 7) * 0.033333335),
+          v7,
+          v6 + 5,
+          0,
+          0);
+        pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(
+          v5,
+          (unsigned int)((char *)&pDecalBuilder->std__vector_pDecals[557].pVertices[57].vWorldPosition.x + 1));
+        v106 = 0;
+        v104 = 0;
+        v103 = 0;
+        v102 = 0;
+        v55 = 8 * LODWORD(v120);
+        v101 = -1;
+        LOBYTE(v55) = 8 * LOBYTE(v120) | 3;
+        v100 = 0;
+        v99 = v55;
+        v98 = (SoundID)14060;
+        goto LABEL_222;
+      }
+    }
+    v54 = 0;
+    goto LABEL_142;
+  }
+  if ( spellnum == 85 )
+  {
+    if ( (signed int)v7 > 0 )
+    {
+      if ( (signed int)v7 <= 2 )
+      {
+        v96 = 300 * v6 + 3840;
+        goto LABEL_221;
+      }
+      if ( v7 == 3 )
+      {
+        LOWORD(v6) = 3 * v6;
+        v96 = 900 * (uSkillLevel & 0x3F) + 3840;
+        goto LABEL_221;
+      }
+      if ( v7 == 4 )
+      {
+        v96 = 1200 * v6 + 3840;
+        LOWORD(v6) = 4 * v6;
+LABEL_221:
+        v5->pActorBuffs[13].Apply(
+          pParty->uTimePlayed + (signed int)(signed __int64)((double)(v96 << 7) * 0.033333335),
+          v7,
+          v6,
+          0,
+          0);
+        pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(v5, 0xFFFFFFu);
+        v106 = 0;
+        v104 = 0;
+        v103 = 0;
+        v102 = 0;
+        v97 = 8 * LODWORD(v120);
+        v101 = -1;
+        LOBYTE(v97) = 8 * LOBYTE(v120) | 3;
+        v100 = 0;
+        v99 = v97;
+        v98 = (SoundID)17070;
+        goto LABEL_222;
+      }
+    }
+    LOWORD(v6) = uSkillLevel;
+    v96 = 0;
+    goto LABEL_221;
+  }
+  if ( spellnum == 86 )
+  {
+    if ( (signed int)v7 > 0 )
+    {
+      if ( (signed int)v7 <= 2 )
+      {
+        v93 = 300 * v6;
+        goto LABEL_208;
+      }
+      if ( v7 == 3 )
+      {
+        v93 = 900 * v6;
+        goto LABEL_208;
+      }
+      if ( v7 == 4 )
+      {
+        v93 = 1200 * v6;
+LABEL_208:
+        v94 = v93 + 3840;
+LABEL_212:
+        v5->pActorBuffs[14].Apply(
+          pParty->uTimePlayed + (signed int)(signed __int64)((double)(v94 << 7) * 0.033333335),
+          v7,
+          v6 + 5,
+          0,
+          0);
+        pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(v5, 0xFFFFFFu);
+        v106 = 0;
+        v104 = 0;
+        v103 = 0;
+        v102 = 0;
+        v95 = 8 * LODWORD(v120);
+        v101 = -1;
+        LOBYTE(v95) = 8 * LOBYTE(v120) | 3;
+        v100 = 0;
+        v99 = v95;
+        v98 = (SoundID)17080;
+        goto LABEL_222;
+      }
+    }
+    v94 = 0;
+    goto LABEL_212;
+  }
+  if ( spellnum == 90 )
+    goto LABEL_159;
+  if ( spellnum != 93 )
+  {
+    if ( spellnum != 95 )
+    {
+      v49 = spellnum == 97;
+      goto LABEL_158;
+    }
+    if ( (signed int)v7 > 0 )
+    {
+      if ( (signed int)v7 <= 3 )
+      {
+        v67 = 300 * v6;
+        goto LABEL_168;
+      }
+      if ( v7 == 4 )
+      {
+        v67 = 900 * v6;
+LABEL_168:
+        v68 = v67 + 3840;
+LABEL_171:
+        v5->pActorBuffs[20].Apply(
+          pParty->uTimePlayed + (signed int)(signed __int64)((double)(v68 << 7) * 0.033333335),
+          v7,
+          0,
+          0,
+          0);
+        pGame->pStru6Instance->_4A7E89_sparkles_on_actor_after_it_casts_buff(
+          v5,
+          (unsigned int)((char *)&array_77EC08[1607].v_18.z + 2));
+        v106 = 0;
+        v104 = 0;
+        v103 = 0;
+        v102 = 0;
+        v69 = 8 * LODWORD(v120);
+        v101 = -1;
+        LOBYTE(v69) = 8 * LOBYTE(v120) | 3;
+        v100 = 0;
+        v99 = v69;
+        v98 = (SoundID)18060;
+        goto LABEL_222;
+      }
+    }
+    v68 = 0;
+    goto LABEL_171;
+  }
+  v70 = 3;
+  if ( uSkillLevel & 0x100 )
+  {
+    v108 = 9;
+  }
+  else
+  {
+    if ( (uSkillLevel & 0x80u) == 0 )
+    {
+      if ( !(uSkillLevel & 0x40) )
+        goto LABEL_179;
+      v108 = 5;
+    }
+    else
+    {
+      v108 = 7;
+    }
+  }
+  v70 = v108;
+LABEL_179:
+  spellnume = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
+  a1.uItemType = stru_4E3ACC[93].uItemType;
+  v116 = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360 / (v70 - 1);
+  v71 = 0;
+  if ( (signed int)pObjectList->uNumObjects <= 0 )
+  {
+LABEL_183:
+    LOWORD(v71) = 0;
+  }
+  else
+  {
+    v72 = &pObjectList->pObjects->uObjectID;
+    while ( stru_4E3ACC[93].uItemType != *v72 )
+    {
+      ++v71;
+      v72 += 28;
+      if ( v71 >= (signed int)pObjectList->uNumObjects )
+        goto LABEL_183;
+    }
+  }
+  a1.uObjectDescID = v71;
+  a1.stru_24.Reset();
+  a1.field_48 = 93;
+  v73 = v5->vPosition.x;
+  v74 = v5->vPosition.y;
+  a1.field_4C = uSkillLevel;
+  a1.vPosition.x = v73;
+  v75 = v5->vPosition.z + ((signed int)v5->uActorHeight >> 1);
+  v76 = v117;
+  v77 = LOWORD(v117->uYawAngle);
+  a1.field_50 = 0;
+  a1.vPosition.y = v74;
+  a1.vPosition.z = v75;
+  a1.uFacing = v77;
+  a1.uSoundID = 0;
+  a1.uAttributes = 0;
+  a1.uSectorID = pIndoor->GetSector(v73, v74, v75);
+  v78 = 8 * LODWORD(v120);
+  LOBYTE(v78) = 8 * LOBYTE(v120) | 3;
+  a1.field_58 = v78;
+  a1.uSpriteFrameID = 0;
+  a1.field_5C = 0;
+  a1.field_60_distance_related_prolly_lod = 3;
+  a1c = spellnume / -2;
+  if ( spellnume / -2 > spellnume / 2 )
+  {
+    v80 = spellnume / -2;
+  }
+  else
+  {
+    do
+    {
+      v79 = v76->uYawAngle;
+      a1.uFacing = a1c + LOWORD(v76->uYawAngle);
+      v80 = a1.Create(
+              v79,
+              v76->uPitchAngle,
+              pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+              0);
+      a1c += v116;
+    }
+    while ( a1c <= spellnume / 2 );
+  }
+  if ( v80 != -1 )
+  {
+    v106 = 0;
+    v104 = 0;
+    v103 = 0;
+    v102 = 0;
+    v81 = 8 * v80;
+    v101 = -1;
+    LOBYTE(v81) = v81 | 2;
+    v100 = 0;
+    v99 = v81;
+    v22 = (SoundID)word_4EE088_sound_ids[93];
+    goto LABEL_202;
+  }
+}
+
+
+//----- (0043ABB0) --------------------------------------------------------
+bool Actor::_43ABB0(Actor *a1, Actor *a2)
+{
+  unsigned int v2; // esi@1
+  unsigned int v3; // edi@1
+  bool result; // eax@9
+
+  v2 = a1->uAlly;
+  v3 = a2->uAlly;
+  if ( !v2 )
+    v2 = (a1->pMonsterInfo.uID - 1) / 3 + 1;
+  if ( !v3 )
+    v3 = (a2->pMonsterInfo.uID - 1) / 3 + 1;
+  if ( (signed int)v2 >= 39 && (signed int)v2 <= 44 && (signed int)v3 >= 39 && (signed int)v3 <= 44
+    || (signed int)v2 >= 45 && (signed int)v2 <= 50 && (signed int)v3 >= 45 && (signed int)v3 <= 50
+    || (signed int)v2 >= 51 && (signed int)v2 <= 62 && (signed int)v3 >= 51 && (signed int)v3 <= 62
+    || (signed int)v2 >= 78 && (signed int)v2 <= 83 && (signed int)v3 >= 78 && (signed int)v3 <= 83 )
+    result = 1;
+  else
+    result = v2 == v3;
+  return result;
+}
+
+//----- (0043AC45) --------------------------------------------------------
+void Actor::_43AC45(unsigned int uActorID, int a2)
+{
+  Actor *v2; // esi@1
+  char *v3; // edi@4
+  int v4; // ebx@8
+  int v5; // ST1C_4@8
+  int v6; // eax@8
+  int v7; // [sp+4h] [bp-10h]@1
+  unsigned int uActorID_; // [sp+Ch] [bp-8h]@1
+  signed int v9; // [sp+10h] [bp-4h]@3
+
+  uActorID_ = uActorID;
+  v2 = &pActors[uActorID];
+  v7 = a2;
+  if ( a2 == 1 )
+    BYTE2(v2->uAttributes) |= 8u;
+  v9 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v3 = (char *)&pActors[0].vPosition.y;
+    do
+    {
+      if ( ((Actor *)(v3 - 144))->CanAct() )
+      {
+        if ( v9 != uActorID_ )
+        {
+          if ( Actor::_43ABB0(v2, (Actor *)(v3 - 144)) )
+          {
+            v4 = abs(*((short *)v3 - 1) - v2->vPosition.x);
+            v5 = abs(*(short *)v3 - v2->vPosition.y);
+            v6 = abs(*((short *)v3 + 1) - v2->vPosition.z);
+            if ( (double)sub_4621DA(v4, v5, v6) < 4096.0 )
+            {
+              *(v3 - 83) = 4;
+              if ( v7 == 1 )
+                *(v3 - 106) |= 8u;
+            }
+          }
+        }
+      }
+      ++v9;
+      v3 += 836;
+    }
+    while ( v9 < (signed int)uNumActors );
+  }
+}
+
+
+//----- (00404874) --------------------------------------------------------
+char __fastcall Actor::_404874(unsigned int uActorID, AIDirection *a2, int a3, char a4)
+{
+  AIDirection *v4; // edi@1
+  Actor *v5; // esi@1
+  char result; // al@1
+  char *v7; // eax@15
+  unsigned __int16 v8; // ax@18
+  unsigned __int16 v9; // ax@19
+  __int16 v10; // ax@19
+  signed int v11; // ecx@19
+  int v12; // eax@19
+  int v13; // edx@28
+  //LayingItem a1; // [sp+Ch] [bp-74h]@1
+  unsigned int v15; // [sp+7Ch] [bp-4h]@1
+  signed int v16; // [sp+88h] [bp+8h]@14
+  signed int v17; // [sp+88h] [bp+8h]@19
+
+  v15 = uActorID;
+  v4 = a2;
+  v5 = &pActors[uActorID];
+
+  LayingItem a1; // [sp+Ch] [bp-74h]@1
+  //LayingItem::LayingItem(&a1);
+
+  result = a3 - 1;
+  switch ( a3 )
+  {
+    case 1:
+      a1.uItemType = 545;
+      goto LABEL_14;
+    case 2:
+      a1.uItemType = 550;
+      goto LABEL_14;
+    case 3:
+      a1.uItemType = 510;
+      goto LABEL_14;
+    case 4:
+      a1.uItemType = 500;
+      goto LABEL_14;
+    case 5:
+      a1.uItemType = 515;
+      goto LABEL_14;
+    case 6:
+      a1.uItemType = 505;
+      goto LABEL_14;
+    case 7:
+      a1.uItemType = 530;
+      goto LABEL_14;
+    case 8:
+      a1.uItemType = 525;
+      goto LABEL_14;
+    case 9:
+      a1.uItemType = 520;
+      goto LABEL_14;
+    case 10:
+      a1.uItemType = 535;
+      goto LABEL_14;
+    case 11:
+      a1.uItemType = 540;
+      goto LABEL_14;
+    case 13:
+      a1.uItemType = 555;
+LABEL_14:
+      v16 = 0;
+      if ( (signed int)pObjectList->uNumObjects <= 0 )
+        goto LABEL_18;
+      v7 = (char *)&pObjectList->pObjects->uObjectID;
+      break;
+    default:
+      return result;
+  }
+  while ( (short)a1.uItemType != *(short *)v7 )
+  {
+    ++v16;
+    v7 += 56;
+    if ( v16 >= (signed int)pObjectList->uNumObjects )
+    {
+LABEL_18:
+      v8 = 0;
+      goto LABEL_19;
+    }
+  }
+  v8 = v16;
+LABEL_19:
+  a1.uObjectDescID = v8;
+  a1.stru_24.Reset();
+  a1.vPosition.x = v5->vPosition.x;
+  a1.field_48 = 0;
+  a1.vPosition.y = v5->vPosition.y;
+  a1.field_4C = 0;
+  v17 = v5->uActorHeight;
+  a1.field_50 = 0;
+  v9 = LOWORD(v4->uYawAngle);
+  a1.vPosition.z = v5->vPosition.z - (unsigned int)(signed __int64)((double)v17 * -0.75);
+  a1.uFacing = v9;
+  a1.uSoundID = 0;
+  a1.uAttributes = 0;
+  v10 = pIndoor->GetSector(a1.vPosition.x, a1.vPosition.y, a1.vPosition.z);
+  v11 = v4->uDistance;
+  a1.uSectorID = v10;
+  v12 = 8 * v15;
+  LOBYTE(v12) = 8 * v15 | AI_OBJECT_ACTOR;
+  a1.uSpriteFrameID = 0;
+  a1.field_58 = v12;
+  a1.field_5C = 0;
+  if ( (double)v11 >= 307.2 )
+  {
+    if ( v11 >= 1024 )
+    {
+      a1.field_60_distance_related_prolly_lod = 2;
+      if ( v11 >= 2560 )
+        a1.field_60_distance_related_prolly_lod = 3;
+    }
+    else
+    {
+      a1.field_60_distance_related_prolly_lod = 1;
+    }
+  }
+  else
+  {
+    a1.field_60_distance_related_prolly_lod = 0;
+  }
+  a1.field_61 = a4;
+  result = a1.Create(
+             v4->uYawAngle,
+             v4->uPitchAngle,
+             pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+             0);
+  if ( v5->pMonsterInfo.uSpecialAbilityType == 1 )
+  {
+    result = v5->pMonsterInfo.uSpecialAbilityDamageDiceBonus;
+    if ( result == 2 )
+    {
+      a1.vPosition.z += 40;
+      v13 = v4->uYawAngle;
+    }
+    else
+    {
+      if ( result != 3 )
+        return result;
+      a1.Create(
+        v4->uYawAngle + 30,
+        v4->uPitchAngle,
+        pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+        0);
+      v13 = v4->uYawAngle - 30;
+    }
+    result = a1.Create(
+               v13,
+               v4->uPitchAngle,
+               pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+               0);
+  }
+  return result;
+}
+
+//----- (00404736) --------------------------------------------------------
+signed int __fastcall Actor::Explode(unsigned int uActorID)
+{
+  Actor *v1; // esi@1
+  signed int v2; // edx@1
+  char *v3; // ecx@2
+  unsigned __int16 v4; // ax@5
+  int v5; // ebx@6
+  int v6; // ecx@6
+  int v7; // eax@6
+  LayingItem a1; // [sp+Ch] [bp-78h]@1
+  unsigned int v10; // [sp+7Ch] [bp-8h]@1
+  int v11; // [sp+80h] [bp-4h]@6
+
+  v10 = uActorID;
+  v1 = &pActors[uActorID];
+  v2 = 0;
+  a1.uItemType = 600;
+  if ( (signed int)pObjectList->uNumObjects <= 0 )
+  {
+LABEL_5:
+    v4 = 0;
+  }
+  else
+  {
+    v3 = (char *)&pObjectList->pObjects->uObjectID;
+    while ( *(short *)v3 != 600 )
+    {
+      ++v2;
+      v3 += 56;
+      if ( v2 >= (signed int)pObjectList->uNumObjects )
+        goto LABEL_5;
+    }
+    v4 = v2;
+  }
+  a1.uObjectDescID = v4;
+  a1.stru_24.Reset();
+  a1.vPosition.y = v1->vPosition.y;
+  a1.field_48 = 0;
+  v5 = v1->vPosition.x;
+  v11 = v1->uActorHeight;
+  a1.field_4C = 0;
+  a1.field_50 = 0;
+  a1.vPosition.x = v5;
+  v6 = v1->vPosition.z - (unsigned int)(signed __int64)((double)v11 * -0.75);
+  a1.uFacing = 0;
+  a1.vPosition.z = v6;
+  a1.uSoundID = 0;
+  a1.uAttributes = 0;
+  a1.uSectorID = pIndoor->GetSector(v5, a1.vPosition.y, v6);
+  v7 = 8 * v10;
+  LOBYTE(v7) = 8 * v10 | 3;
+  a1.uSpriteFrameID = 0;
+  a1.field_58 = v7;
+  a1.field_5C = 0;
+  a1.field_60_distance_related_prolly_lod = 3;
+  a1.field_61 = 4;
+  return a1.Create(0, 0, 0, 0);
+}
+
+//----- (004040E9) --------------------------------------------------------
+// // Get direction vector from object1 to object2,
+// // distance from object1 to object2 and Euler angles of the direction vector
+// //
+// //
+// // object1 & object2 format :  objectType | (objectID << 3)
+// //    objectType == 2 - LayingItem
+// //    objectType == 3 - Actor
+// //    objectType == 4 - Party
+// //    objectType == 5 - Decoration
+// //
+// // originally this function had following prototype:
+// // struct DirectionInfo GetDirectionInfo(signed int object1, signed int object2, signed int a4)
+// // but compiler converts functions returning structures by value in the such way
+AIDirection *__fastcall Actor::GetDirectionInfo(unsigned int uObj1ID, unsigned int uObj2ID, AIDirection *pOut, int a4)
+{
+  signed int v4; // eax@1
+  unsigned int v5; // ecx@1
+  unsigned int v6; // ebx@1
+  int v7; // ecx@2
+  int v8; // ecx@3
+  int v9; // ecx@4
+  BLVFace *v10; // eax@8
+  unsigned int v11; // ecx@8
+  signed int v12; // eax@9
+  int v13; // ecx@9
+  int v14; // eax@9
+  int v15; // eax@11
+  int v16; // eax@12
+  int v17; // eax@13
+  int v18; // edx@15
+  signed int v19; // eax@25
+  signed int v20; // eax@28
+  int v21; // ebx@28
+  signed int v22; // eax@28
+  BLVFace *v23; // eax@35
+  int v24; // edx@35
+  unsigned int v25; // ecx@35
+  signed int v26; // eax@36
+  int v27; // ecx@36
+  int v28; // eax@36
+  int v29; // eax@37
+  signed int v30; // eax@42
+  double v31; // st7@45
+  double v32; // st6@45
+  double v33; // st7@45
+  AIDirection *result; // eax@48
+  int v35; // [sp-18h] [bp-64h]@17
+  int v36; // [sp-14h] [bp-60h]@17
+  Vec3_int_ v37; // [sp-10h] [bp-5Ch]@15
+  int *v38; // [sp-4h] [bp-50h]@15
+  int *v39; // [sp+0h] [bp-4Ch]@15
+  int *v40; // [sp+4h] [bp-48h]@15
+  AIDirection v41; // [sp+14h] [bp-38h]@46
+  float v42; // [sp+30h] [bp-1Ch]@23
+  float v43; // [sp+34h] [bp-18h]@45
+  float v44; // [sp+38h] [bp-14h]@33
+  float v45; // [sp+3Ch] [bp-10h]@33
+  int outz; // [sp+40h] [bp-Ch]@6
+  int outy; // [sp+44h] [bp-8h]@6
+  int outx; // [sp+48h] [bp-4h]@6
+  float a4a; // [sp+58h] [bp+Ch]@45
+
+  v4 = (signed int)uObj1ID >> 3;
+  v5 = (uObj1ID & 7) - 2;
+  v6 = uObj2ID;
+  if ( !v5 )
+  {
+    v19 = v4;
+    outx = pLayingItems[v19].vPosition.x;
+    v13 = pLayingItems[v19].vPosition.y;
+    v14 = pLayingItems[v19].vPosition.z;
+    goto LABEL_26;
+  }
+  v7 = v5 - 1;
+  if ( !v7 )
+  {
+    outx = pActors[v4].vPosition.x;
+    outy = pActors[v4].vPosition.y;
+    LODWORD(v42) = pActors[v4].uActorHeight;
+    v11 = pActors[v4].vPosition.z - (unsigned int)(signed __int64)((double)SLODWORD(v42) * -0.75);
+    goto LABEL_24;
+  }
+  v8 = v7 - 1;
+  if ( !v8 )
+  {
+    if ( !v4 )
+    {
+      outx = pParty->vPosition.x;
+      outy = pParty->vPosition.y;
+      v14 = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+LABEL_27:
+      outz = v14;
+      goto LABEL_28;
+    }
+    v15 = v4 - 1;
+    if ( v15 )
+    {
+      v16 = v15 - 1;
+      if ( v16 )
+      {
+        v17 = v16 - 1;
+        if ( v17 )
+        {
+          if ( v17 != 1 )
+            goto LABEL_28;
+          v40 = &outz;
+          v39 = &outy;
+          v38 = &outx;
+          v18 = pParty->sRotationY - stru_5C6E00->uIntegerHalfPi;
+          v37.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+          goto LABEL_20;
+        }
+        v40 = &outz;
+        v39 = &outy;
+        v38 = &outx;
+        v18 = pParty->sRotationY - stru_5C6E00->uIntegerHalfPi;
+        v37.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+      }
+      else
+      {
+        v40 = &outz;
+        v39 = &outy;
+        v38 = &outx;
+        v37.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+        v18 = stru_5C6E00->uIntegerHalfPi + pParty->sRotationY;
+      }
+      *(_QWORD *)&v37.x = *(_QWORD *)&pParty->vPosition.x;
+      v36 = 0;
+      v35 = 8;
+LABEL_21:
+      Vec3_int_::Rotate(v35, v18, v36, v37, v38, v39, v40);
+      goto LABEL_28;
+    }
+    v40 = &outz;
+    v39 = &outy;
+    v38 = &outx;
+    v37.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+    v18 = stru_5C6E00->uIntegerHalfPi + pParty->sRotationY;
+LABEL_20:
+    *(_QWORD *)&v37 = *(_QWORD *)&pParty->vPosition.x;
+    v36 = 0;
+    v35 = 24;
+    goto LABEL_21;
+  }
+  v9 = v8 - 1;
+  if ( !v9 )
+  {
+    v12 = v4;
+    outx = pLevelDecorations[v12].vPosition.x;
+    v13 = pLevelDecorations[v12].vPosition.y;
+    v14 = pLevelDecorations[v12].vPosition.z;
+LABEL_26:
+    outy = v13;
+    goto LABEL_27;
+  }
+  if ( v9 != 1 )
+  {
+    outz = 0;
+    outy = 0;
+    outx = 0;
+    goto LABEL_28;
+  }
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    v10 = &pIndoor->pFaces[v4];
+    outx = (v10->pBounding.x1 + v10->pBounding.x2) >> 1;
+    outy = (v10->pBounding.y1 + v10->pBounding.y2) >> 1;
+    v11 = (v10->pBounding.z1 + v10->pBounding.z2) >> 1;
+LABEL_24:
+    outz = v11;
+  }
+LABEL_28:
+  v20 = v6;
+  v21 = v6 & 7;
+  v22 = v20 >> 3;
+  if ( v21 == 2 )
+  {
+    v30 = v22;
+    LODWORD(v45) = pLayingItems[v30].vPosition.x;
+    v27 = pLayingItems[v30].vPosition.y;
+    v28 = pLayingItems[v30].vPosition.z;
+    goto LABEL_43;
+  }
+  if ( v21 == 3 )
+  {
+    LODWORD(v45) = pActors[v22].vPosition.x;
+    LODWORD(v44) = pActors[v22].vPosition.y;
+    v25 = pActors[v22].vPosition.z - (unsigned int)(signed __int64)((double)pActors[v22].uActorHeight * -0.75);
+    goto LABEL_41;
+  }
+  if ( v21 == 4 )
+  {
+    LODWORD(v45) = pParty->vPosition.x;
+    LODWORD(v44) = pParty->vPosition.y;
+    v29 = a4;
+    if ( !a4 )
+      v29 = pParty->sEyelevel;
+    v28 = pParty->vPosition.z + v29;
+    goto LABEL_44;
+  }
+  if ( v21 == 5 )
+  {
+    v26 = v22;
+    LODWORD(v45) = pLevelDecorations[v26].vPosition.x;
+    v27 = pLevelDecorations[v26].vPosition.y;
+    v28 = pLevelDecorations[v26].vPosition.z;
+LABEL_43:
+    LODWORD(v44) = v27;
+LABEL_44:
+    a4 = v28;
+    goto LABEL_45;
+  }
+  if ( v21 != 6 )
+  {
+    a4 = 0;
+    v44 = 0.0;
+    v45 = 0.0;
+    goto LABEL_45;
+  }
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    v23 = &pIndoor->pFaces[v22];
+    v24 = v23->pBounding.y1;
+    LODWORD(v45) = (v23->pBounding.x1 + v23->pBounding.x2) >> 1;
+    LODWORD(v44) = (v24 + v23->pBounding.y2) >> 1;
+    v25 = (v23->pBounding.z1 + v23->pBounding.z2) >> 1;
+LABEL_41:
+    a4 = v25;
+  }
+LABEL_45:
+  v31 = (double)SLODWORD(v45) - (double)outx;
+  v42 = v31;
+  v32 = (double)SLODWORD(v44) - (double)outy;
+  v43 = v32;
+  a4a = (double)a4 - (double)outz;
+  v45 = v32 * v32;
+  v44 = v31 * v31;
+  v33 = sqrt(a4a * a4a + v44 + v45);
+  if ( v33 <= 1.0 )
+  {
+    v41.vDirection.x = 65536;
+    v41.vDirection.y = 0;
+    v41.vDirection.z = 0;
+    v41.uDistance = 1;
+    v41.uDistanceXZ = 1;
+    v41.uYawAngle = 0;
+    v41.uPitchAngle = 0;
+  }
+  else
+  {
+    v41.vDirection.x = (signed __int64)(1.0 / v33 * v42 * 65536.0);
+    v41.vDirection.y = (signed __int64)(1.0 / v33 * v43 * 65536.0);
+    v41.vDirection.z = (signed __int64)(1.0 / v33 * a4a * 65536.0);
+    v41.uDistance = (signed __int64)v33;
+    v41.uDistanceXZ = (signed __int64)sqrt(v44 + v45);
+    v41.uYawAngle = stru_5C6E00->Atan2((signed __int64)v42, (signed __int64)v43);
+    v41.uPitchAngle = stru_5C6E00->Atan2(v41.uDistanceXZ, (signed __int64)a4a);
+  }
+  result = pOut;
+  memcpy(pOut, &v41, 0x1Cu);
+  return result;
+}
+
+
+//----- (00404030) --------------------------------------------------------
+unsigned int __fastcall Actor::FaceObject(unsigned int uActorID, unsigned int uObjID, int _48, AIDirection *a4)
+{
+  unsigned int v4; // edi@1
+  unsigned int v5; // esi@1
+  unsigned int result; // eax@2
+  AIDirection *v7; // eax@3
+  unsigned int v8; // ecx@3
+  Actor *v9; // ebx@3
+  AIDirection *v10; // esi@4
+  unsigned __int16 v11; // ax@5
+  AIDirection a3; // [sp+8h] [bp-38h]@4
+  AIDirection v13; // [sp+24h] [bp-1Ch]@4
+
+  v4 = uObjID;
+  v5 = uActorID;
+  if ( rand() % 100 >= 5 )
+  {
+    v7 = a4;
+    v8 = 0;
+    v9 = &pActors[v5];
+    if ( !a4 )
+    {
+      v10 = Actor::GetDirectionInfo(8 * v5 | AI_OBJECT_ACTOR, v4, &a3, 0);
+      v7 = &v13;
+      memcpy(&v13, v10, sizeof(v13));
+      v8 = 0;
+    }
+    v9->uYawAngle = LOWORD(v7->uYawAngle);
+    v11 = LOWORD(v7->uPitchAngle);
+    v9->uCurrentActionTime = v8;
+    v9->vVelocity.z = v8;
+    v9->vVelocity.y = v8;
+    v9->vVelocity.x = v8;
+    v9->uPitchAngle = v11;
+    v9->uCurrentActionLength = 256;
+    v9->uAIState = Interacting;
+    result = v9->UpdateAnimation();
+  }
+  else
+  {
+    result = Actor::_402F87(v5, v4, a4);
+  }
+  return result;
+}
+
+//----- (00403F58) --------------------------------------------------------
+unsigned int __fastcall Actor::_403F58(unsigned int uActorID, signed int uObjID, int uActionLength, AIDirection *a4)
+{
+  unsigned int v4; // esi@1
+  unsigned int result; // eax@2
+  AIDirection *v6; // eax@3
+  unsigned int v7; // edi@3
+  Actor *v8; // ebx@3
+  AIDirection *v9; // esi@4
+  AIDirection a3; // [sp+4h] [bp-3Ch]@4
+  AIDirection v11; // [sp+20h] [bp-20h]@4
+  signed int a2; // [sp+3Ch] [bp-4h]@1
+
+  a2 = uObjID;
+  v4 = uActorID;
+  if ( rand() % 2 )
+  {
+    result = Actor::_402F87(v4, a2, a4);
+  }
+  else
+  {
+    v6 = a4;
+    v7 = 0;
+    v8 = &pActors[v4];
+    if ( !a4 )
+    {
+      v9 = Actor::GetDirectionInfo(8 * v4 | 3, a2, &a3, 0);
+      v6 = &v11;
+      memcpy(&v11, v9, sizeof(v11));
+      v7 = 0;
+    }
+    v8->uYawAngle = LOWORD(v6->uYawAngle);
+    v8->uPitchAngle = LOWORD(v6->uPitchAngle);
+    if ( uActionLength == v7 )
+      v8->uCurrentActionLength = rand() % 256 + 256;
+    else
+      v8->uCurrentActionLength = uActionLength;
+    v8->uCurrentActionTime = v7;
+    v8->uAIState = Standing;
+    v8->vVelocity.z = v7;
+    v8->vVelocity.y = v7;
+    v8->vVelocity.x = v7;
+    result = v8->UpdateAnimation();
+  }
+  return result;
+}
+
+
+
+//----- (00403EB6) --------------------------------------------------------
+unsigned int __fastcall Actor::_403EB6(unsigned int uActorID, unsigned int a2, unsigned int uActionLength, AIDirection *a4)
+{
+  AIDirection *v4; // eax@1
+  unsigned int v5; // esi@1
+  Actor *v6; // ebx@1
+  AIDirection *v7; // esi@2
+  AIDirection a3; // [sp+Ch] [bp-38h]@2
+  AIDirection v10; // [sp+28h] [bp-1Ch]@2
+
+  v4 = a4;
+  v5 = 0;
+  v6 = &pActors[uActorID];
+  if ( !a4 )
+  {
+    v7 = Actor::GetDirectionInfo(8 * uActorID | 3, a2, &a3, 0);
+    v4 = &v10;
+    memcpy(&v10, v7, sizeof(v10));
+    v5 = 0;
+  }
+  v6->uYawAngle = LOWORD(v4->uYawAngle);
+  if ( uActionLength == v5 )
+    v6->uCurrentActionLength = rand() % 256 + 256;
+  else
+    v6->uCurrentActionLength = uActionLength;
+  v6->uCurrentActionTime = v5;
+  v6->uAIState = Standing;
+  v6->vVelocity.z = v5;
+  v6->vVelocity.y = v5;
+  v6->vVelocity.x = v5;
+  return v6->UpdateAnimation();
+}
+
+
+//----- (00403E61) --------------------------------------------------------
+void __fastcall Actor::StandAwhile(unsigned int uActorID)
+{
+  Actor *v1; // esi@1
+
+  v1 = &pActors[uActorID];
+  v1->uCurrentActionLength = rand() % 128 + 128;
+  v1->uCurrentActionTime = 0;
+  v1->uAIState = Standing;
+  v1->vVelocity.z = 0;
+  v1->vVelocity.y = 0;
+  v1->vVelocity.x = 0;
+  v1->UpdateAnimation();
+}
+
+//----- (00403C6C) --------------------------------------------------------
+unsigned int __fastcall Actor::_403C6C(unsigned int uActorID, signed int edx0, struct AIDirection *arg0)
+{
+  Actor *v3; // ebx@1
+  char v4; // zf@1
+  unsigned int result; // eax@3
+  AIDirection *v6; // esi@6
+  AIDirection *v7; // edi@6
+  signed int v8; // eax@7
+  double v9; // st7@9
+  Vec3_int_ v10; // ST04_12@9
+  int v11; // eax@10
+  AIDirection *v12; // eax@11
+  unsigned int v13; // esi@11
+  AIDirection *v14; // esi@12
+  SpriteFrame *v15; // ecx@13
+  __int16 v16; // ax@13
+  unsigned int v17; // ecx@13
+  signed __int64 v18; // qax@13
+  AIDirection a3; // [sp+Ch] [bp-48h]@12
+  AIDirection v20; // [sp+28h] [bp-2Ch]@12
+  unsigned int v21; // [sp+44h] [bp-10h]@9
+  signed int a2; // [sp+48h] [bp-Ch]@1
+  int v23; // [sp+4Ch] [bp-8h]@6
+  unsigned int v24; // [sp+50h] [bp-4h]@1
+  unsigned int v25; // [sp+5Ch] [bp+8h]@13
+
+  v3 = &pActors[uActorID];
+  a2 = edx0;
+  v4 = v3->pMonsterInfo.uMovementType == 5;
+  v24 = uActorID;
+  if ( v4 && v3->pMonsterInfo.uAIType == 1 )
+  {
+    result = Actor::_403EB6(uActorID, edx0, 0, arg0);
+  }
+  else
+  {
+    if ( (edx0 & 7) == 3 )
+    {
+      v8 = edx0 >> 3;
+      v6 = (AIDirection *)pActors[v8].vPosition.x;
+      v7 = (AIDirection *)pActors[v8].vPosition.y;
+      v23 = (signed __int64)((double)pActors[v8].uActorHeight * 0.75 + (double)pActors[v8].vPosition.z);
+    }
+    else
+    {
+      if ( (edx0 & 7) == 4 )
+      {
+        v6 = (AIDirection *)pParty->vPosition.x;
+        v7 = (AIDirection *)pParty->vPosition.y;
+        v23 = pParty->vPosition.z + pParty->sEyelevel;
+      }
+      else
+      {
+        v6 = arg0;
+        v7 = arg0;
+      }
+    }
+    v21 = v3->uActorHeight;
+    v9 = (double)(signed int)v21 * 0.75;
+    v21 = v3->vPosition.z;
+    v10.z = (signed __int64)(v9 + (double)(signed int)v21);
+    v10.y = v3->vPosition.y;
+    v10.x = v3->vPosition.x;
+    if ( sub_407A1C((int)v6, (int)v7, v23, v10) )
+    {
+      v12 = arg0;
+      v13 = 0;
+      if ( !arg0 )
+      {
+        v14 = Actor::GetDirectionInfo(8 * v24 | 3, a2, &a3, 0);
+        v12 = &v20;
+        memcpy(&v20, v14, sizeof(v20));
+        v13 = 0;
+      }
+      v15 = pSpriteFrameTable->pSpriteSFrames;
+      v3->uYawAngle = LOWORD(v12->uYawAngle);
+      v16 = v15[v3->pSpriteIDs[2]].uAnimLength;
+      v17 = v24;
+      v3->uCurrentActionLength = 8 * v16;
+      v3->uCurrentActionTime = v13;
+      v3->uAIState = AttackingMelee;
+      Actor::PlaySound(v17, 0);
+      LODWORD(v18) = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+      v25 = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+      if ( SHIDWORD(v3->pActorBuffs[7].uExpireTime) >= (signed int)v13
+        && (SHIDWORD(v3->pActorBuffs[7].uExpireTime) > (signed int)v13 || LODWORD(v3->pActorBuffs[7].uExpireTime) > v13) )
+      {
+        LODWORD(v18) = 2 * v18;
+        v25 = v18;
+      }
+      if ( pParty->bTurnBasedModeOn != 1 )
+        v18 = (signed __int64)(flt_6BE3A8_debug_recmod2 * (double)(signed int)v25 * 2.133333333333333);
+      v3->pMonsterInfo.uRecoveryTime = v18;
+      v3->vVelocity.z = v13;
+      v3->vVelocity.y = v13;
+      v3->vVelocity.x = v13;
+      result = v3->UpdateAnimation();
+    }
+    else
+    {
+      v11 = rand();
+      result = Actor::_402AD7(v24, a2, v11 % 2, 64, arg0);
+    }
+  }
+  return result;
+}
+
+
+//----- (00438CF3) --------------------------------------------------------
+void Actor::_438CF3(unsigned int uActorID)
+{
+  unsigned int v1; // esi@1
+  unsigned int v2; // edi@2
+  char v3; // bl@3
+  char *v4; // ecx@16
+  signed int v5; // eax@18
+  Player **ppPlayers; // esi@20
+
+  v1 = uLevelMapStatsID;
+  if ( !uLevelMapStatsID || (v2 = uActorID, !pActors[uActorID]._438B9B()) )
+    return;
+  v3 = 1;
+  if ( v1 != 5 )
+  {
+    if ( v1 == 6 || v1 == 7 )
+    {
+      _449B57_test_bit(pParty->_award_bits, 99);
+      if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 100) )
+        return;
+      goto LABEL_12;
+    }
+    if ( v1 != 8 )
+      goto LABEL_12;
+  }
+  if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 99) )
+    v3 = 0;
+  if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 100) )
+    v3 = 1;
+  if ( v3 )
+  {
+LABEL_12:
+    pParty->uFine += 100
+                  * (pMapStats->pInfos[uLevelMapStatsID]._steal_perm
+                   + pActors[v2].pMonsterInfo.uLevel
+                   + GetPartyReputation());
+    if ( pParty->uFine < 0 )
+      pParty->uFine = 0;
+    if ( pParty->uFine > 4000000 )
+      pParty->uFine = 4000000;
+    v4 = (char *)&pOutdoor->ddm;
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+      v4 = (char *)&pIndoor->dlv;
+    v5 = *((int *)v4 + 2);
+    if ( v5 < 10000 )
+      *((int *)v4 + 2) = v5 + 1;
+    ppPlayers = &pPlayers[1];
+    do
+    {
+      if ( pParty->uFine )
+      {
+        if ( !(unsigned __int16)_449B57_test_bit((unsigned __int8 *)(*ppPlayers)->field_152, 1) )
+          _449B7E_toggle_bit((unsigned char *)(*ppPlayers)->field_152, 1, 1u);
+      }
+      ++ppPlayers;
+    }
+    while ( (signed int)ppPlayers <= (signed int)&pPlayers[4] );
+  }
+}
+
+
+//----- (0043AE80) --------------------------------------------------------
+int Actor::AddBloodsplatOnDamageOverlay(unsigned int uActorID, int a2, signed int a3)
+{
+  int result; // eax@1
+  unsigned int v4; // esi@1
+  int v5; // [sp-14h] [bp-18h]@3
+  unsigned int v6; // [sp-10h] [bp-14h]@3
+  int v7; // [sp-Ch] [bp-10h]@3
+  int v8; // [sp-8h] [bp-Ch]@3
+  __int16 v9; // [sp-4h] [bp-8h]@3
+
+  result = a2 - 1;
+  v4 = 8 * uActorID | 3;
+  switch ( a2 )
+  {
+    case 1:
+      if ( a3 )
+      {
+        v9 = 0;
+        v8 = (signed __int64)(sub_43AE12(a3) * 65536.0);
+        v7 = 0;
+        LOWORD(v6) = v4;
+        v5 = 904;
+        goto LABEL_16;
+      }
+      return result;
+    case 2:
+      if ( a3 )
+      {
+        v9 = 0;
+        v8 = (signed __int64)(sub_43AE12(a3) * 65536.0);
+        v7 = 0;
+        LOWORD(v6) = v4;
+        v5 = 905;
+        goto LABEL_16;
+      }
+      return result;
+    case 3:
+      if ( a3 )
+      {
+        v9 = 0;
+        v8 = (signed __int64)(sub_43AE12(a3) * 65536.0);
+        v7 = 0;
+        LOWORD(v6) = v4;
+        v5 = 906;
+        goto LABEL_16;
+      }
+      return result;
+    case 4:
+      if ( a3 )
+      {
+        v9 = 0;
+        v8 = (signed __int64)(sub_43AE12(a3) * 65536.0);
+        v7 = 0;
+        LOWORD(v6) = v4;
+        v5 = 907;
+        goto LABEL_16;
+      }
+      return result;
+    case 5:
+      v9 = 4;
+      v8 = 65536;
+      v7 = 0;
+      v6 = 8 * uActorID | 3;
+      v5 = 901;
+      goto LABEL_16;
+    case 6:
+      v9 = 4;
+      v8 = 65536;
+      v7 = 0;
+      v6 = 8 * uActorID | 3;
+      v5 = 902;
+      goto LABEL_16;
+    case 7:
+      v9 = 4;
+      v8 = 65536;
+      v7 = 0;
+      v6 = 8 * uActorID | 3;
+      v5 = 903;
+      goto LABEL_16;
+    case 8:
+      v9 = 4;
+      v8 = 65536;
+      v7 = 0;
+      v6 = 8 * uActorID | 3;
+      v5 = 900;
+      goto LABEL_16;
+    case 9:
+      v9 = 4;
+      v8 = 65536;
+      v7 = 0;
+      v6 = 8 * uActorID | 3;
+      v5 = 909;
+      goto LABEL_16;
+    case 10:
+      v9 = 4;
+      v8 = 65536;
+      v7 = 0;
+      v6 = 8 * uActorID | 3;
+      v5 = 908;
+LABEL_16:
+      result = pOtherOverlayList->_4418B6(v5, v6, v7, v8, v9);
+      break;
+    default:
+      return result;
+  }
+  return result;
+}
+
+
+//----- (0043B3E0) --------------------------------------------------------
+int Actor::_43B3E0_CalcDamage(Actor *a1, signed int a2)
+{
+  signed int v2; // ebp@1
+  int v3; // eax@9
+  signed int v4; // edi@9
+  int v5; // esi@9
+  int v6; // ebx@11
+  unsigned __int16 v8; // si@21
+  int v9; // edi@21
+  signed int v10; // eax@23
+  int v11; // [sp+10h] [bp-4h]@1
+
+  v2 = 0;
+  v11 = 0;
+  if ( a2 )
+  {
+    if ( a2 == 1 )
+    {
+      v3 = a1->pMonsterInfo.uAttack2DamageDiceRolls;
+      v4 = a1->pMonsterInfo.uAttack2DamageDiceSides;
+      v5 = a1->pMonsterInfo.uAttack2DamageBonus;
+    }
+    else
+    {
+      if ( a2 <= 1 )
+        return 0;
+      if ( a2 <= 3 )
+      {
+        if ( a2 == 2 )
+        {
+          v8 = a1->pMonsterInfo.uSpellSkillAndMastery1;
+          v9 = a1->pMonsterInfo.uSpell1ID;
+        }
+        else
+        {
+          v8 = a1->pMonsterInfo.uSpellSkillAndMastery2;
+          v9 = a1->pMonsterInfo.uSpell2ID;
+        }
+        v10 = SkillToMastery(v8);
+        return _43AFE3_calc_spell_damage(v9, v8 & 0x3F, v10, 0);
+      }
+      if ( a2 != 4 )
+        return 0;
+      v3 = a1->pMonsterInfo.uSpecialAbilityDamageDiceRolls;
+      v4 = a1->pMonsterInfo.uSpecialAbilityDamageDiceSides;
+      v5 = a1->pMonsterInfo.uSpecialAbilityDamageDiceBonus;
+    }
+  }
+  else
+  {
+    if ( (signed __int64)a1->pActorBuffs[14].uExpireTime > 0 )
+      v2 = a1->pActorBuffs[14].uPower;
+    if ( (signed __int64)a1->pActorBuffs[18].uExpireTime > 0 && a1->pActorBuffs[18].uPower > v2 )
+      v2 = a1->pActorBuffs[18].uPower;
+    if ( (signed __int64)a1->pActorBuffs[21].uExpireTime > 0 )
+      v2 += a1->pActorBuffs[21].uPower;
+    v3 = a1->pMonsterInfo.uAttack1DamageDiceRolls;
+    v4 = a1->pMonsterInfo.uAttack1DamageDiceSides;
+    v5 = a1->pMonsterInfo.uAttack1DamageBonus;
+  }
+  if ( v3 > 0 )
+  {
+    v6 = v3;
+    do
+    {
+      --v6;
+      v11 += rand() % v4 + 1;
+    }
+    while ( v6 );
+  }
+  return v11 + v5 + v2;
+}
+
+//----- (00438B9B) --------------------------------------------------------
+char Actor::_438B9B()
+{
+  unsigned int v1; // eax@1
+
+  v1 = this->uAlly;
+  if ( !v1 )
+    v1 = (this->pMonsterInfo.uID - 1) / 3 + 1;
+  return (signed int)v1 >= 39 && (signed int)v1 <= 44
+      || (signed int)v1 >= 45 && (signed int)v1 <= 50
+      || (signed int)v1 >= 51 && (signed int)v1 <= 62
+      || (signed int)v1 >= 78 && (signed int)v1 <= 83;
+}
+
+//----- (0042EBEE) --------------------------------------------------------
+bool Actor::StealFrom(unsigned int uActorID)
+{
+  unsigned int v1; // esi@1
+  Player *pPlayer; // edi@1
+  bool result; // eax@1
+  int v4; // ebx@2
+  unsigned int v5; // eax@2
+  DDM_DLV_Header *v6; // esi@4
+  unsigned int v7; // [sp+8h] [bp-4h]@1
+  int v8; // [sp+8h] [bp-4h]@6
+
+  v1 = uActiveCharacter;
+  v7 = uActorID;
+  pPlayer = (Player *)&stru_AA1058[3].pSounds[6972 * uActiveCharacter + 40552];
+  result = pPlayer->CanAct();
+  if ( result )
+  {
+    pStru277->_427D48(v1);
+    v4 = 0;
+    v5 = pMapStats->GetMapInfo(pCurrentMapName);
+    if ( v5 )
+      v4 = pMapStats->pInfos[v5]._steal_perm;
+    v6 = &pOutdoor->ddm;
+    if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor)
+      v6 = &pIndoor->dlv;
+    pPlayer->StealFromActor(v7, v4, v6->uReputation++);
+    v8 = pPlayer->GetAttackRecoveryTime(0);
+    if ( v8 < 30 )
+      v8 = 30;
+    if ( !pParty->bTurnBasedModeOn )
+      pPlayer->SetRecoveryTime((signed __int64)(flt_6BE3A4_debug_recmod1 * (double)v8 * 2.133333333333333));
+    pTurnEngine->_40471C();
+    result = 1;
+  }
+  return result;
+}
+
+
+//----- (00403A60) --------------------------------------------------------
+unsigned int __fastcall Actor::_403A60(unsigned int uActorID, signed int edx0, AIDirection *pDir)
+{
+  Actor *v3; // ebx@1
+  AIDirection *v4; // esi@3
+  AIDirection *v5; // edi@3
+  signed int v6; // eax@4
+  Vec3_int_ v7; // ST04_12@6
+  unsigned int result; // eax@7
+  AIDirection *v9; // eax@8
+  unsigned int v10; // esi@8
+  AIDirection *v11; // esi@9
+  SpriteFrame *v12; // ecx@10
+  __int16 v13; // ax@10
+  unsigned int v14; // ecx@10
+  unsigned int v15; // eax@10
+  signed int v16; // ecx@17
+  AIDirection a3; // [sp+Ch] [bp-48h]@9
+  AIDirection v18; // [sp+28h] [bp-2Ch]@9
+  int v19; // [sp+44h] [bp-10h]@6
+  signed int a2; // [sp+48h] [bp-Ch]@1
+  int v21; // [sp+4Ch] [bp-8h]@3
+  unsigned int v22; // [sp+50h] [bp-4h]@1
+  unsigned int pDira; // [sp+5Ch] [bp+8h]@10
+
+  v22 = uActorID;
+  v3 = &pActors[uActorID];
+  a2 = edx0;
+  if ( (edx0 & 7) == 3 )
+  {
+    v6 = edx0 >> 3;
+    v4 = (AIDirection *)pActors[v6].vPosition.x;
+    v5 = (AIDirection *)pActors[v6].vPosition.y;
+    v21 = (signed __int64)((double)pActors[v6].uActorHeight * 0.75 + (double)pActors[v6].vPosition.z);
+  }
+  else
+  {
+    if ( (edx0 & 7) == 4 )
+    {
+      v4 = (AIDirection *)pParty->vPosition.x;
+      v5 = (AIDirection *)pParty->vPosition.y;
+      v21 = pParty->vPosition.z + pParty->sEyelevel;
+    }
+    else
+    {
+      v4 = pDir;
+      v5 = pDir;
+    }
+  }
+  v19 = v3->uActorHeight;
+  v7.z = v3->vPosition.z - (unsigned int)(signed __int64)((double)v19 * -0.75);
+  v7.y = v3->vPosition.y;
+  v7.x = v3->vPosition.x;
+  if ( sub_407A1C((int)v4, (int)v5, v21, v7) )
+  {
+    v9 = pDir;
+    v10 = 0;
+    if ( !pDir )
+    {
+      v11 = Actor::GetDirectionInfo(8 * v22 | 3, a2, &a3, 0);
+      v9 = &v18;
+      memcpy(&v18, v11, sizeof(v18));
+      v10 = 0;
+    }
+    v12 = pSpriteFrameTable->pSpriteSFrames;
+    v3->uYawAngle = LOWORD(v9->uYawAngle);
+    v13 = v12[v3->pSpriteIDs[3]].uAnimLength;
+    v14 = v22;
+    v3->uCurrentActionLength = 8 * v13;
+    v3->uCurrentActionTime = v10;
+    v3->uAIState = AttackingRanged4;
+    Actor::PlaySound(v14, 0);
+    v15 = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+    pDira = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+    if ( SHIDWORD(v3->pActorBuffs[7].uExpireTime) >= (signed int)v10
+      && (SHIDWORD(v3->pActorBuffs[7].uExpireTime) > (signed int)v10 || LODWORD(v3->pActorBuffs[7].uExpireTime) > v10) )
+    {
+      v15 *= 2;
+      pDira = v15;
+    }
+    if ( pParty->bTurnBasedModeOn == 1 )
+      v3->pMonsterInfo.uRecoveryTime = v15;
+    else
+      v3->pMonsterInfo.uRecoveryTime = v3->uCurrentActionLength
+                                     - (unsigned int)(signed __int64)(flt_6BE3A8_debug_recmod2
+                                                                    * (double)(signed int)pDira
+                                                                    * -2.133333333333333);
+    v16 = v3->pMonsterInfo.uSpell2ID;
+    v3->vVelocity.z = v10;
+    v3->vVelocity.y = v10;
+    v3->vVelocity.x = v10;
+    if ( sub_42FB5C(v16) )
+    {
+      v3->uCurrentActionLength = 64;
+      v3->uCurrentActionTime = v10;
+      v3->uAIState = Fidgeting;
+      result = v3->UpdateAnimation();
+      v3->uAIState = AttackingRanged4;
+    }
+    else
+    {
+      result = v3->UpdateAnimation();
+    }
+  }
+  else
+  {
+    result = Actor::_402AD7(v22, a2, v22, 64, pDir);
+  }
+  return result;
+}
+
+
+//----- (00403854) --------------------------------------------------------
+unsigned int __fastcall Actor::_403854(unsigned int uActorID, signed int edx0, AIDirection *pDir)
+{
+  Actor *v3; // ebx@1
+  AIDirection *v4; // esi@3
+  AIDirection *v5; // edi@3
+  signed int v6; // eax@4
+  Vec3_int_ v7; // ST04_12@6
+  unsigned int result; // eax@7
+  AIDirection *v9; // eax@8
+  unsigned int v10; // esi@8
+  AIDirection *v11; // esi@9
+  SpriteFrame *v12; // ecx@10
+  __int16 v13; // ax@10
+  unsigned int v14; // ecx@10
+  unsigned int v15; // eax@10
+  signed int v16; // ecx@17
+  AIDirection a3; // [sp+Ch] [bp-48h]@9
+  AIDirection v18; // [sp+28h] [bp-2Ch]@9
+  int v19; // [sp+44h] [bp-10h]@6
+  signed int a2; // [sp+48h] [bp-Ch]@1
+  int v21; // [sp+4Ch] [bp-8h]@3
+  unsigned int v22; // [sp+50h] [bp-4h]@1
+  unsigned int pDira; // [sp+5Ch] [bp+8h]@10
+
+  v22 = uActorID;
+  v3 = &pActors[uActorID];
+  a2 = edx0;
+  if ( (edx0 & 7) == 3 )
+  {
+    v6 = edx0 >> 3;
+    v4 = (AIDirection *)pActors[v6].vPosition.x;
+    v5 = (AIDirection *)pActors[v6].vPosition.y;
+    v21 = (signed __int64)((double)pActors[v6].uActorHeight * 0.75 + (double)pActors[v6].vPosition.z);
+  }
+  else
+  {
+    if ( (edx0 & 7) == 4 )
+    {
+      v4 = (AIDirection *)pParty->vPosition.x;
+      v5 = (AIDirection *)pParty->vPosition.y;
+      v21 = pParty->vPosition.z + pParty->sEyelevel;
+    }
+    else
+    {
+      v4 = pDir;
+      v5 = pDir;
+    }
+  }
+  v19 = v3->uActorHeight;
+  v7.z = v3->vPosition.z - (unsigned int)(signed __int64)((double)v19 * -0.75);
+  v7.y = v3->vPosition.y;
+  v7.x = v3->vPosition.x;
+  if ( sub_407A1C((int)v4, (int)v5, v21, v7) )
+  {
+    v9 = pDir;
+    v10 = 0;
+    if ( !pDir )
+    {
+      v11 = Actor::GetDirectionInfo(8 * v22 | 3, a2, &a3, 0);
+      v9 = &v18;
+      memcpy(&v18, v11, sizeof(v18));
+      v10 = 0;
+    }
+    v12 = pSpriteFrameTable->pSpriteSFrames;
+    v3->uYawAngle = LOWORD(v9->uYawAngle);
+    v13 = v12[v3->pSpriteIDs[3]].uAnimLength;
+    v14 = v22;
+    v3->uCurrentActionLength = 8 * v13;
+    v3->uCurrentActionTime = v10;
+    v3->uAIState = AttackingRanged3;
+    Actor::PlaySound(v14, 0);
+    v15 = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+    pDira = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+    if ( SHIDWORD(v3->pActorBuffs[7].uExpireTime) >= (signed int)v10
+      && (SHIDWORD(v3->pActorBuffs[7].uExpireTime) > (signed int)v10 || LODWORD(v3->pActorBuffs[7].uExpireTime) > v10) )
+    {
+      v15 *= 2;
+      pDira = v15;
+    }
+    if ( pParty->bTurnBasedModeOn == 1 )
+      v3->pMonsterInfo.uRecoveryTime = v15;
+    else
+      v3->pMonsterInfo.uRecoveryTime = v3->uCurrentActionLength
+                                     - (unsigned int)(signed __int64)(flt_6BE3A8_debug_recmod2
+                                                                    * (double)(signed int)pDira
+                                                                    * -2.133333333333333);
+    v16 = v3->pMonsterInfo.uSpell1ID;
+    v3->vVelocity.z = v10;
+    v3->vVelocity.y = v10;
+    v3->vVelocity.x = v10;
+    if ( sub_42FB5C(v16) )
+    {
+      v3->uCurrentActionLength = 64;
+      v3->uCurrentActionTime = v10;
+      v3->uAIState = Fidgeting;
+      result = v3->UpdateAnimation();
+      v3->uAIState = AttackingRanged3;
+    }
+    else
+    {
+      result = v3->UpdateAnimation();
+    }
+  }
+  else
+  {
+    result = Actor::_402AD7(v22, a2, v22, 64, pDir);
+  }
+  return result;
+}
+
+
+//----- (0040368B) --------------------------------------------------------
+unsigned int __fastcall Actor::_40368B(unsigned int uActorID, signed int edx0, AIDirection *pDir)
+{
+  Actor *v3; // ebx@1
+  AIDirection *v4; // esi@3
+  AIDirection *v5; // edi@3
+  signed int v6; // eax@4
+  Vec3_int_ v7; // ST04_12@6
+  unsigned int result; // eax@7
+  AIDirection *v9; // eax@8
+  unsigned int v10; // esi@8
+  AIDirection *v11; // esi@9
+  SpriteFrame *v12; // ecx@10
+  __int16 v13; // ax@10
+  unsigned int v14; // ecx@10
+  signed __int64 v15; // qax@10
+  AIDirection a3; // [sp+Ch] [bp-48h]@9
+  AIDirection v17; // [sp+28h] [bp-2Ch]@9
+  int v18; // [sp+44h] [bp-10h]@6
+  signed int a2; // [sp+48h] [bp-Ch]@1
+  int v20; // [sp+4Ch] [bp-8h]@3
+  unsigned int v21; // [sp+50h] [bp-4h]@1
+  unsigned int pDira; // [sp+5Ch] [bp+8h]@10
+
+  v21 = uActorID;
+  v3 = &pActors[uActorID];
+  a2 = edx0;
+  if ( (edx0 & 7) == 3 )
+  {
+    v6 = edx0 >> 3;
+    v4 = (AIDirection *)pActors[v6].vPosition.x;
+    v5 = (AIDirection *)pActors[v6].vPosition.y;
+    v20 = (signed __int64)((double)pActors[v6].uActorHeight * 0.75 + (double)pActors[v6].vPosition.z);
+  }
+  else
+  {
+    if ( (edx0 & 7) == 4 )
+    {
+      v4 = (AIDirection *)pParty->vPosition.x;
+      v5 = (AIDirection *)pParty->vPosition.y;
+      v20 = pParty->vPosition.z + pParty->sEyelevel;
+    }
+    else
+    {
+      v4 = pDir;
+      v5 = pDir;
+    }
+  }
+  v18 = v3->uActorHeight;
+  v7.z = v3->vPosition.z - (unsigned int)(signed __int64)((double)v18 * -0.75);
+  v7.y = v3->vPosition.y;
+  v7.x = v3->vPosition.x;
+  if ( sub_407A1C((int)v4, (int)v5, v20, v7) )
+  {
+    v9 = pDir;
+    v10 = 0;
+    if ( !pDir )
+    {
+      v11 = Actor::GetDirectionInfo(8 * v21 | 3, a2, &a3, 0);
+      v9 = &v17;
+      memcpy(&v17, v11, sizeof(v17));
+      v10 = 0;
+    }
+    v12 = pSpriteFrameTable->pSpriteSFrames;
+    v3->uYawAngle = LOWORD(v9->uYawAngle);
+    v13 = v12[v3->pSpriteIDs[3]].uAnimLength;
+    v14 = v21;
+    v3->uCurrentActionLength = 8 * v13;
+    v3->uCurrentActionTime = v10;
+    v3->uAIState = AttackingRanged2;
+    Actor::PlaySound(v14, 0);
+    LODWORD(v15) = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+    pDira = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+    if ( SHIDWORD(v3->pActorBuffs[7].uExpireTime) >= (signed int)v10
+      && (SHIDWORD(v3->pActorBuffs[7].uExpireTime) > (signed int)v10 || LODWORD(v3->pActorBuffs[7].uExpireTime) > v10) )
+    {
+      LODWORD(v15) = 2 * v15;
+      pDira = v15;
+    }
+    if ( pParty->bTurnBasedModeOn != 1 )
+      v15 = (signed __int64)(flt_6BE3A8_debug_recmod2 * (double)(signed int)pDira * 2.133333333333333);
+    v3->pMonsterInfo.uRecoveryTime = v15;
+    v3->vVelocity.z = v10;
+    v3->vVelocity.y = v10;
+    v3->vVelocity.x = v10;
+    result = v3->UpdateAnimation();
+  }
+  else
+  {
+    result = Actor::_402AD7(v21, a2, v21, 64, pDir);
+  }
+  return result;
+}
+
+
+//----- (00403476) --------------------------------------------------------
+unsigned int __fastcall Actor::_403476(unsigned int uActorID, signed int edx0, AIDirection *pDir)
+{
+  Actor *v3; // ebx@1
+  int v4; // esi@3
+  int v5; // edi@3
+  signed int v6; // eax@4
+  Vec3_int_ v7; // ST04_12@6
+  unsigned char v8[12]; // ST04_12@7
+  unsigned int result; // eax@8
+  AIDirection *v10; // eax@9
+  unsigned int v11; // esi@9
+  AIDirection *v12; // esi@10
+  SpriteFrame *v13; // ecx@11
+  __int16 v14; // ax@11
+  unsigned int v15; // ecx@11
+  unsigned int v16; // eax@11
+  AIDirection a3; // [sp+Ch] [bp-48h]@10
+  AIDirection v18; // [sp+28h] [bp-2Ch]@10
+  int v19; // [sp+44h] [bp-10h]@6
+  signed int a2; // [sp+48h] [bp-Ch]@1
+  unsigned int v21; // [sp+4Ch] [bp-8h]@1
+  int v22; // [sp+50h] [bp-4h]@3
+  unsigned int pDira; // [sp+5Ch] [bp+8h]@11
+
+  v21 = uActorID;
+  v3 = &pActors[uActorID];
+  a2 = edx0;
+  if ( (edx0 & 7) == 3 )
+  {
+    v6 = edx0 >> 3;
+    v4 = pActors[v6].vPosition.x;
+    v5 = pActors[v6].vPosition.y;
+    v22 = (signed __int64)((double)pActors[v6].uActorHeight * 0.75 + (double)pActors[v6].vPosition.z);
+  }
+  else
+  {
+    if ( (edx0 & 7) == 4 )
+    {
+      v4 = pParty->vPosition.x;
+      v5 = pParty->vPosition.y;
+      v22 = pParty->vPosition.z + pParty->sEyelevel;
+    }
+    else
+    {
+      v4 = (int)pDir;
+      v5 = (int)pDir;
+    }
+  }
+  v19 = v3->uActorHeight;
+  v7.z = v3->vPosition.z - (unsigned int)(signed __int64)((double)v19 * -0.75);
+  v7.y = v3->vPosition.y;
+  v7.x = v3->vPosition.x;
+  if ( sub_407A1C(v4, v5, v22, v7)
+    || (*(unsigned int *)&v8[8] = v22,
+        v19 = v3->uActorHeight,
+        *(_QWORD *)v8 = __PAIR__(v5, v4),
+        sub_407A1C(
+          v3->vPosition.x,
+          v3->vPosition.y,
+          v3->vPosition.z - (unsigned int)(signed __int64)((double)v19 * -0.75),
+          *(Vec3_int_ *)v8)) )
+  {
+    v10 = pDir;
+    v11 = 0;
+    if ( !pDir )
+    {
+      v12 = Actor::GetDirectionInfo(8 * v21 | 3, a2, &a3, 0);
+      v10 = &v18;
+      memcpy(&v18, v12, sizeof(v18));
+      v11 = 0;
+    }
+    v13 = pSpriteFrameTable->pSpriteSFrames;
+    v3->uYawAngle = LOWORD(v10->uYawAngle);
+    v14 = v13[v3->pSpriteIDs[3]].uAnimLength;
+    v15 = v21;
+    v3->uCurrentActionLength = 8 * v14;
+    v3->uCurrentActionTime = v11;
+    v3->uAIState = AttackingRanged1;
+    Actor::PlaySound(v15, 0);
+    v16 = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+    pDira = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uRecoveryTime;
+    if ( SHIDWORD(v3->pActorBuffs[7].uExpireTime) >= (signed int)v11
+      && (SHIDWORD(v3->pActorBuffs[7].uExpireTime) > (signed int)v11 || LODWORD(v3->pActorBuffs[7].uExpireTime) > v11) )
+    {
+      v16 *= 2;
+      pDira = v16;
+    }
+    if ( pParty->bTurnBasedModeOn == 1 )
+      v3->pMonsterInfo.uRecoveryTime = v16;
+    else
+      v3->pMonsterInfo.uRecoveryTime = v3->uCurrentActionLength
+                                     - (unsigned int)(signed __int64)(flt_6BE3A8_debug_recmod2
+                                                                    * (double)(signed int)pDira
+                                                                    * -2.133333333333333);
+    v3->vVelocity.z = v11;
+    v3->vVelocity.y = v11;
+    v3->vVelocity.x = v11;
+    result = v3->UpdateAnimation();
+  }
+  else
+  {
+    result = Actor::_402AD7(v21, a2, v21, 64, pDir);
+  }
+  return result;
+}
+
+//----- (004032B2) --------------------------------------------------------
+void __fastcall Actor::_4032B2(unsigned int a1, unsigned int a2, int a3, int uActionLength)
+{
+  unsigned int v4; // edi@1
+  Actor *v5; // esi@1
+  int v6; // ebx@1
+  int v7; // ST08_4@1
+  int v8; // eax@1
+  unsigned int v9; // ebx@11
+  int v10; // ebx@13
+  signed __int16 v11; // cx@17
+  unsigned int v12; // [sp-8h] [bp-44h]@10
+  AIDirection *v13; // [sp-4h] [bp-40h]@10
+  AIDirection v14; // [sp+Ch] [bp-30h]@7
+  int v15; // [sp+28h] [bp-14h]@11
+  unsigned int v16; // [sp+2Ch] [bp-10h]@1
+  int y; // [sp+30h] [bp-Ch]@1
+  unsigned int uActorID; // [sp+34h] [bp-8h]@1
+  int v19; // [sp+38h] [bp-4h]@1
+
+  uActorID = a1;
+  v4 = a1;
+  v5 = &pActors[a1];
+  v16 = a2;
+  v6 = v5->vInitialPosition.x - v5->vPosition.x;
+  v7 = v5->vInitialPosition.x - v5->vPosition.x;
+  y = v5->vInitialPosition.y - v5->vPosition.y;
+  v19 = abs(v7);
+  v8 = abs(y);
+  if ( v19 <= v8 )
+    v19 = v8 + (v19 >> 1);
+  else
+    v19 += v8 >> 1;
+  if ( MonsterStats::BelongsToSupertype(v5->pMonsterInfo.uID, MONSTER_SUPERTYPE_TREANT) )
+  {
+    if ( !uActionLength )
+      uActionLength = 256;
+    Actor::_403F58(uActorID, 4, uActionLength, &v14);
+    return;
+  }
+  if ( pActors[v4].pMonsterInfo.uMovementType == 3 && v19 < 128 )
+  {
+    v13 = &v14;
+    v12 = 256;
+LABEL_16:
+    Actor::_403EB6(uActorID, v16, v12, v13);
+    return;
+  }
+  v15 = (rand() & 0xF) << 12;
+  v19 += (unsigned __int64)(v15 * (signed __int64)a3) >> 16;
+  v9 = (stru_5C6E00->uIntegerDoublePi - 1) & stru_5C6E00->Atan2(v6, y);
+  if ( rand() % 100 < 25 )
+  {
+    Actor::StandAwhile(uActorID);
+    return;
+  }
+  v10 = v9 + rand() % 256 - 128;
+  if ( abs(v10 - v5->uYawAngle) > 256 && !(BYTE2(v5->uAttributes) & 0x20) )
+  {
+    v13 = &v14;
+    v12 = 256;
+    goto LABEL_16;
+  }
+  v11 = v5->uMovementSpeed;
+  v5->uYawAngle = v10;
+  if ( v11 )
+    v5->uCurrentActionLength = 32 * v19 / v11;
+  else
+    v5->uCurrentActionLength = 0;
+  v5->uCurrentActionTime = 0;
+  v5->uAIState = Tethered;
+  if ( rand() % 100 < 2 )
+    Actor::PlaySound(uActorID, 3u);
+  v5->UpdateAnimation();
+}
+
+
+//----- (004031C1) --------------------------------------------------------
+char __fastcall Actor::_4031C1_update_job(unsigned int uActorID, signed int a2, int a3)
+{
+  unsigned int v3; // edi@1
+  Actor *v4; // esi@1
+  ActorJob *v5; // eax@1
+  signed int v6; // edx@2
+  ActorJob *v7; // eax@2
+  signed int v8; // edi@2
+  char *v9; // ecx@2
+  __int16 v10; // cx@15
+  signed int v12; // [sp+8h] [bp-4h]@1
+
+  v3 = uActorID;
+  v12 = a2;
+  v4 = &pActors[uActorID];
+  v5 = (ActorJob *)pActors[uActorID].CanAct();
+  if ( v5 )
+  {
+    v6 = 65535;
+    v7 = &v4->pScheduledJobs[v3];
+    v8 = 7;
+    v9 = (char *)&v7[7].uHour;
+    while ( !(*(v9 - 3) & 1) || (unsigned __int8)*v9 > v12 )
+    {
+      --v8;
+      v9 -= 12;
+      if ( v8 < 0 )
+        goto LABEL_8;
+    }
+    v6 = v8;
+LABEL_8:
+    if ( !v8 && v6 == 65535 )
+      v6 = 7;
+    v5 = &v7[v6];
+    if ( v4->vInitialPosition.x != v5->vPos.x
+      || v4->vInitialPosition.y != v5->vPos.y
+      || v4->vInitialPosition.z != v5->vPos.z
+      || v4->pMonsterInfo.uMovementType != v5->uAction )
+    {
+      v4->vInitialPosition.x = v5->vPos.x;
+      v4->vInitialPosition.y = v5->vPos.y;
+      v10 = v5->vPos.z;
+      v4->vInitialPosition.z = v10;
+      LOBYTE(v5) = v5->uAction;
+      v4->pMonsterInfo.uMovementType = (unsigned __int8)v5;
+      if ( a3 == 1 )
+      {
+        v4->vPosition.x = v4->vInitialPosition.x;
+        v4->vPosition.y = v4->vInitialPosition.y;
+        LOBYTE(v5) = v10;
+        v4->vPosition.z = v10;
+      }
+    }
+  }
+  return (char)v5;
+}
+
+
+//----- (004030AD) --------------------------------------------------------
+__int16 __fastcall Actor::_4030AD(unsigned int uActorID, signed int edx0, int arg0)
+{
+  unsigned int v3; // edi@1
+  Actor *v4; // ebx@1
+  __int16 result; // ax@10
+  SpriteFrame *v6; // ecx@16
+  __int16 v7; // ax@16
+  unsigned int v8; // ecx@16
+  AIDirection a3; // [sp+Ch] [bp-40h]@16
+  AIDirection v10; // [sp+28h] [bp-24h]@16
+  unsigned int v11; // [sp+44h] [bp-8h]@1
+  signed int a2; // [sp+48h] [bp-4h]@1
+
+  v3 = uActorID;
+  a2 = edx0;
+  v4 = &pActors[uActorID];
+  v11 = uActorID;
+  if ( v4->uAIState == 7 )
+    BYTE2(v4->uAttributes) |= 2u;
+  if ( v4->pMonsterInfo.uHostilityType != 4 )
+  {
+    v4->uAttributes &= 0xFFFFFFFBu;
+    v4->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Long;
+  }
+  if ( (signed __int64)v4->pActorBuffs[1].uExpireTime > 0 )
+    v4->pActorBuffs[1].Reset();
+  if ( (signed __int64)v4->pActorBuffs[4].uExpireTime > 0 )
+    v4->pActorBuffs[4].Reset();
+  if ( arg0
+    || (result = v4->uAIState, result != 8)
+    && result != 3
+    && result != 12
+    && result != 13
+    && result != 18
+    && result != 2 )
+  {
+    memcpy(&v10, Actor::GetDirectionInfo(8 * v3 | 3, a2, &a3, 0), sizeof(v10));
+    v6 = pSpriteFrameTable->pSpriteSFrames;
+    v4->uYawAngle = LOWORD(v10.uYawAngle);
+    v7 = v6[v4->pSpriteIDs[4]].uAnimLength;
+    v8 = v11;
+    v4->uCurrentActionTime = 0;
+    v4->uAIState = Stunned;
+    v4->uCurrentActionLength = 8 * v7;
+    Actor::PlaySound(v8, 2u);
+    result = v4->UpdateAnimation();
+  }
+  return result;
+}
+
+//----- (00402F87) --------------------------------------------------------
+int __fastcall Actor::_402F87(unsigned int uActorID, unsigned int uObjID, AIDirection *a4)
+{
+  int v3; // edi@1
+  AIDirection *v4; // esi@1
+  Actor *v5; // ebx@1
+  SpriteFrame *v6; // ecx@3
+  unsigned int v7; // eax@3
+  int v8; // edx@3
+  unsigned int v9; // eax@3
+  int result; // eax@4
+  AIDirection a3; // [sp+Ch] [bp-5Ch]@2
+  AIDirection v12; // [sp+28h] [bp-40h]@2
+  AIDirection v13; // [sp+44h] [bp-24h]@2
+  unsigned int v14; // [sp+60h] [bp-8h]@1
+  unsigned int v15; // [sp+64h] [bp-4h]@1
+
+  v3 = uActorID;
+  v4 = a4;
+  v5 = &pActors[uActorID];
+  v14 = uObjID;
+  v15 = uActorID;
+  if ( !a4 )
+  {
+    memcpy(&v13, Actor::GetDirectionInfo(8 * uActorID | AI_OBJECT_ACTOR, uObjID, &a3, (int)a4), sizeof(v13));
+    memcpy(&v12, &v13, sizeof(v12));
+    v3 = v15;
+    v4 = &v12;
+  }
+  v6 = pSpriteFrameTable->pSpriteSFrames;
+  v5->uYawAngle = LOWORD(v4->uYawAngle);
+  v5->uCurrentActionLength = 8 * v6[v5->pSpriteIDs[7]].uAnimLength;
+  v7 = stru_5C6E00->Atan2(v5->vPosition.x - pIndoorCamera->pos.x, v5->vPosition.y - pIndoorCamera->pos.y);
+  LOWORD(v8) = v5->uYawAngle;
+  v9 = stru_5C6E00->uIntegerPi + v8 + ((signed int)stru_5C6E00->uIntegerPi >> 3) - v7;
+  if ( BYTE1(v9) & 7 )
+  {
+    result = Actor::_403EB6(v3, v14, v5->uCurrentActionLength, v4);
+  }
+  else
+  {
+    v5->uAIState = Fidgeting;
+    v5->uCurrentActionTime = 0;
+    v5->vVelocity.z = 0;
+    v5->vVelocity.y = 0;
+    v5->vVelocity.x = 0;
+    if ( rand() % 100 < 5 )
+      Actor::PlaySound(v3, 3u);
+    result = v5->UpdateAnimation();
+  }
+  return result;
+}
+
+//----- (00402F27) --------------------------------------------------------
+unsigned int __fastcall Actor::Resurrect(unsigned int uActorID)
+{
+  Actor *pActor; // esi@1
+  SpriteFrame *v2; // edx@1
+  int v3; // eax@1
+
+  pActor = &pActors[uActorID];
+  v2 = pSpriteFrameTable->pSpriteSFrames;
+  v3 = pActor->pSpriteIDs[5];
+  pActor->uCurrentActionTime = 0;
+  pActor->uAIState = Resurrected;
+  pActor->uCurrentActionAnimation = ANIM_Dying;
+  pActor->uCurrentActionLength = 8 * v2[v3].uAnimLength;
+  pActor->sCurrentHP = LOWORD(pActor->pMonsterInfo.uHP);
+  Actor::PlaySound(uActorID, 1u);
+  return pActor->UpdateAnimation();
+}
+
+
+//----- (00402D6E) --------------------------------------------------------
+void __fastcall Actor::Die(unsigned int uActorID)
+{
+  Actor *v1; // esi@1
+  SpriteFrame *v2; // ecx@1
+  int v3; // eax@1
+  int v4; // ecx@1
+  char *v5; // eax@1
+  SpellBuff *v6; // edi@5
+  signed int v7; // ebx@5
+  MONSTER_TYPE v8; // eax@7
+  int v9; // eax@23
+  ItemGen _this; // [sp+8h] [bp-28h]@7
+  unsigned int v11; // [sp+2Ch] [bp-4h]@1
+
+  v1 = &pActors[uActorID];
+  v11 = uActorID;
+  v2 = pSpriteFrameTable->pSpriteSFrames;
+  v3 = 60 * v1->pSpriteIDs[5];
+  v1->uCurrentActionTime = 0;
+  v1->uAIState = Dying;
+  v1->uCurrentActionAnimation = 5;
+  LOWORD(v3) = *(__int16 *)((char *)&v2->uAnimLength + v3);
+  v1->sCurrentHP = 0;
+  v1->uCurrentActionLength = 8 * v3;
+  v1->pActorBuffs[6].Reset();
+  v1->pActorBuffs[5].Reset();
+  Actor::PlaySound(v11, 1u);
+  v1->UpdateAnimation();
+  v4 = v1->pMonsterInfo.uID;
+  v5 = (char *)pParty->field_75A;
+  do
+  {
+    if ( v4 == *((short *)v5 - 5) )
+      *(short *)v5 = 1;
+    v5 += 2;
+  }
+  while ( (signed int)v5 < (signed int)&pParty->field_764 );
+  v6 = v1->pActorBuffs;
+  v7 = 22;
+  do
+  {
+    v6->Reset();
+    ++v6;
+    --v7;
+  }
+  while ( v7 );
+  _this.Reset();
+  v8 = (MONSTER_TYPE)v1->pMonsterInfo.uID;
+  if ( v8 > MONSTER_HARPY_3 )
+  {
+    if ( v8 < MONSTER_OOZE_1 )
+      goto LABEL_21;
+    if ( v8 <= MONSTER_OOZE_3 )
+    {
+      _this.uItemID = ITEM_OOZE_ECTOPLASM_BOTTLE;
+      goto LABEL_21;
+    }
+    if ( v8 <= MONSTER_PEASANT_GOBLIN_MALE_3_3 || v8 > MONSTER_TROLL_3 )
+    {
+LABEL_21:
+      if ( !_this.uItemID )
+        goto LABEL_24;
+      goto LABEL_22;
+    }
+    _this.uItemID = ITEM_TROLL_BLOOD;
+  }
+  else
+  {
+    if ( v8 >= MONSTER_HARPY_1 )
+    {
+      _this.uItemID = ITEM_HARPY_FEATHER;
+    }
+    else
+    {
+      if ( v8 < MONSTER_DEVIL_1 )
+        goto LABEL_21;
+      if ( v8 > MONSTER_DEVIL_3 )
+      {
+        if ( v8 <= MONSTER_DRAGON_3 )
+        {
+          _this.uItemID = ITEM_DRAGON_EYE;
+          goto LABEL_22;
+        }
+        goto LABEL_21;
+      }
+      _this.uItemID = ITEM_DEVIL_ICHOR;
+    }
+  }
+LABEL_22:
+  if ( rand() % 100 < 20 )
+  {
+    v9 = rand();
+    sub_42F7EB_DropItemAt(
+      pItemsTable->pItems[_this.uItemID].uSpriteID,
+      v1->vPosition.x,
+      v1->vPosition.y,
+      v1->vPosition.z + 16,
+      v9 % 200 + 200,
+      1,
+      1,
+      0,
+      &_this);
+  }
+LABEL_24:
+  if ( v1->pMonsterInfo.uSpecialAbilityType == MONSTER_SPECIAL_ABILITY_EXPLODE )
+    Actor::Explode(v11);
+}
+
+//----- (00402CED) --------------------------------------------------------
+void __fastcall Actor::PlaySound(unsigned int uActorID, unsigned int uSoundID)
+{
+  Actor *v2; // eax@1
+  unsigned __int16 v3; // dx@1
+  int v4; // eax@3
+  int v5; // eax@4
+  unsigned int v6; // eax@6
+  signed int v7; // eax@12
+  signed int v8; // [sp-18h] [bp-1Ch]@10
+  signed int v9; // [sp-14h] [bp-18h]@10
+  int v10; // [sp-10h] [bp-14h]@10
+  unsigned int v11; // [sp-Ch] [bp-10h]@10
+  int v12; // [sp-8h] [bp-Ch]@10
+
+  v2 = &pActors[uActorID];
+  v3 = v2->pSoundSampleIDs[uSoundID];
+  if ( v3 )
+  {
+    if ( (signed __int64)v2->pActorBuffs[3].uExpireTime <= 0 )
+    {
+      v12 = 0;
+      v11 = 0;
+      v10 = 0;
+      v9 = 0;
+      v8 = -1;
+    }
+    else
+    {
+      v4 = v2->pActorBuffs[3].uPower - 2;
+      if ( v4 )
+      {
+        v5 = v4 - 1;
+        if ( v5 )
+        {
+          if ( v5 == 1 )
+            v6 = 55125;
+          else
+            v6 = uActorID;
+        }
+        else
+        {
+          v6 = 44100;
+        }
+      }
+      else
+      {
+        v6 = 33075;
+      }
+      v12 = v6;
+      v11 = 0;
+      v10 = 0;
+      v9 = 0;
+      v8 = 0;
+    }
+    v7 = 8 * uActorID;
+    LOBYTE(v7) = 8 * uActorID | 3;
+    pAudioPlayer->PlaySound((SoundID)(signed __int16)v3, v7, 0, v8, v9, v10, v11, v12);
+  }
+}
+
+
+//----- (00402AD7) --------------------------------------------------------
+unsigned int __fastcall Actor::_402AD7(unsigned int uActorID, unsigned int a2, signed int arg0, signed int uActionLength, AIDirection *pDir)
+{
+  unsigned int v5; // edi@1
+  int v6; // eax@1
+  Actor *v7; // ebx@1
+  unsigned int v8; // ecx@1
+  char v9; // zf@1
+  AIDirection *v10; // esi@6
+  int v12; // ecx@19
+  unsigned int v13; // eax@19
+  AIDirection a3; // [sp+Ch] [bp-5Ch]@7
+  AIDirection v15; // [sp+28h] [bp-40h]@7
+  AIDirection v16; // [sp+44h] [bp-24h]@7
+  unsigned int v17; // [sp+60h] [bp-8h]@1
+  unsigned int v18; // [sp+64h] [bp-4h]@1
+  int v19; // [sp+70h] [bp+8h]@19
+
+  v5 = uActorID;
+  v6 = 0;
+  v7 = &pActors[uActorID];
+  v18 = a2;
+  v8 = 8 * uActorID | 3;
+  v9 = v7->pMonsterInfo.uFlying == 0;
+  v17 = v5;
+  if ( !v9 && !pParty->bFlying )
+  {
+    if ( v7->pMonsterInfo.uMissleAttack1Type )
+      v6 = v7->uActorRadius + 512;
+    else
+      v6 = pParty->uPartyHeight;
+  }
+  v10 = pDir;
+  if ( !pDir )
+  {
+    memcpy(&v15, Actor::GetDirectionInfo(v8, a2, &a3, v6), sizeof(v15));
+    memcpy(&v16, &v15, sizeof(v16));
+    v5 = v17;
+    v10 = &v16;
+  }
+  if ( MonsterStats::BelongsToSupertype(v7->pMonsterInfo.uID, MONSTER_SUPERTYPE_TREANT) )
+  {
+    if ( !uActionLength )
+      uActionLength = 256;
+    return Actor::_403F58(v5, 4, uActionLength, v10);
+  }
+  if ( (double)(signed int)v10->uDistance < 307.2 )
+  {
+    if ( !uActionLength )
+      uActionLength = 256;
+    return Actor::_403EB6(v5, v18, uActionLength, v10);
+  }
+  if ( !v7->uMovementSpeed )
+    return Actor::_403EB6(v5, v18, uActionLength, v10);
+  v18 = 16;
+  if ( arg0 % 2 )
+    v18 = -16;
+  v12 = ((unsigned __int64)(stru_5C6E00->SinCos(v18 + stru_5C6E00->uIntegerPi + v10->uYawAngle)
+                          * (signed __int64)v10->uDistanceXZ) >> 16)
+      + pParty->vPosition.x;
+  v13 = stru_5C6E00->uIntegerPi + v10->uYawAngle;
+  v17 = v12;
+  v19 = stru_5C6E00->SinCos(v18 + v13 - stru_5C6E00->uIntegerHalfPi);
+  v7->uYawAngle = stru_5C6E00->Atan2(
+                    v17 - v7->vPosition.x,
+                    pParty->vPosition.y
+                  + ((unsigned __int64)(v19 * (signed __int64)v10->uDistanceXZ) >> 16)
+                  - v7->vPosition.y);
+  if ( uActionLength )
+    v7->uCurrentActionLength = uActionLength;
+  else
+    v7->uCurrentActionLength = 128;
+  v7->uPitchAngle = LOWORD(v10->uPitchAngle);
+  v7->uAIState = Pursuing;
+  return v7->UpdateAnimation();
+}
+
+//----- (00402968) --------------------------------------------------------
+unsigned int __fastcall Actor::_402968(unsigned int uActorID, signed int edx0, int uActionLength, AIDirection *a4)
+{
+  unsigned int v4; // esi@1
+  Actor *v5; // ebx@1
+  unsigned int result; // eax@1
+  int v7; // ecx@2
+  signed __int16 v8; // cx@10
+  unsigned __int16 v9; // ax@15
+  AIDirection v10; // [sp+8h] [bp-7Ch]@4
+  AIDirection a3; // [sp+24h] [bp-60h]@3
+  AIDirection v12; // [sp+40h] [bp-44h]@3
+  AIDirection v13; // [sp+5Ch] [bp-28h]@4
+  signed int a1; // [sp+78h] [bp-Ch]@2
+  unsigned int v15; // [sp+7Ch] [bp-8h]@1
+  signed int a2; // [sp+80h] [bp-4h]@1
+
+  v4 = uActorID;
+  a2 = edx0;
+  v15 = uActorID;
+  v5 = &pActors[uActorID];
+  result = pActors[uActorID].CanAct();
+  if ( result )
+  {
+    v7 = 8 * v4 | 3;
+    a1 = 8 * v4 | 3;
+    if ( !a4 )
+    {
+      a4 = &v12;
+      memcpy(&v12, Actor::GetDirectionInfo(v7, a2, &a3, v5->pMonsterInfo.uFlying), sizeof(v12));
+      v7 = a1;
+    }
+    memcpy(&a3, Actor::GetDirectionInfo(v7, 4u, &v10, 0), sizeof(a3));
+    memcpy(&v13, &a3, sizeof(v13));
+    if ( MonsterStats::BelongsToSupertype(v5->pMonsterInfo.uID, MONSTER_SUPERTYPE_TREANT)
+      || (a2 & 7) == 3 && (double)(signed int)v13.uDistance < 307.2 )
+    {
+      if ( !uActionLength )
+        uActionLength = 256;
+      result = Actor::_403F58(v15, 4, uActionLength, &v13);
+    }
+    else
+    {
+      v8 = v5->uMovementSpeed;
+      if ( v8 )
+        v5->uCurrentActionLength = (signed int)(a4->uDistanceXZ << 7) / v8;
+      else
+        v5->uCurrentActionLength = 0;
+      if ( v5->uCurrentActionLength > 256 )
+        v5->uCurrentActionLength = 256;
+      v5->uYawAngle = LOWORD(stru_5C6E00->uIntegerHalfPi) + LOWORD(a4->uYawAngle);
+      v5->uYawAngle = LOWORD(stru_5C6E00->uDoublePiMask) & (v5->uYawAngle + rand() % (signed int)stru_5C6E00->uIntegerPi);
+      v9 = LOWORD(a4->uPitchAngle);
+      v5->uCurrentActionTime = 0;
+      v5->uPitchAngle = v9;
+      v5->uAIState = Fleeing;
+      result = v5->UpdateAnimation();
+    }
+  }
+  return result;
+}
+
+
+//----- (0040281C) --------------------------------------------------------
+int __fastcall Actor::_40281C(unsigned int uActorID, unsigned int a2, signed int uActionLength, AIDirection *pDir, int a5)
+{
+  unsigned int v5; // edi@1
+  int v6; // eax@1
+  Actor *v7; // ebx@1
+  unsigned int v8; // ecx@1
+  char v9; // zf@1
+  AIDirection *v10; // esi@7
+  signed int v11; // edx@12
+  signed __int16 v13; // cx@19
+  unsigned __int16 v14; // ax@25
+  int v15; // [sp-8h] [bp-54h]@12
+  AIDirection *v16; // [sp-4h] [bp-50h]@12
+  AIDirection a3; // [sp+Ch] [bp-40h]@8
+  AIDirection v18; // [sp+28h] [bp-24h]@8
+  unsigned int v19; // [sp+44h] [bp-8h]@1
+  unsigned int v20; // [sp+48h] [bp-4h]@1
+
+  v5 = uActorID;
+  v6 = 0;
+  v7 = &pActors[uActorID];
+  v19 = a2;
+  v8 = 8 * uActorID | 3;
+  v9 = v7->pMonsterInfo.uFlying == 0;
+  v20 = v5;
+  if ( !v9 && !pParty->bFlying )
+  {
+    if ( v7->pMonsterInfo.uMissleAttack1Type && uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+      v6 = v7->uActorRadius + 512;
+    else
+      v6 = pParty->uPartyHeight;
+  }
+  v10 = pDir;
+  if ( !pDir )
+  {
+    memcpy(&v18, Actor::GetDirectionInfo(v8, a2, &a3, v6), sizeof(v18));
+    memcpy(0, &v18, 0x1Cu);
+    v10 = 0;
+    v5 = v20;
+  }
+  if ( MonsterStats::BelongsToSupertype(v7->pMonsterInfo.uID, MONSTER_SUPERTYPE_TREANT) )
+  {
+    if ( !uActionLength )
+      uActionLength = 256;
+    v16 = v10;
+    v15 = uActionLength;
+    v11 = 4;
+    return Actor::_403F58(v5, v11, v15, v16);
+  }
+  if ( (signed int)v10->uDistance < a5 )
+  {
+    if ( !uActionLength )
+      uActionLength = 256;
+    v11 = v19;
+    v16 = v10;
+    v15 = uActionLength;
+    return Actor::_403F58(v5, v11, v15, v16);
+  }
+  if ( uActionLength )
+  {
+    v7->uCurrentActionLength = uActionLength;
+  }
+  else
+  {
+    v13 = v7->uMovementSpeed;
+    if ( v13 )
+      v7->uCurrentActionLength = (signed int)(v10->uDistanceXZ << 7) / v13;
+    else
+      v7->uCurrentActionLength = 0;
+    if ( v7->uCurrentActionLength > 32 )
+      v7->uCurrentActionLength = 32;
+  }
+  v7->uYawAngle = LOWORD(v10->uYawAngle);
+  v14 = LOWORD(v10->uPitchAngle);
+  v7->uCurrentActionTime = 0;
+  v7->uPitchAngle = v14;
+  v7->uAIState = Pursuing;
+  return v7->UpdateAnimation();
+}
+
+
+//----- (00402686) --------------------------------------------------------
+unsigned int __fastcall Actor::_402686(unsigned int uActorID, unsigned int a2, signed int uActionLength, AIDirection *a4)
+{
+  unsigned int v4; // edi@1
+  int v5; // eax@1
+  Actor *v6; // ebx@1
+  int v7; // ecx@1
+  char v8; // zf@1
+  AIDirection *v9; // esi@7
+  signed int v10; // edx@12
+  signed __int16 v12; // cx@19
+  int v13; // edx@25
+  __int16 v14; // ax@25
+  unsigned __int16 v15; // ax@26
+  unsigned __int16 v16; // ax@28
+  int v17; // [sp-8h] [bp-54h]@12
+  AIDirection *v18; // [sp-4h] [bp-50h]@12
+  AIDirection a3; // [sp+Ch] [bp-40h]@8
+  AIDirection v20; // [sp+28h] [bp-24h]@8
+  int v21; // [sp+44h] [bp-8h]@1
+  unsigned int v22; // [sp+48h] [bp-4h]@1
+
+  v4 = uActorID;
+  v5 = 0;
+  v6 = &pActors[uActorID];
+  v21 = a2;
+  v7 = 8 * uActorID | 3;
+  v8 = v6->pMonsterInfo.uFlying == 0;
+  v22 = v4;
+  if ( !v8 && !pParty->bFlying )
+  {
+    if ( v6->pMonsterInfo.uMissleAttack1Type && uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+      v5 = v6->uActorRadius + 512;
+    else
+      v5 = pParty->uPartyHeight;
+  }
+  v9 = a4;
+  if ( !a4 )
+  {
+    memcpy(&v20, Actor::GetDirectionInfo(v7, a2, &a3, v5), sizeof(v20));
+    memcpy(0, &v20, 0x1Cu);
+    v9 = 0;
+    v4 = v22;
+  }
+  if ( MonsterStats::BelongsToSupertype(v6->pMonsterInfo.uID, MONSTER_SUPERTYPE_TREANT) )
+  {
+    if ( !uActionLength )
+      uActionLength = 256;
+    v18 = v9;
+    v17 = uActionLength;
+    v10 = 4;
+    return Actor::_403F58(v4, v10, v17, v18);
+  }
+  if ( (double)(signed int)v9->uDistance < 307.2 )
+  {
+    if ( !uActionLength )
+      uActionLength = 256;
+    v10 = v21;
+    v18 = v9;
+    v17 = uActionLength;
+    return Actor::_403F58(v4, v10, v17, v18);
+  }
+  if ( uActionLength )
+  {
+    v6->uCurrentActionLength = uActionLength + rand() % uActionLength;
+  }
+  else
+  {
+    v12 = v6->uMovementSpeed;
+    if ( v12 )
+      v6->uCurrentActionLength = (signed int)(v9->uDistanceXZ << 7) / v12;
+    else
+      v6->uCurrentActionLength = 0;
+    if ( v6->uCurrentActionLength > 128 )
+      v6->uCurrentActionLength = 128;
+  }
+  v13 = rand() % 2;
+  v14 = LOWORD(v9->uYawAngle);
+  if ( v13 )
+    v15 = v14 + 256;
+  else
+    v15 = v14 - 256;
+  v6->uYawAngle = v15;
+  v16 = LOWORD(v9->uPitchAngle);
+  v6->uCurrentActionTime = 0;
+  v6->uPitchAngle = v16;
+  v6->uAIState = Pursuing;
+  if ( rand() % 100 < 2 )
+    Actor::PlaySound(v4, 2u);
+  return v6->UpdateAnimation();
+}
+
+//----- (00401221) --------------------------------------------------------
+void __fastcall Actor::_401221(unsigned int uActorID, int *a2, unsigned int a3)
+{
+  Actor *v3; // esi@1
+  unsigned int v4; // ebx@1
+  int v5; // ecx@1
+  unsigned int v6; // eax@1
+  char *v7; // edi@2
+  __int16 v8; // ax@3
+  int v9; // eax@10
+  signed int v10; // eax@13
+  int v11; // ebx@16
+  int v12; // eax@16
+  int v13; // eax@25
+  signed int v14; // eax@31
+  int v15; // edi@43
+  int v16; // ebx@45
+  int v17; // eax@45
+  int v18; // eax@51
+  int v19; // [sp+Ch] [bp-24h]@16
+  int *v20; // [sp+10h] [bp-20h]@1
+  signed int v21; // [sp+14h] [bp-1Ch]@1
+  unsigned int v22; // [sp+18h] [bp-18h]@1
+  int v23; // [sp+1Ch] [bp-14h]@16
+  unsigned int v24; // [sp+20h] [bp-10h]@1
+  int v25; // [sp+24h] [bp-Ch]@1
+  signed int v26; // [sp+28h] [bp-8h]@1
+  int v27; // [sp+2Ch] [bp-4h]@16
+  int v28; // [sp+2Ch] [bp-4h]@45
+
+  v25 = -1;
+  v22 = uActorID;
+  v3 = &pActors[uActorID];
+  v4 = 0;
+  v5 = 0;
+  v6 = v3->uLastCharacterIDToHit;
+  *a2 = 0;
+  v20 = a2;
+  v21 = 0;
+  v24 = v6;
+  v26 = 0;
+  if ( (signed int)uNumActors <= 0 )
+    goto LABEL_26;
+  v7 = (char *)&pActors[0].uAIState;
+  do
+  {
+    v8 = *(short *)v7;
+    if ( *(short *)v7 == 5 || v8 == 4 || v8 == 11 || v8 == 17 || v8 == 19 || v22 == v5 )
+      goto LABEL_23;
+    if ( v24 == v4 || (v9 = 8 * v5, LOBYTE(v9) = 8 * v5 | 3, v24 != v9) )
+      goto LABEL_13;
+    if ( ((Actor *)(v7 - 176))->IsAlive() == 1 )
+    {
+      v24 = v4;
+      v3->uLastCharacterIDToHit = v4;
+LABEL_13:
+      v10 = v3->GetActorsRelation((Actor *)(v7 - 176));
+      if ( v10 == v4 )
+        goto LABEL_23;
+      goto LABEL_14;
+    }
+    v18 = *((unsigned int *)v7 + 133);
+    if ( (v18 != v4 || v3->uGroup != v4) && v18 == v3->uGroup )
+      goto LABEL_23;
+    v10 = 4;
+LABEL_14:
+    if ( v3->pMonsterInfo.uHostilityType )
+      v10 = pMonsterStats->pInfos[v3->pMonsterInfo.uID].uHostilityType;
+    v11 = dword_4DF380[v10];
+    v23 = abs(v3->vPosition.x - *((short *)v7 - 17));
+    v27 = abs(v3->vPosition.y - *((short *)v7 - 16));
+    v12 = abs(v3->vPosition.z - *((short *)v7 - 15));
+    v19 = v12;
+    if ( v23 <= v11
+      && v27 <= v11
+      && v12 <= v11
+      && sub_4070EF_prolly_collide_objects(8 * v26 | 3, 8 * v22 | 3)
+      && v23 * v23 + v27 * v27 + v19 * v19 < (unsigned int)v25 )
+    {
+      v25 = v23 * v23 + v27 * v27 + v19 * v19;
+      v21 = v26;
+    }
+    v4 = 0;
+LABEL_23:
+    v7 += 836;
+    v5 = v26++ + 1;
+  }
+  while ( v26 < (signed int)uNumActors );
+  if ( v25 != -1 )
+  {
+    v13 = 8 * v21;
+    LOBYTE(v13) = 8 * v21 | 3;
+    *v20 = v13;
+  }
+LABEL_26:
+  if ( SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) >= (signed int)v4
+    && (SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) > (signed int)v4 || LODWORD(pParty->pPartyBuffs[11].uExpireTime) > v4) )
+    a3 = v4;
+  if ( a3 != v4 )
+  {
+    v14 = v3->GetActorsRelation(0);
+    if ( BYTE2(v3->uAttributes) & 8
+      && SHIDWORD(v3->pActorBuffs[12].uExpireTime) <= (signed int)v4
+      && (SHIDWORD(v3->pActorBuffs[12].uExpireTime) < (signed int)v4 || LODWORD(v3->pActorBuffs[12].uExpireTime) <= v4)
+      && SHIDWORD(v3->pActorBuffs[1].uExpireTime) <= (signed int)v4
+      && (SHIDWORD(v3->pActorBuffs[1].uExpireTime) < (signed int)v4 || LODWORD(v3->pActorBuffs[1].uExpireTime) <= v4)
+      && SHIDWORD(v3->pActorBuffs[2].uExpireTime) <= (signed int)v4
+      && (SHIDWORD(v3->pActorBuffs[2].uExpireTime) < (signed int)v4 || LODWORD(v3->pActorBuffs[2].uExpireTime) <= v4) )
+      v14 = 4;
+    if ( v14 != v4 )
+    {
+      v15 = dword_4DF390;
+      if ( !v3->pMonsterInfo.uHostilityType )
+        v15 = dword_4DF380[v14];
+      v16 = abs(v3->vPosition.x - pParty->vPosition.x);
+      v28 = abs(v3->vPosition.y - pParty->vPosition.y);
+      v17 = abs(v3->vPosition.z - pParty->vPosition.z);
+      if ( v16 <= v15 && v28 <= v15 && v17 <= v15 )
+      {
+        if ( v16 * v16 + v28 * v28 + v17 * v17 < (unsigned int)v25 )
+          *v20 = 4;
+      }
+    }
+  }
+}
+// 4DF380: using guessed type int dword_4DF380[];
+// 4DF390: using guessed type int dword_4DF390;
+
+//----- (0040104C) --------------------------------------------------------
+signed int Actor::GetActorsRelation(Actor *a2)
+{
+  Actor *v2; // esi@1
+  int v3; // ebp@5
+  int v4; // edi@11
+  unsigned int v5; // edx@15
+  unsigned int v6; // eax@16
+  unsigned int v7; // ebp@19
+  int v8; // eax@22
+  unsigned int v9; // edx@25
+  unsigned int v10; // edx@33
+
+  auto a1 = this;
+  v2 = a2;
+  if ( a1 )
+  {
+    if ( SHIDWORD(a1->pActorBuffs[9].uExpireTime) >= 0
+      && (SHIDWORD(a1->pActorBuffs[9].uExpireTime) > 0 || LODWORD(a1->pActorBuffs[9].uExpireTime) > 0) )
+      return 4;
+    v3 = a1->pMonsterInfo.uID;
+  }
+  else
+  {
+    v3 = 0;
+  }
+  if ( a2 )
+  {
+    if ( SHIDWORD(a2->pActorBuffs[9].uExpireTime) >= 0
+      && (SHIDWORD(a2->pActorBuffs[9].uExpireTime) > 0 || LODWORD(a2->pActorBuffs[9].uExpireTime) > 0) )
+      return 4;
+    v4 = a2->pMonsterInfo.uID;
+  }
+  else
+  {
+    v4 = 0;
+  }
+  if ( a2 )
+  {
+    if ( a1 )
+    {
+      v5 = a2->uGroup;
+      if ( v5 )
+      {
+        v6 = a1->uGroup;
+        if ( v6 )
+        {
+          if ( v5 == v6 )
+            return 0;
+        }
+      }
+    }
+  }
+  if ( v3 )
+    v7 = (v3 - 1) / 3 + 1;
+  else
+    v7 = 0;
+  if ( v4 )
+    v8 = (v4 - 1) / 3 + 1;
+  else
+    v8 = 0;
+  if ( a1 )
+  {
+    v9 = a1->uAlly;
+    if ( (signed int)v9 <= 0 )
+    {
+      if ( v9 != 9999 )
+        goto LABEL_30;
+    }
+    else
+    {
+      if ( v9 != 9999 )
+      {
+        v7 = a1->uAlly;
+        goto LABEL_30;
+      }
+    }
+    v7 = 0;
+LABEL_30:
+    if ( (signed __int64)a1->pActorBuffs[12].uExpireTime > 0 )
+      v7 = 0;
+  }
+  if ( !v2 )
+    goto LABEL_40;
+  v10 = v2->uAlly;
+  if ( (signed int)v10 <= 0 )
+  {
+    if ( v10 != 9999 )
+      goto LABEL_38;
+  }
+  else
+  {
+    if ( v10 != 9999 )
+    {
+      v8 = v2->uAlly;
+      goto LABEL_38;
+    }
+  }
+  v8 = 0;
+LABEL_38:
+  if ( (signed __int64)v2->pActorBuffs[12].uExpireTime > 0 )
+    v8 = 0;
+LABEL_40:
+  if ( a1 && (signed __int64)a1->pActorBuffs[1].uExpireTime > 0 && !v8
+    || v2 && (signed __int64)v2->pActorBuffs[1].uExpireTime > 0 && !v7 )
+    return 0;
+  if ( a1 && (signed __int64)a1->pActorBuffs[12].uExpireTime <= 0 && a1->uAttributes & 0x80000 && !v8 )
+    return 4;
+  if ( v2 && a1 && (signed __int64)a1->pActorBuffs[12].uExpireTime <= 0 && v2->uAttributes & 0x80000 )
+  {
+    if ( v7 )
+      goto LABEL_55;
+    return 4;
+  }
+  if ( !v7 )
+  {
+    if ( (!v2 || (signed __int64)v2->pActorBuffs[12].uExpireTime > 0 || !(v2->uAttributes & 0x80000))
+      && !*((unsigned char *)&pFactionTable->relations + 89 * v8) )
+    {
+LABEL_56:
+      if ( v8 < 89 )
+        return *((unsigned char *)&pFactionTable->relations + 89 * v7 + v8);
+      return 0;
+    }
+    return 4;
+  }
+LABEL_55:
+  if ( (signed int)v7 < 89 )
+    goto LABEL_56;
+  return 0;
+}
+
+
+//----- (0045976D) --------------------------------------------------------
+unsigned int Actor::UpdateAnimation()
+{
+  AIState state; // edx@1
+  unsigned int result; // eax@1
+
+  state = (AIState)this->uAIState;
+  BYTE2(this->uAttributes) &= 0xDFu;
+  result = this->uAttributes;
+  switch ( state )
+  {
+    case Tethered:
+      this->uCurrentActionAnimation = ANIM_Walking;
+      return result;
+    case AttackingMelee:
+      this->uCurrentActionAnimation = ANIM_AtkMelee;
+      goto LABEL_10;
+    case AttackingRanged1:
+    case AttackingRanged2:
+    case AttackingRanged3:
+    case AttackingRanged4:
+      this->uCurrentActionAnimation = ANIM_AtkRanged;
+      goto LABEL_10;
+    case Dying:
+    case Resurrected:
+      this->uCurrentActionAnimation = ANIM_Dying;
+      goto LABEL_10;
+    case Pursuing:
+    case Fleeing:
+      this->uCurrentActionAnimation = ANIM_Walking;
+      goto LABEL_10;
+    case Stunned:
+      this->uCurrentActionAnimation = ANIM_GotHit;
+      goto LABEL_10;
+    case Fidgeting:
+      this->uCurrentActionAnimation = ANIM_Bored;
+      goto LABEL_10;
+    case Standing:
+    case Interacting:
+    case Summoned:
+      this->uCurrentActionAnimation = ANIM_Standing;
+LABEL_10:
+      result |= 0x200000u;
+      this->uAttributes = result;
+      break;
+    case Dead:
+      result = 60 * this->pSpriteIDs[6];
+      if ( *(__int16 *)((char *)pSpriteFrameTable->pSpriteSFrames->pHwSpriteIDs + result) <= 0 )
+        this->uAIState = Removed;
+      else
+        this->uCurrentActionAnimation = ANIM_Dead;
+      break;
+    default:
+      return result;
+  }
+  return result;
+}
+
+//----- (00459671) --------------------------------------------------------
+void Actor::Reset()
+{
+  this->pActorName[0] = 0;
+  this->word_000086_some_monster_id = 0;
+  this->uNPC_ID = 0;
+  this->vPosition.z = 0;
+  this->vPosition.y = 0;
+  this->vPosition.x = 0;
+  this->vVelocity.z = 0;
+  this->vVelocity.y = 0;
+  this->vVelocity.x = 0;
+  this->uYawAngle = 0;
+  this->uPitchAngle = 0;
+  this->uAttributes = 0;
+  this->uSectorID = 0;
+  this->uCurrentActionTime = 0;
+  this->vInitialPosition.z = 0;
+  this->vInitialPosition.y = 0;
+  this->vInitialPosition.x = 0;
+  this->vGuardingPosition.z = 0;
+  this->vGuardingPosition.y = 0;
+  this->vGuardingPosition.x = 0;
+  this->uTetherDistance = 256;
+  this->uActorRadius = 32;
+  this->uActorHeight = 128;
+  this->uAIState = Standing;
+  this->uCurrentActionAnimation = 0;
+  this->uMovementSpeed = 200;
+  this->uCarriedItemID = 0;
+  this->uGroup = 0;
+  this->uAlly = 0;
+  this->uSummonerID = 0;
+  this->uLastCharacterIDToHit = 0;
+  this->dword_000334_unique_name = 0;
+  memset(this->pSpriteIDs, 0, sizeof(pSpriteIDs));
+  memset(this->pActorBuffs, 0, 0x160u);
+}
+
+//----- (0045959A) --------------------------------------------------------
+void Actor::PrepareSprites(char load_sounds_if_bit1_set)
+{
+  //Actor *v2; // edi@1
+  MonsterDesc *v3; // esi@1
+  //__int16 v4; // ax@2
+  unsigned __int16 *v5; // ecx@4
+  unsigned __int16 *v6; // eax@4
+  signed int v7; // edx@4
+  //char pSpriteName[120]; // [sp+Ch] [bp-88h]@2
+  MonsterInfo *v9; // [sp+84h] [bp-10h]@1
+  //int v10; // [sp+88h] [bp-Ch]@1
+  //char *Source; // [sp+8Ch] [bp-8h]@1
+  //unsigned __int16 *v12; // [sp+90h] [bp-4h]@1
+
+  //v2 = this;
+  //v10 = 8;
+  v3 = &pMonsterList->pMonsters[pMonsterInfo.uID - 1];
+  v9 = &pMonsterStats->pInfos[pMonsterInfo.uID - 1 + 1];
+  //v12 = pSpriteIDs;
+  //Source = (char *)v3->pSpriteNames;
+  //do
+  for (uint i = 0; i < 8; ++i)
+  {
+    //strcpy(pSpriteName, v3->pSpriteNames[i]);
+    pSpriteIDs[i] = pSpriteFrameTable->FastFindSprite(v3->pSpriteNames[i]);
+    //*v12 = v4;
+    pSpriteFrameTable->InitializeSprite(pSpriteIDs[i]);
+    //++v12;
+    //Source += 10;
+    //--v10;
+  }
+  //while ( v10 );
+  uActorHeight = v3->uMonsterHeight;
+  uActorRadius = v3->uMonsterRadius;
+  uMovementSpeed = LOWORD(v9->uBaseSpeed);
+  if ( !(load_sounds_if_bit1_set & 1) )
+  {
+    v5 = pSoundSampleIDs;
+    v6 = v3->pSoundSampleIDs;
+    v7 = 4;
+    do
+    {
+      *v5 = *v6;
+      ++v6;
+      ++v5;
+      --v7;
+    }
+    while ( v7 );
+  }
+}
+
+
+//----- (00459667) --------------------------------------------------------
+void Actor::Remove()
+{
+  this->uAIState = Removed;
+}
+
+
+//----- (0044FD29) --------------------------------------------------------
+int Actor::_44FD29(int a2)
+{
+  Actor *v2; // edi@1
+  unsigned __int8 v3; // al@1
+  int v4; // esi@1
+  int v5; // edx@2
+  int v6; // eax@8
+  int v7; // edi@10
+  Actor *v8; // esi@10
+  MonsterInfo *v9; // ebx@10
+  MonsterDesc *v10; // edi@10
+  unsigned __int16 v11; // ax@10
+  int v12; // eax@10
+  int v13; // ebx@10
+  int v14; // eax@10
+  int v15; // edi@10
+  int v16; // eax@10
+  int v17; // ebx@10
+  Actor *v18; // ecx@10
+  signed __int64 v19; // qax@10
+  unsigned int v20; // eax@12
+  int v21; // eax@13
+  int result; // eax@13
+  Actor *v23; // eax@16
+  int v24; // [sp+Ch] [bp-1Ch]@1
+  unsigned int uFaceID; // [sp+10h] [bp-18h]@8
+  int v26; // [sp+14h] [bp-14h]@10
+  int v27; // [sp+18h] [bp-10h]@10
+  int v28; // [sp+1Ch] [bp-Ch]@8
+  int v29; // [sp+20h] [bp-8h]@10
+  Actor *v30; // [sp+24h] [bp-4h]@1
+
+  v2 = this;
+  v24 = a2;
+  v30 = this;
+  v3 = this->pMonsterInfo.uSpecialAbilityDamageDiceRolls;
+  v4 = this->pMonsterInfo.field_3C_some_special_attack;
+  if ( v3 )
+  {
+    if ( v3 >= 1u && v3 <= 3u )
+      v4 = v4 + v3 - 1;
+  }
+  else
+  {
+    v5 = rand() % 100;
+    if ( v5 >= 60 )
+    {
+      ++v4;
+      if ( v5 >= 90 )
+        ++v4;
+    }
+  }
+  v6 = v2->vPosition.z;
+  v28 = 0;
+  uFaceID = v6;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    v28 = pIndoor->GetSector(v2->vPosition.x, v2->vPosition.y, v6);
+  v7 = v4 - 1;
+  v8 = &pActors[uNumActors];
+  v27 = (((uCurrentlyLoadedLevelType != LEVEL_Outdoor) - 1) & 0x40) + 64;
+  v29 = v7;
+  v9 = &pMonsterStats->pInfos[v7 + 1];
+  pActors[uNumActors].Reset();
+  v10 = &pMonsterList->pMonsters[v7];
+  strcpy(v8->pActorName, v9->pName);
+  v8->sCurrentHP = LOWORD(v9->uHP);
+  memcpy(&v8->pMonsterInfo, v9, 0x58u);
+  v8->word_000086_some_monster_id = v29 + 1;
+  v8->uActorRadius = v10->uMonsterRadius;
+  v8->uActorHeight = v10->uMonsterHeight;
+  v11 = v10->uMovementSpeed;
+  v8->pMonsterInfo.uTreasureDiceRolls = 0;
+  v8->pMonsterInfo.uTreasureType = 0;
+  v8->pMonsterInfo.uExp = 0;
+  v8->uMovementSpeed = v11;
+  v12 = rand();
+  v13 = v12 % 2048;
+  v14 = stru_5C6E00->SinCos(v12 % 2048);
+  v26 = v14;
+  v15 = ((unsigned __int64)(v14 * (signed __int64)v27) >> 16) + v30->vPosition.x;
+  v16 = stru_5C6E00->SinCos(v13 - stru_5C6E00->uIntegerHalfPi);
+  v26 = v16;
+  v29 = (unsigned __int64)(v16 * (signed __int64)v27) >> 16;
+  LOWORD(v16) = uFaceID;
+  v17 = v29 + v30->vPosition.y;
+  v8->vInitialPosition.z = uFaceID;
+  v8->vPosition.z = v16;
+  LOWORD(v16) = v28;
+  v8->vInitialPosition.x = v15;
+  v8->vPosition.x = v15;
+  v8->vInitialPosition.y = v17;
+  v8->vPosition.y = v17;
+  v8->uTetherDistance = 256;
+  v8->uSectorID = v16;
+  v8->PrepareSprites(0);
+  v18 = v30;
+  v8->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+  LODWORD(v19) = v18->uAlly;
+  if ( !(uint)v19 )
+  {
+    uFaceID = v18->pMonsterInfo.uID - 1;
+    v19 = (signed __int64)((double)uFaceID * 0.33333334);
+    v18 = v30;
+  }
+  v8->uAlly = v19;
+  v20 = v18->uGroup;
+  v8->uCurrentActionTime = 0;
+  v8->uGroup = v20;
+  v8->uAIState = Summoned;
+  v8->uCurrentActionLength = 256;
+  v8->UpdateAnimation();
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor
+    || (v21 = v30->vPosition.z,
+        v27 = v30->vPosition.z,
+        result = pIndoor->GetSector(v15, v17, v21),
+        result == v28)
+    && (result = _46CEC3_get_floor_level(v15, v17, v27, result, &uFaceID), result != -30000)
+    && (result = abs(result - v27), result <= 1024) )
+  {
+    v23 = v30;
+    ++uNumActors;
+    ++v23->pMonsterInfo.uSpecialAbilityDamageDiceBonus;
+    if ( v23->uAttributes & 0x80000 )
+      v8->uAttributes |= 0x80000u;
+    result = 8 * v24;
+    LOBYTE(result) = 8 * v24 | 3;
+    v8->uSummonerID = result;
+  }
+  return result;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Actor.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,288 @@
+#pragma once
+#include "VectorTypes.h"
+#include "Items.h"
+#include "Monsters.h"
+#include "Spells.h"
+
+
+
+
+
+
+/*  357 */
+#pragma pack(push, 1)
+struct stru319
+{
+  void LootActor(struct Actor *pActor);
+  int which_player_would_attack(struct Actor *pActor);
+  bool special_ability_use_check(struct Actor *pActor, int a2);
+  int _427102(struct Actor *pActor, signed int a2);
+  int PlayerHitOrMiss(struct Player *pPlayer, struct Actor *pActor, int a3, int a4);
+  bool _4273BB(struct Actor *pActor, struct Actor *a2, int a3, int a4);
+  bool ActorHitOrMiss(struct Actor *pActor, struct Player *pPlayer);
+  int _427546(int a2);
+  int CalcMagicalDamageToActor(struct Actor *pActor, int a2, signed int a3);
+  bool GetMagicalResistance(struct Actor *pActor, unsigned int uType);
+  int FindClosesActor(int a2, int a3, int a4);
+
+  char field_0;
+};
+#pragma pack(pop)
+
+
+extern stru319 stru_50C198; // idb
+
+
+
+
+
+
+/*  361 */
+enum ACTOR_BUFF_INDEX
+{
+  ACTOR_BUFF_STONED = 0x5,
+  ACTOR_BUFF_PARALYZED = 0x6,
+};
+
+
+
+
+
+/*  295 */
+enum ObjectType
+{
+  OBJECT_unk0 = 0x0,
+  OBJECT_unk1 = 0x1,
+  OBJECT_Item = 0x2,
+  OBJECT_Actor = 0x3,
+  OBJECT_Player = 0x4,
+  OBJECT_Decoration = 0x5,
+  OBJECT_BModel = 0x6,
+};
+
+
+
+
+
+
+
+/*  337 */
+enum AI_OBJECT_TYPE
+{
+  AI_OBJECT_LAYING_ITEM = 0x2,
+  AI_OBJECT_ACTOR = 0x3,
+  AI_OBJECT_PARTY = 0x4,
+  AI_OBJECT_DECORATION = 0x5,
+};
+
+/*  264 */
+enum AIState : unsigned __int16
+{
+  Standing = 0x0,
+  Tethered = 0x1,
+  AttackingMelee = 0x2,
+  AttackingRanged1 = 0x3,
+  Dying = 0x4,
+  Dead = 0x5,
+  Pursuing = 0x6,
+  Fleeing = 0x7,
+  Stunned = 0x8,
+  Fidgeting = 0x9,
+  Interacting = 0xA,
+  Removed = 0xB,
+  AttackingRanged2 = 0xC,
+  AttackingRanged3 = 0xD,
+  Stoned = 0xE,
+  Paralyzed = 0xF,
+  Resurrected = 0x10,
+  Summoned = 0x11,
+  AttackingRanged4 = 0x12,
+  Disabled = 0x13,
+};
+
+/*  265 */
+enum ActorAnimation : __int32
+{
+  ANIM_Standing = 0x0,
+  ANIM_Walking = 0x1,
+  ANIM_AtkMelee = 0x2,
+  ANIM_AtkRanged = 0x3,
+  ANIM_GotHit = 0x4,
+  ANIM_Dying = 0x5,
+  ANIM_Dead = 0x6,
+  ANIM_Bored = 0x7,
+};
+
+
+
+
+
+/*  247 */
+#pragma pack(push, 1)
+struct AIDirection
+{
+  Vec3_int_ vDirection;
+  unsigned int uDistance;
+  unsigned int uDistanceXZ;
+  unsigned int uYawAngle;
+  unsigned int uPitchAngle;
+};
+#pragma pack(pop)
+
+
+
+
+
+/*   71 */
+#pragma pack(push, 1)
+struct ActorJob
+{
+  struct Vec3_short_ vPos;
+  unsigned __int16 uAttributes;
+  unsigned __int8 uAction;
+  unsigned __int8 uHour;
+  unsigned __int8 uDay;
+  unsigned __int8 uMonth;
+};
+#pragma pack(pop)
+
+
+/*   66 */
+#pragma pack(push, 1)
+struct Actor
+{
+  //----- (0041F4C1) --------------------------------------------------------
+  inline Actor()
+  {
+    Actor *v1; // esi@1
+    SpellBuff *v2; // eax@1
+    signed int v3; // edx@1
+    ItemGen *v4; // edi@3
+    signed int v5; // ebx@3
+
+  v1 = this;
+  v2 = this->pActorBuffs;
+  v3 = 22;
+  do
+  {
+    v2->uSkill = 0;
+    v2->uPower = 0;
+    v2->uExpireTime = 0;
+    v2->uCaster = 0;
+    v2->uFlags = 0;
+    ++v2;
+    --v3;
+  }
+  while ( v3 );
+  v4 = this->array_000234;
+  v5 = 4;
+  do
+  {
+    v4->Reset();
+    ++v4;
+    --v5;
+  }
+  while ( v5 );
+  Reset();
+}
+
+  int _44FD29(int a2);
+  void Reset();
+  void Remove();
+  void PrepareSprites(char load_sounds_if_bit1_set);
+  unsigned int UpdateAnimation();
+  signed int GetActorsRelation(Actor *a2);
+  void SetRandomGoldIfTheresNoItem();
+  bool CanAct();
+  bool IsAlive();
+  void InitializeDialogue(int bPlayerSaysHello);
+  char _438B9B();
+
+  
+  static void __fastcall _401221(unsigned int uActorID, int *a2, unsigned int a3);
+  static unsigned int __fastcall _402686(unsigned int uActorID, unsigned int a2, signed int uActionLength, struct AIDirection *a4);
+  static int __fastcall _40281C(unsigned int uActorID, unsigned int a2, signed int uActionLength, struct AIDirection *pDir, int a5);
+  static unsigned int __fastcall _402968(unsigned int uActorID, signed int edx0, int uActionLength, struct AIDirection *a4);
+  static unsigned int __fastcall _402AD7(unsigned int uActorID, unsigned int a2, signed int arg0, signed int uActionLength, struct AIDirection *pDir);
+  static void __fastcall PlaySound(unsigned int uActorID, unsigned int uSoundID);
+  static void __fastcall Die(unsigned int uActorID);
+  static unsigned int __fastcall Resurrect(unsigned int uActorID);
+  static int __fastcall _402F87(unsigned int uActorID, unsigned int uObjID, struct AIDirection *a4);
+  static __int16 __fastcall _4030AD(unsigned int uActorID, signed int edx0, int arg0);
+  static char __fastcall _4031C1_update_job(unsigned int uActorID, signed int a2, int a3);
+  static void __fastcall _4032B2(unsigned int a1, unsigned int a2, int a3, int uActionLength);
+  static unsigned int __fastcall _403476(unsigned int uActorID, signed int edx0, struct AIDirection *pDir);
+  static unsigned int __fastcall _40368B(unsigned int uActorID, signed int edx0, struct AIDirection *pDir);
+  static unsigned int __fastcall _403854(unsigned int uActorID, signed int edx0, struct AIDirection *pDir);
+  static unsigned int __fastcall _403A60(unsigned int uActorID, signed int edx0, struct AIDirection *pDir);
+  static unsigned int __fastcall _403C6C(unsigned int uActorID, signed int edx0, struct AIDirection *arg0);
+  static void __fastcall StandAwhile(unsigned int uActorID);
+  static unsigned int __fastcall _403EB6(unsigned int uActorID, unsigned int a2, unsigned int uActionLength, struct AIDirection *a4);
+  static unsigned int __fastcall _403F58(unsigned int uActorID, signed int uObjID, int uActionLength, struct AIDirection *a4);
+  static unsigned int __fastcall FaceObject(unsigned int uActorID, unsigned int uObjID, int _48, struct AIDirection *a4);
+  static struct AIDirection *__fastcall GetDirectionInfo(unsigned int uObj1ID, unsigned int uObj2ID, struct AIDirection *pOut, int a4);
+  static signed int __fastcall Explode(unsigned int uActorID);
+  static char __fastcall _404874(unsigned int uActorID, struct AIDirection *a2, int a3, char a4);
+  static void __fastcall _404AC7(unsigned int uActorID, struct AIDirection *pDir, int spellnum, int a4, unsigned int uSkillLevel);
+  static void _43AC45(unsigned int uActorID, int a2);
+  static bool _43ABB0(Actor *a1, Actor *a2);
+  static bool StealFrom(unsigned int uActorID);
+  static void GiveItem(unsigned int uActorID, unsigned int uItemID, unsigned int bGive);
+  static void ToggleFlag(signed int uActorID, unsigned int uFlag, int bToggle);
+  static void _438CF3(unsigned int uActorID);
+  static void DrawHealthBar(Actor *a1, struct GUIWindow *a2);
+  static int _43B3E0_CalcDamage(Actor *a1, signed int a2);
+  static int AddBloodsplatOnDamageOverlay(unsigned int uActorID, int a2, signed int a3);
+
+
+  char pActorName[32];
+  unsigned __int16 uNPC_ID;
+  __int16 field_22;
+  unsigned int uAttributes;
+  __int16 sCurrentHP;
+  char field_2A[2];
+  struct MonsterInfo pMonsterInfo;
+  __int16 word_000084_range_attack;
+  __int16 word_000086_some_monster_id;
+  unsigned __int16 uActorRadius;
+  unsigned __int16 uActorHeight;
+  unsigned __int16 uMovementSpeed;
+  struct Vec3_short_ vPosition;
+  struct Vec3_short_ vVelocity;
+  unsigned __int16 uYawAngle;
+  unsigned __int16 uPitchAngle;
+  __int16 uSectorID;
+  unsigned __int16 uCurrentActionLength;
+  struct Vec3_short_ vInitialPosition;
+  struct Vec3_short_ vGuardingPosition;
+  unsigned __int16 uTetherDistance;
+  AIState uAIState;
+  unsigned __int16 uCurrentActionAnimation;
+  unsigned __int16 uCarriedItemID;
+  char field_B6;
+  char field_B7;
+  unsigned int uCurrentActionTime;
+  unsigned __int16 pSpriteIDs[8];
+  unsigned __int16 pSoundSampleIDs[4];
+  struct SpellBuff pActorBuffs[22];
+  struct ItemGen array_000234[4];
+  unsigned int uGroup;
+  unsigned int uAlly;
+  struct ActorJob pScheduledJobs[8];
+  unsigned int uSummonerID;
+  unsigned int uLastCharacterIDToHit;
+  int dword_000334_unique_name;
+  char field_338[12];
+};
+#pragma pack(pop)
+
+
+
+
+
+
+//extern Actor pMonsterInfoUI_Doll;
+
+
+extern Actor pActors[500];
+extern size_t uNumActors;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Allocator.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,317 @@
+#include <string.h>
+#include <stdio.h>
+#include "OSAPI.h"
+
+#include "Allocator.h"
+
+#include "mm7_data.h"
+
+
+
+Allocator *pAllocator; // idb
+
+
+
+
+
+void __fastcall CheckMemoryAccessibility(void *pBase, DWORD uSize);
+
+
+
+//----- (00426755) --------------------------------------------------------
+void *Allocator::AllocNamedChunk(const void *pPrevPtrValue, unsigned int uSize, const char *pName)
+{
+  //Allocator *v4; // esi@1
+  unsigned int v5; // eax@7
+  void *result; // eax@8
+  unsigned int *pNumBuffersUsed; // ebx@12
+  unsigned int v8; // edi@15
+  char v9; // zf@15
+  int v10; // eax@16
+  void **v11; // ebx@19
+  void *v12; // eax@22
+  unsigned int Size; // [sp+14h] [bp+Ch]@16
+
+  //v4 = this;
+  if ( pPrevPtrValue && !aborting_app )
+    AbortWithError();
+  if ( !bBigBufferAllocated && !aborting_app )
+    AbortWithError();
+  v5 = uSize;
+  if ( uSize )
+  {
+    if ( (uSize & 0x80000000u) != 0 && !aborting_app )
+    {
+      AbortWithError();
+      v5 = uSize;
+    }
+    pNumBuffersUsed = &uNumBuffersUsed;
+    if (uNumBuffersUsed == 6000 && !aborting_app)
+    {
+      AbortWithError();
+      v5 = uSize;
+    }
+    v8 = *pNumBuffersUsed;
+    v9 = bUseBigBuffer == 0;
+    ++*pNumBuffersUsed;
+    if ( v9 )
+    {
+      v12 = malloc(v5);
+      v11 = &pMemoryBuffers[v8];
+      *v11 = v12;
+      if ( v12 )
+      {
+        uMemoryBuffersSizes[v8] = uSize;
+      }
+      else
+      {
+        if ( !aborting_app )
+          AbortWithError();
+      }
+    }
+    else
+    {
+      LOBYTE(v5) = v5 & 0xFC;
+      v10 = v5 + 4;
+      Size = v10;
+      if ( v10 + uNextFreeOffsetInBigBuffer > uBigBufferSizeAligned )
+      {
+        printf("Id: %s  Size: %i\n", pName, v10);
+        CreateFileDump("Memory");
+        if ( !aborting_app )
+          AbortWithError();
+      }
+      v11 = &pMemoryBuffers[v8];
+      *v11 = (char *)pBigMemoryBuffer + uNextFreeOffsetInBigBuffer;
+      uMemoryBuffersSizes[v8] = Size;
+      if (pName)
+        strncpy(pMemoryBuffersNames[v8], pName, 11);
+      uNextFreeOffsetInBigBuffer += Size;
+    }
+    result = *v11;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+// 720018: using guessed type int aborting_app;
+
+
+
+//----- (004266CD) --------------------------------------------------------
+bool Allocator::Initialize(unsigned int uNumKBytes)
+{
+  if (bBigBufferAllocated)
+    return false;
+
+  if (!uNumKBytes)
+    return false;
+
+  pBigMemoryBuffer = malloc(uNumKBytes * 1024);
+  if (!pBigMemoryBuffer)
+    return false;
+
+  pBigBufferAligned = (char *)pBigMemoryBuffer + -((unsigned __int16)pBigMemoryBuffer & 0xFFF) + 4096;
+  uBigBufferSizeAligned = (uNumKBytes * 1024) - 4096;
+
+  uNumBuffersUsed = 0;
+  uNextFreeOffsetInBigBuffer = 0;
+
+  bUseBigBuffer = true;
+  return bBigBufferAllocated = true;
+}
+
+
+//----- (00426474) --------------------------------------------------------
+void Allocator::FreeChunk(void *ptr)
+{
+  Allocator *v2; // esi@1
+  unsigned int v3; // eax@5
+  signed int i; // edi@5
+  unsigned int v5; // eax@13
+  signed int v6; // ecx@16
+  signed int j; // edx@16
+  char v8; // zf@20
+
+  v2 = this;
+  if ( ptr )
+  {
+    if ( !this->bBigBufferAllocated && !aborting_app )
+      AbortWithError();
+    v3 = v2->uNumBuffersUsed;
+    for ( i = 0; i < (signed int)v3; ++i )
+    {
+      if ( v2->pMemoryBuffers[i] == ptr )
+        break;
+    }
+    if ( i >= (signed int)v3 && !aborting_app )
+      AbortWithError();
+    if ( !v2->bUseBigBuffer )
+      free(v2->pMemoryBuffers[i]);
+    v2->pMemoryBuffers[i] = 0;
+    v2->uMemoryBuffersSizes[i] = 0;
+    LOBYTE(v2->pMemoryBuffers[3 * i + 12000]) = 0;
+    v5 = v2->uNumBuffersUsed;
+    if ( i == v5 - 1 )
+    {
+      if ( i )
+      {
+        v6 = 0;
+        for ( j = 0; j < (signed int)v5; ++j )
+        {
+          if ( v2->pMemoryBuffers[j] )
+            v6 = j;
+        }
+        v8 = v2->bUseBigBuffer == 0;
+        v2->uNumBuffersUsed = v6 + 1;
+        if ( !v8 )
+          v2->uNextFreeOffsetInBigBuffer = (char *)v2->pMemoryBuffers[v6]
+                                         + v2->uMemoryBuffersSizes[v6]
+                                         - v2->pBigMemoryBuffer;
+      }
+      else
+      {
+        v2->uNextFreeOffsetInBigBuffer = 0;
+        v2->uNumBuffersUsed = 0;
+      }
+    }
+  }
+}
+// 720018: using guessed type int aborting_app;
+
+
+
+//----- (00426429) --------------------------------------------------------
+Allocator::Allocator()
+{
+  Allocator *v1; // eax@1
+  signed int v2; // ecx@1
+  int v3; // edx@1
+
+  v1 = this;
+  v2 = 0;
+  v1->uBigBufferSizeAligned = 0;
+  v1->bBigBufferAllocated = 0;
+  v3 = (int)v1->pMemoryBuffersNames;
+  do
+  {
+    v1->pMemoryBuffers[v2] = 0;
+    v1->uMemoryBuffersSizes[v2] = 0;
+    *(char *)v3 = 0;
+    ++v2;
+    v3 += 12;
+  }
+  while ( v2 < 6000 );
+  v1->uDumpsCount = 0;
+}
+
+
+//----- (0042654C) --------------------------------------------------------
+bool Allocator::CreateFileDump(const char *a1)
+{
+  Allocator *v2; // esi@1
+  unsigned int v3; // ST44_4@1
+  FILE *v4; // eax@1
+  FILE *v5; // edi@1
+  bool result; // eax@2
+  unsigned int v7; // ecx@5
+  int v8; // edx@5
+  int v9; // eax@6
+  int v10; // eax@8
+  int v11; // ecx@8
+  signed int v12; // ebx@8
+  signed int v13; // ebx@10
+  struct _MEMORYSTATUS memstat; // [sp+8h] [bp-38h]@5
+  char Filename[20]; // [sp+28h] [bp-18h]@1
+  unsigned int *v16; // [sp+3Ch] [bp-4h]@11
+  int a1a; // [sp+48h] [bp+8h]@11
+
+  v2 = this;
+  v3 = this->uDumpsCount;
+  this->uDumpsCount = v3 + 1;
+  sprintf(Filename, "Mem%03i.txt", v3);
+  v4 = fopen(Filename, "w");
+  v5 = v4;
+  if ( v4 )
+  {
+    if ( a1 )
+      fprintf(v4, "%s\n\n", a1);
+    fprintf(v5, "Windows Memory Status");
+    GlobalMemoryStatus(&memstat);
+    fprintf(v5, "dwLength:         %d\n\n", memstat.dwLength);
+    fprintf(v5, "dwMemoryLoad:     %d\n", memstat.dwMemoryLoad);
+    fprintf(v5, "dwTotalPhys:      %d\n", memstat.dwTotalPhys);
+    fprintf(v5, "dwAvailPhys:      %d\n", memstat.dwAvailPhys);
+    fprintf(v5, "dwTotalPageFile:  %d\n", memstat.dwTotalPageFile);
+    fprintf(v5, "dwAvailPageFile:  %d\n", memstat.dwAvailPageFile);
+    fprintf(v5, "dwTotalVirtual:   %d\n", memstat.dwTotalVirtual);
+    fprintf(v5, "dwAvailVirtual:   %d\n\n\n", memstat.dwAvailVirtual);
+    v7 = v2->uNumBuffersUsed;
+    v8 = 0;
+    if ( (signed int)v7 > 0 )
+    {
+      v9 = (int)v2->uMemoryBuffersSizes;
+      do
+      {
+        v8 += *(int *)v9;
+        v9 += 4;
+        --v7;
+      }
+      while ( v7 );
+    }
+    v10 = 0;
+    v11 = (int)v2->uMemoryBuffersSizes;
+    v12 = 6000;
+    do
+    {
+      v10 += *(int *)v11;
+      v11 += 4;
+      --v12;
+    }
+    while ( v12 );
+    fprintf(v5, "Size: %i  %i  %i\n\n", v2->uNumBuffersUsed, v8, v10);
+    v13 = 0;
+    if ( (signed int)v2->uNumBuffersUsed > 0 )
+    {
+      v16 = v2->uMemoryBuffersSizes;
+      a1a = (int)v2->pMemoryBuffersNames;
+      do
+      {
+        fprintf(v5, "%10i %10i %s\n", v13, *v16, a1a);
+        a1a += 12;
+        ++v16;
+        ++v13;
+      }
+      while ( v13 < (signed int)v2->uNumBuffersUsed );
+    }
+    fclose(v5);
+    result = 0;
+  }
+  else
+  {
+    result = 1;
+  }
+  return result;
+}
+
+
+
+
+
+
+
+
+//----- (00426892) --------------------------------------------------------
+static void __fastcall CheckMemoryAccessibility(void *pBase, DWORD uSize)
+{
+  DWORD v2; // edi@1
+  DWORD i; // eax@1
+  struct _SYSTEM_INFO SystemInfo; // [sp+8h] [bp-24h]@1
+
+  v2 = uSize;
+  GetSystemInfo(&SystemInfo);
+  for ( i = 16 * SystemInfo.dwPageSize; i < v2; i += SystemInfo.dwPageSize )
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Allocator.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,31 @@
+#pragma once
+
+
+#pragma pack(push, 1)
+struct Allocator
+{
+  static Allocator *Create() {static Allocator a; return &a;}
+
+  Allocator();
+  bool  Initialize(unsigned int uNumKBytes);
+  void *AllocNamedChunk(const void *pPrevPtrValue, unsigned int uSize, const char *pName);
+  void FreeChunk(void *ptr);
+  bool CreateFileDump(const char *a1);
+
+  void *pMemoryBuffers[6000];
+  unsigned int uMemoryBuffersSizes[6000];
+  char pMemoryBuffersNames[6000][12];
+  unsigned int uDumpsCount;
+  unsigned int uNumBuffersUsed;
+  void *pBigMemoryBuffer;
+  unsigned int uNextFreeOffsetInBigBuffer;
+  unsigned int uBigBufferSizeAligned;
+  unsigned int bBigBufferAllocated;
+  unsigned int bUseBigBuffer;
+  void *pBigBufferAligned;
+};
+#pragma pack(pop)
+
+
+
+extern Allocator *pAllocator; // idb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Arcomage.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,5799 @@
+#include <string>
+
+#include "Arcomage.h"
+#include "VideoPlayer.h"
+#include "AudioPlayer.h"
+#include "Mouse.h"
+#include "Game.h"
+#include "Viewport.h"
+#include "Time.h"
+#include "GUIFont.h"
+#include "Party.h"
+#include "GUIWindow.h"
+#include "Events2D.h"
+#include "stru272.h"
+#include "VectorTypes.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+ArcomageGame *pArcomageGame = new ArcomageGame;
+ArcomageCard pCards[87];
+ArcomageGame_stru0 stru_505708[2];
+
+
+
+
+
+/*  267 */
+#pragma pack(push, 1)
+struct stru273
+{
+  bool _40DD2F();
+  bool Inside(Vec4_int_ *pXYZW);
+
+  int x;
+  int y;
+  char field_8;
+  char field_9;
+  char field_A;
+  char field_B;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+//----- (0040DD2F) --------------------------------------------------------
+bool stru273::_40DD2F()
+{
+  bool result; // eax@1
+
+  this->x = pArcomageGame->mouse_x;
+  result = pArcomageGame->mouse_y;
+  this->y = pArcomageGame->mouse_y;
+  this->field_8 = pArcomageGame->mouse_left;
+  this->field_9 = pArcomageGame->mouse_left == pArcomageGame->field_F7;
+  this->field_8 = pArcomageGame->mouse_left;
+  this->field_B = pArcomageGame->mouse_right == pArcomageGame->field_F8;
+  pArcomageGame->field_F7 = pArcomageGame->mouse_left;
+  pArcomageGame->field_F8 = pArcomageGame->mouse_right;
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (0040DD93) --------------------------------------------------------
+bool stru273::Inside(Vec4_int_ *pXYZW)
+{
+  int v2; // eax@3
+
+  auto a1 = this;
+  return a1->x >= pXYZW->x && a1->x <= pXYZW->z && (v2 = a1->y, v2 >= pXYZW->y) && v2 <= pXYZW->w;
+}
+
+
+
+
+//----- (0040DFAF) --------------------------------------------------------
+void ArcomageGame::OnMouseClick(char right_left, bool bDown)
+{
+  if ( right_left )
+    pArcomageGame->mouse_right = bDown;
+  else
+    pArcomageGame->mouse_left = bDown;
+}
+
+//----- (0040DFC1) --------------------------------------------------------
+void ArcomageGame::OnMouseMove(POINT *pXY)
+{
+  pArcomageGame->mouse_x = pXY->x;
+  pArcomageGame->mouse_y = pXY->y;
+}
+
+
+//----- (0040DF47) --------------------------------------------------------
+void DoBlt_Copy(unsigned __int16 *pPixels)
+{
+  unsigned __int16 *v1; // ebx@1
+  ArcomageRect rect; // [sp+Ch] [bp-18h]@1
+  int pTargetXY[2]; // [sp+1Ch] [bp-8h]@1
+
+  v1 = pPixels;
+  pRenderer->Present();
+  pTargetXY[0] = 0;
+  pTargetXY[1] = 0;
+  rect.x = 0;
+  rect.z = 640;
+  rect.y = 0;
+  rect.w = 480;
+  pRenderer->BeginScene();
+  pArcomageGame->pBlit_Copy_pixels = v1;
+  Blt_Copy(&rect, pTargetXY, 2);
+  pRenderer->EndScene();
+  pArcomageGame->pBlit_Copy_pixels = 0;
+}
+
+//----- (0040DDC9) --------------------------------------------------------
+void __thiscall ArcomageGame::PlaySound(unsigned int a1)
+{
+  SoundID v1; // eax@10
+  signed int v2; // [sp-4h] [bp-4h]@2
+
+  switch ( a1 )
+  {
+    case 0x28u:
+    case 0x2Bu:
+    case 0x2Eu:
+      v2 = SOUND_Arcomage_LoseResources;
+      goto LABEL_10;
+    case 0x27u:
+    case 0x29u:
+    case 0x2Au:
+    case 0x2Cu:
+    case 0x2Du:
+    case 0x2Fu:
+      v2 = SOUND_Arcomage_AddResources;
+      goto LABEL_10;
+    case 0u:
+    case 0xCu:
+    case 0xEu:
+    case 0xFu:
+    case 0x10u:
+    case 0x30u:
+    case 0x32u:
+    case 0x35u:
+      v2 = SOUND_Arcomage_TowerWallDamage;
+      goto LABEL_10;
+    case 0x15u:
+    case 0x16u:
+    case 0x17u:
+      v2 = SOUND_Arcomage_DrawCard;
+      goto LABEL_10;
+    case 0x38u:
+      v2 = 124;
+      goto LABEL_10;
+    case 0x1Fu:
+    case 0x22u:
+    case 0x25u:
+      v2 = SOUND_Arcomage_ProductionDamage;
+      goto LABEL_10;
+    case 1u:
+    case 0x1Eu:
+    case 0x20u:
+    case 0x21u:
+    case 0x23u:
+    case 0x24u:
+    case 0x26u:
+      v2 = SOUND_Arcomage_ProductionUpgrade;
+      goto LABEL_10;
+    case 0x14u:
+      v2 = SOUND_Arcomage_127;
+LABEL_10:
+      v1 = (SoundID)v2;
+      goto LABEL_16;
+    case 3u:
+      v1 = SOUND_Arcomage_128;
+      goto LABEL_16;
+    case 0x34u:
+    case 0x36u:
+      v1 = SOUND_Arcomage_TowerUpgrade;
+      goto LABEL_16;
+    case 0xAu:
+    case 0xBu:
+    case 0xDu:
+      v1 = (SoundID)130;
+      goto LABEL_16;
+    case 0x37u:
+      v1 = (SoundID)131;
+      goto LABEL_16;
+    case 0x31u:
+    case 0x33u:
+      v1 = SOUND_Arcomage_WallUpgrade;
+LABEL_16:
+      pAudioPlayer->PlaySound(v1, 0, 0, -1, 0, 0, 0, 0);
+      break;
+    default:
+      return;
+  }
+}
+
+//----- (0040DC2D) --------------------------------------------------------
+bool ArcomageGame::MsgLoop(int a1, ArcomageGame_stru1 *a2)
+{
+  void *v2; // ebp@1
+  BOOL v3; // eax@1
+  int v4; // edx@6
+  int v5; // edx@6
+  int v6; // eax@6
+  int v7; // edx@7
+
+  v2 = a2;
+  pArcomageGame->field_0 = 0;
+  pArcomageGame->stru1.field_0 = 0;
+  v3 = PeekMessageA(&pArcomageGame->msg, 0, 0, 0, PM_REMOVE);
+  if ( pArcomageGame->msg.message == WM_QUIT )
+    Game_DeinitializeAndTerminate(0);
+  if ( v3 > 0 )
+  {
+    TranslateMessage(&pArcomageGame->msg);
+    DispatchMessageA(&pArcomageGame->msg);
+  }
+  if (pAsyncMouse)
+  {
+    EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);
+    v4 = *((unsigned int *)pAsyncMouse + 7);
+    pArcomageGame->mouse_x = *((unsigned int *)pAsyncMouse + 6);
+    pArcomageGame->mouse_y = v4;
+    v5 = *((unsigned int *)pAsyncMouse + 27);
+    v6 = *(unsigned int *)v5;
+    if ( *(unsigned int *)v5 != v5 )
+    {
+      do
+      {
+        v7 = *(unsigned int *)(v6 + 20);
+        if ( v7 & 1 )
+        {
+          pArcomageGame->stru1.field_0 = 7;
+        }
+        else
+        {
+          if ( v7 & 2 )
+            pArcomageGame->stru1.field_0 = 8;
+        }
+        v6 = *(unsigned int *)v6;
+      }
+      while ( v6 != *((unsigned int *)pAsyncMouse + 27) );
+    }
+    pAsyncMouse->_46B944();
+    if ( !*((unsigned char *)pAsyncMouse + 90) )
+      pArcomageGame->field_F6 = 1;
+    LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);
+  }
+  memcpy(v2, &pArcomageGame->stru1, 0xCu);
+  return pArcomageGame->stru1.field_0 != 0;
+}
+
+
+//----- (0040D7D5) --------------------------------------------------------
+void am_BeginScene(unsigned __int16 *pPcxPixels, int a2, int a3)
+{
+  unsigned __int16 *v3; // esi@1
+
+  v3 = pPcxPixels;
+  pRenderer->BeginScene();
+  pArcomageGame->pBlit_Copy_pixels = v3;
+}
+
+//----- (0040D7EC) --------------------------------------------------------
+void __fastcall Blt_Chroma(ArcomageRect *pSrcXYZW, int *pTargetXY, int a3, int a4)
+{
+  ArcomageRect *pSrcXYZW_; // esi@1
+  int x; // ecx@1
+  int y; // edx@1
+  unsigned __int16 *pSrc; // eax@2
+  unsigned __int16 *v8; // edi@3
+  int uSrcTotalWidth; // ecx@4
+  unsigned int v10; // esi@9
+  int v11; // ebx@11
+  unsigned __int16 *v12; // edx@11
+  char v13; // zf@17
+  unsigned __int16 *v14; // ebx@20
+  int v15; // eax@20
+  unsigned __int16 *v16; // ecx@20
+  unsigned int v17; // eax@23
+  std::string v18; // [sp-18h] [bp-3Ch]@8
+  const char *v19; // [sp-8h] [bp-2Ch]@8
+  int v20; // [sp-4h] [bp-28h]@8
+  std::string *v21; // [sp+Ch] [bp-18h]@8
+  unsigned __int16 *v22; // [sp+10h] [bp-14h]@9
+  int v23; // [sp+14h] [bp-10h]@3
+  int v24; // [sp+18h] [bp-Ch]@3
+  int uSrcPitch; // [sp+1Ch] [bp-8h]@5
+  int a3a; // [sp+23h] [bp-1h]@8
+  int v27; // [sp+30h] [bp+Ch]@13
+
+  pSrcXYZW_ = pSrcXYZW;
+  x = *pTargetXY;
+  y = pTargetXY[1];
+  if ( !pRenderer->uNumSceneBegins || (pSrc = pArcomageGame->pBlit_Copy_pixels) == 0 )
+    return;
+  v8 = &pRenderer->pTargetSurface[x + y * pRenderer->uTargetSurfacePitch];
+  v23 = pSrcXYZW_->z - pSrcXYZW_->x;
+  v24 = pSrcXYZW_->w - pSrcXYZW_->y;
+  if ( pArcomageGame->pBlit_Copy_pixels == pArcomageGame->pBackgroundPixels )
+  {
+    uSrcTotalWidth = (signed __int16)pArcomageGame->pGameBackground.uWidth;
+LABEL_5:
+    uSrcPitch = uSrcTotalWidth;
+    goto LABEL_9;
+  }
+  if ( pArcomageGame->pBlit_Copy_pixels == pArcomageGame->pSpritesPixels )
+  {
+    uSrcTotalWidth = (signed __int16)pArcomageGame->pSprites.uWidth;
+    goto LABEL_5;
+  }
+      MessageBoxW(nullptr, L"Problem in Blit_Chroma", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\am_nw.cpp:157", 0);
+  pSrc = pArcomageGame->pBlit_Copy_pixels;
+LABEL_9:
+  v22 = &pSrc[pSrcXYZW_->x + uSrcPitch * pSrcXYZW_->y];
+  v10 = 0xFFu >> (8 - LOBYTE(pRenderer->uTargetBBits));
+  v21 = (std::string *)((((pRenderer->uTargetGBits != 6) - 1) & 0x4A00) + 12783);
+  if ( a4 == 2 )
+  {
+    if ( v24 > 0 )
+    {
+      v11 = v23;
+      v12 = v22;
+      uSrcPitch = 2 * (uSrcPitch - v23);
+      do
+      {
+        if ( v11 > 0 )
+        {
+          v27 = v11;
+          do
+          {
+            if ( *v12 != v10 )
+              *v8 = *v12;
+            ++v8;
+            ++v12;
+            --v27;
+          }
+          while ( v27 );
+        }
+        v12 = (unsigned __int16 *)((char *)v12 + uSrcPitch);
+        v13 = v24-- == 1;
+        v8 += pRenderer->uTargetSurfacePitch - v11;
+      }
+      while ( !v13 );
+    }
+  }
+  else
+  {
+    if ( v24 > 0 )
+    {
+      v14 = (unsigned __int16 *)v23;
+      v15 = uSrcPitch - v23;
+      v23 = v24;
+      v16 = v22;
+      uSrcPitch = 2 * v15;
+      do
+      {
+        if ( (signed int)v14 > 0 )
+        {
+          v22 = v14;
+          do
+          {
+            v17 = *v16;
+            if ( v17 != v10 )
+            {
+              v24 = *v8;
+              *v8 = ((unsigned __int16)v21 & ((unsigned int)v24 >> 1)) + ((unsigned __int16)v21 & (v17 >> 1));
+            }
+            ++v8;
+            ++v16;
+            v22 = (unsigned __int16 *)((char *)v22 - 1);
+          }
+          while ( v22 );
+        }
+        v16 = (unsigned __int16 *)((char *)v16 + uSrcPitch);
+        v13 = v23-- == 1;
+        v8 += pRenderer->uTargetSurfacePitch - (uint)v14;
+      }
+      while ( !v13 );
+    }
+  }
+}
+
+//----- (0040D9B1) --------------------------------------------------------
+void __fastcall Blt_Copy(ArcomageRect *pSrcXYZW, int *pTargetXY, int a3)
+{
+  ArcomageRect *pSrcXYZW_; // esi@1
+  int x; // ecx@1
+  int y; // edx@1
+  unsigned __int16 *v6; // eax@2
+  unsigned __int16 *v7; // edi@3
+  int uSrcRegionWidth; // ebx@3
+  int uSrcTotalWidth; // ecx@4
+  unsigned __int16 *pSrc; // esi@8
+  int v11; // edx@9
+  int v12; // eax@12
+  int v13; // ecx@19
+  char v14; // zf@21
+  std::string v15; // [sp-18h] [bp-38h]@7
+  const char *v16; // [sp-8h] [bp-28h]@7
+  int v17; // [sp-4h] [bp-24h]@7
+  unsigned int v18; // [sp+Ch] [bp-14h]@7
+  int v19; // [sp+10h] [bp-10h]@8
+  int v20; // [sp+14h] [bp-Ch]@17
+  int uSrcRegionHeight; // [sp+18h] [bp-8h]@3
+  int a3a; // [sp+1Fh] [bp-1h]@7
+
+  pSrcXYZW_ = pSrcXYZW;
+  x = *pTargetXY;
+  y = pTargetXY[1];
+  if ( pRenderer->uNumSceneBegins )
+  {
+    v6 = pArcomageGame->pBlit_Copy_pixels;
+    if ( pArcomageGame->pBlit_Copy_pixels )
+    {
+      v7 = &pRenderer->pTargetSurface[x + y * pRenderer->uTargetSurfacePitch];
+      uSrcRegionWidth = pSrcXYZW_->z - pSrcXYZW_->x;
+      uSrcRegionHeight = pSrcXYZW_->w - pSrcXYZW_->y;
+      if ( pArcomageGame->pBlit_Copy_pixels == pArcomageGame->pBackgroundPixels )
+      {
+        uSrcTotalWidth = (signed __int16)pArcomageGame->pGameBackground.uWidth;
+      }
+      else
+      {
+        if ( pArcomageGame->pBlit_Copy_pixels == pArcomageGame->pSpritesPixels )
+        {
+          uSrcTotalWidth = (signed __int16)pArcomageGame->pSprites.uWidth;
+        }
+        else
+        {
+      MessageBoxW(nullptr, L"Problem in Blit_Copy", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\am_nw.cpp:246", 0);
+          uSrcTotalWidth = a3;
+          v6 = pArcomageGame->pBlit_Copy_pixels;
+        }
+      }
+      pSrc = &v6[pSrcXYZW_->x + uSrcTotalWidth * pSrcXYZW_->y];
+      v19 = (((pRenderer->uTargetGBits != 6) - 1) & 0x4A00) + 0x31EF;
+      if ( a3 == 2 )
+      {
+        v11 = uSrcRegionHeight;
+        if ( uSrcRegionHeight > 0 )
+        {
+          uSrcRegionHeight = 2 * (uSrcTotalWidth - uSrcRegionWidth);
+          do
+          {
+            if ( uSrcRegionWidth > 0 )
+            {
+              v12 = uSrcRegionWidth;
+              do
+              {
+                *v7 = *pSrc;
+                ++v7;
+                ++pSrc;
+                --v12;
+              }
+              while ( v12 );
+            }
+            pSrc = (unsigned __int16 *)((char *)pSrc + uSrcRegionHeight);
+            --v11;
+            v7 += pRenderer->uTargetSurfacePitch - uSrcRegionWidth;
+          }
+          while ( v11 );
+        }
+      }
+      else
+      {
+        if ( uSrcRegionHeight > 0 )
+        {
+          v20 = uSrcRegionHeight;
+          uSrcRegionHeight = 2 * (uSrcTotalWidth - uSrcRegionWidth);
+          do
+          {
+            if ( uSrcRegionWidth > 0 )
+            {
+              v13 = uSrcRegionWidth;
+              do
+              {
+                v18 = *v7;
+                *v7 = (v19 & (v18 >> 1)) + (v19 & ((unsigned int)*pSrc >> 1));
+                ++v7;
+                ++pSrc;
+                --v13;
+              }
+              while ( v13 );
+            }
+            pSrc = (unsigned __int16 *)((char *)pSrc + uSrcRegionHeight);
+            v14 = v20-- == 1;
+            v7 += pRenderer->uTargetSurfacePitch - uSrcRegionWidth;
+          }
+          while ( !v14 );
+        }
+      }
+    }
+  }
+}
+
+//----- (0040DB10) --------------------------------------------------------
+void __cdecl am_EndScene()
+{
+  pRenderer->EndScene();
+  pArcomageGame->pBlit_Copy_pixels = 0;
+}
+
+//----- (0040D7B7) --------------------------------------------------------
+bool ArcomageGame::LoadSprites()
+{
+  bool result; // eax@1
+
+  pArcomageGame->pSprites.Load("sprites.pcx", 2);
+  result = (bool)pArcomageGame->pSprites.pPixels;
+  pArcomageGame->pSpritesPixels = pArcomageGame->pSprites.pPixels;
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (0040D799) --------------------------------------------------------
+bool ArcomageGame::LoadBackground()
+{
+  bool result; // eax@1
+
+  pArcomageGame->pGameBackground.Load("layout.pcx", 2);
+  result = (bool)pArcomageGame->pGameBackground.pPixels;
+  pArcomageGame->pBackgroundPixels = pArcomageGame->pGameBackground.pPixels;
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (00408BB4) --------------------------------------------------------
+bool __fastcall am_408BB4(int a1)
+{
+  char result; // al@3
+  signed int v3; // ebx@8
+  int v4; // esi@8
+  int v5; // eax@9
+  int v6; // edi@9
+  int v7; // eax@11
+  signed int v8; // eax@11
+  int v9; // ebx@5
+  int v10; // eax@5
+  int v11; // ecx@18
+  char v12; // bl@20
+  int v13; // eax@20
+  ArcomageCard *v14; // ecx@20
+  char v15; // dl@20
+  char v16; // dl@24
+  int v17; // edx@25
+  int v18; // edx@27
+  char v19; // dl@31
+  int v20; // edx@32
+  char v21; // dl@35
+  char v22; // dl@39
+  int v23; // edx@40
+  char v24; // dl@45
+  int v25; // edx@46
+  char v26; // dl@52
+  int v27; // edx@53
+  char v28; // dl@58
+  int v29; // edx@59
+  char v30; // dl@64
+  int v31; // edx@65
+  char v32; // dl@70
+  int v33; // edx@71
+  char v34; // dl@76
+  int v35; // edx@77
+  char v36; // dl@82
+  int v37; // edx@83
+  char v38; // dl@86
+  char v39; // dl@90
+  int v40; // edi@93
+  char v41; // dl@93
+  int v42; // esi@93
+  char v43; // bl@94
+  int v44; // esi@95
+  char v45; // dl@99
+  char v46; // dl@103
+  char v47; // dl@107
+  char v48; // dl@111
+  char v49; // dl@115
+  ArcomageGame_stru0 *v50; // ebx@116
+  ArcomageGame_stru0 *v51; // edx@116
+  int v52; // esi@124
+  int v53; // edx@124
+  int v54; // edx@127
+  int v55; // esi@130
+  int v56; // edi@138
+  int l; // esi@138
+  int v58; // eax@140
+  int v59; // ecx@142
+  int v60; // edx@142
+  int v61; // ebx@142
+  int v62; // eax@145
+  int v63; // esi@146
+  int v64; // ebx@4
+  int v65; // eax@4
+  int v66; // ecx@168
+  char v67; // bl@170
+  int v68; // eax@170
+  ArcomageCard *v69; // ecx@170
+  char v70; // dl@170
+  char v71; // dl@174
+  int v72; // edx@175
+  int v73; // edx@177
+  char v74; // dl@181
+  char v75; // dl@184
+  char v76; // dl@188
+  int v77; // edx@189
+  char v78; // dl@194
+  char v79; // dl@200
+  int v80; // edx@201
+  char v81; // dl@206
+  int v82; // edx@207
+  char v83; // dl@212
+  int v84; // edx@213
+  char v85; // dl@218
+  int v86; // edx@219
+  char v87; // dl@224
+  int v88; // edx@225
+  char v89; // dl@230
+  int v90; // edx@231
+  char v91; // dl@234
+  int v92; // edx@235
+  char v93; // dl@238
+  int v94; // edx@239
+  int v95; // esi@241
+  char v96; // dl@241
+  int v97; // esi@241
+  char v98; // bl@242
+  int v99; // edi@243
+  int v100; // edx@245
+  int v101; // edi@246
+  char v102; // dl@247
+  int v103; // edx@248
+  char v104; // dl@251
+  int v105; // edx@252
+  char v106; // dl@255
+  int v107; // edx@256
+  char v108; // dl@259
+  int v109; // edx@260
+  char v110; // dl@263
+  ArcomageGame_stru0 *v111; // ebx@264
+  ArcomageGame_stru0 *v112; // edx@264
+  int v113; // esi@272
+  int v114; // edx@272
+  int v115; // edx@275
+  int v116; // esi@278
+  int v117; // edi@286
+  int j; // esi@286
+  int v119; // eax@288
+  int v120; // ecx@290
+  int v121; // edx@290
+  int v122; // ebx@290
+  int v123; // eax@293
+  int v124; // esi@294
+  int v125; // [sp-28h] [bp-28h]@130
+  int v126; // [sp-28h] [bp-28h]@278
+  int k; // [sp-24h] [bp-24h]@18
+  int i; // [sp-24h] [bp-24h]@168
+  int v129; // [sp-20h] [bp-20h]@5
+  int v130; // [sp-20h] [bp-20h]@4
+  int v131; // [sp-1Ch] [bp-1Ch]@17
+  int v132; // [sp-1Ch] [bp-1Ch]@140
+  int v133; // [sp-1Ch] [bp-1Ch]@167
+  int v134; // [sp-1Ch] [bp-1Ch]@288
+  int v135; // [sp-18h] [bp-18h]@5
+  int v136; // [sp-18h] [bp-18h]@4
+  signed int v137; // [sp-14h] [bp-14h]@0
+  int v138; // [sp-14h] [bp-14h]@93
+  int v139; // [sp-14h] [bp-14h]@130
+  int v140; // [sp-14h] [bp-14h]@241
+  int v141; // [sp-14h] [bp-14h]@278
+  ArcomageGame_stru0 *v142; // [sp-10h] [bp-10h]@5
+  ArcomageGame_stru0 *v143; // [sp-10h] [bp-10h]@4
+  ArcomageGame_stru0 *v144; // [sp-Ch] [bp-Ch]@5
+  ArcomageGame_stru0 *v145; // [sp-Ch] [bp-Ch]@4
+  char v146; // [sp-8h] [bp-8h]@35
+  char v147; // [sp-8h] [bp-8h]@184
+  char v148; // [sp-5h] [bp-5h]@20
+  char v149; // [sp-5h] [bp-5h]@170
+
+  byte_4FAA00 = 1;
+  if ( dword_4DF3A4 )
+  {
+    if ( dword_4DF3A4 != 1 )
+    {
+      result = dword_4DF3A4 - 2;
+      if ( dword_4DF3A4 != 2 )
+        return result;
+      v64 = a1;
+      v145 = &stru_505708[a1];
+      v130 = a1;
+      v143 = &stru_505708[(a1 + 1) % 2];
+      v136 = am_40BB49(a1);
+      v65 = 0;
+      do
+      {
+        if ( v65 >= v136 )
+        {
+          dword_4FA9B0[2 * v65] = -1;
+          dword_4FA9B4[2 * v65] = -9999;
+        }
+        else
+        {
+          dword_4FA9B0[2 * v65] = v65;
+          dword_4FA9B4[2 * v65] = 0;
+        }
+        ++v65;
+      }
+      while ( v65 < 10 );
+      v133 = 0;
+      if ( v136 > 0 )
+      {
+        v66 = 47 * v64;
+        for ( i = 47 * v64; ; v66 = i )
+        {
+          v67 = 99;
+          v68 = 2 * v133;
+          v69 = &pCards[stru_505708[0].arr_44[v66 + dword_4FA9B0[2 * v133]]];
+          v70 = v69->field_38[2];
+          v149 = v69->field_38[2];
+          if ( v145->field_24 >= 10 )
+          {
+            if ( v70 == 99
+              || v69->field_48[4] == 99
+              || v69->field_48[15] == 99
+              || (v74 = BYTE1(v69->field_68), v74 == 99) )
+              v73 = 5 * (v143->field_24 - v145->field_24);
+            else
+              v73 = 5 * (v149 + v69->field_48[4] + v69->field_48[15] + v74);
+          }
+          else
+          {
+            if ( v70 == 99
+              || v69->field_48[4] == 99
+              || v69->field_48[15] == 99
+              || (v71 = BYTE1(v69->field_68), v71 == 99) )
+              v72 = 5 * (v143->field_24 - v145->field_24);
+            else
+              v72 = 5 * (v149 + v69->field_48[4] + v69->field_48[15] + v71);
+            v73 = 4 * v72;
+          }
+          dword_4FA9B4[v68] += v73;
+          v75 = v69->field_38[1];
+          v147 = v69->field_38[1];
+          if ( v145->field_28 >= 10 )
+          {
+            if ( v75 == 99
+              || v69->field_48[3] == 99
+              || v69->field_48[14] == 99
+              || (v78 = LOBYTE(v69->field_68), v78 == 99) )
+              v77 = v143->field_28 - v145->field_28;
+            else
+              v77 = v147 + v69->field_48[3] + v69->field_48[14] + v78;
+          }
+          else
+          {
+            if ( v75 == 99
+              || v69->field_48[3] == 99
+              || v69->field_48[14] == 99
+              || (v76 = LOBYTE(v69->field_68), v76 == 99) )
+              v77 = 5 * (v143->field_28 - v145->field_28);
+            else
+              v77 = 5 * (v147 + v69->field_48[3] + v69->field_48[14] + v76);
+          }
+          dword_4FA9B4[v68] += v77;
+          dword_4FA9B4[v68] += 7 * (v69->field_38[0] + v69->field_48[2] + v69->field_48[13] + v69->field_58[15]);
+          if ( BYTE2(v69->field_30) == 99
+            || v69->field_38[12] == 99
+            || v69->field_48[7] == 99
+            || (v79 = v69->field_58[9], v79 == 99) )
+            v80 = 5 * (v143->field_2C - v145->field_2C);
+          else
+            v80 = 5 * (BYTE2(v69->field_30) + v69->field_38[12] + v69->field_48[7] + v79);
+          dword_4FA9B4[v68] += 8 * v80;
+          if ( BYTE3(v69->field_30) == 99
+            || v69->field_38[13] == 99
+            || v69->field_48[8] == 99
+            || (v81 = v69->field_58[10], v81 == 99) )
+            v82 = 5 * (v143->field_30 - v145->field_30);
+          else
+            v82 = 5 * (BYTE3(v69->field_30) + v69->field_38[13] + v69->field_48[8] + v81);
+          dword_4FA9B4[v68] += 8 * v82;
+          if ( LOBYTE(v69->field_34) == 99
+            || v69->field_38[14] == 99
+            || v69->field_48[9] == 99
+            || (v83 = v69->field_58[11], v83 == 99) )
+            v84 = 5 * (v143->field_34 - v145->field_34);
+          else
+            v84 = 5 * (LOBYTE(v69->field_34) + v69->field_38[14] + v69->field_48[9] + v83);
+          dword_4FA9B4[v68] += 8 * v84;
+          if ( BYTE1(v69->field_34) == 99
+            || v69->field_38[15] == 99
+            || v69->field_48[10] == 99
+            || (v85 = v69->field_58[12], v85 == 99) )
+            v86 = v143->field_38 - v145->field_38;
+          else
+            v86 = BYTE1(v69->field_34) + v69->field_38[15] + v69->field_48[10] + v85;
+          dword_4FA9B4[v68] += 2 * v86;
+          if ( BYTE2(v69->field_34) == 99
+            || v69->field_48[0] == 99
+            || v69->field_48[11] == 99
+            || (v87 = v69->field_58[13], v87 == 99) )
+            v88 = v143->field_3C - v145->field_3C;
+          else
+            v88 = BYTE2(v69->field_34) + v69->field_48[0] + v69->field_48[11] + v87;
+          dword_4FA9B4[v68] += 2 * v88;
+          if ( BYTE3(v69->field_34) == 99
+            || v69->field_48[1] == 99
+            || v69->field_48[12] == 99
+            || (v89 = v69->field_58[14], v89 == 99) )
+            v90 = v143->field_40 - v145->field_40;
+          else
+            v90 = BYTE3(v69->field_34) + v69->field_48[1] + v69->field_48[12] + v89;
+          dword_4FA9B4[v68] += 2 * v90;
+          if ( v69->field_38[11] == 99 || (v91 = v69->field_58[8], v91 == 99) )
+            v92 = 10 * (v145->field_24 - v143->field_24);
+          else
+            v92 = -10 * (v69->field_38[11] + v91);
+          dword_4FA9B4[v68] += v92;
+          if ( v69->field_38[10] == 99 || (v93 = v69->field_58[7], v93 == 99) )
+            v94 = 3 * (v145->field_28 - v143->field_28);
+          else
+            v94 = -3 * (v69->field_38[10] + v93);
+          dword_4FA9B4[v68] += v94;
+          v95 = v69->field_38[9];
+          v140 = v95;
+          v96 = v69->field_38[3];
+          dword_4FA9B4[v68] += -7 * (v69->field_58[6] + v95);
+          v97 = dword_4FA9B4[v68];
+          if ( v96 == 99 )
+            goto LABEL_245;
+          v98 = v69->field_58[0];
+          if ( v98 == 99 )
+            break;
+          v99 = v96 + v98;
+          v67 = 99;
+          dword_4FA9B4[v68] = v97 - 5 * v99;
+LABEL_246:
+          v101 = v140;
+          if ( v69->field_38[4] == v67 || (v102 = v69->field_58[1], v102 == v67) )
+            v103 = 5 * (v145->field_30 - v143->field_30);
+          else
+            v103 = -5 * (v69->field_38[4] + v102);
+          dword_4FA9B4[v68] += v103;
+          if ( v69->field_38[5] == v67 || (v104 = v69->field_58[2], v104 == v67) )
+            v105 = 5 * (v145->field_34 - v143->field_34);
+          else
+            v105 = -5 * (v69->field_38[5] + v104);
+          dword_4FA9B4[v68] += v105;
+          if ( v69->field_38[6] == v67 || (v106 = v69->field_58[3], v106 == v67) )
+            v107 = v145->field_38 - v143->field_38;
+          else
+            v107 = -(v69->field_38[6] + v106);
+          dword_4FA9B4[v68] += 2 * v107;
+          if ( v69->field_38[7] == v67 || (v108 = v69->field_58[4], v108 == v67) )
+            v109 = v145->field_3C - v143->field_3C;
+          else
+            v109 = -(v69->field_38[7] + v108);
+          dword_4FA9B4[v68] += 2 * v109;
+          if ( v69->field_38[8] == v67 || (v110 = v69->field_58[5], v110 == v67) )
+          {
+            v112 = v145;
+            v111 = v143;
+            dword_4FA9B4[v68] += 2 * (v145->field_40 - v143->field_40);
+          }
+          else
+          {
+            v111 = v143;
+            dword_4FA9B4[v68] += -2 * (v69->field_38[8] + v110);
+            v112 = v145;
+          }
+          if ( LOBYTE(v69->field_30) || v69->field_48[5] )
+            dword_4FA9B4[v68] *= 10;
+          if ( LOBYTE(v69->field_24) == 1 )
+          {
+            v113 = LOBYTE(v69->field_28);
+            v114 = v112->field_38;
+          }
+          else
+          {
+            if ( LOBYTE(v69->field_24) == 2 )
+            {
+              v113 = BYTE1(v69->field_28);
+              v114 = v112->field_3C;
+            }
+            else
+            {
+              if ( LOBYTE(v69->field_24) != 3 )
+                goto LABEL_278;
+              v113 = BYTE2(v69->field_28);
+              v114 = v112->field_40;
+            }
+          }
+          v115 = v114 - v113;
+          if ( v115 > 3 )
+            v115 = 3;
+          dword_4FA9B4[v68] += 5 * v115;
+LABEL_278:
+          v116 = v69->field_58[8];
+          v141 = v111->field_24;
+          v126 = v69->field_38[11];
+          if ( v141 <= v116 + v126 )
+            dword_4FA9B4[v68] += 9999;
+          v137 = v111->field_28 + v141;
+          if ( v137 <= v116 + v126 + v69->field_58[6] + v69->field_58[7] + v101 + v69->field_38[10] )
+            dword_4FA9B4[v68] += 9999;
+          if ( v69->field_48[15] + (signed int)BYTE1(v69->field_68) + v145->field_24 + v69->field_48[4] + v149 >= dword_4E1884 )
+            dword_4FA9B4[v68] += 9999;
+          ++v133;
+          if ( v133 >= v136 )
+          {
+            v64 = v130;
+            goto LABEL_286;
+          }
+        }
+        v67 = 99;
+LABEL_245:
+        v100 = v145->field_2C - v143->field_2C;
+        dword_4FA9B4[v68] = v97 + 4 * v100 + v100;
+        goto LABEL_246;
+      }
+LABEL_286:
+      v117 = v136 - 1;
+      for ( j = v136 - 1; j >= 0; --j )
+      {
+        v137 = 0;
+        if ( j > 0 )
+        {
+          v119 = (int)dword_4FA9B0;
+          v134 = j;
+          v137 = j;
+          do
+          {
+            if ( *(unsigned int *)(v119 + 4) < *(unsigned int *)(v119 + 12) )
+            {
+              v120 = *(unsigned int *)v119;
+              v121 = *(unsigned int *)(v119 + 4);
+              *(unsigned int *)v119 = *(unsigned int *)(v119 + 8);
+              v122 = *(unsigned int *)(v119 + 12);
+              *(unsigned int *)(v119 + 8) = v120;
+              *(unsigned int *)(v119 + 4) = v122;
+              v64 = v130;
+              *(unsigned int *)(v119 + 12) = v121;
+            }
+            v119 += 8;
+            --v134;
+          }
+          while ( v134 );
+        }
+      }
+      v123 = v136 - 1;
+      if ( am_byte_4FAA77 )
+      {
+        if ( v117 >= 0 )
+        {
+          while ( !BYTE3(pCards[stru_505708[0].arr_44[47 * v64 + dword_4FA9B0[2 * v123]]].field_28) )
+          {
+            --v123;
+            if ( v123 < 0 )
+              return am_40BCFB(v64, v137);
+          }
+          v137 = dword_4FA9B0[2 * v123];
+        }
+      }
+      else
+      {
+        v124 = 0;
+        if ( v117 >= 0 )
+        {
+          while ( !BYTE3(pCards[stru_505708[0].arr_44[47 * v64 + dword_4FA9B0[2 * v123]]].field_28) )
+          {
+            --v123;
+            if ( v123 < 0 )
+              goto LABEL_299;
+          }
+          v137 = dword_4FA9B0[2 * v123];
+        }
+LABEL_299:
+        if ( v136 > 0 )
+        {
+          while ( !am_40BF15(v64, dword_4FA9B0[2 * v124]) || dword_4FA9B4[2 * v124] < 0 )
+          {
+            ++v124;
+            if ( v124 >= v136 )
+              return am_40BCFB(v64, v137);
+          }
+          return am_40BE0E(v64, dword_4FA9B0[2 * v124]);
+        }
+      }
+      return am_40BCFB(v64, v137);
+    }
+    v9 = a1;
+    v144 = &stru_505708[a1];
+    v129 = a1;
+    v142 = &stru_505708[(a1 + 1) % 2];
+    v135 = am_40BB49(a1);
+    v10 = 0;
+    do
+    {
+      if ( v10 >= v135 )
+      {
+        dword_4FA9B0[2 * v10] = -1;
+        dword_4FA9B4[2 * v10] = -9999;
+      }
+      else
+      {
+        dword_4FA9B0[2 * v10] = v10;
+        dword_4FA9B4[2 * v10] = 0;
+      }
+      ++v10;
+    }
+    while ( v10 < 10 );
+    v131 = 0;
+    if ( v135 > 0 )
+    {
+      v11 = 47 * v9;
+      for ( k = 47 * v9; ; v11 = k )
+      {
+        v12 = 99;
+        v13 = 2 * v131;
+        v14 = &pCards[stru_505708[0].arr_44[v11 + dword_4FA9B0[2 * v131]]];
+        v15 = v14->field_38[2];
+        v148 = v14->field_38[2];
+        if ( v144->field_24 >= 10 )
+        {
+          if ( v15 == 99 || v14->field_48[4] == 99 || v14->field_48[15] == 99 || (v19 = BYTE1(v14->field_68), v19 == 99) )
+            v20 = 5 * (v142->field_24 - v144->field_24);
+          else
+            v20 = 5 * (v148 + v14->field_48[4] + v14->field_48[15] + v19);
+          v18 = 2 * v20;
+        }
+        else
+        {
+          if ( v15 == 99 || v14->field_48[4] == 99 || v14->field_48[15] == 99 || (v16 = BYTE1(v14->field_68), v16 == 99) )
+            v17 = 5 * (v142->field_24 - v144->field_24);
+          else
+            v17 = 5 * (v148 + v14->field_48[4] + v14->field_48[15] + v16);
+          v18 = 4 * v17;
+        }
+        dword_4FA9B4[v13] += v18;
+        v21 = v14->field_38[1];
+        v146 = v14->field_38[1];
+        if ( v144->field_28 >= 10 )
+        {
+          if ( v21 == 99
+            || v14->field_48[3] == 99
+            || v14->field_48[14] == 99
+            || (v24 = LOBYTE(v14->field_68), v24 == 99) )
+            v25 = v142->field_28 - v144->field_28;
+          else
+            v25 = v146 + v14->field_48[3] + v14->field_48[14] + v24;
+          v23 = 2 * v25;
+        }
+        else
+        {
+          if ( v21 == 99
+            || v14->field_48[3] == 99
+            || v14->field_48[14] == 99
+            || (v22 = LOBYTE(v14->field_68), v22 == 99) )
+            v23 = 5 * (v142->field_28 - v144->field_28);
+          else
+            v23 = 5 * (v146 + v14->field_48[3] + v14->field_48[14] + v22);
+        }
+        dword_4FA9B4[v13] += v23;
+        dword_4FA9B4[v13] += 7 * (v14->field_38[0] + v14->field_48[2] + v14->field_48[13] + v14->field_58[15]);
+        if ( BYTE2(v14->field_30) == 99
+          || v14->field_38[12] == 99
+          || v14->field_48[7] == 99
+          || (v26 = v14->field_58[9], v26 == 99) )
+          v27 = 5 * (v142->field_2C - v144->field_2C);
+        else
+          v27 = 5 * (BYTE2(v14->field_30) + v14->field_38[12] + v14->field_48[7] + v26);
+        dword_4FA9B4[v13] += 8 * v27;
+        if ( BYTE3(v14->field_30) == 99
+          || v14->field_38[13] == 99
+          || v14->field_48[8] == 99
+          || (v28 = v14->field_58[10], v28 == 99) )
+          v29 = 5 * (v142->field_30 - v144->field_30);
+        else
+          v29 = 5 * (BYTE3(v14->field_30) + v14->field_38[13] + v14->field_48[8] + v28);
+        dword_4FA9B4[v13] += 8 * v29;
+        if ( LOBYTE(v14->field_34) == 99
+          || v14->field_38[14] == 99
+          || v14->field_48[9] == 99
+          || (v30 = v14->field_58[11], v30 == 99) )
+          v31 = 5 * (v142->field_34 - v144->field_34);
+        else
+          v31 = 5 * (LOBYTE(v14->field_34) + v14->field_38[14] + v14->field_48[9] + v30);
+        dword_4FA9B4[v13] += 8 * v31;
+        if ( BYTE1(v14->field_34) == 99
+          || v14->field_38[15] == 99
+          || v14->field_48[10] == 99
+          || (v32 = v14->field_58[12], v32 == 99) )
+          v33 = v142->field_38 - v144->field_38;
+        else
+          v33 = BYTE1(v14->field_34) + v14->field_38[15] + v14->field_48[10] + v32;
+        dword_4FA9B4[v13] += 2 * v33;
+        if ( BYTE2(v14->field_34) == 99
+          || v14->field_48[0] == 99
+          || v14->field_48[11] == 99
+          || (v34 = v14->field_58[13], v34 == 99) )
+          v35 = v142->field_3C - v144->field_3C;
+        else
+          v35 = BYTE2(v14->field_34) + v14->field_48[0] + v14->field_48[11] + v34;
+        dword_4FA9B4[v13] += 2 * v35;
+        if ( BYTE3(v14->field_34) == 99
+          || v14->field_48[1] == 99
+          || v14->field_48[12] == 99
+          || (v36 = v14->field_58[14], v36 == 99) )
+          v37 = v142->field_40 - v144->field_40;
+        else
+          v37 = BYTE3(v14->field_34) + v14->field_48[1] + v14->field_48[12] + v36;
+        dword_4FA9B4[v13] += 2 * v37;
+        if ( v14->field_38[11] == 99 || (v38 = v14->field_58[8], v38 == 99) )
+          dword_4FA9B4[v13] += v144->field_24 - v142->field_24;
+        else
+          dword_4FA9B4[v13] -= v14->field_38[11] + v38;
+        if ( v14->field_38[10] == 99 || (v39 = v14->field_58[7], v39 == 99) )
+          dword_4FA9B4[v13] += v144->field_28 - v142->field_28;
+        else
+          dword_4FA9B4[v13] -= v14->field_38[10] + v39;
+        v40 = v14->field_38[9];
+        v138 = v14->field_38[9];
+        dword_4FA9B4[v13] -= v40 + v14->field_58[6];
+        v41 = v14->field_38[3];
+        v42 = dword_4FA9B4[v13];
+        if ( v41 == 99 )
+          goto LABEL_97;
+        v43 = v14->field_58[0];
+        if ( v43 == 99 )
+          break;
+        v44 = v42 - v43;
+        v12 = 99;
+        dword_4FA9B4[v13] = v44 - v41;
+LABEL_98:
+        if ( v14->field_38[4] == v12 || (v45 = v14->field_58[1], v45 == v12) )
+          dword_4FA9B4[v13] += v144->field_30 - v142->field_30;
+        else
+          dword_4FA9B4[v13] -= v14->field_38[4] + v45;
+        if ( v14->field_38[5] == v12 || (v46 = v14->field_58[2], v46 == v12) )
+          dword_4FA9B4[v13] += v144->field_34 - v142->field_34;
+        else
+          dword_4FA9B4[v13] -= v14->field_38[5] + v46;
+        if ( v14->field_38[6] == v12 || (v47 = v14->field_58[3], v47 == v12) )
+          dword_4FA9B4[v13] += v144->field_38 - v142->field_38;
+        else
+          dword_4FA9B4[v13] -= v14->field_38[6] + v47;
+        if ( v14->field_38[7] == v12 || (v48 = v14->field_58[4], v48 == v12) )
+          dword_4FA9B4[v13] += v144->field_3C - v142->field_3C;
+        else
+          dword_4FA9B4[v13] -= v14->field_38[7] + v48;
+        if ( v14->field_38[8] == v12 || (v49 = v14->field_58[5], v49 == v12) )
+        {
+          v51 = v144;
+          v50 = v142;
+          dword_4FA9B4[v13] += v144->field_40 - v142->field_40;
+        }
+        else
+        {
+          v50 = v142;
+          dword_4FA9B4[v13] -= v14->field_38[8] + v49;
+          v51 = v144;
+        }
+        if ( LOBYTE(v14->field_30) || v14->field_48[5] )
+          dword_4FA9B4[v13] *= 10;
+        if ( LOBYTE(v14->field_24) == 1 )
+        {
+          v52 = LOBYTE(v14->field_28);
+          v53 = v51->field_38;
+        }
+        else
+        {
+          if ( LOBYTE(v14->field_24) == 2 )
+          {
+            v52 = BYTE1(v14->field_28);
+            v53 = v51->field_3C;
+          }
+          else
+          {
+            if ( LOBYTE(v14->field_24) != 3 )
+              goto LABEL_130;
+            v52 = BYTE2(v14->field_28);
+            v53 = v51->field_40;
+          }
+        }
+        v54 = v53 - v52;
+        if ( v54 > 3 )
+          v54 = 3;
+        dword_4FA9B4[v13] += 5 * v54;
+LABEL_130:
+        v55 = v14->field_58[8];
+        v139 = v50->field_24;
+        v125 = v14->field_38[11];
+        if ( v139 <= v55 + v125 )
+          dword_4FA9B4[v13] += 9999;
+        v137 = v50->field_28 + v139;
+        if ( v137 <= v55 + v125 + v14->field_58[6] + v14->field_58[7] + v40 + v14->field_38[10] )
+          dword_4FA9B4[v13] += 9999;
+        if ( v14->field_48[15] + (signed int)BYTE1(v14->field_68) + v144->field_24 + v14->field_48[4] + v148 >= dword_4E1884 )
+          dword_4FA9B4[v13] += 9999;
+        ++v131;
+        if ( v131 >= v135 )
+        {
+          v9 = v129;
+          goto LABEL_138;
+        }
+      }
+      v12 = 99;
+LABEL_97:
+      v40 = v138;
+      dword_4FA9B4[v13] = v42 + v144->field_2C - v142->field_2C;
+      goto LABEL_98;
+    }
+LABEL_138:
+    v56 = v135 - 1;
+    for ( l = v135 - 1; l >= 0; --l )
+    {
+      v137 = 0;
+      if ( l > 0 )
+      {
+        v58 = (int)dword_4FA9B0;
+        v132 = l;
+        v137 = l;
+        do
+        {
+          if ( *(unsigned int *)(v58 + 4) < *(unsigned int *)(v58 + 12) )
+          {
+            v59 = *(unsigned int *)v58;
+            v60 = *(unsigned int *)(v58 + 4);
+            *(unsigned int *)v58 = *(unsigned int *)(v58 + 8);
+            v61 = *(unsigned int *)(v58 + 12);
+            *(unsigned int *)(v58 + 8) = v59;
+            *(unsigned int *)(v58 + 4) = v61;
+            v9 = v129;
+            *(unsigned int *)(v58 + 12) = v60;
+          }
+          v58 += 8;
+          --v132;
+        }
+        while ( v132 );
+      }
+    }
+    v62 = v135 - 1;
+    if ( am_byte_4FAA77 )
+    {
+      if ( v56 >= 0 )
+      {
+        while ( !BYTE3(pCards[stru_505708[0].arr_44[47 * v9 + dword_4FA9B0[2 * v62]]].field_28) )
+        {
+          --v62;
+          if ( v62 < 0 )
+            return am_40BCFB(v9, v137);
+        }
+        v137 = dword_4FA9B0[2 * v62];
+      }
+    }
+    else
+    {
+      v63 = 0;
+      if ( v56 >= 0 )
+      {
+        while ( !BYTE3(pCards[stru_505708[0].arr_44[47 * v9 + dword_4FA9B0[2 * v62]]].field_28) )
+        {
+          --v62;
+          if ( v62 < 0 )
+            goto LABEL_151;
+        }
+        v137 = dword_4FA9B0[2 * v62];
+      }
+LABEL_151:
+      if ( v135 > 0 )
+      {
+        while ( !am_40BF15(v9, dword_4FA9B0[2 * v63]) || dword_4FA9B4[2 * v63] < 0 )
+        {
+          ++v63;
+          if ( v63 >= v135 )
+            return am_40BCFB(v9, v137);
+        }
+        return am_40BE0E(v9, dword_4FA9B0[2 * v63]);
+      }
+    }
+    return am_40BCFB(v9, v137);
+  }
+  v3 = 0;
+  v4 = a1;
+  if ( am_byte_4FAA77 )
+  {
+LABEL_11:
+    v7 = am_40BB49(v4);
+    v8 = rand_interval(0, v7 - 1);
+    result = am_40BCFB(v4, v8);
+  }
+  else
+  {
+    while ( 1 )
+    {
+      v5 = am_40BB49(v4);
+      v6 = rand_interval(0, v5 - 1);
+      if ( am_40BF15(v4, v6) )
+        break;
+      ++v3;
+      if ( v3 >= 10 )
+        goto LABEL_11;
+    }
+    result = am_40BE0E(v4, v6);
+  }
+  return result;
+}
+// 408BB4: could not find valid save-restore pair for ebp
+// 4DF3A4: using guessed type int dword_4DF3A4;
+// 4E1884: using guessed type int dword_4E1884;
+// 4FA9B0: using guessed type int dword_4FA9B0[];
+// 4FA9B4: using guessed type int dword_4FA9B4[];
+// 4FAA00: using guessed type char byte_4FAA00;
+// 4FAA77: using guessed type char am_byte_4FAA77;
+
+
+
+//----- (00409E6A) --------------------------------------------------------
+void ArcomageGame::Loop()
+{
+  int v0; // edx@2
+  int v1; // ecx@14
+  signed int v2; // eax@15
+  stru272 *v3; // esi@17
+  __int16 *v4; // esi@23
+
+  while ( !pArcomageGame->field_F5 )
+  {
+    pArcomageGame->field_F6 = 1;
+    byte_4FAA24 = 1;
+    am_40A346(amuint_4FAA6C);
+LABEL_8:
+    while ( byte_4FAA24 )
+    {
+      amuint_4FABC0 = -1;
+      am_40A283(amuint_4FAA6C, v0);
+      while ( 1 )
+      {
+        byte_4FAA24 = am_40A560(amuint_4FAA6C);
+        if ( am_40BB49(amuint_4FAA6C) <= dword_4E1874 )
+          break;
+        am_byte_4FAA77 = 1;
+        if ( pArcomageGame->field_F4 )
+          goto LABEL_8;
+      }
+      am_byte_4FAA77 = 0;
+    }
+    pArcomageGame->field_F5 = am_40A514();
+    if ( !pArcomageGame->field_F5 )
+      am_40A383();
+    if ( pArcomageGame->field_F4 )
+      pArcomageGame->field_F5 = 1;
+  }
+  am_40D444();
+  if ( byte_4FAA2C )
+  {
+    v2 = retzero_sub_40DFA7((int)dword_4FAA28);
+    v1 = 1000;
+    dword_4FAA70 = v2 / 1000;
+  }
+  else
+  {
+    dword_4FAA70 = -1;
+  }
+  pVideoPlayer->BinkUpdatePalette(dword_4FAA28);
+  v3 = array_4FAC10;
+  do
+  {
+    v3->ptr_0->_40E0F5(1, 1);
+    v3->ptr_0->_40DFFE();
+    ++v3;
+  }
+  while ( (signed int)v3 < (signed int)&unk_5052C8 );
+  if (pAsyncMouse)
+  {
+    pAsyncMouse->_409E3D(*((unsigned char *)pAsyncMouse + 103));
+    pAsyncMouse->_46B944();
+  }
+  pArcomageGame->pGameBackground.Release();
+  pArcomageGame->pSprites.Release();
+  pArcomageGame->bGameInProgress = 0;
+  viewparams->bRedrawGameUI = 1;
+  if ( pVideoPlayer->AnyMovieLoaded() )
+    pVideoPlayer->_4BF5B2();
+  v4 = am_sounds;
+  do
+  {
+    pSoundList->_4A9DCD((unsigned __int16)*v4, 1);
+    ++v4;
+  }
+  while ( (signed int)v4 <= (signed int)&unk_4FAA20 );
+}
+// 40DFA7: using guessed type uint __stdcall retzero_sub_40DFA7(uint);
+// 4E1874: using guessed type int dword_4E1874;
+// 4FAA24: using guessed type char byte_4FAA24;
+// 4FAA2C: using guessed type char byte_4FAA2C;
+// 4FAA70: using guessed type int dword_4FAA70;
+// 4FAA77: using guessed type char am_byte_4FAA77;
+
+//----- (00409FE9) --------------------------------------------------------
+char __cdecl am_409FE9()
+{
+  signed int v0; // edi@1
+  signed int v1; // esi@4
+  int *v2; // ecx@7
+  int *v3; // eax@7
+  signed int v4; // edx@7
+  int v5; // edx@13
+  signed int v6; // ecx@13
+  signed int v7; // eax@13
+
+  amuint_4FAA6C = dword_505890;
+  sub_409BE8();
+  v0 = 0;
+  do
+  {
+    if ( v0 )
+    {
+      v1 = v0;
+      inv_strcpy(pArcomageGame->pPlayer2Name, stru_505708[v0].pPlayerName);
+      if ( byte_4E185C )
+        LOBYTE(stru_505708[v1].field_20) = 0;
+      else
+        LOBYTE(stru_505708[v1].field_20) = 1;
+    }
+    else
+    {
+      inv_strcpy(pArcomageGame->pPlayer1Name, (char *)stru_505708);
+      LOBYTE(stru_505708[0].field_20) = 1;
+    }
+    stru_505708[v0].field_24 = amuint_4E1860;
+    stru_505708[v0].field_28 = amuint_4E1864;
+    stru_505708[v0].field_2C = amuint_4E1868;
+    stru_505708[v0].field_30 = amuint_4E186C;
+    stru_505708[v0].field_34 = amuint_4E1870;
+    stru_505708[v0].field_38 = amuint_505884;
+    stru_505708[v0].field_3C = amuint_505888;
+    stru_505708[v0].field_40 = amuint_50588C;
+    v2 = &stru_505708[v0].arr_6C[0][1];
+    v3 = stru_505708[v0].arr_44;
+    v4 = 10;
+    do
+    {
+      *v3 = -1;
+      if ( am_byte_4E185D )
+      {
+        *(v2 - 1) = -1;
+        *v2 = -1;
+      }
+      else
+      {
+        *(v2 - 1) = 0;
+        *v2 = 0;
+      }
+      ++v3;
+      v2 += 2;
+      --v4;
+    }
+    while ( v4 );
+    ++v0;
+  }
+  while ( v0 < 2 );
+  inv_strcpy(pDeckMaster, byte_5054C8);
+  v5 = 0;
+  v6 = (signed int)dword_505554;
+  v7 = -2;
+  do
+  {
+    byte_5054E8[v7 + 2] = 0;
+    *(unsigned int *)v6 = v5;
+    switch ( v7 )
+    {
+      default:
+        ++v5;
+        break;
+      case 0:
+      case 2:
+      case 6:
+      case 9:
+      case 13:
+      case 18:
+      case 23:
+      case 33:
+      case 36:
+      case 38:
+      case 44:
+      case 46:
+      case 52:
+      case 57:
+      case 69:
+      case 71:
+      case 75:
+      case 79:
+      case 81:
+      case 84:
+      case 89:
+        break;
+    }
+    v6 += 4;
+    ++v7;
+  }
+  while ( v6 < (signed int)&unk_505704 );
+  return am_40A198();
+}
+// 4E185C: using guessed type char byte_4E185C;
+// 4E185D: using guessed type char am_byte_4E185D;
+// 4E1860: using guessed type int amuint_4E1860;
+// 4E1864: using guessed type int amuint_4E1864;
+// 4E1868: using guessed type int amuint_4E1868;
+// 4E186C: using guessed type int amuint_4E186C;
+// 4E1870: using guessed type int amuint_4E1870;
+// 505554: using guessed type int dword_505554[];
+// 505884: using guessed type int amuint_505884;
+// 505888: using guessed type int amuint_505888;
+// 50588C: using guessed type int amuint_50588C;
+// 505890: using guessed type int dword_505890;
+
+//----- (0040A198) --------------------------------------------------------
+char __cdecl am_40A198()
+{
+  int *v0; // edi@1
+  int *v1; // edx@2
+  signed int v2; // esi@2
+  signed int v3; // eax@4
+  signed int v4; // esi@12
+  int v5; // eax@13
+  int v6; // edx@13
+  char *v7; // eax@13
+  char result; // al@14
+  char v9[108]; // [sp+8h] [bp-6Ch]@1
+
+  ArcomageGame::PlaySound(0x14u);
+  memset(byte_5054E8, 0, sizeof(byte_5054E8));
+  memset(v9, 0, sizeof(v9));
+  v0 = stru_505708[0].arr_44;
+  do
+  {
+    v1 = v0;
+    v2 = 10;
+    do
+    {
+      if ( *v1 > -1 )
+      {
+        v3 = 0;
+        while ( dword_505554[v3] != *v1 || byte_5054E8[v3] )
+        {
+          ++v3;
+          if ( v3 >= 108 )
+            goto LABEL_10;
+        }
+        byte_5054E8[v3] = 1;
+      }
+LABEL_10:
+      ++v1;
+      --v2;
+    }
+    while ( v2 );
+    v0 += 47;
+  }
+  while ( (signed int)v0 < (signed int)&pArcomageGame->msg.pt.y );
+  v4 = 0;
+  do
+  {
+    do
+    {
+      v5 = rand();
+      v6 = v5 % 108;
+      v7 = &v9[v5 % 108];
+    }
+    while ( *v7 == 1 );
+    *v7 = 1;
+    dword_505314[v4] = dword_505554[v6];
+    result = byte_5054E8[v6];
+    array_4FAC10[9].field_4[v4++ + 4232] = result;
+  }
+  while ( v4 < 108 );
+  dword_4FABC8 = 0;
+  amuint_4FABC4 = -1;
+  pArcomageGame->field_F6 = 1;
+  return result;
+}
+// 4FABC4: using guessed type int amuint_4FABC4;
+// 4FABC8: using guessed type int dword_4FABC8;
+// 505314: using guessed type int dword_505314[];
+// 505554: using guessed type int dword_505554[];
+// 40A198: using guessed type char var_6C[108];
+
+//----- (0040A255) --------------------------------------------------------
+int __fastcall am_40A255(int a1, int a2)
+{
+  int i; // edi@1
+  signed int v3; // esi@2
+  int result; // eax@3
+
+  for ( i = 0; i < dword_4E1874; ++i )
+  {
+    v3 = 0;
+    do
+      result = am_40A283(v3++, a2);
+    while ( v3 < 2 );
+  }
+  pArcomageGame->field_F6 = 1;
+  return result;
+}
+// 4E1874: using guessed type int dword_4E1874;
+
+//----- (0040A283) --------------------------------------------------------
+signed int __fastcall am_40A283(int a1, int a2)
+{
+  signed int v2; // eax@1
+  int v3; // edi@1
+  int v4; // esi@1
+  char v5; // bl@1
+  signed int result; // eax@7
+  int v7; // esi@8
+
+  v2 = dword_4FABC8;
+  v3 = a1;
+  v4 = a1;
+  v5 = 0;
+  do
+  {
+    if ( v2 >= 108 )
+    {
+      am_40A198();
+      v2 = dword_4FABC8;
+    }
+    if ( !array_4FAC10[9].field_4[v2 + 4232] )
+    {
+      v3 = dword_505314[v2];
+      v5 = 1;
+    }
+    ++v2;
+    dword_4FABC8 = v2;
+  }
+  while ( !v5 );
+  ArcomageGame::PlaySound(0x15u);
+  result = am_40A324(v4);
+  if ( result != -1 )
+  {
+    amuint_4FAA4C = result;
+    stru_505708[0].arr_44[result + 47 * v4] = v3;
+    v7 = 188 * v4 + 8 * result;
+    *(int *)((char *)stru_505708[0].arr_6C[0] + v7) = rand_interval(-4, 4);
+    result = rand_interval(-4, 4);
+    *(int *)((char *)&stru_505708[0].arr_6C[0][1] + v7) = result;
+    pArcomageGame->field_F6 = 1;
+    byte_4FAA2D = 1;
+  }
+  return result;
+}
+// 4FAA2D: using guessed type char byte_4FAA2D;
+// 4FAA4C: using guessed type int amuint_4FAA4C;
+// 4FABC8: using guessed type int dword_4FABC8;
+// 505314: using guessed type int dword_505314[];
+
+//----- (0040A324) --------------------------------------------------------
+signed int __fastcall am_40A324(int a1)
+{
+  signed int result; // eax@1
+  signed int v2; // edx@1
+  char *v3; // ecx@1
+
+  result = -1;
+  v2 = 0;
+  v3 = (char *)stru_505708[a1].arr_44;
+  while ( *(unsigned int *)v3 != -1 )
+  {
+    ++v2;
+    v3 += 4;
+    if ( v2 >= 10 )
+      return result;
+  }
+  return v2;
+}
+
+//----- (0040A346) --------------------------------------------------------
+int __fastcall am_40A346(int a1)
+{
+  int v1; // ecx@1
+  int result; // eax@1
+
+  v1 = a1;
+  stru_505708[v1].field_38 += dword_4E1878 + stru_505708[v1].field_2C;
+  stru_505708[v1].field_3C += dword_4E187C + stru_505708[v1].field_30;
+  result = dword_4E1880 + stru_505708[v1].field_34;
+  stru_505708[v1].field_40 += result;
+  return result;
+}
+// 4E1878: using guessed type int dword_4E1878;
+// 4E187C: using guessed type int dword_4E187C;
+// 4E1880: using guessed type int dword_4E1880;
+
+//----- (0040A383) --------------------------------------------------------
+void __cdecl am_40A383()
+{
+  int v0; // eax@4
+  int v1; // ecx@4
+  unsigned __int8 v2; // sf@4
+  unsigned __int8 v3; // of@4
+  int v4; // eax@6
+  char Dest[64]; // [sp+4h] [bp-64h]@4
+  int v6; // [sp+44h] [bp-24h]@6
+  int v7; // [sp+48h] [bp-20h]@6
+  int v8; // [sp+4Ch] [bp-1Ch]@6
+  int v9; // [sp+50h] [bp-18h]@6
+  ArcomageGame_stru1 v10; // [sp+54h] [bp-14h]@7
+  int v11[2]; // [sp+60h] [bp-8h]@4
+
+  if ( !pArcomageGame->field_F4 )
+  {
+    if ( LOBYTE(stru_505708[0].field_20) != 1 || LOBYTE(stru_505708[1].field_20) != 1 )
+    {
+      ++amuint_4FAA6C;
+      am_byte_4FAA75 = 1;
+      if ( amuint_4FAA6C >= 2 )
+        amuint_4FAA6C = 0;
+    }
+    else
+    {
+      //nullsub_1();
+      v11[0] = 0;
+      v11[1] = 0;
+      inv_strcpy("Ñëåä", Dest);
+      v0 = 0;
+      v11[1] = 200;
+      v11[0] = 320 - 12 * v0 / 2;
+      pPrimaryWindow_draws_text(-1, Dest, v11);
+      am_byte_4FAA75 = 1;
+      v1 = amuint_4FAA6C + 1;
+      v3 = __OFSUB__(amuint_4FAA6C + 1, 2);
+      v2 = amuint_4FAA6C++ - 1 < 0;
+      if ( !(v2 ^ v3) )
+      {
+        v1 = 0;
+        amuint_4FAA6C = 0;
+      }
+      inv_strcpy(stru_505708[v1].pPlayerName, Dest);
+      v4 = 0;
+      v11[1] = 260;
+      v11[0] = 320 - 12 * v4 / 2;
+      pPrimaryWindow_draws_text(-1, Dest, v11);
+      v6 = 0;
+      v8 = 640;
+      v7 = 0;
+      v9 = 480;
+      //nullsub_1();
+      CallRenderPresent();
+      //nullsub_1();
+      while ( 1 )
+      {
+        while ( 1 )
+        {
+          while ( !ArcomageGame::MsgLoop(20, &v10) )
+            ;
+          if ( v10.field_0 != 1 )
+            break;
+          if ( v10.field_4 )
+            goto LABEL_13;
+          //nullsub_1();
+        }
+        if ( v10.field_0 > 4 )
+        {
+          if ( v10.field_0 <= 8 )
+            goto LABEL_13;
+          if ( v10.field_0 == 10 )
+            break;
+        }
+      }
+      pArcomageGame->field_F4 = 1;
+      byte_4FAA74 = 1;
+LABEL_13:
+      v11[0] = 0;
+      v11[1] = 0;
+      v6 = 0;
+      v8 = 640;
+      v7 = 0;
+      v9 = 480;
+      //nullsub_1();
+      CallRenderPresent();
+    }
+  }
+}
+
+
+//----- (0040A514) --------------------------------------------------------
+bool __cdecl am_40A514()
+{
+  bool result; // eax@1
+  char *v1; // ecx@1
+
+  LOBYTE(result) = 0;
+  v1 = (char *)&stru_505708[0].field_24;
+  do
+  {
+    if ( *(unsigned int *)v1 <= 0 )
+      LOBYTE(result) = 1;
+    if ( *(unsigned int *)v1 >= dword_4E1884 )
+      LOBYTE(result) = 1;
+    if ( *((unsigned int *)v1 + 5) >= dword_4E1888
+      || *((unsigned int *)v1 + 6) >= dword_4E1888
+      || *((unsigned int *)v1 + 7) >= dword_4E1888 )
+      LOBYTE(result) = 1;
+    v1 += 188;
+  }
+  while ( (signed int)v1 < (signed int)&pArcomageGame->stru1.field_4 );
+  if ( result )
+    byte_4FAA2C = 1;
+  return result;
+}
+// 4E1884: using guessed type int dword_4E1884;
+// 4E1888: using guessed type int dword_4E1888;
+// 4FAA2C: using guessed type char byte_4FAA2C;
+
+//----- (0040A560) --------------------------------------------------------
+char am_40A560(unsigned int _this)
+{
+  int v1; // ebp@0
+  unsigned __int64 v2; // qax@3
+  unsigned __int64 v3; // kr00_8@3
+  int v4; // ecx@17
+  int v5; // esi@67
+  char Dest[100]; // [sp+8h] [bp-A8h]@67
+  int v8; // [sp+6Ch] [bp-44h]@3
+  int pSrcXYZW[4]; // [sp+70h] [bp-40h]@75
+  int v10[4]; // [sp+80h] [bp-30h]@69
+  int pTargetXY[2]; // [sp+90h] [bp-20h]@75
+  ArcomageGame_stru1 a2; // [sp+98h] [bp-18h]@8
+  int v13; // [sp+A4h] [bp-Ch]@1
+  int a1; // [sp+A8h] [bp-8h]@1
+  char v15; // [sp+AEh] [bp-2h]@63
+  char v16; // [sp+AFh] [bp-1h]@1
+
+  uCardID = -1;
+  a1 = _this;
+  v16 = 0;
+  v13 = 20;
+  byte_4FAA00 = 0;
+  dword_4FAA68 = 0;
+  amuint_4FAA38 = 10;
+  amuint_4FAA34 = 5;
+  if ( amuint_4FAA4C != -1 )
+    byte_4FAA2D = 1;
+  do
+  {
+    do
+    {
+      do
+      {
+        v2 = pEventTimer->Time();
+        v3 = v2 - pArcomageGame->event_timer_time;
+        v8 = HIDWORD(v3);
+      }
+      while ( SHIDWORD(v3) < 0 );
+    }
+    while ( SHIDWORD(v2) < (signed int)(((unsigned int)v2 < pArcomageGame->event_timer_time)
+                                      + ((unsigned __int64)pArcomageGame->event_timer_time >> 32)) | HIDWORD(v3) == 0
+         && (unsigned int)v3 < 6 );
+    pArcomageGame->event_timer_time = pEventTimer->Time();
+    if ( pArcomageGame->field_F4 )
+      v16 = 1;
+    ArcomageGame::MsgLoop(0, &a2);
+    switch ( a2.field_0 )
+    {
+      case 2:
+        if ( a2.field_4 == 129 && a2.field_8 == 1 )
+        {
+          pAudioPlayer->StopChannels(-1, -1);
+          dword_4FAA68 = 0;
+          goto LABEL_16;
+        }
+        break;
+      case 9:
+        pArcomageGame->field_F6 = 1;
+        break;
+      case 0xA:
+        pAudioPlayer->StopChannels(-1, -1);
+        byte_4FAA74 = 1;
+LABEL_16:
+        v16 = 1;
+        pArcomageGame->field_F4 = 1;
+        break;
+    }
+    v4 = amuint_4FAA6C;
+    if ( LOBYTE(stru_505708[amuint_4FAA6C].field_20) != 1 && !byte_4FAA00 && !byte_4FAA2E && !byte_4FAA2D )
+    {
+      if ( am_byte_4FAA75 )
+        am_byte_4FAA76 = 1;
+      am_408BB4(amuint_4FAA6C);
+      v4 = amuint_4FAA6C;
+      byte_4FAA2E = 1;
+    }
+    if ( amuint_4FAA4C != -1 && amuint_4FAA38 > 10 )
+      amuint_4FAA38 = 10;
+    if ( byte_4FAA2E || byte_4FAA2D || LOBYTE(stru_505708[v4].field_20) != 1 )
+    {
+      pArcomageGame->field_F6 = 1;
+      if ( byte_4FAA2D )
+      {
+        --amuint_4FAA38;
+        if ( amuint_4FAA38 < 0 )
+        {
+          byte_4FAA2D = 0;
+          amuint_4FAA38 = 10;
+          v16 = 0;
+        }
+      }
+      if ( byte_4FAA2E )
+      {
+        --v13;
+        if ( v13 < 0 )
+        {
+          if ( dword_4FAA68 > 1 )
+          {
+            --dword_4FAA68;
+            byte_4FAA00 = 0;
+          }
+          else
+          {
+            v16 = 1;
+          }
+          byte_4FAA2E = 0;
+          v13 = 20;
+        }
+      }
+    }
+    else
+    {
+      if ( am_byte_4FAA77 )
+      {
+        if ( a2.field_0 == 7 && am_40BCFB(a1, dword_4FABBC) )
+        {
+          if ( am_byte_4FAA75 )
+            am_byte_4FAA76 = 1;
+          if ( dword_4FAA64 > 0 )
+          {
+            --dword_4FAA64;
+            am_byte_4FAA77 = am_40BB49(a1) > dword_4E1874;
+          }
+          byte_4FAA2E = 1;
+        }
+        if ( a2.field_0 == 8 && am_40BCFB(a1, dword_4FABBC) )
+        {
+          if ( am_byte_4FAA75 )
+            am_byte_4FAA76 = 1;
+          if ( dword_4FAA64 > 0 )
+          {
+            --dword_4FAA64;
+            am_byte_4FAA77 = am_40BB49(a1) > dword_4E1874;
+          }
+          byte_4FAA2E = 1;
+        }
+      }
+      else
+      {
+        if ( a2.field_0 == 7 )
+        {
+          if ( am_40BE0E(a1, dword_4FABBC) )
+          {
+            byte_4FAA2E = 1;
+            if ( am_byte_4FAA75 )
+              am_byte_4FAA76 = 1;
+          }
+        }
+        if ( a2.field_0 == 8 )
+        {
+          if ( am_40BCFB(a1, dword_4FABBC) )
+          {
+            byte_4FAA2E = 1;
+            if ( am_byte_4FAA75 )
+              am_byte_4FAA76 = 1;
+          }
+        }
+      }
+    }
+    //nullsub_1();
+    if ( false )
+    {
+      if ( !v15 )
+      {
+        //nullsub_1();
+        v15 = 1;
+      }
+    }
+    else
+    {
+      v15 = 0;
+    }
+    if ( false )
+    {
+      //nullsub_1();
+      //nullsub_1();
+      inv_strcpy(pAreYouSureWishToLeave, Dest);
+      v5 = 0;//unk::const_0(&unk_4E19FC, 0);
+      //nullsub_1();
+      if ( v5 == 1 )
+      {
+        pAudioPlayer->StopChannels(-1, -1);
+        v16 = 1;
+        pArcomageGame->field_F4 = 1;
+        dword_4FAA68 = 0;
+      }
+      v10[0] = 0;
+      v10[2] = 640;
+      v10[1] = 0;
+      v10[3] = 480;
+      //nullsub_1();
+    }
+    if ( dword_4FABB8 != am_40BB67(a1) )
+    {
+      dword_4FABB8 = am_40BB67(a1);
+      pArcomageGame->field_F6 = 1;
+    }
+    if ( pArcomageGame->field_F6 )
+    {
+      am_blts(v13);
+      DoBlt_Copy(pArcomageGame->pBackgroundPixels);
+      pArcomageGame->field_F6 = 0;
+    }
+    if ( pArcomageGame->field_F9 )
+    {
+      pTargetXY[0] = 0;
+      pTargetXY[1] = 0;
+      pSrcXYZW[0] = 0;
+      pSrcXYZW[2] = 640;
+      pSrcXYZW[1] = 0;
+      pSrcXYZW[3] = 480;
+      am_BeginScene(pArcomageGame->pBackgroundPixels, -1, 1);
+      Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, 2);
+      am_EndScene();
+      am_blts(v13);
+      pRenderer->Present();
+      pArcomageGame->field_F9 = 0;
+    }
+  }
+  while ( !v16 );
+  return dword_4FAA68 > 0;
+}
+// 40DB22: using guessed type uint __stdcall unk__const_0(uint, uint);
+// 4E1874: using guessed type int dword_4E1874;
+// 4FAA00: using guessed type char byte_4FAA00;
+// 4FAA2D: using guessed type char byte_4FAA2D;
+// 4FAA2E: using guessed type char byte_4FAA2E;
+// 4FAA34: using guessed type int amuint_4FAA34;
+// 4FAA38: using guessed type int amuint_4FAA38;
+// 4FAA4C: using guessed type int amuint_4FAA4C;
+// 4FAA64: using guessed type int dword_4FAA64;
+// 4FAA68: using guessed type int dword_4FAA68;
+// 4FAA74: using guessed type char byte_4FAA74;
+// 4FAA75: using guessed type char am_byte_4FAA75;
+// 4FAA76: using guessed type char am_byte_4FAA76;
+// 4FAA77: using guessed type char am_byte_4FAA77;
+// 4FABB8: using guessed type int dword_4FABB8;
+
+//----- (0040A9AF) --------------------------------------------------------
+void __thiscall am_blts(int a1)
+{
+  int v1; // esi@1
+  stru272_stru0 **v2; // esi@1
+
+  v1 = a1;
+  am_BeginScene(pArcomageGame->pSpritesPixels, -1, 1);
+  am_chroma_blts();
+  am_EndScene();
+  am_BeginScene(pArcomageGame->pSpritesPixels, -1, 1);
+  am_40B4B9();
+  am_chroma_and_copy_blts();
+  am_chroma_blt();
+  am_DrawUI();
+  am_EndScene();
+  am_BeginScene(pArcomageGame->pSpritesPixels, -1, 1);
+  am_40B76F(v1);
+  v2 = (stru272_stru0 **)array_4FAC10;
+  do
+  {
+    if ( *((unsigned char *)v2 - 64) )
+      (*v2)->_40E133();
+    v2 += 1067;
+  }
+  while ( (signed int)v2 < (signed int)&unk_5052C8 );
+  dword_4FABBC = am_40BB67(amuint_4FAA6C);
+  am_40AA4E();
+  am_EndScene();
+}
+
+//----- (0040AA4E) --------------------------------------------------------
+void __cdecl am_40AA4E()
+{
+  signed int v0; // ebx@1
+  char v1; // ch@2@3
+  char *v2; // esi@4
+  signed int v3; // edi@6
+  int *v4; // esi@6
+  int v5; // [sp-4h] [bp-2Ch]@4
+  int v6; // [sp+Ch] [bp-1Ch]@10
+  int v7; // [sp+10h] [bp-18h]@10
+  int v8; // [sp+14h] [bp-14h]@10
+  int v9; // [sp+18h] [bp-10h]@10
+  int v10; // [sp+1Ch] [bp-Ch]@6
+  char v11; // [sp+20h] [bp-8h]@1
+  char v12; // [sp+21h] [bp-7h]@1
+  char v13; // [sp+22h] [bp-6h]@1
+  char v14; // [sp+24h] [bp-4h]@1
+  char v15; // [sp+25h] [bp-3h]@1
+  char v16; // [sp+26h] [bp-2h]@1
+
+  v14 = 0;
+  v15 = -1;
+  v16 = 0;
+  v11 = -1;
+  v12 = 0;
+  v13 = 0;
+  v0 = (signed int)byte_4FABD1;
+  do
+  {
+    if ( *(unsigned char *)(v0 - 1) && (*(stru272_stru0 **)(v0 + 63))->_40E2A7() == 2 )
+    {
+      BYTE3(v5) = v1;
+      v2 = &v14;
+      if ( !*(unsigned char *)v0 )
+        v2 = &v11;
+      LOWORD(v5) = *(_WORD *)v2;
+      BYTE2(v5) = v2[2];
+      v10 = (unsigned __int16)R8G8B8_to_TargetFormat(v5);
+      v3 = 0;
+      v4 = (int *)(v0 + 71);
+      do
+      {
+        if ( *(v4 - 1) > 0 )
+        {
+          if ( v3 % 2 )
+          {
+            Render::SetPixel((Vec2_int_ *)v4, v10);
+          }
+          else
+          {
+            v6 = *v4;
+            v8 = v6 + 2;
+            v7 = v4[1];
+            v9 = v7 + 2;
+            DrawRect((Vec4_int_ *)&v6, v10, 1);
+          }
+        }
+        ++v3;
+        v4 += 7;
+      }
+      while ( v3 < 150 );
+    }
+    v0 += 4268;
+  }
+  while ( v0 < (signed int)&array_4FAC10[9].field_4[4201] );
+}
+
+//----- (0040AB0A) --------------------------------------------------------
+void __cdecl am_chroma_blts()
+{
+  int v0; // eax@1
+  int v1; // eax@1
+  int v2; // eax@1
+  int v3; // eax@1
+  int v4; // eax@1
+  int v5; // eax@1
+  int pSrcXYZW[4]; // [sp+Ch] [bp-18h]@1
+  int pTargetXY[2]; // [sp+1Ch] [bp-8h]@1
+
+  pSrcXYZW[1] = 0;
+  pSrcXYZW[0] = 765;
+  pSrcXYZW[2] = 843;
+  pSrcXYZW[3] = 216;
+  pTargetXY[0] = 8;
+  pTargetXY[1] = 56;
+  Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, 2);
+  pTargetXY[0] = 555;
+  pTargetXY[1] = 56;
+  Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, 2);
+  LOWORD(v0) = pArcomageGame->field_54;
+  pTargetXY[0] = 8;
+  pSrcXYZW[0] = 283;
+  pSrcXYZW[2] = 361;
+  pSrcXYZW[1] = 166;
+  pSrcXYZW[3] = 190;
+  pTargetXY[1] = 13;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v0, 2);
+  LOWORD(v1) = pArcomageGame->field_54;
+  pTargetXY[0] = 555;
+  pTargetXY[1] = 13;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v1, 2);
+  LOWORD(v2) = pArcomageGame->field_54;
+  pSrcXYZW[0] = 234;
+  pSrcXYZW[2] = 283;
+  pSrcXYZW[1] = 166;
+  pSrcXYZW[3] = 190;
+  pTargetXY[0] = 100;
+  pTargetXY[1] = 296;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v2, 2);
+  LOWORD(v3) = pArcomageGame->field_54;
+  pTargetXY[0] = 492;
+  pTargetXY[1] = 296;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v3, 2);
+  LOWORD(v4) = pArcomageGame->field_54;
+  pSrcXYZW[0] = 192;
+  pSrcXYZW[2] = 234;
+  pSrcXYZW[1] = 166;
+  pSrcXYZW[3] = 190;
+  pTargetXY[0] = 168;
+  pTargetXY[1] = 296;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v4, 2);
+  pTargetXY[0] = 430;
+  LOWORD(v5) = pArcomageGame->field_54;
+  pTargetXY[1] = 296;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v5, 2);
+}
+
+//----- (0040AC5F) --------------------------------------------------------
+void __cdecl am_DrawUI()
+{
+  int v0; // ecx@7
+  int v1; // ecx@9
+  int v2; // eax@11
+  int v3; // ecx@12
+  int v4; // eax@14
+  int v5; // ecx@14
+  int v6; // eax@16
+  int v7; // ecx@16
+  int v8; // eax@18
+  int v9; // ecx@18
+  int v10; // eax@20
+  char Dest[32]; // [sp+Ch] [bp-28h]@2
+  int v12[2]; // [sp+2Ch] [bp-8h]@2
+
+  if ( am_byte_4FAA77 )
+  {
+    inv_strcpy(pGlobalTXT_LocalizationStrings[266], Dest);// DISCARD A CARD
+    v12[0] = 320 - pArcomageGame->pFont2->GetLineWidth(Dest) / 2;
+    v12[1] = 306;
+    pPrimaryWindow_draws_text(-1, Dest, v12);
+  }
+  inv_strcpy((const char *)stru_505708, Dest);
+  if ( !amuint_4FAA6C )
+    inv_strcat("***", Dest);
+  v12[0] = 47 - pArcomageGame->pFont1->GetLineWidth(Dest) / 2;
+  v12[1] = 21;
+  pPrimaryWindow_draws_text(-1, Dest, v12);
+  inv_strcpy(stru_505708[1].pPlayerName, Dest);
+  if ( amuint_4FAA6C == 1 )
+    inv_strcat("***", Dest);
+  v12[0] = 595 - pArcomageGame->pFont1->GetLineWidth(Dest) / 2;
+  v12[1] = 21;
+  pPrimaryWindow_draws_text(-1, Dest, v12);
+  intToString(stru_505708[0].field_24, Dest);
+  v12[0] = 123 - pArcomageGame->pFont1->GetLineWidth(Dest) / 2;
+  v12[1] = 305;
+  pPrimaryWindow_draws_text(-1, Dest, v12);
+  intToString(stru_505708[1].field_24, Dest);
+  v12[0] = 515 - pArcomageGame->pFont1->GetLineWidth(Dest) / 2;
+  v12[1] = 305;
+  pPrimaryWindow_draws_text(-1, Dest, v12);
+  intToString(stru_505708[0].field_28, Dest);
+  v12[0] = 188 - pArcomageGame->pFont1->GetLineWidth(Dest) / 2;
+  v12[1] = 305;
+  pPrimaryWindow_draws_text(-1, Dest, v12);
+  intToString(stru_505708[1].field_28, Dest);
+  v12[0] = 451 - pArcomageGame->pFont1->GetLineWidth(Dest) / 2;
+  v12[1] = 305;
+  pPrimaryWindow_draws_text(-1, Dest, v12);
+  v0 = stru_505708[0].field_2C;
+  if ( byte_4E185E )
+    v0 = dword_4E1878 + stru_505708[0].field_2C;
+  intToString(v0, Dest);
+  v12[0] = 14 - 6 * 0 / 2;
+  v12[1] = 92;
+  am_40B102(-1, Dest, v12);
+  v1 = stru_505708[1].field_2C;
+  if ( byte_4E185E )
+    v1 = dword_4E1878 + stru_505708[1].field_2C;
+  intToString(v1, Dest);
+  v2 = 0;
+  v12[1] = 92;
+  v12[0] = 561 - 6 * v2 / 2;
+  am_40B102(-1, Dest, v12);
+  if ( byte_4E185E )
+    v3 = stru_505708[0].field_30 + dword_4E187C;
+  else
+    v3 = stru_505708[0].field_30;
+  intToString(v3, Dest);
+  v4 = 0;
+  v12[1] = 164;
+  v12[0] = 14 - 6 * v4 / 2;
+  am_40B102(-1, Dest, v12);
+  v5 = stru_505708[1].field_30;
+  if ( byte_4E185E )
+    v5 = dword_4E187C + stru_505708[1].field_30;
+  intToString(v5, Dest);
+  v6 = 0;
+  v12[1] = 164;
+  v12[0] = 561 - 6 * v6 / 2;
+  am_40B102(-1, Dest, v12);
+  v7 = stru_505708[0].field_34;
+  if ( byte_4E185E )
+    v7 = dword_4E1880 + stru_505708[0].field_34;
+  intToString(v7, Dest);
+  v8 = 0;
+  v12[1] = 236;
+  v12[0] = 14 - 6 * v8 / 2;
+  am_40B102(-1, Dest, v12);
+  v9 = stru_505708[1].field_34;
+  if ( byte_4E185E )
+    v9 = dword_4E1880 + stru_505708[1].field_34;
+  intToString(v9, Dest);
+  v10 = 0;
+  v12[1] = 236;
+  v12[0] = 561 - 6 * v10 / 2;
+  am_40B102(-1, Dest, v12);
+  intToString(stru_505708[0].field_38, Dest);
+  v12[1] = 114;
+  v12[0] = 10;
+  am_40B17E(-1, (int)Dest, v12);
+  intToString(stru_505708[1].field_38, Dest);
+  v12[0] = 557;
+  v12[1] = 114;
+  am_40B17E(-1, (int)Dest, v12);
+  intToString(stru_505708[0].field_3C, Dest);
+  v12[0] = 10;
+  v12[1] = 186;
+  am_40B1F3(-1, (int)Dest, (int)v12);
+  intToString(stru_505708[1].field_3C, Dest);
+  v12[0] = 557;
+  v12[1] = 186;
+  am_40B1F3(-1, (int)Dest, (int)v12);
+  intToString(stru_505708[0].field_40, Dest);
+  v12[0] = 10;
+  v12[1] = 258;
+  am_40B268(-1, Dest, v12);
+  intToString(stru_505708[1].field_40, Dest);
+  v12[0] = 557;
+  v12[1] = 258;
+  am_40B268(-1, Dest, v12);
+}
+// 4E185E: using guessed type char byte_4E185E;
+// 4E1878: using guessed type int dword_4E1878;
+// 4E187C: using guessed type int dword_4E187C;
+// 4E1880: using guessed type int dword_4E1880;
+// 4FAA77: using guessed type char am_byte_4FAA77;
+
+//----- (0040B102) --------------------------------------------------------
+void __fastcall am_40B102(int a1, char *a2, int *pXY)
+{
+  char *v3; // esi@1
+  int v4; // eax@1
+  unsigned __int8 v5; // bl@2
+  char v6; // zf@2
+  int v7; // eax@3
+  int v8; // ecx@3
+  int v9; // [sp+8h] [bp-18h]@3
+  int v10; // [sp+Ch] [bp-14h]@3
+  int v11; // [sp+10h] [bp-10h]@3
+  int v12; // [sp+14h] [bp-Ch]@3
+  int v13; // [sp+18h] [bp-8h]@1
+  int v14; // [sp+1Ch] [bp-4h]@1
+
+  v3 = a2;
+  am_BeginScene(pArcomageGame->pSpritesPixels, -1, 1);
+  v4 = pXY[1];
+  v13 = *pXY;
+  v14 = v4;
+  do
+  {
+    v5 = *v3++;
+    v6 = v5 == 0;
+    if ( v5 )
+    {
+      v7 = 22 * v5;
+      v8 = v7 - 864;
+      v7 -= 842;
+      v11 = v7;
+      LOWORD(v7) = pArcomageGame->field_54;
+      v9 = v8;
+      v10 = 190;
+      v12 = 207;
+      Blt_Chroma((ArcomageRect *)&v9, &v13, v7, 1);
+      v13 += 22;
+      v6 = v5 == 0;
+    }
+  }
+  while ( !v6 );
+  am_EndScene();
+}
+
+//----- (0040B17E) --------------------------------------------------------
+void __fastcall am_40B17E(int a1, int a2, int *pXY)
+{
+  int v3; // esi@1
+  int v4; // eax@1
+  unsigned __int8 v5; // bl@2
+  char v6; // zf@2
+  int v7; // eax@3
+  int v8; // [sp+8h] [bp-18h]@3
+  int v9; // [sp+Ch] [bp-14h]@3
+  int v10; // [sp+10h] [bp-10h]@3
+  int v11; // [sp+14h] [bp-Ch]@3
+  int v12; // [sp+18h] [bp-8h]@1
+  int v13; // [sp+1Ch] [bp-4h]@1
+
+  v3 = a2;
+  am_BeginScene(pArcomageGame->pSpritesPixels, -1, 1);
+  v4 = pXY[1];
+  v12 = *pXY;
+  v13 = v4;
+  do
+  {
+    v5 = *(unsigned char *)v3++;
+    v6 = v5 == 0;
+    if ( v5 )
+    {
+      v7 = 13 * v5;
+      v8 = v7 - 370;
+      v10 = v7 - 357;
+      v9 = 128;
+      v11 = 138;
+      Blt_Copy((ArcomageRect *)&v8, &v12, 2);
+      v12 += 13;
+      v6 = v5 == 0;
+    }
+  }
+  while ( !v6 );
+  am_EndScene();
+}
+
+//----- (0040B1F3) --------------------------------------------------------
+void __fastcall am_40B1F3(int a1, int a2, int a3)
+{
+  int v3; // esi@1
+  int v4; // eax@1
+  unsigned __int8 v5; // bl@2
+  char v6; // zf@2
+  int v7; // eax@3
+  int v8; // [sp+8h] [bp-18h]@3
+  int v9; // [sp+Ch] [bp-14h]@3
+  int v10; // [sp+10h] [bp-10h]@3
+  int v11; // [sp+14h] [bp-Ch]@3
+  int v12; // [sp+18h] [bp-8h]@1
+  int v13; // [sp+1Ch] [bp-4h]@1
+
+  v3 = a2;
+  am_BeginScene(pArcomageGame->pSpritesPixels, -1, 1);
+  v4 = *(unsigned int *)(a3 + 4);
+  v12 = *(unsigned int *)a3;
+  v13 = v4;
+  do
+  {
+    v5 = *(unsigned char *)v3++;
+    v6 = v5 == 0;
+    if ( v5 )
+    {
+      v7 = 13 * v5;
+      v8 = v7 - 370;
+      v10 = v7 - 357;
+      v9 = 138;
+      v11 = 148;
+      Blt_Copy((ArcomageRect *)&v8, &v12, 2);
+      v12 += 13;
+      v6 = v5 == 0;
+    }
+  }
+  while ( !v6 );
+  am_EndScene();
+}
+
+//----- (0040B268) --------------------------------------------------------
+void __fastcall am_40B268(int a1, char *a2, int *pXY)
+{
+  char *v3; // esi@1
+  int v4; // eax@1
+  unsigned __int8 v5; // bl@2
+  char v6; // zf@2
+  int v7; // eax@3
+  int v8; // [sp+8h] [bp-18h]@3
+  int v9; // [sp+Ch] [bp-14h]@3
+  int v10; // [sp+10h] [bp-10h]@3
+  int v11; // [sp+14h] [bp-Ch]@3
+  int v12; // [sp+18h] [bp-8h]@1
+  int v13; // [sp+1Ch] [bp-4h]@1
+
+  v3 = a2;
+  am_BeginScene(pArcomageGame->pSpritesPixels, -1, 1);
+  v4 = pXY[1];
+  v12 = *pXY;
+  v13 = v4;
+  do
+  {
+    v5 = *v3++;
+    v6 = v5 == 0;
+    if ( v5 )
+    {
+      v7 = 13 * v5;
+      v8 = v7 - 370;
+      v10 = v7 - 357;
+      v9 = 148;
+      v11 = 158;
+      Blt_Copy((ArcomageRect *)&v8, &v12, 2);
+      v12 += 13;
+      v6 = v5 == 0;
+    }
+  }
+  while ( !v6 );
+  am_EndScene();
+}
+
+//----- (0040B2DD) --------------------------------------------------------
+void __cdecl am_chroma_and_copy_blts()
+{
+  int v0; // eax@1
+  int v1; // esi@3
+  int v2; // eax@3
+  int v3; // eax@3
+  int v4; // esi@5
+  int v5; // eax@5
+  int pSrcXYZW[4]; // [sp+0h] [bp-18h]@3
+  int v7; // [sp+4h] [bp-14h]@3
+  int v8; // [sp+8h] [bp-10h]@3
+  int v9; // [sp+Ch] [bp-Ch]@3
+  int pTargetXY[2]; // [sp+10h] [bp-8h]@3
+
+  v0 = stru_505708[0].field_24;
+  if ( stru_505708[0].field_24 > dword_4E1884 )
+    v0 = dword_4E1884;
+  v7 = 0;
+  pSrcXYZW[0] = 892;
+  v8 = 937;
+  pTargetXY[0] = 102;
+  v1 = 200 * v0 / dword_4E1884;
+  v9 = v1;
+  pTargetXY[1] = 297 - v1;
+  Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, 2);
+  v7 = 0;
+  v2 = 203 - v1;
+  pTargetXY[1] = 203 - v1;
+  LOWORD(v2) = pArcomageGame->field_54;
+  pSrcXYZW[0] = 384;
+  v8 = 452;
+  v9 = 94;
+  pTargetXY[0] = 91;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v2, 2);
+  v3 = stru_505708[1].field_24;
+  if ( stru_505708[1].field_24 > dword_4E1884 )
+    v3 = dword_4E1884;
+  v7 = 0;
+  pSrcXYZW[0] = 892;
+  v8 = 937;
+  pTargetXY[0] = 494;
+  v4 = 200 * v3 / dword_4E1884;
+  v9 = v4;
+  pTargetXY[1] = 297 - v4;
+  Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, 2);
+  LOWORD(v5) = pArcomageGame->field_54;
+  pSrcXYZW[0] = 384;
+  v8 = 452;
+  v7 = 94;
+  v9 = 188;
+  pTargetXY[0] = 483;
+  pTargetXY[1] = 203 - v4;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v5, 2);
+}
+// 4E1884: using guessed type int dword_4E1884;
+
+//----- (0040B400) --------------------------------------------------------
+void __cdecl am_chroma_blt()
+{
+  int v0; // eax@1
+  int v1; // eax@4
+  int v2; // ecx@4
+  int v3; // eax@5
+  int v4; // eax@8
+  int v5; // esi@8
+  int pSrcXYZW[4]; // [sp+4h] [bp-18h]@4
+  int pTargetXY[2]; // [sp+14h] [bp-8h]@4
+
+  v0 = stru_505708[0].field_28;
+  if ( stru_505708[0].field_28 <= 100 )
+  {
+    if ( stru_505708[0].field_28 <= 0 )
+      goto LABEL_5;
+  }
+  else
+  {
+    v0 = 100;
+  }
+  pSrcXYZW[1] = 0;
+  pSrcXYZW[0] = 843;
+  v1 = 200 * v0 / 100;
+  pSrcXYZW[2] = 867;
+  pTargetXY[0] = 177;
+  pSrcXYZW[3] = v1;
+  v2 = 297 - v1;
+  LOWORD(v1) = pArcomageGame->field_54;
+  pTargetXY[1] = v2;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v1, 2);
+LABEL_5:
+  v3 = stru_505708[1].field_28;
+  if ( stru_505708[1].field_28 <= 100 )
+  {
+    if ( stru_505708[1].field_28 <= 0 )
+      return;
+  }
+  else
+  {
+    v3 = 100;
+  }
+  pSrcXYZW[1] = 0;
+  pSrcXYZW[0] = 843;
+  v4 = 200 * v3 / 100;
+  pSrcXYZW[2] = 867;
+  pTargetXY[0] = 439;
+  pSrcXYZW[3] = v4;
+  v5 = 297 - v4;
+  LOWORD(v4) = pArcomageGame->field_54;
+  pTargetXY[1] = v5;
+  Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v4, 2);
+}
+
+//----- (0040B4B9) --------------------------------------------------------
+void __cdecl am_40B4B9()
+{
+  int v0; // esi@1
+  int v1; // ebx@1
+  int v2; // edi@1
+  int v3; // edx@2
+  int v4; // eax@3
+  int v5; // ecx@3
+  int v6; // eax@3
+  unsigned int v7; // ecx@4
+  int v8; // eax@16
+  int v9; // ecx@16
+  int v10; // eax@16
+  signed int v11; // edi@18
+  int v12; // esi@20
+  unsigned int v13; // ecx@20
+  int v14; // eax@23
+  unsigned int v15; // eax@25
+  unsigned int v16; // ecx@25
+  int *v17; // esi@26
+  unsigned int v18; // eax@29
+  int *v19; // ecx@29
+  int v20; // ecx@31
+  int v21; // [sp-4h] [bp-2Ch]@8
+  int pSrcXYZW[4]; // [sp+Ch] [bp-1Ch]@8
+  int pTargetXY[2]; // [sp+1Ch] [bp-Ch]@1
+  int v24; // [sp+24h] [bp-4h]@1
+
+  v0 = am_40BB49(amuint_4FAA6C);
+  v1 = 0;
+  v2 = 0;
+  pTargetXY[1] = 327;
+  v24 = (640 - 96 * v0) / (v0 + 1);
+  pTargetXY[0] = (640 - 96 * v0) / (v0 + 1);
+  while ( v2 < v0 )
+  {
+    v3 = amuint_4FAA6C;
+    if ( am_byte_4E185D != (_BYTE)v1 )
+    {
+      v4 = 188 * amuint_4FAA6C + 8 * v2;
+      v5 = *(int *)((char *)stru_505708[0].arr_6C[0] + v4);
+      v6 = *(int *)((char *)&stru_505708[0].arr_6C[0][1] + v4);
+      pTargetXY[0] += v5;
+      pTargetXY[1] += v6;
+    }
+    v7 = stru_505708[0].arr_44[v2 + 47 * amuint_4FAA6C];
+    if ( v7 == -1 )
+    {
+      ++v0;
+      goto LABEL_15;
+    }
+    if ( v2 != amuint_4FAA4C )
+    {
+      if ( LOBYTE(stru_505708[amuint_4FAA6C].field_20) == (_BYTE)v1 && byte_505881 == (_BYTE)v1 )
+      {
+        pSrcXYZW[0] = 192;
+        pSrcXYZW[2] = 288;
+        pSrcXYZW[1] = v1;
+        pSrcXYZW[3] = 128;
+        v21 = 2;
+LABEL_12:
+        Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, v21);
+        goto LABEL_13;
+      }
+      ArcomageGame::GetCardRect(v7, (ArcomageRect *)pSrcXYZW);
+      if ( !am_40BF15(amuint_4FAA6C, v2) )
+      {
+        v1 = 0;
+        v21 = 0;
+        goto LABEL_12;
+      }
+      Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, 2);
+      v1 = 0;
+    }
+LABEL_13:
+    v3 = amuint_4FAA6C;
+    pTargetXY[0] += v24 + 96;
+LABEL_15:
+    if ( am_byte_4E185D != (_BYTE)v1 )
+    {
+      v8 = 188 * v3 + 8 * v2;
+      v9 = *(int *)((char *)stru_505708[0].arr_6C[0] + v8);
+      v10 = *(int *)((char *)&stru_505708[0].arr_6C[0][1] + v8);
+      pTargetXY[0] -= v9;
+      pTargetXY[1] -= v10;
+    }
+    ++v2;
+  }
+  v11 = 0;
+  do
+  {
+    if ( am_byte_4FAA76 == (_BYTE)v1 )
+    {
+      v12 = 4 * v11;
+      v13 = amuint_4FAA78[8 * v11];
+      if ( v13 != -1 )
+      {
+        ArcomageGame::GetCardRect(v13, (ArcomageRect *)pSrcXYZW);
+        Blt_Copy((ArcomageRect *)pSrcXYZW, amuint_4FAA90[v12], v1);
+      }
+      if ( am_byte_4FAA7C[v12 * 8] != (_BYTE)v1 )
+      {
+        pTargetXY[0] = amuint_4FAA90[v12][0] + 12;
+        v14 = amuint_4FAA90[v12][1] + 40;
+        pTargetXY[1] = amuint_4FAA90[v12][1] + 40;
+        LOWORD(v14) = pArcomageGame->field_54;
+        pSrcXYZW[0] = 843;
+        pSrcXYZW[2] = 916;
+        pSrcXYZW[1] = 200;
+        pSrcXYZW[3] = 216;
+        Blt_Chroma((ArcomageRect *)pSrcXYZW, pTargetXY, v14, 2);
+      }
+    }
+    else
+    {
+      if ( amuint_4FAA34 <= v1 )
+      {
+        if ( v11 == 9 )
+        {
+          am_byte_4FAA76 = v1;
+          am_byte_4FAA75 = v1;
+          amuint_4FAA34 = 5;
+        }
+        v18 = 32 * v11;
+        v19 = &amuint_4FAA78[8 * v11];
+        if ( *v19 != -1 )
+          amuint_4FABC4 = *v19;
+        *v19 = -1;
+        amuint_4FAA90[v18 / 8][0] = amuint_4FAA80[v18 / 4];
+        v20 = amuint_4FAA84[v18 / 4];
+        am_byte_4FAA7C[v18] = v1;
+        amuint_4FAA90[v18 / 8][1] = v20;
+      }
+      else
+      {
+        v15 = 32 * v11;
+        v16 = amuint_4FAA78[8 * v11];
+        if ( v16 != -1 )
+        {
+          v17 = amuint_4FAA90[v15 / 8];
+          *v17 += amuint_4FAA88[v15 / 4];
+          amuint_4FAA90[v15 / 8][1] += amuint_4FAA8C[v15 / 4];
+          ArcomageGame::GetCardRect(v16, (ArcomageRect *)pSrcXYZW);
+          Blt_Copy((ArcomageRect *)pSrcXYZW, v17, v1);
+        }
+      }
+    }
+    ++v11;
+  }
+  while ( v11 < 10 );
+  if ( am_byte_4FAA76 != (_BYTE)v1 )
+    --amuint_4FAA34;
+  pSrcXYZW[0] = 192;
+  pSrcXYZW[2] = 288;
+  pSrcXYZW[1] = v1;
+  pSrcXYZW[3] = 128;
+  pTargetXY[0] = 120;
+  pTargetXY[1] = 18;
+  Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, v1);
+}
+// 4E185D: using guessed type char am_byte_4E185D;
+// 4FAA34: using guessed type int amuint_4FAA34;
+// 4FAA4C: using guessed type int amuint_4FAA4C;
+// 4FAA75: using guessed type char am_byte_4FAA75;
+// 4FAA76: using guessed type char am_byte_4FAA76;
+// 4FAA78: using guessed type int amuint_4FAA78[];
+// 4FAA80: using guessed type int amuint_4FAA80[];
+// 4FAA84: using guessed type int amuint_4FAA84[];
+// 4FAA88: using guessed type int amuint_4FAA88[];
+// 4FAA8C: using guessed type int amuint_4FAA8C[];
+// 4FABC4: using guessed type int amuint_4FABC4;
+// 505881: using guessed type char byte_505881;
+
+
+
+//----- (0040B76F) --------------------------------------------------------
+void __fastcall am_40B76F(int a1)
+{
+  int v1; // eax@3
+  int v2; // eax@3
+  int v3; // esi@4
+  int v4; // eax@4
+  int *v5; // edx@6
+  int *v6; // ecx@6
+  signed int v7; // ebx@11
+  int v8; // eax@15
+  signed int v9; // ecx@15
+  int v10; // eax@20
+  int v11; // ecx@20
+  int v12; // eax@20
+  unsigned int v13; // ecx@21
+  double v14; // st7@22
+  int *v15; // edx@23
+  int v16; // eax@32
+  char v17; // zf@37
+  int v18; // eax@41
+  int v19; // eax@46
+  int v20; // ecx@46
+  int v21; // eax@46
+  int v22; // [sp-4h] [bp-2Ch]@6
+  int v23; // [sp-4h] [bp-2Ch]@28
+  int pSrcXYZW[4]; // [sp+Ch] [bp-1Ch]@6
+  int pTargetXY[2]; // [sp+1Ch] [bp-Ch]@20
+  int v26; // [sp+24h] [bp-4h]@1
+
+  v26 = a1;
+  if ( amuint_4FAA4C != -1 )
+  {
+    if ( amuint_4FAA38 >= 9 )
+    {
+      am_uint_4FAA44_blt_xy[1] = 18;
+      am_uint_4FAA44_blt_xy[0] = 120;
+      v1 = am_40BB49(amuint_4FAA6C);
+      v2 = (640 - 96 * v1) / v1 + 96;
+      if ( am_byte_4E185D )
+      {
+        v3 = 188 * amuint_4FAA6C + 8 * amuint_4FAA4C;
+        amuint_4FAA3C_blt_xy[0] = (amuint_4FAA4C * v2 + *(int *)((char *)stru_505708[0].arr_6C[0] + v3) - 120) / 10;
+        v4 = (*(int *)((char *)&stru_505708[0].arr_6C[0][1] + v3) + 309) / 10;
+      }
+      else
+      {
+        amuint_4FAA3C_blt_xy[0] = (amuint_4FAA4C * v2 - 120) / 10;
+        v4 = 30;
+      }
+      am_uint_4FAA44_blt_xy[1] += v4;
+      am_uint_4FAA44_blt_xy[0] += amuint_4FAA3C_blt_xy[0];
+      pSrcXYZW[1] = 0;
+      amuint_4FAA3C_blt_xy[1] = v4;
+      pSrcXYZW[0] = 192;
+      pSrcXYZW[2] = 288;
+      pSrcXYZW[3] = 128;
+      v22 = 2;
+      v5 = am_uint_4FAA44_blt_xy;
+      v6 = pSrcXYZW;
+      goto LABEL_7;
+    }
+    pSrcXYZW[1] = 0;
+    v6 = pSrcXYZW;
+    v5 = am_uint_4FAA44_blt_xy;
+    v22 = 2;
+    pSrcXYZW[3] = 128;
+    pSrcXYZW[2] = 288;
+    pSrcXYZW[0] = 192;
+    if ( amuint_4FAA38 )
+    {
+      am_uint_4FAA44_blt_xy[0] += amuint_4FAA3C_blt_xy[0];
+      am_uint_4FAA44_blt_xy[1] += amuint_4FAA3C_blt_xy[1];
+LABEL_7:
+      Blt_Copy((ArcomageRect *)v6, v5, v22);
+      goto LABEL_11;
+    }
+    am_uint_4FAA44_blt_xy[0] += amuint_4FAA3C_blt_xy[0];
+    am_uint_4FAA44_blt_xy[1] += amuint_4FAA3C_blt_xy[1];
+    Blt_Copy((ArcomageRect *)pSrcXYZW, am_uint_4FAA44_blt_xy, 2);
+    amuint_4FAA4C = -1;
+  }
+LABEL_11:
+  v7 = (signed int)amuint_4FAA78;
+  if ( uCardID != -1 )
+  {
+    if ( v26 <= 10 )
+    {
+      if ( v26 == 10 )
+      {
+        ArcomageGame::GetCardRect(uCardID, (ArcomageRect *)pSrcXYZW);
+        v8 = 0;
+        v9 = (signed int)amuint_4FAA78;
+        while ( *(unsigned int *)v9 != -1 )
+        {
+          v9 += 32;
+          ++v8;
+          if ( v9 >= (signed int)&dword_4FABB8 )
+            goto LABEL_20;
+        }
+        amuint_4FAA78[8 * v8] = uCardID;
+        am_byte_4FAA7C[32 * v8] = 1;
+LABEL_20:
+        v10 = 8 * v8;
+        v11 = amuint_4FAA80[v10];
+        v12 = amuint_4FAA84[v10];
+        pTargetXY[0] = v11;
+        pTargetXY[1] = v12;
+        Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, 0);
+        uCardID = -1;
+      }
+    }
+    else
+    {
+      ArcomageGame::GetCardRect(uCardID, (ArcomageRect *)pSrcXYZW);
+      amuint_4FAA5C_blt_xy[0] += amuint_4FAA54_blt_xy[0];
+      amuint_4FAA5C_blt_xy[1] += amuint_4FAA54_blt_xy[1];
+      Blt_Copy((ArcomageRect *)pSrcXYZW, amuint_4FAA5C_blt_xy, 0);
+    }
+  }
+  v13 = amuint_4FABC0;
+  if ( amuint_4FABC0 != -1 )
+  {
+    v14 = (double)v26;
+    if ( v14 > 15.0 )
+    {
+      ArcomageGame::GetCardRect(amuint_4FABC0, (ArcomageRect *)pSrcXYZW);
+      v15 = amuint_4FAA5C_blt_xy;
+      amuint_4FAA5C_blt_xy[0] += amuint_4FAA54_blt_xy[0];
+      amuint_4FAA5C_blt_xy[1] += amuint_4FAA54_blt_xy[1];
+LABEL_28:
+      v23 = 2;
+LABEL_29:
+      Blt_Copy((ArcomageRect *)pSrcXYZW, v15, v23);
+      return;
+    }
+    if ( v14 == 15.0 )
+    {
+      am_40BF77(amuint_4FAA6C, amuint_4FABC0);
+      v13 = amuint_4FABC0;
+      goto LABEL_26;
+    }
+    if ( v14 == 5.0 )
+    {
+      amuint_4FAA5C_blt_xy[0] = 272;
+      amuint_4FAA5C_blt_xy[1] = 173;
+      v16 = 0;
+      do
+      {
+        if ( *(unsigned int *)v7 == -1 )
+          break;
+        v7 += 32;
+        ++v16;
+      }
+      while ( v7 < (signed int)&dword_4FABB8 );
+      v26 = 32 * v16;
+      amuint_4FAA54_blt_xy[0] = (amuint_4FAA80[8 * v16] - 272) / 5;
+      amuint_4FAA54_blt_xy[1] = (amuint_4FAA84[8 * v16] - 173) / 5;
+      ArcomageGame::GetCardRect(amuint_4FABC0, (ArcomageRect *)pSrcXYZW);
+      pTargetXY[0] = 272;
+      pTargetXY[1] = 173;
+      goto LABEL_27;
+    }
+    if ( v14 >= 5.0 )
+    {
+      v17 = v26 == 0;
+    }
+    else
+    {
+      v17 = v26 == 0;
+      if ( v26 > 0 )
+      {
+        ArcomageGame::GetCardRect(amuint_4FABC0, (ArcomageRect *)pSrcXYZW);
+        v15 = amuint_4FAA5C_blt_xy;
+        amuint_4FAA5C_blt_xy[0] += amuint_4FAA54_blt_xy[0];
+        amuint_4FAA5C_blt_xy[1] += amuint_4FAA54_blt_xy[1];
+        v23 = 0;
+        goto LABEL_29;
+      }
+    }
+    if ( !v17 )
+    {
+LABEL_26:
+      ArcomageGame::GetCardRect(v13, (ArcomageRect *)pSrcXYZW);
+      pTargetXY[0] = 272;
+      pTargetXY[1] = 173;
+LABEL_27:
+      v15 = pTargetXY;
+      goto LABEL_28;
+    }
+    ArcomageGame::GetCardRect(amuint_4FABC0, (ArcomageRect *)pSrcXYZW);
+    v18 = 0;
+    while ( *(unsigned int *)v7 != -1 )
+    {
+      v7 += 32;
+      ++v18;
+      if ( v7 >= (signed int)&dword_4FABB8 )
+        goto LABEL_46;
+    }
+    amuint_4FAA78[8 * v18] = amuint_4FABC0;
+LABEL_46:
+    v19 = 8 * v18;
+    v20 = amuint_4FAA80[v19];
+    v21 = amuint_4FAA84[v19];
+    pTargetXY[0] = v20;
+    pTargetXY[1] = v21;
+    Blt_Copy((ArcomageRect *)pSrcXYZW, pTargetXY, 0);
+    amuint_4FABC0 = -1;
+  }
+}
+// 4E185D: using guessed type char am_byte_4E185D;
+// 4FAA38: using guessed type int amuint_4FAA38;
+// 4FAA4C: using guessed type int amuint_4FAA4C;
+// 4FAA78: using guessed type int amuint_4FAA78[];
+// 4FAA80: using guessed type int amuint_4FAA80[];
+// 4FAA84: using guessed type int amuint_4FAA84[];
+// 4FABB8: using guessed type int dword_4FABB8;
+
+//----- (0040BB12) --------------------------------------------------------
+void ArcomageGame::GetCardRect(unsigned int uCardID, ArcomageRect *pCardRect)
+{
+  ArcomageRect *pXYZW; // esi@1
+  int v3; // edx@1
+  int v4; // ecx@1
+
+  pXYZW = pCardRect;
+  v3 = pCards[uCardID].slot % 10;
+  v4 = (pCards[uCardID].slot / 10 << 7) + 220;
+  pXYZW->y = v4;
+  pXYZW->x = 96 * v3;
+  pXYZW->w = v4 + 128;
+  pXYZW->z = 96 * v3 + 96;
+}
+
+//----- (0040BB49) --------------------------------------------------------
+int __fastcall am_40BB49(int a1)
+{
+  int result; // eax@1
+  char *v2; // ecx@1
+  signed int v3; // edx@1
+
+  result = 0;
+  v2 = (char *)stru_505708[a1].arr_44;
+  v3 = 10;
+  do
+  {
+    if ( *(unsigned int *)v2 != -1 )
+      ++result;
+    v2 += 4;
+    --v3;
+  }
+  while ( v3 );
+  return result;
+}
+
+//----- (0040BB67) --------------------------------------------------------
+signed int __fastcall am_40BB67(int a1)
+{
+  int v1; // esi@1
+  signed int result; // eax@1
+  int v3; // ebx@1
+  char v4; // zf@1
+  int v5; // eax@3
+  int v6; // eax@4
+  int v7; // ecx@6
+  char *v8; // eax@6
+  int v9; // eax@10
+  int v10; // ecx@10
+  int v11; // eax@10
+  char v12; // ch@2@11
+  int v13; // ST00_4@12
+  unsigned __int16 v14; // ax@12
+  int v15; // eax@13
+  int v16; // ecx@13
+  int v17; // eax@13
+  char v18; // al@16
+  char v19; // ch@2@16
+  int v20; // ST00_4@19
+  unsigned __int16 v21; // ax@19
+  int pXYZW[4]; // [sp+Ch] [bp-3Ch]@3
+  stru273 v26; // [sp+1Ch] [bp-2Ch]@2
+  int a1a; // [sp+28h] [bp-20h]@1
+  int v25; // [sp+2Ch] [bp-1Ch]@3
+  int var18; // [sp+30h] [bp-18h]@3
+  int i; // [sp+34h] [bp-14h]@4
+  int v28; // [sp+38h] [bp-10h]@1
+  int a2; // [sp+3Ch] [bp-Ch]@3
+  int v30; // [sp+40h] [bp-8h]@1
+  char v31; // [sp+44h] [bp-4h]@12
+  char v32; // [sp+45h] [bp-3h]@12
+  char v33; // [sp+46h] [bp-2h]@12
+
+  v1 = a1;
+  v30 = 0;
+  result = -1;
+  v3 = 188 * a1;
+  a1a = a1;
+  v4 = LOBYTE(stru_505708[a1].field_20) == 0;
+  v28 = -1;
+  if ( !v4 )
+  {
+    if ( v26._40DD2F() )
+    {
+      v5 = am_40BB49(v1);
+      a2 = 0;
+      v25 = v5;
+      pXYZW[1] = 327;
+      pXYZW[3] = 455;
+      pXYZW[0] = (640 - 96 * v5) / (v5 + 1);
+      var18 = pXYZW[0] + 96;
+      pXYZW[2] = pXYZW[0] + 96;
+      if ( v5 > 0 )
+      {
+        v6 = 47 * v1;
+        for ( i = 47 * v1; ; v6 = i )
+        {
+          v7 = v30;
+          v8 = (char *)&stru_505708[0].arr_44[v30 + v6];
+          if ( *(unsigned int *)v8 == -1 )
+          {
+            do
+            {
+              v8 += 4;
+              ++v7;
+            }
+            while ( *(unsigned int *)v8 == -1 );
+            v30 = v7;
+          }
+          if ( am_byte_4E185D )
+          {
+            v9 = v3 + 8 * v7;
+            v10 = *(int *)((char *)stru_505708[0].arr_6C[0] + v9);
+            v11 = *(int *)((char *)&stru_505708[0].arr_6C[0][1] + v9);
+            pXYZW[0] += v10;
+            pXYZW[2] += v10;
+            pXYZW[1] += v11;
+            pXYZW[3] += v11;
+          }
+          if ( v26.Inside((Vec4_int_ *)pXYZW) )
+            break;
+          v31 = 0;
+          v32 = 0;
+          v33 = 0;
+          BYTE3(v13) = v12;
+          LOWORD(v13) = *(_WORD *)&v31;
+          BYTE2(v13) = 0;
+          v14 = R8G8B8_to_TargetFormat(v13);
+          DrawRect((Vec4_int_ *)pXYZW, v14, 0);
+          pXYZW[0] += var18;
+          pXYZW[2] += var18;
+          if ( am_byte_4E185D )
+          {
+            v15 = v3 + 8 * v30;
+            v16 = *(int *)((char *)stru_505708[0].arr_6C[0] + v15);
+            v17 = *(int *)((char *)&stru_505708[0].arr_6C[0][1] + v15);
+            pXYZW[0] -= v16;
+            pXYZW[2] -= v16;
+            pXYZW[1] -= v17;
+            pXYZW[3] -= v17;
+          }
+          ++v30;
+          ++a2;
+          if ( a2 >= v25 )
+            goto LABEL_20;
+        }
+        v28 = a2;
+        v18 = am_40BF15(a1a, a2);
+        v31 = -1;
+        if ( v18 )
+        {
+          v32 = -1;
+          v33 = -1;
+        }
+        else
+        {
+          v32 = 0;
+          v33 = 0;
+        }
+        BYTE3(v20) = v19;
+        LOWORD(v20) = *(_WORD *)&v31;
+        BYTE2(v20) = v33;
+        v21 = R8G8B8_to_TargetFormat(v20);
+        DrawRect((Vec4_int_ *)pXYZW, v21, 0);
+      }
+    }
+LABEL_20:
+    result = v28;
+  }
+  return result;
+}
+// 4E185D: using guessed type char am_byte_4E185D;
+
+//----- (0040BCFB) --------------------------------------------------------
+char __fastcall am_40BCFB(int a1, signed int a2)
+{
+  int v2; // esi@2
+  signed int v3; // edi@2
+  char *v4; // eax@2
+  int v5; // ecx@7
+  int v6; // ebx@7
+  int v7; // esi@8
+  int v8; // eax@8
+  int v9; // esi@8
+  int v10; // ecx@8
+  int v11; // eax@8
+  int v12; // eax@8
+  signed int v13; // edx@9
+  unsigned int v14; // eax@12
+  char result; // al@12
+
+  if ( a2 <= -1 )
+    goto LABEL_16;
+  v2 = 0;
+  v3 = 0;
+  v4 = (char *)stru_505708[a1].arr_44;
+  do
+  {
+    if ( *(unsigned int *)v4 != -1 )
+    {
+      if ( a2 == v2 )
+        break;
+      ++v2;
+    }
+    ++v3;
+    v4 += 4;
+  }
+  while ( v3 < 10 );
+  v5 = v3 + 47 * a1;
+  v6 = 4 * v5 + 5265228;
+  if ( BYTE3(pCards[stru_505708[0].arr_44[v5]].field_28) )
+  {
+    ArcomageGame::PlaySound(0x16u);
+    v7 = amuint_4FAA6C;
+    v8 = am_40BB49(amuint_4FAA6C);
+    v9 = 188 * v7 + 8 * v3;
+    v10 = 96 * v3 + *(int *)((char *)stru_505708[0].arr_6C[0] + v9) + (640 - 96 * v8) / (v8 + 1);
+    v11 = *(int *)((char *)&stru_505708[0].arr_6C[0][1] + v9) + 327;
+    amuint_4FAA5C_blt_xy[0] = v10;
+    amuint_4FAA5C_blt_xy[1] = v11;
+    v12 = 0;
+    if ( !am_byte_4FAA75 )
+    {
+      v13 = (signed int)amuint_4FAA78;
+      do
+      {
+        if ( *(unsigned int *)v13 == -1 )
+          break;
+        v13 += 32;
+        ++v12;
+      }
+      while ( v13 < (signed int)&dword_4FABB8 );
+    }
+    pArcomageGame->field_F6 = 1;
+    amuint_4FAA54_blt_xy[0] = (amuint_4FAA80[8 * v12] - v10) / 10;
+    amuint_4FAA54_blt_xy[1] = (amuint_4FAA84[8 * v12] - 327) / 10;
+    v14 = *(unsigned int *)v6;
+    *(unsigned int *)v6 = -1;
+    am_byte_4FAA77 = 0;
+    uCardID = v14;
+    result = 1;
+  }
+  else
+  {
+LABEL_16:
+    result = 0;
+  }
+  return result;
+}
+// 4FAA75: using guessed type char am_byte_4FAA75;
+// 4FAA77: using guessed type char am_byte_4FAA77;
+// 4FAA78: using guessed type int amuint_4FAA78[];
+// 4FAA80: using guessed type int amuint_4FAA80[];
+// 4FAA84: using guessed type int amuint_4FAA84[];
+// 4FABB8: using guessed type int dword_4FABB8;
+
+//----- (0040BE0E) --------------------------------------------------------
+bool __fastcall am_40BE0E(int a1, signed int a2)
+{
+  bool result; // eax@0
+  int v3; // ebp@1
+  int v4; // ecx@2
+  ArcomageGame_stru0 *v5; // esi@2
+  int v6; // edi@2
+  int v7; // eax@2
+  int v8; // ebx@8
+  int v9; // eax@8
+  int v10; // ebx@8
+  int v11; // ebp@8
+  int v12; // ecx@8
+  int v13; // eax@8
+  ArcomageCard *v14; // eax@8
+  int v15; // ecx@8
+  int v16; // ecx@8
+
+  v3 = a1;
+  if ( a2 <= -1 )
+    goto LABEL_12;
+  v4 = 0;
+  v5 = &stru_505708[v3];
+  v6 = 0;
+  v7 = (int)v5->arr_44;
+  do
+  {
+    if ( *(unsigned int *)v7 != -1 )
+    {
+      if ( a2 == v4 )
+        break;
+      ++v4;
+    }
+    ++v6;
+    v7 += 4;
+  }
+  while ( v6 < 10 );
+  result = am_40BF15(v3, v6);
+  if ( result )
+  {
+    ArcomageGame::PlaySound(0x17u);
+    v8 = amuint_4FAA6C;
+    v9 = am_40BB49(amuint_4FAA6C);
+    v10 = 188 * v8 + 8 * v6;
+    v11 = v6 + 47 * v3;
+    amuint_4FAA54_blt_xy[1] = -30;
+    pArcomageGame->field_F6 = 1;
+    v12 = 96 * v6 + *(int *)((char *)stru_505708[0].arr_6C[0] + v10) + (640 - 96 * v9) / (v9 + 1);
+    v13 = *(int *)((char *)&stru_505708[0].arr_6C[0][1] + v10) + 327;
+    amuint_4FAA5C_blt_xy[0] = v12;
+    amuint_4FAA5C_blt_xy[1] = v13;
+    amuint_4FAA54_blt_xy[0] = (272 - v12) / 5;
+    v14 = &pCards[v5->arr_44[v6]];
+    v5->field_38 -= LOBYTE(v14->field_28);
+    v15 = BYTE1(v14->field_28);
+    v5->field_40 -= BYTE2(v14->field_28);
+    v5->field_3C -= v15;
+    result = 4 * v11 + 5265228;
+    v16 = stru_505708[0].arr_44[v11];
+    stru_505708[0].arr_44[v11] = -1;
+    amuint_4FABC0 = v16;
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+LABEL_12:
+    LOBYTE(result) = 0;
+  }
+  return result;
+}
+
+//----- (0040BF15) --------------------------------------------------------
+bool __fastcall am_40BF15(int a1, int a2)
+{
+  ArcomageGame_stru0 *v2; // esi@1
+  bool result; // eax@1
+  ArcomageCard *v4; // ecx@1
+
+  v2 = &stru_505708[a1];
+  LOBYTE(result) = 1;
+  v4 = &pCards[v2->arr_44[a2]];
+  if ( SBYTE1(v4->field_24) > v2->field_2C )
+    LOBYTE(result) = 0;
+  if ( SBYTE2(v4->field_24) > v2->field_30 )
+    LOBYTE(result) = 0;
+  if ( SBYTE3(v4->field_24) > v2->field_34 )
+    LOBYTE(result) = 0;
+  if ( SLOBYTE(v4->field_28) > v2->field_38 )
+    LOBYTE(result) = 0;
+  if ( SBYTE1(v4->field_28) > v2->field_3C )
+    LOBYTE(result) = 0;
+  if ( SBYTE2(v4->field_28) > v2->field_40 )
+    LOBYTE(result) = 0;
+  return result;
+}
+
+
+
+
+//----- (0040BF77) --------------------------------------------------------
+void __fastcall am_40BF77(int a1, unsigned int uCardID)
+{
+  ArcomageGame_stru0 *v2; // esi@1
+  int v3; // eax@1
+  ArcomageGame_stru0 *v4; // edi@1
+  int v5; // eax@2
+  char v6; // sf@2
+  unsigned __int8 v7; // of@2
+  int v8; // eax@3
+  int v9; // eax@4
+  char v10; // zf@5
+  int v11; // eax@8
+  unsigned __int8 v12; // zf@8
+  char v13; // sf@8
+  unsigned __int8 v14; // of@8
+  int v15; // eax@9
+  int v16; // eax@10
+  char v17; // zf@12
+  char v18; // al@15
+  int v19; // eax@16
+  int v20; // eax@17
+  int v21; // eax@22
+  int v22; // eax@23
+  int v23; // eax@26
+  int v24; // edx@26
+  signed int v25; // ebx@26
+  ArcomageCard *v26; // ebx@28
+  int v27; // eax@28
+  int v28; // edx@33
+  int v29; // eax@33
+  int v30; // eax@35
+  int v31; // edx@40
+  int v32; // eax@40
+  int v33; // eax@42
+  int v34; // edx@47
+  int v35; // eax@47
+  int v36; // eax@49
+  int v37; // edx@54
+  int v38; // eax@54
+  bool v39; // eax@56
+  int v40; // edx@61
+  int v41; // eax@61
+  int v42; // eax@63
+  int v43; // edx@68
+  int v44; // eax@68
+  char v45; // al@70
+  int v46; // eax@72
+  int v47; // edx@77
+  int v48; // eax@77
+  int v49; // eax@79
+  int v50; // edx@84
+  int v51; // eax@84
+  int v52; // eax@86
+  int v53; // eax@91
+  int v54; // edx@91
+  int v55; // eax@93
+  int v56; // eax@98
+  int v57; // edx@98
+  int v58; // eax@100
+  int v59; // eax@105
+  int v60; // edx@105
+  int v61; // eax@107
+  int v62; // eax@112
+  int v63; // edx@112
+  int v64; // eax@114
+  int v65; // eax@119
+  int v66; // edx@119
+  int v67; // eax@121
+  int v68; // eax@126
+  int v69; // edx@126
+  char v70; // al@128
+  int v71; // eax@130
+  int v72; // eax@135
+  int v73; // edx@135
+  int v74; // eax@137
+  int v75; // eax@142
+  int v76; // edx@142
+  int v77; // eax@144
+  int v78; // eax@151
+  int v79; // ecx@151
+  int v80; // eax@155
+  int v81; // eax@162
+  int v82; // ecx@162
+  int v83; // eax@166
+  int v84; // eax@173
+  int v85; // ecx@173
+  int v86; // eax@177
+  int v87; // eax@184
+  int v88; // ecx@184
+  bool v89; // eax@188
+  int v90; // eax@195
+  int v91; // ecx@195
+  int v92; // eax@199
+  int v93; // eax@206
+  int v94; // ecx@206
+  char v95; // al@210
+  int v96; // eax@211
+  int v97; // edx@211
+  int v98; // eax@211
+  int v99; // eax@211
+  int v100; // eax@212
+  int v101; // eax@219
+  int v102; // ecx@219
+  int v103; // eax@223
+  int v104; // eax@231
+  int v105; // edx@231
+  signed int v106; // ebx@231
+  ArcomageCard *v107; // ebx@233
+  int v108; // eax@233
+  int v109; // edx@238
+  int v110; // eax@238
+  int v111; // eax@240
+  int v112; // edx@245
+  int v113; // eax@245
+  int v114; // eax@247
+  int v115; // edx@252
+  int v116; // eax@252
+  int v117; // eax@254
+  int v118; // edx@259
+  int v119; // eax@259
+  bool v120; // eax@261
+  int v121; // edx@266
+  int v122; // eax@266
+  int v123; // eax@268
+  int v124; // edx@273
+  int v125; // eax@273
+  char v126; // al@275
+  int v127; // eax@277
+  int v128; // edx@282
+  int v129; // eax@282
+  int v130; // eax@284
+  int v131; // edx@289
+  int v132; // eax@289
+  int v133; // eax@291
+  int v134; // eax@296
+  int v135; // edx@296
+  int v136; // eax@298
+  int v137; // eax@303
+  int v138; // edx@303
+  int v139; // eax@305
+  int v140; // eax@310
+  int v141; // edx@310
+  int v142; // eax@312
+  int v143; // eax@317
+  int v144; // edx@317
+  int v145; // eax@319
+  int v146; // eax@324
+  int v147; // edx@324
+  int v148; // eax@326
+  int v149; // eax@331
+  int v150; // edx@331
+  char v151; // al@333
+  int v152; // eax@335
+  int v153; // eax@340
+  int v154; // edx@340
+  int v155; // eax@342
+  int v156; // eax@347
+  int v157; // edx@347
+  int v158; // eax@349
+  int v159; // eax@356
+  int v160; // ecx@356
+  int v161; // eax@360
+  int v162; // eax@367
+  int v163; // ecx@367
+  int v164; // eax@371
+  int v165; // eax@378
+  int v166; // ecx@378
+  int v167; // eax@382
+  int v168; // eax@389
+  int v169; // ecx@389
+  bool v170; // eax@393
+  int v171; // eax@400
+  int v172; // ecx@400
+  int v173; // eax@404
+  int v174; // eax@411
+  int v175; // ecx@411
+  char v176; // al@415
+  int v177; // eax@416
+  int v178; // edx@416
+  int v179; // eax@416
+  int v180; // eax@416
+  int v181; // eax@417
+  int v182; // eax@424
+  int v183; // ecx@424
+  int v184; // eax@429
+  int v185; // ecx@429
+  signed int v186; // esi@511
+  Vec2_int_ v187; // [sp+Ch] [bp-64h]@488
+  //int v188; // [sp+10h] [bp-60h]@488
+  int v189; // [sp+14h] [bp-5Ch]@1
+  ArcomageCard *pCard; // [sp+18h] [bp-58h]@1
+  int v191; // [sp+1Ch] [bp-54h]@1
+  int v192; // [sp+20h] [bp-50h]@1
+  int v193; // [sp+24h] [bp-4Ch]@1
+  int v194; // [sp+28h] [bp-48h]@1
+  int v195; // [sp+2Ch] [bp-44h]@1
+  int v196; // [sp+30h] [bp-40h]@1
+  int v197; // [sp+34h] [bp-3Ch]@1
+  int v198; // [sp+38h] [bp-38h]@1
+  int v199; // [sp+3Ch] [bp-34h]@1
+  int v200; // [sp+40h] [bp-30h]@1
+  int v201; // [sp+44h] [bp-2Ch]@1
+  int v202; // [sp+48h] [bp-28h]@1
+  int v203; // [sp+4Ch] [bp-24h]@1
+  int v204; // [sp+50h] [bp-20h]@1
+  bool v205; // [sp+54h] [bp-1Ch]@1
+  int v206; // [sp+58h] [bp-18h]@1
+  int v207; // [sp+5Ch] [bp-14h]@1
+  int v208; // [sp+60h] [bp-10h]@1
+  int v209; // [sp+64h] [bp-Ch]@1
+  int v210; // [sp+68h] [bp-8h]@1
+  int v211; // [sp+6Ch] [bp-4h]@1
+
+  v194 = 0;
+  v210 = 0;
+  v208 = 0;
+  v197 = 0;
+  v205 = 0;
+  v203 = 0;
+  v201 = 0;
+  v199 = 0;
+  v192 = 0;
+  v196 = 0;
+  v211 = 0;
+  v209 = 0;
+  v207 = 0;
+  v206 = 0;
+  v204 = 0;
+  v202 = 0;
+  v200 = 0;
+  v198 = 0;
+  v191 = 0;
+  v195 = 0;
+  v193 = a1;
+  v2 = &stru_505708[a1];
+  pCard = &pCards[uCardID];
+  v3 = pCard->field_2C;
+  v189 = (a1 + 1) % 2;
+  v4 = &stru_505708[v189];
+  switch ( v3 )
+  {
+    case 2:
+      v5 = v2->field_2C;
+      v7 = __OFSUB__(v5, v4->field_2C);
+      v6 = v5 - v4->field_2C < 0;
+      goto LABEL_18;
+    case 3:
+      v8 = v2->field_30;
+      v7 = __OFSUB__(v8, v4->field_30);
+      v6 = v8 - v4->field_30 < 0;
+      goto LABEL_18;
+    case 4:
+      v9 = v2->field_34;
+      v7 = __OFSUB__(v9, v4->field_34);
+      v6 = v9 - v4->field_34 < 0;
+      goto LABEL_18;
+    case 5:
+      v10 = v2->field_2C == v4->field_2C;
+      goto LABEL_21;
+    case 6:
+      v10 = v2->field_30 == v4->field_30;
+      goto LABEL_21;
+    case 7:
+      v10 = v2->field_34 == v4->field_34;
+      goto LABEL_21;
+    case 8:
+      v11 = v2->field_2C;
+      v14 = __OFSUB__(v11, v4->field_2C);
+      v12 = v11 == v4->field_2C;
+      v13 = v11 - v4->field_2C < 0;
+      goto LABEL_24;
+    case 9:
+      v15 = v2->field_30;
+      v14 = __OFSUB__(v15, v4->field_30);
+      v12 = v15 == v4->field_30;
+      v13 = v15 - v4->field_30 < 0;
+      goto LABEL_24;
+    case 10:
+      v16 = v2->field_34;
+      v14 = __OFSUB__(v16, v4->field_34);
+      v12 = v16 == v4->field_34;
+      v13 = v16 - v4->field_34 < 0;
+      goto LABEL_24;
+    case 11:
+      v10 = v2->field_28 == 0;
+      goto LABEL_21;
+    case 12:
+      v17 = v2->field_28 == 0;
+      goto LABEL_15;
+    case 13:
+      v10 = v4->field_28 == 0;
+      goto LABEL_21;
+    case 14:
+      v17 = v4->field_28 == 0;
+LABEL_15:
+      v18 = !v17;
+      goto LABEL_25;
+    case 15:
+      v19 = v2->field_28;
+      v7 = __OFSUB__(v19, v4->field_28);
+      v6 = v19 - v4->field_28 < 0;
+      goto LABEL_18;
+    case 16:
+      v20 = v2->field_24;
+      v7 = __OFSUB__(v20, v4->field_24);
+      v6 = v20 - v4->field_24 < 0;
+LABEL_18:
+      v18 = v6 ^ v7;
+      goto LABEL_25;
+    case 17:
+      v10 = v2->field_28 == v4->field_28;
+      goto LABEL_21;
+    case 18:
+      v10 = v2->field_24 == v4->field_24;
+LABEL_21:
+      v18 = v10;
+      goto LABEL_25;
+    case 19:
+      v21 = v2->field_28;
+      v14 = __OFSUB__(v21, v4->field_28);
+      v12 = v21 == v4->field_28;
+      v13 = v21 - v4->field_28 < 0;
+      goto LABEL_24;
+    case 20:
+      v22 = v2->field_24;
+      v14 = __OFSUB__(v22, v4->field_24);
+      v12 = v22 == v4->field_24;
+      v13 = v22 - v4->field_24 < 0;
+LABEL_24:
+      v18 = !((unsigned __int8)(v13 ^ v14) | v12);
+LABEL_25:
+      if ( v18 )
+        goto LABEL_26;
+      goto LABEL_231;
+    default:
+LABEL_26:
+      v23 = BYTE1(pCard->field_30);
+      v24 = v23 + (LOBYTE(pCard->field_30) == 1);
+      v25 = 0;
+      dword_4FAA68 = v23 + (LOBYTE(pCard->field_30) == 1);
+      dword_4FAA64 = v23;
+      if ( v23 > 0 )
+      {
+        do
+        {
+          am_40A283(v193, v24);
+          ++v25;
+        }
+        while ( v25 < SBYTE1(pCard->field_30) );
+      }
+      v26 = pCard;
+      am_byte_4FAA77 = am_40BB49(v193) > dword_4E1874;
+      LOBYTE(v27) = BYTE2(pCard->field_30);
+      if ( (_BYTE)v27 )
+      {
+        if ( (_BYTE)v27 == 99 )
+        {
+          v28 = v2->field_2C;
+          v29 = v4->field_2C;
+          if ( v28 < v29 )
+          {
+            v2->field_2C = v29;
+            v194 = v29 - v28;
+          }
+        }
+        else
+        {
+          v27 = (char)v27;
+          v6 = (char)v27 + v2->field_2C < 0;
+          v2->field_2C += (char)v27;
+          if ( v6 )
+            v2->field_2C = 0;
+          v194 = v27;
+        }
+      }
+      LOBYTE(v30) = BYTE3(v26->field_30);
+      if ( (_BYTE)v30 )
+      {
+        if ( (_BYTE)v30 == 99 )
+        {
+          v31 = v2->field_30;
+          v32 = v4->field_30;
+          if ( v31 < v32 )
+          {
+            v2->field_30 = v32;
+            v210 = v32 - v31;
+          }
+        }
+        else
+        {
+          v30 = (char)v30;
+          v6 = (char)v30 + v2->field_30 < 0;
+          v2->field_30 += (char)v30;
+          if ( v6 )
+            v2->field_30 = 0;
+          v210 = v30;
+        }
+      }
+      LOBYTE(v33) = LOBYTE(v26->field_34);
+      if ( (_BYTE)v33 )
+      {
+        if ( (_BYTE)v33 == 99 )
+        {
+          v34 = v2->field_34;
+          v35 = v4->field_34;
+          if ( v34 < v35 )
+          {
+            v2->field_34 = v35;
+            v208 = v35 - v34;
+          }
+        }
+        else
+        {
+          v33 = (char)v33;
+          v6 = (char)v33 + v2->field_34 < 0;
+          v2->field_34 += (char)v33;
+          if ( v6 )
+            v2->field_34 = 0;
+          v208 = v33;
+        }
+      }
+      LOBYTE(v36) = BYTE1(v26->field_34);
+      if ( (_BYTE)v36 )
+      {
+        if ( (_BYTE)v36 == 99 )
+        {
+          v37 = v2->field_38;
+          v38 = v4->field_38;
+          if ( v37 < v38 )
+          {
+            v2->field_38 = v38;
+            v197 = v38 - v37;
+          }
+        }
+        else
+        {
+          v36 = (char)v36;
+          v6 = (char)v36 + v2->field_38 < 0;
+          v2->field_38 += (char)v36;
+          if ( v6 )
+            v2->field_38 = 0;
+          v197 = v36;
+        }
+      }
+      LOBYTE(v39) = BYTE2(v26->field_34);
+      if ( v39 )
+      {
+        if ( v39 == 99 )
+        {
+          v40 = v2->field_3C;
+          v41 = v4->field_3C;
+          if ( v40 < v41 )
+          {
+            v2->field_3C = v41;
+            v205 = v41 - v40;
+          }
+        }
+        else
+        {
+          v39 = v39;
+          v6 = v39 + v2->field_3C < 0;
+          v2->field_3C += v39;
+          if ( v6 )
+            v2->field_3C = 0;
+          v205 = v39;
+        }
+      }
+      LOBYTE(v42) = BYTE3(v26->field_34);
+      if ( (_BYTE)v42 )
+      {
+        if ( (_BYTE)v42 == 99 )
+        {
+          v43 = v2->field_40;
+          v44 = v4->field_40;
+          if ( v43 < v44 )
+          {
+            v2->field_40 = v44;
+            v203 = v44 - v43;
+          }
+        }
+        else
+        {
+          v42 = (char)v42;
+          v6 = (char)v42 + v2->field_40 < 0;
+          v2->field_40 += (char)v42;
+          if ( v6 )
+            v2->field_40 = 0;
+          v203 = v42;
+        }
+      }
+      v45 = v26->field_38[0];
+      if ( v45 )
+      {
+        v196 = am_40D402(v193, v45);
+        v192 = v26->field_38[0] - v196;
+      }
+      LOBYTE(v46) = v26->field_38[1];
+      if ( (_BYTE)v46 )
+      {
+        if ( (_BYTE)v46 == 99 )
+        {
+          v47 = v2->field_28;
+          v48 = v4->field_28;
+          if ( v47 < v48 )
+          {
+            v2->field_28 = v48;
+            v201 = v48 - v47;
+          }
+        }
+        else
+        {
+          v46 = (char)v46;
+          v6 = (char)v46 + v2->field_28 < 0;
+          v2->field_28 += (char)v46;
+          if ( v6 )
+            v2->field_28 = 0;
+          v201 = v46;
+        }
+      }
+      LOBYTE(v49) = v26->field_38[2];
+      if ( (_BYTE)v49 )
+      {
+        if ( (_BYTE)v49 == 99 )
+        {
+          v50 = v2->field_24;
+          v51 = v4->field_24;
+          if ( v50 < v51 )
+          {
+            v2->field_24 = v51;
+            v199 = v51 - v50;
+          }
+        }
+        else
+        {
+          v49 = (char)v49;
+          v6 = (char)v49 + v2->field_24 < 0;
+          v2->field_24 += (char)v49;
+          if ( v6 )
+            v2->field_24 = 0;
+          v199 = v49;
+        }
+      }
+      LOBYTE(v52) = v26->field_38[3];
+      if ( (_BYTE)v52 )
+      {
+        if ( (_BYTE)v52 == 99 )
+        {
+          v53 = v2->field_2C;
+          v54 = v4->field_2C;
+          if ( v53 > v54 )
+          {
+            v4->field_2C = v53;
+            v211 = v53 - v54;
+          }
+        }
+        else
+        {
+          v52 = (char)v52;
+          v6 = (char)v52 + v4->field_2C < 0;
+          v4->field_2C += (char)v52;
+          if ( v6 )
+            v4->field_2C = 0;
+          v211 = v52;
+        }
+      }
+      LOBYTE(v55) = v26->field_38[4];
+      if ( (_BYTE)v55 )
+      {
+        if ( (_BYTE)v55 == 99 )
+        {
+          v56 = v2->field_30;
+          v57 = v4->field_30;
+          if ( v56 > v57 )
+          {
+            v4->field_30 = v56;
+            v209 = v56 - v57;
+          }
+        }
+        else
+        {
+          v55 = (char)v55;
+          v6 = (char)v55 + v4->field_30 < 0;
+          v4->field_30 += (char)v55;
+          if ( v6 )
+            v4->field_30 = 0;
+          v209 = v55;
+        }
+      }
+      LOBYTE(v58) = v26->field_38[5];
+      if ( (_BYTE)v58 )
+      {
+        if ( (_BYTE)v58 == 99 )
+        {
+          v59 = v2->field_34;
+          v60 = v4->field_34;
+          if ( v59 > v60 )
+          {
+            v4->field_34 = v59;
+            v207 = v59 - v60;
+          }
+        }
+        else
+        {
+          v58 = (char)v58;
+          v6 = (char)v58 + v4->field_34 < 0;
+          v4->field_34 += (char)v58;
+          if ( v6 )
+            v4->field_34 = 0;
+          v207 = v58;
+        }
+      }
+      LOBYTE(v61) = v26->field_38[6];
+      if ( (_BYTE)v61 )
+      {
+        if ( (_BYTE)v61 == 99 )
+        {
+          v62 = v2->field_38;
+          v63 = v4->field_38;
+          if ( v62 > v63 )
+          {
+            v4->field_38 = v62;
+            v206 = v62 - v63;
+          }
+        }
+        else
+        {
+          v61 = (char)v61;
+          v6 = (char)v61 + v4->field_38 < 0;
+          v4->field_38 += (char)v61;
+          if ( v6 )
+            v4->field_38 = 0;
+          v206 = v61;
+        }
+      }
+      LOBYTE(v64) = v26->field_38[7];
+      if ( (_BYTE)v64 )
+      {
+        if ( (_BYTE)v64 == 99 )
+        {
+          v65 = v2->field_3C;
+          v66 = v4->field_3C;
+          if ( v65 > v66 )
+          {
+            v4->field_3C = v65;
+            v204 = v65 - v66;
+          }
+        }
+        else
+        {
+          v64 = (char)v64;
+          v6 = (char)v64 + v4->field_3C < 0;
+          v4->field_3C += (char)v64;
+          if ( v6 )
+            v4->field_3C = 0;
+          v204 = v64;
+        }
+      }
+      LOBYTE(v67) = v26->field_38[8];
+      if ( (_BYTE)v67 )
+      {
+        if ( (_BYTE)v67 == 99 )
+        {
+          v68 = v2->field_40;
+          v69 = v4->field_40;
+          if ( v68 > v69 )
+          {
+            v4->field_40 = v68;
+            v202 = v68 - v69;
+          }
+        }
+        else
+        {
+          v67 = (char)v67;
+          v6 = (char)v67 + v4->field_40 < 0;
+          v4->field_40 += (char)v67;
+          if ( v6 )
+            v4->field_40 = 0;
+          v202 = v67;
+        }
+      }
+      v70 = v26->field_38[9];
+      if ( v70 )
+      {
+        v195 = am_40D402(v189, v70);
+        v191 = v26->field_38[9] - v195;
+      }
+      LOBYTE(v71) = v26->field_38[10];
+      if ( (_BYTE)v71 )
+      {
+        if ( (_BYTE)v71 == 99 )
+        {
+          v72 = v2->field_28;
+          v73 = v4->field_28;
+          if ( v72 > v73 )
+          {
+            v4->field_28 = v72;
+            v200 = v72 - v73;
+          }
+        }
+        else
+        {
+          v71 = (char)v71;
+          v6 = (char)v71 + v4->field_28 < 0;
+          v4->field_28 += (char)v71;
+          if ( v6 )
+            v4->field_28 = 0;
+          v200 = v71;
+        }
+      }
+      LOBYTE(v74) = v26->field_38[11];
+      if ( (_BYTE)v74 )
+      {
+        if ( (_BYTE)v74 == 99 )
+        {
+          v75 = v2->field_24;
+          v76 = v4->field_24;
+          if ( v75 > v76 )
+          {
+            v4->field_24 = v75;
+            v198 = v75 - v76;
+          }
+        }
+        else
+        {
+          v74 = (char)v74;
+          v6 = (char)v74 + v4->field_24 < 0;
+          v4->field_24 += (char)v74;
+          if ( v6 )
+            v4->field_24 = 0;
+          v198 = v74;
+        }
+      }
+      LOBYTE(v77) = v26->field_38[12];
+      if ( (_BYTE)v77 )
+      {
+        if ( (_BYTE)v77 == 99 )
+        {
+          v78 = v2->field_2C;
+          v79 = v4->field_2C;
+          if ( v78 != v79 )
+          {
+            if ( v78 <= v79 )
+            {
+              v2->field_2C = v79;
+              v194 = v79 - v78;
+            }
+            else
+            {
+              v4->field_2C = v78;
+              v211 = v78 - v79;
+            }
+          }
+        }
+        else
+        {
+          v77 = (char)v77;
+          v2->field_2C += (char)v77;
+          v4->field_2C += (char)v77;
+          if ( v2->field_2C < 0 )
+            v2->field_2C = 0;
+          if ( v4->field_2C < 0 )
+            v4->field_2C = 0;
+          v194 = v77;
+          v211 = v77;
+        }
+      }
+      LOBYTE(v80) = v26->field_38[13];
+      if ( (_BYTE)v80 )
+      {
+        if ( (_BYTE)v80 == 99 )
+        {
+          v81 = v2->field_30;
+          v82 = v4->field_30;
+          if ( v81 != v82 )
+          {
+            if ( v81 <= v82 )
+            {
+              v2->field_30 = v82;
+              v210 = v82 - v81;
+            }
+            else
+            {
+              v4->field_30 = v81;
+              v209 = v81 - v82;
+            }
+          }
+        }
+        else
+        {
+          v80 = (char)v80;
+          v2->field_30 += (char)v80;
+          v4->field_30 += (char)v80;
+          if ( v2->field_30 < 0 )
+            v2->field_30 = 0;
+          if ( v4->field_30 < 0 )
+            v4->field_30 = 0;
+          v209 = v80;
+          v210 = v80;
+        }
+      }
+      LOBYTE(v83) = v26->field_38[14];
+      if ( (_BYTE)v83 )
+      {
+        if ( (_BYTE)v83 == 99 )
+        {
+          v84 = v2->field_34;
+          v85 = v4->field_34;
+          if ( v84 != v85 )
+          {
+            if ( v84 <= v85 )
+            {
+              v2->field_34 = v85;
+              v208 = v85 - v84;
+            }
+            else
+            {
+              v4->field_34 = v84;
+              v207 = v84 - v85;
+            }
+          }
+        }
+        else
+        {
+          v83 = (char)v83;
+          v2->field_34 += (char)v83;
+          v4->field_34 += (char)v83;
+          if ( v2->field_34 < 0 )
+            v2->field_34 = 0;
+          if ( v4->field_34 < 0 )
+            v4->field_34 = 0;
+          v208 = v83;
+          v207 = v83;
+        }
+      }
+      LOBYTE(v86) = v26->field_38[15];
+      if ( (_BYTE)v86 )
+      {
+        if ( (_BYTE)v86 == 99 )
+        {
+          v87 = v2->field_38;
+          v88 = v4->field_38;
+          if ( v87 != v88 )
+          {
+            if ( v87 <= v88 )
+            {
+              v2->field_38 = v88;
+              v197 = v88 - v87;
+            }
+            else
+            {
+              v4->field_38 = v87;
+              v206 = v87 - v88;
+            }
+          }
+        }
+        else
+        {
+          v86 = (char)v86;
+          v2->field_38 += (char)v86;
+          v4->field_38 += (char)v86;
+          if ( v2->field_38 < 0 )
+            v2->field_38 = 0;
+          if ( v4->field_38 < 0 )
+            v4->field_38 = 0;
+          v197 = v86;
+          v206 = v86;
+        }
+      }
+      LOBYTE(v89) = v26->field_48[0];
+      if ( v89 )
+      {
+        if ( v89 == 99 )
+        {
+          v90 = v2->field_3C;
+          v91 = v4->field_3C;
+          if ( v90 != v91 )
+          {
+            if ( v90 <= v91 )
+            {
+              v205 = v91 > v90;
+              v2->field_3C = v91;
+            }
+            else
+            {
+              v204 = 1;
+              v4->field_3C = v90;
+            }
+          }
+        }
+        else
+        {
+          v89 = v89;
+          v2->field_3C += v89;
+          v4->field_3C += v89;
+          if ( v2->field_3C < 0 )
+            v2->field_3C = 0;
+          if ( v4->field_3C < 0 )
+            v4->field_3C = 0;
+          v205 = v89;
+          v204 = v89;
+        }
+      }
+      LOBYTE(v92) = v26->field_48[1];
+      if ( (_BYTE)v92 )
+      {
+        if ( (_BYTE)v92 == 99 )
+        {
+          v93 = v2->field_40;
+          v94 = v4->field_40;
+          if ( v93 != v94 )
+          {
+            if ( v93 <= v94 )
+            {
+              v2->field_40 = v94;
+              v203 = v94 - v93;
+            }
+            else
+            {
+              v4->field_40 = v93;
+              v202 = v93 - v94;
+            }
+          }
+        }
+        else
+        {
+          v92 = (char)v92;
+          v2->field_40 += (char)v92;
+          v4->field_40 += (char)v92;
+          if ( v2->field_40 < 0 )
+            v2->field_40 = 0;
+          if ( v4->field_40 < 0 )
+            v4->field_40 = 0;
+          v203 = v92;
+          v202 = v92;
+        }
+      }
+      v95 = v26->field_48[2];
+      if ( v95 )
+      {
+        v96 = am_40D402(v193, v95);
+        v97 = v26->field_48[2];
+        v196 = v96;
+        v98 = am_40D402(v189, v97);
+        v195 = v98;
+        v99 = v26->field_48[2] - v98;
+        v192 = v26->field_48[2] - v196;
+        v191 = v99;
+      }
+      LOBYTE(v100) = v26->field_48[3];
+      if ( (_BYTE)v100 )
+      {
+        if ( (_BYTE)v100 == 99 )
+        {
+          v101 = v2->field_28;
+          v102 = v4->field_28;
+          if ( v101 != v102 )
+          {
+            if ( v101 <= v102 )
+            {
+              v2->field_28 = v102;
+              v201 = v102 - v101;
+            }
+            else
+            {
+              v4->field_28 = v101;
+              v200 = v101 - v102;
+            }
+          }
+        }
+        else
+        {
+          v100 = (char)v100;
+          v2->field_28 += (char)v100;
+          v4->field_28 += (char)v100;
+          if ( v2->field_28 < 0 )
+            v2->field_28 = 0;
+          if ( v4->field_28 < 0 )
+            v4->field_28 = 0;
+          v201 = v100;
+          v200 = v100;
+        }
+      }
+      LOBYTE(v103) = v26->field_48[4];
+      break;
+    case 0:
+LABEL_231:
+      v104 = pCard->field_48[6];
+      v105 = v104 + (pCard->field_48[5] == 1);
+      v106 = 0;
+      dword_4FAA68 = v104 + (pCard->field_48[5] == 1);
+      dword_4FAA64 = v104;
+      if ( v104 > 0 )
+      {
+        do
+        {
+          am_40A283(v193, v105);
+          ++v106;
+        }
+        while ( v106 < pCard->field_48[6] );
+      }
+      v107 = pCard;
+      am_byte_4FAA77 = am_40BB49(v193) > dword_4E1874;
+      LOBYTE(v108) = pCard->field_48[7];
+      if ( (_BYTE)v108 )
+      {
+        if ( (_BYTE)v108 == 99 )
+        {
+          v109 = v2->field_2C;
+          v110 = v4->field_2C;
+          if ( v109 < v110 )
+          {
+            v2->field_2C = v110;
+            v194 = v110 - v109;
+          }
+        }
+        else
+        {
+          v108 = (char)v108;
+          v6 = (char)v108 + v2->field_2C < 0;
+          v2->field_2C += (char)v108;
+          if ( v6 )
+            v2->field_2C = 0;
+          v194 = v108;
+        }
+      }
+      LOBYTE(v111) = v107->field_48[8];
+      if ( (_BYTE)v111 )
+      {
+        if ( (_BYTE)v111 == 99 )
+        {
+          v112 = v2->field_30;
+          v113 = v4->field_30;
+          if ( v112 < v113 )
+          {
+            v2->field_30 = v113;
+            v210 = v113 - v112;
+          }
+        }
+        else
+        {
+          v111 = (char)v111;
+          v6 = (char)v111 + v2->field_30 < 0;
+          v2->field_30 += (char)v111;
+          if ( v6 )
+            v2->field_30 = 0;
+          v210 = v111;
+        }
+      }
+      LOBYTE(v114) = v107->field_48[9];
+      if ( (_BYTE)v114 )
+      {
+        if ( (_BYTE)v114 == 99 )
+        {
+          v115 = v2->field_34;
+          v116 = v4->field_34;
+          if ( v115 < v116 )
+          {
+            v2->field_34 = v116;
+            v208 = v116 - v115;
+          }
+        }
+        else
+        {
+          v114 = (char)v114;
+          v6 = (char)v114 + v2->field_34 < 0;
+          v2->field_34 += (char)v114;
+          if ( v6 )
+            v2->field_34 = 0;
+          v208 = v114;
+        }
+      }
+      LOBYTE(v117) = v107->field_48[10];
+      if ( (_BYTE)v117 )
+      {
+        if ( (_BYTE)v117 == 99 )
+        {
+          v118 = v2->field_38;
+          v119 = v4->field_38;
+          if ( v118 < v119 )
+          {
+            v2->field_38 = v119;
+            v197 = v119 - v118;
+          }
+        }
+        else
+        {
+          v117 = (char)v117;
+          v6 = (char)v117 + v2->field_38 < 0;
+          v2->field_38 += (char)v117;
+          if ( v6 )
+            v2->field_38 = 0;
+          v197 = v117;
+        }
+      }
+      LOBYTE(v120) = v107->field_48[11];
+      if ( v120 )
+      {
+        if ( v120 == 99 )
+        {
+          v121 = v2->field_3C;
+          v122 = v4->field_3C;
+          if ( v121 < v122 )
+          {
+            v2->field_3C = v122;
+            v205 = v122 - v121;
+          }
+        }
+        else
+        {
+          v120 = v120;
+          v6 = v120 + v2->field_3C < 0;
+          v2->field_3C += v120;
+          if ( v6 )
+            v2->field_3C = 0;
+          v205 = v120;
+        }
+      }
+      LOBYTE(v123) = v107->field_48[12];
+      if ( (_BYTE)v123 )
+      {
+        if ( (_BYTE)v123 == 99 )
+        {
+          v124 = v2->field_40;
+          v125 = v4->field_40;
+          if ( v124 < v125 )
+          {
+            v2->field_40 = v125;
+            v203 = v125 - v124;
+          }
+        }
+        else
+        {
+          v123 = (char)v123;
+          v6 = (char)v123 + v2->field_40 < 0;
+          v2->field_40 += (char)v123;
+          if ( v6 )
+            v2->field_40 = 0;
+          v203 = v123;
+        }
+      }
+      v126 = v107->field_48[13];
+      if ( v126 )
+      {
+        v196 = am_40D402(v193, v126);
+        v192 = v107->field_48[13] - v196;
+      }
+      LOBYTE(v127) = v107->field_48[14];
+      if ( (_BYTE)v127 )
+      {
+        if ( (_BYTE)v127 == 99 )
+        {
+          v128 = v2->field_28;
+          v129 = v4->field_28;
+          if ( v128 < v129 )
+          {
+            v2->field_28 = v129;
+            v201 = v129 - v128;
+          }
+        }
+        else
+        {
+          v127 = (char)v127;
+          v6 = (char)v127 + v2->field_28 < 0;
+          v2->field_28 += (char)v127;
+          if ( v6 )
+            v2->field_28 = 0;
+          v201 = v127;
+        }
+      }
+      LOBYTE(v130) = v107->field_48[15];
+      if ( (_BYTE)v130 )
+      {
+        if ( (_BYTE)v130 == 99 )
+        {
+          v131 = v2->field_24;
+          v132 = v4->field_24;
+          if ( v131 < v132 )
+          {
+            v2->field_24 = v132;
+            v199 = v132 - v131;
+          }
+        }
+        else
+        {
+          v130 = (char)v130;
+          v6 = (char)v130 + v2->field_24 < 0;
+          v2->field_24 += (char)v130;
+          if ( v6 )
+            v2->field_24 = 0;
+          v199 = v130;
+        }
+      }
+      LOBYTE(v133) = v107->field_58[0];
+      if ( (_BYTE)v133 )
+      {
+        if ( (_BYTE)v133 == 99 )
+        {
+          v134 = v2->field_2C;
+          v135 = v4->field_2C;
+          if ( v134 > v135 )
+          {
+            v4->field_2C = v134;
+            v211 = v134 - v135;
+          }
+        }
+        else
+        {
+          v133 = (char)v133;
+          v6 = (char)v133 + v4->field_2C < 0;
+          v4->field_2C += (char)v133;
+          if ( v6 )
+            v4->field_2C = 0;
+          v211 = v133;
+        }
+      }
+      LOBYTE(v136) = v107->field_58[1];
+      if ( (_BYTE)v136 )
+      {
+        if ( (_BYTE)v136 == 99 )
+        {
+          v137 = v2->field_30;
+          v138 = v4->field_30;
+          if ( v137 > v138 )
+          {
+            v4->field_30 = v137;
+            v209 = v137 - v138;
+          }
+        }
+        else
+        {
+          v136 = (char)v136;
+          v6 = (char)v136 + v4->field_30 < 0;
+          v4->field_30 += (char)v136;
+          if ( v6 )
+            v4->field_30 = 0;
+          v209 = v136;
+        }
+      }
+      LOBYTE(v139) = v107->field_58[2];
+      if ( (_BYTE)v139 )
+      {
+        if ( (_BYTE)v139 == 99 )
+        {
+          v140 = v2->field_34;
+          v141 = v4->field_34;
+          if ( v140 > v141 )
+          {
+            v4->field_34 = v140;
+            v207 = v140 - v141;
+          }
+        }
+        else
+        {
+          v139 = (char)v139;
+          v6 = (char)v139 + v4->field_34 < 0;
+          v4->field_34 += (char)v139;
+          if ( v6 )
+            v4->field_34 = 0;
+          v207 = v139;
+        }
+      }
+      LOBYTE(v142) = v107->field_58[3];
+      if ( (_BYTE)v142 )
+      {
+        if ( (_BYTE)v142 == 99 )
+        {
+          v143 = v2->field_38;
+          v144 = v4->field_38;
+          if ( v143 > v144 )
+          {
+            v4->field_38 = v143;
+            v206 = v143 - v144;
+          }
+        }
+        else
+        {
+          v142 = (char)v142;
+          v6 = (char)v142 + v4->field_38 < 0;
+          v4->field_38 += (char)v142;
+          if ( v6 )
+            v4->field_38 = 0;
+          v206 = v142;
+        }
+      }
+      LOBYTE(v145) = v107->field_58[4];
+      if ( (_BYTE)v145 )
+      {
+        if ( (_BYTE)v145 == 99 )
+        {
+          v146 = v2->field_3C;
+          v147 = v4->field_3C;
+          if ( v146 > v147 )
+          {
+            v4->field_3C = v146;
+            v204 = v146 - v147;
+          }
+        }
+        else
+        {
+          v145 = (char)v145;
+          v6 = (char)v145 + v4->field_3C < 0;
+          v4->field_3C += (char)v145;
+          if ( v6 )
+            v4->field_3C = 0;
+          v204 = v145;
+        }
+      }
+      LOBYTE(v148) = v107->field_58[5];
+      if ( (_BYTE)v148 )
+      {
+        if ( (_BYTE)v148 == 99 )
+        {
+          v149 = v2->field_40;
+          v150 = v4->field_40;
+          if ( v149 > v150 )
+          {
+            v4->field_40 = v149;
+            v202 = v149 - v150;
+          }
+        }
+        else
+        {
+          v148 = (char)v148;
+          v6 = (char)v148 + v4->field_40 < 0;
+          v4->field_40 += (char)v148;
+          if ( v6 )
+            v4->field_40 = 0;
+          v202 = v148;
+        }
+      }
+      v151 = v107->field_58[6];
+      if ( v151 )
+      {
+        v195 = am_40D402(v189, v151);
+        v191 = v107->field_58[6] - v195;
+      }
+      LOBYTE(v152) = v107->field_58[7];
+      if ( (_BYTE)v152 )
+      {
+        if ( (_BYTE)v152 == 99 )
+        {
+          v153 = v2->field_28;
+          v154 = v4->field_28;
+          if ( v153 > v154 )
+          {
+            v4->field_28 = v153;
+            v200 = v153 - v154;
+          }
+        }
+        else
+        {
+          v152 = (char)v152;
+          v6 = (char)v152 + v4->field_28 < 0;
+          v4->field_28 += (char)v152;
+          if ( v6 )
+            v4->field_28 = 0;
+          v200 = v152;
+        }
+      }
+      LOBYTE(v155) = v107->field_58[8];
+      if ( (_BYTE)v155 )
+      {
+        if ( (_BYTE)v155 == 99 )
+        {
+          v156 = v2->field_24;
+          v157 = v4->field_24;
+          if ( v156 > v157 )
+          {
+            v4->field_24 = v156;
+            v198 = v156 - v157;
+          }
+        }
+        else
+        {
+          v155 = (char)v155;
+          v6 = (char)v155 + v4->field_24 < 0;
+          v4->field_24 += (char)v155;
+          if ( v6 )
+            v4->field_24 = 0;
+          v198 = v155;
+        }
+      }
+      LOBYTE(v158) = v107->field_58[9];
+      if ( (_BYTE)v158 )
+      {
+        if ( (_BYTE)v158 == 99 )
+        {
+          v159 = v2->field_2C;
+          v160 = v4->field_2C;
+          if ( v159 != v160 )
+          {
+            if ( v159 <= v160 )
+            {
+              v2->field_2C = v160;
+              v194 = v160 - v159;
+            }
+            else
+            {
+              v4->field_2C = v159;
+              v211 = v159 - v160;
+            }
+          }
+        }
+        else
+        {
+          v158 = (char)v158;
+          v2->field_2C += (char)v158;
+          v4->field_2C += (char)v158;
+          if ( v2->field_2C < 0 )
+            v2->field_2C = 0;
+          if ( v4->field_2C < 0 )
+            v4->field_2C = 0;
+          v194 = v158;
+          v211 = v158;
+        }
+      }
+      LOBYTE(v161) = v107->field_58[10];
+      if ( (_BYTE)v161 )
+      {
+        if ( (_BYTE)v161 == 99 )
+        {
+          v162 = v2->field_30;
+          v163 = v4->field_30;
+          if ( v162 != v163 )
+          {
+            if ( v162 <= v163 )
+            {
+              v2->field_30 = v163;
+              v210 = v163 - v162;
+            }
+            else
+            {
+              v4->field_30 = v162;
+              v209 = v162 - v163;
+            }
+          }
+        }
+        else
+        {
+          v161 = (char)v161;
+          v2->field_30 += (char)v161;
+          v4->field_30 += (char)v161;
+          if ( v2->field_30 < 0 )
+            v2->field_30 = 0;
+          if ( v4->field_30 < 0 )
+            v4->field_30 = 0;
+          v209 = v161;
+          v210 = v161;
+        }
+      }
+      LOBYTE(v164) = v107->field_58[11];
+      if ( (_BYTE)v164 )
+      {
+        if ( (_BYTE)v164 == 99 )
+        {
+          v165 = v2->field_34;
+          v166 = v4->field_34;
+          if ( v165 != v166 )
+          {
+            if ( v165 <= v166 )
+            {
+              v2->field_34 = v166;
+              v208 = v166 - v165;
+            }
+            else
+            {
+              v4->field_34 = v165;
+              v207 = v165 - v166;
+            }
+          }
+        }
+        else
+        {
+          v164 = (char)v164;
+          v2->field_34 += (char)v164;
+          v4->field_34 += (char)v164;
+          if ( v2->field_34 < 0 )
+            v2->field_34 = 0;
+          if ( v4->field_34 < 0 )
+            v4->field_34 = 0;
+          v208 = v164;
+          v207 = v164;
+        }
+      }
+      LOBYTE(v167) = v107->field_58[12];
+      if ( (_BYTE)v167 )
+      {
+        if ( (_BYTE)v167 == 99 )
+        {
+          v168 = v2->field_38;
+          v169 = v4->field_38;
+          if ( v168 != v169 )
+          {
+            if ( v168 <= v169 )
+            {
+              v2->field_38 = v169;
+              v197 = v169 - v168;
+            }
+            else
+            {
+              v4->field_38 = v168;
+              v206 = v168 - v169;
+            }
+          }
+        }
+        else
+        {
+          v167 = (char)v167;
+          v2->field_38 += (char)v167;
+          v4->field_38 += (char)v167;
+          if ( v2->field_38 < 0 )
+            v2->field_38 = 0;
+          if ( v4->field_38 < 0 )
+            v4->field_38 = 0;
+          v197 = v167;
+          v206 = v167;
+        }
+      }
+      LOBYTE(v170) = v107->field_58[13];
+      if ( v170 )
+      {
+        if ( v170 == 99 )
+        {
+          v171 = v2->field_3C;
+          v172 = v4->field_3C;
+          if ( v171 != v172 )
+          {
+            if ( v171 <= v172 )
+            {
+              v205 = v172 > v171;
+              v2->field_3C = v172;
+            }
+            else
+            {
+              v204 = 1;
+              v4->field_3C = v171;
+            }
+          }
+        }
+        else
+        {
+          v170 = v170;
+          v2->field_3C += v170;
+          v4->field_3C += v170;
+          if ( v2->field_3C < 0 )
+            v2->field_3C = 0;
+          if ( v4->field_3C < 0 )
+            v4->field_3C = 0;
+          v205 = v170;
+          v204 = v170;
+        }
+      }
+      LOBYTE(v173) = v107->field_58[14];
+      if ( (_BYTE)v173 )
+      {
+        if ( (_BYTE)v173 == 99 )
+        {
+          v174 = v2->field_40;
+          v175 = v4->field_40;
+          if ( v174 != v175 )
+          {
+            if ( v174 <= v175 )
+            {
+              v2->field_40 = v175;
+              v203 = v175 - v174;
+            }
+            else
+            {
+              v4->field_40 = v174;
+              v202 = v174 - v175;
+            }
+          }
+        }
+        else
+        {
+          v173 = (char)v173;
+          v2->field_40 += (char)v173;
+          v4->field_40 += (char)v173;
+          if ( v2->field_40 < 0 )
+            v2->field_40 = 0;
+          if ( v4->field_40 < 0 )
+            v4->field_40 = 0;
+          v203 = v173;
+          v202 = v173;
+        }
+      }
+      v176 = v107->field_58[15];
+      if ( v176 )
+      {
+        v177 = am_40D402(v193, v176);
+        v178 = v107->field_58[15];
+        v196 = v177;
+        v179 = am_40D402(v189, v178);
+        v195 = v179;
+        v180 = v107->field_58[15] - v179;
+        v192 = v107->field_58[15] - v196;
+        v191 = v180;
+      }
+      LOBYTE(v181) = LOBYTE(v107->field_68);
+      if ( (_BYTE)v181 )
+      {
+        if ( (_BYTE)v181 == 99 )
+        {
+          v182 = v2->field_28;
+          v183 = v4->field_28;
+          if ( v182 != v183 )
+          {
+            if ( v182 <= v183 )
+            {
+              v2->field_28 = v183;
+              v201 = v183 - v182;
+            }
+            else
+            {
+              v4->field_28 = v182;
+              v200 = v182 - v183;
+            }
+          }
+        }
+        else
+        {
+          v181 = (char)v181;
+          v2->field_28 += (char)v181;
+          v4->field_28 += (char)v181;
+          if ( v2->field_28 < 0 )
+            v2->field_28 = 0;
+          if ( v4->field_28 < 0 )
+            v4->field_28 = 0;
+          v201 = v181;
+          v200 = v181;
+        }
+      }
+      LOBYTE(v103) = BYTE1(v107->field_68);
+      break;
+  }
+  if ( (_BYTE)v103 )
+  {
+    if ( (_BYTE)v103 == 99 )
+    {
+      v184 = v2->field_24;
+      v185 = v4->field_24;
+      if ( v184 != v185 )
+      {
+        if ( v184 <= v185 )
+        {
+          v2->field_24 = v185;
+          v199 = v185 - v184;
+        }
+        else
+        {
+          v4->field_24 = v184;
+          v198 = v184 - v185;
+        }
+      }
+    }
+    else
+    {
+      v103 = (char)v103;
+      v2->field_24 += (char)v103;
+      v4->field_24 += (char)v103;
+      if ( v2->field_24 < 0 )
+        v2->field_24 = 0;
+      if ( v4->field_24 < 0 )
+        v4->field_24 = 0;
+      v199 = v103;
+      v198 = v103;
+    }
+  }
+  if ( v194 > 0 || v211 > 0 )
+    ArcomageGame::PlaySound(0x1Eu);
+  if ( v194 < 0 || v211 < 0 )
+    ArcomageGame::PlaySound(0x1Fu);
+  if ( v210 > 0 || v209 > 0 )
+    ArcomageGame::PlaySound(0x21u);
+  if ( v210 < 0 || v209 < 0 )
+    ArcomageGame::PlaySound(0x22u);
+  if ( v208 > 0 || v207 > 0 )
+    ArcomageGame::PlaySound(0x24u);
+  if ( v208 < 0 || v207 < 0 )
+    ArcomageGame::PlaySound(0x25u);
+  if ( v197 > 0 || v206 > 0 )
+    ArcomageGame::PlaySound(0x27u);
+  if ( v197 < 0 || v206 < 0 )
+    ArcomageGame::PlaySound(0x28u);
+  if ( v205 > 0 || v204 > 0 )
+    ArcomageGame::PlaySound(0x2Au);
+  if ( v205 < 0 || v204 < 0 )
+    ArcomageGame::PlaySound(0x2Bu);
+  if ( v203 > 0 || v202 > 0 )
+    ArcomageGame::PlaySound(0x2Du);
+  if ( v203 < 0 || v202 < 0 )
+    ArcomageGame::PlaySound(0x2Eu);
+  if ( v192 || v191 || v196 || v195 )
+    ArcomageGame::PlaySound(0x30u);
+  if ( v201 > 0 || v200 > 0 )
+    ArcomageGame::PlaySound(0x31u);
+  if ( v201 < 0 || v200 < 0 )
+    ArcomageGame::PlaySound(0x32u);
+  if ( v199 > 0 || v198 > 0 )
+    ArcomageGame::PlaySound(0x34u);
+  if ( v199 < 0 || v198 < 0 )
+    ArcomageGame::PlaySound(0x35u);
+  if ( v193 )
+  {
+    if ( v194 )
+    {
+      v187.x = 573;
+      v187.y = 92;
+      am_40D2B4(&v187, v194);
+    }
+    if ( v211 )
+    {
+      v187.x = 26;
+      v187.y = 92;
+      am_40D2B4(&v187, v211);
+    }
+    if ( v210 )
+    {
+      v187.x = 573;
+      v187.y = 164;
+      am_40D2B4(&v187, v210);
+    }
+    if ( v209 )
+    {
+      v187.x = 26;
+      v187.y = 164;
+      am_40D2B4(&v187, v209);
+    }
+    if ( v208 )
+    {
+      v187.x = 573;
+      v187.y = 236;
+      am_40D2B4(&v187, v208);
+    }
+    if ( v207 )
+    {
+      v187.x = 26;
+      v187.y = 236;
+      am_40D2B4(&v187, v207);
+    }
+    if ( v197 )
+    {
+      v187.x = 563;
+      v187.y = 114;
+      am_40D2B4(&v187, v197);
+    }
+    if ( v206 )
+    {
+      v187.x = 16;
+      v187.y = 114;
+      am_40D2B4(&v187, v206);
+    }
+    if ( v205 )
+    {
+      v187.x = 563;
+      v187.y = 186;
+      am_40D2B4(&v187, v205);
+    }
+    if ( v204 )
+    {
+      v187.x = 16;
+      v187.y = 186;
+      am_40D2B4(&v187, v204);
+    }
+    if ( v203 )
+    {
+      v187.x = 563;
+      v187.y = 258;
+      am_40D2B4(&v187, v203);
+    }
+    if ( v202 )
+    {
+      v187.x = 16;
+      v187.y = 258;
+      am_40D2B4(&v187, v202);
+    }
+    v186 = 296;
+    if ( v201 )
+    {
+      v187.x = 442;
+      v187.y = 296;
+      am_40D2B4(&v187, v201);
+    }
+    if ( v200 )
+    {
+      v187.x = 180;
+      v187.y = 296;
+      am_40D2B4(&v187, v200);
+    }
+    if ( v199 )
+    {
+      v187.x = 514;
+      v187.y = 296;
+      am_40D2B4(&v187, v199);
+    }
+    if ( v198 )
+    {
+      v187.x = 122;
+      v187.y = 296;
+      am_40D2B4(&v187, v198);
+    }
+    if ( v196 )
+    {
+      v187.x = 442;
+      v187.y = 296;
+      am_40D2B4(&v187, v196);
+    }
+    if ( v192 )
+    {
+      v187.x = 514;
+      v187.y = 296;
+      am_40D2B4(&v187, v192);
+    }
+    if ( v195 )
+    {
+      v187.x = 180;
+      v187.y = 296;
+      am_40D2B4(&v187, v195);
+    }
+    if ( v191 )
+    {
+      v187.x = 122;
+      goto LABEL_567;
+    }
+  }
+  else
+  {
+    if ( v194 )
+    {
+      v187.x = 26;
+      v187.y = 92;
+      am_40D2B4(&v187, v194);
+    }
+    if ( v211 )
+    {
+      v187.x = 573;
+      v187.y = 92;
+      am_40D2B4(&v187, v211);
+    }
+    if ( v210 )
+    {
+      v187.x = 26;
+      v187.y = 164;
+      am_40D2B4(&v187, v210);
+    }
+    if ( v209 )
+    {
+      v187.x = 573;
+      v187.y = 164;
+      am_40D2B4(&v187, v209);
+    }
+    if ( v208 )
+    {
+      v187.x = 26;
+      v187.y = 236;
+      am_40D2B4(&v187, v208);
+    }
+    if ( v207 )
+    {
+      v187.x = 573;
+      v187.y = 236;
+      am_40D2B4(&v187, v207);
+    }
+    if ( v197 )
+    {
+      v187.x = 16;
+      v187.y = 114;
+      am_40D2B4(&v187, v197);
+    }
+    if ( v206 )
+    {
+      v187.x = 563;
+      v187.y = 114;
+      am_40D2B4(&v187, v206);
+    }
+    if ( v205 )
+    {
+      v187.x = 16;
+      v187.y = 186;
+      am_40D2B4(&v187, v205);
+    }
+    if ( v204 )
+    {
+      v187.x = 563;
+      v187.y = 186;
+      am_40D2B4(&v187, v204);
+    }
+    if ( v203 )
+    {
+      v187.x = 16;
+      v187.y = 258;
+      am_40D2B4(&v187, v203);
+    }
+    if ( v202 )
+    {
+      v187.x = 563;
+      v187.y = 258;
+      am_40D2B4(&v187, v202);
+    }
+    v186 = 296;
+    if ( v201 )
+    {
+      v187.x = 180;
+      v187.y = 296;
+      am_40D2B4(&v187, v201);
+    }
+    if ( v200 )
+    {
+      v187.x = 442;
+      v187.y = 296;
+      am_40D2B4(&v187, v200);
+    }
+    if ( v199 )
+    {
+      v187.x = 122;
+      v187.y = 296;
+      am_40D2B4(&v187, v199);
+    }
+    if ( v198 )
+    {
+      v187.x = 514;
+      v187.y = 296;
+      am_40D2B4(&v187, v198);
+    }
+    if ( v196 )
+    {
+      v187.x = 180;
+      v187.y = 296;
+      am_40D2B4(&v187, v196);
+    }
+    if ( v192 )
+    {
+      v187.x = 122;
+      v187.y = 296;
+      am_40D2B4(&v187, v192);
+    }
+    if ( v195 )
+    {
+      v187.x = 442;
+      v187.y = 296;
+      am_40D2B4(&v187, v195);
+    }
+    if ( v191 )
+    {
+      v187.x = 514;
+LABEL_567:
+      v187.y = v186;
+      am_40D2B4(&v187, v191);
+      return;
+    }
+  }
+}
+
+
+
+
+//----- (0040D2B4) --------------------------------------------------------
+int __fastcall am_40D2B4(Vec2_int_ *a1, int a2)
+{
+  int v2; // ebp@1
+  Vec2_int_ *v3; // edi@1
+  char *v4; // ebx@1
+  int result; // eax@3
+  unsigned int v6; // esi@7
+  stru272_stru0 *v7; // ecx@10
+  stru272_stru0 *v8; // ecx@12
+  int v9; // edx@17
+  int v10; // ecx@17
+  signed int v11; // [sp+10h] [bp-8h]@1
+  stru272_stru0 **v12; // [sp+14h] [bp-4h]@1
+
+  v11 = 0;
+  v2 = a2;
+  v3 = a1;
+  v4 = byte_4FABD0;
+  v12 = (stru272_stru0 **)array_4FAC10;
+  while ( *v4 )
+  {
+    result = (*v12)->_40E2A7();
+    if ( !result )
+    {
+      *v4 = 0;
+      --v11;
+      v12 -= 1067;
+      v4 -= 4268;
+    }
+    ++v11;
+    v12 += 1067;
+    v4 += 4268;
+    if ( v11 >= 10 )
+      return result;
+  }
+  v6 = 4268 * v11;
+  byte_4FABD0[4268 * v11] = 1;
+  if ( v2 <= 0 )
+  {
+    byte_4FABD1[v6] = 0;
+    v2 = -v2;
+  }
+  else
+  {
+    byte_4FABD1[v6] = 1;
+  }
+  *(unsigned int *)((char *)&unk_4FABD4 + v6) = v3->x - 20;
+  dword_4FABDC[v6 / 4] = v3->x + 20;
+  dword_4FABD8[v6 / 4] = v3->y - 20;
+  dword_4FABE0[v6 / 4] = v3->y + 20;
+  v7 = array_4FAC10[v6 / 0x10AC].ptr_0;
+  dword_4FABE4[v6 / 4] = -60;
+  dword_4FABE8[v6 / 4] = 60;
+  dword_4FABEC[v6 / 4] = 180;
+  dword_4FABF0[v6 / 4] = 0x3F000000u;
+  dword_4FABF4[v6 / 4] = 150;
+  dword_4FABF8[v6 / 4] = 0x42480000u;
+  dword_4FABFC[v6 / 4] = 0x40400000u;
+  dword_4FAC00[v6 / 4] = 0x41000000u;
+  dword_4FAC04[v6 / 4] = 5;
+  dword_4FAC08[v6 / 4] = 15;
+  dword_4FAC0C[v6 / 4] = (int)array_4FAC10[v6 / 0x10AC].field_4;
+  v7->_40E01A((int)((char *)&unk_4FABD4 + v6));
+  if ( 10 * v2 > 150 )
+    v2 = 15;
+  v8 = array_4FAC10[v6 / 0x10AC].ptr_0;
+  if ( v8->field_0 != 0x67707274 )
+    return 2;
+  if ( !v8->field_59 )
+    return 3;
+  v8->field_8 = 10 * v2;
+  v9 = v8->field_4;
+  v8->field_30 = 0.0;
+  v8->field_58 = 0;
+  v8->field_44 = 0;
+  v8->field_4C = 0;
+  v8->field_48 = 0;
+  v8->field_50 = 0;
+  v10 = v8->field_54;
+  do
+  {
+    *(unsigned int *)v10 = 0;
+    v10 += 28;
+    --v9;
+  }
+  while ( v9 );
+  return 0;
+}
+// 40D2B4: using guessed type int __fastcall am_40D2B4(uint, uint);
+// 4FABD8: using guessed type int dword_4FABD8[];
+// 4FABDC: using guessed type int dword_4FABDC[];
+// 4FABE0: using guessed type int dword_4FABE0[];
+// 4FABE4: using guessed type int dword_4FABE4[];
+// 4FABE8: using guessed type int dword_4FABE8[];
+// 4FABEC: using guessed type int dword_4FABEC[];
+// 4FABF0: using guessed type int dword_4FABF0[];
+// 4FABF4: using guessed type int dword_4FABF4[];
+// 4FABF8: using guessed type int dword_4FABF8[];
+// 4FABFC: using guessed type int dword_4FABFC[];
+// 4FAC00: using guessed type int dword_4FAC00[];
+// 4FAC04: using guessed type int dword_4FAC04[];
+// 4FAC08: using guessed type int dword_4FAC08[];
+// 4FAC0C: using guessed type int dword_4FAC0C[];
+
+//----- (0040D402) --------------------------------------------------------
+int __fastcall am_40D402(int a1, int a2)
+{
+  ArcomageGame_stru0 *v2; // ecx@1
+  int v3; // esi@1
+  int result; // eax@3
+
+  v2 = &stru_505708[a1];
+  v3 = v2->field_28;
+  if ( v3 <= 0 )
+  {
+    result = 0;
+  }
+  else
+  {
+    if ( v3 >= -a2 )
+    {
+      result = a2;
+      v2->field_28 = a2 + v3;
+      goto LABEL_7;
+    }
+    a2 += v3;
+    result = -v3;
+    v2->field_28 = 0;
+  }
+  v2->field_24 += a2;
+LABEL_7:
+  if ( v2->field_24 < 0 )
+    v2->field_24 = 0;
+  return result;
+}
+// 40D402: using guessed type int __fastcall am_40D402(uint, uint);
+
+//----- (0040D444) --------------------------------------------------------
+int __cdecl am_40D444()
+{
+  int v0; // esi@1
+  int v1; // edi@1
+  int v2; // eax@1
+  int v3; // eax@23
+  int v4; // edx@25
+  int v5; // ecx@28
+  int v6; // eax@28
+  GUIWindow *v7; // ecx@50
+  signed int v8; // eax@50
+  char *v9; // eax@52
+  signed int v10; // eax@54
+  char *v11; // esi@59
+  char *v12; // esi@65
+  signed int v14; // [sp-4h] [bp-58h]@46
+  char pText[64]; // [sp+Ch] [bp-48h]@1
+  int xy[2]; // [sp+4Ch] [bp-8h]@1
+
+  v0 = -1;
+  v1 = -1;
+  //nullsub_1();
+  xy[0] = 0;
+  xy[1] = 0;
+  inv_strcpy("Ïîáåäè", pText);
+  v2 = 0;
+  xy[1] = 160;
+  xy[0] = 320 - 12 * v2 / 2;
+  pPrimaryWindow_draws_text(-1, pText, xy);
+  if ( stru_505708[0].field_24 < dword_4E1884 )
+  {
+    if ( stru_505708[1].field_24 < dword_4E1884 )
+      goto LABEL_10;
+    v0 = 2;
+  }
+  else
+  {
+    if ( stru_505708[1].field_24 < dword_4E1884 )
+    {
+      v0 = 1;
+    }
+    else
+    {
+      if ( stru_505708[0].field_24 == stru_505708[1].field_24 )
+      {
+        v0 = 0;
+        v1 = 4;
+        goto LABEL_10;
+      }
+      v0 = (stru_505708[0].field_24 <= stru_505708[1].field_24) + 1;
+    }
+  }
+  v1 = 0;
+LABEL_10:
+  if ( stru_505708[0].field_24 <= 0 )
+  {
+    if ( stru_505708[1].field_24 > 0 )
+    {
+      v0 = 2;
+    }
+    else
+    {
+      if ( stru_505708[0].field_24 == stru_505708[1].field_24 )
+      {
+LABEL_20:
+        if ( stru_505708[0].field_28 == stru_505708[1].field_28 )
+        {
+          v0 = 0;
+          v1 = 4;
+        }
+        else
+        {
+          v0 = (stru_505708[0].field_28 <= stru_505708[1].field_28) + 1;
+          v1 = 1;
+        }
+        goto LABEL_23;
+      }
+      v0 = (stru_505708[0].field_24 <= stru_505708[1].field_24) + 1;
+    }
+    goto LABEL_17;
+  }
+  if ( stru_505708[1].field_24 <= 0 )
+  {
+    v0 = 1;
+LABEL_17:
+    v1 = 2;
+  }
+  if ( !v0 && v1 == 4 )
+    goto LABEL_20;
+LABEL_23:
+  v3 = stru_505708[0].field_38;
+  if ( stru_505708[0].field_38 <= stru_505708[0].field_3C )
+  {
+    v3 = stru_505708[0].field_40;
+    v4 = stru_505708[0].field_3C;
+    if ( stru_505708[0].field_3C > stru_505708[0].field_40 )
+      goto LABEL_28;
+  }
+  else
+  {
+    if ( stru_505708[0].field_38 <= stru_505708[0].field_40 )
+    {
+      v4 = stru_505708[0].field_40;
+      goto LABEL_28;
+    }
+  }
+  v4 = v3;
+LABEL_28:
+  v5 = stru_505708[1].field_38;
+  v6 = stru_505708[1].field_3C;
+  if ( stru_505708[1].field_38 <= stru_505708[1].field_3C )
+  {
+    v5 = stru_505708[1].field_40;
+    if ( stru_505708[1].field_3C > stru_505708[1].field_40 )
+      goto LABEL_33;
+    goto LABEL_32;
+  }
+  v6 = stru_505708[1].field_40;
+  if ( stru_505708[1].field_38 > stru_505708[1].field_40 )
+LABEL_32:
+    v6 = v5;
+LABEL_33:
+  if ( v0 == -1 )
+  {
+    if ( v1 != -1 )
+      goto LABEL_49;
+    if ( v4 < dword_4E1888 )
+    {
+      if ( v6 < dword_4E1888 )
+        goto LABEL_49;
+      v0 = 2;
+    }
+    else
+    {
+      if ( v6 < dword_4E1888 )
+      {
+        v0 = 1;
+      }
+      else
+      {
+        if ( v4 == v6 )
+          goto LABEL_46;
+        v0 = (v4 <= v6) + 1;
+      }
+    }
+    v1 = 3;
+  }
+  if ( !v0 && v1 == 4 )
+  {
+    if ( v4 != v6 )
+    {
+      v14 = 5;
+      v0 = (v4 <= v6) + 1;
+      goto LABEL_48;
+    }
+LABEL_46:
+    v0 = 0;
+    v14 = 4;
+LABEL_48:
+    v1 = v14;
+  }
+LABEL_49:
+  pArcomageGame->field_B0 = v1;
+  pArcomageGame->uGameResult = v0;
+  if ( v0 == 1 )
+  {
+    v7 = ptr_507BC0;
+    v8 = (signed int)ptr_507BC0->ptr_1C;
+    if ( v8 >= 108 )
+    {
+      if ( v8 <= 120 )
+      {
+        v9 = (char *)&pParty->uNumGoldInBank + v8 + 1;
+        if ( !*v9 )
+        {
+          *v9 = 1;
+
+          //auto _a = (signed __int64)(p2DEvents_minus1__20[13 * (unsigned int)v7->ptr_1C] * 100.0);
+          auto _a = (signed __int64)(p2DEvents[(unsigned int)v7->ptr_1C - 1].fPriceMultiplier * 100.0);
+          party_finds_gold(_a, 0);
+        }
+      }
+    }
+    v10 = 108;
+    do
+    {
+      if ( !*((unsigned char *)&pParty->uNumGoldInBank + v10 + 1) )
+        break;
+      ++v10;
+    }
+    while ( v10 <= 120 );
+    if ( v10 == 121 )
+      _449B7E_toggle_bit(pParty->_award_bits, 238, 1u);
+    v11 = pParty->pPlayers[0].field_152;
+    do
+    {
+      if ( !(unsigned __int16)_449B57_test_bit((unsigned __int8 *)v11, 1) )
+        _449B7E_toggle_bit((unsigned char *)v11, 103, 1u);
+      v11 += 6972;
+    }
+    while ( (signed int)v11 < (signed int)((char *)&pParty->field_777C[36] + 2) );
+    ++pParty->field_874;
+    if ( pParty->field_874 > 1000000 )
+      pParty->field_874 = 1000000;
+  }
+  else
+  {
+    v12 = pParty->pPlayers[0].field_152;
+    do
+    {
+      if ( !(unsigned __int16)_449B57_test_bit((unsigned __int8 *)v12, 1) )
+        _449B7E_toggle_bit((unsigned char *)v12, 104, 1u);
+      v12 += 6972;
+    }
+    while ( (signed int)v12 < (signed int)((char *)&pParty->field_777C[36] + 2) );
+    ++pParty->field_878;
+    if ( pParty->field_878 > 1000000 )
+      pParty->field_878 = 1000000;
+  }
+  return 0;
+}
+
+
+
+//----- (00409C8B) --------------------------------------------------------
+void __cdecl PrepareArcomage()
+{
+  int v0; // ecx@3
+  signed __int64 v1; // qax@4
+  int v2; // esi@4
+  __int16 *v3; // esi@5
+  signed int v4; // edi@5
+  stru272 *v5; // esi@7
+  int v6; // edx@9
+  int v7; // ecx@9
+  int pXYZW[4]; // [sp+8h] [bp-1Ch]@5
+  int pXY[2]; // [sp+18h] [bp-Ch]@5
+  int v10; // [sp+20h] [bp-4h]@3
+
+  if (pAsyncMouse)
+    pAsyncMouse->_409E3D(1);
+  pAudioPlayer->StopChannels(-1, -1);
+  strcpy(pArcomageGame->pPlayer1Name, pArcomagePlayer1Name);
+  strcpy(pArcomageGame->pPlayer2Name, pArcomagePlayer2Name);
+  am_byte_4FAA76 = 0;
+  am_byte_4FAA75 = 0;
+  v10 = 1;
+  v0 = (int)am_byte_4FAA7C;
+  do
+  {
+    v1 = v10;
+    *(int *)(v0 - 4) = -1;
+    *(char *)v0 = 0;
+    v0 += 32;
+    v2 = 138 * (unsigned __int64)(v1 / 4) + 18;
+    HIDWORD(v1) = 100 * (unsigned __int64)(v1 % 4) + 120;
+    *(int *)(v0 - 28) = HIDWORD(v1);
+    *(int *)(v0 - 24) = v2;
+    *(int *)(v0 - 20) = (120 - HIDWORD(v1)) / 5;
+    ++v10;
+    *(int *)(v0 - 16) = (18 - v2) / 5;
+    *(int *)(v0 - 12) = *(int *)(v0 - 28);
+    *(int *)(v0 - 8) = *(int *)(v0 - 24);
+  }
+  while ( v10 - 1 < 10 );
+  pXY[0] = 0;
+  pXY[1] = 0;
+  ArcomageGame::LoadBackground();
+  pXYZW[0] = 0;
+  pXYZW[2] = 640;
+  pXYZW[1] = 0;
+  pXYZW[3] = 480;
+  am_BeginScene(pArcomageGame->pBackgroundPixels, -1, 1);
+  Blt_Copy((ArcomageRect *)pXYZW, pXY, 2);
+  am_EndScene();
+  pRenderer->Present();
+  ArcomageGame::LoadSprites();
+  CallRenderPresent();
+  v3 = am_sounds;
+  v4 = 120;
+  do
+  {
+    *v3 = pSoundList->LoadSound(v4++, 0);
+    ++v3;
+  }
+  while ( (signed int)v3 <= (signed int)&unk_4FAA20 );
+  v5 = array_4FAC10;
+  do
+  {
+    v5->_40DFD1();
+    ++v5;
+  }
+  while ( (signed int)v5 < (signed int)&unk_5052C8 );
+  dword_4FABBC = -1;
+  amuint_4FAA4C = -1;
+  byte_4FAA74 = 0;
+  pArcomageGame->field_F4 = 0;
+  byte_4FAA2C = 0;
+  byte_505880 = 0;
+  dword_4FAA70 = 0;
+  am_byte_4FAA77 = 0;
+  am_409FE9();
+  am_40A255(v7, v6);
+  //nullsub_1();
+  pArcomageGame->field_F5 = 0;
+  pArcomageGame->pFont1 = pFontComic;
+  pArcomageGame->pFont2 = pFontArrus;
+}
+
+
+//----- (0040D711) --------------------------------------------------------
+ArcomageGame::ArcomageGame()
+{
+  ArcomageGame *v1; // esi@1
+
+  v1 = this;
+  this->field_4 = 0;
+  //RGBTexture::RGBTexture(&this->pGameBackground);
+  //RGBTexture::RGBTexture(&v1->pSprites);
+  v1->bGameInProgress = 0;
+  v1->field_F9 = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Arcomage.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,133 @@
+#pragma once
+#include "OSAPI.h"
+
+#include "Texture.h"
+
+
+
+#pragma pack(push, 1)
+struct ArcomageRect
+{
+  int x;
+  int y;
+  int z;
+  int w;
+};
+#pragma pack(pop)
+
+
+/*  272 */
+#pragma pack(push, 1)
+struct ArcomageCard
+{
+  char pCardName[20];
+  int field_14;
+  int field_18;
+  int field_1C;
+  int slot;
+  int field_24;
+  int field_28;
+  int field_2C;
+  float field_30;
+  int field_34;
+  char field_38[16];
+  char field_48[16];
+  char field_58[16];
+  int field_68;
+};
+#pragma pack(pop)
+
+
+
+
+#pragma pack(push, 1)
+struct ArcomageGame_stru0
+{
+  char pPlayerName[32];
+  int field_20;
+  int field_24;
+  int field_28;
+  int field_2C;
+  int field_30;
+  int field_34;
+  int field_38;
+  int field_3C;
+  int field_40;
+  int arr_44[10];
+  int arr_6C[10][2];
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct ArcomageGame_stru1
+{
+  int field_0;
+  int field_4;
+  int field_8;
+};
+#pragma pack(pop)
+
+
+
+
+#pragma pack(push, 1)
+struct ArcomageGame
+{
+  ArcomageGame();
+
+  static bool LoadBackground();
+  static bool LoadSprites();
+  static bool MsgLoop(int a1, ArcomageGame_stru1 *a2);
+  static void PlaySound(unsigned int a1);
+  static void OnMouseClick(char right_left, bool bDown);
+  static void OnMouseMove(POINT *pXY);
+  static void GetCardRect(unsigned int uCardID, ArcomageRect *pCardRect);
+
+  static void Loop();
+
+  char field_0;
+  char field_1;
+  char field_2;
+  char field_3;
+  int field_4;
+  ArcomageGame_stru1 stru1;
+  tagMSG msg;
+  int mouse_x;
+  int mouse_y;
+  char mouse_left;
+  char field_39;
+  char mouse_right;
+  char field_3B;
+  unsigned __int16 *pBackgroundPixels;
+  unsigned __int16 *pSpritesPixels;
+  unsigned __int16 *pBlit_Copy_pixels;
+  struct GUIFont *pFont1;//ptr_48;
+  struct GUIFont *pFont2;//ptr_4C;
+  int field_50;
+  __int16 field_54;
+  __int16 field_56;
+  RGBTexture pGameBackground;
+  RGBTexture pSprites;
+  int event_timer_time;
+  int uGameResult;
+  int field_B0;
+  char pPlayer1Name[32];
+  char pPlayer2Name[32];
+  char field_F4;
+  char field_F5;
+  char field_F6;
+  char field_F7;
+  char field_F8;
+  char field_F9;
+  char bGameInProgress;
+};
+#pragma pack(pop)
+
+
+
+
+extern ArcomageGame *pArcomageGame;
+extern ArcomageCard pCards[87];
+extern ArcomageGame_stru0 stru_505708[2];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AudioPlayer.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2700 @@
+#include <string>
+
+#include "AudioPlayer.h"
+#include "Allocator.h"
+#include "FrameTableInc.h"
+#include "Indoor.h"
+#include "LayingItem.h"
+#include "Party.h"
+#include "Actor.h"
+#include "Game.h"
+#include "DecorationList.h"
+#include "Time.h"
+#include "OSInfo.h"
+#include "Math.h"
+#include "MapInfo.h"
+#include "Log.h"
+
+#include "Bink_Smacker.h"
+
+#include "mm7_data.h"
+
+
+
+PCMWAVEFORMAT pcmWaveFormat;
+
+int Aureal3D_SplashScreen;
+int Aureal3D_SplashAudio;
+int uFindSound_BinSearch_ResultID; // weak
+int uLastLoadedSoundID; // weak
+int sLastTrackLengthMS;
+Sound pSounds[3000];
+AudioPlayer *pAudioPlayer;
+SoundList *pSoundList;
+
+
+stru339_spell_sound stru_A750F8[4];
+stru339_spell_sound stru_AA1058[4];
+
+
+
+unsigned __int8 uSoundVolumeMultiplier = 4;
+unsigned __int8 uVoicesVolumeMultiplier = 4;
+unsigned __int8 uMusicVolimeMultiplier = 4;
+int bWalkSound; // idb
+
+float pSoundVolumeLevels[10] = 
+{
+  0.0,
+  0.10999999940395,
+  0.21999999880791,
+  0.33000001311302,
+  0.43999999761581,
+  0.55000001192093,
+  0.66000002622604,
+  0.76999998092651,
+  0.87999999523163,
+  0.99000000953674
+}; // idb
+
+
+
+
+void ReleaseSoundData(void *_this);
+
+
+
+
+//----- (004A9953) --------------------------------------------------------
+void SoundList::Initialize()
+{
+  SoundList *pSoundList; // esi@1
+  signed int v2; // edi@2
+  SoundDesc *pSoundDesc; // eax@5
+  void *pSoundData; // ebx@7
+  unsigned int uSoundSize; // eax@7
+  char *pSoundBytes; // ebx@7
+  AILFILETYPE pType; // eax@7
+  int v8; // eax@8
+  char pSoundName[120]; // [sp+4h] [bp-A4h]@4
+  AILSOUNDINFO pInfo; // [sp+7Ch] [bp-2Ch]@10
+  int v12; // [sp+A0h] [bp-8h]@12
+  int a2; // [sp+A4h] [bp-4h]@1
+
+  pSoundList = this;
+  a2 = 1;
+  if ( (signed int)this->uNumSounds > 1 )
+  {
+    v2 = 1;
+    //while ( 1 )
+	do
+    {
+	  sprintf(pSoundName, "%s", pSounds[v2].pSoundName);
+	 // pSoundList->pSounds[v2].pSoundData[0] = ::LoadSound(pSoundName, (SoundData *)0xFFFFFFFF, pSounds[v2].uSoundID); Ritor1: it's error - result: no sound
+	  pSoundDesc = &pSoundList->pSounds[v2];
+      if ( pSoundList->pSounds[v2].eType != SOUND_DESC_SYSTEM || (sprintf(pSoundName, "%s", pSounds[v2].pSoundName),
+            pSoundList->pSounds[v2].pSoundData[0] = ::LoadSound(pSoundName, (SoundData *)0xFFFFFFFF, pSounds[v2].uSoundID),
+            !pAudioPlayer->b3DSoundInitialized)
+        || (pSoundDesc = &pSoundList->pSounds[v2], !(pSoundDesc->uFlags & 2))
+        || !pSoundDesc->pSoundData[0] ) // íóæíî ïåðåâåðíóòü
+        goto LABEL_17;
+      pSoundData = pSoundDesc->pSoundData[0];
+      uSoundSize = *(int *)pSoundData;
+      pSoundBytes = (char *)pSoundData + 4;
+      pType = AIL_file_type(pSoundBytes, uSoundSize);
+      if ( !pType )
+        //goto LABEL_15;
+	  {
+		LOBYTE(pSoundList->pSounds[v2].bDecompressed) = 0;
+		goto LABEL_16;
+	  }
+      v8 = pType - 1;
+      if ( v8 )
+	  {
+        /*break;
+      pSoundList->pSounds[v2].p3DSound = pSoundList->pSounds[v2].pSoundData[0];
+LABEL_16:
+      pSoundList->_4A9DCD(a2, 1);
+LABEL_17:
+      ++a2;
+      ++v2;
+      if ( a2 >= (signed int)pSoundList->uNumSounds )
+        return;
+    }*/
+      if ( v8 == 1 )
+      {
+        if ( AIL_WAV_info(pSoundBytes, &pInfo) && pInfo.uChannels != 2 )
+        {
+          if ( !AIL_decompress_ADPCM(&pInfo, &pSoundList->pSounds[v2].p3DSound, &v12) )
+          {
+            pSoundList->pSounds[v2].p3DSound = 0;
+            LOBYTE(pSoundList->pSounds[v2].bDecompressed) = 1;
+          }
+        }
+        goto LABEL_16;
+      }
+//LABEL_15:
+      LOBYTE(pSoundList->pSounds[v2].bDecompressed) = 0;
+      goto LABEL_16;
+    }
+	pSoundList->pSounds[v2].p3DSound = pSoundList->pSounds[v2].pSoundData[0];
+LABEL_16:
+    pSoundList->_4A9DCD(a2, 1);
+LABEL_17:
+      ++a2;
+      ++v2;
+	}
+    while ( a2 < (signed int)pSoundList->uNumSounds );
+  }
+}
+
+//----- (004A9A67) --------------------------------------------------------
+__int16 SoundList::LoadSound(int a1, unsigned int a3)
+{
+  AILSOUNDINFO v24; // [sp+84h] [bp-28h]@23
+
+  if (bNoSound || !uNumSounds)
+    return 0;
+
+  uint       uSoundIdx = 0;
+  SoundDesc *pSound = nullptr;
+  for (uint i = 1; i < uNumSounds; ++i)
+    if (pSounds[i].uSoundID == a1)
+    {
+      uSoundIdx = i;
+      pSound = &pSounds[i];
+      break;
+    }
+  if (!pSound)
+    return 0;
+
+  if (pSound->uFlags & 2 && pSound->p3DSound ||
+      ~pSound->uFlags & 2 && pSound->pSoundData[0])
+    return uSoundIdx;
+
+  if (!pSound->pSoundData[0])
+    pSound->pSoundData[0] = ::LoadSound(pSound->pSoundName, (SoundData *)0xFFFFFFFF, pSound->uSoundID);
+
+  if (!pSound->pSoundData[0])
+    return 0;
+
+  if (a3)
+    pSound->uFlags |= 1u;
+
+  if (!pAudioPlayer->b3DSoundInitialized)
+    return uSoundIdx;
+
+  if (~pSound->uFlags & 2 || !pSound->pSoundData[0])
+    return uSoundIdx;
+
+
+  auto pSoundData = pSound->pSoundData[0];
+  switch (AIL_file_type((void *)pSoundData->pData, pSoundData->uDataSize))
+  {
+    default:
+    case AILFILETYPE_UNKNOWN:
+      pSound->bDecompressed = false;
+      return 0;
+
+    case AILFILETYPE_PCM_WAV:
+      pSound->p3DSound = pSound->pSoundData[0];
+      return uSoundIdx;
+
+    case AILFILETYPE_ADPCM_WAV:
+      if (AIL_WAV_info((void *)pSoundData->pData, &v24) && v24.uChannels != 2)
+      {
+        if (!AIL_decompress_ADPCM(&v24, &pSound->p3DSound, &a1) )
+        {
+          pSound->p3DSound = nullptr;
+          pSound->bDecompressed = true;
+          _4A9DCD(uSoundIdx, 0);
+        }
+      }
+      return uSoundIdx;
+  };
+}
+
+//----- (004A9BBD) --------------------------------------------------------
+int SoundList::LoadSound(unsigned int a2, LPVOID lpBuffer, int uBufferSizeLeft, int *pOutSoundSize, int a6)
+{
+  //SoundList *v6; // edi@1
+  signed int v7; // esi@1
+  //unsigned __int8 v8; // zf@1
+  //unsigned __int8 v9; // sf@1
+  SoundDesc *v10; // eax@3
+  SoundDesc *v11; // ecx@3
+  int v12; // ebx@7
+  int result; // eax@13
+  SoundHeader *v14; // esi@16
+  DWORD *v15; // edi@16
+  int v16; // ebx@16
+  unsigned int v17; // eax@18
+  void *v18; // ebx@19
+  std::string v19; // [sp-18h] [bp-38h]@22
+  const char *v20; // [sp-8h] [bp-28h]@22
+  int v21; // [sp-4h] [bp-24h]@22
+  //SoundList *v22; // [sp+Ch] [bp-14h]@1
+  SoundDesc *Args; // [sp+10h] [bp-10h]@3
+  unsigned int v24; // [sp+14h] [bp-Ch]@2
+  int v25; // [sp+18h] [bp-8h]@2
+  int v26; // [sp+1Ch] [bp-4h]@1
+
+  //v6 = this;
+  v7 = 0;
+  //v22 = this;
+  //v8 = this->uNumSounds == 0;
+  //v9 = (this->uNumSounds & 0x80000000u) != 0;
+  v26 = 0;
+  if (!uNumSounds)
+    return 0;
+
+
+    v24 = 0;
+    v25 = 44;
+    while ( 1 )
+    {
+      v10 = pSounds;
+      v11 = &v10[v24 / 0x78];
+      Args = &v10[v24 / 0x78];
+      if ( a2 == v10[v24 / 0x78].uSoundID )
+      {
+        if ( a6 == v7 && *(int *)&v10->pSoundName[v25] != v7 )
+          return v26;
+        if ( (signed int)pAudioPlayer->uNumSoundHeaders > v7 )
+          break;
+      }
+LABEL_12:
+      ++v26;
+      v25 += 120;
+      v24 += 120;
+      if ( v26 >= (signed int)uNumSounds )
+        return 0;
+    }
+    v12 = 0;
+    while ( _strcmpi(pAudioPlayer->pSoundHeaders[v12].pSoundName, v11->pSoundName) )
+    {
+      ++v7;
+      ++v12;
+      if ( v7 >= (signed int)pAudioPlayer->uNumSoundHeaders )
+      {
+        v7 = 0;
+        goto LABEL_12;
+      }
+      v11 = Args;
+    }
+    v14 = &pAudioPlayer->pSoundHeaders[v7];
+    v15 = (DWORD *)&v14->uDecompressedSize;
+    a2 = v14->uDecompressedSize;
+    v16 = a2;
+    if ( (signed int)a2 > uBufferSizeLeft )
+      Abortf("Sound %s is size %i bytes, sound buffer size is %i bytes", Args, a2, uBufferSizeLeft);
+    SetFilePointer(pAudioPlayer->hAudioSnd, v14->uFileOffset, 0, 0);
+    v17 = v14->uCompressedSize;
+    if ( (signed int)v17 >= (signed int)*v15 )
+    {
+      if ( v17 == *v15 )
+      {
+        ReadFile(pAudioPlayer->hAudioSnd, lpBuffer, *v15, (LPDWORD)&Args, 0);
+      }
+      else
+      {
+      MessageBoxW(nullptr, L"Can't load sound file!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Sound.cpp:666", 0);
+      }
+    }
+    else
+    {
+      v18 = malloc(v14->uCompressedSize);
+      ReadFile(pAudioPlayer->hAudioSnd, v18, v14->uCompressedSize, (LPDWORD)&Args, 0);
+      zlib::MemUnzip(lpBuffer, &v14->uDecompressedSize, v18, v14->uCompressedSize);
+      free(v18);
+      v16 = a2;
+    }
+    result = v26;
+    pSounds->pSoundData[a6 + 30 * v26] = (SoundData *)lpBuffer;
+    *pOutSoundSize = v16;
+
+  return result;
+}
+
+//----- (004A9D3E) --------------------------------------------------------
+SoundDesc *SoundList::Release()
+{
+  SoundList *v1; // esi@1
+  signed int v2; // ebx@1
+  int v3; // edi@2
+  SoundDesc *result; // eax@3
+  void *v5; // ecx@3
+
+  v1 = this;
+  v2 = 0;
+  if ( (signed int)this->uNumSounds > 0 )
+  {
+    v3 = 0;
+    do
+    {
+      result = v1->pSounds;
+      v5 = result[v3].pSoundData[0];
+      if ( v5 )
+      {
+        ReleaseSoundData(v5);
+        v1->pSounds[v3].pSoundData[0] = 0;
+        result = (SoundDesc *)((char *)&v1->pSounds[v3] + 40);
+        *(int *)&result->pSoundName[0] &= 0xFFFFFFFEu;
+      }
+      ++v2;
+      ++v3;
+    }
+    while ( v2 < (signed int)v1->uNumSounds );
+  }
+  return result;
+}
+
+//----- (004A9D79) --------------------------------------------------------
+void SoundList::_4A9D79(int a2)
+{
+  SoundList *v2; // esi@1
+  int v3; // edi@1
+  signed int i; // ebx@1
+  SoundDesc *v5; // eax@2
+  SOUND_DESC_TYPE v6; // ecx@2
+  void *v7; // eax@5
+
+  v2 = this;
+  v3 = 0;
+  for ( i = 0; i < (signed int)v2->uNumSounds; ++v3 )
+  {
+    v5 = &v2->pSounds[v3];
+    v6 = v5->eType;
+    if ( v6 != SOUND_DESC_SYSTEM && (a2 || v6 != SOUND_DESC_LOCK) )
+    {
+      v7 = v5->pSoundData[0];
+      if ( v7 )
+      {
+        ReleaseSoundData(v7);
+        v2->pSounds[v3].pSoundData[0] = 0;
+      }
+      v2->pSounds[v3].uFlags &= 0xFFFFFFFEu;
+    }
+    ++i;
+  }
+}
+
+//----- (004A9DCD) --------------------------------------------------------
+void SoundList::_4A9DCD(unsigned int uSoundID, char a3)
+{
+  unsigned int v3; // esi@1
+  //SoundList *v4; // edi@1
+  SoundDesc *v5; // eax@1
+  void *v6; // ecx@8
+
+  v3 = uSoundID;
+  //v4 = this;
+  v5 = &this->pSounds[uSoundID];
+  if ( v5->eType != SOUND_DESC_SYSTEM )
+  {
+    if ( v5->uFlags & 2 && v5->p3DSound && a3 )
+    {
+      if ( LOBYTE(v5->bDecompressed) )
+        AIL_mem_free_lock(v5->p3DSound);
+      pSounds[v3].p3DSound = 0;
+      pSounds[v3].uFlags &= 0xFFFFFFFEu;
+    }
+    v6 = pSounds[v3].pSoundData[0];
+    if ( v6 )
+    {
+      ReleaseSoundData(v6);
+      pSounds[v3].pSoundData[0] = 0;
+      pSounds[v3].uFlags &= 0xFFFFFFFEu;
+    }
+  }
+}
+
+
+//----- (004A9E3D) --------------------------------------------------------
+void SoundList::ToFile()
+{
+  SoundList *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  v1 = this;
+  v2 = fopen("data\\dsounds.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dsounds.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pSounds, 0x78u, v1->uNumSounds, v3);
+  fclose(v3);
+}
+
+//----- (004A9E89) --------------------------------------------------------
+void *SoundList::FromFile(void *pSerialized)
+{
+  uNumSounds = *(int *)pSerialized;
+  pSounds = (SoundDesc *)pAllocator->AllocNamedChunk(pSounds, 120 * uNumSounds, "Snd Des.");
+  return memcpy(pSounds, (char *)pSerialized + 4, 120 * uNumSounds);
+}
+
+//----- (004A9ED0) --------------------------------------------------------
+int SoundList::FromFileTxt(const char *Args)
+{
+  SoundList *v2; // ebx@1
+  __int32 v3; // edi@1
+  FILE *v4; // eax@1
+  unsigned int v5; // esi@3
+  void *v6; // eax@9
+  FILE *v7; // ST0C_4@11
+  char *i; // eax@11
+  int v9; // eax@14
+  const char *v10; // ST0C_4@14
+  int v11; // eax@18
+  SoundDesc *v12; // ecx@18
+  char v13; // zf@18
+  unsigned int v14; // eax@18
+  int v15; // eax@23
+  char Buf; // [sp+Ch] [bp-2F0h]@3
+  FrameTableTxtLine v18; // [sp+200h] [bp-FCh]@4
+  FrameTableTxtLine v19; // [sp+27Ch] [bp-80h]@4
+  FILE *File; // [sp+2F8h] [bp-4h]@1
+  unsigned int Argsa; // [sp+304h] [bp+8h]@3
+
+  v2 = this;
+  pAllocator->FreeChunk(this->pSounds);
+  v3 = 0;
+  v2->pSounds = 0;
+  v2->uNumSounds = 0;
+  v4 = fopen(Args, "r");
+  File = v4;
+  if ( !v4 )
+    Abortf("SoundListClass::load - Unable to open file: %s.");
+  v5 = 0;
+  Argsa = 0;
+  if ( fgets(&Buf, 490, v4) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v19, texture_frame_table_txt_parser(&Buf, &v18), sizeof(v19));
+      if ( v19.field_0 && *v19.pProperties[0] != 47 )
+        ++Argsa;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v5 = Argsa;
+    v3 = 0;
+  }
+  v2->uNumSounds = v5;
+  v6 = pAllocator->AllocNamedChunk(v2->pSounds, 120 * v5, "Snd Des.");
+  v2->pSounds = (SoundDesc *)v6;
+  if ( v6 == (void *)v3 )
+    Abortf("SoundListClass::load - Out of Memory!");
+  memset(v6, v3, 120 * v2->uNumSounds);
+  v7 = File;
+  v2->uNumSounds = v3;
+  fseek(v7, v3, v3);
+  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v19, texture_frame_table_txt_parser(&Buf, &v18), sizeof(v19));
+    if ( v19.field_0 && *v19.pProperties[0] != 47 )
+    {
+      sprintf(v2->pSounds[v2->uNumSounds].pSoundName, "%s", v19.pProperties[0]);
+      v9 = atoi(v19.pProperties[1]);
+      v10 = v19.pProperties[2];
+      v2->pSounds[v2->uNumSounds].uSoundID = v9;
+      if ( _strcmpi(v10, "system") )
+      {
+        if ( _strcmpi(v19.pProperties[2], "swap") )
+        {
+          v11 = _strcmpi(v19.pProperties[2], "lock");
+          v12 = v2->pSounds;
+          v13 = v11 == 0;
+          v14 = v2->uNumSounds;
+          if ( v13 )
+            v12[v14].eType = SOUND_DESC_LOCK;
+          else
+            v12[v14].eType = SOUND_DESC_LEVEL;
+        }
+        else
+        {
+          v2->pSounds[v2->uNumSounds].eType = SOUND_DESC_SWAP;
+        }
+      }
+      else
+      {
+        v2->pSounds[v2->uNumSounds].eType = SOUND_DESC_SYSTEM;
+      }
+      if ( v19.field_0 >= 4 && !_strcmpi(v19.pProperties[3], "3D") )
+      {
+        v15 = (int)&v2->pSounds[v2->uNumSounds].uFlags;
+        *(int *)v15 |= 2u;
+      }
+      ++v2->uNumSounds;
+    }
+  }
+  fclose(File);
+  return 1;
+}
+
+//----- (004AA13F) --------------------------------------------------------
+void AudioPlayer::PlayMusicTrack(MusicID eTrack)
+{
+  if (!bNoSound && bPlayerReady && hAILRedbook && uMusicVolimeMultiplier)
+  {
+    AIL_redbook_stop(hAILRedbook);
+    AIL_redbook_set_volume(hAILRedbook, (signed)(pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0));
+    AIL_redbook_track_info(hAILRedbook, eTrack, &uCurrentMusicTrackStartMS, &uCurrentMusicTrackEndMS);
+    AIL_redbook_play(hAILRedbook, uCurrentMusicTrackStartMS + 1, uCurrentMusicTrackEndMS);
+    uCurrentMusicTrackLength = ((uCurrentMusicTrackEndMS - uCurrentMusicTrackStartMS) * 128) / 1000;
+  }
+}
+
+
+//----- (004AA1F3) --------------------------------------------------------
+void AudioPlayer::SetMusicVolume(int vol)
+{
+  if (bPlayerReady)
+  {
+    if (hAILRedbook)
+      AIL_redbook_set_volume(hAILRedbook, vol);
+  }
+}
+
+//----- (004AA214) --------------------------------------------------------
+void AudioPlayer::SetMasterVolume(unsigned int uVolume)
+{
+  AudioPlayer *v2; // esi@1
+  _DIG_DRIVER *hDrv; // eax@2
+
+  v2 = this;
+  if ( this->bPlayerReady )
+  {
+    hDrv = this->hDigDriver;
+    this->uMasterVolume = uVolume;
+    if ( hDrv )
+      AIL_set_digital_master_volume(hDrv, uVolume);
+    if ( v2->b3DSoundInitialized )
+      v2->s3DSoundVolume = (signed __int64)((double)(signed int)uVolume * 0.5);
+  }
+}
+// 4D8304: using guessed type int __stdcall AIL_set_digital_master_volume(int, int);
+
+//----- (004AA258) --------------------------------------------------------
+void AudioPlayer::_4AA258(int a2)
+{
+  AudioPlayer *v2; // esi@1
+  int v3; // edi@4
+  AudioPlayer_3DSample *v4; // ebx@5
+  int v5; // ebx@11
+  MixerChannel *v6; // edi@12
+
+  v2 = this;
+  if ( this->bPlayerReady )
+  {
+    if ( this->b3DSoundInitialized && a2 && (v3 = 0, this->uNum3DSamples > 0) )
+    {
+      v4 = this->p3DSamples;
+      while ( v4->field_4 != a2 || AIL_3D_sample_status(v4->hSample) != 4 )
+      {
+        ++v3;
+        ++v4;
+        if ( v3 >= v2->uNum3DSamples )
+          goto LABEL_9;
+      }
+      AIL_end_3D_sample(v2->p3DSamples[v3].hSample);
+    }
+    else
+    {
+LABEL_9:
+      if ( v2->hDigDriver )
+      {
+        if ( a2 )
+        {
+          v5 = 0;
+          if ( v2->uMixerChannels > 0 )
+          {
+            v6 = v2->pMixerChannels;
+            do
+            {
+              if ( v6->dword_000004 == a2 )
+              {
+                if ( AIL_sample_status(v6->hSample) == 4 )
+                {
+                  AIL_end_sample(v6->hSample);
+                  _4ABE55(v6);
+                }
+              }
+              ++v5;
+              ++v6;
+            }
+            while ( v5 < v2->uMixerChannels );
+          }
+        }
+      }
+    }
+  }
+}
+// 4D82F4: using guessed type int __stdcall AIL_3D_sample_status(int);
+// 4D82F8: using guessed type int __stdcall AIL_sample_status(int);
+// 4D82FC: using guessed type int __stdcall AIL_end_sample(int);
+// 4D8300: using guessed type int __stdcall AIL_end_3D_sample(int);
+
+//----- (004AA306) --------------------------------------------------------
+void AudioPlayer::PlaySound(SoundID eSoundID, signed int a3, unsigned int uNumRepeats, signed int PartyX, signed int PartyY, int a7, unsigned int uVolume, int sPlaybackRate)
+{
+  //AudioPlayer *pAudioPlayer1; // esi@1
+  signed int pNum; // edx@5
+  int *pSoundID; // ecx@6
+  int v12; // edi@13
+  signed int v13; // ecx@17
+  signed int v14; // eax@20
+  int v15; // eax@24
+  signed int v16; // eax@25
+  LayingItem *pLayingItem; // eax@28
+  signed int v18; // eax@29
+  Actor *pActor1; // eax@32
+  signed int v20; // ecx@32
+  double v21; // st7@32
+  signed int v22; // ecx@33
+  AudioPlayer_3DSample *pAudioPlayer_3DSample; // esi@53
+  AudioPlayer_3DSample *pAudioPlayer_3DSample1; // esi@61
+  int v25; // esi@67
+  double v26; // st7@68
+  int v27; // ST18_4@68
+  int v28; // ebx@68
+  int v29; // eax@68
+  AudioPlayer_3DSample *pAudioPlayer_3DSample2; // esi@69
+  int v31; // ST18_4@70
+  int v32; // ebx@70
+  int v33; // eax@70
+  int v34; // eax@70
+  char v35; // zf@70
+  signed int v36; // ebx@74
+  //AudioPlayer *pAudioPlayer2; // edi@79
+  AudioPlayer_3DSample *pAudioPlayer_3DSample3; // esi@79
+  unsigned int v39; // ebx@80
+  int v40; // eax@81
+  char *v41; // edi@82
+  int v42; // esi@82
+  double v43; // st7@91
+  LayingItem *pLayingItem2; // eax@92
+  Actor *pActor; // eax@93
+  signed int v46; // ecx@93
+  double v47; // st7@93
+  BLVDoor *pBLVDoor; // eax@97
+  double v49; // st7@104
+  int v50; // ST18_4@104
+  int v51; // ebx@104
+  int v52; // eax@104
+  float v53; // ST0C_4@106
+  float v54; // ST04_4@106
+  //AudioPlayer *pAudioPlayer3; // edx@106
+  SoundDesc *pSoundDesc; // edx@107
+  LayingItem *pLayingItem3; // eax@114
+  int v58; // edx@115
+  int v59; // ecx@115
+  Actor *pActor2; // eax@118
+  MixerChannel *pMixerChannel; // esi@126
+  signed int v62; // esi@133
+  //AudioPlayer *pAudioPlayer4; // ebx@133
+  MixerChannel *pMixerChannel2; // edi@134
+  int v65; // ebx@141
+  //AudioPlayer *pAudioPlayer5; // ecx@142
+  MixerChannel *pMixerChannel3; // edi@142
+  int v68; // eax@143
+  MixerChannel *pMixerChannel4; // edi@149
+  int v70; // ecx@152
+  SoundDesc *pSoundDesc2; // eax@153
+  int v72; // edi@156
+  MixerChannel *pMixerChannel5; // esi@157
+  unsigned int pVolume; // eax@157
+  int pPartyX; // ebx@159
+  int v76; // ebx@160
+  LayingItem *pLayingItem4; // edi@164
+  unsigned int pPosY; // edx@166
+  unsigned int pPosX; // ecx@166
+  int v80; // eax@167
+  Actor *pActor3; // edi@168
+  BLVDoor *pBLVDoor2; // edi@173
+  int v83; // eax@183
+  int v84; // eax@183
+  _SAMPLE *v85; // ST18_4@186
+  unsigned int v86; // [sp+14h] [bp-60h]@84
+  int v87; // [sp+14h] [bp-60h]@115
+  RenderVertexSoft pRenderVertexSoft; // [sp+24h] [bp-50h]@1
+  unsigned int v89; // [sp+54h] [bp-20h]@12
+  int v90; // [sp+58h] [bp-1Ch]@68
+  float v91; // [sp+5Ch] [bp-18h]@68
+  //unsigned int v92; // [sp+60h] [bp-14h]@10
+  float v93; // [sp+64h] [bp-10h]@1
+  signed int varC; // [sp+68h] [bp-Ch]@68
+  AudioPlayer *pAudioPlayer; // [sp+6Ch] [bp-8h]@1
+  int v96; // [sp+70h] [bp-4h]@19
+  signed int uNumRepeatsb; // [sp+84h] [bp+10h]@93
+  float uNumRepeatsa; // [sp+84h] [bp+10h]@104
+  float v99; // [sp+8Ch] [bp+18h]@104
+  signed int v100; // [sp+90h] [bp+1Ch]@32
+  int v101; // [sp+90h] [bp+1Ch]@52
+  int v102; // [sp+90h] [bp+1Ch]@60
+  int v103; // [sp+90h] [bp+1Ch]@68
+
+  pAudioPlayer = this;
+  v35 = this->bPlayerReady == 0;
+  //pAudioPlayer = this;
+  pRenderVertexSoft.flt_2C = 0.0;
+  LODWORD(v93) = 10000;
+  if ( v35 || !uSoundVolumeMultiplier || !this->hDigDriver || !eSoundID )
+    return;
+ pNum = 0;
+  if ( (signed int)pSoundList->uNumSounds <= 0 )
+  {
+LABEL_9:
+    pNum = 0;
+  }
+  else
+  {
+    pSoundID = (int *)&pSoundList->pSounds->uSoundID;
+    while ( *pSoundID != eSoundID )
+    {
+      ++pNum;
+      pSoundID += 30;
+      if ( pNum >= (signed int)pSoundList->uNumSounds )
+        goto LABEL_9;
+    }
+  }
+  /* v92 = pNum;//38 
+ pNum = 0;
+  for ( pSoundID = (int *)&pSoundList->pSounds->uSoundID; *pSoundID != eSoundID; pSoundID += 30)
+  {
+    ++pNum;
+  }*/
+  if ( !pNum )
+    return;
+  if ( !pAudioPlayer->b3DSoundInitialized || (v89 = 120 * pNum, !(pSoundList->pSounds[pNum].uFlags & 2)) )
+  {
+    //pSoundDesc = (SoundDesc *)7;
+    if ( a3 < 0 )
+    {
+      if ( a3 == -1 )
+      {
+        varC = 13;
+        v96 = 13;
+        goto LABEL_133;
+      }
+      varC = 14;
+      v96 = 14;
+LABEL_123:
+      if ( a3 )
+      {
+        if ( a3 != -1 )
+        {
+          LODWORD(v91) = 0;
+          if ( pAudioPlayer->uMixerChannels > 0 )
+          {
+            pMixerChannel = pAudioPlayer->pMixerChannels;
+            do
+            {
+              if ( AIL_sample_status(pMixerChannel->hSample) == 4 && pMixerChannel->dword_000004 == a3
+                && AIL_sample_status(pMixerChannel->hSample) == 4 )
+              {
+                if ( pMixerChannel->uSourceTrackIdx == pNum )
+                  return;
+                AIL_end_sample(pMixerChannel->hSample);
+                _4ABE55(pMixerChannel);
+              }
+              ++LODWORD(v91);
+              ++pMixerChannel;
+            }
+            while ( SLODWORD(v91) < pAudioPlayer->uMixerChannels );
+          }
+        }
+      }
+LABEL_133:
+      v62 = varC;
+      //pAudioPlayer4 = pAudioPlayer;
+      if ( varC <= v96 )
+      {
+        pMixerChannel2 = &pAudioPlayer->pMixerChannels[varC];
+        while ( AIL_sample_status(pMixerChannel2->hSample) != 2 )
+        {
+          ++v62;
+          ++pMixerChannel2;
+          if ( v62 > v96 )
+            goto LABEL_140;
+        }
+        AIL_end_sample(pMixerChannel2->hSample);
+        if ( pMixerChannel2->uSourceTrackIdx )
+          _4ABE55(pMixerChannel2);
+      }
+LABEL_140:
+      if ( v62 != v96 + 1 )//10!=13
+      {
+LABEL_150:
+        if ( LODWORD(v93) == 10000 )
+          LODWORD(v93) = pAudioPlayer->uMasterVolume;
+        v70 = 0;
+        if ( !a7 )
+        {
+          //pSoundDesc = pSoundList->pSounds;
+          pSoundDesc2 = &pSoundList->pSounds[pNum];
+          if ( !pSoundDesc2->pSoundData[0] )
+          {
+            if (pSoundDesc2->eType == SOUND_DESC_SWAP)
+              pSoundList->LoadSound(eSoundID, 0);
+          }
+        }
+        v72 = 4 * (a7 + 30 * pNum) + 44;
+        if ( !*(int *)&pSoundList->pSounds->pSoundName[v72] )
+          return;
+        pMixerChannel5 = &pAudioPlayer->pMixerChannels[v62];
+        AIL_init_sample(pMixerChannel5->hSample);
+        AIL_set_sample_file(pMixerChannel5->hSample, (void *)(*(int *)&pSoundList->pSounds->pSoundName[v72] + 4 * (a7 == 0)), -1);
+        pVolume = uVolume;
+        if ( !uVolume )
+          pVolume = LODWORD(v93);
+        AIL_set_sample_volume(pMixerChannel5->hSample, pVolume);
+        pPartyX = PartyX;
+        if ( PartyX != -1 )
+        {
+          if ( !PartyX )
+            pPartyX = pParty->vPosition.x;
+          if ( !PartyY )
+            PartyY = pParty->vPosition.y;
+          if ( uNumRepeats )
+            AIL_set_sample_loop_count(pMixerChannel5->hSample, uNumRepeats - 1);
+          v83 = sub_4AB66C(pPartyX, PartyY);
+          AIL_set_sample_pan(pMixerChannel5->hSample, v83);
+          v84 = GetSoundStrengthByDistanceFromParty(pPartyX, PartyY, pParty->vPosition.z);
+          AIL_set_sample_volume(pMixerChannel5->hSample, v84);
+          v76 = a3;
+          goto LABEL_184;
+        }
+        v76 = a3;
+        if ( (a3 & 7) == 1 )
+        {
+          if ( uCurrentlyLoadedLevelType != LEVEL_Indoor )
+            goto LABEL_184;
+          pBLVDoor2 = &pIndoor->pDoors[a3 >> 3];
+          if ( !pBLVDoor2->uDoorID )
+            return;
+          if ( !GetSoundStrengthByDistanceFromParty(*pBLVDoor2->pXOffsets, *pBLVDoor2->pYOffsets, *pBLVDoor2->pZOffsets) )
+          {
+            AIL_end_sample(pMixerChannel5->hSample);
+            pAudioPlayer->AudioPlayer::_4ABE55(pMixerChannel5);
+            return;
+          }
+          pPosY = *pBLVDoor2->pYOffsets;
+          pPosX = *pBLVDoor2->pXOffsets;
+          //goto LABEL_167;
+		  v80 = sub_4AB66C(pPosX, pPosY);
+          AIL_set_sample_pan(pMixerChannel5->hSample, v80);
+          goto LABEL_184;
+        }
+        if ( (a3 & 7) == 2 )
+        {
+          pLayingItem4 = &pLayingItems[a3 >> 3];
+          if ( !GetSoundStrengthByDistanceFromParty(pLayingItem4->vPosition.x, pLayingItem4->vPosition.y, pLayingItem4->vPosition.z) )
+            return;
+        }
+        else
+        {
+          if ( (a3 & 7) == 3 )
+          {
+            pActor3 = &pActors[a3 >> 3];
+            if ( !GetSoundStrengthByDistanceFromParty(pActor3->vPosition.x, pActor3->vPosition.y, pActor3->vPosition.z) )
+              return;
+            pPosY = pActor3->vPosition.y;
+            pPosX = pActor3->vPosition.x;
+            //goto LABEL_167;
+			v80 = sub_4AB66C(pPosX, pPosY);
+            AIL_set_sample_pan(pMixerChannel5->hSample, v80);
+			goto LABEL_184;
+          }
+          if ( (a3 & 7) != 5 )
+          {
+LABEL_184:
+            if ( uNumRepeats )
+              AIL_set_sample_loop_count(pMixerChannel5->hSample, uNumRepeats - 1);
+            v85 = pMixerChannel5->hSample;
+            pMixerChannel5->uSourceTrackIdx = pNum;
+            pMixerChannel5->dword_000004 = v76;
+            pMixerChannel5->uSourceTrackID = eSoundID;
+            AIL_start_sample(v85);
+            if ( sPlaybackRate )
+              AIL_set_sample_playback_rate(pMixerChannel5->hSample, sPlaybackRate);
+            if ( (v76 & 7) == 4 )
+              AIL_sample_ms_position(pMixerChannel5->hSample, &sLastTrackLengthMS, 0);
+            return;
+          }
+          pLayingItem4 = (LayingItem *)&pLevelDecorations[a3 >> 3];
+          if ( !GetSoundStrengthByDistanceFromParty(pLayingItem4->vPosition.x, pLayingItem4->vPosition.y, pLayingItem4->vPosition.z) )
+            return;
+          AIL_set_sample_loop_count(pMixerChannel5->hSample, uNumRepeats - 1);
+        }
+        pPosY = pLayingItem4->vPosition.y;
+        pPosX = pLayingItem4->vPosition.x;
+//LABEL_167:
+        v80 = sub_4AB66C(pPosX, pPosY);
+        AIL_set_sample_pan(pMixerChannel5->hSample, v80);
+        goto LABEL_184;
+      }
+      v65 = varC;
+      v62 = -1;
+      v91 = v93;
+      if ( varC <= v96 )
+      {
+        //pAudioPlayer5 = pAudioPlayer;
+        pMixerChannel3 = &pAudioPlayer->pMixerChannels[varC];
+        do
+        {
+          v68 = AIL_sample_volume(pMixerChannel3->hSample);
+          if ( v68 < SLODWORD(v91) )
+          {
+            LODWORD(v91) = v68;
+            v62 = v65;
+          }
+          ++v65;
+          ++pMixerChannel3;
+        }
+        while ( v65 <= v96 );
+        if ( v62 != -1 )
+        {
+//LABEL_149:
+          //pAudioPlayer4 = pAudioPlayer;
+          pMixerChannel4 = &pAudioPlayer->pMixerChannels[v62];
+          AIL_end_sample(pMixerChannel4->hSample);
+          _4ABE55(pMixerChannel4);
+          goto LABEL_150;
+        }
+        v65 = varC;
+      }
+      v62 = 13;
+      if ( v65 != 13 )
+        return;
+      //goto LABEL_149;
+	  //pAudioPlayer4 = pAudioPlayer;
+      pMixerChannel4 = &pAudioPlayer->pMixerChannels[v62];
+      AIL_end_sample(pMixerChannel4->hSample);
+      _4ABE55(pMixerChannel4);
+      goto LABEL_150;
+    }
+    if ( (a3 & 7) == 2 )
+    {
+      varC = 5;
+      v96 = 7;
+      pLayingItem3 = &pLayingItems[a3 >> 3];
+    }
+    else
+    {
+      if ( (a3 & 7) == 3 )
+      {
+        *(float *)&varC = 0.0;
+        pActor2 = &pActors[a3 >> 3];
+        v96 = 3;
+        v58 = pActor2->vPosition.y;
+        v87 = pActor2->vPosition.z;
+        v59 = pActor2->vPosition.x;
+LABEL_116:
+        LODWORD(v93) = GetSoundStrengthByDistanceFromParty(v59, /*(int)pSoundDesc*/ v58, v87);
+        if ( v93 == 0.0 )
+          return;
+        goto LABEL_123;
+      }
+      if ( (a3 & 7) != 5 )
+      {
+        if ( (a3 & 7) == 6 )
+        {
+          varC = 8;
+          v96 = 9;
+        }
+        else
+        {
+          varC = 10;
+          v96 = 12;
+        }
+        goto LABEL_123;
+      }
+      varC = 4;
+      v96 = 4;
+      pLayingItem3 = (LayingItem *)&pLevelDecorations[a3 >> 3];
+    }
+    v87 = pLayingItem3->vPosition.z;
+    v58 = pLayingItem3->vPosition.y;
+    v59 = pLayingItem3->vPosition.x;
+    goto LABEL_116;
+  }
+  v12 = 13;
+  if ( a3 < 0 )
+  {
+    v15 = pAudioPlayer->uNum3DSamples;
+    if ( a3 == -1 )
+    {
+      if ( v15 < 16 )
+        v12 = v15 - 1;
+      v96 = v12;
+      //goto LABEL_46;
+	  pRenderVertexSoft.vWorldPosition.x = (double)pParty->vPosition.x;
+      pRenderVertexSoft.vWorldPosition.y = (double)pParty->vPosition.y;
+      v21 = (double)pParty->sEyelevel + (double)pParty->vPosition.z;
+      goto LABEL_47;
+    }
+    if ( v15 >= 16 )
+      v15 = 14;
+    v12 = v15;
+    //goto LABEL_45;
+	v96 = v15;
+    pRenderVertexSoft.vWorldPosition.x = (double)pParty->vPosition.x;
+    pRenderVertexSoft.vWorldPosition.y = (double)pParty->vPosition.y;
+    v21 = (double)pParty->sEyelevel + (double)pParty->vPosition.z;
+    goto LABEL_47;
+  }
+  if ( (a3 & 7) == 2 )
+  {
+    v22 = pAudioPlayer->uNum3DSamples;
+    if ( v22 < 16 )
+    {
+      v12 = 5 * v22 / 16;
+      v96 = 7 * v22 / 16;
+    }
+    else
+    {
+      v96 = 7;
+      v12 = 5;
+    }
+    pLayingItem = &pLayingItems[a3 >> 3];
+  }
+  else
+  {
+    if ( (a3 & 7) == 3 )
+    {
+      v18 = pAudioPlayer->uNum3DSamples;
+      v12 = 0;
+      if ( v18 < 16 )
+        v96 = 3 * v18 / 16;
+      else
+        v96 = 3;
+      pActor1 = &pActors[a3 >> 3];
+      v20 = pActor1->vPosition.y;
+      pRenderVertexSoft.vWorldPosition.x = (double)pActor1->vPosition.x;
+      v100 = pActor1->vPosition.z;
+      pRenderVertexSoft.vWorldPosition.y = (double)v20;
+      v21 = (double)v100;
+      goto LABEL_47;
+    }
+    if ( (a3 & 7) != 5 )
+    {
+      v13 = pAudioPlayer->uNum3DSamples;
+      if ( (a3 & 7) == 6 )
+      {
+        if ( v13 >= 16 )
+        {
+          v96 = 9;
+          v12 = 8;
+          //goto LABEL_46;
+		  pRenderVertexSoft.vWorldPosition.x = (double)pParty->vPosition.x;
+          pRenderVertexSoft.vWorldPosition.y = (double)pParty->vPosition.y;
+		  v21 = (double)pParty->sEyelevel + (double)pParty->vPosition.z;
+		  goto LABEL_47;
+        }
+        v12 = 8 * v13 / 16;
+        v14 = 9 * v13;
+      }
+      else
+      {
+        if ( v13 >= 16 )
+        {
+          v96 = 12;
+          v12 = 10;
+//LABEL_46:
+          pRenderVertexSoft.vWorldPosition.x = (double)pParty->vPosition.x;
+          pRenderVertexSoft.vWorldPosition.y = (double)pParty->vPosition.y;
+          v21 = (double)pParty->sEyelevel + (double)pParty->vPosition.z;
+          goto LABEL_47;
+        }
+        v12 = 10 * v13 / 16;
+        v14 = 12 * v13;
+      }
+      v15 = v14 / 16;
+//LABEL_45:
+      v96 = v15;
+      //goto LABEL_46;
+	  pRenderVertexSoft.vWorldPosition.x = (double)pParty->vPosition.x;
+      pRenderVertexSoft.vWorldPosition.y = (double)pParty->vPosition.y;
+      v21 = (double)pParty->sEyelevel + (double)pParty->vPosition.z;
+      goto LABEL_47;
+    }
+    v16 = pAudioPlayer->uNum3DSamples;
+    if ( v16 < 16 )
+    {
+      v12 = v16 / 4;
+      v96 = v16 / 4;
+    }
+    else
+    {
+      v12 = 4;
+      v96 = 4;
+    }
+    pLayingItem = (LayingItem *)&pLevelDecorations[a3 >> 3];
+  }
+  pRenderVertexSoft.vWorldPosition.x = (double)pLayingItem->vPosition.x;
+  pRenderVertexSoft.vWorldPosition.y = (double)pLayingItem->vPosition.y;
+  v21 = (double)pLayingItem->vPosition.z;
+LABEL_47:
+  pRenderVertexSoft.vWorldPosition.z = v21;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    sub_4AAEA6_transform(&pRenderVertexSoft);
+  else
+    pGame->pIndoorCameraD3D->ViewTransform(&pRenderVertexSoft, 1);
+  if ( a3 )
+  {
+    if ( a3 != -1 )
+    {
+      v101 = 0;
+      if ( pAudioPlayer->uNum3DSamples > 0 )
+      {
+        pAudioPlayer_3DSample = pAudioPlayer->p3DSamples;
+        do
+        {
+          if ( AIL_3D_sample_status(pAudioPlayer_3DSample->hSample) == 4 
+			  && pAudioPlayer_3DSample->field_4 == a3 && AIL_3D_sample_status(pAudioPlayer_3DSample->hSample) == 4 )
+          {
+            if ( pAudioPlayer_3DSample->field_8 == pNum )
+              return;
+            AIL_end_3D_sample(pAudioPlayer_3DSample->hSample);
+            pAudioPlayer->_4ABF23(pAudioPlayer_3DSample);
+          }
+          ++v101;
+          ++pAudioPlayer_3DSample;
+        }
+        while ( v101 < pAudioPlayer->uNum3DSamples );
+      }
+    }
+  }
+  v102 = v12;
+  if ( v12 <= v96 )
+  {
+    pAudioPlayer_3DSample1 = &pAudioPlayer->p3DSamples[v12];
+    while ( AIL_3D_sample_status(pAudioPlayer_3DSample1->hSample) != 2 )
+    {
+      ++v102;
+      ++pAudioPlayer_3DSample1;
+      if ( v102 > v96 )
+        goto LABEL_67;
+    }
+    AIL_end_3D_sample(pAudioPlayer_3DSample1->hSample);
+    if ( pAudioPlayer_3DSample1->field_8 )
+      pAudioPlayer->_4ABF23(pAudioPlayer_3DSample1);
+  }
+LABEL_67:
+  v25 = v96;
+  if ( v102 == v96 + 1 )
+  {
+    LODWORD(v91) = -1;
+    v103 = 0;
+    *(float *)&varC = pRenderVertexSoft.vWorldViewPosition.y * -0.012207031;
+    v93 = 0.0;
+    v26 = pRenderVertexSoft.vWorldViewPosition.x * 0.012207031;
+    *(float *)&uVolume = v26;
+    v27 = abs((signed __int64)v26);
+    v28 = abs((signed __int64)v93);
+    v29 = abs((signed __int64)*(float *)&varC);
+    v90 = sub_4621DA(v29, v28, v27);
+    sPlaybackRate = v12;
+    if ( v12 > v25 )
+      goto LABEL_192;
+    pAudioPlayer_3DSample2 = &pAudioPlayer->p3DSamples[v12];
+    do
+    {
+      AIL_3D_position(pAudioPlayer_3DSample2->hSample, &varC, &v93, (long *)&uVolume);
+      v31 = abs((signed __int64)*(float *)&uVolume);
+      v32 = abs((signed __int64)v93);
+      v33 = abs((signed __int64)*(float *)&varC);
+      v34 = sub_4621DA(v33, v32, v31);
+      v35 = v103 == v34;
+      if ( v103 < v34 )
+      {
+        v103 = v34;
+        v35 = 1;
+      }
+      if ( v35 && v90 < v103 )
+      {
+        v36 = sPlaybackRate;
+        LODWORD(v91) = sPlaybackRate;
+      }
+      else
+      {
+        v36 = LODWORD(v91);
+      }
+      ++sPlaybackRate;
+      ++pAudioPlayer_3DSample2;
+    }
+    while ( sPlaybackRate <= v96 );
+    if ( v36 == -1 )
+    {
+LABEL_192:
+      v36 = 13;
+      if ( v12 != 13 )
+        return;
+    }
+    //pAudioPlayer2 = pAudioPlayer;
+    pAudioPlayer_3DSample3 = &pAudioPlayer->p3DSamples[v36];
+    AIL_end_3D_sample(pAudioPlayer_3DSample3->hSample);
+    pAudioPlayer->_4ABF23(pAudioPlayer_3DSample3);
+    v102 = v36;
+  }
+  v39 = v89;
+  if ( pSoundList->pSounds[v89 / 0x78].p3DSound || (LOWORD(v40) = pSoundList->LoadSound(eSoundID, 0), v40) )
+  {
+    v41 = (char *)pAudioPlayer + 16 * v102;
+    v42 = (int)(v41 + 20);
+    if ( AIL_set_3D_sample_file(*((int *)v41 + 5), *(void **)((char *)&pSoundList->pSounds->p3DSound + v39)) )
+    {
+      if ( uNumRepeats )
+        v86 = uNumRepeats - 1;
+      else
+        v86 = 1;
+      AIL_set_3D_sample_loop_count(*(int *)v42, v86);
+      if ( PartyX == -1 )
+      {
+        if ( (a3 & 7) == 1 )
+        {
+          if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+          {
+			//goto LABEL_103;
+            pBLVDoor = &pIndoor->pDoors[a3 >> 3];
+            if ( !pBLVDoor->uDoorID )
+             return;
+            pRenderVertexSoft.vWorldPosition.x = (double)*pBLVDoor->pXOffsets;
+            pRenderVertexSoft.vWorldPosition.y = (double)*pBLVDoor->pYOffsets;
+            v47 = (double)*pBLVDoor->pZOffsets;
+LABEL_101:
+            pRenderVertexSoft.vWorldPosition.z = v47;
+          //if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+          //{
+            sub_4AAEA6_transform(&pRenderVertexSoft);
+            //goto LABEL_104;
+          //}
+		  }
+//LABEL_103:
+		  if ( uCurrentlyLoadedLevelType != LEVEL_Indoor )
+            pGame->pIndoorCameraD3D->ViewTransform(&pRenderVertexSoft, 1);
+//LABEL_104:
+          AIL_start_3D_sample(*(int *)v42);
+          AIL_set_3D_sample_float_distances(*(int **)v42, 100.0, 20.0, 100.0, 20.0);
+          AIL_set_3D_sample_volume(*(int **)v42, pAudioPlayer->s3DSoundVolume);
+          v99 = pRenderVertexSoft.vWorldViewPosition.y * -0.012207031;
+          v49 = pRenderVertexSoft.vWorldViewPosition.x * 0.012207031;
+          uNumRepeatsa = v49;
+          v50 = abs((signed __int64)v49);
+          v51 = abs(0);
+          v52 = abs((signed __int64)v99);
+          if ( sub_4621DA(v52, v51, v50) <= 100 )
+          {
+            AIL_set_3D_position((void *)*(int *)v42, LODWORD(v99), 0.0, LODWORD(uNumRepeatsa));
+            v53 = -uNumRepeatsa;
+            v54 = -v99;
+            AIL_set_3D_orientation((void *)*(int *)v42, LODWORD(v54), 0.0, LODWORD(v53), 0.0, 1.0, 0.0);
+            //pAudioPlayer3 = pAudioPlayer;
+            *((int *)v41 + 6) = a3;
+            *((int *)v41 + 7) = pNum;
+            *(&pAudioPlayer->bEAXSupported + 4 * (v102 + 2)) = eSoundID;
+          }
+          else
+          {
+            AIL_end_3D_sample(*(int **)v42);
+            pAudioPlayer->_4ABF23((AudioPlayer_3DSample *)(v41 + 20));
+          }
+          return;
+        }
+        if ( (a3 & 7) == 2 )
+        {
+          pLayingItem2 = &pLayingItems[a3 >> 3];
+        }
+        else
+        {
+          if ( (a3 & 7) == 3 )
+          {
+            pActor = &pActors[a3 >> 3];
+            v46 = pActor->vPosition.y;
+            pRenderVertexSoft.vWorldPosition.x = (double)pActor->vPosition.x;
+            uNumRepeatsb = pActor->vPosition.z;
+            pRenderVertexSoft.vWorldPosition.y = (double)v46;
+            v47 = (double)uNumRepeatsb;
+            goto LABEL_101;
+          }
+          if ( (a3 & 7) != 5 )
+          {
+            pRenderVertexSoft.vWorldPosition.x = (double)pParty->vPosition.x;
+            v43 = (double)pParty->vPosition.y;
+LABEL_100:
+            pRenderVertexSoft.vWorldPosition.y = v43;
+            v47 = (double)pParty->sEyelevel + (double)pParty->vPosition.z;
+            goto LABEL_101;
+          }
+          pLayingItem2 = (LayingItem *)&pLevelDecorations[a3 >> 3];
+        }
+        pRenderVertexSoft.vWorldPosition.x = (double)pLayingItem2->vPosition.x;
+        pRenderVertexSoft.vWorldPosition.y = (double)pLayingItem2->vPosition.y;
+        v47 = (double)pLayingItem2->vPosition.z;
+        goto LABEL_101;
+      }
+      pRenderVertexSoft.vWorldPosition.x = (double)PartyX;
+      v43 = (double)PartyY;
+      goto LABEL_100;
+    }
+  }
+}
+
+//----- (0040DEA5) --------------------------------------------------------
+void __cdecl AudioPlayer::MessWithChannels()
+{
+  pAudioPlayer->StopChannels(-1, -1);
+}
+
+
+
+//----- (004AAFCF) --------------------------------------------------------
+void AudioPlayer::_4AAFCF()
+{
+  AudioPlayer *v1; // edi@1
+  int v2; // ebx@1
+  unsigned __int8 v3; // zf@1
+  int *v4; // eax@2
+  unsigned __int8 v5; // sf@4
+  AudioPlayer_3DSample *v6; // esi@5
+  int v7; // ebx@6
+  int v8; // ebx@9
+  int v9; // ebx@10
+  int v10; // ebx@11
+  double v11; // st7@13
+  LayingItem *v12; // eax@14
+  Actor *v13; // eax@15
+  signed int v14; // edx@15
+  BLVDoor *v15; // eax@19
+  double v16; // st7@22
+  double v17; // st6@22
+  double v18; // st5@23
+  double v19; // st4@24
+  double v20; // st3@24
+  double v21; // st6@28
+  double v22; // st7@32
+  int v23; // ST1C_4@32
+  int v24; // ebx@32
+  int v25; // eax@32
+  float v26; // ST10_4@34
+  float v27; // ST08_4@34
+  MixerChannel *v28; // esi@38
+  unsigned __int8 v29; // of@43
+  MixerChannel *v30; // esi@44
+  int v31; // eax@45
+  LayingItem *v32; // eax@49
+  Actor *v33; // edi@50
+  int v34; // eax@50
+  unsigned int v35; // edx@51
+  unsigned int v36; // ecx@51
+  LayingItem *v37; // edi@53
+  int v38; // eax@53
+  BLVDoor *v39; // edi@56
+  int v40; // eax@57
+  int v41; // eax@60
+  MixerChannel *v42; // edi@65
+  int v43; // ebx@68
+  LevelDecoration *v44; // esi@68
+  int v45; // ST1C_4@68
+  int v46; // edi@68
+  int v47; // eax@68
+  DecorationDesc *v48; // edi@69
+  __int16 v49; // ax@69
+  __int16 v50; // ax@70
+  __int16 v51; // ax@71
+  __int16 v52; // ax@73
+  signed int v53; // eax@88
+  RenderVertexSoft a1; // [sp+24h] [bp-48h]@1
+  float v55; // [sp+54h] [bp-18h]@22
+  float v56; // [sp+58h] [bp-14h]@22
+  int uNumRepeats; // [sp+5Ch] [bp-10h]@15
+  float v58; // [sp+60h] [bp-Ch]@23
+  int v59; // [sp+64h] [bp-8h]@4
+  AudioPlayer *thisa; // [sp+68h] [bp-4h]@1
+
+  v1 = this;
+  v2 = 0;
+  thisa = this;
+  v3 = this->bPlayerReady == 0;
+  a1.flt_2C = 0.0;
+  if ( !v3 )
+  {
+    v4 = &this->field_2D0_time_left;
+    *v4 -= pEventTimer->uTimeElapsed;
+    if ( this->field_2D0_time_left <= 0 )
+    {
+      v3 = this->b3DSoundInitialized == 0;
+      *v4 = 32;
+      if ( !v3 )
+      {
+        v3 = this->uNum3DSamples == 0;
+        v5 = this->uNum3DSamples < 0;
+        v59 = 0;
+        if ( !(v5 | v3) )
+        {
+          v6 = this->p3DSamples;
+          while ( 1 )
+          {
+            v7 = v6->field_4 & 7;
+            if ( AIL_3D_sample_status(v6->hSample) == 2 )
+            {
+              AIL_end_3D_sample(v6->hSample);
+              v1->_4ABF23(v6);
+            }
+            if ( AIL_3D_sample_status(v6->hSample) != 4 )
+              goto LABEL_35;
+            v8 = v7 - 1;
+            if ( v8 )
+              break;
+            if ( uCurrentlyLoadedLevelType != LEVEL_Indoor )
+              goto LABEL_31;
+            v15 = &pIndoor->pDoors[v6->field_4 >> 3];
+            if ( v15->uDoorID )
+            {
+              uNumRepeats = *v15->pXOffsets;
+              a1.vWorldPosition.x = (double)uNumRepeats;
+              uNumRepeats = *v15->pYOffsets;
+              a1.vWorldPosition.y = (double)uNumRepeats;
+              uNumRepeats = *v15->pZOffsets;
+              v11 = (double)uNumRepeats;
+              goto LABEL_21;
+            }
+LABEL_35:
+            ++v59;
+            ++v6;
+            if ( v59 >= v1->uNum3DSamples )
+            {
+              v2 = 0;
+              goto LABEL_37;
+            }
+          }
+          v9 = v8 - 1;
+          if ( v9 )
+          {
+            v10 = v9 - 1;
+            if ( !v10 )
+            {
+              v13 = &pActors[v6->field_4 >> 3];
+              uNumRepeats = v13->vPosition.x;
+              v14 = v13->vPosition.y;
+              a1.vWorldPosition.x = (double)uNumRepeats;
+              uNumRepeats = v13->vPosition.z;
+              a1.vWorldPosition.y = (double)v14;
+              v11 = (double)uNumRepeats;
+              goto LABEL_21;
+            }
+            if ( v10 != 2 )
+            {
+              a1.vWorldPosition.x = (double)pParty->vPosition.x;
+              a1.vWorldPosition.y = (double)pParty->vPosition.y;
+              v11 = (double)pParty->sEyelevel + (double)pParty->vPosition.z;
+              goto LABEL_21;
+            }
+            v12 = (LayingItem *)&pLevelDecorations[v6->field_4 >> 3];
+          }
+          else
+          {
+            v12 = &pLayingItems[v6->field_4 >> 3];
+          }
+          a1.vWorldPosition.x = (double)v12->vPosition.x;
+          a1.vWorldPosition.y = (double)v12->vPosition.y;
+          v11 = (double)v12->vPosition.z;
+LABEL_21:
+          a1.vWorldPosition.z = v11;
+          if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+          {
+            v16 = pBLVRenderParams->fCosineNegX;
+            v17 = pBLVRenderParams->fSineNegX;
+            v55 = pBLVRenderParams->fCosineY;
+            v56 = pBLVRenderParams->fSineY;
+            if ( pBLVRenderParams->sPartyRotX )
+            {
+              v58 = a1.vWorldPosition.x - (double)pParty->vPosition.x;
+              *(float *)&uNumRepeats = a1.vWorldPosition.y - (double)pParty->vPosition.y;
+              v18 = a1.vWorldPosition.z - (double)pParty->vPosition.z;
+              if ( pRenderer->pRenderD3D )
+              {
+                v19 = *(float *)&uNumRepeats * v56 + v58 * v55;
+                v20 = v58 * v56 - *(float *)&uNumRepeats * v55;
+              }
+              else
+              {
+                v19 = v58 * v55 - *(float *)&uNumRepeats * v56;
+                v20 = v58 * v56 + *(float *)&uNumRepeats * v55;
+              }
+              a1.vWorldViewPosition.x = v19 * v16 - v18 * v17;
+              a1.vWorldViewPosition.y = v20;
+              a1.vWorldViewPosition.z = v19 * v17 + v18 * v16;
+            }
+            else
+            {
+              v58 = a1.vWorldPosition.x - (double)pParty->vPosition.x;
+              *(float *)&uNumRepeats = a1.vWorldPosition.y - (double)pParty->vPosition.y;
+              if ( pRenderer->pRenderD3D )
+              {
+                a1.vWorldViewPosition.x = *(float *)&uNumRepeats * v56 + v58 * v55;
+                v21 = v58 * v56 - *(float *)&uNumRepeats * v55;
+              }
+              else
+              {
+                a1.vWorldViewPosition.x = v58 * v55 - *(float *)&uNumRepeats * v56;
+                v21 = v58 * v56 + *(float *)&uNumRepeats * v55;
+              }
+              a1.vWorldViewPosition.y = v21;
+              a1.vWorldViewPosition.z = a1.vWorldPosition.z - (double)pParty->vPosition.z;
+            }
+          }
+          else
+          {
+LABEL_31:
+            pGame->pIndoorCameraD3D->ViewTransform(&a1, 1u);
+          }
+          v58 = a1.vWorldViewPosition.y * -0.012207031;
+          v22 = a1.vWorldViewPosition.x * 0.012207031;
+          *(float *)&uNumRepeats = v22;
+          v23 = abs((signed __int64)v22);
+          v24 = abs(0);
+          v25 = abs((signed __int64)v58);
+          if ( sub_4621DA(v25, v24, v23) <= 100 )
+          {
+            AIL_set_3D_position(v6->hSample, LODWORD(v58), 0.0, uNumRepeats);
+            v26 = -*(float *)&uNumRepeats;
+            v27 = -v58;
+            AIL_set_3D_orientation(v6->hSample, LODWORD(v27), 0.0, LODWORD(v26), 0.0, 1.0, 0.0);
+          }
+          else
+          {
+            AIL_end_3D_sample(v6->hSample);
+            v1->_4ABF23(v6);
+          }
+          goto LABEL_35;
+        }
+      }
+LABEL_37:
+      if ( v1->uMixerChannels > v2 )
+      {
+        v28 = v1->pMixerChannels;
+        do
+        {
+          if ( AIL_sample_status(v28->hSample) == 2 )
+          {
+            AIL_end_sample(v28->hSample);
+            v1->_4ABE55(v28);
+          }
+          ++v2;
+          ++v28;
+        }
+        while ( v2 < v1->uMixerChannels );
+        v2 = 0;
+      }
+      //v29 = __OFSUB__(v1->uMixerChannels, v2);
+	  v29 = v1->uMixerChannels > v2;
+      v3 = v1->uMixerChannels == v2;
+      v5 = v1->uMixerChannels - v2 < 0;
+      v59 = v2;
+      if ( !((unsigned __int8)(v5 ^ v29) | v3) )
+      {
+        v30 = v1->pMixerChannels;
+        while ( 1 )
+        {
+          v31 = v30->dword_000004;
+          if ( (v30->dword_000004 & 7) == 1 )
+          {
+            if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+            {
+              v39 = &pIndoor->pDoors[v31 >> 3];
+              if ( !v39->uDoorID )
+              {
+LABEL_61:
+                v1 = thisa;
+                goto LABEL_62;
+              }
+              v40 = GetSoundStrengthByDistanceFromParty(*v39->pXOffsets, *v39->pYOffsets, *v39->pZOffsets);
+              if ( !v40 )
+              {
+LABEL_58:
+                AIL_end_sample(v30->hSample);
+                thisa->_4ABE55(v30);
+                goto LABEL_61;
+              }
+              AIL_set_sample_volume(v30->hSample, v40);
+              v35 = *v39->pYOffsets;
+              v36 = *v39->pXOffsets;
+LABEL_60:
+              v41 = sub_4AB66C(v36, v35);
+              AIL_set_sample_pan(v30->hSample, v41);
+              goto LABEL_61;
+            }
+          }
+          else
+          {
+            if ( (v30->dword_000004 & 7) == 2 )
+            {
+              v32 = &pLayingItems[v31 >> 3];
+              goto LABEL_53;
+            }
+            if ( (v30->dword_000004 & 7) == 3 )
+            {
+              v33 = &pActors[v31 >> 3];
+              v34 = GetSoundStrengthByDistanceFromParty(v33->vPosition.x, v33->vPosition.y, v33->vPosition.z);
+              if ( !v34 )
+                goto LABEL_58;
+              AIL_set_sample_volume(v30->hSample, v34);
+              v35 = v33->vPosition.y;
+              v36 = v33->vPosition.x;
+              goto LABEL_60;
+            }
+            if ( (v30->dword_000004 & 7) == 5 )
+            {
+              v32 = (LayingItem *)&pLevelDecorations[v31 >> 3];
+LABEL_53:
+              v37 = v32;
+              v38 = GetSoundStrengthByDistanceFromParty(v32->vPosition.x, v32->vPosition.y, v32->vPosition.z);
+              if ( !v38 )
+                goto LABEL_58;
+              AIL_set_sample_volume(v30->hSample, v38);
+              v35 = v37->vPosition.y;
+              v36 = v37->vPosition.x;
+              goto LABEL_60;
+            }
+          }
+LABEL_62:
+          ++v59;
+          ++v30;
+          if ( v59 >= v1->uMixerChannels )
+          {
+            v2 = 0;
+            break;
+          }
+        }
+      }
+      if ( pCurrentScreen != v2 )
+      {
+        v42 = &v1->pMixerChannels[4];
+        if ( AIL_sample_status(v42->hSample) == 4 )
+          AIL_end_sample(v42->hSample);
+        return;
+      }
+      v59 = v2;
+      if ( _6807E0_num_decorations_with_sounds_6807B8 <= v2 )
+        return;
+      while ( 1 )
+      {
+        LODWORD(v56) = 1;
+        v43 = 4 * v59 + 6817720;
+        v44 = &pLevelDecorations[_6807B8_level_decorations_ids[v59]];
+        v45 = abs(v44->vPosition.z - pParty->vPosition.z);
+        v46 = abs(v44->vPosition.y - pParty->vPosition.y);
+        v47 = abs(v44->vPosition.x - pParty->vPosition.x);
+        if ( sub_4621DA(v47, v46, v45) <= 8192 )
+          break;
+LABEL_89:
+        ++v59;
+        if ( v59 >= _6807E0_num_decorations_with_sounds_6807B8 )
+          return;
+      }
+      v48 = &pDecorationList->pDecorations[v44->uDecorationDescID];
+      v49 = v48->uFlags;
+      uNumRepeats = (~(unsigned __int8)v48->uFlags & 0x40) >> 6;
+      if ( HIBYTE(v49) & 3 )
+      {
+        v50 = v44->field_1A;
+        v55 = 0.0;
+        uNumRepeats = 2;
+        if ( v50 )
+        {
+          v51 = v50 - 32;
+          v44->field_1A = v51;
+          if ( v51 < 0 )
+            v44->field_1A = 0;
+        }
+      }
+      v52 = v48->uFlags;
+      if ( !(HIBYTE(v52) & 1) )
+      {
+        if ( !(HIBYTE(v52) & 2) )
+          goto LABEL_84;
+        if ( v55 != 0.0 )
+          goto LABEL_85;
+      }
+      v56 = 0.0;
+      if ( pParty->uCurrentHour >= 5 && pParty->uCurrentHour < 6
+        || pParty->uCurrentHour >= 0x14 && pParty->uCurrentHour < 0x15 )
+      {
+        if ( !v44->field_1A && rand() % 100 < 100 )
+          LODWORD(v56) = 1;
+        LODWORD(v55) = 1;
+      }
+LABEL_84:
+      if ( v55 == 0.0 )
+      {
+LABEL_87:
+        if ( v56 != 0.0 )
+        {
+          v53 = 8 * *(int *)v43;
+          LOBYTE(v53) = v53 | 5;
+          thisa->PlaySound((SoundID)v48->uSoundID, v53, uNumRepeats, -1, 0, 0, 0, 0);
+        }
+        goto LABEL_89;
+      }
+LABEL_85:
+      if ( !v44->field_1A )
+        v44->field_1A = (rand() % 15 + 1) << 7;
+      goto LABEL_87;
+    }
+  }
+}
+
+
+
+//----- (004AB66C) --------------------------------------------------------
+int __fastcall sub_4AB66C(int a1, int a2)
+{
+  signed int v2; // eax@1
+
+  v2 = stru_5C6E00->uDoublePiMask & (stru_5C6E00->Atan2(a1 - pParty->vPosition.x, a2 - pParty->vPosition.y)
+                                  - stru_5C6E00->uIntegerHalfPi
+                                  - pParty->sRotationY);
+  if ( v2 > (signed int)stru_5C6E00->uIntegerPi )
+    v2 = 2 * stru_5C6E00->uIntegerPi - v2;
+  return (v2 >> 3) - (v2 >> 10);
+}
+// 4AB66C: using guessed type int __fastcall sub_4AB66C(int, int);
+
+//----- (004AB6B1) --------------------------------------------------------
+int __fastcall GetSoundStrengthByDistanceFromParty(int a1, int a2, int a3)
+{
+  int v3; // esi@1
+  int v4; // edi@1
+  int v5; // ST08_4@1
+  int v6; // esi@1
+  int v7; // eax@1
+  int result; // eax@2
+  int v9; // [sp+10h] [bp+8h]@1
+
+  v3 = a2;
+  v4 = a1;
+  v5 = abs(a3 - pParty->vPosition.z);
+  v6 = abs(v3 - pParty->vPosition.y);
+  v7 = abs(v4 - pParty->vPosition.x);
+  v9 = sub_4621DA(v7, v6, v5);
+  if ( v9 <= 8192 )
+    result = 114 - (unsigned __int64)(signed __int64)((double)v9 * 0.0001220703125 * 100.0);
+  else
+    result = 0;
+  return result;
+}
+
+
+
+//----- (004AB71F) --------------------------------------------------------
+void AudioPlayer::StopChannels(int uStartChannel, int uEndChannel)
+{
+  //AudioPlayer *v3; // esi@1
+  int v4; // ecx@1
+  char *v5; // edi@4
+  int v6; // ebx@12
+  MixerChannel *pChannel; // edi@14
+  //_STREAM *v8; // esi@23
+  int v9; // [sp+4h] [bp-4h]@3
+
+  //v3 = this;
+  v4 = 0;
+  if ( bPlayerReady )
+  {
+    if ( b3DSoundInitialized )
+    {
+      v9 = 0;
+      if ( uNum3DSamples > 0 )
+      {
+        v5 = (char *)&p3DSamples[0].field_8;
+        do
+        {
+          if ( (uStartChannel == -1 || v4 < uStartChannel || v4 > uEndChannel)
+            && *(int *)v5
+            && pSoundList->pSounds[*(int *)v5].eType != SOUND_DESC_SYSTEM)
+          {
+            AIL_end_3D_sample(*((int **)v5 - 2));
+            _4ABF23((AudioPlayer_3DSample *)(v5 - 8));
+            *((int *)v5 - 1) = 0;
+            v4 = v9;
+          }
+          ++v4;
+          v5 += 16;
+          v9 = v4;
+        }
+        while ( v4 < uNum3DSamples );
+      }
+    }
+    v6 = 0;
+    if ( hDigDriver && uMixerChannels > 0 )
+    {
+      pChannel = pMixerChannels;
+      do
+      {
+        if ( (uStartChannel == -1 || v6 < uStartChannel || v6 > uEndChannel)
+          && pSoundList->pSounds[pChannel->uSourceTrackIdx].eType != SOUND_DESC_SYSTEM)
+        {
+          AIL_end_sample(pChannel->hSample);
+          _4ABE55(pChannel);
+          pChannel->dword_000004 = 0;
+        }
+        ++v6;
+        ++pChannel;
+      }
+      while (v6 < uMixerChannels);
+    }
+    if (hSequence)
+      AIL_end_sequence(hSequence);
+    //v8 = hStream;
+    if (hStream)
+      AIL_pause_stream(hStream, 1);
+  }
+}
+
+
+//----- (004AB818) --------------------------------------------------------
+void AudioPlayer::LoadAudioSnd()
+{
+  DWORD NumberOfBytesRead; // [sp+Ch] [bp-4h]@3
+
+  hAudioSnd = CreateFileA("Sounds\\Audio.snd", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0x8000080u, 0);
+  if (hAudioSnd == INVALID_HANDLE_VALUE)
+  {
+    Log::Warning(L"Can't open file: %s", L"Sounds\\Audio.snd");
+    return;
+  }
+
+  ReadFile(hAudioSnd, &uNumSoundHeaders, 4u, &NumberOfBytesRead, 0);
+  pSoundHeaders = nullptr;
+  pSoundHeaders = (SoundHeader *)pAllocator->AllocNamedChunk(0, 52 * uNumSoundHeaders + 2, 0);
+  ReadFile(hAudioSnd, pSoundHeaders, 52 * uNumSoundHeaders, &NumberOfBytesRead, 0);
+}
+
+//----- (004AB8CE) --------------------------------------------------------
+void AudioPlayer::Initialize(HWND hWnd)
+{
+  //AudioPlayer *v2; // esi@1
+  int v3; // ebx@1
+  //_DIG_DRIVER *v4; // eax@1
+  char v5; // dl@5
+  _PROVIDER *v6; // eax@9
+  HWND v7; // ST00_4@9
+  MixerChannel *pChannel; // edi@14
+  _SAMPLE *v9; // eax@15
+  //_REDBOOK *v10; // eax@19
+  //int v11; // ecx@21
+  int v12; // [sp+Ch] [bp-Ch]@9
+  char *Str1; // [sp+10h] [bp-8h]@6
+  int v14; // [sp+14h] [bp-4h]@5
+
+  //v2 = this;
+  v3 = 0;
+  this->hWindow = hWnd;
+  this->hAILRedbook = 0;
+  this->hDigDriver = 0;
+  this->dword_0002AC = 0;
+  this->hSequence = 0;
+  this->uMasterVolume = 127;
+  this->dword_0002C8 = 64;
+  this->dword_0002CC = 2;
+
+  MSS32_DLL_Initialize();
+  BINKW32_DLL_Initialize();
+  SMACKW32_DLL_Initialize();
+  
+  AIL_startup();
+  if (bCanLoadFromCD)
+    hAILRedbook = AIL_redbook_open_drive(cMM7GameCDDriveLetter/*cGameCDDriveLetter*/);
+  //else
+  //  hAILRedbook = AIL_redbook_open(0);
+  //v4 = Audio_GetFirstHardwareDigitalDriver();
+
+  hDigDriver = Audio_GetFirstHardwareDigitalDriver();
+  if ( hDigDriver )
+    SmackSoundUseMSS(hDigDriver);
+  if ( ReadWindowsRegistryInt("Disable3DSound", 0) != 1 && pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT )
+  {
+    v14 = 0;
+    bEAXSupported = 0;
+    b3DSoundInitialized = 0;
+    ReadWindowsRegistryString("3DSoundProvider", p3DSoundProvider, 128u, "NONE");
+    CheckA3DSupport(v5);
+    while ( AIL_enumerate_3D_providers(&v14, (HPROVIDER *)&hWnd, &Str1) )
+    {
+      if ( !strcmp(Str1, p3DSoundProvider) )
+      {
+        if ( AIL_open_3D_provider((HPROVIDER)hWnd) )
+        {
+          bEAXSupported = 0;
+          b3DSoundInitialized = 0;
+          h3DSoundProvider = 0;
+        }
+        else
+        {
+          v6 = (_PROVIDER *)hWnd;
+          v7 = hWnd;
+          b3DSoundInitialized = 1;
+          h3DSoundProvider = v6;
+          uNum3DSamples = 4;
+          AIL_3D_provider_attribute((HPROVIDER)v7, "EAX environment selection", &v12);
+          if ( v12 != -1 )
+            bEAXSupported = 1;
+        }
+        pAudioPlayer->_4AC0A2();
+        break;
+      }
+    }
+  }
+  if ( uMixerChannels > 0 )
+  {
+    pChannel = pMixerChannels;
+    do
+    {
+      v9 = AIL_allocate_sample_handle(hDigDriver);
+      pChannel->hSample = v9;
+      if ( !v9 )
+        break;
+      ++v3;
+      ++pChannel;
+    }
+    while ( v3 < uMixerChannels );
+  }
+  uMixerChannels = v3;
+  if ( bPlayerReady )
+    StopChannels(-1, -1);
+  //v10 = hAILRedbook;
+  bPlayerReady = true;
+  if ( hAILRedbook )
+  {
+    AIL_redbook_stop(hAILRedbook);
+    uNumRedbookTracks = AIL_redbook_tracks(hAILRedbook);
+  }
+  pAudioPlayer->sRedbookVolume = AIL_redbook_volume(hAILRedbook);
+  pAudioPlayer->SetMasterVolume(pSoundVolumeLevels[uSoundVolumeMultiplier] * 128.0);
+  if ( bPlayerReady && hAILRedbook )
+    AIL_redbook_set_volume(hAILRedbook, (unsigned __int64)(pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0) >> 32);
+  LoadAudioSnd();
+}
+
+//----- (004ABAF7) --------------------------------------------------------
+_DIG_DRIVER *Audio_GetFirstHardwareDigitalDriver(void)
+{
+  int v0; // ecx@1
+  unsigned int v1; // ebp@2
+  size_t v2; // eax@4
+  signed int v3; // kr14_4@9
+  char *v5; // [sp+10h] [bp-Ch]@2
+  unsigned int v6; // [sp+14h] [bp-8h]@1
+  _DIG_DRIVER *hDrv; // [sp+18h] [bp-4h]@3
+  
+  static int dword_4F00DC = 22050;
+  static int dword_4F00E0 = 16;
+  static int dword_4F00E4 = 2;
+
+  AIL_set_preference(15, 0);
+  AIL_set_preference(33, 1);
+  v0 = dword_4F00DC;
+  pAudioPlayer->pDeviceNames[0][0] = 0;
+  pAudioPlayer->uNumDevices = 0;
+  v6 = 0;
+
+  if ( dword_4F00DC < 11025 )
+    return 0;
+  v1 = 0;
+  v5 = (char *)pAudioPlayer->array_000BF0;
+  while ( 1 )
+  {
+    while ( 1 )
+    {
+      pcmWaveFormat.wf.wFormatTag = 1;
+      pcmWaveFormat.wf.nChannels = dword_4F00E4;
+      pcmWaveFormat.wf.nSamplesPerSec = v0;
+      pcmWaveFormat.wf.nBlockAlign = dword_4F00E4 * dword_4F00E0 / 8;
+      pcmWaveFormat.wBitsPerSample = dword_4F00E0;
+      pcmWaveFormat.wf.nAvgBytesPerSec = v0 * dword_4F00E4 * dword_4F00E0 / 8;
+      if ( !AIL_waveOutOpen(&hDrv, 0, -1, &pcmWaveFormat.wf) )
+        break;
+      if ( !AIL_get_preference(15) )
+        goto LABEL_8;
+      v3 = dword_4F00DC;
+      v0 = dword_4F00DC / 2;
+      dword_4F00DC /= 2;
+      if ( v3 / 2 < 11025 )
+      {
+        if ( dword_4F00E0 == 8 )
+        {
+          v0 = 22050;
+          dword_4F00E0 = 8;
+          dword_4F00DC = 22050;
+        }
+        goto LABEL_12;
+      }
+    }
+    strcpy(pAudioPlayer->pDeviceNames[v1 / 8], "Device: ");
+    v2 = strlen(pAudioPlayer->pDeviceNames[v1 / 8]);
+    AIL_digital_configuration(hDrv, (int *)v5, (int *)(v5 + 64), (char *)pAudioPlayer->pDeviceNames + v2 + v1 * 16);
+    ++v6;
+    v1 += 8;
+    v5 += 4;
+    pAudioPlayer->uNumDevices = v6;
+    if ( AIL_get_preference(15) )
+      return hDrv;
+    if ( !strstr(pAudioPlayer->pDeviceNames[v1 / 8 - 1], "Emulated") )
+      return hDrv;
+    AIL_waveOutClose(hDrv);
+    AIL_set_preference(15, 1);
+LABEL_8:
+    AIL_set_preference(15, 1);
+    v0 = dword_4F00DC;
+LABEL_12:
+    if ( v0 < 11025 )
+      return 0;
+  }
+}
+
+
+//----- (004ABC9B) --------------------------------------------------------
+LSTATUS AudioPlayer::CheckA3DSupport(char a2)
+{
+  LSTATUS result; // eax@1
+  DWORD cbData; // [sp+8h] [bp-Ch]@1
+  int Data; // [sp+Ch] [bp-8h]@1
+  HKEY hKey; // [sp+10h] [bp-4h]@1
+  char v6; // [sp+1Ch] [bp+8h]@0
+
+  hKey = 0;
+  cbData = 4;
+  Data = 0;
+  result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Aureal\\A3D", 0, 0x2001Fu, &hKey);
+  if ( !result )
+  {
+    if ( v6 )
+      RegQueryValueExA(hKey, "SplashAudio", 0, 0, (LPBYTE)&Aureal3D_SplashAudio, &cbData);
+    else
+      Data = Aureal3D_SplashAudio;
+    RegSetValueExA(hKey, "SplashAudio", 0, 4u, (const BYTE *)&Data, 4u);
+    Data = 0;
+    if ( v6 )
+      RegQueryValueExA(hKey, "SplashScreen", 0, 0, (LPBYTE)&Aureal3D_SplashScreen, &cbData);
+    else
+      Data = Aureal3D_SplashScreen;
+    RegSetValueExA(hKey, "SplashScreen", 0, 4u, (const BYTE *)&Data, 4u);
+    result = RegCloseKey(hKey);
+  }
+  return result;
+}
+// 4ABC9B: inconsistent function type and number of purged bytes
+
+//----- (004ABD5B) --------------------------------------------------------
+void AudioPlayer::Release()
+{
+  AudioPlayer *v1; // esi@1
+  int v2; // edi@1
+  MixerChannel *v3; // ebx@3
+  char v4; // dl@5
+  int v5; // ebx@6
+  AudioPlayer_3DSample *v6; // edi@7
+  int v7; // edx@14
+  int v8; // ecx@14
+  void *v9; // ecx@15
+
+  v1 = this;
+  v2 = 0;
+  if ( this->bPlayerReady )
+  {
+    CloseHandle(pVideoPlayer->hMagicVid);
+    CloseHandle(pVideoPlayer->hMightVid);
+    v1->StopChannels(-1, -1);
+    if ( v1->uMixerChannels > 0 )
+    {
+      v3 = v1->pMixerChannels;
+      do
+      {
+        AIL_release_sample_handle(v3->hSample);
+        ++v2;
+        ++v3;
+      }
+      while ( v2 < v1->uMixerChannels );
+    }
+    if ( ReadWindowsRegistryInt("Disable3DSound", 0) != 1 )
+    {
+      v5 = 0;
+      v1->CheckA3DSupport(v4);
+      if ( v1->uNum3DSamples > 0 )
+      {
+        v6 = v1->p3DSamples;
+        do
+        {
+          if ( v6->hSample )
+          {
+            AIL_release_3D_sample_handle(v6->hSample);
+            v6->hSample = 0;
+          }
+          ++v5;
+          ++v6;
+        }
+        while ( v5 < v1->uNum3DSamples );
+      }
+      if ( v1->h3DSoundProvider )
+      {
+        AIL_close_3D_provider(v1->h3DSoundProvider);
+        v1->h3DSoundProvider = 0;
+      }
+    }
+    if ( v1->hAILRedbook )
+    {
+      AIL_redbook_stop(v1->hAILRedbook);
+      AIL_redbook_set_volume((HREDBOOK)v8, v7);
+      AIL_redbook_close(v1->hAILRedbook);
+    }
+    AIL_shutdown();
+    pSoundList->Release();
+    v9 = *(void **)&v1->field_C78[0];
+    if ( v9 )
+      ReleaseSoundData(v9);
+    CloseHandle(v1->hAudioSnd);
+  }
+}
+
+//----- (004ABE55) --------------------------------------------------------
+void AudioPlayer::_4ABE55(MixerChannel *pChannel)
+{
+  int v2; // ebx@1
+  //AudioPlayer *v3; // esi@1
+  SoundDesc *v4; // eax@2
+  unsigned __int8 v5; // zf@5
+  unsigned __int8 v6; // sf@5
+  char *v7; // edi@6
+  int v8; // eax@8
+  int v9; // ST04_4@8
+  int v10; // ecx@12
+  int v11; // edi@13
+  int v12; // eax@13
+  unsigned __int8 v13; // of@13
+  int v14[16]; // [sp+Ch] [bp-48h]@8
+  int v15; // [sp+4Ch] [bp-8h]@5
+  int v16; // [sp+50h] [bp-4h]@5
+
+  v2 = 0;
+  //v3 = this;
+  if ( pSoundList->pSounds )
+  {
+    v4 = &pSoundList->pSounds[pChannel->uSourceTrackIdx];
+    if ( v4->eType == SOUND_DESC_SWAP)
+    {
+      if ( v4->pSoundData[0] && !(v4->uFlags & 1) )
+      {
+        v5 = this->uMixerChannels == 0;
+        v6 = this->uMixerChannels < 0;
+        v15 = 0;
+        v16 = 0;
+        if ( v6 | v5 )
+          goto LABEL_16;
+        v7 = (char *)this->pMixerChannels;
+        do
+        {
+          if ( pChannel->uSourceTrackID == *((int *)v7 + 3) )
+          {
+            v8 = v16;
+            v9 = *(int *)v7;
+            ++v16;
+            v14[v8] = v2;
+            if ( AIL_sample_status((HSAMPLE)v9) == 4 )
+              ++v15;
+          }
+          ++v2;
+          v7 += 16;
+        }
+        while ( v2 < uMixerChannels );
+        if ( !v15 )
+        {
+LABEL_16:
+          pSoundList->_4A9DCD(pChannel->uSourceTrackIdx, 1);
+          v10 = 0;
+          if ( v16 > 0 )
+          {
+            do
+            {
+              v11 = v14[v10];
+              v12 = 16 * (v14[v10++] + 47);
+              pMixerChannels[v11].uSourceTrackID = 0;
+              v13 = __OFSUB__(v10, v16);
+              v6 = v10 - v16 < 0;
+              *(unsigned int *)((char *)&bEAXSupported + v12) = 0;
+            }
+            while ( v6 ^ v13 );
+          }
+        }
+      }
+    }
+  }
+}
+// 4D82F8: using guessed type int __stdcall AIL_sample_status(int);
+// 4ABE55: using guessed type int var_48[16];
+
+
+
+//----- (004AAEA6) --------------------------------------------------------
+int __fastcall sub_4AAEA6_transform(RenderVertexSoft *a1)
+{
+  double v1; // st7@1
+  double v2; // st6@1
+  int result; // eax@1
+  double v4; // st5@2
+  double v5; // st4@3
+  double v6; // st3@3
+  double v7; // st7@6
+  double v8; // st6@7
+  float v9; // [sp+0h] [bp-10h]@1
+  float v10; // [sp+4h] [bp-Ch]@1
+  float v11; // [sp+8h] [bp-8h]@2
+  float v12; // [sp+8h] [bp-8h]@6
+  float v13; // [sp+Ch] [bp-4h]@2
+  float v14; // [sp+Ch] [bp-4h]@6
+
+  v1 = pBLVRenderParams->fCosineNegX;
+  v2 = pBLVRenderParams->fSineNegX;
+  v9 = pBLVRenderParams->fCosineY;
+  v10 = pBLVRenderParams->fSineY;
+  result = 0;
+  if ( pBLVRenderParams->sPartyRotX )
+  {
+    v13 = a1->vWorldPosition.x - (double)pParty->vPosition.x;
+    v11 = a1->vWorldPosition.y - (double)pParty->vPosition.y;
+    v4 = a1->vWorldPosition.z - (double)pParty->vPosition.z;
+    if ( pRenderer->pRenderD3D )
+    {
+      v5 = v11 * pBLVRenderParams->fSineY + v13 * pBLVRenderParams->fCosineY;
+      v6 = v13 * pBLVRenderParams->fSineY - v11 * pBLVRenderParams->fCosineY;
+    }
+    else
+    {
+      v5 = v13 * pBLVRenderParams->fCosineY - v11 * pBLVRenderParams->fSineY;
+      v6 = v13 * pBLVRenderParams->fSineY + v11 * pBLVRenderParams->fCosineY;
+    }
+    a1->vWorldViewPosition.x = v5 * v1 - v4 * v2;
+    a1->vWorldViewPosition.y = v6;
+    a1->vWorldViewPosition.z = v5 * v2 + v4 * v1;
+  }
+  else
+  {
+    v14 = a1->vWorldPosition.x - (double)pParty->vPosition.x;
+    v12 = a1->vWorldPosition.y - (double)pParty->vPosition.y;
+    v7 = a1->vWorldPosition.z - (double)pParty->vPosition.z;
+    if ( pRenderer->pRenderD3D )
+    {
+      a1->vWorldViewPosition.x = v12 * pBLVRenderParams->fSineY + v14 * pBLVRenderParams->fCosineY;
+      v8 = v14 * v10 - v12 * v9;
+    }
+    else
+    {
+      a1->vWorldViewPosition.x = v14 * pBLVRenderParams->fCosineY - v12 * pBLVRenderParams->fSineY;
+      v8 = v14 * v10 + v12 * v9;
+    }
+    a1->vWorldViewPosition.y = v8;
+    a1->vWorldViewPosition.z = v7;
+  }
+  return result;
+}
+
+
+
+
+//----- (004ABF23) --------------------------------------------------------
+void AudioPlayer::_4ABF23(AudioPlayer_3DSample *a2)
+{
+  int v2; // ebx@1
+  //AudioPlayer *v3; // esi@1
+  SoundDesc *v4; // eax@2
+  unsigned __int8 v5; // zf@5
+  unsigned __int8 v6; // sf@5
+  char *v7; // edi@6
+  int v8; // eax@8
+  int v9; // ST04_4@8
+  int v10; // ecx@12
+  int v11; // eax@13
+  unsigned __int8 v12; // of@13
+  int v13[16]; // [sp+Ch] [bp-48h]@8
+  int v14; // [sp+4Ch] [bp-8h]@5
+  int v15; // [sp+50h] [bp-4h]@5
+
+  v2 = 0;
+  //v3 = this;
+  if ( pSoundList->pSounds )
+  {
+    v4 = &pSoundList->pSounds[a2->field_8];
+    if ( v4->eType == SOUND_DESC_SWAP)
+    {
+      if ( v4->p3DSound && !(v4->uFlags & 1) )
+      {
+        v5 = this->uNum3DSamples == 0;
+        v6 = this->uNum3DSamples < 0;
+        v14 = 0;
+        v15 = 0;
+        if ( v6 | v5 )
+          goto LABEL_16;
+        v7 = (char *)this->p3DSamples;
+        do
+        {
+          if ( a2->field_C == *((int *)v7 + 3) )
+          {
+            v8 = v15;
+            v9 = *(int *)v7;
+            ++v15;
+            v13[v8] = v2;
+            if ( AIL_3D_sample_status((void *)v9) == 4 )
+              ++v14;
+          }
+          ++v2;
+          v7 += 16;
+        }
+        while ( v2 < uNum3DSamples );
+        if ( !v14 )
+        {
+LABEL_16:
+          pSoundList->_4A9DCD(a2->field_8, 1);
+          v10 = 0;
+          if ( v15 > 0 )
+          {
+            do
+            {
+              v11 = v13[v10++];
+              *(&bEAXSupported + 4 * (v11 + 2)) = 0;
+              v12 = __OFSUB__(v10, v15);
+              v6 = v10 - v15 < 0;
+              p3DSamples[v11].field_8 = 0;
+            }
+            while ( v6 ^ v12 );
+          }
+        }
+      }
+    }
+  }
+}
+// 4D82F4: using guessed type int __stdcall AIL_3D_sample_status(int);
+// 4ABF23: using guessed type int var_48[16];
+
+//----- (004ABFDB) --------------------------------------------------------
+void __cdecl PlayLevelMusic()
+{
+  unsigned int v0; // eax@1
+
+  v0 = pMapStats->GetMapInfo(pCurrentMapName);
+  if ( v0 )
+    pAudioPlayer->PlayMusicTrack((MusicID)pMapStats->pInfos[v0].uRedbookTrackID);
+}
+
+//----- (004AC004) --------------------------------------------------------
+void AudioPlayer::SetEAXPreferences()
+{
+  AudioPlayer *v1; // edi@1
+  _PROVIDER *v2; // ST00_4@2
+  _PROVIDER *v3; // ST00_4@2
+  float v4; // [sp+4h] [bp-4h]@2
+
+  v1 = this;
+  if ( this->bEAXSupported )
+  {
+    v2 = this->h3DSoundProvider;
+    v4 = 0.0;
+    AIL_set_3D_provider_preference(v2, "EAX effect volume", (int *)&v4);
+    v3 = v1->h3DSoundProvider;
+    v4 = 1.0;
+    AIL_set_3D_provider_preference(v3, "EAX damping", (int *)&v4);
+  }
+}
+// 4D82DC: using guessed type int __stdcall AIL_set_3D_provider_preference(int, int, int);
+
+//----- (004AC041) --------------------------------------------------------
+void AudioPlayer::SetMapEAX()
+{
+  AudioPlayer *v1; // esi@1
+  unsigned int v2; // eax@1
+  int v3; // [sp+4h] [bp-4h]@3
+
+  v1 = this;
+  v2 = pMapStats->GetMapInfo(pCurrentMapName);
+  if ( v1->b3DSoundInitialized && v1->bEAXSupported )
+  {
+    v3 = pMapStats->pInfos[v2].uEAXEnv;
+    if ( (unsigned int)v3 >= 0x1A )
+    {
+      SetEAXPreferences();
+      v1->field_214 = -1;
+    }
+    else
+    {
+      AIL_set_3D_provider_preference(v1->h3DSoundProvider, "EAX environment selection", &v3);
+      v1->field_214 = v3;
+    }
+  }
+}
+// 4D82DC: using guessed type int __stdcall AIL_set_3D_provider_preference(int, int, int);
+
+//----- (004AC0A2) --------------------------------------------------------
+int AudioPlayer::_4AC0A2()
+{
+  AudioPlayer *v1; // esi@1
+  unsigned int v2; // eax@1
+  char v3; // zf@1
+  int v4; // ebx@1
+  int *v5; // edi@2
+  int v6; // eax@4
+  AudioPlayer_3DSample *v8; // ebx@7
+  void *v9; // eax@8
+  int v10; // ebx@14
+  unsigned int v11; // eax@14
+  int v12; // [sp+1Ch] [bp-8h]@1
+  int v13; // [sp+20h] [bp-4h]@6
+
+  v1 = this;
+  v2 = pMapStats->GetMapInfo(pCurrentMapName);
+  v3 = v1->b3DSoundInitialized == 0;
+  v4 = v2;
+  v12 = v2;
+  if ( !v3 )
+  {
+    v5 = &v1->uNum3DSamples;
+    AIL_3D_provider_attribute(v1->h3DSoundProvider, "Maximum supported samples", &v1->uNum3DSamples);
+    if ( v1->uNum3DSamples > 32 )
+      *v5 = 32;
+    v6 = *v5;
+    if ( !*v5 )
+    {
+      v1->b3DSoundInitialized = 0;
+      return -1;
+    }
+    v13 = 0;
+    if ( v6 > 0 )
+    {
+      v8 = v1->p3DSamples;
+      while ( 1 )
+      {
+        v9 = (void *)AIL_allocate_3D_sample_handle(v1->h3DSoundProvider);
+        v8->hSample = v9;
+        if ( !v9 )
+          break;
+        AIL_set_3D_sample_float_distances(v9, 4096.0, 256.0, 4096.0, 256.0);
+        AIL_set_3D_sample_volume(v8->hSample, v1->s3DSoundVolume);
+        ++v13;
+        ++v8;
+        if ( v13 >= *v5 )
+          goto LABEL_12;
+      }
+      *v5 = v13;
+LABEL_12:
+      v4 = v12;
+    }
+    if ( v1->bEAXSupported )
+    {
+      v10 = v4;
+      v11 = pMapStats->pInfos[v10].uEAXEnv;
+      v12 = pMapStats->pInfos[v10].uEAXEnv;
+      if ( v11 >= 0x1A )
+      {
+        pAudioPlayer->SetEAXPreferences();
+        v1->field_214 = -1;
+      }
+      else
+      {
+        AIL_set_3D_provider_preference(v1->h3DSoundProvider, "EAX environment selection", &v12);
+        v1->field_214 = v12;
+      }
+    }
+  }
+  return 1;
+}
+
+
+//----- (004A96BE) --------------------------------------------------------
+void ReleaseSoundData(void *_this)
+{
+  int v1; // esi@1
+  char *v2; // eax@1
+
+  v1 = 0;
+  v2 = (char *)&pSounds[0].pSoundData;
+  while ( *(void **)v2 != _this )
+  {
+    v2 += 128;
+    ++v1;
+    if ( (signed int)v2 >= (signed int)&pAudioPlayer->p3DSamples[6].field_8 )
+      return;
+  }
+  pAllocator->FreeChunk(_this);
+  memset(&pSounds[v1], 0, 0x80u);
+}
+
+//----- (004A96FF) --------------------------------------------------------
+SoundHeader *__fastcall FindSound_BinSearch(unsigned int uStart, unsigned int uEnd, const char *pName)
+{
+  unsigned int v3; // ebx@1
+  unsigned int v4; // esi@1
+  SoundHeader *result; // eax@2
+  signed int v6; // ebx@11
+  int v7; // edi@13
+  unsigned int v8; // esi@14
+  unsigned int v9; // esi@20
+  unsigned int v10; // [sp+Ch] [bp-4h]@1
+
+  v3 = uEnd;
+  v10 = uEnd;
+  v4 = uStart;
+  while ( 1 )
+  {
+    v6 = v3 - v4;
+    result = &pAudioPlayer->pSoundHeaders[v6 / 2 + v4];
+    if ( !result )
+      return result;
+    result = (SoundHeader *)_strcmpi(pName, result->pSoundName);
+    if ( !result )
+      uFindSound_BinSearch_ResultID = v6 / 2 + v4;
+    if ( v4 == v10 )
+      goto LABEL_17;
+    if ( (signed int)result < 0 )
+      break;
+    if ( v6 <= 4 )
+    {
+      v7 = v4;
+      if ( (signed int)v4 < (signed int)v10 )
+      {
+        v9 = v4;
+        do
+        {
+          result = (SoundHeader *)_strcmpi(pName, pAudioPlayer->pSoundHeaders[v9].pSoundName);
+          if ( !result )
+            goto LABEL_24;
+          ++v7;
+          ++v9;
+        }
+        while ( v7 < (signed int)v10 );
+      }
+LABEL_17:
+      uFindSound_BinSearch_ResultID = -1;
+      return result;
+    }
+    v4 += v6 / 2;
+LABEL_10:
+    v3 = v10;
+  }
+  if ( v6 > 4 )
+  {
+    v10 = v6 / 2 + v4;
+    goto LABEL_10;
+  }
+  v7 = v4;
+  if ( (signed int)v4 >= (signed int)v10 )
+    goto LABEL_17;
+  v8 = v4;
+  while ( 1 )
+  {
+    result = (SoundHeader *)_strcmpi(pName, pAudioPlayer->pSoundHeaders[v8].pSoundName);
+    if ( !result )
+      break;
+    ++v7;
+    ++v8;
+    if ( v7 >= (signed int)v10 )
+      goto LABEL_17;
+  }
+LABEL_24:
+  uFindSound_BinSearch_ResultID = v7;
+  return result;
+}
+// F1B4C8: using guessed type int uFindSound_BinSearch_ResultID;
+
+//----- (004A97C6) --------------------------------------------------------
+SoundData *LoadSound(const char *pSoundName, SoundData *pOutBuff, unsigned int uID)
+{
+  SoundData *v3; // edi@1
+  int v4; // ecx@1
+  //Sound *v5; // eax@1
+  SoundHeader *v6; // esi@5
+  unsigned int *pDecompressedSize; // ebx@5
+  unsigned int v8; // eax@5
+  unsigned int v9; // eax@7
+  SoundData *result; // eax@9
+  int v11; // esi@15
+  int v12; // eax@15
+  char *v13; // ecx@16
+  int v14; // eax@19
+  std::string v15; // [sp-18h] [bp-34h]@12
+  const char *v16; // [sp-8h] [bp-24h]@12
+  int v17; // [sp-4h] [bp-20h]@12
+  char v18; // [sp+Ch] [bp-10h]@12
+  int v19; // [sp+10h] [bp-Ch]@5
+  DWORD NumberOfBytesRead; // [sp+14h] [bp-8h]@8
+  const char *pSoundName_; // [sp+18h] [bp-4h]@1
+
+  pSoundName_ = pSoundName;
+  v3 = pOutBuff;
+  v4 = 0;
+  for (uint i = 0; i < 3000; ++i)
+    if (pSounds[i].uID == uID)
+      return pSounds[i].pSoundData;
+
+  FindSound_BinSearch(0, pAudioPlayer->uNumSoundHeaders, pSoundName_);
+  if ( uFindSound_BinSearch_ResultID == -1 )
+    goto LABEL_22;
+  v6 = &pAudioPlayer->pSoundHeaders[uFindSound_BinSearch_ResultID];
+  pDecompressedSize = &v6->uDecompressedSize;
+  v8 = v6->uDecompressedSize;
+  v19 = v6->uDecompressedSize;
+  if ( v3 == (SoundData *)-1 )
+    v3 = (SoundData *)pAllocator->AllocNamedChunk(0, v8 + 4, pSoundName_);
+  SetFilePointer(pAudioPlayer->hAudioSnd, v6->uFileOffset, 0, 0);
+  v9 = *pDecompressedSize;
+  if ( (signed int)v6->uCompressedSize >= (signed int)*pDecompressedSize )
+  {
+    v6->uCompressedSize = v9;
+    if ( v9 )
+    {
+      ReadFile(pAudioPlayer->hAudioSnd, (char *)v3 + 4, v9, &NumberOfBytesRead, 0);
+    }
+    else
+    {
+      MessageBoxW(nullptr, L"Can't load sound file!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Sound.cpp:448", 0);
+    }
+  }
+  else
+  {
+    uID = (unsigned int)malloc(v6->uCompressedSize);
+    ReadFile(pAudioPlayer->hAudioSnd, (LPVOID)uID, v6->uCompressedSize, &NumberOfBytesRead, 0);
+    zlib::MemUnzip((char *)v3 + 4, &v6->uDecompressedSize, (const void *)uID, v6->uCompressedSize);
+    free((void *)uID);
+  }
+  if ( v3 )
+  {
+    v11 = v19;
+    v12 = 0;
+    *(int *)v3 = v19;
+    uLastLoadedSoundID = 0;
+    if ( pSounds[0].pSoundData )
+    {
+      v13 = (char *)&pSounds[0].pSoundData;
+      do
+      {
+        v13 += 128;
+        ++v12;
+      }
+      while ( *(int *)v13 );
+      uLastLoadedSoundID = v12;
+    }
+    v16 = pSounds[v12].field_4;
+    strcpy((char *)v16, pSoundName_);
+    v14 = uLastLoadedSoundID++ << 7;
+    pSoundList->uTotalLoadedSoundSize += v11;
+    pSounds[uLastLoadedSoundID].pSoundData = v3;
+    result = v3;
+  }
+  else
+  {
+LABEL_22:
+    result = 0;
+  }
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AudioPlayer.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,320 @@
+#pragma once
+#include "OSAPI.h"
+
+
+
+
+
+
+
+#pragma pack(push, 1)
+struct _PROVIDER {char unk_0;};
+struct _SAMPLE   {char unk_0;};
+//struct _STREAM   {char unk_0;};
+struct _REDBOOK  {char unk_0;};
+struct _DIG_DRIVER {char unk_0;};
+struct _SEQUENCE {char unk_0;};
+#pragma pack(pop)
+
+
+
+/*   22 */
+#pragma pack(push, 1)
+struct AudioPlayer_3DSample
+{
+  inline AudioPlayer_3DSample()
+  {
+    hSample = 0;
+    field_4 = 0;
+    field_8 = 0;
+    field_C = 0;
+  }
+
+  void *hSample;
+  int field_4;
+  int field_8;
+  int field_C;
+};
+#pragma pack(pop)
+
+
+
+
+/*   26 */
+#pragma pack(push, 1)
+struct SoundHeader
+{
+  char pSoundName[40];
+  unsigned int uFileOffset;
+  unsigned int uCompressedSize;
+  unsigned int uDecompressedSize;
+};
+#pragma pack(pop)
+
+/*   27 */
+#pragma pack(push, 1)
+struct MixerChannel
+{
+  inline MixerChannel():
+    hSample(nullptr), dword_000004(0), uSourceTrackIdx(0), uSourceTrackID(0)
+  {}
+
+  _SAMPLE *hSample;
+  int dword_000004;
+  unsigned int uSourceTrackIdx;
+  unsigned int uSourceTrackID;
+};
+#pragma pack(pop)
+
+
+
+
+
+/*  308 */
+enum SoundID
+{
+  SOUND_0 = 0,
+  SOUND_EnteringAHouse = 0x6,
+  SOUND_8 = 0x8,
+  SOUND_27 = 0x1B,
+  SOUND_Arcomage_LoseResources = 0x78,
+  SOUND_Arcomage_AddResources = 0x79,
+  SOUND_Arcomage_TowerWallDamage = 0x7A,
+  SOUND_Arcomage_DrawCard = 0x7B,
+  SOUND_Arcomage_ProductionDamage = 0x7D,
+  SOUND_Arcomage_ProductionUpgrade = 0x7E,
+  SOUND_Arcomage_127 = 0x7F,
+  SOUND_Arcomage_128 = 0x80,
+  SOUND_Arcomage_TowerUpgrade = 0x81,
+  SOUND_Arcomage_WallUpgrade = 0x84,
+  SOUND_GoldReceived = 0xC8,
+  SOUND_PlayerCantCastSpell = 0xD1,
+  SOUND_Bell = 0xD9,
+  SOUND_20001 = 0x4E21,
+};
+
+
+enum MusicID: unsigned __int32
+{
+  MUSIC_Credits = 15
+};
+
+/*   20 */
+#pragma pack(push, 1)
+struct AudioPlayer
+{
+  //----- (004A9669) --------------------------------------------------------
+  AudioPlayer():
+    bPlayerReady(false), b3DSoundInitialized(false),
+    hAILRedbook(nullptr), hStream(nullptr)
+  {
+	/*AudioPlayer_3DSample *v0; //ecx@1
+	signed int v1; //edi@1
+
+	v0 = p3DSamples;
+	v1 = 32;
+	do
+	{
+		v0->field_4 = 0;
+		v0->field_8 = 0;
+		v0->field_C = 0;
+		v0->hSample = 0;
+		++v0;
+		--v1;
+	}
+	while (v1);*/
+    uMixerChannels = 16;
+    field_2D0_time_left = 256;
+    uNumRedbookTracks = 0;
+    uCurrentMusicTrackLength = 0;
+    field_2D4 = 0;
+    s3DSoundVolume = 127;
+  }
+
+  void SetMusicVolume(int vol);
+  void SetMasterVolume(unsigned int uVolume);
+  void _4AA258(int a2);
+  void PlaySound(SoundID eSoundID, signed int a3, unsigned int uNumRepeats, signed int a5, signed int a6, int a7, unsigned int uVolume, int sPlaybackRate);
+  void _4AAFCF();
+  void StopChannels(int uStartChannel, int uEndChannel);
+  void LoadAudioSnd();
+  void Initialize(HWND hWnd);
+  LSTATUS CheckA3DSupport(char a2);
+  void Release();
+  void _4ABE55(MixerChannel *pChannel);
+  void _4ABF23(AudioPlayer_3DSample *a2);
+  void SetEAXPreferences();
+  void SetMapEAX();
+  int _4AC0A2();
+  void PlayMusicTrack(enum MusicID eTrack);
+  void __cdecl MessWithChannels();
+
+
+  unsigned int bEAXSupported;
+  unsigned int b3DSoundInitialized;
+  int s3DSoundVolume;
+  struct _PROVIDER *h3DSoundProvider;
+  int uNum3DSamples;
+  struct AudioPlayer_3DSample p3DSamples[32];
+  int field_214;
+  int sRedbookVolume;
+  char p3DSoundProvider[128];
+  unsigned int bPlayerReady;
+  HWND hWindow;
+  struct _REDBOOK *hAILRedbook;
+  struct _DIG_DRIVER *hDigDriver;
+  int dword_0002AC;
+  struct _SEQUENCE *hSequence;
+  int dword_0002B4;
+  struct SoundHeader *pSoundHeaders;
+  HANDLE hAudioSnd;
+  unsigned int uNumSoundHeaders;
+  unsigned int uMasterVolume;
+  int dword_0002C8;
+  int dword_0002CC;
+  int field_2D0_time_left;
+  int field_2D4;
+  unsigned int uCurrentMusicTrackLength;
+  unsigned int uNumRedbookTracks;
+  unsigned int uCurrentMusicTrackStartMS;
+  unsigned int uCurrentMusicTrackEndMS;
+  struct MixerChannel pMixerChannels[16];
+  int uMixerChannels;
+  int field_3EC;
+  char pDeviceNames[16][128];
+  int array_000BF0[16];
+  int array_000C30[16];
+  unsigned int uNumDevices;
+  struct _STREAM *hStream;
+  char field_C78[8];
+  int cGameCDDriveLetter;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+/*  325 */
+enum SOUND_DESC_TYPE : __int32
+{
+  SOUND_DESC_LEVEL = 0x0,
+  SOUND_DESC_SYSTEM = 0x1,
+  SOUND_DESC_SWAP = 0x2,
+  SOUND_DESC_3 = 0x3,
+  SOUND_DESC_LOCK = 0x4,
+};
+
+/*  326 */
+enum SOUND_DESC_FLAGS
+{
+  SOUND_DESC_LOCKED = 0x1,
+  SOUND_DESC_3D = 0x2,
+};
+
+
+
+
+#pragma pack(push, 1)
+struct SoundData
+{
+  unsigned int uDataSize;
+  char         pData[1];
+};
+
+struct SoundDesc
+{
+  char pSoundName[32];
+  unsigned int uSoundID;
+  SOUND_DESC_TYPE eType;
+  int uFlags;
+  SoundData *pSoundData[17];
+  void *p3DSound;
+  int bDecompressed;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct SoundList
+{
+  inline SoundList():
+    uNumSounds(0), pSounds(nullptr), uTotalLoadedSoundSize(0)
+  {}
+
+  void Initialize();
+  __int16 LoadSound(int a1, unsigned int a3);
+  int LoadSound(unsigned int a2, LPVOID lpBuffer, int uBufferSizeLeft, int *pOutSoundSize, int a6);
+  SoundDesc *Release();
+  void _4A9D79(int a2);
+  void _4A9DCD(unsigned int uSoundID, char a3);
+  void ToFile();
+  void *FromFile(void *pSerialized);
+  int FromFileTxt(const char *Args);
+
+  unsigned int uNumSounds;
+  SoundDesc *pSounds;
+  unsigned int uTotalLoadedSoundSize;
+};
+#pragma pack(pop)
+
+
+
+
+
+/*  241 */
+#pragma pack(push, 1)
+struct Sound
+{
+  unsigned int uID;
+  char field_4[120];
+  SoundData *pSoundData;
+};
+#pragma pack(pop)
+
+
+
+
+extern int Aureal3D_SplashScreen;
+extern int Aureal3D_SplashAudio;
+extern int uFindSound_BinSearch_ResultID; // weak
+extern int uLastLoadedSoundID; // weak
+extern int sLastTrackLengthMS;
+extern Sound pSounds[3000];
+extern AudioPlayer *pAudioPlayer;
+extern SoundList *pSoundList;
+
+extern unsigned __int8 uSoundVolumeMultiplier;
+extern unsigned __int8 uVoicesVolumeMultiplier;
+extern unsigned __int8 uMusicVolimeMultiplier;
+extern int bWalkSound; // idb
+
+extern float pSoundVolumeLevels[10]; // idb
+
+
+
+
+
+
+
+
+/*  379 */
+#pragma pack(push, 1)
+struct stru339_spell_sound
+{
+  int _494836(int uSoundID, int a6);
+
+  char pSounds[44744];
+  int field_AEC8[45];
+  int field_AF7C[18];
+  int field_AFC4;
+  int pSoundsSizes[2];
+  int pSoundsOffsets[2];
+};
+#pragma pack(pop)
+extern stru339_spell_sound stru_A750F8[4];
+extern stru339_spell_sound stru_AA1058[4];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Autonotes.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,26 @@
+#pragma once
+
+
+
+
+/*  351 */
+enum AUTONOTE_TYPE : __int32
+{
+  AUTONOTE_POTION_RECEPIE = 0x0,
+  AUTONOTE_STAT_HINT = 0x1,
+  AUTONOTE_OBELISK = 0x2,
+  AUTONOTE_SEER = 0x3,
+  AUTONOTE_MISC = 0x4,
+  AUTONOTE_TEACHER = 0x5,
+};
+
+/*  350 */
+#pragma pack(push, 1)
+struct Autonote
+{
+  const char *pText;
+  enum AUTONOTE_TYPE eType;
+};
+#pragma pack(pop)
+extern Autonote stru_723720[195]; // weak
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Awards.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,12 @@
+#pragma once
+
+
+/*  353 */
+#pragma pack(push, 1)
+struct Award
+{
+  const char *pText;
+  unsigned int uSort;
+};
+#pragma pack(pop)
+extern Award pAwards[104];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BSPModel.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,30 @@
+#include "BSPModel.h"
+#include "Allocator.h"
+
+
+
+//----- (00478389) --------------------------------------------------------
+void BSPModel::Release()
+{
+  BSPModel *v1; // esi@1
+  void *v2; // ST00_4@1
+  void *v3; // ST00_4@1
+  void *v4; // ST00_4@1
+
+  v1 = this;
+  pAllocator->FreeChunk(*(void **)&this->pModelName[4]);
+  v2 = *(void **)&v1->pModelName[16];
+  *(int *)&v1->pModelName[4] = 0;
+  pAllocator->FreeChunk(v2);
+  v3 = *(void **)&v1->pModelName[20];
+  *(int *)&v1->pModelName[16] = 0;
+  pAllocator->FreeChunk(v3);
+  v4 = *(void **)&v1->pModelName[28];
+  *(int *)&v1->pModelName[20] = 0;
+  pAllocator->FreeChunk(v4);
+  *(int *)&v1->pModelName[28] = 0;
+  *(int *)&v1->pModelName[24] = 0;
+  *(int *)&v1->pModelName[8] = 0;
+  *(int *)&v1->pModelName[0] = 0;
+  *(short *)&v1->pModelName[12] = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BSPModel.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,62 @@
+#pragma once
+#include "VectorTypes.h"
+
+
+#pragma pack(push, 1)
+struct BSPNode
+{
+  __int16 uFront;
+  __int16 uBack;
+  __int16 uCoplanarOffset;
+  __int16 uCoplanarSize;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct BSPVertexBuffer
+{
+  int uNumVertices;
+  Vec3_int_ *pVertices;
+};
+#pragma pack(pop)
+
+
+
+/*   80 */
+#pragma pack(push, 1)
+struct BSPModel
+{
+  void Release();
+
+
+  char pModelName[32];
+  char pModelName2[32];
+  int field_40;
+  struct BSPVertexBuffer pVertices;
+  unsigned int uNumFaces;
+  unsigned int uNumConvexFaces;
+  struct ODMFace *pFaces;
+  unsigned __int16 *pFacesOrdering;
+  unsigned int uNumNodes;
+  struct BSPNode *pNodes;
+  unsigned int uNumDecorations;
+  int sCenterX;
+  int sCenterY;
+  Vec3_int_ vPosition;
+  int sMinX;
+  int sMinY;
+  int sMinZ;
+  int sMaxX;
+  int sMaxY;
+  int sMaxZ;
+  int sSomeOtherMinX;
+  int sSomeOtherMinY;
+  int sSomeOtherMinZ;
+  int sSomeOtherMaxX;
+  int sSomeOtherMaxY;
+  int sSomeOtherMaxZ;
+  Vec3_int_ vBoundingCenter;
+  int sBoundingRadius;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bink_Smacker.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,328 @@
+#include "Bink_Smacker.h"
+
+
+
+
+
+
+
+int (__stdcall *smackw32_SmackSoundUseMSS)(HDIGDRIVER) = 0;
+unsigned int (__stdcall *smackw32_SmackUseMMX)(unsigned int) = 0;
+HSMACK (__stdcall *smackw32_SmackOpen)(HANDLE, unsigned int, unsigned int) = 0;
+HSMACKBLIT (__stdcall *smackw32_SmackBlitOpen)(unsigned int) = 0;
+void (__stdcall *smackw32_SmackToBuffer)(HSMACK, unsigned int, unsigned int, unsigned int, unsigned int, void *, unsigned int) = 0;
+void (__stdcall *smackw32_SmackBlitSetPalette)(HSMACKBLIT, void *, unsigned int) = 0;
+unsigned int (__stdcall *smackw32_SmackDoFrame)(HSMACK) = 0;
+unsigned int (__stdcall *smackw32_SmackToBufferRect)(HSMACK, unsigned int) = 0;
+void (__stdcall *smackw32_SmackBlit)(HSMACKBLIT, void *, unsigned int, unsigned int, unsigned int, void *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) = 0;
+void (__stdcall *smackw32_SmackNextFrame)(HSMACK) = 0;
+unsigned int (__stdcall *smackw32_SmackWait)(HSMACK) = 0;
+unsigned int (__stdcall *smackw32_SmackSoundOnOff)(HSMACK, unsigned int) = 0;
+void (__stdcall *smackw32_SmackClose)(HSMACK) = 0;
+void (__stdcall *smackw32_SmackBufferClose)(HSMACKBUF) = 0;
+void (__stdcall *smackw32_SmackBlitClose)(HSMACKBLIT) = 0;
+int  (__stdcall *smackw32_SmackBlitClear)(HSMACKBLIT, unsigned short *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, int) = 0;
+int  (__stdcall *smackw32_SmackGoto)(_SMACK *, long) = 0;
+void SMACKW32_DLL_Initialize()
+{
+ HMODULE pDll = LoadLibraryW(L"SmackW32.dll");
+
+ smackw32_SmackSoundUseMSS = (int (__stdcall *)(HDIGDRIVER))GetProcAddress(pDll, "_SmackSoundUseMSS@4");
+ smackw32_SmackUseMMX = (unsigned int (__stdcall *)(unsigned int))GetProcAddress(pDll, "_SmackUseMMX@4");
+ smackw32_SmackOpen = (HSMACK (__stdcall *)(HANDLE, unsigned int, unsigned int))GetProcAddress(pDll, "_SmackOpen@12");
+ smackw32_SmackBlitOpen = (HSMACKBLIT (__stdcall *)(unsigned int))GetProcAddress(pDll, "_SmackBlitOpen@4");
+ smackw32_SmackToBuffer = (void (__stdcall *)(HSMACK, unsigned int, unsigned int, unsigned int, unsigned int, void *, unsigned int))GetProcAddress(pDll, "_SmackToBuffer@28");
+ smackw32_SmackBlitSetPalette = (void (__stdcall *)(HSMACKBLIT, void *, unsigned int))GetProcAddress(pDll, "_SmackBlitSetPalette@12");
+ smackw32_SmackDoFrame = (unsigned int (__stdcall *)(HSMACK))GetProcAddress(pDll, "_SmackDoFrame@4");
+ smackw32_SmackToBufferRect = (unsigned int (__stdcall *)(HSMACK, unsigned int))GetProcAddress(pDll, "_SmackToBufferRect@8");
+ smackw32_SmackBlit = (void (__stdcall *)(HSMACKBLIT, void *, unsigned int, unsigned int, unsigned int, void *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int))GetProcAddress(pDll, "_SmackBlit@44");
+ smackw32_SmackNextFrame = (void (__stdcall *)(HSMACK))GetProcAddress(pDll, "_SmackNextFrame@4");
+ smackw32_SmackWait = (unsigned int (__stdcall *)(HSMACK))GetProcAddress(pDll, "_SmackWait@4");
+ smackw32_SmackSoundOnOff = (unsigned int (__stdcall *)(HSMACK, unsigned int))GetProcAddress(pDll, "_SmackSoundOnOff@8");
+ smackw32_SmackClose = (void (__stdcall *)(HSMACK))GetProcAddress(pDll, "_SmackClose@4");
+ smackw32_SmackBufferClose = (void (__stdcall *)(HSMACKBUF))GetProcAddress(pDll, "_SmackBufferClose@4");
+ smackw32_SmackBlitClose = (void (__stdcall *)(HSMACKBLIT))GetProcAddress(pDll, "_SmackBlitClose@4");
+ smackw32_SmackBlitClear = (int (__stdcall *)(HSMACKBLIT, unsigned short *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, int))GetProcAddress(pDll, "_SmackBlitClear@32");
+ smackw32_SmackGoto = (int  (__stdcall *)(_SMACK *, long))GetProcAddress(pDll, "_SmackGoto@8");
+}
+
+
+
+
+
+
+void __stdcall SmackBlitClose(HSMACKBLIT hBlit)
+{
+ (smackw32_SmackBlitClose)(hBlit);
+}
+
+void __stdcall SmackBufferClose(HSMACKBUF hBuf)
+{
+ (smackw32_SmackBufferClose)(hBuf);
+}
+
+void __stdcall SmackClose(HSMACK hSmack)
+{
+ (smackw32_SmackClose)(hSmack);
+}
+
+unsigned int __stdcall SmackSoundOnOff(HSMACK hSmack, unsigned int bOn)
+{
+ return (smackw32_SmackSoundOnOff)(hSmack, bOn);
+}
+
+unsigned int __stdcall SmackWait(HSMACK hSmack)
+{
+ return (smackw32_SmackWait)(hSmack);
+}
+
+void __stdcall SmackNextFrame(HSMACK hSmack)
+{
+ (smackw32_SmackNextFrame)(hSmack);
+}
+
+void __stdcall SmackBlit(HSMACKBLIT hBlit, void *pDest, unsigned int uDestPitch, unsigned int uDestX, unsigned int uDestY, void *pSrc, unsigned int uSrcPitch, unsigned int uSrcX, unsigned int uSrcY, unsigned int uSrcZ, unsigned int uSrcW)
+{
+ (smackw32_SmackBlit)(hBlit, pDest, uDestPitch, uDestX, uDestY, pSrc, uSrcPitch, uSrcX, uSrcY, uSrcZ, uSrcW);
+}
+
+unsigned int __stdcall SmackToBufferRect(HSMACK hSmack, unsigned int uSmackSurface)
+{
+ return (smackw32_SmackToBufferRect)(hSmack, uSmackSurface);
+}
+
+unsigned int __stdcall SmackDoFrame(HSMACK hSmack)
+{
+ return (smackw32_SmackDoFrame)(hSmack);
+}
+
+void __stdcall SmackBlitSetPalette(HSMACKBLIT hBlit, void *pPalette, unsigned int uPalType)
+{
+ (smackw32_SmackBlitSetPalette)(hBlit, pPalette, uPalType);
+}
+
+int __stdcall SmackSoundUseMSS(HDIGDRIVER hDrv)
+{
+ return (smackw32_SmackSoundUseMSS)(hDrv);
+}
+
+unsigned int __stdcall SmackUseMMX(unsigned int flag)
+{
+ return (smackw32_SmackUseMMX)(flag);
+}
+
+HSMACK __stdcall SmackOpen(HANDLE hSourceFile, unsigned int uFlags, unsigned int uExtraBuffers)
+{
+ return (smackw32_SmackOpen)(hSourceFile, uFlags, uExtraBuffers);
+}
+
+HSMACKBLIT __stdcall SmackBlitOpen(unsigned int uSurfaceFormat)
+{
+ return (smackw32_SmackBlitOpen)(uSurfaceFormat);
+}
+
+void __stdcall SmackToBuffer(HSMACK hSmack, unsigned int uX, unsigned int uY, unsigned int uPitch, unsigned int uHeight, void *pBuffer, unsigned int uFlags)
+{
+ (smackw32_SmackToBuffer)(hSmack, uX, uY, uPitch, uHeight, pBuffer, uFlags);
+}
+
+int __stdcall SmackBlitClear(HSMACKBLIT a1, unsigned short *pFrameData, unsigned int uTargetSurfacePitch, unsigned int uOutX, unsigned int uOutY, unsigned int uOutZ, unsigned int uOutW, int a8)
+{
+ return (smackw32_SmackBlitClear)(a1, pFrameData, uTargetSurfacePitch, uOutX, uOutY, uOutZ, uOutW, a8);
+}
+
+int __stdcall SmackGoto(_SMACK *a1, long a2)
+{
+ return (smackw32_SmackGoto)(a1, a2);
+}
+
+
+int __stdcall SmackBufferOpen(HWND a1, long a2, long a3, long a4, long a5, long a6)
+{
+ __asm int 3
+ return 0;
+}
+
+int __fastcall SmackVolumePan(long a1, long a2, _SMACK *a3, long a4, long a5, long a6)
+{
+ __asm int 3
+ return 0;
+}
+
+
+// sub_4D83D0: using guessed type int __stdcall SmackBufferNewPalette(_DWORD, _DWORD, _DWORD);
+int __stdcall SmackBufferNewPalette(long a1, long a2, long a3)
+{
+ __asm int 3
+ return 0;
+}
+
+// sub_4D83D4: using guessed type int __stdcall SmackColorRemapWithTrans(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD);
+int __stdcall SmackColorRemapWithTrans(long a1, long a2, long a3, long a4, long a5)
+{
+ __asm int 3
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+int (__stdcall *binkw32_BinkDDSurfaceType)(struct IDirectDrawSurface *) = 0;
+int (__stdcall *binkw32_BinkSetSoundSystem)(void *, HDIGDRIVER) = 0;
+int (__stdcall *binkw32_BinkOpenMiles)(int) = 0;
+HBINK (__stdcall *binkw32_BinkOpen)(void *, unsigned int) = 0;
+int (__stdcall *binkw32_BinkWait)(HBINK) = 0;
+int (__stdcall *binkw32_BinkDoFrame)(HBINK) = 0;
+int (__stdcall *binkw32_BinkNextFrame)(HBINK) = 0;
+int (__stdcall *binkw32_BinkGetRects)(HBINK, unsigned int) = 0;
+int (__stdcall *binkw32_BinkCopyToBuffer)(HBINK, void *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) = 0;
+int (__stdcall *binkw32_BinkPause)(HBINK, int) = 0;
+int (__stdcall *binkw32_BinkClose)(HBINK) = 0;
+int (__stdcall *binkw32_BinkBufferSetOffset)(void *, int, int) = 0;
+int (__stdcall *binkw32_BinkBufferSetScale)(void *, unsigned int, unsigned int) = 0;
+void BINKW32_DLL_Initialize()
+{
+ HMODULE pDll = LoadLibraryW(L"BinkW32.dll");
+
+ binkw32_BinkDDSurfaceType = (int (__stdcall *)(struct IDirectDrawSurface *))GetProcAddress(pDll, "_BinkDDSurfaceType@4");
+ binkw32_BinkSetSoundSystem = (int (__stdcall *)(void *, HDIGDRIVER))GetProcAddress(pDll, "_BinkSetSoundSystem@8");
+ binkw32_BinkOpenMiles = (int (__stdcall *)(int))GetProcAddress(pDll, "_BinkOpenMiles@4");
+ binkw32_BinkOpen = (HBINK (__stdcall *)(void *, unsigned int))GetProcAddress(pDll, "_BinkOpen@8");
+ binkw32_BinkWait = (int (__stdcall *)(HBINK))GetProcAddress(pDll, "_BinkWait@4");
+ binkw32_BinkBufferSetOffset = (int (__stdcall *)(void *, int, int))GetProcAddress(pDll, "_BinkBufferSetOffset@12");
+ binkw32_BinkBufferSetScale = (int (__stdcall *)(void *, unsigned int, unsigned int))GetProcAddress(pDll, "_BinkBufferSetScale@12");
+ binkw32_BinkDoFrame = (int (__stdcall *)(HBINK))GetProcAddress(pDll, "_BinkDoFrame@4");
+ binkw32_BinkNextFrame = (int (__stdcall *)(HBINK))GetProcAddress(pDll, "_BinkNextFrame@4");
+ binkw32_BinkGetRects = (int (__stdcall *)(HBINK, unsigned int))GetProcAddress(pDll, "_BinkGetRects@8");
+ binkw32_BinkCopyToBuffer = (int (__stdcall *)(HBINK, void *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int))GetProcAddress(pDll, "_BinkCopyToBuffer@28");
+ binkw32_BinkPause = (int (__stdcall *)(HBINK, int))GetProcAddress(pDll, "_BinkPause@8");
+ binkw32_BinkClose = (int (__stdcall *)(HBINK))GetProcAddress(pDll, "_BinkClose@4");
+}
+
+
+int __stdcall BinkPause(HBINK hBink, int bPause)
+{
+ return (binkw32_BinkPause)(hBink, bPause);
+}
+
+int __stdcall BinkClose(HBINK hBink)
+{
+ return (binkw32_BinkClose)(hBink);
+}
+
+int __stdcall BinkGetRects(HBINK hBink, unsigned int uFlags)
+{
+ return (binkw32_BinkGetRects)(hBink, uFlags);
+}
+
+int __stdcall BinkCopyToBuffer(HBINK hBink, void *pBuffer, unsigned int lPitch, unsigned int uNumScanlines, unsigned int uX, unsigned int uY, unsigned int uFlags)
+{
+ return (binkw32_BinkCopyToBuffer)(hBink, pBuffer, lPitch, uNumScanlines, uX, uY, uFlags);
+}
+
+int __stdcall BinkDoFrame(HBINK hBink)
+{
+ return (binkw32_BinkDoFrame)(hBink);
+}
+
+int __stdcall BinkNextFrame(HBINK hBink)
+{
+ return (binkw32_BinkNextFrame)(hBink);
+}
+
+HBINK __stdcall BinkOpen(void *hFileHandle, unsigned int uFlags)
+{
+ return (binkw32_BinkOpen)(hFileHandle, uFlags);
+}
+
+int __stdcall BinkOpenMiles(int unk)
+{
+ return (binkw32_BinkOpenMiles)(unk);
+}
+
+int __stdcall BinkWait(HBINK hBink)
+{
+ return (binkw32_BinkWait)(hBink);
+}
+
+
+
+int __stdcall BinkBufferSetOffset(void *pStruct, int b, int c)
+{
+ return (binkw32_BinkBufferSetOffset)(pStruct, b, c);
+}
+
+int __stdcall BinkBufferSetScale(void *pStruct, unsigned int uWidth, unsigned int uHeight)
+{
+ return (binkw32_BinkBufferSetScale)(pStruct, uWidth, uHeight);
+}
+
+int __stdcall BinkDDSurfaceType(struct IDirectDrawSurface *pDDS)
+{
+ return (binkw32_BinkDDSurfaceType)(pDDS);
+}
+
+int __stdcall BinkSetSoundSystem(void *pSoundSystem, HDIGDRIVER hDrv)
+{
+ return (binkw32_BinkSetSoundSystem)(pSoundSystem, hDrv);
+}
+
+
+
+
+
+
+int __stdcall BinkGoto(_BINK *a1, long a2, long a3)
+{
+ __asm int 3
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bink_Smacker.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,193 @@
+#pragma once
+#include "AIL.h"
+
+
+
+
+void BINKW32_DLL_Initialize();
+
+
+int __stdcall BinkDDSurfaceType(struct IDirectDrawSurface *);
+int __stdcall BinkSetSoundSystem(void *pSoundSystem, HDIGDRIVER hDrv);
+int __stdcall BinkOpenMiles(int);
+HBINK __stdcall BinkOpen(void *hFileHandle, unsigned int uFlags);
+int __stdcall BinkWait(HBINK);
+int __stdcall BinkDoFrame(HBINK);
+int __stdcall BinkNextFrame(HBINK);
+int __stdcall BinkGetRects(HBINK hBink, unsigned int uFlags);
+int __stdcall BinkCopyToBuffer(HBINK hBink, void *pBuffer, unsigned int lPitch, unsigned int uNumLines, unsigned int uX, unsigned int uY, unsigned int uFlags);
+int __stdcall BinkPause(HBINK, int bPause);
+int __stdcall BinkClose(HBINK);
+int __stdcall BinkGoto(HBINK, long a2, long a3);
+
+int __stdcall BinkBufferSetOffset(void *, int, int);
+int __stdcall BinkBufferSetScale(void *, unsigned int uWidth, unsigned int uHeight);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void SMACKW32_DLL_Initialize();
+
+struct _SMACK
+{
+  unsigned int Version;           // SMK2 only right now
+  unsigned int Width;             // Width (1 based, 640 for example)
+  unsigned int Height;            // Height (1 based, 480 for example)
+  unsigned int Frames;            // Number of frames (1 based, 100 = 100 frames)
+  unsigned int MSPerFrame;        // Frame Rate
+  unsigned int SmackerType;       // bit 0 set=ring frame
+  unsigned int LargestInTrack[7]; // Largest single size for each track
+  unsigned int tablesize;         // Size of the init tables
+  unsigned int codesize;          // Compression info   
+  unsigned int absize;            // ditto
+  unsigned int detailsize;        // ditto
+  unsigned int typesize;          // ditto
+  unsigned int TrackType[7];      // high byte=0x80-Comp,0x40-PCM data,0x20-16 bit,0x10-stereo
+  unsigned int extra;             // extra value (should be zero)
+  unsigned int NewPalette;        // set to one if the palette changed
+  unsigned char Palette[772];      // palette data
+  unsigned int PalType;           // type of palette
+  unsigned int FrameNum;          // 0374 Frame Number to be displayed
+  unsigned int FrameSize;         // The current frame's size in bytes
+  unsigned int SndSize;           // The current frame sound tracks' size in bytes
+  int LastRectx;                  // 0380 Rect set in from SmackToBufferRect (X coord)
+  int LastRecty;                  // Rect set in from SmackToBufferRect (Y coord)
+  int LastRectw;                  // Rect set in from SmackToBufferRect (Width)
+  int LastRecth;                  // 038C Rect set in from SmackToBufferRect (Height)
+  unsigned int OpenFlags;         // flags used on open
+  unsigned int LeftOfs;           // Left Offset used in SmackTo
+  unsigned int TopOfs;            // Top Offset used in SmackTo
+  unsigned int LargestFrameSize;  // Largest frame size
+  unsigned int Highest1SecRate;   // Highest 1 sec data rate
+  unsigned int Highest1SecFrame;  // Highest 1 sec data rate starting frame
+  unsigned int ReadError;         // Set to non-zero if a read error has ocurred
+  unsigned int addr32;            // translated address for 16 bit interface
+};
+
+
+
+struct _SMACKBLIT
+{
+  unsigned int    Flags;
+  unsigned char  *Palette;
+  unsigned int    PalType;
+  unsigned short *SmoothTable;
+  unsigned short *Conv8to16Table;
+  unsigned int    whichmode;
+  unsigned int    palindex;
+  unsigned int    t16index;
+  unsigned int    smoothindex;
+  unsigned int    smoothtype;
+  unsigned int    firstpalette;
+};
+
+struct _SMACKBUF
+{
+        unsigned int Reversed;             // 1 if the buffer is upside down
+        unsigned int SurfaceType;          // SMACKSURFACExxxx defines
+        unsigned int BlitType;             // SMACKxxxxBLIT defines
+        unsigned int FullScreen;           // 1 if full-screen
+        unsigned int Width;
+        unsigned int Height;
+        unsigned int Pitch;
+        unsigned int Zoomed;
+        unsigned int ZWidth;
+        unsigned int ZHeight;
+        unsigned int DispColors;           // colors on the screen
+        unsigned int MaxPalColors;         // total possible colors in palette (usually 256)
+        unsigned int PalColorsInUse;       // Used colors in palette (usually 236)
+        unsigned int StartPalColor;        // first usable color index (usually 10)
+        unsigned int EndPalColor;          // last usable color index (usually 246)
+        RGBQUAD Palette[256];
+        unsigned int PalType;
+        unsigned int forceredraw;  // force a complete redraw on next blit (for >8bit)
+        unsigned int didapalette;  // force an invalidate on the next palette change
+
+        void * Buffer;
+        void * DIBRestore;
+        unsigned int OurBitmap;
+        unsigned int OrigBitmap;
+        unsigned int OurPalette;
+        unsigned int WinGDC;
+        unsigned int FullFocused;
+        unsigned int ParentHwnd;
+        unsigned int OldParWndProc;
+        unsigned int OldDispWndProc;
+        unsigned int DispHwnd;
+        unsigned int WinGBufHandle;
+        void * lpDD;
+        void * lpDDSP;
+        unsigned int DDSurfaceType;
+        struct _SMACKBLIT DDblit;
+        int ddSoftwarecur;
+        int didaddblit;
+        int lastwasdd;
+        RECT ddscreen;
+        int manyblits;
+        int * blitrects;
+        int * rectsptr;
+        int maxrects;
+        int numrects;
+        HDC lastdc;
+};
+
+
+
+int __stdcall SmackSoundUseMSS(HDIGDRIVER hDrv);
+unsigned int __stdcall SmackUseMMX(unsigned int flag);
+HSMACK __stdcall SmackOpen(HANDLE hSourceFile, unsigned int uFlags, unsigned int uExtraBuffers);
+HSMACKBLIT __stdcall SmackBlitOpen(unsigned int uSurfaceFormat);
+void __stdcall SmackToBuffer(HSMACK, unsigned int uX, unsigned int uY, unsigned int uPitch, unsigned int uHeight, void *pBuffer, unsigned int uFlags);
+void __stdcall SmackBlitSetPalette(HSMACKBLIT hBlit, void *pPalette, unsigned int uPalType);
+unsigned int __stdcall SmackDoFrame(HSMACK);
+unsigned int __stdcall SmackToBufferRect(HSMACK, unsigned int uSmackSurface);
+void __stdcall SmackBlit(HSMACKBLIT, void *pDest, unsigned int uDestPitch, unsigned int uDestX, unsigned int uDestY, void *pSrc, unsigned int uSrcPitch, unsigned int uSrcX, unsigned int uSrcY, unsigned int uSrcZ, unsigned int uSrcW);
+void __stdcall SmackNextFrame(HSMACK);
+unsigned int __stdcall SmackWait(HSMACK);
+unsigned int __stdcall SmackSoundOnOff(HSMACK, unsigned int bOn);
+void __stdcall SmackClose(HSMACK);
+void __stdcall SmackBufferClose(HSMACKBUF);
+void __stdcall SmackBlitClose(HSMACKBLIT);
+int __stdcall SmackBlitClear(HSMACKBLIT a1, unsigned short *pFrameData, unsigned int uTargetSurfacePitch, unsigned int uOutX, unsigned int uOutY, unsigned int uOutZ, unsigned int uOutW, int a8);
+
+
+
+
+
+int __stdcall SmackBufferOpen(HWND a1, long a2, long a3, long a4, long a5, long a6);
+int __fastcall SmackVolumePan(long a1, long a2, _SMACK *a3, long a4, long a5, long a6);
+
+int __stdcall SmackGoto(_SMACK *a1, long a2);
+
+// sub_4D83D0: using guessed type int __stdcall SmackBufferNewPalette(_DWORD, _DWORD, _DWORD);
+int __stdcall SmackBufferNewPalette(long a1, long a2, long a3);
+
+// sub_4D83D4: using guessed type int __stdcall SmackColorRemapWithTrans(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD);
+int __stdcall SmackColorRemapWithTrans(long a1, long a2, long a3, long a4, long a5);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CShow.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,114 @@
+#pragma once
+#include "VideoPlayer.h"
+#include "Mouse.h"
+
+
+
+/*  302 */
+enum MovieType
+{
+  MOVIE_Invalid = 0x0,
+  MOVIE_3DOLogo = 0x1,
+  MOVIE_NWCLogo = 0x2,
+  MOVIE_JVC = 0x3,
+  MOVIE_Emerald = 0x4,
+  MOVIE_Intro = 0x5,
+  MOVIE_Death = 0x6,
+  MOVIE_Outro = 0x7,
+};
+
+
+#pragma pack(push, 1)
+struct CShow
+{
+  //----- (004A9507) --------------------------------------------------------
+  CShow() {}
+
+  //----- (004A9510) --------------------------------------------------------
+  virtual ~CShow() {}
+
+  
+  //----- (004A952D) --------------------------------------------------------
+  void CShow::PlayMovie(MovieType eVideo, bool bShowMouseAfterPlayback)
+  {
+  int v3; // edx@5
+  const char *Name; // ecx@5
+  //std::string v5; // [sp-18h] [bp-24h]@4
+  //signed int v6; // [sp-Ch] [bp-18h]@10
+  int ScreenSizeFlag; // [sp-8h] [bp-14h]@4
+  int v8; // [sp-4h] [bp-10h]@4
+  //char v9; // [sp+0h] [bp-Ch]@14
+  //char v10; // [sp+4h] [bp-8h]@4
+  //int a3; // [sp+Bh] [bp-1h]@14
+
+  if (pAsyncMouse)
+    pAsyncMouse->Suspend();
+  switch ( eVideo )
+  {
+    case MOVIE_Invalid:
+      MessageBoxW(nullptr, L"No movie", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Show.cpp:40", 0);
+      break;
+    case MOVIE_3DOLogo:
+      v8 = 1;
+      ScreenSizeFlag = 0;
+      v3 = 0;
+      Name = "3dologo";
+      VideoPlayer::MovieLoop(Name, v3, ScreenSizeFlag, v8);
+      break;
+    case MOVIE_NWCLogo:
+      v8 = 1;
+      ScreenSizeFlag = 1;
+      v3 = 0;
+      Name = "new world logo";
+      VideoPlayer::MovieLoop(Name, v3, ScreenSizeFlag, v8);
+      break;
+    case MOVIE_JVC:
+      v8 = 1;
+      ScreenSizeFlag = 1;
+      v3 = 0;
+      Name = "jvc";
+      VideoPlayer::MovieLoop(Name, v3, ScreenSizeFlag, v8);
+      break;
+    case MOVIE_Intro:
+      v8 = 1;
+      ScreenSizeFlag = 1;
+      v3 = 0;
+      Name = "Intro";
+      VideoPlayer::MovieLoop(Name, v3, ScreenSizeFlag, v8);
+      break;
+    case MOVIE_Emerald:
+      v8 = 1;
+      ScreenSizeFlag = 1;
+      v3 = 0;
+      Name = "Intro Post";
+      VideoPlayer::MovieLoop(Name, v3, ScreenSizeFlag, v8);
+      break;
+    case MOVIE_Death:
+      v8 = 1;
+      ScreenSizeFlag = 1;
+      v3 = 2;
+      Name = "losegame";
+      VideoPlayer::MovieLoop(Name, v3, ScreenSizeFlag, v8);
+      break;
+    case MOVIE_Outro:
+      v8 = 1;
+      ScreenSizeFlag = 1;
+      v3 = 20;
+      Name = "end_seq1";
+      VideoPlayer::MovieLoop(Name, v3, ScreenSizeFlag, v8);
+      break;
+    default:
+      MessageBoxW(nullptr, L"Invalid movie requested in CShow::Run()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Show.cpp:72", 0);
+      break;
+  }
+  if ( bShowMouseAfterPlayback )
+  {
+    if (pAsyncMouse)
+      pAsyncMouse->Resume();
+  }
+}
+
+
+  void (__thiscall ***vdestructor_ptr)(CShow *, bool);
+};
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Chest.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,120 @@
+#include <stdio.h>
+
+#include "Chest.h"
+#include "FrameTableInc.h"
+#include "Allocator.h"
+
+#include "mm7_data.h"
+
+
+
+
+size_t uNumChests; // idb
+struct ChestList *pChestList;
+Chest pChests[20];
+
+
+
+
+
+//----- (00458B03) --------------------------------------------------------
+void ChestList::ToFile()
+{
+  ChestList *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  v1 = this;
+  v2 = fopen("data\\dchest.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dchest.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pChests, 0x24u, v1->uNumChests, v3);
+  fclose(v3);
+}
+
+
+//----- (00458B4F) --------------------------------------------------------
+void ChestList::FromFile(void *pSerialized)
+{
+  uNumChests = *(int *)pSerialized;
+  pChests = (ChestDesc *)pAllocator->AllocNamedChunk(pChests, 36 * uNumChests, "Chest Descrip");
+  memcpy(pChests, (char *)pSerialized + 4, 36 * uNumChests);
+}
+
+
+//----- (00458B9C) --------------------------------------------------------
+int ChestList::FromFileTxt(const char *Args)
+{
+  ChestList *v2; // ebx@1
+  __int32 v3; // edi@1
+  FILE *v4; // eax@1
+  unsigned int v5; // esi@3
+  const void *v6; // ST18_4@9
+  void *v7; // eax@9
+  FILE *v8; // ST0C_4@11
+  char *i; // eax@11
+  char v10; // al@14
+  const char *v11; // ST14_4@14
+  char v12; // al@14
+  const char *v13; // ST10_4@14
+  char Buf; // [sp+8h] [bp-2F0h]@3
+  FrameTableTxtLine v16; // [sp+1FCh] [bp-FCh]@4
+  FrameTableTxtLine v17; // [sp+278h] [bp-80h]@4
+  FILE *File; // [sp+2F4h] [bp-4h]@1
+  unsigned int Argsa; // [sp+300h] [bp+8h]@3
+
+  v2 = this;
+  pAllocator->FreeChunk(this->pChests);
+  v3 = 0;
+  v2->pChests = 0;
+  v2->uNumChests = 0;
+  v4 = fopen(Args, "r");
+  File = v4;
+  if ( !v4 )
+    Abortf("ChestDescriptionList::load - Unable to open file: %s.");
+  v5 = 0;
+  Argsa = 0;
+  if ( fgets(&Buf, 490, v4) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v17, texture_frame_table_txt_parser(&Buf, &v16), sizeof(v17));
+      if ( v17.field_0 && *v17.pProperties[0] != 47 )
+        ++Argsa;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v5 = Argsa;
+    v3 = 0;
+  }
+  v6 = v2->pChests;
+  v2->uNumChests = v5;
+  v7 = pAllocator->AllocNamedChunk(v6, 36 * v5, "Chest Descrip");
+  v2->pChests = (ChestDesc *)v7;
+  if ( v7 == (void *)v3 )
+    Abortf("ChestDescriptionList::load - Out of Memory!");
+  memset(v7, v3, 36 * v2->uNumChests);
+  v8 = File;
+  v2->uNumChests = v3;
+  fseek(v8, v3, v3);
+  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v17, texture_frame_table_txt_parser(&Buf, &v16), sizeof(v17));
+    if ( v17.field_0 && *v17.pProperties[0] != 47 )
+    {
+      strcpy(v2->pChests[v2->uNumChests].pName, v17.pProperties[0]);
+      v10 = atoi(v17.pProperties[1]);
+      v11 = v17.pProperties[2];
+      v2->pChests[v2->uNumChests].uWidth = v10;
+      v12 = atoi(v11);
+      v13 = v17.pProperties[3];
+      v2->pChests[v2->uNumChests].uHeight = v12;
+      v2->pChests[v2->uNumChests++].uTextureID = atoi(v13);
+    }
+  }
+  fclose(File);
+  return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Chest.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,73 @@
+#pragma once
+#include "Items.h"
+
+
+
+
+/*  348 */
+enum CHEST_FLAGS
+{
+  CHEST_TRAPPED = 0x1,
+  CHEST_ITEMS_PLACED = 0x2,
+  CHEST_OPENED = 0x4,
+};
+
+
+
+#pragma pack(push, 1)
+struct ChestDesc
+{
+  char pName[32];
+  char uWidth;
+  char uHeight;
+  __int16 uTextureID;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct ChestList
+{
+  inline ChestList():  //----- (00458438)
+    uNumChests(0), pChests(nullptr)
+  {}
+
+  void ToFile();
+  void FromFile(void *pSerialized);
+  int FromFileTxt(const char *Args);
+
+
+  unsigned int uNumChests;
+  struct ChestDesc *pChests;
+};
+#pragma pack(pop)
+
+
+
+/*   65 */
+#pragma pack(push, 1)
+struct Chest
+{
+  static int CanPlaceItemAt(signed int a1, int a2, unsigned int uChestID);
+  static int _41FF64(unsigned int uChestID);
+  static int _41FFA2(int a1, ItemGen *a2, unsigned int uChestID);
+  static unsigned int PlaceItemAt(unsigned int a1, unsigned int uItemIdx, unsigned int uChestID);
+  static char *_420284(unsigned int uChestID);
+  static bool Open(unsigned int uChestID);
+  static void DrawChestUI(unsigned int uChestID);
+  static void ToggleFlag(unsigned int uChestID, unsigned __int16 uFlag, unsigned int bToggle);
+
+  unsigned __int16 uChestBitmapID;
+  unsigned __int16 uFlags;
+  struct ItemGen mm7__vector_pItems[140];
+  __int16 pInventoryIndices[140];
+};
+#pragma pack(pop)
+
+
+
+
+extern size_t uNumChests; // idb
+extern struct ChestList *pChestList;
+extern Chest pChests[20];
\ No newline at end of file
Binary file Debug/AIL.obj has changed
Binary file Debug/Actor.obj has changed
Binary file Debug/Allocator.obj has changed
Binary file Debug/Arcomage.obj has changed
Binary file Debug/AudioPlayer.obj has changed
Binary file Debug/BSPModel.obj has changed
Binary file Debug/Bink_Smacker.obj has changed
Binary file Debug/CL.read.1.tlog has changed
Binary file Debug/CL.write.1.tlog has changed
Binary file Debug/Chest.obj has changed
Binary file Debug/DecalBuilder.obj has changed
Binary file Debug/Events.obj has changed
Binary file Debug/FrameTableInc.obj has changed
Binary file Debug/GUIButton.obj has changed
Binary file Debug/GUIFont.obj has changed
Binary file Debug/GUIProgressBar.obj has changed
Binary file Debug/GUIWindow.obj has changed
Binary file Debug/Game.obj has changed
Binary file Debug/GameUIs.obj has changed
Binary file Debug/GammaControl.obj has changed
Binary file Debug/Indoor.obj has changed
Binary file Debug/IndoorCamera.obj has changed
Binary file Debug/IndoorCameraD3D.obj has changed
Binary file Debug/Items.obj has changed
Binary file Debug/Keyboard.obj has changed
Binary file Debug/LOD.obj has changed
Binary file Debug/LayingItem.obj has changed
Binary file Debug/LightmapBuilder.obj has changed
Binary file Debug/LightsStack.obj has changed
Binary file Debug/Log.obj has changed
Binary file Debug/MM7.exe has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug/MM7.exe.embed.manifest	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+</assembly>
\ No newline at end of file
Binary file Debug/MM7.exe.embed.manifest.res has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug/MM7.exe.intermediate.manifest	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+</assembly>
Binary file Debug/MM7.ilk has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug/MM7.lastbuildstate	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2 @@
+#v4.0:v100
+Debug|Win32|D:\ÐœÐ¾Ñ Ð¿Ð°Ð¿ÐºÐ°\MM7 original\|
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug/MM7.log	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,23 @@
+ПоÑтроение начато 12.01.2013 9:43:01.
+     1>Проект "D:\ÐœÐ¾Ñ Ð¿Ð°Ð¿ÐºÐ°\MM7 original\MM7.vcxproj" в узле 2 (целевые объекты build).
+     1>InitializeBuildStatus:
+         Создание "Debug\MM7.unsuccessfulbuild", так как было задано "AlwaysCreate".
+       ClCompile:
+         Ð”Ð»Ñ Ð²Ñех выходных данных Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ðµ требуетÑÑ.
+         Ð”Ð»Ñ Ð²Ñех выходных данных Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ðµ требуетÑÑ.
+       ResourceCompile:
+         Ð”Ð»Ñ Ð²Ñех выходных данных Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ðµ требуетÑÑ.
+       ManifestResourceCompile:
+         Ð”Ð»Ñ Ð²Ñех выходных данных Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ðµ требуетÑÑ.
+       Link:
+         Ð”Ð»Ñ Ð²Ñех выходных данных Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ðµ требуетÑÑ.
+       Manifest:
+         Ð”Ð»Ñ Ð²Ñех выходных данных Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ðµ требуетÑÑ.
+       FinalizeBuildStatus:
+         Файл "Debug\MM7.unsuccessfulbuild" удалÑетÑÑ.
+         Обращение к "Debug\MM7.lastbuildstate".
+     1>ПоÑтроение проекта "D:\ÐœÐ¾Ñ Ð¿Ð°Ð¿ÐºÐ°\MM7 original\MM7.vcxproj" завершено (целевые объекты build).
+
+ПоÑтроение уÑпешно завершено.
+
+Затраченное времÑ: 00:00:00.12
Binary file Debug/MM7.pdb has changed
Binary file Debug/MM7_manifest.rc has changed
Binary file Debug/Might and Magic Trilogy.res has changed
Binary file Debug/Monsters.obj has changed
Binary file Debug/Mouse.obj has changed
Binary file Debug/OSAPI.obj has changed
Binary file Debug/Outdoor.obj has changed
Binary file Debug/Overlays.obj has changed
Binary file Debug/PaletteManager.obj has changed
Binary file Debug/ParticleEngine.obj has changed
Binary file Debug/Party.obj has changed
Binary file Debug/Player.obj has changed
Binary file Debug/RCa04864 has changed
Binary file Debug/Random.obj has changed
Binary file Debug/Render.obj has changed
Binary file Debug/SaveLoad.obj has changed
Binary file Debug/Spells.obj has changed
Binary file Debug/Sprites.obj has changed
Binary file Debug/Texture.obj has changed
Binary file Debug/TileFrameTable.obj has changed
Binary file Debug/Time.obj has changed
Binary file Debug/VideoPlayer.obj has changed
Binary file Debug/Vis.obj has changed
Binary file Debug/Weather.obj has changed
Binary file Debug/cl.command.1.tlog has changed
Binary file Debug/lib/zlib/adler32.obj has changed
Binary file Debug/lib/zlib/compress.obj has changed
Binary file Debug/lib/zlib/crc32.obj has changed
Binary file Debug/lib/zlib/deflate.obj has changed
Binary file Debug/lib/zlib/infblock.obj has changed
Binary file Debug/lib/zlib/infcodes.obj has changed
Binary file Debug/lib/zlib/inffast.obj has changed
Binary file Debug/lib/zlib/inflate.obj has changed
Binary file Debug/lib/zlib/inftrees.obj has changed
Binary file Debug/lib/zlib/infutil.obj has changed
Binary file Debug/lib/zlib/trees.obj has changed
Binary file Debug/lib/zlib/uncompr.obj has changed
Binary file Debug/lib/zlib/zutil.obj has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug/link-cvtres.read.1.tlog	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1 @@
+ÿþ
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug/link-cvtres.write.1.tlog	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1 @@
+ÿþ
\ No newline at end of file
Binary file Debug/link.command.1.tlog has changed
Binary file Debug/link.read.1.tlog has changed
Binary file Debug/link.write.1.tlog has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug/mm6text.cas	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,203 @@
+//Gender	I	R	D	V	T	P	X
+//Dubles names
+F	Ñåêèðà	Ñåêèðû	Ñåêèðå	Ñåêèðó	Ñåêèðîé	Ñåêèðå
+M	Äðîèä	Äðîèäà	Äðîèäó	Äðîèäà	Äðîèäîì	Äðîèäå
+M	Òàìëîê	Òàìëîêà	Òàìëîêó	Òàìëîêà	Òàìëîêîì	Òàìëîêå
+F	Øàïî÷êà	Øàïî÷êè	Øàïî÷êå	Øàïî÷êó	Øàïî÷êîé	Øàïî÷êå
+M	Áëàñòåð	Áëàñòåðà	Áëàñòåðó	Áëàñòåð	Áëàñòåðîì	Áëàñòåðå
+F	Ñòàëüíàÿ	Ñòàëüíîé	Ñòàëüíîé	Ñòàëüíóþ	Ñòàëüíîé	Ñòàëüíîé
+M	Öàðü	Öàðÿ	Öàðþ	Öàðÿ	Öàðåì	Öàðå
+F	Ýëåãàíòíàÿ	Ýëåãàíòíîé	Ýëåãàíòíîé	Ýëåãàíòíóþ	Ýëåãàíòíîé	Ýëåãàíòíîé
+M	Ïîñâÿù¸ííûé	Ïîñâÿù¸ííîãî	Ïîñâÿù¸ííîìó	Ïîñâÿù¸ííîãî	Ïîñâÿù¸ííûì	Ïîñâÿù¸ííîì
+M	Àíãåë	Àíãåëà	Àíãåëó	Àíãåëà	Àíãåëîì	Àíãåëå
+F	Ýëüôèéñêàÿ	Ýëüôèéñêîé	Ýëüôèéñêîé	Ýëüôèéñêóþ	Ýëüôèéñêîé	Ýëüôèéñêîé
+F	Ìîäíàÿ	Ìîäíîé	Ìîäíîé	Ìîäíóþ	Ìîäíîé	Ìîäíîé
+F	Áóòûëêà	Áóòûëêè	Áóòûëêå	Áóòûëêó	Áóòûëêîé	Áóòûëêå
+M	Ïëàâó÷èé ãëàç	Ïëàâó÷åãî ãëàçà	Ïëàâó÷åìó ãëàçó	Ïëàâó÷èé ãëàç	Ïëàâó÷èì ãëàçîì	Ïëàâó÷åì ãëàçå
+F	Ðóêà	Ðóêè	Ðóêå	Ðóêó	Ðóêîé	Ðóêå
+F	Ïðàâàÿ	Ïðàâîé	Ïðàâîé	Ïðàâóþ	Ïðàâîé	Ïðàâîé
+F	Ëåâàÿ	Ëåâîé	Ëåâîé	Ëåâóþ	Ëåâîé	Ëåâîé
+F	Àëåáàðäà	Àëåáàðäû	Àëåáàðäå	Àëåáàðäó	Àëåáàðäîé	Àëåáàðäå
+M	Âîäíûé	Âîäíîãî	Âîäíîìó	Âîäíîãî	Âîäíûì	Âîäíîì
+F	Òðóáà	Òðóáû	Òðóáå	Òðóáó	Òðóáîé	Òðóáå
+F	Ñàáëÿ	Ñàáëè	Ñàáëå	Ñàáëþ	Ñàáëåé	Ñàáëå
+F	Ãîëîâà	Ãîëîâû	Ãîëîâå	Ãîëîâó	Ãîëîâîé	Ãîëîâå
+F	Óòÿæåëåííàÿ	Óòÿæåëåííîé	Óòÿæåëåííîé	Óòÿæåëåííóþ	Óòÿæåëåííîé	Óòÿæåëåííîé
+F	Ñèåðòàëüíàÿ	Ñèåðòàëüíîé	Ñèåðòàëüíîé	Ñèåðòàëüíóþ	Ñèåðòàëüíîé	Ñèåðòàëüíîé
+M	Ñèíèé	Ñèíåãî	Ñèíèìó	Ñèíèé	Ñèíèì	Ñèíåì
+F	Ïîëîâàÿ	Ïîëîâîé	Ïîëîâîé	Ïîëîâóþ	Ïîëîâîé	Ïîëîâîé
+M	Ìàëûé ùèò	Ìàëîãî ùèòà	Ìàëîìó ùèòó	Ìàëûé ùèò	Ìàëûì ùèòîì	Ìàëîì ùèòå
+M	Áðîíçîâûé àìóëåò	Áðîíçîâîãî àìóëåòà	Áðîíçîâîìó àìóëåòó	Áðîíçîâûé àìóëåò	Áðîíçîâûì àìóëåòîì	Áðîíçîâîì àìóëåòå
+M	ñëèçåíü	ñëèçíÿ	ñëèçíþ	ñëèçíÿ	ñëèçíåì	ñëèçíå
+M	Îãíåííûé	Îãíåííîãî	Îãíåííîìó	Îãíåííîãî	Îãíåííûì	Îãíåííîì
+M	Ðîãàòûé	Ðîãàòîãî	Ðîãàòîìó	Ðîãàòûé	Ðîãàòûì	Ðîãàòîì
+F	Æåëåçíàÿ	Æåëåçíîé	Æåëåçíîé	Æåëåçíóþ	Æåëåçíîé	Æåëåçíîé
+F	Ôèëüòîâàÿ	Ôèëüòîâîé	Ôèëüòîâîé	Ôèëüòîâóþ	Ôèëüòîâîé	Ôèëüòîâîé
+F	Êåðãàðîâàÿ	Êåðãàðîâîé	Êåðãàðîâîé	Êåðãàðîâóþ	Êåðãàðîâîé	Êåðãàðîâîé
+M	cëèçåíü	cëèçíÿ	cëèçíþ	cëèçíÿ	ñëèçíåì	ñëèçíå
+F	Êîæàíàÿ	Êîæàíîé	Êîæàíîé	Êîæàíóþ	Êîæàíîé	Êîæàíîé
+F	Øèïîâàòàÿ	Øèïîâàòîé	Øèïîâàòîé	Øèïîâàòóþ	Øèïîâàòîé	Øèïîâàòîé
+F	Ñòàëüòîâàÿ	Ñòàëüòîâîé	Ñòàëüòîâîé	Ñòàëüòîâóþ	Ñòàëüòîâîé	Ñòàëüòîâîé
+F	Ýðóäèíîâàÿ	Ýðóäèíîâîé	Ýðóäèíîâîé	Ýðóäèíîâóþ	Ýðóäèíîâîé	Ýðóäèíîâîé
+F	Ðóäà	Ðóäû	Ðóäå	Ðóäó	Ðóäîé	Ðóäå
+F	Ðóõ	Ðóõ	Ðóõ	Ðóõ	Ðóõ	Ðóõ
+F	Àëèñà	Àëèñû	Àëèñå	Àëèñó	Àëèñîé	Àëèñå
+F	Äåéÿ	Äåéè	Äåéå	Äåéþ	Äåéåé	Äåéå
+M	Äüÿâîë	Äüÿâîëà	Äüÿâîëó	Äüÿâîëà	Äüÿâîëîì	Äüÿâîëå
+M	Ïðèçðàê	Ïðèçðàêà	Ïðèçðàêó	Ïðèçðàêà	Ïðèçðàêîì	Ïðèçðàêå
+M	Áîëîòíûé	Áîëîòíîãî	Áîëîòíîìó	Áîëîòíîãî	Áîëîòíûì	Áîëîòíîì
+M	Ãîðíûé	Ãîðíîãî	Ãîðíîìó	Ãîðíîãî	Ãîðíûì	Ãîðíîì
+M	Ýëèòíûé ñòðåëîê	Ýëèòíîãî ñòðåëêà	Ýëèòíîìó ñòðåëêó	Ýëèòíîãî ñòðåëêà	Ýëèòíûì ñòðåëêîì	Ýëèòíîì ñòðåëêå
+M	Ïîñâÿùåííûé	Ïîñâÿùåííîãî	Ïîñâÿùåííîìó	Ïîñâÿùåííîãî	Ïîñâÿùåííûì	Ïîñâÿùåííîì
+F	Ýðàôèéñêàÿ êàíàëèçàöèÿ	Ýðàôèéñêîé êàíàëèçàöèè	Ýðàôèéñêîé êàíàëèçàöèè	Ýðàôèéñêóþ êàíàëèçàöèþ	Ýðàôèéñêîé êàíàëèçàöèåé	Ýðàôèéñêîé êàíàëèçàöèè
+M	Ãíèþùèé òðóï	Ãíèþùåãî òðóïà	Ãíèþùåìó òðóïó	Ãíèþùèé òðóï	Ãíèþùèì òðóïîì	Ãíèþùåì òðóïå
+M	×åðòîã	×åðòîãà	×åðòîãó	×åðòîã	×åðòîãîì	×åðòîãå
+M	Ìåðòâåö	Ìåðòâåöà	Ìåðòâåöó	Ìåðòâåöà	Ìåðòâåöîì	Ìåðòâåöå
+M	Óïûðü	Óïûðÿ	Óïûðþ	Óïûðÿ	Óïûðåì	Óïûðå
+M	Ñòðàæ	Ñòðàæà	Ñòðàæó	Ñòðàæà	Ñòðàæîì	Ñòðàæå
+M	Âóðäàëàê	Âóðäàëàêà	Âóðäàëàêó	Âóðäàëàêà	Âóðäàëàêîì	Âóðäàëàêå
+M	Àðõàíãåë	Àðõàíãåëà	Àðõàíãåëó	Àðõàíãåëà	Àðõàíãåëîì	Àðõàíãåëå
+M	Ãëàç äüÿâîëà	Ãëàçà äüÿâîëà	Ãëàçó äüÿâîëà	Ãëàç äüÿâîëà	Ãëàçîì äüÿâîëà	Ãëàçå äüÿâîëà
+M	Ðîáåðò Ìóäðûé	Ðîáåðòà Ìóäðîãî	Ðîáåðòó Ìóäðîìó	Ðîáåðòà Ìóäðîãî	Ðîáåðòîì Ìóäðûì	Ðîáåðòå Ìóäðîì
+M	Ëàáèðèíò	Ëàáèðèíòà	Ëàáèðèíòó	Ëàáèðèíò	Ëàáèðèíòîì	Ëàáèðèíòå
+M	Âåëèêèé Õðàì	Âåëèêîãî Õðàìà	Âåëèêîìóèé Õðàìó	Âåëèêèé Õðàì	Âåëèêèì Õðàìîì	Âåëèêîì Õðàìå
+M	Ìåäíûé	Ìåäíîãî	Ìåäíîìó	Ìåäíîãî	Ìåäíûì	Ìåäíîì
+M	Ïðèçðàê	Ïðèçðàêà	Ïðèçðàêó	Ïðèçðàêà	Ïðèçðàêîì	Ïðèçðàêå
+M	Êóðãàí	Êóðãàíà	Êóðãàíó	Êóðãàí	Êóðãàíîì	Êóðãàíå
+M	Ñêåëåò	Ñêåëåòà	Ñêåëåòó	Ñêåëåòà	Ñêåëåòîì	Ñêåëåòå
+F	Àøåí Òåìïåð	Àøåí Òåìïåð	Àøåí Òåìïåð	Àøåí Òåìïåð	Àøåí Òåìïåð	Àøåí Òåìïåð
+M	Ëè÷	Ëè÷à	Ëè÷ó	Ëè÷à	Ëè÷åì	Ëè÷å
+M	Ãëèíÿíûé ýëåìåíòàë	Ãëèíÿíîãî ýëåìåíòàëà	Ãëèíÿíîìó ýëåìåíòàëó	Ãëèíÿíîãî ýëåìåíòàëà	Ãëèíÿíûì ýëåìåíòàëîì	Ãëèíÿíîì ýëåìåíòàëå
+F	Íîðìàëüíàÿ ãîëîâà	Íîðìàëüíîé ãîëîâû	Íîðìàëüíîé ãîëîâå	Íîðìàëüíóþ ãîëîâó	Íîðìàëüíîé ãîëîâîé	Íîðìàëüíîé ãîëîâå
+M	Áîëüøîé Ùèò	Áîëüøîãî Ùèòà	Áîëüøîìó Ùèòó	Áîëüøîé Ùèò	Áîëüøèì Ùèòîì	Áîëüøîì Ùèòå
+F	Ýðàôèÿ	Ýðàôèè	Ýðàôèè	Ýðàôèþ	Ýðàôèåé	Ýðàôèè
+M	Èçóìðóäíûé ñëèçåíü	Èçóìðóäíîãî ñëèçíÿ	Èçóìðóäíîìó ñëèçíþ	Èçóìðóäíîãî ñëèçíÿ	Èçóìðóäíûì ñëèçíåì	Èçóìðóäíîì ñëèçíå
+F	Ìýðè Äæî	Ìýðè Äæî	Ìýðè Äæî	Ìýðè Äæî	Ìýðè Äæî	Ìýðè Äæî
+F	Ëè Ýíí	Ëè Ýíí	Ëè Ýíí	Ëè Ýíí	Ëè Ýíí	Ëè Ýíí
+M	Êðàñíûé äðàêîí	Êðàñíîãî äðàêîíà	Êðàñíîìó äðàêîíó	Êðàñíîãî äðàêîíà	Êðàñíûì äðàêîíîì	Êðàñíîì äðàêîíå
+M	Çåëåíûé äðàêîí	Çåëåíîãî äðàêîíà	Çåëåíîìó äðàêîíó	Çåëåíîãî äðàêîíà	Çåëåíûì äðàêîíîì	Çåëåíîì äðàêîíå
+F	Ëåâàÿ íîãà	Ëåâîé íîãè	Ëåâîé íîãå	Ëåâóþ íîãó	Ëåâîé íîãîé	Ëåâîé íîãå
+F	Ïðàâàÿ íîãà	Ïðàâîé íîãè	Ïðàâîé íîãå	Ïðàâóþ íîãó	Ïðàâîé íîãîé	Ïðàâîé íîãå
+M	Áåñïëîòíûé äóõ	Áåñïëîòíîãî äóõà	Áåñïëîòíîìó äóõó	Áåñïëîòíîãî äóõà	Áåñïëîòíûì äóõîì	Áåñïëîòíîì äóõå
+F	Âðàòà	Âðàòà	Âðàòà	@Âðàòà	Âðàòà	Âðàòà
+U	Ìîëîäîå ÷óäèùå	Ìîëîäîãî ÷óäèùà	Ìîëîäîìó ÷óäèùó	Ìîëîäîå ÷óäèùå	Ìîëîäûì ÷óäèùåì	Ìîëîäîì ÷óäèùå
+F	Ïðèëèâíûå ïåùåðû	Ïðèëèâíûõ ïåùåð	Ïðèëèâíûì ïåùåðàì	Ïðèëèâíûå ïåùåðû	Ïðèëèâíûìè ïåùåðàìè	Ïðèëèâíûõ ïåùåðàõ
+F	Òóëàðåàíñêèå ïåùåðû	Òóëàðåàíñêèõ ïåùåð	Òóëàðåàíñêèì ïåùåðàì	Òóëàðåàíñêèå ïåùåðû	Òóëàðåàíñêèìè ïåùåðàìè	Òóëàðåàíñêèõ ïåùåðàõ
+M	Ñòåíû òóìàíà	Ñòåí òóìàíà	Ñòåíàì òóìàíà	Ñòåíû òóìàíà	Ñòåíàìè òóìàíà	Ñòåíàõ òóìàíà
+F	Êàìåííàÿ êîæà	Êàìåííîé êîæè	Êàìåííîé êîæå	Êàìåííóþ êîæó	Êàìåííîé êîæåé	Êàìåííîé êîæå
+M	Ðîé	Ðîÿ	Ðîþ	Ðîé	Ðîåì	Ðîå
+F	Ñåò Äàðêåíìîð	Ñåò Äàðêåíìîð	Ñåò Äàðêåíìîð	Ñåò Äàðêåíìîð	Ñåò Äàðêåíìîð	Ñåò Äàðêåíìîð
+M	Âåëèêèé Õðàì Ñîëíöà	Âåëèêîãî Õðàìà Ñîëíöà	Âåëèêîìó Õðàìó Ñîëíöà	Âåëèêèé Õðàì Ñîëíöà	Âåëèêèì Õðàìîì Ñîëíöà	Âåëèêîì Õðàìå Ñîëíöà
+M	Èíêóáàòîð	Èíêóáàòîðà	Èíêóáàòîðó	Èíêóáàòîð	Èíêóáàòîðîì	Èíêóáàòîðå
+M	Ëóê	Ëóêà	Ëóêó	Ëóê	Ëóêîì	Ëóêå
+M	Áîëüøîé ïàóê	Áîëüøîãî ïàóêà	Áîëüøîìó ïàóêó	Áîëüøîãî ïàóêà	Áîëüøèì ïàóêîì	Áîëüøîì ïàóêå
+M	Îãíåííûé ñòðåêîçàâð	Îãíåííîãî ñòðåêîçàâðà	Îãíåííîìó ñòðåêîçàâðó	Îãíåííîãî ñòðåêîçàâðà	Îãíåííûì ñòðåêîçàâðîì	Îãíåííîì ñòðåêîçàâðå
+M	Âîçäóøíûé ýëåìåíòàë	Âîçäóøíîãî ýëåìåíòàëà	Âîçäóøíîìó ýëåìåíòàëó	Âîçäóøíîãî ýëåìåíòàëà	Âîçäóøíûì ýëåìåíòàëîì	Âîçäóøíîì ýëåìåíòàëå
+//Male
+M	*òåíü	*òíÿ	*òíþ	*òíÿ	*òíåì	*òíå
+M	*èéñÿ	*åãîñÿ	*åìóñÿ	*èéñÿ	*èìñÿ	*åìñå
+M	*òíûé	*òíîãî	*òíîìó	*òíîãî	*òíûì	*òíîì
+M	*àâð	*àâðà	*àâðó	*àâðà	*àâðîì	*àâðå
+M	*ëûé	*ëîãî	*ëîìó	*ëîãî	*ëûì	*ëîì
+M	*âûé	*âîãî	*âîìó	*âîãî	*âûì	*âîì
+M	*íûé	*íîãî	*íîìó	*íûé	*íûì	*íîì
+M	*êèé	*êîãî	*êîìó	*êîãî	*êèì	*êîì
+M	*øèé	*øåãî	*øåìó	*øåãî	*øèì	*øåì
+M	*øîé	*øîãî	*øîìó	*øîé	*øèì	*øîì
+M	*÷èé	*÷åãî	*÷åìó	*÷åãî	*÷èì	*÷åì
+M	*ëîê	*ëêà	*ëêó	*ëêà	*ëêîì	*ëêå
+M	*íåö	*íöà	*íöó	*íöà	*íöåì	*íöå
+M	*íèé	*íåãî	*íåìó	*íåãî	*íèì	*íåì
+M	*òûé	*òîãî	*òîìó	*òîãî	*òûì	*òîì
+M	*áûé	*áîãî	*áîìó	*áîãî	*áûì	*áîì
+M	*ðü	*ðÿ	*ðþ	*ðü	*ðåì	*ðå
+M	*îð	*îðà	*îðó	*îðà	*îðîì	*îðå
+M	*èê	*èêà	*èêó	*èêà	*èêîì	*èêå
+M	*óê	*óêà	*óêó	*óêà	*óêîì	*óêå
+M	*îé	*îãî	*îìó	*îãî	*ûì	*îì
+M	*åö	*öà	*öó	*öà	*öîì	*öå
+M	*åð	*åðà	*åðó	*åðà	*åðîì	*åðå
+M	*åä	*åäà	*åäó	*åäà	*åäîì	*åäå
+M	*åò	*åòà	*åòó	*åò	*åòîì	*åòå
+M	*èä	*èäà	*èäó	*èäà	*èäîì	*èäå
+M	*õâ	*õâà	*õâó	*õâà	*õâîì	*õâå
+M	*èð	*èðà	*èðó	*èðà	*èðîì	*èðå
+M	*àë	*àëà	*àëó	*àëà	*àëîì	*àëå
+M	*åì	*åìà	*åìó	*åìà	*åìîì	*åìå
+M	*àç	*àçà	*àçó	*àç	*àçîì	*àçå
+M	*ðü	*ðÿ	*ðþ	*ðÿ	*ðåì	*ðå
+M	*îì	*îìà	*îìó	*îìà	*îìîì	*îìå
+M	*àæ	*àæà	*àæó	*àæà	*àæåì	*àæå
+M	*ã	*ãà	*ãó	*ãà	*ãîì	*ãå
+M	*í	*íà	*íó	*íà	*íîì	*íå
+M	*ë	*ëà	*ëó	*ë	*ëîì	*ëå
+M	*ä	*äà	*äó	*ä	*äîì	*äå
+M	*ð	*ðà	*ðó	*ð	*ðîì	*ðå
+M	*î	*î	*î	*î	*î	*î
+M	*è	*è	*è	*è	*è	*è
+M	*ò	*òà	*òó	*òà	*òîì	*òå
+M	*ô	*ôà	*ôó	*ôà	*ôîì	*ôå
+M	*ñ	*ñà	*ñó	*ñà	*ñîì	*ñå
+M	*é	*ÿ	*þ	*ÿ	*åì	*å
+M	*ì	*ìà	*ìó	*ì	*ìîì	*ìå
+M	*á	*áà	*áó	*á	*áîì	*áå
+M	*ö	*öà	*öó	*ö	*öîì	*öå
+M	*ü	*ÿ	*þ	*ÿ	*åì	*å
+M	*â	*âà	*âó	*â	*âîì	*âå
+M	*ê	*êà	*êó	*ê	*êîì	*êå
+M	*ÿ	*è	*å	*þ	*åé	*å
+M	*à	*è	*å	*ó	*îé	*å
+M	*å	*å	*å	*å	*å	*å
+M	*÷	*÷à	*÷ó	*÷	*÷åì	*÷å
+M	*æ	*æà	*æó	*æ	*æåì	*æå
+M	*ó	*ó	*ó	*ó	*ó	*ó
+M	*ï	*ïà	*ïó	*ï	*ïîì	*ïå
+M	*þ	*þ	*þ	*þ	*þ	*þ
+M	*ç	*çà	*çó	*çà	*çîì	*çå
+M	*ø	*øà	*øó	*øà	*øåì	*øå
+M	*õ	*õà	*õó	*õà	*õîì	*õå
+//Female
+F	*íàÿ	*íîé	*íîé	*íóþ	*íîé	*íîé
+F	*êàÿ	*êîé	*êîé	*êóþ	*êîé	*êîé
+F	*÷àÿ	*÷åé	*÷åé	*÷óþ	*÷åé	*÷åé
+F	*âàÿ	*âîé	*âîé	*âóþ	*âîé	*âîé
+F	*ûñà	*ûñû	*ûñå	*ûñó	*ûñîé	*ûñå
+F	*èÿ	*èè	*èè	*èþ	*èåé	*èè
+F	*ðû	*ð	*ðàì	*ðû	*ðàìè	*ðàõ
+F	*ñà	*ñ	*ñàì	*ñà	*ñàìè	*ñàõ
+F	*è	*è	*è	*è	*è	*è
+F	*à	*û	*å	*ó	*îé	*å
+F	*ñ	*ñ	*ñ	*ñ	*ñ	*ñ
+F	*í	*í	*í	*í	*í	*í
+F	*é	*é	*é	*é	*é	*é
+F	*ã	*ã	*ã	*ã	*ã	*ã
+F	*ü	*è	*è	*ü	*üþ	*è
+F	*ò	*ò	*ò	*ò	*ò	*ò
+F	*ó	*ó	*ó	*ó	*ó	*ó
+F	*ë	*ë	*ë	*ë	*ë	*ë
+F	*æ	*æ	*æ	*æ	*æ	*æ
+F	*ÿ	*è	*å	*þ	*åé	*å
+F	*ð	*ð	*ð	*ð	*ð	*ð
+F	*ì	*ì	*ì	*ì	*ì	*ì
+F	*ç	*ç	*ç	*ç	*ç	*ç
+//Middle
+U	*ïüå	*ïüÿ	*ïüþ	*ïüå	*ïüåì	*ïüå
+U	*íèå	*íèÿ	*íèþ	*íèå	*íèåì	*íèè
+U	*íåå	*íåãî	*íåìó	*íåå	*íèì	*íåì
+U	*äüå	*äüÿ	*äüþ	*äüå	*äüåì	*äüå
+U	*îè	*îåâ	*îÿì	*îè	*îÿìè	*îÿõ
+U	*òû	*ò	*òàì	*òû	*òàìè	*òàõ
+U	*ãè	*ã	*ãàì	*ãè	*ãàìè	*ãàõ
+U	*ïè	*ïèé	*ïÿì	*ïè	*ïÿìè	*ïÿõ
+U	*öî	*öà	*öó	*öî	*öîì	*öå
+U	*òî	*òà	*òó	*òî	*òîì	*òå
+U	*öå	*öà	*öó	*öå	*öåì	*öå
+U	*êî	*êà	*êó	*êî	*êîì	*êå
+U	*åå	*ãî	*ìó	*åå	*íèì	*íåì
+U	*îå	*ãî	*ìó	*îå	*íûì	*íîì
+U	*õè	*õîâ	*õàì	*õè	*õàìè	*õàõ
+U	*ñû	*ñîâ	*ñàì	*ñû	*ñàìè	*ñàõ
+U	*èå	*èÿ	*èþ	*èå	*èåì	*èå
+U	*î	*à	*ó	*î	*îì	*å
+U	*å	*à	*ó	*å	*åì	*å
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug/mm6text.non	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,747 @@
+//Male	Female	Middle
+Àðîí	Àëèñà	×óäèùå
+Ýéá	Ýëèñîí	Äðåâíåå
+Àâåëü	Àìàíäà	Ãëàçèùå
+Àäàì	Àìáåð	Ñîëíöå
+Àäðèàí	Àìåëèÿ	Ïðèâèäåíèå
+Àäðèàíèñ	Ýìè	Äåðåâî
+Àõìåä	Àíäðåà	Èìåíèå
+Àêèî	Àíæåëà	Ïîêîè
+Àêèðà	Ýíäæè	Êîïè
+Ýë	Àíèòà	Ëîãîâî
+Àëåí	Ýíí	Ìèíåðàëüíûå
+Àëåéí	Àííà	Çëàòûå
+Àëàí	Ýéïðèë	Çàìîðîæåííûå
+Àëüáåðò	Áàðáàðà	Ìàòåðèàëüíûå
+Àëåê	Áåàòðèñ	Ïðèðîäíûå
+Àëåõàíäðî	Áåêè	Õðàíèëèùå
+Àëåêñàíäð	Áåëèíäà 
+Àëüôðåä	Áåðíàäåòòà	Âîåííîå
+Àëüòîí	Áåðíèñ	ó÷èëèùå
+Àëüòðåä	Áåò	Ñâÿòèëèùå
+Ýëâèí	Áåòñè	Ìåëêîâîäüå
+Àìáðîçèé	Áåòòè
+Àìîñ	Áåâåðëè
+Àíäðåé	Áèëëèñ
+Ýíäè	Áîííè
+Àíòîíèé	Áðåíäà
+Àíòîí	Êàíäåéñ
+Àðáè	Êàðëè 
+Àðäà	Êàðìåí
+Àðäåí	Êýðîë
+Àðèýëü	Êýðîëàí
+Àðèñòåé	Êýðîëèí
+Àðèñòèäèñ	Êýððè
+Àðëåí	Êýéñ
+Àðëî	Êàñàíäðà
+Àðìàíä	Êàòåðèíà
+Ýðíè	Êàòè
+Àðíîëüä	Ñåêëèÿ 
+Àðòóð	Íåáåñà
+Àðèõ	×àíäðà
+Ýø	Øåðèë
+Ýøòîí	Êðèñòà
+Îñòèí	Êðèñòèíà
+Áàðåòò	Ñèíäè
+Áåðíè	Êëýð
+Áàðò	Êîííè
+Áîðåãàðä	Êîíñòàíöèÿ
+Áåí	Êîðà
+Áåíåäèêò	Êîðíåëèÿ
+Áåíèòî	Ñèíäèñ
+Áåíäæàìèí	Ñèíòèÿ
+Áåííåò	Äàíà
+Áåííè	Äàôíà
+Áåíóà	Äàðñè
+Áåðíó÷î	Äàðëèí
+Áåðíàðä	Äîíàéñ
+Áåðò	Äåàííà
+Áåðòðàí	Äåááè
+Áèëëè	Äåáîðà
+Áèøîï	Äàðà
+Áëåéí	Äåëîðèñ 
+Áëåéê	Äåíèñ
+Áëîíäî	Äèàíà
+Áî	Äàéàíà
+Áîá	Äîëîðåñ
+Áîááè	Äîìèíèêà
+Áîäî	Äîííà
+Áîðèñ	Äîðèí
+Áðýä	Äîðèñ
+Áðàäåí	Äîðîòè
+Áðýäôîðä	Ýäèò
+Áðýäëè	Ýäíà
+Áðåéí	Ýéëèí
+Áðýíäîí	Ýëåí
+Áðåíäîí	Ýëåîíîðà
+Áðåíò	Åëèçàâåòà
+Áðåò	Ýëëà
+Áðîíâèí	Ýëëåí
+Áðóê	Ýëñè
+Áðþñ	Ýëèññà
+Áðóíî	Ýììà
+Áðàéñ	Ýðèí
+Áàä	Ýòåëü
+Áóôîðä	Åâà
+Á¸ðòîí	Ýâåëèí
+Áàò÷	Ôåéò
+Áàéðîí	Ôåëèöèÿ
+Êààî	Ôëîðåíöèÿ
+Êýë	Ôëîññè
+Êàëåá	Ôðàí÷åñêà
+Êýëëî	Ãåéë
+Êàëüâèí	Ãåíèêêè
+Êýìåðîí	Ãåîðãèíà
+Êàðë	Äæåðàëüäèíà
+Êàðëî	Ãåðòðóäà
+Êàðëîñ	Äæèíà
+Êàðòåð	Äæèíæåð
+Êàðè	Äæèííè
+Êýñè	Ãëåíäà
+Ñåñèëü	Ãëîðèÿ
+Ñåäðèê	Ãðåòõåí
+Öåçàðü	Ãâåíäîëèí
+×àä	Ãâåíí
+×àðëüç	Õàðèåòòà
+×àðëè	Õèòåð
+×åñòåð	Õàéäè
+×åò	Õåëåí
+×èï	Õèëüäà
+Êðèñ	Õèòîìè
+Êðèñòîôåð	Õîëëè
+×àê	Èäà
+×àí	Èëåíà
+Êëàðåíñ	Èðåíà
+Êëàðê	Èðèíà
+Êëýé	Èðèñ
+Êëèôôîðä	Èðìà
+Êëàéä	Äæåêè
+Êîäè	Äæåéí
+Êîëèí	Æàíåòò
+Êîííîð	Æàíèñ
+Êîíðàä	Æàíèí
+Êîíñòàíòèí	Æàííà
+Êîðáåò	Æàñìèí
+Êîðä	Æåéí
+Êîðè	Äæèí
+Êîðíèëèé	Æàíåòòà
+Êîðèñî	Äæàíèñ
+Êðåéã	Æàíåòà
+Êèðóñ	Æåííà
+Äàë	Äæåíèôåð
+Äåéë	Äæåííè
+Äàëëàñ	Äæåññà
+Äàìèàí	Äæåññèêà
+Äýí	Äæîéñ
+Äàíèýëü	Äæîàí
+Äýííè	Äæîàíí
+Äàíòå	Äæîàííà
+Äàðîí	
+Äåéâ	Äæîéñèí
+Äýâè	Äæóäè
+Äàâèä	Þäèôü
+Äèí	Äæóäèñ
+Äåë	Äæóëè
+Äýíèñ	Äæóí
+Äåííè	Êýíäè
+Äåðåê	Êàðåí
+Äåñìîíä	Êýðè
+Äåâîí	Êàòëèí
+Äèòåð	Êýé
+Äîê	Êåéëèí
+Äîäðèäæ	Êåëëè
+Äîëüô	Êåðè
+Äîìèíèê	Êèì
+Äîí	Êèìáåðëè
+Äîíàëüä	Êðèñòåí
+Äóãëàñ	Êðèñòèñ
+Äðþ	Ëàíà
+Äþê	Ëàðà
+Äóíêàí	Ëàóðà
+Äàñòèí	Ëîðåí
+Äâåéí	Ëàóðè
+Äâàéò	Ëåà
+Äèëàí	Ëåàñà
+Ýðë	Ëè Ýíí
+Ýä	Ëèëà
+Ýääè	Ëåîðà
+Ýäãàð	Ëåñëè
+Ýäèñîí	Ëèëëè
+Ýäìîíä	Ëèâèÿ
+Èëüÿ	Ëèíäà
+Ýëèîò	Ëèçà
+Ýëòîí	Ëóèñà
+Ýìèëü	Ëîðà
+Ýììàíóèë	Ëîðåíà
+Ýììåò	Ëóèçà
+Ýíîê	Ëþñèëü
+Ýðèê	Ëèíí
+Ýðíåñò	Ìàäåëåíà
+Ýðíèí	Ìàìè
+Ýðîë	Ìýíäè
+Ýðâèí	Ìàðñèÿ
+Ýòàí	Ìàðñè
+Åâãåíèé	Ìàðãàðèòà
+Ýâàí	Ìàðæ
+Ôàáèàí	Ìàðèÿ
+Ôàðåëë	Ìàðèàíà
+Ôåëèêñ	Ìàðèàííà
+Ôåðäèíàíä	Ìàðèøàëü
+Ôëåò÷åð	Ìýðèëèí
+Ôëîéä	Ìàðèñà
+Ôîððåñò	Ìàðäæîðè
+Ôðàíöèñê	Ìàðëåí
+Ôðàíê	Ìàðíè
+Ôðàíêëèí	Ìàðøà
+Ôðàíö	Ìàðòà
+Ôðåä	Ìàðòèë
+Ôðåäåðèê	Ìýðè
+Ãåéá	Ìýðè Äæî
+Ãàáðèýëü	Ìàðèñ
+Äæåòàíî	Ìîðèíà
+Ãàðåò	Ìåéì
+Ãàðè	Ìåëàíè
+Äæåä	Ìåëèíäà
+Æîôðåé	Ìåëèññà
+Äæîðäæ	Ìåëîäè
+Äæåðàëüä	Ìèøåëü
+Äæåððè	Ìèíäè
+Æèëüáåð	Ìèííè
+Ãèëüìîð	Ìèðèàì
+Äæèíî	Ìîéðà
+Ãëåí	Ìîíèêà
+Ãîíçàëî	Ìþðåëü
+Ãîðäîí	Íàäèíà
+Ãðàõýì	Íýíñè
+Ãðàíò	Íýíñèñ
+Ãðåã	Íàîìè
+Ãðåãîðè	Íàòàëè
+Ãðåé	Íèêîëü
+Ãèëüåðìî	Íèêè
+Ãóñ	Íîðèíà
+Ãàé	Íîðìà
+Õýë	Îëèâèÿ
+Õýìïòîí	Ïåéäæ
+Õàí	Ïàì
+Õàíê	Ïàìåëà
+Ãàíñ	Ïýòòè
+Õàðäè	Ïàòðèñèÿ
+Õàðëàí	Ïàðòè
+Õàðëåé	Ïåã
+Õàðîëüä	Ïåããè
+Õàððèñîí	Ïåííè
+Ãàððè	Ôèëîìåíà
+Õàðâè	Ôèëëèñ
+Õàéäåí	Ïèêñè
+Õèò	Ðàøåëü
+Õèòåò	Ðåáåêêà
+Ãåêòîð	Ðåãèíà
+Ãåëüìóò	Ðåíè
+Ãåíðè	Ðåñàíäà
+Ãåðá	Ðåâè
+Ãåðáåðò	Ðîíäà
+Ãåðìàí	Ðèòà
+Ãåðö	Ðîáåðòà
+Õîê	Ðóáèíà
+Õîëäåí	Ðîøåëü
+Ãîìåð	Ðîìîíà
+Ãîðàöèé	Ðîçà
+Ãîâàðä	Ðîçàëè
+Õüþ	Ðîçàííà
+Õüþãî	Ðîóç
+Îõîòíèê	Ðîçìàðè
+ßí	Ðîçìàðèíà
+Èãíàñèî	Ðîçè
+Èãîðü	Ðóò
+Èêå	Ðóòè
+Àéð	Ñàáðèíà
+Èðâèí	Ñàäè
+Èðâèíã	Ñàëëè
+Èñààê	Ñýíäè
+Èñàî	Ñàíäðà
+Èçìàèë	Ñýíäèí
+Èâàí	Ñàðà
+Èâàð	Ñýðà
+Äæåê	Ñåëåíà
+ßêîá	Øýíîí
+Äæåéê	Øýðîí
+Äæåéìñ	Øåððè
+Äæåìè	Øîóíà
+ßðîä	Øåéëà
+Äæåéñîí	Øåëëè
+ßñïåð	Øåëëèñ
+Õàâüåð	Øýðè
+Äæåé	Øåððèí
+Æàí-Ïîëü	Øåéëàíè
+Æàí-Ïüåð	Ñèìîíà
+Äæåäàé	Ñòåéñè
+Èåðåìèÿ	Ñòåôàíè
+Äæåðîìè	Ñóàííà
+Äæåðîì	Ñüþçàí
+Äæåññ	Ñþçàííà
+Äæèì	Ñüþçè
+Äæîó	Ñâåòëàíà
+Äæîé	Òàìàðà
+Äæîýëü	Òàììè
+Äæîçåô	Òàíÿ
+Èîõàíí	Òàðà
+Äæîí	Òåðåçà
+Èîí	Òåððè
+Èîíà	Òýððè
+Äæîíàòàí	Òåðåñà
+Éîðäàí	Òèôôàíè
+Äæîøóà	Òèíà
+Äæóä	Òðåéñè
+Æóëü	Òðèñèÿ
+Äæàñòèí	Òðèíà
+Êàé	Âàëåðèÿ
+Êàðèí	Âàíåññà
+Êàðëîí	Âåðà
+Êèãàí	Âåðîíèêà
+Êåéò	Âèêè
+Êåë	Âèêòîðèÿ
+Êåâèí	Âèîëåò
+Êåí	Âèðãèíèÿ
+Êåííåò	Âèâüåí
+Êåðí	Âàíäà
+Êåâèíóñ	Âàíåòòà
+Õàíí	Âåíäè
+Êèðê	Âèëüìà
+Ëàíñ	Èîëàíäà
+Ëàððè	Èâîííà
+Ëàðñ	êðûñà	
+Ëàçàðü	ãðîìîâàÿ
+Ëè	îãíåííàÿ
+Ëåéô	Ãèãàíòñêàÿ
+Ëèëàíä	ïåùåðà
+Ëåî	øëÿïà	
+Ëèîí	ïåùåðû
+Ëåîíàðä	Ëåòó÷àÿ
+Ëåðîé	ìûøü
+Ëåñòåð	Àäñêàÿ
+Ëüþèñ	ëóíà
+Ëèàì	Êîðîëåâà
+Ëèíäñåé	Óíäèíà
+Ëàéîíåë	Ñèëüôèäà
+Ëëîéä	Êàìåííàÿ
+Ëîãàí	ãîðãóëüÿ
+Ëîí	Ìðàìîðíàÿ
+Ëîííè	Îáñèäèàíîâàÿ
+Ëîó	Ãàðïèÿ
+Ëóè	âåäüìà
+Ëóèñ	ãèäðà
+Ëîóâåëë	Âîçäóøíàÿ
+Ëàêè	Ìèíèêîðà
+Ëþäâèã	Ìàíòèêîðà
+Ëóèäæè	Ñêîðïèêîðà
+Ëþê	Ìåäóçà
+Ëþòåð	âëàäû÷èöà
+Ëèìàí	Ìåñòíàÿ
+Ëèíäåí	æèòåëüíèöà
+Ìàê	êîëü÷óãà
+Ìàêðî	Öèòàäåëü
+Ìàëêîëüì	Êîëîíèÿ
+Ìàíôðåä	ãîðà
+Ìàííè
+Ìàðê	ïòèöà
+Ìàð÷åëëî	àêóëà
+Ìàðêî	Äðàêîíîâàÿ
+Ìàðêóñ	×åðíàÿ
+Ìàðèî	âäîâà
+Ìàðèîí	Êîøêà
+Ìàðêîíè	Êóðèöà
+Ìàðëîí	Ñîáàêà
+Ìàðøàë	Øêîëà
+Ìàðòèí	Ñòîðîæåâàÿ
+Ìàðâèí	áàøíÿ
+Ìàòâåé	Âðàòà
+Ìàòò	Ëàáîðàòîðèÿ
+Ìàêñ
+Ìàêñâåëë	Òþðüìà
+Ìýë	êâàðòèðà
+Ìåëâèí	Ãèëüäèÿ
+Ìèê	Âåðõîâíàÿ
+Ìàéê	Âûñøàÿ
+Ìàéëç	Ýêñïåðòíàÿ
+Ìèò÷	Íà÷àëüíàÿ
+Ìîõàììåä	Øàõòåðñêàÿ
+Ìîíòå	Ðàòóøà
+Ìîðåë	Ñâÿùåííàÿ
+Ìîððèñ	çåìëÿ
+Ìîðòîí	Àðåíà
+Ìþððåé	Ïîäêîâà
+Ìàéëñ	Íàêèäêà
+Íýéò	Ïàëèöà
+Íàòàí	ïëèòêà
+Íàòàíèýëü	áóëàâà
+Íèë	Êëåïàííàÿ
+Íåä	êîæà
+Íåëüñîí	ïóñòûíÿ
+Íüþò	Áðàêàäà
+Íèêîëàñ	Ïîâåëèòåëüíèöà
+Íèê	Ñêëÿíêà
+Íèêîëàé	Êèðà
+Íîé	Ëèñèÿ
+Íîðì	Ðåëèêâèÿ
+Íîðìàí	Ëàìïà
+Íîððèñ	Òàéíàÿ
+Îëàô	ãðîáíèöà
+Îëèâåð	Áåçäíà
+Îòèñ	Êîðîëåâñêàÿ
+Îóâåí	Êîðîíà
+Ïàðêåð	Êîëîäà
+Ïýò	Ãëûáà
+Ïàòðèê
+Ïîë
+Ïàâåë
+Ïåðñèâàëü
+Ïåðñè
+Ïåððè
+Ïèò
+Ïåòåð
+Ôåäðóñ
+Ôèë
+Ôèëèï
+Ïèðñ
+Ïüåð
+Ïðåñòîí
+Êâàí
+Êâåíòèí
+Êâèíí
+Ðàäó
+Ðàôàýëü
+Ðàëüô
+Ðàìåé
+Ðàìñè
+Ðýíäàë
+Ðàíäîëüô
+Ðýíäè
+Ðàóëü
+Ðàéìîíä
+Ðåã
+Ðåäæèíàëüä
+Ðåíå
+Ðåíöî
+Ðåêñ
+Ðèíàëüäî
+Ðè÷àðä
+Ðèêè
+Ðîá
+Ðîááè
+Ðîáåðò
+Ðîáèí
+Ðîêè
+Ðîäíè
+Ðîëàíä
+Ðîí
+Ðîíàëüä
+Ðîðè
+Ðîññ
+Ðîé
+Ðóäè
+Ðóïåðò
+Ðàññåë
+Ðàñòè
+Ðàéàí
+Ñààä
+Ñàë
+Ñàëüâàòîðå
+Ñýì
+Ñàìþýëü
+Ñàíäèï
+Ñàíòîñ
+Ñîë
+Ñêàëèñ
+Ñêîòò
+Øîí
+Ñåáàñòüÿí
+Ñåðãèî
+Ñåò
+Ñåéìóð
+Øåëäîí
+Øåëë
+Øåðäîí
+Øåðìàí 
+Øèìîí
+Ñèäíåé
+Ñèìîí
+Ñëåéä
+Ñîííè
+Ñïåíñåð
+Ñòåëñ
+Ñòýí
+Ñòýíëè
+Ñòåôàí
+Ñòèâ
+Ñòèâåí
+Ñòþàðò
+Ñóëåéìàí
+Ñâåí
+Ñèëüâåñòð 
+Òýä
+Òàêà
+Òåððàíñ
+Òàäåóñ
+Òåéí
+Òåîäîð
+Òîìàñ
+Òèì
+Òèìîòè
+Òîáèàñ
+Òîää
+Òîì
+Òîíè
+Òðàí
+Òðýâèñ
+Òðåíò
+Òðåíòîí
+Òðóâîð
+Òðèï
+Òàéëåð
+Òàéñîí
+Âàäèì
+Âàë
+Âàíñ
+Âåðí
+Âåðíîí
+Âèêòîð
+Âèêòîðèñ
+Âèí÷åíöî
+Âîëüã
+Âèðãèëèé
+Âëàäèìèð
+Âýéä
+Óàëüäî
+Óîëëåñ
+Âàëüòåð
+Âåéí
+Óîððåí
+Óýáá
+Âåíäåëë
+Âåñëè
+Óèëáåðò
+Âèëüôðåä 
+Âèëàì
+Âèëë
+Âèëëàðä
+Âèëüÿì
+Óèëüñîí
+Âèíñòîí
+Âóäðî
+Êñóàí 
+ßíñè
+Þðèé
+Èâ
+Çàõàðèé
+Çàê
+Çåáóëîí
+Çèê
+Çîëòàí
+Çîðåêñ
+Çèããè
+Ñóäüÿ
+Ìàðõýì
+Ëîðä
+Ñòðåêîçàâð
+Îãíåííûé
+äðàêîí
+èñêàòåëü
+Ñòðåëîê
+ìå÷íèê
+âîð
+Àíãåë
+Àðõàíãåë
+âëàäûêà
+Ëó÷íèê
+Ýëèòíûé
+âàìïèð
+Ïëàâó÷èé
+ãëàç
+Ïîñëóøíèê
+Êëèðèê
+Ñâÿùåííèê
+Äüÿâîë
+ðàáîòíèê
+âîèí
+Êàïèòàí
+Çåëåíûé
+Ñèíèé
+Êðàñíûé
+Ãíîì
+ñîëäàò
+ëåéòåíàíò
+êîìàíäèð
+Âèõðü
+Öèêëîí
+Âîçäóøíûé
+ýëåìåíòàë
+Ãëèíÿíûé
+Êàìåííûé
+Çåìíîé
+×àñîâîé
+Ñòðàæ
+Ìàëûé
+Ñâåò
+Âåëèêèé
+Âîäíûé
+Ýëüô
+ðåéíäæåð
+çàùèòíèê
+óëàí
+Íîâîáðàíåö
+Ãðàáèòåëü
+Íàë¸ò÷èê
+Áàíäèò
+ìå÷
+Ïîñâÿùåííûé
+×åìïèîí
+Ìàñòåð
+äæèíí
+Ìîãó÷èé
+èôðèò
+äóõ
+Ïðèçðàê
+Ãîáëèí
+ïîâåëèòåëü
+Âëàñòåëèí
+Ãîã
+ìàãîã
+ãîëåì
+Áðîíçîâûé
+Ìåäíûé
+Çîëîòîé
+Ãðèôîí
+Ëîâ÷èé
+Êîðîëåâñêèé
+Õàîñ
+Ëè÷
+Êîðîëü
+Âîëõâ
+×àðîäåé
+Àðõèìàã
+ìèíîòàâð
+Ñòàðøèé
+Öàðü
+Ìîíàõ
+Ïîñâÿù¸ííûé
+Íåêðîìàíò
+Ìåðòâûé
+Ìåðòâåö
+Èçóìðóäíûé
+ñëèçåíü
+Ñàïôèðîâûé
+Êðîâàâûé
+Ìåñòíûé
+æèòåëü
+Äðóèä
+óáèéöà
+ðóõ
+ëþäîåä
+Ñêåëåò
+Ïðåäâîäèòåëü
+Áîëüøîé
+ïàóê
+ßäîâèòûé
+Ñòðàæíèê
+Ðàçáîéíèê
+òèòàí
+Ãðîçîâîé
+Òðîãëîäèò
+Ñëàáûé
+Âóðäàëàê
+îãîíü
+×åðíîêíèæíèê
+Êóðãàí
+Âèâåðí
+Ðîãàòûé
+Äðåâíèé
+Ãíèþùèé
+Õîäÿ÷èé
+Áîëîòíûé
+òðîëëü
+Ðå÷íîé
+Ãîðíûé
+Óïûðü
+Âîññòàâøèé
+àä
+Ìóäðûé
+áëàñòåð
+Ìåãàäðàêîí
+Îñîáíÿê
+Äîì
+Ïîñòîÿëûé
+äâîð
+Áðàò
+Ôàìèëüíûé
+×åðòîã
+Âèííûé
+ïîãðåá
+Çîä
+ãîðîä
+Ëàáèðèíò
+Êóëàê
+Õðàì
+Èíêóáàòîð
+Çàìîê
+Øòàá
+çàë
+Òðîííûé
+Ñâåòÿùèéñÿ
+Ñóìåðå÷íûé
+Äåïîçèòàðèé
+áàíê
+ïòè÷èé
+ðàé
+Ýëåãàíòíûé
+îðê
+Ïðèäîðîæíûé
+òðàêòèð
+Ïîñëåäíèé
+ïðèþò
+Ëîÿëüíûé
+íàåìíèê
+Áàð
+Ãèìíàñòè÷åñêèé
+Ó÷åáíûé
+ïîëèãîí
+Øàòåð
+Îðäåí
+Ñîáîð
+Òóìàííûé
+Ñåðûé
+Íåóñòðàøèìûé
+âèòåðñìèò
+Òîí
+Èâåðñîí
+íàëåò÷èê
+Êèíåäæ
+ëóê
+Òàðèí
+Âèòåðí
+Éîõàíñîí
+Äâîðåöêèé
+Äýâðèê
+Ïåëàäèóì
+Äàððîí
+Òåìïåð
+Ôåíòîí
+Êðþëåí
+Øåéí
+Òîððåíò
+Áðàõåéí
+Êàäàðð
+Ïåðèí
+Ëàéòôèíãåð
+Ëåíîðä
+Ñêèííåð
+Àðâèí
+Áåíåêëàóä
+Âåðõîâíûé
+æðåö
+Öåíîôåêñ
+Ðîìòðàêñ
+ðàçâåä÷èê
+Òàðåíò
+Îëäðèí
+Òàìëîê
+Òîðèíñîí
\ No newline at end of file
Binary file Debug/mm7_1.obj has changed
Binary file Debug/mm7_2.obj has changed
Binary file Debug/mm7_3.obj has changed
Binary file Debug/mm7_4.obj has changed
Binary file Debug/mm7_5.obj has changed
Binary file Debug/mm7_6.obj has changed
Binary file Debug/mm7_data.obj has changed
Binary file Debug/mt.command.1.tlog has changed
Binary file Debug/mt.read.1.tlog has changed
Binary file Debug/mt.write.1.tlog has changed
Binary file Debug/rc.command.1.tlog has changed
Binary file Debug/rc.read.1.tlog has changed
Binary file Debug/rc.write.1.tlog has changed
Binary file Debug/stru10.obj has changed
Binary file Debug/stru6.obj has changed
Binary file Debug/stru9.obj has changed
Binary file Debug/vc100.idb has changed
Binary file Debug/vc100.pdb has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DecalBuilder.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,829 @@
+#include "DecalBuilder.h"
+#include "Game.h"
+#include "Time.h"
+#include "stru314.h"
+#include "Outdoor.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+struct DecalBuilder *pDecalBuilder = new DecalBuilder;
+struct BloodsplatContainer *pBloodsplatContainer = new BloodsplatContainer;
+
+
+//----- (0043B570) --------------------------------------------------------
+double DecalBuilder_stru0::_43B570_get_color_mult_by_time()
+{
+  double result; // st7@3
+  
+  if (field_1C_flags & 1)
+  {
+    if ((field_20_time - pEventTimer->Time() + 384) / 384.0 >= 0.0)
+      result = (field_20_time - pEventTimer->Time() + 384) / 384.0;
+    else
+      result = 0.0;
+  }
+  else
+  {
+    result = 1.0;
+  }
+  return result;
+}
+
+
+
+
+
+//----- (0043B6EF) --------------------------------------------------------
+bool BloodsplatContainer::AddBloodsplat(float x, float y, float z, float radius, char r, char g, char b)
+{
+  int *v8; // esi@1
+  int v9; // eax@3
+  Bloodsplat *v10; // eax@3
+  int *result; // eax@3
+  int v12; // ecx@3
+
+  v8 = &this->uNumBloodsplats;
+  if ( this->uNumBloodsplats == 64 )
+    *v8 = 0;
+  v9 = 5 * (*v8)++;
+  v10 = &this->std__vector_pBloodsplats[8 * v9 / 0x28u];
+  v10->x = x;
+  v10->y = y;
+  v10->z = z;
+  v10->radius = radius;
+  v10->r = r;
+  v10->g = g;
+  v10->b = b;
+  result = (int *)&this->std__vector_pBloodsplats_size;
+  v12 = this->std__vector_pBloodsplats_size + 1;
+  if ( v12 > 64 )
+    v12 = 64;
+  *result = v12;
+  LOBYTE(result) = 1;
+  return (bool)result;
+}
+
+//----- (0049B490) --------------------------------------------------------
+bool DecalBuilder::AddBloodsplat(float x, float y, float z, float r, float g, float b, float radius, int a8, int a9)
+{
+  //double v10; // ST1C_8@1
+  char v11; // ST24_1@1
+  //double v12; // ST1C_8@1
+  //double v13; // ST1C_8@1
+  int a7a; // [sp+40h] [bp+18h]@1
+  //float arg14a; // [sp+44h] [bp+1Ch]@1
+  //float arg14b; // [sp+44h] [bp+1Ch]@1
+  //float arg14c; // [sp+44h] [bp+1Ch]@1
+
+  /*arg14a = b * 255.0;
+  v10 = arg14a + 6.7553994e15;
+  v11 = LOBYTE(v10);
+  arg14b = g * 255.0;
+  v12 = arg14b + 6.7553994e15;
+  a7a = LODWORD(v12);
+  arg14c = r * 255.0;
+  v13 = arg14c + 6.7553994e15;*/
+  return pBloodsplatContainer->AddBloodsplat(x, y, z, radius,
+                                             //SLOBYTE(v13), a7a, v11);
+                                             r * 255.0f,
+                                             g * 255.0f,
+                                             b * 255.0f);
+}
+
+//----- (0049B525) --------------------------------------------------------
+void DecalBuilder::Reset(unsigned int bPreserveBloodsplats)
+{
+  if ( !bPreserveBloodsplats )
+  {
+    pBloodsplatContainer->std__vector_pBloodsplats_size = 0;
+    pBloodsplatContainer->uNumBloodsplats = 0;
+  }
+  std__vector_pDecals_size = 0;
+}
+
+//----- (0049B540) --------------------------------------------------------
+char DecalBuilder::ApplyDecals(int a2, char a3, stru154 *a4, int a5, RenderVertexSoft *a6, IndoorCameraD3D_Vec4 *a7, char a8, unsigned int uSectorID)
+{
+  char *v9; // eax@3
+  signed int v10; // ecx@3
+  RenderVertexSoft *v11; // eax@10
+  unsigned int v12; // edx@10
+  RenderVertexSoft *v13; // esi@11
+  RenderVertexSoft *v14; // edi@11
+  char v15; // zf@11
+  stru154 *v16; // esi@12
+  double v18; // st7@17
+  double v19; // st6@17
+  float v20; // eax@17
+  Bloodsplat *v21; // esi@21
+  int v22; // eax@21
+  int v23; // ecx@21
+  double v24; // st7@21
+  int v25; // ebx@21
+  double v26; // st7@21
+  int v27; // edi@21
+  double v28; // st7@21
+  int v29; // ST10_4@21
+  int v30; // ST08_4@21
+  DecalBuilder *v31; // esi@21
+  int v32; // [sp+4h] [bp-44h]@18
+  RenderVertexSoft *v33; // [sp+8h] [bp-40h]@21
+  stru314 *v34; // [sp+Ch] [bp-3Ch]@21
+  float v35; // [sp+10h] [bp-38h]@21
+  float v36; // [sp+14h] [bp-34h]@17
+  int v37; // [sp+18h] [bp-30h]@17
+  int a5a; // [sp+28h] [bp-20h]@21
+  int v39; // [sp+2Ch] [bp-1Ch]@21
+  int v40; // [sp+30h] [bp-18h]@21
+  int v41; // [sp+34h] [bp-14h]@22
+  int v42; // [sp+38h] [bp-10h]@21
+  int v43; // [sp+3Ch] [bp-Ch]@21
+  DecalBuilder *thisa; // [sp+40h] [bp-8h]@1
+  RenderVertexSoft *a11; // [sp+44h] [bp-4h]@8
+
+  __debugbreak();
+
+  auto a9 = uSectorID;
+
+  thisa = this;
+  if ( !a5 )
+    return 0;
+
+  static RenderVertexSoft static_AE4F90[64];
+  static bool __init_flag1 = false;
+  if (!__init_flag1)
+  {
+    __init_flag1 = true;
+
+    for (uint i = 0; i < 64; ++i)
+      static_AE4F90[i].flt_2C = 0.0f;
+  }
+  
+  static stru314 static_AE4F60; // idb
+  /*static bool __init_flag2 = false;
+  if (!__init_flag2)
+  {
+    __init_flag2 = true;
+
+    stru314::stru314(&static_AE4F60);
+  }*/
+
+  a11 = a6;
+  if ( a7 )
+  {
+    if ( a5 > 0 )
+    {
+      v11 = static_AE4F90;
+      v12 = (char *)a6 - (char *)static_AE4F90;
+      a6 = (RenderVertexSoft *)a5;
+      do
+      {
+        v13 = (RenderVertexSoft *)((char *)v11 + v12);
+        v14 = v11;
+        ++v11;
+        v15 = a6 == (RenderVertexSoft *)1;
+        a6 = (RenderVertexSoft *)((char *)a6 - 1);
+        memcpy(v14, v13, 0x30u);
+      }
+      while ( !v15 );
+    }
+    v16 = a4;
+    if ( pGame->pIndoorCameraD3D->_437376(a4, static_AE4F90, (unsigned int *)&a5) == 1 )
+    {
+      if ( !a5 )
+        return 0;
+      a11 = static_AE4F90;
+    }
+  }
+  else
+  {
+    v16 = a4;
+  }
+  v18 = v16->face_plane.vNormal.z;
+  v19 = v16->face_plane.vNormal.y;
+  v20 = v16->face_plane.vNormal.x;
+  v37 = (int)&static_AE4F60.field_1C;
+  static_AE4F60.field_4.y = v19;
+  static_AE4F60.field_4.x = v20;
+  LODWORD(v36) = (DWORD)&static_AE4F60.field_10;
+  static_AE4F60.field_4.z = v18;
+  static_AE4F60.dist = v16->face_plane.dist;
+  if ( !pGame->pIndoorCameraD3D->GetFacetOrientation(
+          v16->polygonType,
+          &static_AE4F60.field_4,
+          &static_AE4F60.field_10,
+          &static_AE4F60.field_1C) )
+  {
+      MessageBoxW(nullptr, L"Error: Failed to get the facet orientation", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\PolyProjector.cpp:101", 0);
+  }
+  int _a7 = 0;
+  if ( thisa->uNumDecals > 0 )
+  {
+    a6 = (RenderVertexSoft *)thisa->std__vector_30B00C;
+    do
+    {
+      v21 = &pBloodsplatContainer->std__vector_pBloodsplats[LODWORD(a6->vWorldPosition.x)];
+      *(float *)&v37 = v21->z;
+      v36 = v21->y;
+      v35 = v21->x;
+      v22 = _43F5C8_get_point_light_level_with_respect_to_lights(a2, a9, v35, v36, *(float *)&v37);
+      v23 = v21->b;
+      v24 = v21->x;
+      v42 = v22;
+      BYTE3(v22) = 0;
+      *(short *)((char *)&v22 + 1) = v21->r;
+      LOBYTE(v22) = v21->g;
+      v43 = v23 | (v22 << 8);
+      v25 = (signed __int64)v24;
+      v26 = v21->z;
+      v27 = (signed __int64)v21->y;
+      v37 = a8;
+      v40 = (signed __int64)v26;
+      v28 = v21->dot_dist;
+      LODWORD(v36) = (uint32)a11;
+      a5a = v25;
+      v39 = v27;
+      LODWORD(v35) = a5;
+      v34 = &static_AE4F60;
+      *(float *)&v33 = v28;
+      v32 = v23 | (v22 << 8);
+      *(float *)&v29 = v21->radius;
+      v30 = (int)v21;
+      v31 = thisa;
+      if ( !thisa->_49B790_build_decal_geometry(
+              v42,
+              a3,
+              v30,
+              (int)&a5a,
+              v29,
+              v43,
+              v33,
+              &static_AE4F60,
+              a5,
+              a11,
+              a8) )
+      {
+      MessageBoxW(nullptr, L"Error: Failed to build decal geometry", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\PolyProjector.cpp:114", 0);
+      }
+      ++_a7;
+      a6 = (RenderVertexSoft *)((char *)a6 + 4);
+    }
+    while ( _a7 < v31->uNumDecals );
+  }
+  return 1;
+}
+
+//----- (0049B790) --------------------------------------------------------
+char DecalBuilder::_49B790_build_decal_geometry(int a2, char a3, int a4, int a5, int a6, unsigned int uColorMultiplier, RenderVertexSoft *a8, stru314 *a9, signed int a10, RenderVertexSoft *a11, char uClipFlags)
+{
+  DecalBuilder *v12; // esi@1
+  Decal *v13; // edi@2
+  char *v14; // eax@2
+  double v15; // st7@4
+  double v16; // st7@4
+  int v17; // eax@4
+  stru314 *v18; // ebx@4
+  double v19; // st7@4
+  double v20; // st7@4
+  double v21; // st7@4
+  double v22; // st6@4
+  double v23; // st6@4
+  double v24; // st5@4
+  char *v25; // eax@4
+  signed int v26; // ecx@4
+  double v27; // st5@4
+  double v28; // st7@5
+  double v29; // st7@6
+  char result; // al@6
+  unsigned int *v31; // edi@7
+  RenderVertexSoft *v32; // ebx@8
+  std::string *v33; // ecx@15
+  int v34; // eax@19
+  const char *v35; // [sp-Ch] [bp-2Ch]@15
+  int v36; // [sp-8h] [bp-28h]@15
+  std::string v37; // [sp-4h] [bp-24h]@15
+  float v38; // [sp+8h] [bp-18h]@6
+  RenderVertexSoft *v39; // [sp+Ch] [bp-14h]@6
+  unsigned int *v40; // [sp+10h] [bp-10h]@6
+
+  v12 = this;
+  if ( *(float *)&a6 == 0.0 )
+    goto LABEL_24;
+  v13 = &this->std__vector_pDecals[this->field_308008];
+  v14 = (char *)&this->std__vector_pDecals[this->field_308008].field_C1C;
+  this->std__vector_pDecals[this->field_308008].field_C18 = (DecalBuilder_stru0 *)a4;
+  *(int *)v14 = 0;
+  if ( a3 & 2 )
+    *(int *)v14 = 1;
+  v15 = *(float *)&a6 - *(float *)&a8;
+  *(float *)&this->field_30C028 = v15;
+  v16 = sqrt((*(float *)&a6 + *(float *)&a6 - v15) * v15);
+  *(float *)&v12->field_30C02C = v16;
+  v17 = a5;
+  v18 = a9;
+  v12->flt_30C030 = 1.0 - (*(float *)&a6 - v16) / *(float *)&a6;
+  v13->field_C08 = (signed __int64)((double)*(signed int *)v17 - *(float *)&a8 * v18->field_4.x);
+  v13->field_C0A = (signed __int64)((double)*(signed int *)(a5 + 4) - *(float *)&a8 * v18->field_4.y);
+  v19 = *(float *)&a6;
+  v13->field_C0C = (signed __int64)((double)*(signed int *)(a5 + 8) - *(float *)&a8 * v18->field_4.z);
+  v20 = v19 * v12->flt_30C030;
+  a8 = v13->pVertices;
+  v12->field_30C034 = v20;
+  v12->field_30C010 = v20 * v18->field_10.x;
+  v12->field_30C014 = v20 * v18->field_10.y;
+  v12->field_30C018 = v20 * v18->field_10.z;
+  v12->field_30C01C = v20 * v18->field_1C.x;
+  v12->field_30C020 = v20 * v18->field_1C.y;
+  v12->field_30C024 = v20 * v18->field_1C.z;
+  a6 = v13->field_C08;
+  v21 = (double)a6;
+  v22 = v21 - v12->field_30C01C;
+  a6 = v13->field_C0A;
+  v13->pVertices[0].vWorldPosition.x = v22 + v12->field_30C010;
+  v23 = (double)a6;
+  v24 = v23 - v12->field_30C020 + v12->field_30C014;
+  v25 = (char *)&v13->pVertices[0].vWorldPosition.y;
+  a6 = v13->field_C0C;
+  v26 = 4;
+  v13->pVertices[0].vWorldPosition.y = v24;
+  v27 = (double)a6;
+  *(float *)&a6 = v27;
+  v13->pVertices[0].vWorldPosition.z = v27 - v12->field_30C024 + v12->field_30C018;
+  v13->pVertices[0].u = 0.0;
+  v13->pVertices[0].v = 0.0;
+  v13->pVertices[1].vWorldPosition.x = v21 - v12->field_30C01C - v12->field_30C010;
+  v13->pVertices[1].vWorldPosition.y = v23 - v12->field_30C020 - v12->field_30C014;
+  v13->pVertices[1].vWorldPosition.z = v27 - v12->field_30C024 - v12->field_30C018;
+  v13->pVertices[1].u = 0.0;
+  v13->pVertices[1].v = 1.0;
+  v13->pVertices[2].vWorldPosition.x = v21 + v12->field_30C01C - v12->field_30C010;
+  v13->pVertices[2].vWorldPosition.y = v23 + v12->field_30C020 - v12->field_30C014;
+  v13->pVertices[2].vWorldPosition.z = v27 + v12->field_30C024 - v12->field_30C018;
+  v13->pVertices[2].u = 1.0;
+  v13->pVertices[2].v = 1.0;
+  v13->pVertices[3].vWorldPosition.x = v21 + v12->field_30C01C + v12->field_30C010;
+  v13->pVertices[3].vWorldPosition.y = v23 + v12->field_30C020 + v12->field_30C014;
+  v13->pVertices[3].vWorldPosition.z = *(float *)&a6 + v12->field_30C024 + v12->field_30C018;
+  v13->pVertices[3].u = 1.0;
+  v13->pVertices[3].v = 0.0;
+  do
+  {
+    v28 = v18->field_4.y * *(float *)v25
+        + *((float *)v25 - 1) * v18->field_4.x
+        + *((float *)v25 + 1) * v18->field_4.z
+        + v18->dist;
+    *((float *)v25 - 1) = *((float *)v25 - 1) - v28 * v18->field_4.x;
+    *(float *)v25 = *(float *)v25 - v28 * v18->field_4.y;
+    v25 += 48;
+    --v26;
+    *((float *)v25 - 11) = *((float *)v25 - 11) - v28 * v18->field_4.z;
+  }
+  while ( v26 );
+  v13->uColorMultiplier = uColorMultiplier;
+  v40 = (unsigned int *)&v13->uNumVertices;
+  v39 = v13->pVertices;
+  v13->uNumVertices = 4;
+  v13->field_C14 = a2;
+  v29 = v18->field_4.z;
+  a6 = (int)&v13->uNumVertices;
+  v38 = v29;
+  result = pGame->pStru9Instance->_4980B9(a11, a10, v18->field_4.x, v18->field_4.y, v38, v39, v40);
+  if ( result )
+  {
+    v31 = (unsigned int *)a6;
+    if ( !*(int *)a6 )
+      goto LABEL_24;
+    v32 = a8;
+    v40 = *(unsigned int **)a6;
+    v39 = a8;
+    pGame->pIndoorCameraD3D->ViewTransform(a8, (unsigned int)v40);
+    v40 = 0;
+    pGame->pIndoorCameraD3D->Project(v32, *v31, 0);
+    if ( !(uClipFlags & 1) )
+    {
+LABEL_19:
+      ++v12->field_308008;
+      v34 = 1024;
+      if ( v12->field_308008 == 1024 )
+        v12->field_308008 = 0;
+      if ( (signed int)(v12->std__vector_pDecals_size + 1) <= 1024 )
+        v34 = v12->std__vector_pDecals_size + 1;
+      v12->std__vector_pDecals_size = v34;
+      goto LABEL_24;
+    }
+    if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+    {
+      if ( uClipFlags & 2 )
+      {
+        v40 = (unsigned int *)&a8;
+        v39 = v12->pVertices;
+        pGame->pIndoorCameraD3D->_436CDC_mess_with_lightmap__clipflag_2(v32, *v31, v12->pVertices, (unsigned int *)&a8);
+LABEL_14:
+        v40 = v31;
+        v39 = v12->pVertices;
+        pGame->pIndoorCameraD3D->_437143((unsigned int)a8, v32, v12->pVertices, v31);
+        goto LABEL_18;
+      }
+      if ( uClipFlags & 4 )
+      {
+        v40 = (unsigned int *)&a8;
+        v39 = v12->pVertices;
+        pGame->pIndoorCameraD3D->_436F09_mess_with_lightmap__clipflag_4(v32, *v31, v12->pVertices, (unsigned int *)&a8);
+        goto LABEL_14;
+      }
+      v39 = (RenderVertexSoft *)"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\PolyProjector.cpp:258";
+      v35 = "Undefined clip flag specified";
+    }
+    else
+    {
+      v39 = (RenderVertexSoft *)"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\PolyProjector.cpp:263";
+      v35 = "Lightpoly builder native indoor clipping not implemented";
+    }
+      MessageBoxA(nullptr, v35, (const char *)v39, 0);
+LABEL_18:
+    if ( *(float *)&a8 != 0.0 )
+      goto LABEL_19;
+LABEL_24:
+    result = 1;
+  }
+  return result;
+}
+
+//----- (0049BBBD) --------------------------------------------------------
+bool DecalBuilder::ApplyBloodsplatDecals_IndoorFace(unsigned int uFaceID)
+{
+  double v7; // st7@12
+
+  if (!pBloodsplatContainer->std__vector_pBloodsplats_size)
+    return true;
+  
+  auto pFace = &pIndoor->pFaces[uFaceID];
+
+  if (pFace->uAttributes & 0x400000)
+    return true;
+  if (pFace->Animated())
+    return true;
+
+  for (uint i = 0; i < pBloodsplatContainer->std__vector_pBloodsplats_size; ++i)
+  {
+    auto pBloodsplat = pBloodsplatContainer->std__vector_pBloodsplats + i;
+    if (pFace->pBounding.x1 - pBloodsplat->radius < pBloodsplat->x &&
+        pFace->pBounding.x2 + pBloodsplat->radius > pBloodsplat->x &&
+        pFace->pBounding.y1 - pBloodsplat->radius < pBloodsplat->y &&
+        pFace->pBounding.y2 + pBloodsplat->radius > pBloodsplat->y &&
+        pFace->pBounding.z1 - pBloodsplat->radius < pBloodsplat->z &&
+        pFace->pBounding.z2 + pBloodsplat->radius > pBloodsplat->z)
+    {
+      v7 = pFace->pFacePlane.vNormal.z * pBloodsplat->z +
+           pFace->pFacePlane.vNormal.y * pBloodsplat->y +
+           pFace->pFacePlane.vNormal.x * pBloodsplat->x +
+           pFace->pFacePlane.dist;
+      if (v7 <= pBloodsplat->radius)
+      {
+        pBloodsplat->dot_dist = v7;
+        std__vector_30B00C[uNumDecals++] = i;
+      }
+    }
+  }
+
+  return true;
+}
+
+//----- (0049BCEB) --------------------------------------------------------
+char DecalBuilder::ApplyDecals_OutdoorFace(ODMFace *pFace)
+{
+  int v2; // edi@1
+  unsigned int v3; // eax@2
+  char *v4; // edx@5
+  double v5; // ST1C_8@12
+  double v6; // ST14_8@12
+  double v7; // ST0C_8@12
+  double v8; // st7@12
+  unsigned int v10; // [sp+20h] [bp-1Ch]@1
+
+  v2 = 0;
+  this->uNumDecals = 0;
+  v10 = pBloodsplatContainer->std__vector_pBloodsplats_size;
+  if ( pBloodsplatContainer->std__vector_pBloodsplats_size )
+  {
+    v3 = pFace->uAttributes;
+    if ( !(v3 & 0x400000) )
+    {
+      if ( !(v3 & 0x10) && (signed int)pBloodsplatContainer->std__vector_pBloodsplats_size > 0 )
+      {
+        v4 = (char *)&pBloodsplatContainer->std__vector_pBloodsplats[0].y;
+        do
+        {
+          if ( (double)pFace->pBoundingBox.x1 - *((float *)v4 + 2) < *((float *)v4 - 1) )
+          {
+            if ( (double)pFace->pBoundingBox.x2 + *((float *)v4 + 2) > *((float *)v4 - 1) )
+            {
+              if ( (double)pFace->pBoundingBox.y1 - *((float *)v4 + 2) < *(float *)v4 )
+              {
+                if ( (double)pFace->pBoundingBox.y2 + *((float *)v4 + 2) > *(float *)v4 )
+                {
+                  if ( (double)pFace->pBoundingBox.z1 - *((float *)v4 + 2) < *((float *)v4 + 1) )
+                  {
+                    if ( (double)pFace->pBoundingBox.z2 + *((float *)v4 + 2) > *((float *)v4 + 1) )
+                    {
+                      v5 = *((float *)v4 - 1) + 6.7553994e15;
+                      v6 = *(float *)v4 + 6.7553994e15;
+                      v7 = *((float *)v4 + 1) + 6.7553994e15;
+                      v8 = (double)((pFace->pFacePlane.dist
+                                   + LODWORD(v5) * pFace->pFacePlane.vNormal.x
+                                   + LODWORD(v6) * pFace->pFacePlane.vNormal.y
+                                   + LODWORD(v7) * pFace->pFacePlane.vNormal.z) >> 16);
+                      if ( v8 <= *((float *)v4 + 2) )
+                      {
+                        *((float *)v4 + 3) = v8;
+                        this->std__vector_30B00C[this->uNumDecals++] = v2;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+          ++v2;
+          v4 += 40;
+        }
+        while ( v2 < (signed int)v10 );
+      }
+    }
+  }
+  return 1;
+}
+
+//----- (0049BE8A) --------------------------------------------------------
+bool DecalBuilder::_49BE8A(struct stru148 *a2, float a3, int a4, RenderVertexSoft *a5, unsigned int uStripType, char a7)
+{
+  bool result; // eax@1
+  RenderVertexSoft *v8; // edi@3
+  float v9; // ebx@3
+  char *v10; // esi@3
+  float v11; // eax@5
+  float v12; // eax@6
+  double v13; // st7@13
+  double v14; // st7@19
+  int v15; // eax@20
+  int v16; // eax@22
+  int v17; // edx@24
+  DecalBuilder *v18; // eax@24
+  std::string v19; // [sp-18h] [bp-54h]@12
+  const char *v20; // [sp-8h] [bp-44h]@12
+  int v21; // [sp-4h] [bp-40h]@12
+  double v22; // [sp+Ch] [bp-30h]@19
+  unsigned int v23; // [sp+14h] [bp-28h]@1
+  DecalBuilder *v24; // [sp+18h] [bp-24h]@1
+  int v25; // [sp+1Ch] [bp-20h]@19
+  float v26; // [sp+20h] [bp-1Ch]@12
+  int v27; // [sp+24h] [bp-18h]@12
+  float v28; // [sp+28h] [bp-14h]@13
+  float v29; // [sp+2Ch] [bp-10h]@7
+  float v30; // [sp+30h] [bp-Ch]@6
+  float v31; // [sp+34h] [bp-8h]@6
+  bool v32; // [sp+38h] [bp-4h]@2
+
+  this->uNumDecals = 0;
+  result = pBloodsplatContainer->std__vector_pBloodsplats_size;
+  v24 = this;
+  v23 = pBloodsplatContainer->std__vector_pBloodsplats_size;
+  if ( pBloodsplatContainer->std__vector_pBloodsplats_size )
+  {
+    v32 = 0;
+    if ( (signed int)pBloodsplatContainer->std__vector_pBloodsplats_size > 0 )
+    {
+      v8 = a5;
+      v9 = a3;
+      v10 = (char *)&pBloodsplatContainer->std__vector_pBloodsplats[0].y;
+      while ( uStripType != 4 )
+      {
+        if ( uStripType == 3 )
+        {
+          if ( a7 )
+          {
+            a3 = v8->vWorldPosition.x;
+            v31 = v8[2].vWorldPosition.x;
+            v30 = v8[1].vWorldPosition.y;
+            v12 = v8[2].vWorldPosition.y;
+            goto LABEL_7;
+          }
+          a3 = v8[1].vWorldPosition.x;
+          v11 = v8[2].vWorldPosition.x;
+LABEL_6:
+          v31 = v11;
+          v30 = v8[1].vWorldPosition.y;
+          v12 = v8->vWorldPosition.y;
+LABEL_7:
+          v29 = v12;
+          goto LABEL_13;
+        }
+      MessageBoxW(nullptr, L"Uknown strip type detected!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\PolyProjector.cpp:434", 0);
+LABEL_13:
+        v21 = uStripType;
+        v13 = pGame->pIndoorCameraD3D->GetPolygonMinZ(v8, uStripType);
+        v21 = uStripType;
+        v28 = v13;
+        v26 = pGame->pIndoorCameraD3D->GetPolygonMaxZ(v8, uStripType);
+        if ( a3 - *((float *)v10 + 2) < *((float *)v10 - 1) )
+        {
+          if ( v31 + *((float *)v10 + 2) > *((float *)v10 - 1) )
+          {
+            if ( v30 - *((float *)v10 + 2) < *(float *)v10 )
+            {
+              if ( v29 + *((float *)v10 + 2) > *(float *)v10 )
+              {
+                if ( v28 - *((float *)v10 + 2) < *((float *)v10 + 1) )
+                {
+                  if ( v26 + *((float *)v10 + 2) > *((float *)v10 + 1) )
+                  {
+                    Vec3_float_::NegDot(&v8->vWorldPosition, (Vec3_float_ *)LODWORD(v9), (float *)a4);
+                    v26 = *(float *)(LODWORD(v9) + 4) * *(float *)v10
+                        + *(float *)(LODWORD(v9) + 8) * *((float *)v10 + 1)
+                        + *(unsigned int *)LODWORD(v9) * *((float *)v10 - 1)
+                        + *(float *)a4;
+                    v22 = v26 + 6.7553994e15;
+                    v25 = LODWORD(v22);
+                    v14 = (double)SLODWORD(v22);
+                    v28 = v14;
+                    if ( v14 <= *((float *)v10 + 2) )
+                    {
+                      v15 = *(int *)&a2->flags;
+                      if ( v15 & 2 || BYTE1(v15) & 1 )
+                      {
+                        v16 = *((int *)v10 + 5);
+                        if ( !(v16 & 1) )
+                        {
+                          LOBYTE(v16) = v16 | 1;
+                          *((int *)v10 + 5) = v16;
+                          *((_QWORD *)v10 + 3) = pEventTimer->Time();
+                        }
+                      }
+                      v17 = v32;
+                      *((int *)v10 + 3) = LODWORD(v28);
+                      v18 = v24;
+                      v24->std__vector_30B00C[v24->uNumDecals] = v17;
+                      ++v18->uNumDecals;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        ++v32;
+        v10 += 40;
+        result = v32;
+        if ( v32 >= (signed int)v23 )
+          goto LABEL_26;
+      }
+      a3 = v8->vWorldPosition.x;
+      v11 = v8[3].vWorldPosition.x;
+      goto LABEL_6;
+    }
+  }
+LABEL_26:
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (0049C095) --------------------------------------------------------
+void DecalBuilder::DrawDecal(Decal *pDecal, float z_bias)
+{
+  signed int v21; // [sp+Ch] [bp-864h]@15
+  RenderVertexD3D3 pVerticesD3D[64]; // [sp+20h] [bp-850h]@6
+
+  if (pDecal->uNumVertices < 3)
+  {
+    Log::Warning(L"Decal has < 3 vertices");
+    return;
+  }
+
+  float color_mult;
+  if ( pDecal->field_C1C & 1 )
+    color_mult = 1.0;
+  else
+    color_mult = pDecal->field_C18->_43B570_get_color_mult_by_time();
+
+  for (uint i = 0; i < pDecal->uNumVertices; ++i)
+  {
+    uint uTint = pRenderer->GetActorTintColor(pDecal->pVertices[i].vWorldViewPosition.x, pDecal->field_C14, 0, 0, nullptr);
+
+    uint uTintR = (uTint >> 16) & 0xFF,
+         uTintG = (uTint >> 8) & 0xFF,
+         uTintB = uTint & 0xFF;
+
+    uint uDecalColorMultR = (pDecal->uColorMultiplier >> 16) & 0xFF,
+         uDecalColorMultG = (pDecal->uColorMultiplier >> 8) & 0xFF,
+         uDecalColorMultB = pDecal->uColorMultiplier & 0xFF;
+
+    uint uFinalR = floorf(uTintR / 255.0 * color_mult * uDecalColorMultR + 0.0f),
+         uFinalG = floorf(uTintG / 255.0 * color_mult * uDecalColorMultG + 0.0f),
+         uFinalB = floorf(uTintB / 255.0 * color_mult * uDecalColorMultB + 0.0f);
+
+
+    float v15;
+    if (fabs(z_bias) < 1e-5)
+      v15 = 1.0 - 1.0 / ((1.0f / get_shading_dist_mist()) * pDecal->pVertices[i].vWorldViewPosition.x * 1000.0);
+     else
+     {
+      v15 = 1.0 - 1.0 / ((1.0f / get_shading_dist_mist()) * pDecal->pVertices[i].vWorldViewPosition.x * 1000.0) - z_bias;
+      if (v15 < 0.000099999997)
+        v15 = 0.000099999997;
+     }
+
+    pVerticesD3D[i].pos.z = v15;
+
+    pVerticesD3D[i].pos.x = pDecal->pVertices[i].vWorldViewProjX;
+    pVerticesD3D[i].pos.y = pDecal->pVertices[i].vWorldViewProjY;
+    pVerticesD3D[i].texcoord.x = pDecal->pVertices[i].u;
+    pVerticesD3D[i].texcoord.y = pDecal->pVertices[i].v;
+    pVerticesD3D[i].diffuse = (uFinalR << 16) | (uFinalG << 8) | uFinalB;
+    pVerticesD3D[i].specular = 0;
+    pVerticesD3D[i].rhw = 1.0 / pDecal->pVertices[i].vWorldViewPosition.x;
+  }
+
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    v21 = D3DDP_DONOTLIGHT | D3DDP_DONOTCLIP | D3DDP_DONOTUPDATEEXTENTS;
+  else
+    v21 = D3DDP_DONOTLIGHT;
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+            pVerticesD3D,
+            pDecal->uNumVertices,
+            v21));
+}
+
+//----- (0049C2CD) --------------------------------------------------------
+void DecalBuilder::DrawDecals(float z_bias)
+{
+  for (uint i = 0; i < std__vector_pDecals_size; ++i)
+    DrawDecal(std__vector_pDecals + i, z_bias);
+}
+
+//----- (0049C304) --------------------------------------------------------
+void DecalBuilder::DrawBloodsplats()
+{
+  if (!std__vector_pDecals_size)
+    return;
+
+  if (pRenderer->bUsingSpecular)
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 3));
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 0));
+
+  auto pTex = pGame->pIndoorCameraD3D->LoadTextureAndGetHardwarePtr("hwsplat04");
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, pTex));
+ 
+  DrawDecals(0.00039999999);
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+
+  if (pRenderer->bUsingSpecular)
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1u));
+}
+
+//----- (0049C550) --------------------------------------------------------
+void DecalBuilder::DrawDecalDebugOutlines()
+{
+  DecalBuilder *v1; // esi@1
+  signed int v2; // ebx@1
+  RenderVertexSoft *v3; // edi@2
+
+  v1 = this;
+  v2 = 0;
+  if ( (signed int)this->std__vector_pDecals_size > 0 )
+  {
+    v3 = this->std__vector_pDecals[0].pVertices;
+    do
+    {
+      pGame->pIndoorCameraD3D->debug_outline_sw(v3, *((int *)v3 - 1), 0xC86400u, 0.0);
+      ++v2;
+      v3 = (RenderVertexSoft *)((char *)v3 + 3104);
+    }
+    while ( v2 < (signed int)v1->std__vector_pDecals_size );
+  }
+}
+
+//----- (0040E4C2) --------------------------------------------------------
+void Decal::Decal_base_ctor()
+{
+  uNumVertices = -1;
+  for (uint i = 0; i < 64; ++i)
+    pVertices[i].flt_2C = 0.0f;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DecalBuilder.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,206 @@
+#pragma once
+#include "Render.h"
+
+
+#pragma pack(push, 1)
+struct DecalBuilder_stru0
+{
+  double _43B570_get_color_mult_by_time();
+
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C_flags;
+  __int64 field_20_time;
+};
+#pragma pack(pop)
+
+
+
+/*  181 */
+#pragma pack(push, 1)
+struct Decal
+{
+  void Decal_base_ctor();
+  //----- (0043B60C) --------------------------------------------------------
+  inline Decal()
+  {
+    Decal_base_ctor();
+    field_C1C = 0;
+  }
+
+  //----- (0043B625) --------------------------------------------------------
+  //void __thiscall Decal::vdtor(Decal *this, bool a2)
+  //----- (0043B641) --------------------------------------------------------
+  virtual ~Decal()
+  {
+  }
+
+  void (__thiscall ***vdestructor_ptr)(Decal *, bool);
+  int uNumVertices;
+  RenderVertexSoft pVertices[64];
+  __int16 field_C08;
+  __int16 field_C0A;
+  __int16 field_C0C;
+  __int16 field_C0E;
+  uint uColorMultiplier;
+  int field_C14;
+  DecalBuilder_stru0 *field_C18;
+  int field_C1C;
+};
+#pragma pack(pop)
+
+/*  180 */
+#pragma pack(push, 1)
+struct DecalBuilder
+{
+  //----- (0049B408) --------------------------------------------------------
+  DecalBuilder()
+  {
+    char *v2; // eax@1
+    signed int v3; // ecx@1
+
+    auto v1 = this;
+    /*_eh_vector_constructor_iterator_(
+    this->std__vector_pDecals,
+    3104,
+    1024,
+    (void (__thiscall *)(void *))Decal::Decal,
+    (void (__thiscall *)(void *))Decal::dtor);*/
+  v1->std__vector_pDecals_size = 0;
+  v1->field_308008 = 0;
+  v2 = (char *)&v1->pVertices[0].flt_2C;
+  v3 = 256;
+  do
+  {
+    *(float *)v2 = 0.0;
+    v2 += 48;
+    --v3;
+  }
+  while ( v3 );
+  }
+
+  //----- (0049B471) --------------------------------------------------------
+  virtual ~DecalBuilder()
+  {}
+
+
+  bool AddBloodsplat(float x, float y, float z, float r, float g, float b, float radius, int a8, int a9);
+  void Reset(unsigned int bPreserveBloodsplats);
+  char ApplyDecals(int a2, char a3, struct stru154 *a4, int a5, struct RenderVertexSoft *a6, struct IndoorCameraD3D_Vec4 *a7, char a8, unsigned int uSectorID);
+  char _49B790_build_decal_geometry(int a2, char a3, int a4, int a5, int a6, unsigned int uColorMultiplier, struct RenderVertexSoft *a8, struct stru314 *a9, signed int a10, struct RenderVertexSoft *a11, char uClipFlags);
+  bool ApplyBloodsplatDecals_IndoorFace(unsigned int uFaceID);
+  char ApplyDecals_OutdoorFace(ODMFace *pFace);
+  bool _49BE8A(struct stru148 *a2, float a3, int a4, struct RenderVertexSoft *a5, unsigned int uStripType, char a7);
+  void DrawDecal(Decal *pDecal, float z_bias);
+  void DrawDecals(float z_bias);
+  void DrawBloodsplats();
+  void DrawDecalDebugOutlines();
+
+
+
+  void (__thiscall ***vdestructor_ptr)(DecalBuilder *, bool);
+  Decal std__vector_pDecals[1024];
+  unsigned int std__vector_pDecals_size;
+  int field_308008;
+  RenderVertexSoft pVertices[256];
+  int std__vector_30B00C[1024];
+  int uNumDecals;
+  float field_30C010;
+  float field_30C014;
+  float field_30C018;
+  float field_30C01C;
+  float field_30C020;
+  float field_30C024;
+  int field_30C028;
+  int field_30C02C;
+  float flt_30C030;
+  float field_30C034;
+};
+#pragma pack(pop)
+
+extern struct DecalBuilder *pDecalBuilder;
+
+
+
+
+
+/*  158 */
+#pragma pack(push, 1)
+struct Bloodsplat
+{
+  //----- (0043B538) --------------------------------------------------------
+  inline Bloodsplat()
+  {
+    this->field_1C = 0;
+    this->field_20 = 0;
+    this->field_24 = 0;
+    //this->vdestructor_ptr = &Bloodsplat_pvdtor;
+  }
+
+  //----- (0043B54C) --------------------------------------------------------
+  //void __thiscall Bloodsplat::vdtor(Bloodsplat *this, char a2)
+
+  //----- (0043B569) --------------------------------------------------------
+  virtual ~Bloodsplat()
+  {
+  }
+
+  void (__thiscall ***vdestructor_ptr)(Bloodsplat *, bool);
+  float x;
+  float y;
+  float z;
+  float radius;
+  float dot_dist;
+  char r;
+  char g;
+  char b;
+  char field_1B;
+  int field_1C;
+  int field_20;
+  int field_24;
+};
+#pragma pack(pop)
+
+/*  159 */
+#pragma pack(push, 1)
+struct BloodsplatContainer
+{
+  //----- (0043B688) --------------------------------------------------------
+  inline BloodsplatContainer()
+  {
+  /*_eh_vector_constructor_iterator_(
+    this->std__vector_pBloodsplats,
+    40,
+    64,
+    (void (__thiscall *)(void *))Bloodsplat::Bloodsplat,
+    (void (__thiscall *)(void *))Bloodsplat::dtor);
+  v1->std__vector_pBloodsplats_size = 0;*/
+    uNumBloodsplats = 0;
+  }
+  //----- (0043B6D6) --------------------------------------------------------
+  virtual ~BloodsplatContainer()
+  {
+    //this->vdestructor_ptr = &BloodsplatContainer_pvdtor;
+    //_eh_vector_destructor_iterator_(this->std__vector_pBloodsplats, 40, 64, Bloodsplat::dtor);
+  }
+
+
+  bool AddBloodsplat(float x, float y, float z, float r, float g, float b, float radius, int a8, int a9);
+  bool AddBloodsplat(float x, float y, float z, float radius, char r, char g, char b);
+
+
+  void (__thiscall ***vdestructor_ptr)(BloodsplatContainer *, bool);
+  Bloodsplat std__vector_pBloodsplats[64];
+  unsigned int std__vector_pBloodsplats_size;
+  int uNumBloodsplats;
+};
+#pragma pack(pop)
+
+
+
+extern struct BloodsplatContainer *pBloodsplatContainer; // idb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DecorationList.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,65 @@
+#pragma once
+
+
+
+
+/*  321 */
+enum DECORATION_FLAGS
+{
+  DECORATION_MOVE_THROUGH = 0x1,
+  DECORATION_DONT_DRAW = 0x2,
+  DECORATION_FLICKER_SLOW = 0x4,
+  DECORATION_FICKER_AVERAGE = 0x8,
+  DECORATION_FICKER_FAST = 0x10,
+  DECORATION_MARKER = 0x20,
+  DECORATION_SLOW_LOOP = 0x40,
+  DECORATION_EMITS_FIRE = 0x80,
+  DECORATION_SOUND_ON_DAWN = 0x100,
+  DECORATION_SOUND_ON_DUSK = 0x200,
+  DECORATION_EMITS_SMOKE = 0x400,
+};
+
+
+
+/*   54 */
+#pragma pack(push, 1)
+struct DecorationDesc
+{
+  char pName[32];
+  char field_20[32];
+  __int16 uType;
+  unsigned __int16 uDecorationHeight;
+  __int16 uRadius;
+  __int16 uLightRadius;
+  unsigned __int16 uSpriteID;
+  __int16 uFlags;
+  __int16 uSoundID;
+  __int16 _pad;
+  unsigned __int8 uColoredLightRed;
+  unsigned __int8 uColoredLightGreen;
+  unsigned __int8 uColoredLightBlue;
+  char __padding;
+};
+#pragma pack(pop)
+
+/*   55 */
+#pragma pack(push, 1)
+struct DecorationList
+{
+  inline DecorationList():   //----- (00458380)
+    pDecorations(nullptr), uNumDecorations(0)
+  {}
+
+  void ToFile();
+  void FromFile(void *pSerialized);
+  bool FromFileTxt(const char *Args);
+  void InitializeDecorationSprite(unsigned int uDecID);
+  unsigned __int16 GetDecorIdByName(const char *pName);
+
+  unsigned int uNumDecorations;
+  struct DecorationDesc *pDecorations;
+};
+#pragma pack(pop)
+
+
+extern struct DecorationList *pDecorationList;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Events.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,28 @@
+#include "Events.h"
+#include "Events2D.h"
+
+
+
+Event pSomeOtherEVT_Events[4400];
+unsigned int uSomeOtherEVT_NumEvents;
+char *pSomeOtherEVT;
+Event pSomeEVT_Events[4400];
+unsigned int uSomeEVT_NumEvents;
+char *pSomeEVT;
+
+unsigned int uGlobalEVT_NumEvents;
+unsigned int uGlobalEVT_Size;
+char pGlobalEVT[46080];
+Event pGlobalEVT_Events[4400];
+
+unsigned int pLevelStrOffsets[500];
+unsigned int uLevelStrNumStrings;
+unsigned int uLevelStrFileSize;
+unsigned int uLevelEVT_NumEvents;
+unsigned int uLevelEVT_Size;
+char pLevelStr[9216];
+char pLevelEVT[9216];
+Event pLevelEVT_Events[4400];
+
+
+_2devent p2DEvents[525]; // weak
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Events.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,325 @@
+#pragma once
+
+
+
+
+/*  167 */
+#pragma pack(push, 1)
+struct Event
+{
+  int uEventID;
+  int field_4;
+  unsigned int uEventOffsetInEVT;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct _evt_raw
+{
+  unsigned char v0;
+  unsigned char v1;
+  unsigned char v2;
+  unsigned char v3;
+  unsigned char v4;
+  unsigned char v5;
+  unsigned char v6;
+  unsigned char v7;
+  unsigned char v8;
+  unsigned char v9;
+  unsigned char v10;
+  unsigned char v11;
+  unsigned char v12;
+  unsigned char v13;
+  unsigned char v14;
+  unsigned char v15;
+  unsigned char v16;
+  unsigned char v17;
+  unsigned char v18;
+  unsigned char v19;
+  unsigned char v20;
+  unsigned char v21;
+  unsigned char v22;
+  unsigned char v23;
+  unsigned char v24;
+  unsigned char v25;
+  unsigned char v26;
+  unsigned char v27;
+  unsigned char v28;
+  unsigned char v29;
+  unsigned char v30;
+  unsigned char v31;
+  unsigned char v32;
+  unsigned char tail[128];
+};
+#pragma pop()
+
+
+
+/*  310 */
+enum EventType
+{
+  EVENT_Exit = 0x1,
+  EVENT_SpeakInHouse = 0x2,
+  EVENT_PlaySound = 0x3,
+  EVENT_MouseOver = 0x4,
+  EVENT_LocationName = 0x5,
+  EVENT_MoveToMap = 0x6,
+  EVENT_OpenChest = 0x7,
+  EVENT_ShowFace = 0x8,
+  EVENT_ReceiveDamage = 0x9,
+  EVENT_SetSnow = 0xA,
+  EVENT_SetTexture = 0xB,
+  EVENT_ShowMovie = 0xC,
+  EVENT_SetSprite = 0xD,
+  EVENT_Compare = 0xE,
+  EVENT_ChangeDoorState = 0xF,
+  EVENT_Add = 0x10,
+  EVENT_Substract = 0x11,
+  EVENT_Set = 0x12,
+  EVENT_SummonMonsters = 0x13,
+  EVENT_CastSpell = 0x15,
+  EVENT_SpeakNPC = 0x16,
+  EVENT_SetFacesBit = 0x17,
+  EVENT_ToggleActorFlag = 0x18,
+  EVENT_RandomGoTo = 0x19,
+  EVENT_InputString = 0x1A,
+  EVENT_StatusText = 0x1D,
+  EVENT_ShowMessage = 0x1E,
+  EVENT_OnTimer = 0x1F,
+  EVENT_ToggleIndoorLight = 0x20,
+  EVENT_PressAnyKey = 0x21,
+  EVENT_SummonItem = 0x22,
+  EVENT_ForPartyMember = 0x23,
+  EVENT_Jmp = 0x24,
+  EVENT_OnMapReload = 0x25,
+  EVENT_OnLongTimer = 0x26,
+  EVENT_SetNPCTopic = 0x27,
+  EVENT_MoveNPC = 0x28,
+  EVENT_GiveItem = 0x29,
+  EVENT_ChangeEvent = 0x2A,
+  EVENT_CheckSkill = 0x2B,
+  EVENT_OnCanShowDialogItemCmp = 0x2C,
+  EVENT_EndCanShowDialogItem = 0x2D,
+  EVENT_SetCanShowDialogItem = 0x2E,
+  EVENT_SetNPCGroupNews = 0x2F,
+  EVENT_SetActorGroup = 0x30,
+  EVENT_NPCSetItem = 0x31,
+  EVENT_SetNPCGreeting = 0x32,
+  EVENT_IsActorAlive = 0x33,
+  EVENT_OnMapLeave = 0x35,
+  EVENT_ChangeGroup = 0x36,
+  EVENT_ChangeGroupAlly = 0x37,
+  EVENT_CheckSeason = 0x38,
+  EVENT_ToggleActorGroupFlag = 0x39,
+  EVENT_ToggleChestFlag = 0x3A,
+  EVENT_CharacterAnimation = 0x3B,
+  EVENT_SetActorItem = 0x3C,
+  EVENT_OnDateTimer = 0x3D,
+  EVENT_EnableDateTimer = 0x3E,
+  EVENT_StopAnimation = 0x3F,
+  EVENT_CheckItemsCount = 0x40,
+  EVENT_RemoveItems = 0x41,
+  EVENT_SpecialJump = 0x42,
+  EVENT_IsTotalBountyHuntingAwardInRange = 0x43,
+  EVENT_IsNPCInParty = 0x44,
+};
+
+/*  311 */
+enum VariableType
+{
+  VAR_Sex = 0x1,
+  VAR_Class = 0x2,
+  VAR_CurrentHP = 0x3,
+  VAR_MaxHP = 0x4,
+  VAR_CurrentSP = 0x5,
+  VAR_MaxSP = 0x6,
+  VAR_ActualAC = 0x7,
+  VAR_ACModifier = 0x8,
+  VAR_BaseLevel = 0x9,
+  VAR_LevelModifier = 0xA,
+  VAR_Age = 0xB,
+  VAR_Award = 0xC,
+  VAR_Experience = 0xD,
+  VAR_Race = 0xE,
+  VAR_QBits_QuestsDone = 0x10,
+  VAR_PlayerItemInHands = 0x11,
+  VAR_Hour = 0x12,
+  VAR_DayOfYear = 0x13,
+  VAR_DayOfWeek = 0x14,
+  VAR_FixedGold = 0x15,
+  VAR_RandomGold = 0x16,
+  VAR_FixedFood = 0x17,
+  VAR_RandomFood = 0x18,
+  VAR_MightBonus = 0x19,
+  VAR_IntellectBonus = 0x1A,
+  VAR_PersonalityBonus = 0x1B,
+  VAR_EnduranceBonus = 0x1C,
+  VAR_SpeedBonus = 0x1D,
+  VAR_AccuracyBonus = 0x1E,
+  VAR_LuckBonus = 0x1F,
+  VAR_BaseMight = 0x20,
+  VAR_BaseIntellect = 0x21,
+  VAR_BasePersonality = 0x22,
+  VAR_BaseEndurance = 0x23,
+  VAR_BaseSpeed = 0x24,
+  VAR_BaseAccuracy = 0x25,
+  VAR_BaseLuck = 0x26,
+  VAR_ActualMight = 0x27,
+  VAR_ActualIntellect = 0x28,
+  VAR_ActualPersonality = 0x29,
+  VAR_ActualEndurance = 0x2A,
+  VAR_ActualSpeed = 0x2B,
+  VAR_ActualAccuracy = 0x2C,
+  VAR_ActualLuck = 0x2D,
+  VAR_FireResistance = 0x2E,
+  VAR_AirResistance = 0x2F,
+  VAR_WaterResistance = 0x30,
+  VAR_EarthResistance = 0x31,
+  VAR_SpiritResistance = 0x32,
+  VAR_MindResistance = 0x33,
+  VAR_BodyResistance = 0x34,
+  VAR_LightResistance = 0x35,
+  VAR_DarkResistance = 0x36,
+  VAR_PhysicalResistance = 0x37,
+  VAR_MagicResistance = 0x38,
+  VAR_FireResistanceBonus = 0x39,
+  VAR_AirResistanceBonus = 0x3A,
+  VAR_WaterResistanceBonus = 0x3B,
+  VAR_EarthResistanceBonus = 0x3C,
+  VAR_SpiritResistanceBonus = 0x3D,
+  VAR_MindResistanceBonus = 0x3E,
+  VAR_BodyResistanceBonus = 0x3F,
+  VAR_LightResistanceBonus = 0x40,
+  VAR_DarkResistanceBonus = 0x41,
+  VAR_PhysicalResistanceBonus = 0x42,
+  VAR_MagicResistanceBonus = 0x43,
+  VAR_StaffSkill = 0x44,
+  VAR_SwordSkill = 0x45,
+  VAR_DaggerSkill = 0x46,
+  VAR_AxeSkill = 0x47,
+  VAR_SpearSkill = 0x48,
+  VAR_BowSkill = 0x49,
+  VAR_MaceSkill = 0x4A,
+  VAR_BlasterSkill = 0x4B,
+  VAR_ShieldSkill = 0x4C,
+  VAR_LeatherSkill = 0x4D,
+  VAR_SkillChain = 0x4E,
+  VAR_PlateSkill = 0x4F,
+  VAR_FireSkill = 0x50,
+  VAR_AirSkill = 0x51,
+  VAR_WaterSkill = 0x52,
+  VAR_EarthSkill = 0x53,
+  VAR_SpiritSkill = 0x54,
+  VAR_MindSkill = 0x55,
+  VAR_BodySkill = 0x56,
+  VAR_LightSkill = 0x57,
+  VAR_DarkSkill = 0x58,
+  VAR_IdentifyItemSkill = 0x59,
+  VAR_MerchantSkill = 0x5A,
+  VAR_RepairSkill = 0x5B,
+  VAR_BodybuildingSkill = 0x5C,
+  VAR_MeditationSkill = 0x5D,
+  VAR_PerceptionSkill = 0x5E,
+  VAR_DiplomacySkill = 0x5F,
+  VAR_ThieverySkill = 0x60,
+  VAR_DisarmTrapSkill = 0x61,
+  VAR_DodgeSkill = 0x62,
+  VAR_UnarmedSkill = 0x63,
+  VAR_IdentifyMonsterSkill = 0x64,
+  VAR_ArmsmasterSkill = 0x65,
+  VAR_StealingSkill = 0x66,
+  VAR_AlchemySkill = 0x67,
+  VAR_LearningSkill = 0x68,
+  VAR_Cursed = 0x69,
+  VAR_Weak = 0x6A,
+  VAR_Asleep = 0x6B,
+  VAR_Afraid = 0x6C,
+  VAR_Drunk = 0x6D,
+  VAR_Insane = 0x6E,
+  VAR_PoisonedGreen = 0x6F,
+  VAR_DiseasedGreen = 0x70,
+  VAR_PoisonedYellow = 0x71,
+  VAR_DiseasedYellow = 0x72,
+  VAR_PoisonedRed = 0x73,
+  VAR_DiseasedRed = 0x74,
+  VAR_Paralyzed = 0x75,
+  VAR_Unconsious = 0x76,
+  VAR_Dead = 0x77,
+  VAR_Stoned = 0x78,
+  VAR_Eradicated = 0x79,
+  VAR_MajorCondition = 0x7A,
+  VAR_MapPersistentVariable_0 = 0x7B,
+  VAR_NPCs = 0xD6,
+  VAR_Reputation = 0xD7,
+  VAR_ActiveSpells = 0xDE,
+  VAR_AutoNotes = 0xDF,
+  VAR_MonthEquals = 0xE2,
+  VAR_NPCs2 = 0xE8,
+  VAR_IsFlying = 0xF0,
+  VAR_HiredNPCHasSpeciality = 0xF1,
+  VAR_CircusPrises = 0xF2,
+  VAR_NumSkillPoints = 0xF3,
+  VAR_MonthEquals2 = 0xF4,
+  VAR_Counter1 = 0xF7,
+  VAR_Counter2 = 0xF8,
+  VAR_Counter3 = 0xF9,
+  VAR_Counter4 = 0xFA,
+  VAR_Counter5 = 0xFB,
+  VAR_Counter6 = 0xFC,
+  VAR_Counter7 = 0xFD,
+  VAR_Counter8 = 0xFE,
+  VAR_Counter9 = 0xFF,
+  VAR_CounterA = 0x100,
+  VAR_ReputationInCurrentLocation = 0x113,
+  VAR_History_0 = 0x114,
+  VAR_History_28 = 0x130,
+  VAR_GoldInBank = 0x132,
+  VAR_NumDeaths = 0x133,
+  VAR_NumBounties = 0x134,
+  VAR_PrisonTerms = 0x135,
+  VAR_ArenaWinsPage = 0x136,
+  VAR_ArenaWinsSquire = 0x137,
+  VAR_ArenaWinsKnight = 0x138,
+  VAR_ArenaWinsLord = 0x139,
+  VAR_Invisible = 0x13A,
+  VAR_ItemEquipped = 0x13B,
+};
+
+
+
+
+extern Event pSomeOtherEVT_Events[4400];
+extern unsigned int uSomeOtherEVT_NumEvents;
+extern char *pSomeOtherEVT;
+extern Event pSomeEVT_Events[4400];
+extern unsigned int uSomeEVT_NumEvents;
+extern char *pSomeEVT;
+
+extern unsigned int uGlobalEVT_NumEvents;
+extern unsigned int uGlobalEVT_Size;
+extern char pGlobalEVT[46080];
+extern Event pGlobalEVT_Events[4400];
+
+extern unsigned int pLevelStrOffsets[500];
+extern unsigned int uLevelStrNumStrings;
+extern unsigned int uLevelStrFileSize;
+extern unsigned int uLevelEVT_NumEvents;
+extern unsigned int uLevelEVT_Size;
+extern char pLevelStr[9216];
+extern char pLevelEVT[9216];
+extern Event pLevelEVT_Events[4400];
+
+
+
+
+
+
+
+/*  312 */
+#pragma pack(push, 1)
+struct ByteArray
+{
+  char f[65535];
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Events2D.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,33 @@
+#pragma once
+
+
+
+/*  168 */
+#pragma pack(push, 1)
+struct _2devent
+{
+  unsigned __int16 uType;
+  unsigned __int16 uAnimationID;
+  char *pName;
+  const char *pProprieterName;
+  const char *pEnterText;
+  const char *pProprieterTitle;
+  __int16 field_14;
+  __int16 _state;
+  __int16 _rep;
+  __int16 _per;
+  __int16 field_1C;
+  __int16 field_1E;
+  float fPriceMultiplier;
+  float flt_24;
+  unsigned __int16 uOpenTime;
+  unsigned __int16 uCloseTime;
+  __int16 uExitPicID;
+  __int16 uExitMapID;
+  __int16 _quest_related;
+  __int16 field_32;
+};
+#pragma pack(pop)
+
+
+extern _2devent p2DEvents[525]; // weak
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FactionTable.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,12 @@
+#pragma once
+
+
+/*  174 */
+#pragma pack(push, 1)
+struct FactionTable
+{
+  void Initialize();
+
+  char relations[89][89];
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameTableInc.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,3 @@
+#include "FrameTableInc.h"
+struct FrameTableTxtLine stru_F8B5E8; // weak
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameTableInc.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,26 @@
+#pragma once
+
+
+
+/*  322 */
+enum FRAME_TABLE_FLAGS
+{
+  FRAME_TABLE_MORE_FRAMES = 0x1,
+  FRAME_TABLE_FIRST = 0x4,
+};
+
+
+
+/*  359 */
+#pragma pack(push, 1)
+struct FrameTableTxtLine
+{
+  int field_0;
+  const char *pProperties[13];
+  const char *pProperties2[16];
+  int field_78;
+};
+#pragma pack(pop)
+
+
+FrameTableTxtLine *texture_frame_table_txt_parser(const char *_this, FrameTableTxtLine *a2);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUIButton.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,179 @@
+#include "GUIButton.h"
+#include "GUIWindow.h"
+#include "GUIFont.h"
+#include "Allocator.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+struct GUIButton *pBtn_CloseBook;
+struct GUIButton *pBtn_InstallRemoveSpell;
+struct GUIButton *pBtn_Autonotes_Instructors;
+struct GUIButton *pBtn_Autonotes_Misc;
+struct GUIButton *pBtn_Book_6;
+struct GUIButton *pBtn_Book_5;
+struct GUIButton *pBtn_Book_4;
+struct GUIButton *pBtn_Book_3;
+struct GUIButton *pBtn_Book_2;
+struct GUIButton *pBtn_Book_1;
+
+
+struct GUIButton *pPlayerCreationUI_BtnReset;
+struct GUIButton *pPlayerCreationUI_BtnOK;
+struct GUIButton *pBtn_ExitCancel;
+struct GUIButton *pBtn_YES;
+struct GUIButton *pPlayerCreationUI_BtnPlus;
+struct GUIButton *pPlayerCreationUI_BtnMinus;
+
+
+struct GUIButton *pButton_RestUI_Main;
+struct GUIButton *pButton_RestUI_Exit;
+struct GUIButton *pButton_RestUI_Wait5Minutes;
+struct GUIButton *pButton_RestUI_WaitUntilDawn;
+struct GUIButton *pButton_RestUI_Wait1Hour;
+
+
+struct GUIButton *pCharacterScreen_ExitBtn;
+struct GUIButton *pCharacterScreen_AwardsBtn;
+struct GUIButton *pCharacterScreen_InventoryBtn;
+struct GUIButton *pCharacterScreen_SkillsBtn;
+struct GUIButton *pCharacterScreen_StatsBtn;
+struct GUIButton *pCharacterScreen_DollBtn;
+struct GUIButton *pCharacterScreen_DetalizBtn;
+
+
+struct GUIButton *pBtn_NPCRight;
+struct GUIButton *pBtn_NPCLeft;
+struct GUIButton *pBtn_GameSettings;
+struct GUIButton *pBtn_QuickReference;
+struct GUIButton *pBtn_CastSpell;
+struct GUIButton *pBtn_Rest;
+struct GUIButton *pBtn_History;
+struct GUIButton *pBtn_Calendar;
+struct GUIButton *pBtn_Maps;
+struct GUIButton *pBtn_Autonotes;
+struct GUIButton *pBtn_Quests;
+
+
+struct GUIButton *pMainMenu_BtnExit;
+struct GUIButton *pMainMenu_BtnCredits;
+struct GUIButton *pMainMenu_BtnLoad;
+struct GUIButton *pMainMenu_BtnNew;
+
+
+struct GUIButton *pBtn_Up;
+struct GUIButton *pBtn_Down;
+struct GUIButton *ptr_507BA4;
+
+
+struct GUIWindow *pPrimaryWindow;
+struct GUIWindow *pChestWindow;
+struct GUIWindow *pDialogueWindow;
+struct GUIWindow *ptr_507BC0;
+struct GUIWindow *pGUIWindow_ScrollWindow;
+struct GUIWindow *ptr_507BC8;
+struct GUIWindow *pGUIWindow_CurrentMenu;
+struct GUIWindow *ptr_507BD0;
+struct GUIWindow *pGUIWindow_Settings;
+struct GUIWindow *ptr_507BDC;
+struct GUIWindow *pGUIWindow_EscMessageWindow;
+struct GUIWindow *pBooksWindow;
+struct GUIWindow *pGUIWindow2;
+
+
+struct GUIButton *pBtn_Resume;
+struct GUIButton *pBtn_QuitGame;
+struct GUIButton *pBtn_GameControls;
+struct GUIButton *pBtn_LoadGame;
+struct GUIButton *pBtn_SaveGame;
+struct GUIButton *pBtn_NewGame;
+
+struct GUIButton *pBtn_SliderRight;
+struct GUIButton *pBtn_SliderLeft;
+
+
+struct GUIButton *ptr_69BD58;
+struct GUIButton *ptr_69BD5C;
+struct GUIButton *ptr_69BD60;
+struct GUIButton *ptr_69BD64;
+
+
+GUIButton *pCreationUI_BtnPressRight2[4];
+GUIButton *pCreationUI_BtnPressLeft2[4];
+GUIButton *pCreationUI_BtnPressLeft[4];
+GUIButton *pCreationUI_BtnPressRight[4];
+
+
+
+
+
+
+//----- (0041D0D8) --------------------------------------------------------
+void GUIButton::_41D0D8(GUIButton *ptr)
+{
+  GUIWindow *v1; // eax@2
+  GUIButton *v2; // edx@2
+  GUIButton *v3; // eax@6
+
+  if ( ptr )
+  {
+    v1 = ptr->pParent;
+    v2 = ptr->pNext;
+    if ( ptr == v1->pControlsHead )
+    {
+      if ( v2 )
+      {
+        v1->pControlsHead = v2;
+        ptr->pNext->pPrev = 0;
+      }
+      else
+      {
+        v1->pControlsHead = 0;
+        ptr->pParent->pControlsTail = 0;
+      }
+    }
+    else
+    {
+      v3 = ptr->pPrev;
+      if ( v2 )
+      {
+        v3->pNext = v2;
+        ptr->pNext->pPrev = v3;
+      }
+      else
+      {
+        v3->pNext = 0;
+        ptr->pParent->pControlsTail = v3;
+      }
+    }
+    --ptr->pParent->uNumControls;
+    pAllocator->FreeChunk(ptr);
+  }
+}
+
+
+//----- (00415180) --------------------------------------------------------
+char GUIButton::DrawLabel(const char *edx0, GUIFont *pFont, int a5, int *a9)
+{
+  const char *v5; // ebx@1
+  GUIButton *v6; // esi@1
+  int v7; // eax@1
+
+  v5 = edx0;
+  v6 = this;
+  //strlen(edx0);
+  v7 = pFont->GetLineWidth(edx0);
+  return pParent->DrawText(
+           pFont,
+           v6->uX + (signed int)(v6->uWidth - v7) / 2,
+           v6->uY + (signed int)(v6->uHeight - LOBYTE(pFont->uFontHeight)) / 2,
+           a5,
+           v5,
+           0,
+           0,
+           (unsigned int)a9);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUIButton.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,134 @@
+#pragma once
+
+
+/*  156 */
+#pragma pack(push, 1)
+struct GUIButton
+{
+  char DrawLabel(const char *edx0, struct GUIFont *pFont, int a5, int *a9);
+
+  static void _41D0D8(GUIButton *ptr);
+
+
+  unsigned int uX;
+  unsigned int uY;
+  unsigned int uWidth;
+  unsigned int uHeight;
+  unsigned int uZ;
+  unsigned int uW;
+  int uButtonType;
+  int field_1C;
+  unsigned int uControlID;
+  unsigned int uControlParam;
+  int field_28;
+  int field_2C;
+  GUIButton *pPrev;
+  GUIButton *pNext;
+  struct GUIWindow *pParent;
+  struct Texture *pTextures[5];
+  unsigned int uNumTextures;
+  unsigned __int8 uHotkey;
+  char pButtonName[32];
+  char field_75[71];
+};
+#pragma pack(pop)
+
+
+
+
+extern struct GUIButton *pBtn_CloseBook;
+extern struct GUIButton *pBtn_InstallRemoveSpell;
+extern struct GUIButton *pBtn_Autonotes_Instructors;
+extern struct GUIButton *pBtn_Autonotes_Misc;
+extern struct GUIButton *pBtn_Book_6;
+extern struct GUIButton *pBtn_Book_5;
+extern struct GUIButton *pBtn_Book_4;
+extern struct GUIButton *pBtn_Book_3;
+extern struct GUIButton *pBtn_Book_2;
+extern struct GUIButton *pBtn_Book_1;
+
+
+extern struct GUIButton *pPlayerCreationUI_BtnReset;
+extern struct GUIButton *pPlayerCreationUI_BtnOK;
+extern struct GUIButton *pBtn_ExitCancel;
+extern struct GUIButton *pBtn_YES;
+extern struct GUIButton *pPlayerCreationUI_BtnPlus;
+extern struct GUIButton *pPlayerCreationUI_BtnMinus;
+
+
+extern struct GUIButton *pButton_RestUI_Main;
+extern struct GUIButton *pButton_RestUI_Exit;
+extern struct GUIButton *pButton_RestUI_Wait5Minutes;
+extern struct GUIButton *pButton_RestUI_WaitUntilDawn;
+extern struct GUIButton *pButton_RestUI_Wait1Hour;
+
+
+extern struct GUIButton *pCharacterScreen_ExitBtn;
+extern struct GUIButton *pCharacterScreen_AwardsBtn;
+extern struct GUIButton *pCharacterScreen_InventoryBtn;
+extern struct GUIButton *pCharacterScreen_SkillsBtn;
+extern struct GUIButton *pCharacterScreen_StatsBtn;
+extern struct GUIButton *pCharacterScreen_DollBtn;
+extern struct GUIButton *pCharacterScreen_DetalizBtn;
+
+
+extern struct GUIButton *pBtn_NPCRight;
+extern struct GUIButton *pBtn_NPCLeft;
+extern struct GUIButton *pBtn_GameSettings;
+extern struct GUIButton *pBtn_QuickReference;
+extern struct GUIButton *pBtn_CastSpell;
+extern struct GUIButton *pBtn_Rest;
+extern struct GUIButton *pBtn_History;
+extern struct GUIButton *pBtn_Calendar;
+extern struct GUIButton *pBtn_Maps;
+extern struct GUIButton *pBtn_Autonotes;
+extern struct GUIButton *pBtn_Quests;
+
+
+extern struct GUIButton *pMainMenu_BtnExit;
+extern struct GUIButton *pMainMenu_BtnCredits;
+extern struct GUIButton *pMainMenu_BtnLoad;
+extern struct GUIButton *pMainMenu_BtnNew;
+
+
+extern struct GUIButton *pBtn_Up;
+extern struct GUIButton *pBtn_Down;
+extern struct GUIButton *ptr_507BA4;
+
+
+extern struct GUIWindow *pPrimaryWindow;
+extern struct GUIWindow *pChestWindow;
+extern struct GUIWindow *pDialogueWindow;
+extern struct GUIWindow *ptr_507BC0;
+extern struct GUIWindow *pGUIWindow_ScrollWindow;
+extern struct GUIWindow *ptr_507BC8;
+extern struct GUIWindow *pGUIWindow_CurrentMenu;
+extern struct GUIWindow *ptr_507BD0;
+extern struct GUIWindow *pGUIWindow_Settings;
+extern struct GUIWindow *ptr_507BDC;
+extern struct GUIWindow *pGUIWindow_EscMessageWindow;
+extern struct GUIWindow *pBooksWindow;
+extern struct GUIWindow *pGUIWindow2;
+
+
+extern struct GUIButton *pBtn_Resume;
+extern struct GUIButton *pBtn_QuitGame;
+extern struct GUIButton *pBtn_GameControls;
+extern struct GUIButton *pBtn_LoadGame;
+extern struct GUIButton *pBtn_SaveGame;
+extern struct GUIButton *pBtn_NewGame;
+
+extern struct GUIButton *pBtn_SliderRight;
+extern struct GUIButton *pBtn_SliderLeft;
+
+
+extern struct GUIButton *ptr_69BD58;
+extern struct GUIButton *ptr_69BD5C;
+extern struct GUIButton *ptr_69BD60;
+extern struct GUIButton *ptr_69BD64;
+
+
+extern GUIButton *pCreationUI_BtnPressRight2[4];
+extern GUIButton *pCreationUI_BtnPressLeft2[4];
+extern GUIButton *pCreationUI_BtnPressLeft[4];
+extern GUIButton *pCreationUI_BtnPressRight[4];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUIFont.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,689 @@
+#include <string>
+
+#include "GUIFont.h"
+#include "GUIWindow.h"
+#include "Render.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+struct GUIFont *pAutonoteFont;
+struct GUIFont *pSpellFont;
+struct GUIFont *pFontArrus;
+struct GUIFont *pFontLucida;
+struct GUIFont *pBook2Font;
+struct GUIFont *pBookFont;
+struct GUIFont *pFontCreate;
+struct GUIFont *pFontCChar;
+struct GUIFont *pFontComic;
+struct GUIFont *pFontSmallnum;
+
+
+
+
+//----- (0044D2FD) --------------------------------------------------------
+void GUIFont::_44D2FD_prolly_draw_credits_entry(GUIFont *pFont, int Str, int a4, unsigned int w, unsigned int h, unsigned __int16 a7, unsigned __int16 a8, const char *pString, unsigned __int16 *pPixels, unsigned int uPixelsWidth)
+{
+  int v11; // ebx@1
+  int v12; // edi@1
+  char *v13; // eax@1
+  char *v14; // eax@1
+  unsigned __int16 *v15; // esi@1
+  GUIFont *v16; // edi@4
+  signed int v17; // ecx@4
+  signed int v18; // eax@6
+  int v19; // [sp+Ch] [bp-5Ch]@1
+  int v20; // [sp+10h] [bp-58h]@1
+  unsigned int v21; // [sp+14h] [bp-54h]@1
+  unsigned int v22; // [sp+18h] [bp-50h]@1
+  unsigned int v23; // [sp+1Ch] [bp-4Ch]@1
+  unsigned int v24; // [sp+20h] [bp-48h]@1
+  GUIFont *v25; // [sp+60h] [bp-8h]@1
+  GUIFont *v26; // [sp+64h] [bp-4h]@1
+  char *Stra; // [sp+70h] [bp+8h]@1
+  int a4a; // [sp+74h] [bp+Ch]@4
+  int a7a; // [sp+80h] [bp+18h]@2
+
+  v11 = a7;
+  v22 = h;
+  v12 = Str;
+  v26 = this;
+  v24 = a4 + h - 1;
+  v21 = w;
+  v25 = pFont;
+  v23 = Str + w - 1;
+  ui_current_text_color = a7;
+  v19 = Str;
+  v20 = a4;
+  v13 = GUIFont::_44C933(pString, this, pFont, (int)&v19, 0, 1);
+  v14 = strtok(v13, "\n");
+  Stra = v14;
+  v15 = &pPixels[uPixelsWidth * a4];
+  if ( v14 )
+  {
+    a7a = v12 >> 1;
+    while ( 1 )
+    {
+      v16 = v26;
+      ui_current_text_color = v11;
+      v17 = 0;
+      a4a = v11;
+      if ( *v14 == '_' )
+      {
+        v16 = v25;
+        a4a = a8;
+        ui_current_text_color = a8;
+        v17 = 1;
+      }
+      v18 = (signed int)(w - v16->GetLineWidth(&v14[v17])) >> 1;
+      if ( v18 < 0 )
+        v18 = 0;
+      v16->_44D0B5(a4a, a8, (int)&v15[v18 + a7a], Stra, uPixelsWidth);
+      v15 += uPixelsWidth * (LOBYTE(v16->uFontHeight) - 3);
+      Stra = strtok(0, "\n");
+      if ( !Stra )
+        break;
+      v14 = Stra;
+    }
+  }
+}
+// 5C6DB4: using guessed type int ui_current_text_color;
+
+
+//----- (0044D1E7) --------------------------------------------------------
+void GUIFont::DrawTextLine(unsigned int uDefaultColor, signed int uX, signed int uY, const char *Str, int a6)
+{
+  size_t v6; // ebx@1
+  GUIFont *v7; // esi@1
+  signed int v8; // edi@3
+  unsigned __int8 v9; // cl@4
+  int v10; // eax@5
+  int v11; // ecx@5
+  int v12; // ecx@6
+  int v13; // ecx@7
+  int v14; // ecx@9
+  unsigned int v15; // edx@9
+  unsigned __int16 v16; // cx@12
+  unsigned __int8 *v17; // eax@12
+  char Dest; // [sp+Ch] [bp-1Ch]@16
+  char v19; // [sp+11h] [bp-17h]@16
+  size_t v20; // [sp+20h] [bp-8h]@2
+  int v21; // [sp+24h] [bp-4h]@1
+  int uXa; // [sp+30h] [bp+8h]@9
+
+  v6 = 0;
+  v21 = uDefaultColor;
+  v7 = this;
+  if ( Str )
+  {
+    v21 = ui_current_text_color;
+    v20 = strlen(Str);
+    if ( (signed int)v20 > 0 )
+    {
+      v8 = uX;
+      do
+      {
+        if ( v7->IsCharValid(v9 = Str[v6]) )
+        {
+          v10 = v9;
+          v11 = v9 - 9;
+          if ( v11 )
+          {
+            v12 = v11 - 1;
+            if ( !v12 )
+              return;
+            v13 = v12 - 2;
+            if ( v13 )
+            {
+              if ( v13 != 1 )
+              {
+                v14 = 3 * v10 + 9;
+                v15 = *((int *)&v7->cFirstChar + v14);
+                uXa = *((int *)&v7->cFirstChar + v14);
+                if ( v15 )
+                {
+                  if ( (signed int)v6 > 0 )
+                    v8 += v7->pMetrics[v10].uLeftSpacing;
+                  v16 = v21;
+                  v17 = (unsigned __int8 *)((char *)&v7[1] + v7->field_C20[v10]);
+                  if ( !v21 )
+                    v16 = -1;
+                  pRenderer->DrawText(v8, uY, v17, v15, LOBYTE(v7->uFontHeight), v7->pFontPalettes[0], v16, 0);
+                  v8 += uXa;
+                  if ( (signed int)v6 < (signed int)v20 )
+                    v8 += v7->pMetrics[(unsigned __int8)Str[v6]].uRightSpacing;
+                }
+              }
+            }
+            else
+            {
+              strncpy(&Dest, &Str[v6 + 1], 5u);
+              v19 = 0;
+              v21 = atoi(&Dest);
+              ui_current_text_color = v21;
+              v6 += 5;
+            }
+          }
+        }
+        ++v6;
+      }
+      while ( (signed int)v6 < (signed int)v20 );
+    }
+  }
+}
+// 5C6DB4: using guessed type int ui_current_text_color;
+
+
+//----- (0044D0B5) --------------------------------------------------------
+void GUIFont::_44D0B5(int a2, int a3, int a4, const char *pString, int a6)
+{
+  int v6; // ebx@1
+  GUIFont *v7; // esi@1
+  int v8; // edi@3
+  unsigned __int8 v9; // cl@4
+  int v10; // eax@5
+  int v11; // ecx@5
+  int v12; // ecx@6
+  int v13; // ecx@7
+  int v14; // ecx@8
+  int v15; // ebx@10
+  int v16; // edx@13
+  __int16 v17; // ax@13
+  char Dest; // [sp+Ch] [bp-20h]@17
+  char v19; // [sp+11h] [bp-1Bh]@17
+  size_t v20; // [sp+20h] [bp-Ch]@2
+  int v21; // [sp+24h] [bp-8h]@1
+  int v22; // [sp+28h] [bp-4h]@2
+  const char *v23; // [sp+38h] [bp+Ch]@4
+
+  v6 = 0;
+  v21 = a2;
+  v7 = this;
+  if ( pString )
+  {
+    v21 = ui_current_text_color;
+    v20 = strlen(pString);
+    v22 = 0;
+    if ( (signed int)v20 > 0 )
+    {
+      v8 = a4;
+      do
+      {
+        v23 = &pString[v6];
+        if ( v7->IsCharValid(v9 = pString[v6]) )
+        {
+          v10 = v9;
+          v11 = v9 - 9;
+          if ( v11 )
+          {
+            v12 = v11 - 1;
+            if ( !v12 )
+              return;
+            v13 = v12 - 2;
+            if ( v13 )
+            {
+              v14 = v13 - 1;
+              if ( v14 )
+              {
+                if ( v14 != 82 )
+                {
+                  v15 = *((int *)&v7->cFirstChar + 3 * v10 + 9);
+                  if ( v15 )
+                  {
+                    if ( v22 > 0 )
+                      v8 += 2 * v7->pMetrics[v10].uLeftSpacing;
+                    v16 = (int)((char *)&v7[1] + v7->field_C20[v10]);
+                    v17 = v21;
+                    if ( !v21 )
+                      v17 = -1;
+                    sub_40F845(v8, v16, v15, LOBYTE(v7->uFontHeight), (int)v7->pFontPalettes[0], v17, 2 * a6);
+                    v8 += 2 * v15;
+                    if ( v22 < (signed int)v20 )
+                      v8 += 2 * v7->pMetrics[(unsigned __int8)*v23].uRightSpacing;
+                  }
+                }
+              }
+            }
+            else
+            {
+              strncpy(&Dest, &pString[v6 + 1], 5u);
+              v19 = 0;
+              v21 = atoi(&Dest);
+              ui_current_text_color = v21;
+              v22 = v6 + 5;
+            }
+          }
+        }
+        v6 = v22++ + 1;
+      }
+      while ( v22 < (signed int)v20 );
+    }
+  }
+}
+// 5C6DB4: using guessed type int ui_current_text_color;
+
+
+//----- (0044C933) --------------------------------------------------------
+char *__fastcall GUIFont::_44C933(const char *pString, GUIFont *pFont, GUIFont *a3, int a4, int a5, int a6)
+{
+  const char *v6; // esi@1
+  size_t v8; // eax@3
+  size_t v9; // edi@3
+  int v10; // eax@3
+  GUIFont *v11; // esi@3
+  int v12; // ebx@3
+  char v13; // cl@5
+  int v14; // edx@11
+  int v15; // ecx@11
+  int v16; // edx@12
+  int v17; // edx@13
+  int v18; // edx@14
+  int v19; // edx@15
+  int v20; // edi@17
+  int v21; // edx@17
+  int v22; // ecx@17
+  int v23; // edi@18
+  char v24; // zf@18
+  int v25; // ecx@19
+  int v26; // eax@19
+  char v27; // dl@24
+  int v28; // eax@46
+  std::string v29; // [sp-18h] [bp-48h]@2
+  const char *v30; // [sp-8h] [bp-38h]@2
+  int v31; // [sp-4h] [bp-34h]@2
+  const char *v32; // [sp+Ch] [bp-24h]@1
+  char Str; // [sp+10h] [bp-20h]@46
+  char v34; // [sp+13h] [bp-1Dh]@46
+  GUIFont *v35; // [sp+14h] [bp-1Ch]@1
+  int v36; // [sp+18h] [bp-18h]@3
+  int v37; // [sp+1Ch] [bp-14h]@3
+  int v38; // [sp+20h] [bp-10h]@4
+  int v39; // [sp+24h] [bp-Ch]@3
+  int v40; // [sp+28h] [bp-8h]@3
+  int i; // [sp+2Ch] [bp-4h]@17
+  std::string *v42; // [sp+38h] [bp+8h]@2
+
+  v6 = pString;
+  v35 = pFont;
+  v32 = pString;
+  if ( !pString )
+  {
+    MessageBoxW(nullptr, L"Invalid string passed !", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Font.cpp:558", 0);
+    return 0;
+  }
+  v8 = strlen(pString);
+  v9 = v8;
+  v39 = v8;
+  strcpy(pTmpBuf3, v6);
+  v10 = a5;
+  v11 = v35;
+  v12 = 0;
+  v40 = 0;
+  v37 = a5;
+  v36 = 0;
+  if ( (signed int)v9 > 0 )
+  {
+    v38 = v9 - 1;
+    do
+    {
+      v13 = pTmpBuf3[v12];
+      if ( (unsigned __int8)v13 >= v11->cFirstChar && (unsigned __int8)v13 <= v11->cLastChar
+        || v13 == '\f'
+        || v13 == '\r'
+        || v13 == '\t'
+        || v13 == '\n' )
+      {
+        v14 = (unsigned __int8)v13 - 9;
+        v15 = (int)&v11->pMetrics[(unsigned __int8)v13];
+        if ( v14 )
+        {
+          v16 = v14 - 1;
+          if ( v16 )
+          {
+            v17 = v16 - 2;
+            if ( v17 )
+            {
+              v18 = v17 - 1;
+              if ( v18 )
+              {
+                v19 = v18 - 19;
+                if ( v19 )
+                {
+                  if ( v19 == 63 )
+                  {
+                    v11 = a3;
+                  }
+                  else
+                  {
+                    v20 = *(int *)(v15 + 8);
+                    v21 = *(int *)(v15 + 4);
+                    v22 = *(int *)v15;
+                    i = v20;
+                    if ( (unsigned int)(v10 + v20 + v22 + v21) < *(int *)(a4 + 8) )
+                    {
+                      v12 = v36;
+                      if ( v36 > v40 )
+                        v10 += v22;
+                      v10 += v21;
+                      if ( v36 < v39 )
+                        v10 += i;
+                    }
+                    else
+                    {
+                      v23 = v40;
+                      v24 = v11 == a3;
+                      pTmpBuf3[v40] = 10;
+                      if ( v24 )
+                      {
+                        v25 = v38;
+                        v26 = v23 + 1;
+                        while ( v25 >= v26 )
+                        {
+                          pTmpBuf3[v25] = byte_5C45AF[v25];
+                          --v25;
+                        }
+                        ++v39;
+                        ++v38;
+                        pTmpBuf3[v23++ + 1] = 95;
+                        v40 = v26;
+                      }
+                      v12 = v36;
+                      v10 = v37;
+                      for ( i = v23; i <= v36; ++i )
+                      {
+                        v27 = pTmpBuf3[i];
+                        if ( (unsigned __int8)v27 >= v11->cFirstChar && (unsigned __int8)v27 <= v11->cLastChar
+                          || v27 == 12
+                          || v27 == 13
+                          || v27 == 9
+                          || v27 == 10 )
+                        {
+                          if ( i > v23 )
+                            v10 += v11->pMetrics[(unsigned __int8)v27].uLeftSpacing;
+                          v10 += *((int *)&v11->cFirstChar + 3 * (unsigned __int8)v27 + 9);
+                          if ( i < v36 )
+                            v10 += v11->pMetrics[(unsigned __int8)v27].uRightSpacing;
+                        }
+                      }
+                    }
+                  }
+                }
+                else
+                {
+                  v10 += *(int *)(v15 + 4);
+                  v40 = v12;
+                }
+              }
+              else
+              {
+                if ( !a6 )
+                  return (char *)v32;
+              }
+            }
+            else
+            {
+              v12 += 5;
+            }
+          }
+          else
+          {
+            v10 = v37;
+            v11 = v35;
+            v40 = v12;
+          }
+        }
+        else
+        {
+          strncpy(&Str, &pTmpBuf3[v12 + 1], 3u);
+          v34 = 0;
+          v28 = atoi(&Str);
+          v10 = a5 + v28;
+          v12 += 3;
+          v37 = v10;
+        }
+      }
+      ++v12;
+      v36 = v12;
+    }
+    while ( v12 < v39 );
+  }
+  return pTmpBuf3;
+}
+
+
+//----- (0044C6C2) --------------------------------------------------------
+int GUIFont::_44C6C2(const char *pInString, GUIWindow *pWindow, unsigned int uX, int a5)
+{
+  const char *v5; // esi@1
+  int v6; // edi@1
+  unsigned __int8 *v8; // ebx@3
+  size_t v9; // eax@3
+  signed int v10; // esi@3
+  int v11; // edx@4
+  unsigned __int8 v12; // cl@4
+  GUIFont *v13; // [sp+Ch] [bp-4h]@1
+  size_t uXa; // [sp+1Ch] [bp+Ch]@3
+
+  auto pFont = this;
+  v5 = pInString;
+  v6 = 0;
+  v13 = pFont;
+  if ( !pInString )
+    return 0;
+  v8 = (unsigned __int8 *)FitTextInAWindow(pInString, pFont, pWindow, uX, 0);
+  v9 = strlen(v5);
+  v10 = 0;
+  uXa = v9;
+  if ( (signed int)v9 > 0 )
+  {
+    while ( !IsCharValid(*v8) )
+    {
+LABEL_11:
+      ++v10;
+      ++v8;
+      if ( v10 >= (signed int)uXa )
+        return (int)v8;
+    }
+    if ( v12 != 9 )
+    {
+      if ( v12 == 10 )
+      {
+        v6 = v6 + *(char *)(v11 + 5) - 3;
+        if ( v6 >= (signed int)(a5 * pWindow->uFrameHeight) )
+          return (int)(v8 + 1);
+        goto LABEL_10;
+      }
+      if ( v12 == 12 )
+      {
+        v8 += 5;
+        v10 += 5;
+LABEL_10:
+        if ( v6 >= (signed int)(a5 * pWindow->uFrameHeight) )
+          return (int)v8;
+        goto LABEL_11;
+      }
+      if ( v12 != 13 )
+        goto LABEL_10;
+    }
+    v8 += 3;
+    v10 += 3;
+    goto LABEL_10;
+  }
+  return (int)v8;
+}
+
+
+
+//----- (0044C62E) --------------------------------------------------------
+int GUIFont::GetStringHeight2(GUIFont *a2, const char *Str, int a4, int a5, int a6)
+{
+  GUIFont *v6; // edi@1
+  int v8; // esi@3
+  unsigned __int8 *v9; // ebx@3
+  size_t v10; // eax@3
+  unsigned __int8 v11; // cl@4
+  signed int Stra; // [sp+Ch] [bp+8h]@3
+  size_t v13; // [sp+14h] [bp+10h]@3
+
+  auto a1 = this;
+  v6 = a1;
+  if ( !Str )
+    return 0;
+  v8 = LOBYTE(a1->uFontHeight) - 3;
+  v9 = (unsigned __int8 *)GUIFont::_44C933(Str, a1, a2, a4, a5, 0);
+  v10 = strlen(Str);
+  Stra = 0;
+  v13 = v10;
+  while ( Stra < (signed int)v13 )
+  {
+    if ( GUIFont::IsCharValid(v11 = *v9) )
+    {
+      if ( v11 == 9 )
+        goto LABEL_9;
+      switch ( v11 )
+      {
+        case 0xAu:
+          v8 = v8 + LOBYTE(v6->uFontHeight) - 3;
+          break;
+        case 0xCu:
+          v9 += 5;
+          Stra += 5;
+          break;
+        case 0xDu:
+LABEL_9:
+          if ( a6 != 1 )
+          {
+            v9 += 3;
+            Stra += 3;
+          }
+          break;
+      }
+    }
+    ++Stra;
+    ++v9;
+  }
+  return v8;
+}
+
+//----- (0044C59D) --------------------------------------------------------
+int GUIFont::CalcTextHeight(const char *pString, GUIWindow *pWindow, int a4, int a5)
+{
+  const char *v5; // ebx@1
+  GUIFont *v6; // edi@1
+  int v8; // esi@3
+  size_t v9; // eax@3
+  signed int v10; // ebx@3
+  unsigned __int8 v11; // cl@4
+  size_t pWindowa; // [sp+10h] [bp+8h]@3
+  unsigned __int8 *uX; // [sp+14h] [bp+Ch]@3
+
+  v5 = pString;
+  v6 = this;
+  if ( !pString )
+    return 0;
+  v8 = LOBYTE(this->uFontHeight) - 3;
+  uX = (unsigned __int8 *)FitTextInAWindow(pString, this, pWindow, a4, 0);
+  v9 = strlen(v5);
+  v10 = 0;
+  pWindowa = v9;
+  while ( v10 < (signed int)pWindowa )
+  {
+    if ( v6->IsCharValid(v11 = *uX) )
+    {
+      if ( v11 == 9 )
+        goto LABEL_9;
+      switch ( v11 )
+      {
+        case 0xAu:
+          v8 = v8 + LOBYTE(v6->uFontHeight) - 3;
+          break;
+        case 0xCu:
+          uX += 5;
+          v10 += 5;
+          break;
+        case 0xDu:
+LABEL_9:
+          if ( a5 != 1 )
+          {
+            uX += 3;
+            v10 += 3;
+          }
+          break;
+      }
+    }
+    ++v10;
+    ++uX;
+  }
+  return v8;
+}
+
+
+//----- (0044C51E) --------------------------------------------------------
+int GUIFont::GetLineWidth(const char *pString)
+{
+  GUIFont *v2; // edi@1
+  size_t v4; // ebp@3
+  int v5; // esi@3
+  signed int i; // ebx@3
+  unsigned __int8 v7; // cl@4
+  const char *v8; // [sp+0h] [bp-4h]@1
+
+  v8 = pString;
+  v2 = this;
+  if ( !pString )
+    return 0;
+  v4 = strlen(pString);
+  v5 = 0;
+  for ( i = 0; i < (signed int)v4; ++i )
+  {
+    if ( IsCharValid(v7 = v8[i]) )
+    {
+      if ( v7 < 9u )
+        goto LABEL_9;
+      if ( v7 <= 0xAu )
+        return v5;
+      if ( v7 != '\f' )
+      {
+        if ( v7 == '\r' )
+          return v5;
+LABEL_9:
+        if ( i > 0 )
+          v5 += v2->pMetrics[v7].uLeftSpacing;
+        v5 += *((int *)&v2->cFirstChar + 3 * v7 + 9);
+        if ( i < (signed int)v4 )
+          v5 += v2->pMetrics[v7].uRightSpacing;
+        continue;
+      }
+      i += 5;
+    }
+  }
+  return v5;
+}
+
+
+
+
+//----- (0044C502) --------------------------------------------------------
+int GUIFont::AlignText_Center(unsigned int uCenterX, const char *pString)
+{
+  signed int v3; // esi@1
+  signed int result; // eax@2
+
+  v3 = (signed int)(uCenterX - GetLineWidth(pString)) >> 1;
+  if ( v3 >= 0 )
+    result = v3;
+  else
+    result = 0;
+  return result;
+}
+
+
+//----- (0044C4DE) --------------------------------------------------------
+bool GUIFont::IsCharValid(char _c)
+{
+  unsigned char c = _c;
+  return c >= cFirstChar && c <= cLastChar || c == '\f' || c == '\r' || c == '\t' || c == '\n';
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUIFont.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,57 @@
+#pragma once
+
+
+/*  171 */
+#pragma pack(push, 1)
+struct GUICharMetric
+{
+  unsigned int uLeftSpacing;
+  unsigned int uWidth;
+  unsigned int uRightSpacing;
+};
+#pragma pack(pop)
+
+/*  170 */
+#pragma pack(push, 1)
+struct GUIFont
+{
+  bool IsCharValid(char c);
+  int AlignText_Center(unsigned int uCenterX, const char *pString);
+  int GetLineWidth(const char *pString);
+  int CalcTextHeight(const char *pString, struct GUIWindow *pWindow, int a4, int a5);
+  int GetStringHeight2(GUIFont *a2, const char *Str, int a4, int a5, int a6);
+  int _44C6C2(const char *pInString, GUIWindow *pWindow, unsigned int uX, int a5);
+  void _44D0B5(int a2, int a3, int a4, const char *pString, int a6);
+  void DrawTextLine(unsigned int uDefaultColor, signed int uX, signed int uY, const char *Str, int a6);
+  void _44D2FD_prolly_draw_credits_entry(GUIFont *pFont, int Str, int a4, unsigned int w, unsigned int h, unsigned __int16 a7, unsigned __int16 a8, const char *pString, unsigned __int16 *pPixels, unsigned int uPixelsWidth);
+
+  static char *__fastcall _44C933(const char *pString, GUIFont *pFont, GUIFont *a3, int a4, int a5, int a6);
+
+  unsigned char cFirstChar;
+  unsigned char cLastChar;
+  char field_2;
+  char field_3;
+  char field_4;
+  __int16 uFontHeight;
+  char field_7;
+  int field_8;
+  unsigned __int16 *pFontPalettes[5];
+  GUICharMetric pMetrics[256];
+  int field_C20[256];
+};
+#pragma pack(pop)
+
+
+
+
+
+extern struct GUIFont *pAutonoteFont;
+extern struct GUIFont *pSpellFont;
+extern struct GUIFont *pFontArrus;
+extern struct GUIFont *pFontLucida;
+extern struct GUIFont *pBook2Font;
+extern struct GUIFont *pBookFont;
+extern struct GUIFont *pFontCreate;
+extern struct GUIFont *pFontCChar;
+extern struct GUIFont *pFontComic;
+extern struct GUIFont *pFontSmallnum;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUIProgressBar.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,208 @@
+#include "GUIProgressBar.h"
+#include "LOD.h"
+#include "Mouse.h"
+#include "Party.h"
+#include "Render.h"
+#include "IconFrameTable.h"
+
+#include "mm7_data.h"
+
+
+
+
+struct GUIProgressBar *pGameLoadingUI_ProgressBar = new GUIProgressBar;
+
+
+
+
+//----- (00443484) --------------------------------------------------------
+bool GUIProgressBar::_443484(Type type)
+{
+  //GUIProgressBar *v2; // esi@1
+  signed int v4; // eax@7
+  int v5; // ecx@8
+  int v6; // edi@8
+  int v7; // edx@14
+  const char *v8; // [sp-8h] [bp-84h]@20
+  unsigned int v9; // [sp-4h] [bp-80h]@20
+  char Str1[64]; // [sp+4h] [bp-78h]@16
+
+  if (type < 1 || type > 1)
+  {
+    __debugbreak();
+    return false;
+  }
+
+  //v2 = this;
+  if (pAsyncMouse)
+    pAsyncMouse->Suspend();
+  if (pLoadingBg.pPixels)
+    return false;
+
+  uType = type;
+
+  v4 = 1;
+  if (uType == TYPE_Fullscreen)
+  {
+    v5 = 0;
+    v6 = (int)&field_10;
+    do
+    {
+      if ( *(char *)(v6 + v4) == 1 )
+        ++v5;
+      ++v4;
+    }
+    while ( v4 <= 5 );
+    if ( v5 == 5 )
+      memset(&field_10, 0, 8u);
+    v7 = rand() % 5 + 1;
+    if ( *(&field_10 + v7) == 1 )
+    {
+      do
+        v7 = rand() % 5 + 1;
+      while ( *(char *)(v6 + v7) == 1 );
+    }
+    sprintf(Str1, "loading%d.pcx", v7);
+    pLoadingBg.Load(Str1, 2);
+    uProgressCurrent = 0;
+    uX = 122;
+    uY = 151;
+    uWidth = 449;
+    uHeight = 56;
+    uProgressMax = 26;
+    pIcons_LOD->_410522(&pLoadingProgress, "loadprog", 2u);
+    Draw();
+    return true;
+  }
+  if ( !pParty->uAlignment )
+  {
+    v9 = 2;
+    v8 = "bardata-b";
+    goto LABEL_23;
+  }
+  if ( pParty->uAlignment == 1 )
+  {
+    v9 = 2;
+    v8 = "bardata";
+    goto LABEL_23;
+  }
+  if ( pParty->uAlignment == 2 )
+  {
+    v9 = 2;
+    v8 = "bardata-c";
+LABEL_23:
+    pIcons_LOD->_410522(&pBardata, v8, v9);
+  }
+  uProgressCurrent = 0;
+  uProgressMax = 26;
+  Draw();
+  return true;
+}
+
+//----- (004435BB) --------------------------------------------------------
+void GUIProgressBar::Reset(unsigned __int8 uMaxProgress)
+{
+  field_9 = 0;
+  uProgressCurrent = 0;
+  uProgressMax = uMaxProgress;
+}
+
+//----- (004435CD) --------------------------------------------------------
+void GUIProgressBar::Progress()
+{
+  unsigned __int8 v1; // al@1
+
+  ++this->uProgressCurrent;
+  v1 = this->uProgressMax;
+  if ( this->uProgressCurrent > v1 )
+    this->uProgressCurrent = v1;
+  Draw();
+}
+
+//----- (004435E2) --------------------------------------------------------
+void GUIProgressBar::Release()
+{
+  GUIProgressBar *v1; // esi@1
+  char v2; // al@5
+  int v3; // edi@7
+
+  v1 = this;
+  if (pAsyncMouse)
+    pAsyncMouse->Resume();
+  if ( v1->uType == 1 )
+  {
+    if ( !v1->pLoadingBg.pPixels )
+      return;
+    v2 = v1->uProgressMax;
+    if ( v1->uProgressCurrent != v2 )
+    {
+      v1->uProgressCurrent = v2 - 1;
+      Progress();
+    }
+    free(v1->pLoadingBg.pPixels);
+    v3 = (int)&v1->pLoadingProgress.pLevelOfDetail0;
+    free(v1->pLoadingProgress.pLevelOfDetail0);
+    free(v1->pLoadingProgress.pPalette16);
+    v1->pLoadingProgress.pPalette16 = 0;
+    v1->pLoadingBg.pPixels = 0;
+  }
+  else
+  {
+    if ( !v1->pBardata.pLevelOfDetail0 )
+      return;
+    free(v1->pBardata.pLevelOfDetail0);
+    v3 = (int)&v1->pBardata.pPalette16;
+    free(v1->pBardata.pPalette16);
+    v1->pBardata.pLevelOfDetail0 = 0;
+  }
+  *(int *)v3 = 0;
+}
+
+//----- (00443670) --------------------------------------------------------
+void GUIProgressBar::Draw()
+{
+  IconFrame *v3; // eax@10
+  float v4; // ST2C_4@10
+
+  //v1 = this;
+  pRenderer->BeginScene();
+  if (uType != TYPE_Fullscreen)
+  {
+    if (pBardata.pLevelOfDetail0)
+    {
+      if (pRenderer->pRenderD3D)
+      {
+        if (!pRenderer->bWindowMode)
+          pRenderer->_49FD3A();
+      }
+      pRenderer->DrawTextureIndexed(0x50u, 0x7Au, &pBardata);
+      v3 = pIconsFrameTable->GetFrame(uIconID_TurnHour, 0);
+      pRenderer->DrawTextureTransparent(0x64u, 0x92u, &pIcons_LOD->pTextures[v3->uTextureID]);
+      v4 = (double)(113 * uProgressCurrent) / (double)uProgressMax;
+      pRenderer->FillRectFast(
+        174,
+        164,
+        floorf(v4 + 0.5f),//COERCE_UNSIGNED_INT64(v4 + 6.7553994e15),
+        16,
+        pRenderer->uTargetRMask);
+      goto LABEL_11;
+    }
+LABEL_6:
+    pRenderer->EndScene();
+    return;
+  }
+
+  if (!pLoadingBg.pPixels)
+    goto LABEL_6;
+
+  pRenderer->DrawTextureRGB(0, 0, &pLoadingBg);
+  pRenderer->Clip_v2(0, 0, 0x27Fu, 0x1DFu);
+  pRenderer->Clip(0xACu, 0x1CBu,
+    15 * (signed int)(signed __int64)((double)(300 * uProgressCurrent) / (double)uProgressMax) / 15 + 172,
+    0x1D7u);
+  pRenderer->DrawTextureTransparent(0xACu, 0x1CBu, &pLoadingProgress);
+  pRenderer->ResetClip();
+LABEL_11:
+  pRenderer->EndScene();
+  pRenderer->Present();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUIProgressBar.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,50 @@
+#pragma once
+#include "Texture.h"
+
+
+/*  278 */
+#pragma pack(push, 1)
+struct GUIProgressBar
+{
+  enum Type: unsigned __int32
+  {
+    TYPE_Fullscreen = 1
+  };
+
+  bool _443484(Type type);
+  void Reset(unsigned __int8 uMaxProgress);
+  void Progress();
+  void Release();
+  void Draw();
+
+  __int16 uX;
+  __int16 uY;
+  __int16 uWidth;
+  __int16 uHeight;
+  char field_8;
+  char field_9;
+  char uProgressMax;
+  char uProgressCurrent;
+  Type uType;
+  char field_10;
+  char field_11;
+  char field_12;
+  char field_13;
+  char field_14;
+  char field_15;
+  char field_16;
+  char field_17;
+  RGBTexture pLoadingBg;
+  RGBTexture field_40;
+  RGBTexture field_68;
+  RGBTexture field_90;
+  RGBTexture field_B8;
+  Texture field_E0;
+  Texture pBardata;
+  Texture pLoadingProgress;
+};
+#pragma pack(pop)
+
+
+
+extern struct GUIProgressBar *pGameLoadingUI_ProgressBar;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUIWindow.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2548 @@
+#include "GUIWindow.h"
+#include "GUIButton.h"
+#include "GUIFont.h"
+#include "Party.h"
+#include "LOD.h"
+#include "Keyboard.h"
+#include "IndoorCamera.h"
+#include "Math.h"
+#include "VideoPlayer.h"
+#include "Allocator.h"
+#include "MapInfo.h"
+#include "Time.h"
+#include "AudioPlayer.h"
+#include "Mouse.h"
+#include "Viewport.h"
+#include "Render.h"
+#include "PlayerFrameTable.h"
+#include "stru179.h"
+#include "SaveLoad.h"
+#include "FactionTable.h"
+#include "StorylineTextTable.h"
+#include "Events2D.h"
+
+
+#include "mm7_data.h"
+
+
+
+
+int pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[1]; // idb
+struct GUIWindow *pWindow_MainMenu;
+struct GUIWindow pWindowList[20];
+
+struct GUIMessageQueue *pMessageQueue_50CBD0 = new GUIMessageQueue;
+
+
+//----- (004356B9) --------------------------------------------------------
+void GUIMessageQueue::PopMessage(enum UIMessageType *pType, int *pParam, int *a4)
+{
+  signed int v4; // edx@1
+  GUIMessage *v5; // eax@2
+
+  v4 = 0;
+  if ( this->uNumMessages )
+  {
+    v5 = this->pMessages;
+    *pType = this->pMessages[0].eType;
+    *pParam = this->pMessages[0].param;
+    *a4 = this->pMessages[0].field_8;
+    if ( (signed int)(this->uNumMessages - 1) > 0 )
+    {
+      do
+      {
+        v5->eType = v5[1].eType;
+        v5->param = v5[1].param;
+        v5->field_8 = v5[1].field_8;
+        ++v4;
+        ++v5;
+      }
+      while ( v4 < (signed int)(this->uNumMessages - 1) );
+    }
+    --this->uNumMessages;
+  }
+}
+
+
+
+//----- (0041D73D) --------------------------------------------------------
+char GUIWindow::_41D73D_draw_buff_tooltip()
+{
+  GUIFont *v1; // esi@1
+  GUIWindow *v2; // edi@1
+  SpellBuff *v3; // eax@1
+  unsigned int v4; // eax@5
+  int v5; // ecx@5
+  unsigned int v6; // eax@5
+  unsigned int v7; // ecx@5
+  char *v8; // ebx@7
+  unsigned int v9; // eax@8
+  unsigned int v10; // ecx@8
+  __int64 v11; // ST28_8@11
+  int v12; // esi@11
+  const char *v13; // ST0C_4@11
+  unsigned int v14; // eax@11
+  char **v16; // [sp+14h] [bp-10h]@7
+  GUIFont *a2; // [sp+18h] [bp-Ch]@1
+  SpellBuff *v18; // [sp+1Ch] [bp-8h]@7
+  int v19; // [sp+20h] [bp-4h]@1
+  int v20; // [sp+20h] [bp-4h]@7
+
+  v1 = pFontComic;
+  v2 = this;
+  a2 = pFontComic;
+  v19 = 0;
+  v3 = pParty->pPartyBuffs;
+  do
+  {
+    if ( (signed __int64)v3->uExpireTime > 0 )
+      ++v19;
+    ++v3;
+  }
+  while ( (signed int)v3 < (signed int)pParty->pPlayers );
+  v4 = LOBYTE(pFontArrus->uFontHeight) + 72;
+  this->uFrameHeight = v4;
+  v5 = v4 + (v19 - 1) * LOBYTE(pFontArrus->uFontHeight);
+  v6 = v2->uFrameWidth;
+  v2->uFrameHeight = v5;
+  v7 = v2->uFrameHeight;
+  v2->uFrameZ = v6 + v2->uFrameX - 1;
+  v2->uFrameW = v2->uFrameY + v7 - 1;
+  v2->DrawMessageBox(0);
+  v2->DrawTitleText(pFontArrus, 0, 0xCu, 0, pGlobalTXT_LocalizationStrings[451], 3u);
+  if ( !v19 )
+    v2->DrawTitleText(v1, 0, 0x28u, 0, pGlobalTXT_LocalizationStrings[153], 3u);
+  v20 = 0;
+  GetTickCount();
+  v8 = &_4E2B21_buff_spell_tooltip_colors[1];
+  v16 = aSpellNames;
+  v18 = pParty->pPartyBuffs;
+  do
+  {
+    v9 = LODWORD(v18->uExpireTime);
+    v10 = HIDWORD(v18->uExpireTime);
+    if ( (v10 & 0x80000000u) == 0 && ((signed int)v10 > 0 || v9) )
+    {
+      v11 = __PAIR__(v10, v9) - pParty->uTimePlayed;
+      v12 = v20 * LOBYTE(v1->uFontHeight) + 40;
+      v13 = *v16;
+      ++v20;
+      v14 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(
+              (unsigned __int8)*(v8 - 1),
+              (unsigned __int8)*v8,
+              (unsigned __int8)v8[1]);
+      v2->DrawText(a2, 52, v12, v14, v13, 0, 0, 0);
+      LOBYTE(v9) = sub_41D20D_buff_remaining_time_string(v12, v2, v11, a2);
+      v1 = a2;
+    }
+    ++v18;
+    ++v16;
+    v8 += 3;
+  }
+  while ( (signed int)v18 < (signed int)pParty->pPlayers );
+  return v9;
+}
+
+
+//----- (0041D3B7) --------------------------------------------------------
+char GUIWindow::DrawQuickCharRecord()
+{
+  Player *pPlayer; // esi@1
+  int v6; // eax@5
+  int v7; // ebx@5
+  unsigned int v8; // ecx@5
+  int v9; // ebx@5
+  unsigned int v10; // eax@5
+  int v11; // eax@5
+  unsigned int v12; // ecx@5
+  Texture *v13; // eax@6
+  unsigned int v14; // eax@12
+  PlayerFrame *v15; // eax@12
+  unsigned int v16; // eax@15
+  unsigned int v20; // eax@15
+  unsigned int v24; // eax@15
+  unsigned int v25; // eax@15
+  unsigned __int8 v28; // al@15
+  char *v29; // eax@16
+  __int64 v35; // ST38_8@22
+  int v36; // esi@22
+  unsigned int v38; // eax@22
+  char *v39; // eax@24
+  signed int uFramesetID; // [sp+20h] [bp-8h]@9
+  int uFramesetIDa; // [sp+20h] [bp-8h]@18
+
+  pPlayer = &pParty->pPlayers[(unsigned int)ptr_1C];
+
+  uint numActivePlayerBuffs = 0;
+
+  for (uint i = 0; i < 24; ++i)
+    if (pPlayer->pPlayerBuffs[i].uExpireTime > 0)
+      ++numActivePlayerBuffs;
+
+  v6 = pFontArrus->uFontHeight + 162;
+  uFrameHeight = v6;
+  v7 = (numActivePlayerBuffs - 1) * pFontArrus->uFontHeight;
+  v8 = uFrameX;
+  v9 = v6 + v7;
+  v10 = uFrameWidth;
+  uFrameHeight = v9;
+  v11 = v10 + v8 - 1;
+  v12 = uFrameY;
+  uFrameZ = v11;
+  uFrameW = v9 + v12 - 1;
+  DrawMessageBox(0);
+  if (pPlayer->Eradicated())
+    v13 = pTexture_PlayerFaceEradicated;
+  else if (pPlayer->Dead())
+    v13 = pTexture_PlayerFaceDead;
+  else
+  {
+      uFramesetID = pPlayerFrameTable->GetFrameIdBy_field0(pPlayer->uExpressionID);
+      if ( !uFramesetID )
+        uFramesetID = 1;
+      if ( pPlayer->uExpressionID == 21 )
+      {
+        v15 = pPlayerFrameTable->GetFrameBy_y(
+                &pPlayer->field_1AA8,
+                &pPlayer->field_1AA4,
+                pMiscTimer->uTimeElapsed);
+      }
+      else
+      {
+        v14 = pMiscTimer->Time();
+        v15 = pPlayerFrameTable->GetFrameBy_x(uFramesetID, v14);
+      }
+      pPlayer->field_1AA2 = v15->uTextureID - 1;
+      v13 = pTextures_PlayerFaces[(unsigned int)ptr_1C][v15->uTextureID];
+  }
+
+  pRenderer->DrawTextureTransparent(uFrameX + 24, uFrameY + 24, v13);
+  v16 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  sprintf(pTmpBuf, "\xC%05d", v16);
+  sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[429], pPlayer->pName, pClassNames[pPlayer->uClass]);
+  strcat(pTmpBuf, pTmpBuf2);
+  strcat(pTmpBuf, "\xC" "00000\n");
+  v20 = UI_GetHealthManaStringColor(pPlayer->sHealth, pPlayer->GetMaxHealth());
+  sprintf(pTmpBuf2, "%s : \x0C" "%05u%d\x0C" "00000 / %d\n", pGlobalTXT_LocalizationStrings[108],
+          v20, pPlayer->sHealth, pPlayer->GetMaxHealth());
+  strcat(pTmpBuf, pTmpBuf2);
+  v24 = UI_GetHealthManaStringColor(pPlayer->sMana, pPlayer->GetMaxMana());
+  sprintf(pTmpBuf2, "%s : \x0C" "%05u%d\x0C" "00000 / %d\n", pGlobalTXT_LocalizationStrings[212],
+          v24, pPlayer->sMana, pPlayer->GetMaxMana());
+  strcat(pTmpBuf, pTmpBuf2);
+  v25 = pPlayer->GetMajorConditionIdx();
+  sprintf(pTmpBuf2, "%s: \x0C" "%05d%s\x0C" "00000\n", pGlobalTXT_LocalizationStrings[47],
+          GetConditionDrawColor(v25), aCharacterConditionNames[v25]);
+  strcat(pTmpBuf, pTmpBuf2);
+  v28 = pPlayer->uQuickSpell;
+  if ( v28 )
+    v29 = pSpellStats->pInfos[v28].pShortName;
+  else
+    v29 = pGlobalTXT_LocalizationStrings[153];
+  sprintf(pTmpBuf2, "%s: %s", pGlobalTXT_LocalizationStrings[172], v29);
+  strcat(pTmpBuf, pTmpBuf2);
+  DrawText(pFontArrus, 120, 22, 0, pTmpBuf, 0, 0, 0);
+
+  uFramesetIDa = 0;
+  for (uint i = 0; i < 24; ++i)
+  {
+    auto buff = pPlayer->pPlayerBuffs + i;
+    if (buff->uExpireTime > 0)
+    {
+      v35 = buff->uExpireTime - pParty->uTimePlayed;
+      v36 = uFramesetIDa++ * pFontComic->uFontHeight + 134;
+      v38 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(
+              _4E2AD8_ui_colors[i * 3],
+              _4E2AD8_ui_colors[i * 3 + 1],
+              _4E2AD8_ui_colors[i * 3 + 2]);
+      DrawText(pFontComic, 52, v36, v38, aSpellNames[20 + i], 0, 0, 0);
+      sub_41D20D_buff_remaining_time_string(v36, this, v35, pFontComic);
+    }
+  }
+
+  v39 = "";
+  if ( uFramesetIDa == 0 )
+    v39 = pGlobalTXT_LocalizationStrings[153];
+  sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[450], v39);
+  return DrawText(pFontArrus, 14, 114, 0, pTmpBuf, 0, 0, 0);
+}
+
+//----- (0041D08F) --------------------------------------------------------
+void GUIWindow::_41D08F(int a2, int a3, int a4, int a5)
+{
+  if ( a2 )
+  {
+    this->pNumPresenceButton = a2;
+    this->field_30 = a3;
+    this->field_34 = a4;
+    this->pCurrentPosActiveItem = a5;
+    this->pStartingPosActiveItem = a5;
+    this->field_44 = 1;
+  }
+  else
+  {
+    this->pNumPresenceButton = 0;
+    this->field_30 = a3;
+    this->field_34 = a4;
+    this->pCurrentPosActiveItem = 0;
+    this->pStartingPosActiveItem = 0;
+    this->field_44 = 0;
+  }
+}
+
+
+//----- (0041C26A) --------------------------------------------------------
+void GUIWindow::Release()
+{
+  GUIWindow *v1; // esi@1
+  unsigned int v2; // eax@2
+  int v3; // eax@5
+  int v4; // eax@6
+  int v5; // eax@14
+  int v6; // eax@15
+  int i; // edi@20
+  GUIButton *v8; // eax@26
+  GUIButton *v9; // edi@27
+  int v10; // esi@28
+  int v11; // ecx@28
+  int v12; // edx@29
+
+  v1 = this;
+  if ( !this )
+    return;
+  v2 = this->eWindowType;
+  if ( (signed int)v2 > 18 )
+  {
+    v5 = v2 - 19;
+    if ( !v5 )
+    {
+      pIcons_LOD->_40F9C5();
+      pCurrentScreen = dword_506978;
+      pKeyActionMap->_459ED1(3);
+      goto LABEL_26;
+    }
+    v6 = v5 - 6;
+    if ( !v6 )
+    {
+      for ( i = 0; i < uNumDialogueNPCPortraits; ++i )
+        pDialogueNPCPortraits[i]->Release();
+      uNumDialogueNPCPortraits = 0;
+      pTexture_Dialogue_Background->Release();
+
+      pIcons_LOD->_40F9C5();
+      pIcons_LOD->_4114F2();
+      dword_5C35D4 = 0;
+      if ( bFlipOnExit )
+      {
+        pIndoorCamera->sRotationY = (stru_5C6E00->uIntegerDoublePi - 1) & (stru_5C6E00->uIntegerPi
+                                                                       + pIndoorCamera->sRotationY);
+        pParty->sRotationY = pIndoorCamera->sRotationY;
+      }
+      pParty->uFlags |= 2u;
+      goto LABEL_26;
+    }
+    if ( v6 == 1 )
+    {
+      pVideoPlayer->Unload();
+      goto LABEL_18;
+    }
+  }
+  else
+  {
+    if ( v2 == 18 )
+    {
+      sub_41140B();
+      sub_411473();
+    }
+    else
+    {
+      if ( !v2 )
+        return;
+      v3 = v2 - 9;
+      if ( v3 )
+      {
+        v4 = v3 - 1;
+        if ( !v4 )
+        {
+          if ( !dword_591084 )
+            pDialogueNPCPortraits[0]->Release();
+          uNumDialogueNPCPortraits = 0;
+          pTexture_Dialogue_Background->Release();
+
+          pIcons_LOD->_40F9C5();
+          goto LABEL_19;
+        }
+        if ( v4 != 7 )
+          goto LABEL_26;
+LABEL_18:
+        pTexture_outside->Release();
+        pTexture_Dialogue_Background->Release();
+        pIcons_LOD->_40F9C5();
+LABEL_19:
+        pCurrentScreen = dword_506978;
+        goto LABEL_26;
+      }
+      OnCloseSpellook();
+    }
+  }
+LABEL_26:
+  v8 = v1->pControlsHead;
+  if ( v8 )
+  {
+    do
+    {
+      v9 = v8->pNext;
+      pAllocator->FreeChunk(v8);
+      v8 = v9;
+    }
+    while ( v9 );
+  }
+  v1->pControlsHead = 0;
+  v1->pControlsTail = 0;
+  v1->uNumControls = 0;
+  v1->eWindowType = WINDOW_null;
+  v10 = v1->field_3C;
+  v11 = uNumVisibleWindows;
+  while ( v10 < v11 )
+  {
+    v12 = pVisibleWindowsIdxs[v10 + 1];
+    pVisibleWindowsIdxs[v10] = v12;
+    --*((int *)&pTexture_PCX.field_18 + 21 * v12);
+    ++v10;
+  }
+  pVisibleWindowsIdxs[v11] = 0;
+  uNumVisibleWindows = v11 - 1;
+}
+
+
+
+
+
+
+//----- (0041CD3B) --------------------------------------------------------
+GUIButton *GUIWindow::GetControl(unsigned int uID)
+{
+  GUIButton *result; // eax@1
+  unsigned int v3; // ecx@1
+
+  result = this->pControlsHead;
+  v3 = uID;
+  if ( (signed int)uID > 0 )
+  {
+    do
+    {
+      result = result->pNext;
+      --v3;
+    }
+    while ( v3 );
+  }
+  return result;
+}
+
+//----- (00411BFC) --------------------------------------------------------
+void GUIWindow::InitializeBookView()
+{
+  GUIWindow *v1; // ebp@1
+  signed int v2; // ecx@8
+  __int64 *v3; // ebp@9
+  char *v4; // ecx@10
+  char *v5; // eax@12
+  int v6; // eax@12
+  __int64 v7; // qax@12
+  unsigned int v8; // esi@12
+  GUIButton *v9; // eax@19
+  signed int v10; // esi@19
+  int v11; // eax@24
+  int v12; // eax@27
+  int i; // esi@28
+  char *v14; // ebp@29
+  int v15; // eax@31
+  unsigned int v16; // esi@35
+  Player *v17; // esi@38
+  unsigned __int16 v18; // ax@38
+  unsigned int v19; // edi@43
+  unsigned int v20; // edi@45
+  void *v21; // esi@45
+  char *v22; // [sp+10h] [bp-5Ch]@9
+  signed int v23; // [sp+10h] [bp-5Ch]@38
+  int v24; // [sp+14h] [bp-58h]@9
+  char *v25; // [sp+14h] [bp-58h]@21
+  GUIWindow v26; // [sp+18h] [bp-54h]@8
+
+  v1 = this;
+  pAudioPlayer->StopChannels(-1, -1);
+  InitializeBookFonts();
+  v1->CreateButton(0x1DBu, 0x1BDu, 0x9Eu, 0x22u, 1, 0, 0x71u, 0, 0, pGlobalTXT_LocalizationStrings[79], 0);
+  pCurrentScreen = 3;
+  dword_506524 = 0;
+  dword_506528 = 0;
+  dword_50651C = 0;
+  dword_506520 = 0;
+  if ( v1->ptr_1C == (void *)177 )
+  {
+    byte_506360 = 0;
+    pTexture_CurrentBook     = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("lb_bordr", TEXTURE_16BIT_PALETTE)];
+    pTexture_LloydBeacons[0] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("sbmap", TEXTURE_16BIT_PALETTE)];
+    pTexture_50635C          = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("sbmap", TEXTURE_16BIT_PALETTE)];
+    pTex_tab_an_6b__zoom_on  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-6b", TEXTURE_16BIT_PALETTE)];
+    pTex_tab_an_6a__zoom_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-6a", TEXTURE_16BIT_PALETTE)];
+    pBtn_Book_1 = v1->CreateButton(
+                    415u,
+                    13u,
+                    39u,
+                    36u,
+                    1,
+                    0,
+                    0xB2u,
+                    0,
+                    0,
+                    pGlobalTXT_LocalizationStrings[375],
+                    0);
+    pBtn_Book_2 = v1->CreateButton(
+                    415u,
+                    48u,
+                    39u,
+                    36u,
+                    1,
+                    0,
+                    0xB2u,
+                    1u,
+                    0,
+                    pGlobalTXT_LocalizationStrings[523],
+                    0);
+    v17 = &pParty->pPlayers[_506348_current_lloyd_playerid];
+    v23 = 1;
+    v18 = v17->pActiveSkills[14];
+    if ( HIBYTE(v18) & 1 || (v18 & 0x80u) != 0 )
+    {
+      v23 = 5;
+    }
+    else
+    {
+      if ( v18 & 0x40 )
+        v23 = 3;
+    }
+    v19 = 0;
+    if ( v23 > 0 )
+    {
+      do
+      {
+        v1->CreateButton(
+          pLloydsBeaconsPreviewXs[v19],
+          pLloydsBeaconsPreviewYs[v19],
+          0x5Cu,
+          0x44u,
+          1,
+          180,
+          0xB3u,
+          v19,
+          0,
+          "",
+          0);
+        ++v19;
+      }
+      while ( (signed int)v19 < v23 );
+    }
+    v20 = 0;
+    v21 = v17->pInstalledBeacons;
+    do
+    {
+      if ( *(_QWORD *)v21 >= (signed __int64)pParty->uTimePlayed )
+        LoadThumbnailLloydTexture(v20, _506348_current_lloyd_playerid + 1);
+      else
+        memset(v21, 0, 0x1Cu);
+      ++v20;
+      v21 = (char *)v21 + 28;
+    }
+    while ( (signed int)v20 < 5 );
+  }
+  else
+  {
+    if ( v1->ptr_1C == (void *)195 )
+    {
+      pTexture_CurrentBook       = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("townport", TEXTURE_16BIT_PALETTE)];
+      pTexture_TownPortalHarmn   = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tpharmndy", TEXTURE_16BIT_PALETTE)];
+      pTexture_TownPortalElf     = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tpelf", TEXTURE_16BIT_PALETTE)];
+      pTexture_TownPortalWarlock = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tpwarlock", TEXTURE_16BIT_PALETTE)];
+      pTexture_TownPortalIsland  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tpisland", TEXTURE_16BIT_PALETTE)];
+      pTexture_TownPortalHeaven  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tpheaven", TEXTURE_16BIT_PALETTE)];
+      v16 = 0;
+      pTexture_TownPortalHell    = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture( "tphell", TEXTURE_16BIT_PALETTE)];
+      do
+      {
+        v1->CreateButton(
+          pTownPortalBook_xs[v16],
+          pTownPortalBook_ys[v16],
+          pTownPortalBook_ws[v16],
+          pTownPortalBook_hs[v16],
+          1,
+          182,
+          0xB7u,
+          v16,
+          0,
+          "",
+          0);
+        ++v16;
+      }
+      while ( (signed int)v16 < 6 );
+    }
+    else
+    {
+      if ( v1->ptr_1C == (void *)200 )
+      {
+        pTexture_CurrentBook     = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture( "sbquiknot", TEXTURE_16BIT_PALETTE)];
+        pTextures_5064A0[10]     = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture( "divbar", TEXTURE_16BIT_PALETTE)];
+        pTex_tab_an_6b__zoom_on  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-6b", TEXTURE_16BIT_PALETTE)];
+        pTex_tab_an_7b__zoot_on  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-7b", TEXTURE_16BIT_PALETTE)];
+        pTex_tab_an_6a__zoom_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-6a", TEXTURE_16BIT_PALETTE)];
+        pTex_tab_an_7a__zoot_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-7a", TEXTURE_16BIT_PALETTE)];
+        pBtn_Book_1 = v1->CreateButton(
+                        pViewport->uViewportX + 398,
+                        pViewport->uViewportY + 1,
+                        pTex_tab_an_6b__zoom_on->uTextureWidth,
+                        pTex_tab_an_6b__zoom_on->uTextureHeight,
+                        1,
+                        0,
+                        0x47u,
+                        0xBu,
+                        0,
+                        pGlobalTXT_LocalizationStrings[192],// "Scroll Up"
+                        pTex_tab_an_6b__zoom_on,
+                        0);
+        pBtn_Book_2 = v1->CreateButton(
+                        pViewport->uViewportX + 398,
+                        pViewport->uViewportY + 38,
+                        pTex_tab_an_7b__zoot_on->uTextureHeight,
+                        pTex_tab_an_7b__zoot_on->uTextureHeight,
+                        1,
+                        0,
+                        0x47u,
+                        0xAu,
+                        0,
+                        pGlobalTXT_LocalizationStrings[193],// "Scroll Down"
+                        pTex_tab_an_7b__zoot_on,
+                        0);
+        dword_506520 = 0;
+        memset(&pStru179, 0, 0xFA0u);
+        for ( i = dword_506528; i < 512; ++i )
+        {
+          v14 = (&dword_722F10)[4 * i];
+          if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, i) && v14 )
+          {
+            v15 = dword_506520++;
+            pStru179->field_0[v15] = i;
+          }
+        }
+      }
+      else
+      {
+        if ( v1->ptr_1C == (void *)201 )
+        {
+          pTexture_AutonotesBook   = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("sbautnot", TEXTURE_16BIT_PALETTE)];
+          pTextures_5064A0[10]     = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("divbar", TEXTURE_16BIT_PALETTE)];
+          pTex_tab_an_6b__zoom_on  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-6b", TEXTURE_16BIT_PALETTE)];
+          pTex_tab_an_7b__zoot_on  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-7b", TEXTURE_16BIT_PALETTE)];
+          pTex_tab_an_6a__zoom_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-6a", TEXTURE_16BIT_PALETTE)];
+          pTex_tab_an_7a__zoot_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-7a", TEXTURE_16BIT_PALETTE)];
+          pTexture_506394 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-1b", TEXTURE_16BIT_PALETTE)];
+          pTexture_506390 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-1a", TEXTURE_16BIT_PALETTE)];
+          pTexture_50638C = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-2b", TEXTURE_16BIT_PALETTE)];
+          pTexture_506388 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-2a", TEXTURE_16BIT_PALETTE)];
+          pTexture_506384 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-3b", TEXTURE_16BIT_PALETTE)];
+          pTexture_506380 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-3a", TEXTURE_16BIT_PALETTE)];
+          pTexture_50637C = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-5b", TEXTURE_16BIT_PALETTE)];
+          pTexture_506378 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-5a", TEXTURE_16BIT_PALETTE)];
+          pTexture_506374 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-4b", TEXTURE_16BIT_PALETTE)];
+          pTexture_506370 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-4a", TEXTURE_16BIT_PALETTE)];
+          pTexture_50636C = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-8b", TEXTURE_16BIT_PALETTE)];
+          pTexture_506368 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-8a", TEXTURE_16BIT_PALETTE)];
+          pBtn_Book_1 = v1->CreateButton(
+                          pViewport->uViewportX + 398,
+                          pViewport->uViewportY + 1,
+                          0x32u,
+                          0x22u,
+                          1,
+                          0,
+                          0x47u,
+                          0xBu,
+                          0,
+                          pGlobalTXT_LocalizationStrings[193],
+                          pTex_tab_an_6b__zoom_on,
+                          0);
+          pBtn_Book_2 = v1->CreateButton(
+                          pViewport->uViewportX + 398,
+                          pViewport->uViewportY + 38,
+                          0x32u,
+                          0x22u,
+                          1,
+                          0,
+                          0x47u,
+                          0xAu,
+                          0,
+                          pGlobalTXT_LocalizationStrings[192],
+                          pTex_tab_an_7b__zoot_on,
+                          0);
+          pBtn_Book_3 = v1->CreateButton(
+                          pViewport->uViewportX + 398,
+                          pViewport->uViewportY + 113,
+                          0x32u,
+                          0x22u,
+                          1,
+                          0,
+                          0x47u,
+                          2u,
+                          0,
+                          pGlobalTXT_LocalizationStrings[85],// "Potion Notes"
+                          pTexture_506394,
+                          0);
+          pBtn_Book_4 = v1->CreateButton(
+                          pViewport->uViewportX + 399,
+                          pViewport->uViewportY + 150,
+                          0x32u,
+                          0x22u,
+                          1,
+                          0,
+                          0x47u,
+                          3u,
+                          0,
+                          pGlobalTXT_LocalizationStrings[137],// "Fountain Notes"
+                          pTexture_50638C,
+                          0);
+          pBtn_Book_5 = v1->CreateButton(
+                          pViewport->uViewportX + 397,
+                          pViewport->uViewportY + 188,
+                          0x32u,
+                          0x22u,
+                          1,
+                          0,
+                          0x47u,
+                          4u,
+                          0,
+                          pGlobalTXT_LocalizationStrings[8],// "Obelisk Notes"
+                          pTexture_506384,
+                          0);
+          pBtn_Book_6 = v1->CreateButton(
+                          pViewport->uViewportX + 397,
+                          pViewport->uViewportY + 226,
+                          0x32u,
+                          0x22u,
+                          1,
+                          0,
+                          0x47u,
+                          5u,
+                          0,
+                          pGlobalTXT_LocalizationStrings[141],// "Seer Notes"
+                          pTexture_50637C,
+                          0);
+          pBtn_Autonotes_Misc = v1->CreateButton(
+                                  pViewport->uViewportX + 397,
+                                  pViewport->uViewportY + 264,
+                                  0x32u,
+                                  0x22u,
+                                  1,
+                                  0,
+                                  0x47u,
+                                  6u,
+                                  0,
+                                  pGlobalTXT_LocalizationStrings[123],// "Miscellaneous Notes"
+                                  pTexture_506374,
+                                  0);
+          v9 = v1->CreateButton(
+                 pViewport->uViewportX + 397,
+                 pViewport->uViewportY + 302,
+                 0x32u,
+                 0x22u,
+                 1,
+                 0,
+                 0x47u,
+                 7u,
+                 0,
+                 pGlobalTXT_LocalizationStrings[662],// "Instructors"
+                 pTexture_50636C,
+                 0);
+          v10 = dword_506528;
+          pBtn_Autonotes_Instructors = v9;
+          dword_506520 = 0;
+          while ( v10 < 196 )
+          {
+            if ( dword_506568 == dword_72371C[2 * v10] )
+            {
+              v25 = (&dword_723718_autonote_related)[8 * (signed __int16)v10];
+              if ( (short)v10 )
+              {
+                if ( (unsigned __int16)_449B57_test_bit(pParty->_autonote_bits, v10) && v25 )
+                {
+                  v11 = dword_506520++;
+                  pStru179->field_0[v11] = (signed __int16)v10;
+                }
+              }
+            }
+            ++v10;
+          }
+        }
+        else
+        {
+          if ( v1->ptr_1C == (void *)202 )
+          {
+            dword_506364 = 1;
+            pTextures_5064A0[12]     = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("sbmap", TEXTURE_16BIT_PALETTE)];
+            pTex_tab_an_6b__zoom_on  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("zoom-on", TEXTURE_16BIT_PALETTE)];
+            pTex_tab_an_7b__zoot_on  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("zoot-on", TEXTURE_16BIT_PALETTE)];
+            pTex_tab_an_6a__zoom_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("zoom-off", TEXTURE_16BIT_PALETTE)];
+            pTex_tab_an_7a__zoot_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("zoot-off", TEXTURE_16BIT_PALETTE)];
+            pTexture_506394 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tabNon", TEXTURE_16BIT_PALETTE)];
+            pTexture_506390 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tabNoff", TEXTURE_16BIT_PALETTE)];
+            pTexture_50638C = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tabSon", TEXTURE_16BIT_PALETTE)];
+            pTexture_506388 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tabSoff", TEXTURE_16BIT_PALETTE)];
+            pTexture_506384 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tabEon", TEXTURE_16BIT_PALETTE)];
+            pTexture_506380 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tabEoff", TEXTURE_16BIT_PALETTE)];
+            pTexture_50637C = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tabWon", TEXTURE_16BIT_PALETTE)];
+            pTexture_506378 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tabWoff", TEXTURE_16BIT_PALETTE)];
+            pBtn_Book_1 = v1->CreateButton(
+                            pViewport->uViewportX + 398,
+                            pViewport->uViewportY + 1,
+                            0x32u,
+                            0x22u,
+                            1,
+                            0,
+                            0x47u,
+                            0,
+                            0,
+                            pGlobalTXT_LocalizationStrings[251],// "Zoom In"
+                            pTex_tab_an_6b__zoom_on,
+                            0);
+            pBtn_Book_2 = v1->CreateButton(
+                            pViewport->uViewportX + 398,
+                            pViewport->uViewportY + 38,
+                            0x32u,
+                            0x22u,
+                            1,
+                            0,
+                            0x47u,
+                            1u,
+                            0,
+                            pGlobalTXT_LocalizationStrings[252],// "Zoom Out"
+                            pTex_tab_an_7b__zoot_on,
+                            0);
+            pBtn_Book_3 = v1->CreateButton(
+                            pViewport->uViewportX + 397,
+                            pViewport->uViewportY + 113,
+                            0x32u,
+                            0x22u,
+                            1,
+                            0,
+                            0x47u,
+                            2u,
+                            0,
+                            pGlobalTXT_LocalizationStrings[192],// Scroll Up
+                            (Texture *)"",
+                            0);
+            pBtn_Book_4 = v1->CreateButton(
+                            pViewport->uViewportX + 397,
+                            pViewport->uViewportY + 150,
+                            0x32u,
+                            0x22u,
+                            1,
+                            0,
+                            0x47u,
+                            3u,
+                            0,
+                            pGlobalTXT_LocalizationStrings[193],// Scroll Down
+                            (Texture *)"",
+                            0);
+            pBtn_Book_5 = v1->CreateButton(
+                            pViewport->uViewportX + 397,
+                            pViewport->uViewportY + 188,
+                            0x32u,
+                            0x22u,
+                            1,
+                            0,
+                            0x47u,
+                            4u,
+                            0,
+                            pGlobalTXT_LocalizationStrings[573],// "Scroll Right"
+                            (Texture *)"",
+                            0);
+            pBtn_Book_6 = v1->CreateButton(
+                            pViewport->uViewportX + 397,
+                            pViewport->uViewportY + 226,
+                            0x32u,
+                            0x22u,
+                            1,
+                            0,
+                            0x47u,
+                            5u,
+                            0,
+                            pGlobalTXT_LocalizationStrings[572],// "Scroll Left"
+                            (Texture *)"",
+                            0);
+            return;
+          }
+          if ( v1->ptr_1C == (void *)203 )
+          {
+            pTextures_5064A0[13] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("sbdate-time", TEXTURE_16BIT_PALETTE)];
+            pTex_moon_new = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("moon_new", TEXTURE_16BIT_PALETTE)];
+            pTex_moon_4   = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("moon_4", TEXTURE_16BIT_PALETTE)];
+            pTex_moon_2   = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("moon_2", TEXTURE_16BIT_PALETTE)];
+            pTex_moon_2_2 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("moon_2", TEXTURE_16BIT_PALETTE)];
+            pTex_moon_ful = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("moon_ful", TEXTURE_16BIT_PALETTE)];
+            return;
+          }
+          if ( v1->ptr_1C != (void *)224 )
+            return;
+          pTextures_5064A0[11] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("sbplayrnot", TEXTURE_16BIT_PALETTE)];
+          pTex_tab_an_6b__zoom_on = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-6b", TEXTURE_16BIT_PALETTE)];
+          pTex_tab_an_7b__zoot_on = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-7b", TEXTURE_16BIT_PALETTE)];
+          pTex_tab_an_6a__zoom_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-6a", TEXTURE_16BIT_PALETTE)];
+          pTex_tab_an_7a__zoot_off = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("tab-an-7a", TEXTURE_16BIT_PALETTE)];
+          pBtn_Book_1 = v1->CreateButton(
+                          pViewport->uViewportX + 398,
+                          pViewport->uViewportY + 1,
+                          pTex_tab_an_6b__zoom_on->uTextureWidth,
+                          pTex_tab_an_6b__zoom_on->uTextureHeight,
+                          1,
+                          0,
+                          0x47u,
+                          0xBu,
+                          0,
+                          pGlobalTXT_LocalizationStrings[192],
+                          pTex_tab_an_6b__zoom_on,
+                          0);
+          pBtn_Book_2 = v1->CreateButton(
+                          pViewport->uViewportX + 398,
+                          pViewport->uViewportY + 38,
+                          pTex_tab_an_7b__zoot_on->uTextureHeight,
+                          pTex_tab_an_7b__zoot_on->uTextureHeight,
+                          1,
+                          0,
+                          0x47u,
+                          0xAu,
+                          0,
+                          pGlobalTXT_LocalizationStrings[193],
+                          pTex_tab_an_7b__zoot_on,
+                          0);
+          dword_506520 = 0;
+          v26.uFrameX = 48;
+          v26.uFrameY = 70;
+          v26.uFrameWidth = 360;
+          v26.uFrameHeight = 264;
+          v2 = LOBYTE(pAutonoteFont->uFontHeight) - 3;
+          v26.uFrameZ = 407;
+          v26.uFrameHeight = v2 * 264 / v2;
+          v26.uFrameW = v26.uFrameHeight + 69;
+          memset(&pStru179, 0, 0xFA0u);
+          memset(byte_5C6D50, 0, 0x64u);
+          if ( dword_506528 < 29 )
+          {
+            v3 = (__int64 *)&pParty->field_3C.field_4F0[2 * dword_506528];
+            v24 = dword_506528 + 1;
+            v22 = (char *)&pStorylineText->field_4[3 * dword_506528 + 2];
+            do
+            {
+              v4 = *(char **)v22;
+              if ( *v3 )
+              {
+                if ( v4 )
+                {
+                  v5 = sub_495461(v4, uActiveCharacter - 1, 0, 0, 0, v3);
+                  v6 = pAutonoteFont->CalcTextHeight(v5, &v26, 1, 0);
+                  v7 = (v6 - 3) / (signed int)v26.uFrameHeight;
+                  v8 = v7 + 1;
+                  if ( (signed int)v7 + 1 > 0 )
+                  {
+                    memset32((void *)(4 * dword_506520 + 6043152), v24, v8);
+                    do
+                    {
+                      LODWORD(v7) = dword_506520++;
+                      byte_5C6D50[(int)v7] = BYTE4(v7);
+                      ++HIDWORD(v7);
+                    }
+                    while ( SHIDWORD(v7) < (signed int)v8 );
+                  }
+                }
+              }
+              v22 += 12;
+              ++v3;
+              ++v24;
+              __debugbreak(); // fix condition
+            }
+            while ( (signed int)v22 < (signed int)&pFactionTable->relations + 8 );
+          }
+        }
+      }
+      v12 = dword_506520;
+      dword_506520 = 0;
+      dword_506524 = v12;
+    }
+  }
+}
+
+
+
+
+//----- (00415551) --------------------------------------------------------
+void GUIWindow::DrawMessageBox(int arg0)
+{
+  unsigned int v2; // edi@1
+  GUIWindow *v3; // ebx@1
+  signed int v4; // esi@2
+  unsigned int v5; // eax@2
+  unsigned int v6; // edx@4
+  unsigned int v7; // ecx@6
+  unsigned int v8; // eax@9
+  __int32 v9; // eax@10
+  unsigned int v10; // eax@18
+  LONG v11; // ecx@18
+  unsigned int v12; // edx@18
+  unsigned int v13; // eax@18
+  const char *v14; // ecx@18
+  int v15; // eax@19
+  unsigned int v16; // esi@19
+  const char *v17; // ebx@25
+  int v18; // eax@26
+  GUIWindow v19; // [sp+Ch] [bp-60h]@18
+  POINT a2; // [sp+60h] [bp-Ch]@8
+  unsigned int v21; // [sp+68h] [bp-4h]@18
+  unsigned int v22; // [sp+74h] [bp+8h]@2
+  unsigned int v23; // [sp+74h] [bp+8h]@18
+
+  v2 = 0;
+  v3 = this;
+  if ( arg0 )
+  {
+    v4 = pViewport->uViewportX;
+    v5 = pViewport->uViewportZ;
+    v2 = pViewport->uViewportY;
+    v22 = pViewport->uViewportW;
+  }
+  else
+  {
+    v4 = 0;
+    v5 = 640;
+    v22 = 480;
+  }
+  v6 = this->uFrameX;
+  if ( (signed int)this->uFrameX >= v4 )
+  {
+    v7 = this->uFrameWidth;
+    if ( (signed int)(v7 + v6) <= (signed int)v5 )
+      goto LABEL_9;
+    v3->uFrameX = v5 - v7;
+  }
+  else
+  {
+    this->uFrameX = v4;
+  }
+  v3->uFrameY = pMouse->GetCursorPos(&a2)->y + 30;
+LABEL_9:
+  v8 = v3->uFrameY;
+  if ( (signed int)v8 >= (signed int)v2 )
+  {
+    if ( (signed int)(v8 + v3->uFrameHeight) <= (signed int)v22 )
+      goto LABEL_14;
+    v9 = pMouse->GetCursorPos(&a2)->y - v3->uFrameHeight - 30;
+  }
+  else
+  {
+    v9 = pMouse->GetCursorPos(&a2)->y + 30;
+  }
+  v3->uFrameY = v9;
+LABEL_14:
+  if ( (signed int)v3->uFrameY < (signed int)v2 )
+    v3->uFrameY = v2;
+  if ( (signed int)v3->uFrameX < v4 )
+    v3->uFrameX = v4;
+  v10 = v3->uFrameWidth;
+  v11 = v3->uFrameX;
+  v12 = v3->uFrameY;
+  v21 = v10;
+  a2.y = v11;
+  v3->uFrameZ = v10 + v11 - 1;
+  v13 = v3->uFrameHeight;
+  v3->uFrameW = v13 + v12 - 1;
+  memcpy(&v19, v3, sizeof(v19));
+  v19.uFrameX += 12;
+  v19.uFrameWidth -= 24;
+  v19.uFrameY += 12;
+  v19.uFrameHeight -= 12;
+  v19.uFrameZ = v19.uFrameWidth + v19.uFrameX - 1;
+  v23 = v12;
+  v19.uFrameW = v19.uFrameHeight + v19.uFrameY - 1;
+  v14 = v3->Hint;
+  if ( v14 )
+  {
+    v15 = pFontLucida->CalcTextHeight(v14, &v19, 0, 0);
+    v12 = v23;
+    v16 = v15 + 24;
+  }
+  else
+  {
+    v16 = v13;
+  }
+  if ( (signed int)v16 < 64 )
+    v16 = 64;
+  if ( (signed int)(v16 + v12) > 479 )
+    v16 = 479 - v12;
+  DrawPopupWindow(a2.y, v12, v21, v16);
+  v17 = v3->Hint;
+  if ( v17 )
+  {
+    v18 = pFontLucida->CalcTextHeight(v17, &v19, 0, 0);
+    v19.DrawTitleText(pFontLucida, 0, (signed int)(v16 - v18) / 2 - 14, 0, v17, 3u);
+  }
+}
+
+
+//----- (0041192C) --------------------------------------------------------
+void __cdecl InitializeBookTextures()
+{
+  //signed int v0; // ebp@3
+  //Texture **v1; // ebx@3
+
+  pAudioPlayer->StopChannels(-1, -1);
+  ++pIcons_LOD->uTexturePacksCount;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  pAudioPlayer->PlaySound((SoundID)230, 0, 0, -1, 0, 0, 0, 0);
+  pTextures_5064A0[9] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("book", TEXTURE_16BIT_PALETTE)];
+  pTexture_pagemask = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("pagemask", TEXTURE_16BIT_PALETTE)];
+  pTexture_506448   = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("ib-m5-u", TEXTURE_16BIT_PALETTE)];
+  ptr_506440        = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("ib-m5-d", TEXTURE_16BIT_PALETTE)];
+  pTexture_50643C   = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("ib-m6-u",TEXTURE_16BIT_PALETTE)];
+  //v0 = 1;
+
+  static const char *texNames[9] =
+  {
+    "SBFB00", "SBAB00", "SBWB00", "SBEB00",
+    "SBSB00", "SBMB00", "SBBB00", "SBLB00",
+  };
+
+  pTexture_506444 = pIcons_LOD->LoadTexturePtr("ib-m6-d",TEXTURE_16BIT_PALETTE);
+  for (uint i = 0; i < 8; ++i)
+  {
+    pTextures_5064A0[i] = pIcons_LOD->LoadTexturePtr(texNames[i], TEXTURE_16BIT_PALETTE);
+
+    sprintf(pTmpBuf, "tab%da", i);
+    pTextures_tabs[i][0] = pIcons_LOD->LoadTexturePtr(pTmpBuf, TEXTURE_16BIT_PALETTE);
+    sprintf(pTmpBuf, "tab%db", i);
+    pTextures_tabs[i][1] = pIcons_LOD->LoadTexturePtr(pTmpBuf, TEXTURE_16BIT_PALETTE);
+  }
+}
+
+//----- (00411AAA) --------------------------------------------------------
+void __cdecl InitializeBookFonts()
+{
+  pAudioPlayer->StopChannels(-1, -1);
+  ++pIcons_LOD->uTexturePacksCount;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  pAudioPlayer->PlaySound((SoundID)230, 0, 0, -1, 0, 0, 0, 0);
+  pTexture_mapbordr = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("mapbordr", TEXTURE_16BIT_PALETTE)];
+  pBookFont = LoadFont("book.fnt", "FONTPAL", 0);
+  pBook2Font = LoadFont("book2.fnt", "FONTPAL", 0);
+  pAutonoteFont = LoadFont("autonote.fnt", "FONTPAL", 0);
+  pSpellFont = LoadFont("spell.fnt", "FONTPAL", 0);
+}
+
+//----- (00411B59) --------------------------------------------------------
+void __fastcall LoadThumbnailLloydTexture(unsigned int uSlot, unsigned int uPlayer)
+{
+  unsigned int v2; // esi@1
+  unsigned int v3; // edi@1
+  FILE *v4; // ebx@1
+  FILE *v5; // eax@2
+  char pContainerName[64]; // [sp+Ch] [bp-44h]@1
+  unsigned int v7; // [sp+4Ch] [bp-4h]@1
+
+  v2 = uSlot;
+  v7 = uPlayer;
+  v3 = uSlot + 1;
+  sprintf(pContainerName, "data\\lloyd%d%d.pcx", uPlayer, uSlot + 1);
+  v4 = fopen(pContainerName, "rb");
+  if ( v4 )
+  {
+    pSavegameThumbnails[v2].LoadFromFILE(v4, 0, 1u);
+    fclose(v4);
+  }
+  else
+  {
+    sprintf(pContainerName, "lloyd%d%d.pcx", v7, v3);
+    v5 = pNew_LOD->FindContainer(pContainerName, 1);
+    if ( v5 )
+      pSavegameThumbnails[v2].LoadFromFILE(v5, 0, 0);
+    else
+      *((int *)&pSavegameThumbnails->pPixels + 10 * v2) = 0;
+  }
+}
+
+
+//----- (00411621) --------------------------------------------------------
+GUIButton *GUIWindow::_411621()
+{
+  Player *v1; // edi@1
+  GUIWindow *v2; // esi@1
+  unsigned int v3; // ebp@1
+  int v4; // eax@3
+  GUIButton *result; // eax@25
+  int a2; // [sp+10h] [bp-8h]@1
+  int v7; // [sp+14h] [bp-4h]@1
+
+  __debugbreak();
+
+  v1 = pPlayers[uActiveCharacter];
+  v2 = this;
+  LoadSpellbook(v1->pNumSpellBookPage);
+  v3 = 0;
+  a2 = 0;
+  v7 = (int)(&v1->spellbook.pFireSpellbook + v1->pNumSpellBookPage);
+  do
+  {
+    if ( *(char *)(v7 + v3) )
+    {
+      v4 = 2 * (12 * v1->pNumSpellBookPage + (unsigned __int8)*(&byte_4E2431[12 * v1->pNumSpellBookPage] + v3));
+      v2->CreateButton(
+        pViewport->uViewportX + dword_4E20D0[v4],
+        pViewport->uViewportY + dword_4E20D0[v4 + 1],
+        *(short *)(dword_50640C[v3] + 24),
+        *(short *)(dword_50640C[v3] + 26),
+        1,
+        79,
+        0x56u,
+        v3,
+        0,
+        "",
+        0);
+      ++a2;
+    }
+    ++v3;
+  }
+  while ( (signed int)v3 < 11 );
+  v2->CreateButton(0, 0, 0, 0, 1, 0, 0x33u, 0, 9u, "", 0);
+  if ( a2 )
+    v2->_41D08F(a2, 0, 0, 0);
+  if ( v1->pActiveSkills[12] )
+    v2->CreateButton(0x18Fu, 0xAu, 0x32u, 0x24u, 1, 0, 0x57u, 0, 0, aSpellSchoolNames[0], 0);
+  if ( v1->pActiveSkills[13] )
+    v2->CreateButton(0x18Fu, 0x2Eu, 0x32u, 0x24u, 1, 0, 0x57u, 1u, 0, aSpellSchoolNames[1], 0);
+  if ( v1->pActiveSkills[14] )
+    v2->CreateButton(0x18Fu, 0x53u, 0x32u, 0x24u, 1, 0, 0x57u, 2u, 0, aSpellSchoolNames[2], 0);
+  if ( v1->pActiveSkills[15] )
+    v2->CreateButton(0x18Fu, 0x79u, 0x32u, 0x24u, 1, 0, 0x57u, 3u, 0, aSpellSchoolNames[3], 0);
+  if ( v1->pActiveSkills[16] )
+    v2->CreateButton(0x18Fu, 0x9Eu, 0x32u, 0x24u, 1, 0, 0x57u, 4u, 0, aSpellSchoolNames[4], 0);
+  if ( v1->pActiveSkills[17] )
+    v2->CreateButton(0x190u, 0xC4u, 0x32u, 0x24u, 1, 0, 0x57u, 5u, 0, aSpellSchoolNames[5], 0);
+  if ( v1->pActiveSkills[18] )
+    v2->CreateButton(0x190u, 0xEAu, 0x32u, 0x24u, 1, 0, 0x57u, 6u, 0, aSpellSchoolNames[6], 0);
+  if ( v1->pActiveSkills[19] )
+    v2->CreateButton(0x190u, 0x10Fu, 0x32u, 0x24u, 1, 0, 0x57u, 7u, 0, aSpellSchoolNames[7], 0);
+  if ( v1->pActiveSkills[20] )
+    v2->CreateButton(0x190u, 0x133u, 0x32u, 0x24u, 1, 0, 0x57u, 8u, 0, aSpellSchoolNames[8], 0);
+  v2->CreateButton(
+    0x1DCu,
+    0x1C2u,
+    pTexture_506444->uTextureWidth,
+    pTexture_506444->uTextureHeight,
+    1,
+    78,
+    0x58u,
+    0,
+    0,
+    "",
+    0);
+  pBtn_InstallRemoveSpell = v2->CreateButton(
+                 0x1DCu,
+                 0x1C2u,
+                 0x30u,
+                 0x20u,
+                 1,
+                 78,
+                 0x58u,
+                 0,
+                 0,
+                 "",
+                 pTexture_506444,
+                 0);
+  v2->CreateButton(
+    0x231u,
+    0x1C2u,
+    ptr_506440->uTextureWidth,
+    ptr_506440->uTextureHeight,
+    1,
+    0,
+    0x71u,
+    0,
+    0,
+    pGlobalTXT_LocalizationStrings[79],
+    0);
+  result = v2->CreateButton(
+             0x231u,
+             0x1C2u,
+             0x30u,
+             0x20u,
+             1,
+             0,
+             0x71u,
+             0,
+             0,
+             pGlobalTXT_LocalizationStrings[79],
+             ptr_506440,
+             0);
+  pBtn_CloseBook = result;
+  return result;
+}
+// 50640C: using guessed type int dword_50640C[];
+
+
+//----- (004B3157) --------------------------------------------------------
+void GUIWindow::_4B3157()
+{
+  unsigned __int16 v1; // di@2
+  const char *v2; // edx@4
+  signed int v3; // edx@5
+  char *v4; // edi@9
+  int v5; // eax@45
+  int v6; // edi@45
+  char *v7; // eax@45
+  int v8; // edi@46
+  int v9; // eax@50
+  unsigned int v10; // [sp-10h] [bp-C8h]@53
+  unsigned __int16 v11; // [sp-Ch] [bp-C4h]@53
+  unsigned int v12; // [sp-Ch] [bp-C4h]@60
+  char *v13; // [sp-8h] [bp-C0h]@50
+  unsigned int v14; // [sp-8h] [bp-C0h]@60
+  unsigned int v15; // [sp-4h] [bp-BCh]@50
+  Texture *v16; // [sp-4h] [bp-BCh]@60
+  GUIWindow w; // [sp+Ch] [bp-ACh]@4
+  GUIWindow v18; // [sp+60h] [bp-58h]@2
+  int v19; // [sp+B4h] [bp-4h]@2
+
+  if ( !ptr_507BC0 )
+    return;
+  memcpy(&v18, this, sizeof(v18));
+  v18.uFrameWidth -= 18;
+  v18.uFrameZ -= 18;
+  v1 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v19 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0x15u, 0x99u, 0xE9u);
+  pRenderer->DrawTextureIndexed(0x1DDu, 0, pTexture_Dialogue_Background);
+  pRenderer->DrawTextureTransparent(
+    0x1D4u,
+    0,
+    (Texture *)(uTextureID_507B04 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507B04] : 0));
+  if ( array_5913D8[6] != (NPCData *)uNumDialogueNPCPortraits || !uHouse_ExitPic )
+  {
+    w.uFrameWidth = 130;
+    w.uFrameHeight = 2 * LOBYTE(pFontCreate->uFontHeight);
+
+    //v2 = (const char *)p2DEvents_minus1_::04[13 * (unsigned int)ptr_507BC0->ptr_1C];
+    v2 = p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].pName;
+
+    if ( v2 )
+    {
+      v3 = 2 * LOBYTE(pFontCreate->uFontHeight) - 6 - pFontCreate->CalcTextHeight(v2, &w, 0, 0);
+      if ( v3 < 0 )
+        v3 = 0;
+      v18.DrawTitleText(
+        pFontCreate,
+        0x1EAu,
+        v3 / 2 + 4,
+        v1,
+        //(const char *)p2DEvents_minus1_::04[13 * (unsigned int)ptr_507BC0->ptr_1C],
+        p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].pName,
+        3u);
+    }
+  }
+  v18.uFrameWidth += 8;
+  v18.uFrameZ += 8;
+  if ( !array_5913D8[6] )
+  {
+    if ( dword_F8B198 == 31 )
+    {
+LABEL_36:
+      sub_4B4F4F();
+      goto LABEL_58;
+    }
+    if ( ptr_F8B1E8 )
+    {
+      w.uFrameWidth = 458;
+      w.uFrameZ = 457;
+      v5 = pFontArrus->CalcTextHeight(ptr_F8B1E8, &w, 13, 0);
+      v6 = v5 + 7;
+      pRenderer->_4A6A68(
+        8u,
+        352 - (v5 + 7),
+        (Texture *)(uTextureID_Leather != -1 ? &pIcons_LOD->pTextures[uTextureID_Leather] : 0),
+        (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - (v5 + 7));
+      pRenderer->DrawTextureIndexed(8u, 347 - v6, pTexture_591428);
+      v7 = FitTextInAWindow(ptr_F8B1E8, pFontArrus, &w, 0xDu, 0);
+      ptr_507BC0->DrawText(pFontArrus, 13, 354 - v6, 0, v7, 0, 0, 0);
+    }
+    v8 = 0;
+    if ( uNumDialogueNPCPortraits <= 0 )
+      goto LABEL_58;
+    while ( 1 )
+    {
+      pRenderer->DrawTextureIndexed(
+        *(&_4E5E50_transui_x + v8 + 6 * uNumDialogueNPCPortraits - 6) - 4,
+        *(&_4E5EE0_transui_y + v8 + 6 * uNumDialogueNPCPortraits - 6) - 4,
+        (Texture *)(uTextureID_50795C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50795C] : 0));
+      pRenderer->DrawTextureIndexed(
+        *(&_4E5E50_transui_x + v8 + 6 * uNumDialogueNPCPortraits - 6),
+        *(&_4E5EE0_transui_y + v8 + 6 * uNumDialogueNPCPortraits - 6),
+        pDialogueNPCPortraits[v8]);
+      if ( uNumDialogueNPCPortraits < 4 )
+        break;
+LABEL_57:
+      ++v8;
+      if ( v8 >= uNumDialogueNPCPortraits )
+        goto LABEL_58;
+    }
+    if ( v8 + 1 == uNumDialogueNPCPortraits && uHouse_ExitPic )
+    {
+      v15 = 3;
+      v13 = pMapStats->pInfos[uHouse_ExitPic].pName;
+      v9 = 94 * v8 + 113;
+    }
+    else
+    {
+      if ( !v8 && dword_591080 )
+      {
+        v15 = 3;
+        //v13 = (char *)p2DEvents_minus1__10[13 * (unsigned int)ptr_507BC0->ptr_1C];
+        v13 = (char *)p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].pProprieterTitle;
+        v11 = v19;
+        v10 = 113;
+LABEL_56:
+        v18.DrawTitleText(pFontCreate, 0x1E3u, v10, v11, v13, v15);
+        goto LABEL_57;
+      }
+      v15 = 3;
+      v13 = array_5913D8[v8 - (dword_591080 != 0)]->pName;
+      v9 = dword_4E5EC8[v8 + 6 * uNumDialogueNPCPortraits] + pDialogueNPCPortraits[v8]->uTextureHeight + 2;
+    }
+    v11 = v19;
+    v10 = v9;
+    goto LABEL_56;
+  }
+  v4 = (char *)array_5913D8[6] - 1;
+  pRenderer->DrawTextureIndexed(
+    _4E5E50_transui_x - 4,
+    _4E5EE0_transui_y - 4,
+    (Texture *)(uTextureID_50795C != -1 ? &pIcons_LOD->pTextures[uTextureID_50795C] : 0));
+  pRenderer->DrawTextureIndexed(_4E5E50_transui_x, _4E5EE0_transui_y, pDialogueNPCPortraits[(signed int)v4]);
+  if ( pCurrentScreen == 14 )
+  {
+    CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+    goto LABEL_58;
+  }
+  if ( v4 || !dword_591080 )
+  {
+    sub_4B2A74();
+  }
+  else
+  {
+    sprintf(
+      pTmpBuf,
+      pGlobalTXT_LocalizationStrings[429],
+      //p2DEvents_minus1_::08[13 * (unsigned int)ptr_507BC0->ptr_1C],
+      p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].pProprieterName,
+      //p2DEvents_minus1__10[13 * (unsigned int)ptr_507BC0->ptr_1C]);
+      p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].pProprieterTitle);
+    v18.DrawTitleText(pFontCreate, 0x1E3u, 0x71u, v19, pTmpBuf, 3u);
+    if ( dword_F8B198 <= 18 )
+    {
+      switch ( dword_F8B198 )
+      {
+        case 18:
+          sub_4B6478();
+          break;
+        case 1:
+          sub_4B910F();
+          break;
+        case 2:
+          sub_4BA928();
+          break;
+        case 3:
+          ui_shop_teachers();
+          break;
+        case 4:
+          sub_4B9CC6();
+          break;
+        default:
+          if ( dword_F8B198 > 4 )
+          {
+            if ( dword_F8B198 <= 16 )
+            {
+              sub_4B5D7C();
+            }
+            else
+            {
+              if ( dword_F8B198 == 17 )
+                sub_4B7911();
+            }
+          }
+          break;
+      }
+      goto LABEL_58;
+    }
+    switch ( dword_F8B198 )
+    {
+      case 21:
+        sub_4B8285_prolly_draw_arcomage_result();
+        break;
+      case 22:
+        _4B7D7E_bank();
+        break;
+      case 23:
+        sub_4B705E();
+        break;
+      default:
+        if ( dword_F8B198 <= 26 )
+          break;
+        if ( dword_F8B198 <= 28 )
+        {
+          TravelByTransport();
+        }
+        else
+        {
+          if ( dword_F8B198 != 30 )
+          {
+            if ( dword_F8B198 != 31 )
+              break;
+            goto LABEL_36;
+          }
+          ui_training();
+        }
+        break;
+    }
+  }
+LABEL_58:
+  if ( array_5913D8[6] == (NPCData *)uNumDialogueNPCPortraits && uHouse_ExitPic )
+  {
+    pRenderer->DrawTextureIndexed(
+      0x22Cu,
+      0x1C3u,
+      (Texture *)(uTextureID_x_x_u != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_x_u] : 0));
+    v16 = (Texture *)(uTextureID_x_ok_u != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_ok_u] : 0);
+    v14 = 451;
+    v12 = 476;
+  }
+  else
+  {
+    v16 = (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0);
+    v14 = 445;
+    v12 = 471;
+  }
+  pRenderer->DrawTextureIndexed(v12, v14, v16);
+}
+
+
+//----- (004B1854) --------------------------------------------------------
+char *GUIWindow::_4B1854(__int64 a2)
+{
+  unsigned int v2; // edi@1
+  unsigned int v3; // esi@1
+  unsigned int v4; // ebp@1
+  unsigned int v5; // ebx@1
+  signed __int64 v6; // ST2C_8@1
+  signed __int64 v7; // kr00_8@1
+  char *v8; // eax@2
+  char *v9; // eax@7
+  char *v10; // eax@13
+  char *v11; // eax@19
+  unsigned __int16 v12; // ST0C_2@22
+  int v13; // eax@22
+  GUIWindow *v15; // [sp+0h] [bp-1Ch]@1
+  signed __int64 v16; // [sp+Ch] [bp-10h]@1
+  signed __int64 v17; // [sp+14h] [bp-8h]@1
+  unsigned int v18; // [sp+20h] [bp+4h]@1
+
+  v15 = this;
+  v2 = (unsigned __int64)(signed __int64)((double)a2 * 0.234375) >> 32;
+  v3 = (signed __int64)((double)a2 * 0.234375);
+  v4 = (unsigned __int64)((signed __int64)((double)a2 * 0.234375) / 60) >> 32;
+  v5 = (signed __int64)((double)a2 * 0.234375) / 60;
+  v6 = (signed __int64)((double)a2 * 0.234375) / 60 / 60;
+  v18 = (unsigned int)v6 / 0x18;
+  v17 = (signed __int64)__PAIR__(v2, v3) % 60;
+  v16 = (signed __int64)__PAIR__(v4, v5) % 60;
+  v7 = v6 % 24;
+  strcpy(pTmpBuf, pGlobalTXT_LocalizationStrings[532]);
+  if ( (unsigned int)v6 / 0x18 )
+  {
+    v8 = pGlobalTXT_LocalizationStrings[57];
+    if ( v18 <= 1 )
+      v8 = pGlobalTXT_LocalizationStrings[56];
+    sprintf(pTmpBuf2, "%d %s ", v18, v8);
+    strcat(pTmpBuf, pTmpBuf2);
+  }
+  if ( v7 )
+  {
+    if ( v7 <= 1 )
+      v9 = pGlobalTXT_LocalizationStrings[109];
+    else
+      v9 = pGlobalTXT_LocalizationStrings[110];
+    sprintf(pTmpBuf2, "%d %s ", v7, v9);
+    strcat(pTmpBuf, pTmpBuf2);
+  }
+  if ( v16 && !v18 )
+  {
+    if ( v16 <= 1 )
+      v10 = pGlobalTXT_LocalizationStrings[437];
+    else
+      v10 = pGlobalTXT_LocalizationStrings[436];
+    sprintf(pTmpBuf2, "%d %s ", v16, v10);
+    strcat(pTmpBuf, pTmpBuf2);
+  }
+  if ( v17 && !v7 )
+  {
+    if ( v17 <= 1 )
+      v11 = pGlobalTXT_LocalizationStrings[439];
+    else
+      v11 = pGlobalTXT_LocalizationStrings[438];
+    sprintf(pTmpBuf2, "%d %s ", v17, v11);
+    strcat(pTmpBuf, pTmpBuf2);
+  }
+  v12 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v13 = pFontArrus->CalcTextHeight(pTmpBuf, v15, 0, 0);
+  return v15->DrawTitleText(pFontArrus, 0, (212 - v13) / 2 + 101, v12, pTmpBuf, 3u);
+}
+
+
+
+//----- (0044D406) --------------------------------------------------------
+char *GUIWindow::DrawTitleText(GUIFont *a2, unsigned int uHorizontalMargin, unsigned int uVerticalMargin, unsigned __int16 uDefaultColor, const char *pInString, unsigned int uLineSpacing)
+{
+  GUIWindow *pWindow; // esi@1
+  unsigned int v8; // ebx@1
+  char *v9; // eax@1
+  char *result; // eax@1
+  unsigned int v11; // edi@1
+  signed int v12; // esi@1
+  int v13; // eax@2
+  GUIFont *pFont; // [sp+Ch] [bp-4h]@1
+  const char *Stra; // [sp+24h] [bp+14h]@5
+
+  pWindow = this;
+  pFont = a2;
+  v8 = this->uFrameWidth - uHorizontalMargin;
+  ui_current_text_color = uDefaultColor;
+  v9 = FitTextInAWindow(pInString, a2, this, uHorizontalMargin, 0);
+  result = strtok(v9, "\n");
+  v11 = uHorizontalMargin + pWindow->uFrameX;
+  v12 = uVerticalMargin + pWindow->uFrameY;
+  while ( 1 )
+  {
+    Stra = result;
+    if ( !result )
+      break;
+    v13 = (signed int)(v8 - pFont->GetLineWidth(result)) >> 1;
+    if ( v13 < 0 )
+      v13 = 0;
+    pFont->DrawTextLine(uDefaultColor, v11 + v13, v12, Stra, 640);
+    v12 += LOBYTE(pFont->uFontHeight) - uLineSpacing;
+    result = strtok(0, "\n");
+  }
+  return result;
+}
+// 5C6DB4: using guessed type int ui_current_text_color;
+
+
+
+//----- (0044CE08) --------------------------------------------------------
+char GUIWindow::DrawText(GUIFont *a2, signed int uX, int uY, unsigned int uFontColor, const char *Str, int a7, int a8, unsigned int uFontShadowColor)
+{
+  GUIWindow *v9; // edi@1
+  GUIFont *v10; // ebx@1
+  int v11; // eax@2
+  signed int v12; // esi@9
+  signed int v13; // edi@9
+  int v14; // edx@9
+  int v15; // eax@25
+  unsigned int v16; // ecx@25
+  int v17; // eax@27
+  int v18; // edi@32
+  int v19; // esi@38
+  std::string v21; // [sp-18h] [bp-50h]@2
+  const char *v22; // [sp-8h] [bp-40h]@2
+  int v23; // [sp-4h] [bp-3Ch]@2
+  char Dest[6]; // [sp+Ch] [bp-2Ch]@32
+  //char v25; // [sp+Fh] [bp-29h]@32
+  //char v26; // [sp+11h] [bp-27h]@34
+  const char *v27; // [sp+20h] [bp-18h]@25
+  int v28; // [sp+24h] [bp-14h]@25
+  int v29; // [sp+28h] [bp-10h]@1
+  size_t v30; // [sp+2Ch] [bp-Ch]@4
+  GUIWindow *v31; // [sp+30h] [bp-8h]@1
+  const char *v32; // [sp+34h] [bp-4h]@7
+  size_t pInString; // [sp+4Ch] [bp+14h]@11
+  
+  auto a1 = this;
+  v29 = 0;
+  v9 = a1;
+  v10 = a2;
+  v31 = a1;
+  if ( !Str )
+  {
+    MessageBoxW(nullptr, L"Invalid string passed!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Font.cpp:859", 0);
+    return v11;
+  }
+  v11 = strcmp(Str, "null");
+  if ( v11 )
+  {
+    v30 = strlen(Str);
+    LOBYTE(v11) = 0;
+    if ( !uX )
+      uX = 12;
+    if ( a8 )
+    {
+      v32 = Str;
+    }
+    else
+    {
+      v11 = (int)FitTextInAWindow(Str, v10, v9, uX, 0);
+      v32 = (const char *)v11;
+    }
+    v12 = uX + v9->uFrameX;
+    v13 = uY + v9->uFrameY;
+    v14 = 0;
+    if ( !a8 || (v11 = v13 + LOBYTE(v10->uFontHeight), v11 <= a8) )
+    {
+      pInString = 0;
+      if ( (signed int)v30 > 0 )
+      {
+        do
+        {
+          LOBYTE(v11) = v32[v14];
+          if ( (unsigned __int8)v11 >= v10->cFirstChar && (unsigned __int8)v11 <= v10->cLastChar
+            || (char)v11 == 12
+            || (char)v11 == 13
+            || (char)v11 == 9
+            || (char)v11 == 10 )
+          {
+            switch ( (unsigned __int8)v11 )
+            {
+              case 9u:
+                strncpy(Dest, &v32[v14 + 1], 3u);
+                Dest[3] = 0;
+                pInString += 3;
+                v29 = atoi(Dest);
+                v19 = atoi(Dest);
+                LOBYTE(v11) = (char)v31;
+                v12 = uX + v31->uFrameX + v19;
+                break;
+              case 0xAu:
+                v11 = LOBYTE(v10->uFontHeight);
+                uY = uY + v11 - 3;
+                v13 = uY + v31->uFrameY;
+                v12 = uX + v29 + v31->uFrameX;
+                if ( a8 )
+                  goto LABEL_36;
+                break;
+              case 0xCu:
+                strncpy(Dest, &v32[v14 + 1], 5u);
+                Dest[5] = 0;
+                v11 = atoi(Dest);
+                pInString += 5;
+                uFontColor = v11;
+                break;
+              case 0xDu:
+                strncpy(Dest, &v32[v14 + 1], 3u);
+                Dest[3] = 0;
+                pInString += 3;
+                v18 = atoi(Dest);
+                v11 = v10->GetLineWidth(&v32[pInString]);
+                v12 = v31->uFrameZ - v11 - v18;
+                v13 = uY + v31->uFrameY;
+                if ( a8 )
+                {
+                  v11 = LOBYTE(v10->uFontHeight);
+LABEL_36:
+                  v11 = v11 + v13 - 3;
+                  if ( v11 > a8 )
+                    return v11;
+                  break;
+                }
+                break;
+              default:
+                if ( (char)v11 == 34 && v32[v14 + 1] == 34 )
+                {
+                  ++v14;
+                  pInString = v14;
+                }
+                v27 = &v32[v14];
+                v15 = (unsigned __int8)v32[v14];
+                v16 = *((int *)&v10->cFirstChar + 3 * v15 + 9);
+                v28 = *((int *)&v10->cFirstChar + 3 * v15 + 9);
+                if ( v14 > 0 )
+                  v12 += v10->pMetrics[v15].uLeftSpacing;
+                v17 = (int)((char *)&v10[1] + v10->field_C20[v15]);
+                if ( (short)uFontColor )
+                  pRenderer->DrawText(
+                    v12,
+                    v13,
+                    (unsigned __int8 *)v17,
+                    v16,
+                    LOBYTE(v10->uFontHeight),
+                    v10->pFontPalettes[0],
+                    uFontColor,
+                    uFontShadowColor);
+                else
+                  pRenderer->DrawTextPalette(
+                    v12,
+                    v13,
+                    v17,
+                    v16,
+                    LOBYTE(v10->uFontHeight),
+                    v10->pFontPalettes[0],
+                    a7);
+                LOBYTE(v11) = v30;
+                v12 += v28;
+                if ( (signed int)pInString < (signed int)v30 )
+                {
+                  LOBYTE(v11) = 3 * *v27;
+                  v12 += v10->pMetrics[(unsigned __int8)*v27].uRightSpacing;
+                }
+                break;
+            }
+          }
+          v14 = pInString++ + 1;
+        }
+        while ( (signed int)pInString < (signed int)v30 );
+      }
+    }
+  }
+  return v11;
+}
+
+
+//----- (0044CB4F) --------------------------------------------------------
+int GUIWindow::DrawTextInRect(GUIFont *a2, unsigned int uX, unsigned int uY, unsigned int uColor, const char *Str1, int Source, int a8)
+{
+  GUIFont *v8; // edi@1
+  int v9; // ebx@1
+  int v11; // esi@3
+  unsigned __int8 v12; // cl@7
+  signed int v13; // esi@19
+  signed int v14; // ebx@19
+  unsigned __int8 v15; // cl@21
+  int v16; // eax@22
+  int v17; // ecx@22
+  int v18; // ecx@23
+  int v19; // ecx@24
+  unsigned int v20; // ecx@26
+  int v21; // eax@28
+  int v22; // ebx@34
+  int v23; // eax@34
+  int v24; // ebx@36
+  char Str; // [sp+Ch] [bp-20h]@34
+  char v26; // [sp+Fh] [bp-1Dh]@34
+  char v27; // [sp+11h] [bp-1Bh]@35
+  int v28; // [sp+20h] [bp-Ch]@17
+  GUIWindow *pWindow; // [sp+24h] [bp-8h]@1
+  size_t v30; // [sp+28h] [bp-4h]@1
+  size_t Str1a; // [sp+40h] [bp+14h]@5
+  size_t Str1b; // [sp+40h] [bp+14h]@19
+  const char *Sourcea; // [sp+44h] [bp+18h]@20
+  int v34; // [sp+48h] [bp+1Ch]@26
+
+  v8 = a2;
+  pWindow = this;
+  v30 = strlen(Str1);
+  v9 = v8->GetLineWidth(Str1);
+  if ( v9 < Source )
+  {
+    pWindow->DrawText(v8, uX, uY, uColor, Str1, 0, 0, 0);
+    return v9;
+  }
+  strcpy(pTmpBuf2, Str1);
+  v11 = 0;
+  if ( a8 )
+    _strrev(pTmpBuf2);
+  Str1a = 0;
+  if ( (signed int)v30 > 0 )
+  {
+    do
+    {
+      if ( v11 >= Source )
+        break;
+      if ( v8->IsCharValid(pTmpBuf2[Str1a]) )
+      {
+        if ( v12 < 9u )
+          goto LABEL_12;
+        if ( v12 > 0xAu )
+        {
+          if ( v12 == 12 )
+          {
+            Str1a += 5;
+          }
+          else
+          {
+            if ( v12 != 13 )
+            {
+LABEL_12:
+              if ( (signed int)Str1a > 0 )
+                v11 += v8->pMetrics[v12].uLeftSpacing;
+              v11 += *((int *)&v8->cFirstChar + 3 * v12 + 9);
+              if ( (signed int)Str1a < (signed int)v30 )
+                v11 += v8->pMetrics[v12].uRightSpacing;
+              goto LABEL_16;
+            }
+          }
+        }
+      }
+LABEL_16:
+      ++Str1a;
+    }
+    while ( (signed int)Str1a < (signed int)v30 );
+  }
+  pTmpBuf[Str1a + 1999] = 0;
+  v30 = strlen(pTmpBuf2);
+  v28 = v8->GetLineWidth(pTmpBuf2);
+  if ( a8 )
+    _strrev(pTmpBuf2);
+  Str1b = 0;
+  v13 = uX + pWindow->uFrameX;
+  v14 = uY + pWindow->uFrameY;
+  if ( (signed int)v30 > 0 )
+  {
+    Sourcea = &pTmpBuf2[1];
+    do
+    {
+      if ( v8->IsCharValid(pTmpBuf2[Str1b]) )
+      {
+        v16 = v15;
+        v17 = v15 - 9;
+        if ( v17 )
+        {
+          v18 = v17 - 1;
+          if ( v18 )
+          {
+            v19 = v18 - 2;
+            if ( v19 )
+            {
+              if ( v19 == 1 )
+              {
+                strncpy(&Str, Sourcea, 3u);
+                v26 = 0;
+                Str1b += 3;
+                Sourcea += 3;
+                v22 = atoi(&Str);
+                v23 = v8->GetLineWidth(&pTmpBuf2[Str1b]);
+                v13 = pWindow->uFrameZ - v23 - v22;
+                v14 = uY;
+              }
+              else
+              {
+                v20 = *((int *)&v8->cFirstChar + 3 * v16 + 9);
+                v34 = *((int *)&v8->cFirstChar + 3 * v16 + 9);
+                if ( (signed int)Str1b > 0 )
+                  v13 += v8->pMetrics[v16].uLeftSpacing;
+                v21 = (int)((char *)&v8[1] + v8->field_C20[v16]);
+                if ( (short)uColor )
+                  pRenderer->DrawText(
+                    v13,
+                    v14,
+                    (unsigned __int8 *)v21,
+                    v20,
+                    LOBYTE(v8->uFontHeight),
+                    v8->pFontPalettes[0],
+                    uColor,
+                    0);
+                else
+                  pRenderer->DrawTextPalette(
+                    v13,
+                    v14,
+                    v21,
+                    v20,
+                    LOBYTE(v8->uFontHeight),
+                    v8->pFontPalettes[0],
+                    0);
+                v13 += v34;
+                if ( (signed int)Str1b < (signed int)v30 )
+                  v13 += v8->pMetrics[(unsigned __int8)pTmpBuf2[Str1b]].uRightSpacing;
+              }
+            }
+            else
+            {
+              strncpy(&Str, Sourcea, 5u);
+              v27 = 0;
+              Str1b += 5;
+              Sourcea += 5;
+              uColor = atoi(&Str);
+            }
+          }
+          else
+          {
+            v24 = LOBYTE(v8->uFontHeight);
+            v13 = uX;
+            uY = uY + v24 - 3;
+            v14 = v24 + uY - 3;
+          }
+        }
+        else
+        {
+          strncpy(&Str, Sourcea, 3u);
+          v26 = 0;
+          atoi(&Str);
+          Str1b += 3;
+          Sourcea += 3;
+        }
+      }
+      ++Str1b;
+      ++Sourcea;
+    }
+    while ( (signed int)Str1b < (signed int)v30 );
+  }
+  return v28;
+}
+
+//----- (0041D12F) --------------------------------------------------------
+GUIButton *GUIWindow::CreateButton(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, int a6, int a7, unsigned int uControlID, unsigned int uControlParam, unsigned __int8 uHotkey, const char *pName, Texture *pTextures, ...)
+{
+  GUIButton *v12; // esi@1
+  unsigned int v13; // eax@1
+  unsigned int v14; // ebx@4
+  unsigned int v15; // eax@4
+  unsigned int v16; // ebx@4
+  unsigned int v17; // eax@4
+  Texture *v18; // eax@4
+  Texture **v19; // ecx@5
+  Texture **v20; // edx@5
+  GUIButton *v21; // eax@7
+
+  v12 = (GUIButton *)pAllocator->AllocNamedChunk(0, 0xBCu, "BUTTON");
+  v12->pParent = this;
+  v12->uX = uX + this->uFrameX;
+  v13 = uY + this->uFrameY;
+  v12->uHeight = uHeight;
+  v12->uY = v13;
+  v12->uWidth = uWidth;
+  if ( a6 == 2 && !uHeight )
+    v12->uHeight = uWidth;
+  v14 = v12->uX;
+  v12->uButtonType = a6;
+  v15 = v14 + uWidth - 1;
+  v16 = 0;
+  v12->uZ = v15;
+  v17 = v12->uY;
+  v12->field_2C = 0;
+  v12->uW = v17 + uHeight - 1;
+  v12->field_1C = a7;
+  v12->uControlID = uControlID;
+  v12->uControlParam = uControlParam;
+  v12->uHotkey = uHotkey;
+  strlen(pName);
+  strcpy(v12->pButtonName, pName);
+  v18 = pTextures;
+  if ( pTextures )
+  {
+    v19 = &pTextures;
+    v20 = v12->pTextures;
+    do
+    {
+      ++v19;
+      *v20 = v18;
+      ++v16;
+      ++v20;
+      v18 = *v19;
+    }
+    while ( *v19 );
+  }
+  v12->uNumTextures = v16;
+  v21 = this->pControlsTail;
+  if ( v21 )
+    v21->pNext = v12;
+  else
+    this->pControlsHead = v12;
+  v12->pPrev = this->pControlsTail;
+  this->pControlsTail = v12;
+  v12->pNext = 0;
+  ++this->uNumControls;
+  return v12;
+}
+
+//----- (00459C2B) --------------------------------------------------------
+void GUIWindow::DrawFlashingInputCursor(signed int a3, int a4, GUIFont *a2)
+{
+  signed int v4; // esi@1
+  GUIWindow *v5; // edi@1
+
+  v4 = a3;
+  v5 = this;
+  if ( GetTickCount() % 1000 > 500 )
+    DrawText(a2, v4, a4, 0, "_", 0, 0, 0);
+}
+
+
+//----- (0041C432) --------------------------------------------------------
+GUIWindow *GUIWindow::Create(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, WindowType eWindowType, int a4, int a5)
+{
+  unsigned int uNextFreeWindowID; // ebp@1
+  //int *v8; // eax@1
+  //GUIWindow *pWindow; // esi@4
+  int v10; // eax@4
+  unsigned int v11; // ebx@15
+  NPCData *v12; // ebp@15
+  void *v13; // ecx@18
+  bool v14; // eax@20
+  void *v15; // ecx@23
+  bool v16; // eax@25
+  void *v17; // ecx@28
+  bool v18; // eax@30
+  void *v19; // ecx@33
+  bool v20; // eax@35
+  void *v21; // ecx@38
+  bool v22; // eax@40
+  void *v23; // ecx@43
+  bool v24; // eax@45
+  int v25; // eax@65
+  unsigned int v26; // ebx@65
+  char *v27; // eax@71
+  const char *v29; // [sp-8h] [bp-18h]@68
+  char *v30; // [sp-4h] [bp-14h]@68
+  int uWidtha; // [sp+14h] [bp+4h]@66
+  int a4a; // [sp+20h] [bp+10h]@15
+
+  uNextFreeWindowID = 0;
+  for (uNextFreeWindowID = 0; uNextFreeWindowID < 20; ++uNextFreeWindowID)
+  {
+    if (pWindowList[uNextFreeWindowID].eWindowType == WINDOW_null)
+      break;
+  }
+
+
+  auto pWindow = &pWindowList[uNextFreeWindowID];
+  pWindow->uFrameWidth = uWidth;
+  pWindow->uFrameZ = uX + uWidth - 1;
+  pWindow->uFrameW = uY + uHeight - 1;
+  pWindow->ptr_1C = (void *)a4;
+  pWindow->Hint = (char *)a5;
+  v10 = uNumVisibleWindows;
+  pWindow->uFrameX = uX;
+  ++v10;
+  pWindow->uFrameY = uY;
+  pWindow->uFrameHeight = uHeight;
+  pWindow->eWindowType = eWindowType;
+  pWindow->field_44 = 0;
+  uNumVisibleWindows = v10;
+  pWindow->field_3C = v10;
+  pVisibleWindowsIdxs[v10] = uNextFreeWindowID + 1;
+  if ( (signed int)eWindowType <= 20 )
+  {
+    if (eWindowType != WINDOW_Chest)
+    {
+      switch (eWindowType)
+      {
+        case WINDOW_Book:
+          pWindow->InitializeBookView();
+          break;
+        case WINDOW_A:
+          dword_506978 = pCurrentScreen;
+          pCurrentScreen = 4;
+          pBtn_ExitCancel = pWindow->CreateButton(
+                         0x1D7u,
+                         0x1BDu,
+                         0xA9u,
+                         0x23u,
+                         1,
+                         0,
+                         0x71u,
+                         0,
+                         0,
+                         pGlobalTXT_LocalizationStrings[79], //"Exit"
+                         (Texture *)(uTextureID_506438 != -1 ? &pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                         0);
+          if ( pWindow->ptr_1C != (void *)1 )
+          {
+            a4a = 0;
+            v11 = LOBYTE(pFontArrus->uFontHeight) - 3;
+            v12 = GetNPCData(uDialogue_SpeakingActorNPC_ID);
+            if ( sub_445C8B(uDialogue_SpeakingActorNPC_ID) == 1 )
+            {
+              if ( v12->joins )
+              {
+                pWindow->CreateButton(0x1E0u, 0x82u, 0x8Cu, v11, 1, 0, 0x88u, 0xDu, 0, "", 0);
+                a4a = 1;
+              }
+              v13 = (void *)v12->bDrawSomeAnim;
+              if ( v13 )
+              {
+                if ( a4a < 4 )
+                {
+                  v14 = sub_4466C4(v13);
+                  if ( v14 == 1 || v14 == 2 )
+                    pWindow->CreateButton(
+                      0x1E0u,
+                      a4a++ * v11 + 130,
+                      0x8Cu,
+                      v11,
+                      1,
+                      0,
+                      0x88u,
+                      0x13u,
+                      0,
+                      "",
+                      0);
+                }
+              }
+              v15 = (void *)v12->evtb;
+              if ( v15 )
+              {
+                if ( a4a < 4 )
+                {
+                  v16 = sub_4466C4(v15);
+                  if ( v16 == 1 || v16 == 2 )
+                    pWindow->CreateButton(
+                      0x1E0u,
+                      a4a++ * v11 + 130,
+                      0x8Cu,
+                      v11,
+                      1,
+                      0,
+                      0x88u,
+                      0x14u,
+                      0,
+                      "",
+                      0);
+                }
+              }
+              v17 = (void *)v12->evtc;
+              if ( v17 )
+              {
+                if ( a4a < 4 )
+                {
+                  v18 = sub_4466C4(v17);
+                  if ( v18 == 1 || v18 == 2 )
+                    pWindow->CreateButton(
+                      0x1E0u,
+                      a4a++ * v11 + 130,
+                      0x8Cu,
+                      v11,
+                      1,
+                      0,
+                      0x88u,
+                      0x15u,
+                      0,
+                      "",
+                      0);
+                }
+              }
+              v19 = (void *)v12->evtd;
+              if ( v19 )
+              {
+                if ( a4a < 4 )
+                {
+                  v20 = sub_4466C4(v19);
+                  if ( v20 == 1 || v20 == 2 )
+                    pWindow->CreateButton(
+                      0x1E0u,
+                      a4a++ * v11 + 130,
+                      0x8Cu,
+                      v11,
+                      1,
+                      0,
+                      0x88u,
+                      0x16u,
+                      0,
+                      "",
+                      0);
+                }
+              }
+              v21 = (void *)v12->evte;
+              if ( v21 )
+              {
+                if ( a4a < 4 )
+                {
+                  v22 = sub_4466C4(v21);
+                  if ( v22 == 1 || v22 == 2 )
+                    pWindow->CreateButton(
+                      0x1E0u,
+                      a4a++ * v11 + 130,
+                      0x8Cu,
+                      v11,
+                      1,
+                      0,
+                      0x88u,
+                      0x17u,
+                      0,
+                      "",
+                      0);
+                }
+              }
+              v23 = (void *)v12->evtf;
+              if ( v23 )
+              {
+                if ( a4a < 4 )
+                {
+                  v24 = sub_4466C4(v23);
+                  if ( v24 == 1 || v24 == 2 )
+                    pWindow->CreateButton(
+                      0x1E0u,
+                      a4a++ * v11 + 130,
+                      0x8Cu,
+                      v11,
+                      1,
+                      0,
+                      0x88u,
+                      0x18u,
+                      0,
+                      "",
+                      0);
+                }
+              }
+            }
+            else
+            {
+              if ( v12->joins )
+              {
+                pWindow->CreateButton(
+                  0x1E0u,
+                  0x82u,
+                  0x8Cu,
+                  v11,
+                  1,
+                  0,
+                  0x88u,
+                  0x4Du,
+                  0,
+                  pGlobalTXT_LocalizationStrings[407],
+                  0);
+                if ( v12->uFlags & 0x80 )
+                {
+                  sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[408], v12->pName);
+                  pWindow->CreateButton(0x1E0u, v11 + 130, 0x8Cu, v11, 1, 0, 0x88u, 0x4Cu, 0, pTmpBuf, 0);
+                }
+                else
+                {
+                  pWindow->CreateButton(
+                    0x1E0u,
+                    v11 + 130,
+                    0x8Cu,
+                    v11,
+                    1,
+                    0,
+                    0x88u,
+                    0x4Cu,
+                    0,
+                    pGlobalTXT_LocalizationStrings[406],
+                    0);
+                }
+                a4a = 2;
+              }
+            }
+            pWindow->_41D08F(a4a, 1, 0, 1);
+          }
+          break;
+        case WINDOW_11:
+          dword_506978 = pCurrentScreen;
+          pCurrentScreen = 17;
+          pBtn_ExitCancel = pWindow->CreateButton(
+                         0x236u,
+                         0x1BDu,
+                         0x4Bu,
+                         0x21u,
+                         1,
+                         0,
+                         0x5Bu,
+                         0,
+                         0x4Eu,
+                         pGlobalTXT_LocalizationStrings[156],
+                         (Texture *)(uTextureID_BUTTDESC2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTDESC2] : 0),
+                         0);
+          pBtn_YES = pWindow->CreateButton(
+                         0x1E6u,
+                         0x1BDu,
+                         0x4Bu,
+                         0x21u,
+                         1,
+                         0,
+                         0x5Au,
+                         0,
+                         0x59u,
+                         pWindow->Hint,
+                         (Texture *)(uTextureID_BUTTYES2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTYES2] : 0),
+                         0);
+          pWindow->CreateButton(
+            _4E5E50_transui_x,
+            _4E5EE0_transui_y,
+            0x3Fu,
+            0x49u,
+            1,
+            0,
+            0x5Au,
+            1u,
+            0x20u,
+            pWindow->Hint,
+            0,
+            0,
+            0);
+          pWindow->CreateButton(8u, 8u, 0x1CCu, 0x158u, 1, 0, 0x5Au, 1u, 0, pWindow->Hint, 0);
+          break;
+        case WINDOW_12:
+          InitializeBookTextures();
+          pWindow->_411621();
+          break;
+        case WINDOW_13:
+          dword_506978 = pCurrentScreen;
+          pKeyActionMap->_459E5A(0, 15, pWindow);
+          pCurrentScreen = 19;
+          break;
+      }
+      return pWindow;
+    }
+LABEL_62:
+    pWindow->CreateButton(0x3Du, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+    pWindow->CreateButton(0xB1u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+    pWindow->CreateButton(0x124u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+    pWindow->CreateButton(0x197u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+    pWindow->CreateButton(0, 0, 0, 0, 1, 0, 0xB0u, 0, 9u, "", 0);
+    return pWindow;
+  }
+  if (eWindowType == WINDOW_HouseInterior)
+  {
+    pCurrentScreen = 13;
+    pBtn_ExitCancel = pWindow->CreateButton(
+                   0x1D7u,
+                   0x1BDu,
+                   0xA9u,
+                   0x23u,
+                   1,
+                   0,
+                   0x71u,
+                   0,
+                   0,
+                   pGlobalTXT_LocalizationStrings[80],
+                   (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                   0);
+    v25 = uNumDialogueNPCPortraits;
+    v26 = 0;
+    if ( uNumDialogueNPCPortraits > 0 )
+    {
+      do
+      {
+        uWidtha = v26 + 1;
+        if ( v26 + 1 == v25 && uHouse_ExitPic )
+        {
+          v30 = pMapStats->pInfos[uHouse_ExitPic].pName;
+          v29 = pGlobalTXT_LocalizationStrings[411];
+        }
+        else
+        {
+          if ( v26 || !dword_591080 )
+            v27 = array_5913D8[v26 - (dword_591080 != 0)]->pName;
+          else
+            //v27 = (char *)p2DEvents_minus1_::08[13 * a4];
+            v27 = (char *)p2DEvents[a4 - 1].pProprieterName;
+          v30 = v27;
+          v29 = pGlobalTXT_LocalizationStrings[435];
+        }
+        sprintf(&byte_591180[100 * v26], v29, v30);
+        array_5913D8[v26 + 7] = (NPCData *)pWindow->CreateButton(
+                                             *(&_4E5E50_transui_x + v26 + 6 * uNumDialogueNPCPortraits - 6),
+                                             *(&_4E5EE0_transui_y + v26 + 6 * uNumDialogueNPCPortraits - 6),
+                                             0x3Fu,
+                                             0x49u,
+                                             1,
+                                             0,
+                                             0x19Au,
+                                             v26,
+                                             0,
+                                             &byte_591180[100 * v26],
+                                             0,
+                                             0,
+                                             0);
+        ++v26;
+        v25 = uNumDialogueNPCPortraits;
+      }
+      while ( uWidtha < uNumDialogueNPCPortraits );
+    }
+    if ( v25 == 1 )
+    {
+      ptr_507BC0 = &pWindowList[uNextFreeWindowID];
+      _4B4224_UpdateNPCTopics(0);
+    }
+  }
+  else
+  {
+    if (eWindowType == WINDOW_1A)
+    {
+      dword_506978 = pCurrentScreen;
+      pCurrentScreen = 18;
+      pBtn_ExitCancel = pWindow->CreateButton(
+                     0x236u,
+                     0x1BDu,
+                     0x4Bu,
+                     0x21u,
+                     1,
+                     0,
+                     0x19Cu,
+                     0,
+                     0x4Eu,
+                     pGlobalTXT_LocalizationStrings[34],
+                     (Texture *)(uTextureID_BUTTDESC2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTDESC2] : 0),
+                     0);
+      pBtn_YES = pWindow->CreateButton(
+                     0x1E6u,
+                     0x1BDu,
+                     0x4Bu,
+                     0x21u,
+                     1,
+                     0,
+                     0x19Bu,
+                     0,
+                     0x59u,
+                     pWindow->Hint,
+                     (Texture *)(uTextureID_BUTTYES2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTYES2] : 0),
+                     0);
+      pWindow->CreateButton(
+        _4E5E50_transui_x,
+        _4E5EE0_transui_y,
+        0x3Fu,
+        0x49u,
+        1,
+        0,
+        0x19Bu,
+        1u,
+        0x20u,
+        pWindow->Hint,
+        0);
+      pWindow->CreateButton(8u, 8u, 0x1CCu, 0x158u, 1, 0, 0x19Bu, 1u, 0, pWindow->Hint, 0);
+      return pWindow;
+    }
+    if (eWindowType == WINDOW_1B)
+    {
+      pEventTimer->Pause();
+      pAudioPlayer->StopChannels(-1, -1);
+      pMouse->SetCursorBitmap("MICON2");
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[39], 2u);
+      return pWindow;
+    }
+    if (eWindowType == WINDOW_1E)
+      goto LABEL_62;
+    if (eWindowType == WINDOW_1F)
+    {
+      pMouse->SetCursorBitmap("MICON2");
+      pBtn_ExitCancel = pWindow->CreateButton(
+                     0x188u,
+                     0x13Eu,
+                     0x4Bu,
+                     0x21u,
+                     1,
+                     0,
+                     0x71u,
+                     0,
+                     0,
+                     pGlobalTXT_LocalizationStrings[34],
+                     (Texture *)(uTextureID_BUTTDESC2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTDESC2] : 0),
+                     0);
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[39], 2u);
+      ++pIcons_LOD->uTexturePacksCount;
+      pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
+      pCurrentScreen = 23;
+      if ( !pIcons_LOD->uNumPrevLoadedFiles )
+        pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+    }
+  }
+  return pWindow;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUIWindow.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,258 @@
+#pragma once
+#include "GUIButton.h"
+
+
+
+
+
+/*  251 */
+enum MENU_STATE : __int32
+{
+  MENU_MAIN = 0x0,
+  MENU_NEWGAME = 0x1,
+  MENU_CREDITS = 0x2,
+  MENU_SAVELOAD = 0x3,
+  MENU_FINISHED = 0x4,
+  MENU_5 = 0x5,
+  MENU_CREATEPARTY = 0x6,
+  MENU_7 = 0x7,
+  MENU_Credits = 0x8,
+  MENU_LOAD = 0x9,
+  MENU_10 = 0xA,
+};
+
+
+
+
+
+
+
+
+
+/*  298 */
+enum WindowType: unsigned __int32
+{
+  WINDOW_null = 0,
+  WINDOW_MainMenu = 0x1,
+  WINDOW_CharacterRecord = 0x4,
+  WINDOW_Options = 0x6,
+  WINDOW_Book = 0x9,
+  WINDOW_A = 10,
+  WINDOW_11 = 17,
+  WINDOW_12 = 18,
+  WINDOW_13 = 19,
+  WINDOW_Chest = 0x14,
+  WINDOW_MainMenu_Load = 0x18,
+  WINDOW_HouseInterior = 0x19,
+  WINDOW_1A = 26,
+  WINDOW_1B = 27,
+  WINDOW_1E = 30,
+  WINDOW_1F = 31,
+  WINDOW_FinalWindow = 0x46,
+  WINDOW_5A = 0x5A,
+  WINDOW_5E = 0x5E,
+  WINDOW_KeyMappingOptions = 0x69,
+  WINDOW_VideoOptions = 0x6A
+};
+
+/*  155 */
+#pragma pack(push, 1)
+struct GUIWindow
+{
+  GUIButton *CreateButton(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, int a6, int a7, unsigned int uControlID, unsigned int uControlParam, unsigned __int8 uHotkey, const char *pName, Texture *pTextures, ...);
+  void DrawFlashingInputCursor(signed int a3, int a4, struct GUIFont *a2);
+  int DrawTextInRect(GUIFont *a2, unsigned int uX, unsigned int uY, unsigned int uColor, const char *Str1, int Source, int a8);
+  char DrawText(GUIFont *a2, signed int uX, int uY, unsigned int uFontColor, const char *Str, int a7, int a8, unsigned int uFontShadowColor);
+  char *DrawTitleText(GUIFont *a2, unsigned int uHorizontalMargin, unsigned int uVerticalMargin, unsigned __int16 uDefaultColor, const char *pInString, unsigned int uLineSpacing);
+  char *_4B1854(__int64 a2);
+  void _4B3157();
+  GUIButton *_411621();
+  void InitializeBookView();
+  void DrawMessageBox(int arg0);
+  GUIButton *GetControl(unsigned int uID);
+  void Release();
+  void _41D08F(int a2, int a3, int a4, int a5);
+  char DrawQuickCharRecord();
+  char _41D73D_draw_buff_tooltip();
+
+  static GUIWindow *Create(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, enum WindowType eType, int a4, int a5);
+
+  unsigned int uFrameX;
+  unsigned int uFrameY;
+  unsigned int uFrameWidth;
+  unsigned int uFrameHeight;
+  unsigned int uFrameZ;
+  unsigned int uFrameW;
+  WindowType   eWindowType;
+  void *ptr_1C;
+  unsigned int uNumControls;
+  int field_24;
+  int pNumPresenceButton; 
+  int pCurrentPosActiveItem;
+  int field_30;
+  int field_34;
+  int pStartingPosActiveItem;
+  int field_3C;
+  int field_40;
+  int field_44;
+  char *Hint;
+  GUIButton *pControlsHead;
+  GUIButton *pControlsTail;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+/*  296 */
+enum UIMessageType
+{
+  UIMSG_00 = 0x0,
+  UIMSG_ChangeGameState = 0x5,
+  UIMSG_PlayArcomage = 0x1D,
+  UIMSG_MainMenu_ShowPartyCreationWnd = 0x36,
+  UIMSG_MainMenu_ShowLoadWindow = 0x37,
+  UIMSG_ShowCredits = 0x38,
+  UIMSG_ExitToWindows = 0x39,
+  UIMSG_3C = 0x3C,
+  UIMSG_PlayerCreationClickPlus = 0x3E,
+  UIMSG_PlayerCreationClickMinus = 0x3F,
+  UIMSG_PlayerCreationSelectActiveSkill = 0x40,
+  UIMSG_PlayerCreationSelectClass = 0x41,
+  UIMSG_PlayerCreationClickOK = 0x42,
+  UIMSG_PlayerCreationClickReset = 0x43,
+  UIMSG_PlayerCreationRemoveUpSkill = 0x4A,
+  UIMSG_PlayerCreationRemoveDownSkill = 0x4B,
+  UIMSG_4B = 0x4B,
+  UIMSG_LoadGame = 0x52,
+  UIMSG_SaveGame = 0x53,
+  UIMSG_ShowStatus_DateTime = 0x5C,
+  UIMSG_ShowStatus_ManaHP = 0x5D,
+  UIMSG_ShowStatus_Player = 0x5E,
+  UIMSG_ShowStatus_Food = 0x64,
+  UIMSG_ShowStatus_Funds = 0x65,
+  UIMSG_6B = 0x6B,
+  UIMSG_SelectCharacter = 0x6E,
+  UIMSG_ChangeSoundVolume = 0x6F,
+  UIMSG_ChangeMusicVolume = 0x70,
+  UIMSG_CloseBook = 0x71,
+  UIMSG_PlayerCreationSelectQuality = 0x76,
+  UIMSG_SkillUp = 0x79,
+  UIMSG_StartNewGame = 0x7C,
+  UIMSG_Game_OpenLoadGameDialog = 0x7D,
+  UIMSG_Game_OpenOptionsDialog = 0x7F,
+  UIMSG_SetGraphicsMode = 0x83,
+  UIMSG_Quit = 0x84,
+  UIMSG_PlayerCreationVoiceBack = 0x90,
+  UIMSG_PlayerCreationVoiceForward = 0x91,
+  UIMSG_StartNPCDialogue = 0xA1,
+  UIMSG_A2 = 0xA2,
+  UIMSG_A3 = 0xA3,
+  UIMSG_A4 = 0xA4,
+  UIMSG_A5 = 0xA5,
+  UIMSG_A6 = 0xA6,
+  UIMSG_A7 = 0xA7,
+  UIMSG_A8 = 0xA8,
+  UIMSG_A9 = 0xA9,
+  UIMSG_AA = 0xAA,
+  UIMSG_SelectFacePlayerBack = 0xAB,
+  UIMSG_SelectFacePlayerForward = 0xAC,
+  UIMSG_AD = 0xAD,
+  UIMSG_AE = 0xAE,
+  UIMSG_AF = 0xAF,
+  UIMSG_CycleCharacters = 0xB0,
+  UIMSG_B1 = 0xB1,
+  UIMSG_B2 = 0xB2,
+  UIMSG_B3 = 0xB3,
+  UIMSG_B4 = 0xB4,
+  UIMSG_B5 = 0xB5,
+  UIMSG_B6 = 0xB6,
+  UIMSG_B7 = 0xB7,
+  UIMSG_SetTurnSpeed = 0xB8,
+  UIMSG_ToggleWalkSound = 0xB9,
+  UIMSG_ChangeVoiceVolume = 0xBA,
+  UIMSG_ToggleShowDamage = 0xBB,
+  UIMSG_BC = 0xBC,
+  UIMSG_BD = 0xBD,
+  UIMSG_BE = 0xBE,
+  UIMSG_BF = 0xBF,
+  UIMSG_C0 = 0xC0,
+  UIMSG_C1 = 0xC1,
+  UIMSG_C2 = 0xC2,
+  UIMSG_C3 = 0xC3,
+  UIMSG_C4 = 0xC4,
+  UIMSG_ShowFinalWindow = 0xC5,
+  UIMSG_C6 = 0xC6,
+  UIMSG_C7 = 0xC7,
+  UIMSG_OpenQuestBook = 0xC8,
+  UIMSG_OpenAutonotes = 0xC9,
+  UIMSG_OpenMapBook = 0xCA,
+  UIMSG_OpenCalendar = 0xCB,
+  UIMSG_CC = 0xCC,
+  UIMSG_CD = 0xCD,
+  UIMSG_CE = 0xCE,
+  UIMSG_CF = 0xCF,
+  UIMSG_D0 = 0xD0,
+  UIMSG_D1 = 0xD1,
+  UIMSG_D2 = 0xD2,
+  UIMSG_D3 = 0xD3,
+  UIMSG_D4 = 0xD4,
+  UIMSG_D5 = 0xD5,
+  UIMSG_D6 = 0xD6,
+  UIMSG_OpenHistoryBook = 0xE0,
+  UIMSG_ToggleAlwaysRun = 0xE1,
+  UIMSG_ToggleFlipOnExit = 0xE2,
+  UIMSG_OpenRestUI = 0x199,
+  UIMSG_OpenKeyMappingOptions = 0x19F,
+  UIMSG_ResetKeyMapping = 0x1A2,
+  UIMSG_OpenVideoOptions = 0x1A5,
+  UIMSG_ToggleBloodsplats = 0x1A6,
+  UIMSG_ToggleColoredLights = 0x1A7,
+  UIMSG_ToggleTint = 0x1A8,
+};
+
+
+
+
+
+
+/*  249 */
+#pragma pack(push, 1)
+struct GUIMessage
+{
+  enum UIMessageType eType;
+  int param;
+  int field_8;
+};
+#pragma pack(pop)
+
+
+
+
+
+/*  250 */
+#pragma pack(push, 1)
+struct GUIMessageQueue
+{
+  inline GUIMessageQueue():
+    uNumMessages(0)
+  {}
+
+  void PopMessage(UIMessageType *pMsg, int *pParam, int *a4);
+  void SendMessage(UIMessageType msg, int param, unsigned int a4);
+
+  unsigned int uNumMessages;
+  GUIMessage pMessages[40];
+};
+#pragma pack(pop)
+
+extern struct GUIMessageQueue *pMessageQueue_50CBD0; // idb
+
+
+
+
+extern int pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[]; // idb
+extern struct GUIWindow *pWindow_MainMenu;
+extern struct GUIWindow pWindowList[20];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Game.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1144 @@
+#include "Game.h"
+#include "Party.h"
+#include "IndoorCamera.h"
+#include "Math.h"
+#include "LightmapBuilder.h"
+#include "Viewport.h"
+#include "Time.h"
+#include "Outdoor.h"
+#include "Overlays.h"
+#include "stru279.h"
+#include "AudioPlayer.h"
+#include "LOD.h"
+#include "OSInfo.h"
+#include "GUIWindow.h"
+#include "Party.h"
+#include "TurnEngine.h"
+#include "stru157.h"
+#include "VideoPlayer.h"
+#include "Bink_Smacker.h"
+#include "Events.h"
+#include "Arcomage.h"
+
+//#include "MM7.h"
+
+
+
+
+
+
+Game *pGame;
+
+
+
+
+
+//----- (00435694) --------------------------------------------------------
+void Game::ToggleFlags2(unsigned int uFlag)
+{
+  unsigned int v2; // eax@1
+
+  v2 = this->uFlags2;
+  if ( v2 & uFlag )
+    this->uFlags2 = v2 & ~uFlag;
+  else
+    this->uFlags2 = uFlag | v2;
+}
+
+//----- (0044103C) --------------------------------------------------------
+void Game::Draw()
+{
+  float v2; // ST24_4@11
+  //double v3; // ST28_8@11
+  int v4; // edi@26
+  int v5; // eax@35
+
+  uFlags2 &= 0xFFFFFFFDu;
+  if ( pParty->_497FC5_check_party_perception_against_level() )
+    uFlags2 |= 2u;
+  pIndoorCamera->sRotationX = pParty->sRotationX;
+  pIndoorCamera->sRotationY = pParty->sRotationY;
+  pIndoorCamera->pos.x = pParty->vPosition.x - ((unsigned __int64)(stru_5C6E00->SinCos(pParty->sRotationY)
+                                          * (signed __int64)pParty->field_18) >> 16);
+  pIndoorCamera->pos.y = pParty->vPosition.y - ((unsigned __int64)(stru_5C6E00->SinCos(pParty->sRotationY - stru_5C6E00->uIntegerHalfPi)
+                                          * (signed __int64)pParty->field_18) >> 16);
+  pIndoorCamera->pos.z = pParty->vPosition.z + pParty->sEyelevel;
+  pIndoorCamera->Initialize2();
+  pIndoorCameraD3D->CreateWorldMatrixAndSomeStuff();
+  pIndoorCameraD3D->_4374E8_ProllyBuildFrustrum();
+
+  if ( pVideoPlayer->AnyMovieLoaded() )
+  {
+    if ( pRenderer->pRenderD3D )
+      goto LABEL_22;
+    pRenderer->BeginSceneD3D();
+    pMouse->DrawCursorToTarget();
+  }
+  else
+  {
+    if ( pParty->vPosition.x != pParty->vPrevPosition.x | pParty->sRotationY != pParty->sPrevRotationY | pParty->vPosition.y != pParty->vPrevPosition.z 
+		| pParty->sRotationX != pParty->sPrevRotationX | pParty->vPosition.z != pParty->vPrevPosition.y | pParty->sEyelevel != pParty->sPrevEyelevel )
+      pParty->uFlags |= 2u;
+    pParty->vPrevPosition.x = pParty->vPosition.x;
+    pParty->vPrevPosition.y = pParty->vPosition.z;
+    //v0 = &pRenderer;
+    pParty->sPrevRotationY = pParty->sRotationY;
+    pParty->vPrevPosition.z = pParty->vPosition.y;
+    pParty->sPrevRotationX = pParty->sRotationX;
+    pParty->sPrevEyelevel = pParty->sEyelevel;
+    pRenderer->BeginSceneD3D();
+
+    if ( !pRenderer->pRenderD3D )
+      pMouse->DrawCursorToTarget();
+    if ( !sub_4226C2() || viewparams->field_48 == 1 )
+    {
+      if ( pRenderer->pRenderD3D )
+      {
+        v2 = (double)(((signed int)pMiscTimer->uTotalGameTimeElapsed >> 2) & 0x1F) * 0.032258064 * 6.0;
+        //v3 = v2 + 6.7553994e15;
+        //pRenderer->field_1036A8_bitmapid = LODWORD(v3);
+        pRenderer->field_1036A8_bitmapid = floorf(v2 + 0.5f);
+      }
+
+      if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+        pIndoor->Draw();
+      else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+        pOutdoor->Draw();
+
+      if (pRenderer->pRenderD3D)
+      {
+        pDecalBuilder->DrawBloodsplats();
+        if (pRenderer->pRenderD3D)
+          pGame->pLightmapBuilder->DrawLightmaps(2);
+      }
+    }
+  }
+  pRenderer->DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene();
+LABEL_22:
+  pRenderer->BeginScene();
+  if (pRenderer->pRenderD3D)
+    pMouse->DrawCursorToTarget();
+  if (pOtherOverlayList->field_3EC)
+    viewparams->bRedrawGameUI = 1;
+  v4 = viewparams->bRedrawGameUI;
+  GameUI_DrawStatusBar();
+  if (!viewparams->bRedrawGameUI)
+  {
+    GameUI_DrawRightPanelItems();
+  }
+  else
+  {
+    GameUI_DrawRightPanelFrames();
+    GameUI_DrawStatusBar_2();
+    viewparams->bRedrawGameUI = false;
+  }
+  if (!pVideoPlayer->pSmackerMovie)
+  {
+    GameUI_DrawMinimap(488, 16, 625, 133, viewparams->uMinimapZoom, pParty->uFlags & 2);
+    if (v4)
+    {
+      if ( !sub_4226C2() && pRenderer->pRenderD3D)
+        pRenderer->FillRectFast(pViewport->uViewportX, pViewport->uViewportY, pViewport->uViewportZ - pViewport->uViewportX,
+          pViewport->uViewportW - pViewport->uViewportY + 1, pRenderer->uTargetGMask | pRenderer->uTargetBMask);
+      viewparams->field_48 = 0;
+    }
+  }
+  v5 = pOtherOverlayList->field_3EC;
+  pOtherOverlayList->field_3EC = 0;
+  viewparams->bRedrawGameUI = v5;
+  GameUI_DrawPartySpells();
+  //if (v4 || pParty->pHirelings[0].evtc || pParty->pHirelings[1].evtc ) 
+    //DrawHiredNPCs();//Ritor1: it's temporarily
+  GameUI_DrawPortraits(v4);
+  GameUI_DrawLifeManaBars();
+  GameUI_DrawCharacterSelectionFrame();
+  if ( sub_44100D() )
+    draw_right_panel();
+  if ( !pVideoPlayer->AnyMovieLoaded() )
+  {
+    pStru6Instance->DrawPlayerBuffAnims();
+    pOtherOverlayList->_441964(v4);
+    GameUI_DrawTorchlightAndWizardEye();
+  }
+  GUI_UpdateWindows();
+  pParty->_4909F4();
+  ++stru_51076C.field_8;
+  dword_5B5924 = 0;
+  if (v4)
+    pMouse->field_14 = 1;
+  pMouse->_469EA4();
+  pMouse->DrawCursor();
+  pMouse->_469E1C();
+  pRenderer->EndScene();
+  pRenderer->Present();
+  pParty->uFlags &= 0xFFFFFFFDu;
+}
+
+
+//----- (0047A815) --------------------------------------------------------
+void Game::DrawParticles()
+{
+  pParticleEngine->Draw();
+}
+
+//----- (00463149) --------------------------------------------------------
+void Game::Loop()
+{
+  //signed int v0; // ebp@3
+  //signed int v1; // esi@4
+  //Render *v2; // edi@7
+  //signed int v3; // esi@7
+  signed int pNewNPCsCount; // ecx@58
+  char *pFlags; // eax@59
+  Player *pPlayer; // esi@65
+  OtherOverlay *pOtherOverlay; // esi@67
+  signed int v8; // edi@67
+  int pPlayerNum; // edi@69
+  int *pHealth; // esi@71
+  signed int v11; // esi@78
+  int v12; // eax@83
+  const char *pLocationName; // [sp-4h] [bp-68h]@74
+  bool bLoading; // [sp+10h] [bp-54h]@1
+  signed int bLoadinga; // [sp+10h] [bp-54h]@19
+  signed int v16; // [sp+14h] [bp-50h]@8
+  int v17[4]; // [sp+18h] [bp-4Ch]@80
+  MSG Msg; // [sp+28h] [bp-3Ch]@20
+  char Source[64]; // [sp+44h] [bp-20h]@76
+
+  bLoading = uCurrentMenuID == MENU_LOAD;
+  SetCurrentMenuID((MENU_STATE)-1);
+  if (bLoading)
+  {
+    pParty->Reset();
+    dword_6BE340 = 0;
+    uGameState = 0;
+    LoadGame(uLoadGameUI_SelectedSlot);
+  }
+
+  for (uint i = 1; i < 5; ++i)
+    for (uint j = 1; j < 6; ++j)
+    {
+      sprintf(pTmpBuf, "data\\lloyd%d%d.pcx", i, j);
+      remove(pTmpBuf);
+    }
+
+  LoadPlayerPortraintsAndVoices();
+  pIcons_LOD->dword_11B84 = pIcons_LOD->uNumLoadedFiles;
+  pAudioPlayer->SetMusicVolume(pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0);
+
+  while ( 2 )
+  {
+    v16 = 1;
+    if (pMessageQueue_50CBD0->uNumMessages)
+      pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+
+    pPartyActionQueue->uNumActions = 0;
+    if (pParty->bTurnBasedModeOn)
+    {
+      pTurnEngine->End(false);
+      pParty->bTurnBasedModeOn = false;
+    }
+    DoPrepareWorld(bLoading, 1);
+    pEventTimer->Resume();
+    dword_6BE364_game_settings_1 |= 0x80;
+    dword_6BE340 = 2;
+    // uGame_if_0_else_ui_id__11_save__else_load__8_drawSpellInfoPopup__22_final_window__26_keymapOptions__2_options__28_videoOptions = 0;
+	pCurrentScreen = 0;
+    if (pAsyncMouse)
+      pAsyncMouse->Resume();
+    if (pGame->pKeyboardInstance->bUsingAsynKeyboard && pAsyncKeyboard )
+      pAsyncKeyboard->Resume();
+    if ( pRenderer->pRenderD3D )
+      pGame->pVisInstance->_4C1A02();
+    bLoadinga = 0;
+    do
+    {
+      while ( PeekMessageA(&Msg, 0, 0, 0, PM_REMOVE) )
+      {
+        if ( Msg.message == WM_QUIT )
+          Game_DeinitializeAndTerminate(0);
+        TranslateMessage(&Msg);
+        DispatchMessageA(&Msg);
+      }
+      if (dword_6BE364_game_settings_1 & 0x0100 )
+      {
+        WaitMessage();
+        continue;
+      }
+      pGame->_44EEA7();
+      GameUI_WritePointedObjectStatusString();
+      ProcessInputActions();
+      GameUI_MsgProc();
+      if ( pArcomageGame->bGameInProgress )
+      {
+        ArcomageGame::Loop();
+//LABEL_89:
+        pRenderer->Present();
+        continue;
+      }
+      if (pAsyncMouse)
+        pAsyncMouse->_46B736_consume_click_lists(1);
+      if ( pVideoPlayer->pSmackerMovie && !SmackWait(pVideoPlayer->pSmackerMovie) )
+      {
+        pRenderer->BeginScene();
+        pMouse->DrawCursorToTarget();
+        pVideoPlayer->SmackUpdatePalette(pVideoPlayer->hWindow);
+        pMouse->_469EA4();
+        pRenderer->EndScene();
+      }
+      if ( pVideoPlayer->pBinkMovie && !BinkWait(pVideoPlayer->pBinkMovie) )
+      {
+        pRenderer->BeginScene();
+        pMouse->DrawCursorToTarget();
+        pVideoPlayer->BinkUpdatePalette(pVideoPlayer->hWindow);
+        pMouse->_469EA4();
+        pRenderer->EndScene();
+      }
+      pEventTimer->Update();
+      pMiscTimer->Update();
+      OnTimer(0);
+      GameUI_StatusBar_UpdateTimedString(0);
+      if ( pMiscTimer->bPaused && !pEventTimer->bPaused )
+        pMiscTimer->Resume();
+      if ( pEventTimer->bTackGameTime && !pParty->bTurnBasedModeOn )
+        pEventTimer->bTackGameTime = 0;
+      if ( !pEventTimer->bPaused && !uGameState )
+      {
+        if ( !pEventTimer->bTackGameTime )
+          _494035_timed_effects__water_walking_damage__etc();
+        if ( dword_6BE364_game_settings_1 & 1 )
+        {
+          dword_6BE364_game_settings_1 &= 0xFFFFFFFEu;
+        }
+        else
+        {
+          sub_401A91_AI();
+          sub_46BDC0_UpdateUserInput_and_MapSpecificStuff();
+        }
+      }
+      if ( v16 )
+      {
+        v16 = 0;
+        viewparams->bRedrawGameUI = true;
+      }
+      //pAudioPlayer->_4AAFCF();Ritor1: it's temporarily
+      if (uGameState == 1)
+        //goto LABEL_96;
+	  {
+		bLoadinga = 1;
+        continue;
+	  }
+      if (uGameState == 2)
+      {
+        pAudioPlayer->StopChannels(-1, -1);
+        PrepareWorld(0);
+        uGameState = 0;
+        continue;
+      }
+      if ( (signed int)uGameState <= 2 )
+        //goto LABEL_85;
+		pGame->Draw();
+        continue;
+      if ( (signed int)uGameState <= 5 || uGameState == 7 )
+      {
+//LABEL_96:
+        bLoadinga = 1;
+        continue;
+      }
+      if ( uGameState != 8 )
+      {
+        if ( uGameState != 9 )
+        {
+//LABEL_85:
+          pGame->Draw();
+          continue;
+        }
+        pRenderer->BeginScene();
+        GUI_UpdateWindows();
+        pRenderer->EndScene();
+        //goto LABEL_89;
+		pRenderer->Present();
+        continue;
+      }
+      pAudioPlayer->StopChannels(-1, -1);
+      memset(pParty->pHirelings, 0, 0x4Cu);
+      memset(&pParty->pHirelings[1], 0, 0x4Cu);
+      pNewNPCsCount = 0;
+      if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+      {
+        pFlags = (char *)&pNPCStats->pNewNPCData[0].uFlags;
+        do
+        {
+          if ( *((int *)pFlags + 6) )
+            *pFlags &= 0x7Fu;
+          ++pNewNPCsCount;
+          pFlags += 76;
+        }
+        while ( pNewNPCsCount < (signed int)pNPCStats->uNumNewNPCs );
+      }
+      pVideoPlayer->PlayDeathMovie();
+      if ( pVideoPlayer->AnyMovieLoaded() )
+        pVideoPlayer->Unload();
+      SaveGame(0, 0);
+      ++pParty->uNumDeaths;
+      pPlayer = pParty->pPlayers;
+      do
+      {
+        pPlayer->SetVariable(VAR_Award, 85);
+        ++pPlayer;
+      }
+      while ( (signed int)pPlayer < (signed int)pParty->pHirelings );
+      pParty->field_764 = 0;
+      pParty->uTimePlayed += 0x276000ui64;
+      LOWORD(pParty->uFlags) &= 0xFDFBu;
+      pParty->SetGold(0);
+      pOtherOverlay = pOtherOverlayList->pOverlays;
+      v8 = 50;
+      do
+      {
+        pOtherOverlay->Reset();
+        ++pOtherOverlay;
+        --v8;
+      }
+      while ( v8 );
+      memset(pParty->pPartyBuffs, 0, 0x140u);
+      pPlayerNum = 1;
+      if ( pParty->bTurnBasedModeOn == 1 )
+      {
+        pTurnEngine->End(1);
+        pParty->bTurnBasedModeOn = 0;
+      }
+      pHealth = &pParty->pPlayers[0].sHealth;//193C
+      do
+      {
+        memset(pHealth - 0x64F, 0, 0xA0u);//(pConditions, 0, 160)
+        memset(pHealth - 0x67, 0, 0x180u);//(pPlayerBuffs[0], 0, 384)
+        *pHealth = 1;
+        pHealth += 1743; //6CF
+        uActiveCharacter = 1;
+      }
+      while ( (signed int)pHealth < (signed int)&pParty->field_871C[567] );
+      if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 136) )
+      {
+        pParty->vPosition.x = -17331;            // respawn in harmondale
+        pParty->vPosition.y = 12547;
+        pParty->vPosition.z = 465;
+        pParty->sRotationY = 0;
+        pLocationName = "out02.odm";
+      }
+      else
+      {
+        pParty->vPosition.x = 12552;             // respawn on emerald isle
+        pParty->vPosition.y = 1816;
+        pParty->vPosition.z = 0;
+        pParty->sRotationY = 512;
+        pLocationName = "out01.odm";
+      }
+      strcpy(Source, pLocationName);
+      pParty->uFallStartY = pParty->vPosition.z;
+      pParty->sRotationX = 0;
+      pParty->uFallSpeed = 0;
+      pParty->field_6E4 = 0;
+      pParty->field_6E0 = 0;
+      if ( _strcmpi(Source, pCurrentMapName) )
+      {
+        strcpy(pCurrentMapName, Source);
+        _5B65A8_npcdata_uflags_or_other = pParty->vPosition.x;
+        _5B65AC_npcdata_fame_or_other = pParty->vPosition.y;
+        _5B65B0_npcdata_rep_or_other = pParty->vPosition.z;
+        _5B65B4_npcdata_loword_house_or_other = pParty->sRotationY;
+        _5B65B8_npcdata_hiword_house_or_other = pParty->sRotationX;
+        dword_5B65C0 = 1;
+        PrepareWorld(1);
+      }
+      InitializeActors();
+      v11 = 0;
+      do
+      {
+        if ( pPlayers[pPlayerNum]->CanAct() )
+          v17[v11++] = pPlayerNum;
+        ++pPlayerNum;
+      }
+      while ( pPlayerNum <= 4 );
+      if ( v11 )
+      {
+        v12 = rand();
+        pPlayers[v17[v12 % v11]]->PlaySound(99, 0);
+      }
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[524], 2u);// "Once again you've cheated death!.." "Âû ñíîâà îáõèòðèëè ñìåðòü! …"
+      uGameState = 0;
+    }
+    while ( !bLoadinga );
+    dword_6BE340 = 0;
+    pEventTimer->Pause();
+    ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
+    if ( uGameState == 3 )
+    {
+      sub_491E3A();
+      LoadPlayerPortraintsAndVoices();
+      uGameState = 0;
+      pIcons_LOD->dword_11B84 = pIcons_LOD->uNumLoadedFiles;
+      bLoading = true;
+      continue;
+    }
+    break;
+  }
+  pCurrentScreen = 16;//îêíî âèäåî ðîëèêà 
+  sub_491E3A();
+}
+
+
+
+//----- (0044F192) --------------------------------------------------------
+void Game::PrepareBloodsplats()
+{
+  for (uint i = 0; i < uNumBloodsplats; ++i)
+  {
+    pBloodsplatContainer->AddBloodsplat(
+        pBloodsplats[i].x,
+        pBloodsplats[i].y,
+        pBloodsplats[i].z,
+        pBloodsplats[i].radius,
+        pBloodsplats[i].r,
+        pBloodsplats[i].g,
+        pBloodsplats[i].b);
+   }
+}
+
+
+//----- (0044F120) --------------------------------------------------------
+void Game::PushStationaryLights(int a2)
+{
+  signed int v3; // ebx@1
+  char *v4; // esi@2
+
+  auto v2 = this;
+  v3 = 0;
+  if ( (signed int)this->uNumStationaryLights > 0 )
+  {
+    v4 = (char *)&this->pStationaryLights[0].vRGBColor.y;
+    do
+    {
+      pStationaryLightsStack->AddLight(
+        (signed __int64)*((float *)v4 - 4),
+        (signed __int64)*((float *)v4 - 3),
+        (signed __int64)*((float *)v4 - 2),
+        (signed __int64)*((float *)v4 + 2),
+        (signed __int64)*((float *)v4 - 1),
+        (signed __int64)*(float *)v4,
+        (signed __int64)*((float *)v4 + 1),
+        byte_4E94D0);
+      ++v3;
+      v4 += 28;
+    }
+    while ( v3 < (signed int)v2->uNumStationaryLights );
+  }
+}
+// 4E94D0: using guessed type char byte_4E94D0;
+
+//----- (0044F0FD) --------------------------------------------------------
+void Game::_44F0FD()
+{
+  ToggleFlags(0x40u);
+
+  if ( !(uFlags & 0x40) )
+  {
+    uNumBloodsplats = 0;
+    field_E0C = 0;
+  }
+}
+
+//----- (0044F0D8) --------------------------------------------------------
+void Game::ToggleFlags(uint uMask)
+{
+  if (uFlags & uMask)
+    uFlags &= ~uMask;
+  else
+    uFlags |= uMask;
+}
+
+
+//----- (0044F07B) --------------------------------------------------------
+bool Game::_44F07B()
+{
+  if (!pKeyboardInstance->IsKeyBeingHeld(VK_SHIFT) &&
+      !pKeyboardInstance->IsKeyBeingHeld(VK_LSHIFT) &&
+      !pKeyboardInstance->IsKeyBeingHeld(VK_LSHIFT) ||
+
+      (pKeyboardInstance->WasKeyPressed(VK_F11) == 0 &&
+       pKeyboardInstance->WasKeyPressed(VK_F11)))
+    return true;
+  return false;
+}
+
+//----- (0044EEA7) --------------------------------------------------------
+bool Game::_44EEA7()
+{
+  //Game *v1; // esi@1
+  double v2; // st7@2
+  float depth; // ST00_4@9
+  bool result; // eax@9
+  unsigned int v5; // eax@14
+  __int64 v6; // kr00_8@21
+  unsigned int y; // [sp+4h] [bp-24h]@2
+  unsigned int x; // [sp+8h] [bp-20h]@2
+  bool v9; // [sp+Ch] [bp-1Ch]@2
+  stru157 *v10; // [sp+10h] [bp-18h]@2
+  stru157 *v11; // [sp+14h] [bp-14h]@2
+  POINT a2; // [sp+20h] [bp-8h]@1
+
+  //v1 = this;
+  ++qword_5C6DF0;
+  pParticleEngine->UpdateParticles();
+  pMouseInstance->GetCursorPos(&a2);
+  if ( sub_4637E0_is_there_popup_onscreen() )
+  {
+    v11 = &a5;
+    v10 = &stru_F93E30;
+    v9 = 0;
+    x = a2.y;
+    y = a2.x;
+    v2 = GetPickDepth();
+  }
+  else
+  {
+    if ( uFlags2 & 0x10 )
+    {
+      v11 = &a5;
+      v10 = &stru_F93E1C;
+    }
+    else
+    {
+      static bool __init_flag = false;
+      static stru157 static_sub_44EEA7_stru157;
+      if (!__init_flag)
+      {
+        __init_flag = true;
+        static_sub_44EEA7_stru157.field_8 = -1;
+        static_sub_44EEA7_stru157.field_0 = 0;
+        static_sub_44EEA7_stru157.field_4 = 2;
+        static_sub_44EEA7_stru157.field_C = 0;
+        static_sub_44EEA7_stru157.field_10 = 0;
+      }
+      v11 = &a5;
+      v10 = &static_sub_44EEA7_stru157;
+    }
+    v2 = 5120.0;
+    v9 = 0;
+    x = a2.y;
+    y = a2.x;
+  }
+  depth = v2;
+
+  PickMouse(depth, y, x, v9, v10, v11);
+  pLightmapBuilder->std__vector_000004_size = 0;
+  pLightmapBuilder->std__vector_183808_size = 0;
+  pDecalBuilder->std__vector_pDecals_size = 0;
+  pDecalBuilder->field_308008 = 0;
+  result = _44F07B();
+  if ( result )
+  {
+    if ( uFlags & 8 )
+      LOBYTE(pStru10Instance->field_4) = 0;
+    if ( pRenderer->pRenderD3D && uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    {
+      v5 = GetLevelFogColor();
+      pRenderer->uFogColor = v5 & 0xFFFFFF;
+    }
+    if (uFlags & 0x0400)
+      uFlags2 |= 0x01;
+    if ( !pRenderer->pRenderD3D && uCurrentlyLoadedLevelType == LEVEL_Outdoor && pMobileLightsStack->uNumLightsActive )
+    {
+      uFlags2 |= 0x01;
+      field_E10 = qword_5C6DF0;
+    }
+    v6 = qword_5C6DF0 - field_E10;
+    if ( qword_5C6DF0 - field_E10 == 1 )
+      uFlags2 |= v6;
+    if (uNumStationaryLights_in_pStationaryLightsStack != pStationaryLightsStack->uNumLightsActive )
+    {
+      uFlags2 |= 1u;
+      uNumStationaryLights_in_pStationaryLightsStack = pStationaryLightsStack->uNumLightsActive;
+    }
+    _44E904();
+    LOBYTE(result) = 1;
+  }
+  return result;
+}
+
+
+//----- (0044EDE4) --------------------------------------------------------
+bool Game::AlterGamma(BLVFace *pFace, unsigned int *pColor)
+{
+  if (pGame->uFlags2 & 2 && pFace->uAttributes & 2)
+  {
+    *pColor = ReplaceHSV(*pColor, 1.0, fSaturation, -1.0);
+    return true;
+  }
+  else
+    return false;
+}
+
+//----- (0044EE30) --------------------------------------------------------
+bool Game::_44EE30(ODMFace *a2, int a3)
+{
+  if (uFlags2 & 0x2 && a2->uAttributes & 0x02)
+  {
+    *(int *)a3 = ReplaceHSV(*(int *)a3, 1.0, fSaturation, -1.0);
+    return true;
+  }
+  else
+    return false;
+}
+
+
+//----- (004645FA) --------------------------------------------------------
+void Game::Deinitialize()
+{
+  struct tagRECT Rect; // [sp+0h] [bp-10h]@6
+
+  if (pAsyncMouse)
+    pAsyncMouse->Suspend();
+  if (pGame->pKeyboardInstance->bUsingAsynKeyboard && pAsyncKeyboard)
+    pAsyncKeyboard->Suspend();
+  WriteWindowsRegistryInt("startinwindow", pRenderer->bWindowMode);
+  if ( GetWindowRect(hWnd, &Rect) && pRenderer->bWindowMode )
+  {
+    WriteWindowsRegistryInt("window X", Rect.left);
+    WriteWindowsRegistryInt("window Y", Rect.top);
+  }
+  WriteWindowsRegistryInt("debug flags", stru_51076C.registry_debug_flags);
+  WriteWindowsRegistryInt("valAlwaysRun", bAlwaysRun);
+  pItemsTable->Release();
+  pNPCStats->Release();
+  if (pAsyncKeyboard)
+    pAsyncKeyboard->Release();
+  if (pAsyncMouse)
+    pAsyncMouse->Release();
+  if (pMouse)
+    pMouse->Deactivate();
+
+  pAudioPlayer->Release();//error
+  pNew_LOD->FreeSubIndexAndIO();
+  pGames_LOD->FreeSubIndexAndIO();
+  ClipCursor(0);
+  Game::Destroy();
+}
+
+//----- (0044EE7C) --------------------------------------------------------
+bool Game::draw_debug_outlines()
+{
+  if (uFlags & 0x04)
+  {
+    pLightmapBuilder->DrawDebugOutlines(-1);
+    pDecalBuilder->DrawDecalDebugOutlines();
+  }
+  return true;
+}
+
+//----- (0044EC23) --------------------------------------------------------
+int Game::_44EC23(stru148 *a2, int *a3, signed int a4)
+{
+  double v4; // st7@4
+  //double v5; // ST00_8@4
+  signed int v6; // eax@5
+  //double v7; // ST00_8@6
+  signed int result; // eax@8
+  //double v9; // ST00_8@9
+  //double v10; // ST00_8@11
+  float a2a; // [sp+14h] [bp+8h]@4
+  float a3a; // [sp+18h] [bp+Ch]@4
+  float a3b; // [sp+18h] [bp+Ch]@6
+  float a4a; // [sp+1Ch] [bp+10h]@9
+  float a4b; // [sp+1Ch] [bp+10h]@11
+
+  if ( this->uFlags2 & 2 && a2->field_59 == 5 && a2->pODMFace->uAttributes & 2 )
+  {
+    v4 = (double)a4;
+    a2a = v4;
+    *a3 |= 2u;
+    a3a = (1.0 - this->fSaturation) * v4;
+    //v5 = a3a + 6.7553994e15;
+    //if ( SLODWORD(v5) >= 0 )
+    if (floorf(a3a + 0.5f) >= 0 )
+    {
+      a3b = (1.0 - this->fSaturation) * a2a;
+      //v7 = a3b + 6.7553994e15;
+      //v6 = LODWORD(v7);
+      v6 = floorf(a3b + 0.5f);
+    }
+    else
+    {
+      v6 = 0;
+    }
+    if ( a4 >= v6 )
+    {
+      a4a = (1.0 - fSaturation) * a2a;
+      //v9 = a4a + 6.7553994e15;
+      //if ( SLODWORD(v9) >= 0 )
+      if (floorf(a4a + 0.5f) >= 0)
+      {
+        a4b = (1.0 - fSaturation) * a2a;
+        //v10 = a4b + 6.7553994e15;
+        //result = LODWORD(v10);
+        result = floorf(a4b + 0.5f);
+      }
+      else
+      {
+        result = 0;
+      }
+    }
+    else
+    {
+      result = a4;
+    }
+  }
+  else
+  {
+    result = -1;
+  }
+  return result;
+}
+
+
+
+//----- (00465C8B) --------------------------------------------------------
+Game *Game::Create()
+{
+  return new Game;
+}
+
+//----- (00465CF3) --------------------------------------------------------
+void Game::Destroy()
+{
+  if (pGame)
+    delete pGame;
+  pGame = nullptr;
+}
+
+//----- (0044ED0A) --------------------------------------------------------
+signed int Game::_44ED0A(BLVFace *a2, int *a3, signed int a4)
+{
+  double v4; // st7@3
+  //double v5; // ST00_8@3
+  signed int v6; // eax@4
+  //double v7; // ST00_8@5
+  signed int result; // eax@7
+  //double v9; // ST00_8@8
+  //double v10; // ST00_8@10
+  float v11; // [sp+14h] [bp+8h]@3
+  float v12; // [sp+18h] [bp+Ch]@3
+  float v13; // [sp+18h] [bp+Ch]@5
+  float v14; // [sp+1Ch] [bp+10h]@8
+  float v15; // [sp+1Ch] [bp+10h]@10
+
+  if ( this->uFlags2 & 2 && a2->uAttributes & 2 )
+  {
+    v4 = (double)a4;
+    v11 = v4;
+    *a3 |= 2u;
+    v12 = (1.0 - this->fSaturation) * v4;
+    //v5 = v12 + 6.7553994e15;
+    if (floorf(v12 + 0.5f)/* SLODWORD(v5)*/ >= 0 )
+    {
+      v13 = (1.0 - this->fSaturation) * v11;
+      //v7 = v13 + 6.7553994e15;
+      //v6 = LODWORD(v7);
+      v6 = floorf(v13 + 0.5f);
+    }
+    else
+    {
+      v6 = 0;
+    }
+    if ( a4 >= v6 )
+    {
+      v14 = (1.0 - fSaturation) * v11;
+      //v9 = v14 + 6.7553994e15;
+      if (floorf(v14 + 0.5f)/* SLODWORD(v9)*/ >= 0 )
+      {
+        v15 = (1.0 - fSaturation) * v11;
+        //v10 = v15 + 6.7553994e15;
+        //result = LODWORD(v10);
+        result = floorf(v15 + 0.5f);
+      }
+      else
+      {
+        result = 0;
+      }
+    }
+    else
+    {
+      result = a4;
+    }
+  }
+  else
+  {
+    result = -1;
+  }
+  return result;
+}
+
+
+//----- (0044E4B7) --------------------------------------------------------
+Game::Game()
+{
+  uNumStationaryLights = 0;
+  uNumBloodsplats = 0;
+  field_E0C = 0;
+  field_E10 = 0;
+  uNumStationaryLights_in_pStationaryLightsStack = 0;
+  bGammaControlInitialized = false;
+  uFlags = 0;
+  uFlags2 = 0;
+  uSomeGammaStartTime = 0;
+  uSomeGammaDeltaTime = 0;
+
+  pThreadWardInstance = new ThreadWard;
+  pParticleEngine = new ParticleEngine;
+  pMouse = pMouseInstance = new Mouse(pThreadWardInstance);
+  pLightmapBuilder = new LightmapBuilder;
+  pVisInstance = new Vis;
+  pStru6Instance = new stru6;
+  pIndoorCameraD3D = new IndoorCameraD3D;
+  pStru9Instance = new stru9;
+  pStru10Instance = new stru10;
+  pStru11Instance = new stru11;
+  pStru12Instance = new stru12(pStru11Instance);
+  pCShow = new CShow;
+  pKeyboardInstance = new Keyboard;
+  pGammaController = new GammaController;
+
+  uFlags |= 0x0800;
+  uFlags2 |= 0x24;
+
+  _44F0FD();
+
+  bWinNT4_0 = false;
+  if (pVersion->pVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+      pVersion->pVersionInfo.dwMajorVersion == 4)
+    bWinNT4_0 = true;
+}
+
+//----- (0044E7F3) --------------------------------------------------------
+Game::~Game()
+{
+  if (pGammaController)
+    delete pGammaController;
+  if (pKeyboardInstance)
+    delete pKeyboardInstance;
+  if (pCShow)
+    delete pCShow;
+  if (pStru12Instance)
+    delete pStru12Instance;
+  if (pStru11Instance)
+    delete pStru11Instance;
+  if (pStru10Instance)
+    delete pStru10Instance;
+  if (pStru9Instance)
+    delete pStru9Instance;
+  if (pIndoorCameraD3D)
+    delete pIndoorCameraD3D;
+  if (pStru6Instance)
+    delete pStru6Instance;
+  if (pVisInstance)
+    delete pVisInstance;
+  if (pLightmapBuilder)
+    delete pLightmapBuilder;
+  if (pMouseInstance)
+    delete pMouseInstance;
+  if (pParticleEngine)
+    delete pParticleEngine;
+  if (pThreadWardInstance)
+    delete pThreadWardInstance;
+}
+
+//----- (0044E904) --------------------------------------------------------
+void Game::_44E904()
+{
+  //Game *v1; // esi@1
+  unsigned __int64 v2; // qax@1
+  unsigned int v3; // ecx@1
+  int v4; // edi@1
+  unsigned __int8 v5; // cf@7
+  double v6; // st7@13
+  double v7; // st7@15
+  signed __int64 v8; // [sp+Ch] [bp-8h]@1
+
+  //v1 = this;
+  v2 = pEventTimer->Time();
+  v4 = (v2 - uSomeGammaStartTime) >> 32;
+  v3 = v2 - LODWORD(uSomeGammaStartTime);
+  v8 = v2 - uSomeGammaStartTime;
+  if ( v4 < 0
+    || SHIDWORD(v2) < ((unsigned int)v2 < LODWORD(uSomeGammaStartTime)) + HIDWORD(uSomeGammaStartTime) | v4 == 0
+    && v3 <= 0x80 )
+  {
+    if ( v4 > 0 || v4 >= 0 )
+      goto LABEL_12;
+    v3 = 0;
+    v4 = 0;
+  }
+  else
+  {
+    if ( uSomeGammaDeltaTime )
+    {
+      LODWORD(uSomeGammaDeltaTime) = 0;
+      HIDWORD(uSomeGammaDeltaTime) = 0;
+    }
+    else
+    {
+      LODWORD(uSomeGammaDeltaTime) = v3;
+      HIDWORD(uSomeGammaDeltaTime) = v4;
+    }
+    v5 = __CFADD__(v3, -128);
+    v3 -= 128;
+    v4 = v5 + v4 - 1;
+  }
+  uSomeGammaStartTime = v2;
+  v8 = __PAIR__(v4, v3);
+LABEL_12:
+  if ( uSomeGammaDeltaTime )
+    v6 = (double)(signed __int64)(uSomeGammaDeltaTime - __PAIR__(v4, v3));
+  else
+    v6 = (double)v8;
+  v7 = v6 * 0.0078125;
+  if ( v7 < 0.0 || v7 <= 1.0 )
+  {
+    if ( v7 < 0.0 )
+      v7 = 0.0;
+  }
+  else
+  {
+    v7 = 1.0;
+  }
+  if ( pRenderer->pRenderD3D )
+    fSaturation = v7;
+  else
+    fSaturation = (1.0 - 0.5) * v7 + 0.5;
+}
+
+//----- (0044EA17) --------------------------------------------------------
+bool Game::InitializeGammaController()
+{
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
+    pGammaController->InitializeFromSurface(pRenderer->pFrontBuffer4);
+
+  bGammaControlInitialized = true;
+  uSomeGammaStartTime = pEventTimer->Time();
+  return true;
+}
+
+//----- (0044EA5E) --------------------------------------------------------
+char Game::PickMouse(float fPickDepth, unsigned int uMouseX, unsigned int uMouseY, bool bOutline, stru157 *a5, stru157 *a6)
+{
+  char result; // al@3
+  std::string v10; // [sp-4h] [bp-24h]@5
+  float v11; // [sp+4h] [bp-1Ch]@10
+  float v12; // [sp+8h] [bp-18h]@10
+  const char *v13; // [sp+Ch] [bp-14h]@5
+  int v14; // [sp+10h] [bp-10h]@5
+  std::string *v15; // [sp+18h] [bp-8h]@5
+  int a3; // [sp+1Fh] [bp-1h]@5
+
+  auto v7 = this;
+  if (!pCurrentScreen && pRenderer->pRenderD3D)
+  {
+    if (!pVisInstance)
+    {
+      MessageBoxW(nullptr, L"The 'Vis' object pointer has not been instatiated, but CGame::Pick() is trying to call through it.", nullptr, 0);
+      ExitProcess(0);
+    }
+
+    if ( (signed int)uMouseX >= (signed int)pViewport->uScreenX
+      && (signed int)uMouseX <= (signed int)pViewport->uScreenZ
+      && (signed int)uMouseY >= (signed int)pViewport->uScreenY
+      && (signed int)uMouseY <= (signed int)pViewport->uScreenW )
+    {
+      v14 = (int)a6;
+      v12 = (double)(signed int)uMouseY;
+      v11 = (double)(signed int)uMouseX;
+      pVisInstance->PickMouse(fPickDepth, v11, v12, a5, a6);
+
+      if (bOutline)
+        OutlineSelection();
+    }
+    return true;
+  }
+  return false;
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (0044EB12) --------------------------------------------------------
+bool Game::_44EB12(bool bOutline, stru157 *a3, stru157 *a4)
+{
+  if ( !pCurrentScreen && pVisInstance && pRenderer->pRenderD3D )
+  {
+    bool r = pVisInstance->_4C05CC(&pVisInstance->stru1, a3, a4);
+
+    if (bOutline)
+      OutlineSelection();
+    return r;
+  }
+  return false;
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (0044EB5A) --------------------------------------------------------
+void Game::OutlineSelection()
+{
+  Vis *v1; // eax@1
+  Vis_stru1_stru0 *v2; // eax@3
+  void *v3; // edx@9
+  int v4; // eax@10
+  int v5; // eax@11
+  int v6; // eax@14
+  int v7; // eax@15
+  const char *v9; // [sp-8h] [bp-14h]@8
+  int v10; // [sp-4h] [bp-10h]@8
+  char v11; // [sp+0h] [bp-Ch]@18
+  int a3; // [sp+Ah] [bp-2h]@8
+
+  v1 = this->pVisInstance;
+  if ( v1 )
+  {
+    v2 = (Vis_stru1_stru0 *)((signed int)v1->stru1.uNumPointers <= 0 ? 0 : v1->stru1.array_1804[0]);
+    if ( v2 )
+    {
+      if ( v2->uObjectType == 1 )
+      {
+        MessageBoxW(nullptr, L"Sprite outline currently Unsupported", nullptr, 0);
+        ExitProcess(0);
+      }
+
+        if ( v2->uObjectType == 2 )
+        {
+          v3 = v2->pObjectInfo;                 // TODO  2 objects for indoor/outdoor
+                                                // some clues in header for Vis_stru1_stru0
+          if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+          {
+            v4 = *((int *)v3 + 11);
+            if ( v4 & 0x10000 )
+              v5 = v4 & 0xFFFEFFFF;
+            else
+              v5 = v4 | 0x10000;
+            *((int *)v3 + 11) = v5;
+          }
+          else
+          {
+            v6 = *((int *)v3 + 7);
+            if ( v6 & 0x10000 )
+              v7 = v6 & 0xFFFEFFFF;
+            else
+              v7 = v6 | 0x10000;
+            *((int *)v3 + 7) = v7;
+          }
+        }
+        else
+        {
+          MessageBoxW(nullptr, L"Undefined CObjectInfo type requested in CGame::outline_selection()", nullptr, 0);
+          ExitProcess(0);
+        }
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Game.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,173 @@
+#pragma once
+#include "LightmapBuilder.h"
+#include "DecalBuilder.h"
+#include "ParticleEngine.h"
+#include "Vis.h"
+#include "Mouse.h"
+#include "Keyboard.h"
+#include "IndoorCameraD3D.h"
+#include "CShow.h"
+#include "GammaControl.h"
+#include "stru6.h"
+#include "stru9.h"
+#include "stru10.h"
+#include "stru11.h"
+#include "stru12.h"
+
+
+
+
+
+/*  320 */
+enum GAME_STATE
+{
+  GAME_STATE_0 = 0x0,
+  GAME_FINISHED = 0x1,
+  GAME_STATE_2 = 0x2,
+  GAME_STATE_3 = 0x3,
+  GAME_STATE_4 = 0x4,
+  GAME_STATE_5 = 0x5,
+  GAME_STATE_6 = 0x6,
+  GAME_STATE_7 = 0x7,
+  GAME_STATE_8 = 0x8,
+  GAME_STATE_FINAL_WINDOW = 0x9,
+  GAME_STATE_A = 0xA
+};
+
+
+
+/*  105 */
+#pragma pack(push, 1)
+struct Game__StationaryLight
+{
+  Vec3_float_ vPosition;
+  Vec3_float_ vRGBColor;
+  float flt_18;
+};
+#pragma pack(pop)
+
+
+/*  108 */
+#pragma pack(push, 1)
+struct Game_stru0
+{
+  int field_0;
+  unsigned __int8 *ptr_4;
+  int field_8;
+  int field_C;
+};
+#pragma pack(pop)
+
+
+/*  279 */
+#pragma pack(push, 1)
+//Game_stru1
+struct Game_Bloodsplat
+{
+  float x;
+  float y;
+  float z;
+  float r;
+  float g;
+  float b;
+  float radius;
+};
+#pragma pack(pop)
+
+/*  104 */
+#pragma pack(push, 1)
+struct Game
+{
+  static Game *Create();
+  static void  Destroy();
+
+protected: Game();
+protected: ~Game();
+
+public:
+  void _44E904();
+  bool InitializeGammaController();
+  char PickMouse(float fPickDepth, unsigned int uMouseX, unsigned int uMouseY, bool bOutline, struct stru157 *a5, struct stru157 *a6);
+  bool _44EB12(bool bOutline, struct stru157 *a3, struct stru157 *a4);
+  void OutlineSelection();
+  signed int _44EC23(struct stru148 *a2, int *a3, signed int a4);
+  signed int _44ED0A(struct BLVFace *a2, int *a3, signed int a4);
+  bool AlterGamma(struct BLVFace *pFace, unsigned int *pColor);
+  bool _44EE30(struct ODMFace *a2, int a3);
+  bool draw_debug_outlines();
+  bool _44EEA7();
+  bool _44F07B();
+  void ToggleFlags(unsigned int uMask);
+  void ToggleFlags2(unsigned int uFlag);
+  void _44F0FD();
+  void PushStationaryLights(int a2);
+  void PrepareBloodsplats();
+  void Deinitialize();
+  void Loop();
+  void DrawParticles();
+  void Draw();
+
+  //----- (0042EB6A) --------------------------------------------------------
+  struct stru6 *GetStru6() {return this->pStru6Instance;}
+  //----- (0042EB71) --------------------------------------------------------
+  struct IndoorCameraD3D *GetIndoorCamera() {return this->pIndoorCameraD3D;}
+
+
+  void (__thiscall ***vdestructor_ptr)(Game *, bool);
+  Game__StationaryLight pStationaryLights[25];
+  char field_2C0[1092];
+  unsigned int uNumStationaryLights;
+  Game_Bloodsplat pBloodsplats[20];
+  int field_938;
+  int field_93C;
+  int field_940;
+  int field_944;
+  int field_948;
+  int field_94C;
+  int field_950;
+  int field_954;
+  int field_958;
+  int field_95C;
+  int field_960;
+  int field_964;
+  int field_968;
+  int field_96C;
+  int field_970;
+  Mouse *pMouse;
+  int field_978;
+  Game_stru0 stru_97C;
+  char field_98C[1148];
+  int uNumBloodsplats;
+  int field_E0C;
+  __int64 field_E10;
+  int uNumStationaryLights_in_pStationaryLightsStack;
+  unsigned int bGammaControlInitialized;
+  unsigned int uFlags;
+  unsigned int uFlags2;
+  float fSaturation;
+  unsigned __int64 uSomeGammaStartTime;
+  __int64 uSomeGammaDeltaTime;
+  ThreadWard *pThreadWardInstance;
+  ParticleEngine *pParticleEngine;
+  Mouse *pMouseInstance;
+  LightmapBuilder *pLightmapBuilder;
+  Vis *pVisInstance;
+  stru6 *pStru6Instance;
+  IndoorCameraD3D *pIndoorCameraD3D;
+  stru9 *pStru9Instance;
+  stru10 *pStru10Instance;
+  stru11 *pStru11Instance;
+  stru12 *pStru12Instance;
+  CShow *pCShow;
+  Keyboard *pKeyboardInstance;
+  GammaController *pGammaController;
+  int field_E74;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+extern Game *pGame;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GameUIs.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,321 @@
+#include <direct.h>
+#include <io.h>
+#include <assert.h>
+
+#include "GUIWindow.h"
+#include "GUIFont.h"
+#include "LOD.h"
+#include "SaveLoad.h"
+#include "Render.h"
+
+#include "mm7_data.h"
+
+
+//----- (0045E361) --------------------------------------------------------
+void __fastcall GameUI_DrawLoadMenu(unsigned int uDialogueType)
+{
+  unsigned int v1; // ebp@5
+  unsigned int v2; // eax@5
+  //signed int v3; // ebp@11
+  FILE *v4; // eax@14
+  FILE *v5; // eax@18
+  unsigned int v6; // eax@25
+  GUIButton *v7; // eax@27
+  const char *v8; // [sp-8h] [bp-26Ch]@25
+  //char *v9; // [sp-4h] [bp-268h]@19
+  enum TEXTURE_TYPE v10; // [sp-4h] [bp-268h]@25
+  unsigned int uDialogueType_; // [sp+10h] [bp-254h]@1
+  //RGBTexture *pTex; // [sp+10h] [bp-254h]@12
+  //SavegameHeader *Dest; // [sp+14h] [bp-250h]@12
+  //const char *Str1; // [sp+18h] [bp-24Ch]@12
+  LODWriteableFile pLODFile; // [sp+1Ch] [bp-248h]@1
+  int v16; // [sp+260h] [bp-4h]@1
+
+  uDialogueType_ = uDialogueType;
+  dword_6BE138 = -1;
+  ++pIcons_LOD->uTexturePacksCount;
+  v16 = 0;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  memset(pSavegameUsedSlots, 0, sizeof(pSavegameUsedSlots));
+  memset(pSavegameThumbnails, 0, 45 * sizeof(RGBTexture));
+  uTextureID_loadsave = pIcons_LOD->LoadTexture("loadsave", TEXTURE_16BIT_PALETTE);
+  uTextureID_load_up = pIcons_LOD->LoadTexture("load_up", TEXTURE_16BIT_PALETTE);
+  uTextureID_save_up = pIcons_LOD->LoadTexture("save_up", TEXTURE_16BIT_PALETTE);
+  uTextureID_LS_loadU = pIcons_LOD->LoadTexture("LS_loadU", TEXTURE_16BIT_PALETTE);
+  uTextureID_LS_saveU = pIcons_LOD->LoadTexture("LS_saveU", TEXTURE_16BIT_PALETTE);
+  uTextureID_x_u = pIcons_LOD->LoadTexture("x_u", TEXTURE_16BIT_PALETTE);
+  if ( uDialogueType_ )
+  {
+    pRenderer->DrawTextureIndexed(8, 8, (Texture *)(uTextureID_loadsave != -1 ? &pIcons_LOD->pTextures[uTextureID_loadsave] : 0));
+    if ( pCurrentScreen == 11 )//save or load
+    {
+      v1 = uTextureID_save_up;
+      v2 = uTextureID_LS_saveU;
+    }
+    else
+    {
+      v1 = uTextureID_load_up;
+      v2 = uTextureID_LS_loadU;
+    }
+    pRenderer->DrawTextureIndexed(241, 302, (Texture *)(v2 != -1 ? (int)&pIcons_LOD->pTextures[v2] : 0));
+    pRenderer->DrawTextureIndexed(18, 141, (Texture *)(v1 != -1 ? (int)&pIcons_LOD->pTextures[v1] : 0));
+    pRenderer->DrawTextureIndexed(351, 302, (Texture *)(uTextureID_x_u != -1 ? &pIcons_LOD->pTextures[uTextureID_x_u] : 0));
+  }
+  else
+  {
+    pRenderer->DrawTextureRGB(0, 0, &pTexture_PCX);
+  }
+  pGUIWindow_CurrentMenu = GUIWindow::Create(saveload_dlg_xs[uDialogueType_], saveload_dlg_ys[uDialogueType_], saveload_dlg_zs[uDialogueType_],
+                             saveload_dlg_ws[uDialogueType_], WINDOW_MainMenu_Load, 0, 0);
+  pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, 25, 199, 0, pGlobalTXT_LocalizationStrings[505], 0, 0, 0);// "Reading..."
+  pRenderer->Present();
+  pSavegameList->Initialize(0);
+  if ( dword_6A0C9C > (signed int)uNumSavegameFiles )
+  {
+    dword_6A0C9C = 0;
+    uLoadGameUI_SelectedSlot = 0;
+  }
+  pLODFile.AllocSubIndicesAndIO(0x12C, 0);
+  assert(sizeof(SavegameHeader) == 0x64);
+  //v3 = 0;
+  for (uint i = 0; i < uNumSavegameFiles; ++i)
+  {
+    //Dest = pSavegameHeader;
+    //pTex = pSavegameThumbnails;
+    //Str1 = (const char *)pSavegameList->pSavesNames;
+    //while ( 1 )
+    //{
+    sprintf(pTmpBuf, "saves\\%s", pSavegameList->pSavesNames[i]);
+    if (_access(pTmpBuf, 6))
+    {
+      pSavegameUsedSlots[i] = 0;
+      strcpy(pSavegameHeader[i].pName, pGlobalTXT_LocalizationStrings[72]); // "Empty"
+      continue;
+    }
+	pLODFile.LoadFile(pTmpBuf, 1);
+    v4 = pLODFile.FindContainer("header.bin", true);
+    if ( v4 )
+      fread(&pSavegameHeader[i], 0x64, 1, v4);
+    if ( !_strcmpi(pSavegameList->pSavesNames[i], pGlobalTXT_LocalizationStrings[613]) )// "AutoSave.MM7"
+      strcpy(pSavegameList->pSavesNames[i], pGlobalTXT_LocalizationStrings[16]);// "Autosave"
+	v5 = pLODFile.FindContainer("image.pcx", true);
+    if ( !v5 )
+    {
+      pSavegameUsedSlots[i] = 0;
+      strcpy(pSavegameList->pSavesNames[i], "");
+    }
+    else
+    {
+      pSavegameThumbnails[i].LoadFromFILE(v5, 0, true);
+      pLODFile.CloseWriteFile();
+      pSavegameUsedSlots[i] = 1;
+    }
+//LABEL_23:
+      //Str1 += 280;
+      //++pTex;
+      //++Dest;
+      //++v3;
+      //if ( v3 >= (signed int)uNumSavegameFiles )
+      //  goto LABEL_24;
+    //}
+    //goto LABEL_22;
+  }
+
+//LABEL_24:
+  pLODFile.FreeSubIndexAndIO();
+  if ( pCurrentScreen == 11 ) // save/load screen
+  {
+    v6 = pIcons_LOD->LoadTexture("x_d", TEXTURE_16BIT_PALETTE);
+    v10 = (TEXTURE_TYPE)2;
+    v8 = "LS_saveD";
+  }
+  else
+  {
+    v6 = pIcons_LOD->LoadTexture("x_d", TEXTURE_16BIT_PALETTE);
+    v10 = (TEXTURE_TYPE)2;
+    v8 = "LS_loadD";
+  }
+  uTextureID_x_d = v6;
+  uTextureID_LS_ = pIcons_LOD->LoadTexture(v8, v10);
+  uTextureID_AR_UP_DN = pIcons_LOD->LoadTexture("AR_UP_DN", TEXTURE_16BIT_PALETTE);
+  uTextureID_AR_DN_DN = pIcons_LOD->LoadTexture("AR_DN_DN", TEXTURE_16BIT_PALETTE);
+  pGUIWindow_CurrentMenu->CreateButton(21, 198, 191, 18, 1, 0, 0xA5, 0, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21, 219, 191, 18, 1, 0, 0xA5, 1, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21, 240, 191, 18, 1, 0, 0xA5, 2, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21, 261, 191, 18, 1, 0, 0xA5, 3, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21, 282, 191, 18, 1, 0, 0xA5, 4, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21, 303, 191, 18, 1, 0, 0xA5, 5, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21, 324, 191, 18, 1, 0, 0xA5, 6, 0, "", 0);
+  ptr_69BD64 = pGUIWindow_CurrentMenu->CreateButton(241, 302, 105, 40, 1, 0, 0xA4, 0, 0, "",
+                 (Texture *)(uTextureID_LS_ != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_LS_] : 0), 0);
+  ptr_69BD60 = pGUIWindow_CurrentMenu->CreateButton(350, 302, 105, 40, 1, 0, 0xA6, 0, 0, "",
+                 (Texture *)(uTextureID_x_d != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_d] : 0), 0);
+  ptr_69BD5C = pGUIWindow_CurrentMenu->CreateButton(215, 199, 17, 17, 1, 0, 0xA2, 0, 0, "",
+                 (Texture *)(uTextureID_AR_UP_DN != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_AR_UP_DN] : 0), 0);
+  ptr_69BD58 = pGUIWindow_CurrentMenu->CreateButton(215, 0x143, 0x11, 0x11, 1, 0, 0xA3, uNumSavegameFiles, 0, "",
+         (Texture *)(uTextureID_AR_DN_DN != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_AR_DN_DN] : 0), 0);
+  v16 = -1;
+  //ptr_69BD58 = v7;
+}
+
+//----- (0045E93E) --------------------------------------------------------
+void __cdecl GameUI_DrawSaveMenu()
+{
+  unsigned int v0; // ebp@4
+  unsigned int v1; // eax@4
+  unsigned int *v2; // ebp@6
+  char *v3; // eax@7
+  FILE *v4; // eax@11
+  FILE *v5; // eax@11
+  const char *v6; // ST64_4@14
+  GUIButton *v7; // eax@16
+  char *v8; // [sp+10h] [bp-254h]@6
+  SavegameHeader *Dest; // [sp+14h] [bp-250h]@6
+  RGBTexture *this_; // [sp+18h] [bp-24Ch]@6
+  LODWriteableFile v11; // [sp+1Ch] [bp-248h]@1
+  int v12; // [sp+260h] [bp-4h]@1
+
+  ++pIcons_LOD->uTexturePacksCount;
+  v12 = 0;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  memset(pSavegameUsedSlots, 0, 0xB4u);
+  memset(&pSavegameThumbnails, 0, 0x708u);
+  uTextureID_loadsave = pIcons_LOD->LoadTexture("loadsave", TEXTURE_16BIT_PALETTE);
+  uTextureID_load_up = pIcons_LOD->LoadTexture("load_up", TEXTURE_16BIT_PALETTE);
+  uTextureID_save_up = pIcons_LOD->LoadTexture("save_up", TEXTURE_16BIT_PALETTE);
+  uTextureID_LS_loadU = pIcons_LOD->LoadTexture("LS_loadU", TEXTURE_16BIT_PALETTE);
+  uTextureID_LS_saveU = pIcons_LOD->LoadTexture("LS_saveU", TEXTURE_16BIT_PALETTE);
+  uTextureID_x_u = pIcons_LOD->LoadTexture("x_u", TEXTURE_16BIT_PALETTE);
+  pRenderer->DrawTextureIndexed(
+    8u,
+    8u,
+    (Texture *)(uTextureID_loadsave != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_loadsave] : 0));
+  if ( pCurrentScreen == 11 )
+  {
+    v0 = uTextureID_save_up;
+    v1 = uTextureID_LS_saveU;
+  }
+  else
+  {
+    v0 = uTextureID_load_up;
+    v1 = uTextureID_LS_loadU;
+  }
+  pRenderer->DrawTextureIndexed(0xF1u, 0x12Eu, (Texture *)(v1 != -1 ? (int)&pIcons_LOD->pTextures[v1] : 0));
+  pRenderer->DrawTextureIndexed(
+    0x15Fu,
+    0x12Eu,
+    (Texture *)(uTextureID_x_u != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_u] : 0));
+  pRenderer->DrawTextureIndexed(0x12u, 0x8Du, (Texture *)(v0 != -1 ? (int)&pIcons_LOD->pTextures[v0] : 0));
+  pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, 25, 199, 0, pGlobalTXT_LocalizationStrings[505], 0, 0, 0);
+  pRenderer->Present();
+  pSavegameList->Initialize(1u);
+  v11.AllocSubIndicesAndIO(0x12Cu, 0);
+  v2 = pSavegameUsedSlots;
+  Dest = pSavegameHeader;
+  this_ = pSavegameThumbnails;
+  v8 = (char *)pSavegameList->pSavesNames;
+  do
+  {
+    v3 = v8;
+    if ( !*v8 )
+      v3 = "1.mm7";
+    sprintf(pTmpBuf, "saves\\%s", v3);
+    if ( _access(pTmpBuf, 0) || _access(pTmpBuf, 6) )
+    {
+      v6 = pGlobalTXT_LocalizationStrings[72];
+      *v2 = 0;
+      strcpy(Dest->pName, v6);
+    }
+    else
+    {
+      v11.LoadFile(pTmpBuf, 1);
+      v4 = v11.FindContainer("header.bin", 1);
+      fread(Dest, 0x64u, 1u, v4);
+      v5 = v11.FindContainer("image.pcx", 1);
+      if ( v5 )
+      {
+        this_->LoadFromFILE(v5, 0, 1u);
+        v11.CloseWriteFile();
+        *v2 = 1;
+      }
+      else
+      {
+        *v2 = 0;
+      }
+    }
+    v8 += 280;
+    ++this_;
+    ++Dest;
+    ++v2;
+  }
+  while ( (signed int)v8 < (signed int)&_69FBB4_ptr_iterator_end );
+  v11.FreeSubIndexAndIO();
+  uTextureID_x_d = pIcons_LOD->LoadTexture("x_d", TEXTURE_16BIT_PALETTE);
+  uTextureID_LS_ = pIcons_LOD->LoadTexture("LS_saveD", TEXTURE_16BIT_PALETTE);
+  uTextureID_AR_UP_DN = pIcons_LOD->LoadTexture("AR_UP_DN", TEXTURE_16BIT_PALETTE);
+  uTextureID_AR_DN_DN = pIcons_LOD->LoadTexture("AR_DN_DN", TEXTURE_16BIT_PALETTE);
+  pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, (WindowType)(WINDOW_Chest|WINDOW_MainMenu|0x2), 0, 0);
+  pGUIWindow_CurrentMenu->CreateButton(21u, 198u, 0xBFu, 0x12u, 1, 0, 0xA5u, 0, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21u, 218u, 0xBFu, 0x12u, 1, 0, 0xA5u, 1u, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21u, 238u, 0xBFu, 0x12u, 1, 0, 0xA5u, 2u, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21u, 258u, 0xBFu, 0x12u, 1, 0, 0xA5u, 3u, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21u, 278u, 0xBFu, 0x12u, 1, 0, 0xA5u, 4u, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21u, 298u, 0xBFu, 0x12u, 1, 0, 0xA5u, 5u, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(21u, 318u, 0xBFu, 0x12u, 1, 0, 0xA5u, 6u, 0, "", 0);
+  ptr_69BD64 = pGUIWindow_CurrentMenu->CreateButton(
+                 0xF1u,
+                 0x12Eu,
+                 0x69u,
+                 0x28u,
+                 1,
+                 0,
+                 0xA4u,
+                 0,
+                 0,
+                 "",
+                 (Texture *)(uTextureID_LS_ != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_LS_] : 0),
+                 0);
+  ptr_69BD60 = pGUIWindow_CurrentMenu->CreateButton(
+                 0x15Eu,
+                 0x12Eu,
+                 0x69u,
+                 0x28u,
+                 1,
+                 0,
+                 0xA6u,
+                 0,
+                 0,
+                 "",
+                 (Texture *)(uTextureID_x_d != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_d] : 0),
+                 0);
+  ptr_69BD5C = pGUIWindow_CurrentMenu->CreateButton(
+                 0xD7u,
+                 0xC7u,
+                 0x11u,
+                 0x11u,
+                 1,
+                 0,
+                 0xA2u,
+                 0,
+                 0,
+                 "",
+                 (Texture *)(uTextureID_AR_UP_DN != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_AR_UP_DN] : 0),
+                 0);
+  v7 = pGUIWindow_CurrentMenu->CreateButton(
+         0xD7u,
+         0x143u,
+         0x11u,
+         0x11u,
+         1,
+         0,
+         0xA3u,
+         0x22u,
+         0,
+         "",
+         (Texture *)(uTextureID_AR_DN_DN != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_AR_DN_DN] : 0),
+         0);
+  v12 = -1;
+  ptr_69BD58 = v7;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GammaControl.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,183 @@
+#include <string>
+
+#include "GammaControl.h"
+#include "Render.h"
+#include "OSInfo.h"
+
+#include "mm7_data.h"
+
+
+
+//----- (0044F324) --------------------------------------------------------
+void GammaController::GetRamp()
+{
+  if (pGammaControl)
+    ErrD3D(pGammaControl->GetGammaRamp(0, &pDefaultRamp));
+  else
+    MessageBoxW(nullptr, L"Gamma control not active", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\GammaControl.cpp:83", 0);
+}
+
+//----- (0044F377) --------------------------------------------------------
+double GammaController::_44F377(DDGAMMARAMP *a1)
+{
+  double v2; // st7@1
+  unsigned __int16 *v3; // ecx@1
+  double v4; // st6@2
+  double result; // st7@7
+  signed int v6; // [sp+0h] [bp-8h]@1
+  signed int v7; // [sp+4h] [bp-4h]@1
+
+  v7 = 0;
+  v2 = 0.0;
+  v6 = 256;
+  v3 = a1->green;
+  do
+  {
+    v4 = ((double)*(v3 - 256) + (double)v3[256] + (double)*v3) * 0.000015259022 * 0.33333334;
+    if ( v4 == 0.0 )
+      --v6;
+    else
+      v2 = v2 + (double)v7 * 0.0039215689 / v4;
+    ++v7;
+    ++v3;
+  }
+  while ( v7 < 256 );
+  if ( v6 )
+    result = v2 / (double)v6;
+  else
+    result = 1.0;
+  return result;
+}
+
+//----- (0044F408) --------------------------------------------------------
+void GammaController::SetGammaRamp(DDGAMMARAMP *pRamp)
+{
+  if (pGammaControl)
+    ErrD3D(pGammaControl->SetGammaRamp(0, pRamp));
+  else
+    MessageBoxW(nullptr, L"Gamma control not active", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\GammaControl.cpp:120", 0);
+}
+
+//----- (0044F45B) --------------------------------------------------------
+int GammaController::InitGammaRamp(DDGAMMARAMP *pRamp)
+{
+  unsigned __int16 *v2; // esi@1
+  double v3; // st7@2
+  signed __int64 v4; // qax@3
+  signed int v6; // [sp+Ch] [bp-4h]@1
+
+  v6 = 0;
+  v2 = pRamp->green;
+  do
+  {
+    v3 = (double)v6 * 0.0039215689 * this->fGamma;
+    if ( v3 >= 1.0 || (v4 = (signed __int64)(v3 * 65535.0), (signed int)v4 > 65535) )
+      goto LABEL_12;
+    if ( (signed int)v4 < 0 )
+    {
+      LODWORD(v4) = 0;
+      goto LABEL_8;
+    }
+    if ( (signed int)v4 > 65535 )
+LABEL_12:
+      LODWORD(v4) = 65535;
+LABEL_8:
+    ++v6;
+    v2[256] = v4;
+    *v2 = v4;
+    *(v2 - 256) = v4;
+    ++v2;
+  }
+  while ( v6 < 256 );
+  return v4;
+}
+
+//----- (0044F4D9) --------------------------------------------------------
+void GammaController::Initialize(float gamma)
+{
+  GammaController *v2; // esi@1
+  double v3; // st7@3
+  double v4; // st6@4
+
+  v2 = this;
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4)
+  {
+    InitializeFromSurface(pRenderer->pFrontBuffer4);
+    v3 = 2.8;
+    if ( gamma <= 2.8f )
+      v4 = gamma;
+    else
+      v4 = 2.8;
+    if ( v4 >= 0.1f )
+    {
+      if ( gamma <= 2.8f )
+        v3 = gamma;
+    }
+    else
+    {
+      v3 = 0.1;
+    }
+    v2->fGamma = v3;
+    InitGammaRamp(&v2->field_60C);
+    SetGammaRamp(&v2->field_60C);
+  }
+}
+
+
+//----- (0044F2B2) --------------------------------------------------------
+bool GammaController::IsGammaSupported()
+{
+  bool result; // eax@3
+  HRESULT v1; // eax@4
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    DDCAPS halCaps; // [sp+0h] [bp-180h]@4
+    memset(&halCaps, 0, sizeof(DDCAPS));
+    halCaps.dwSize = sizeof(DDCAPS);
+
+    ErrD3D(pRenderer->pDirectDraw4->GetCaps(&halCaps, 0));
+    return (halCaps.dwCaps2 >> 17) & 1;
+  }
+  else
+    return false;
+}
+
+
+
+//----- (0044F215) --------------------------------------------------------
+GammaController::GammaController()
+{
+  static float flt_4D8670_default_gamma = 1.0f;
+
+  pGammaControl = nullptr;
+  fGamma = flt_4D8670_default_gamma;
+}
+
+
+
+//----- (0044F24B) --------------------------------------------------------
+void GammaController::InitializeFromSurface(IDirectDrawSurface4 *a2)
+{
+  GammaController *v2; // esi@1
+  IDirectDrawGammaControl **v3; // edi@1
+  IDirectDrawGammaControl *v4; // eax@1
+
+  v2 = this;
+  v3 = &this->pGammaControl;
+  this->pSurface = a2;
+  v4 = this->pGammaControl;
+  if ( v4 )
+  {
+    v4->Release();
+    *v3 = 0;
+  }
+  if ( IsGammaSupported() )
+  {
+    ErrD3D(a2->QueryInterface(IID_IDirectDrawGammaControl, (LPVOID *)v3));
+    GetRamp();
+    memcpy(&v2->field_60C, &v2->pDefaultRamp, 0x600u);
+    fGamma = _44F377(&v2->field_60C);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GammaControl.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,31 @@
+#pragma once
+#include "Render.h"
+
+#pragma pack(push, 1)
+struct GammaController
+{
+  GammaController();
+  inline ~GammaController() {} //----- (0044F22E)
+  
+  void Initialize/*_44F4D9*/(float gamma);
+
+  void GetRamp();
+  double _44F377(DDGAMMARAMP *a1);
+  void SetGammaRamp(DDGAMMARAMP *pRamp);
+  int InitGammaRamp(DDGAMMARAMP *pRamp);
+
+  /*protected*/void InitializeFromSurface(struct IDirectDrawSurface4 *a2);
+
+  static bool IsGammaSupported();
+
+
+
+
+  void (__thiscall ***vdestructor_ptr)(GammaController *, bool);
+  IDirectDrawSurface4 *pSurface;
+  IDirectDrawGammaControl *pGammaControl;
+  DDGAMMARAMP pDefaultRamp;
+  DDGAMMARAMP field_60C;
+  float fGamma;//field_C0C;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IconFrameTable.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,79 @@
+#pragma once
+
+
+
+
+
+/*   44 */
+#pragma pack(push, 1)
+struct IconFrame
+{
+  char pAnimationName[12];
+  char pTextureName[12];
+  __int16 uAnimTime;
+  __int16 uAnimLength;
+  __int16 uFlags;
+  unsigned __int16 uTextureID;
+};
+#pragma pack(pop)
+
+/*   45 */
+#pragma pack(push, 1)
+struct IconFrameTable
+{
+  inline IconFrameTable():
+    uNumIcons(0), pIcons(nullptr)
+  {}
+
+  unsigned int FindIcon(const char *pIconName);
+  IconFrame *GetFrame(unsigned int uIconID, unsigned int uFrameID);
+  void InitializeAnimation(unsigned int uIconID);
+  void ToFile();
+  void FromFile(void *pSerialized);
+  int FromFileTxt(const char *Args);
+  int GetIconAnimLength(unsigned int uIconID);
+
+  unsigned int uNumIcons;
+  struct IconFrame *pIcons;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+
+
+
+/*   76 */
+#pragma pack(push, 1)
+struct UIAnimation
+{
+  unsigned __int16 uIconID;
+  __int16 field_2;
+  __int16 uAnimTime;
+  __int16 uAnimLength;
+  __int16 x;
+  __int16 y;
+  char field_C;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+extern struct IconFrameTable *pIconsFrameTable;
+
+
+extern struct UIAnimation *pUIAnim_Food;
+extern struct UIAnimation *pUIAnim_Gold;
+extern struct UIAnimation *pUIAnum_Torchlight;
+extern struct UIAnimation *pUIAnim_WizardEye;
+
+extern struct UIAnimation *pUIAnims[4];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Indoor.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,4766 @@
+#include <assert.h>
+
+#include "Outdoor.h"
+#include "Render.h"
+#include "LayingItem.h"
+#include "Events.h"
+#include "Game.h"
+#include "Viewport.h"
+#include "Time.h"
+#include "Party.h"
+#include "Math.h"
+#include "Allocator.h"
+#include "LOD.h"
+#include "DecorationList.h"
+#include "ObjectList.h"
+#include "Actor.h"
+#include "Chest.h"
+#include "GUIProgressBar.h"
+#include "stru123.h"
+#include "AudioPlayer.h"
+#include "Log.h"
+#include "TurnEngine.h"
+#include "PaletteManager.h"
+#include "MapInfo.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+
+
+
+IndoorLocation *pIndoor = new IndoorLocation;
+BLVRenderParams *pBLVRenderParams = new BLVRenderParams;
+
+struct DecorationList *pDecorationList;
+
+LevelDecoration pLevelDecorations[3000];
+size_t uNumLevelDecorations;
+LevelDecoration *_5C3420_pDecoration;
+
+LEVEL_TYPE uCurrentlyLoadedLevelType = LEVEL_null;
+
+stru320 stru_F8AD28; // idb
+stru337 stru_F81018;
+stru167_wrap array_5118E8;
+BspRenderer_stru2 stru_F8A590;
+BspRenderer *pBspRenderer = new BspRenderer; // idb
+stru141 stru_721530;
+stru352 stru_F83B80[480];
+
+
+
+unsigned __int16 pDoorSoundIDsByLocationID[78] =
+{
+  300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+  300, 300, 300, 404, 302, 306, 308, 304, 308, 302, 400, 302, 300,
+  308, 308, 306, 308, 308, 304, 300, 404, 406, 300, 400, 406, 404,
+  306, 302, 408, 304, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+  300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 404, 304,
+  400, 300, 300, 404, 304, 400, 300, 300, 404, 304, 400, 300, 300
+};
+
+
+
+//----- (0043F39E) --------------------------------------------------------
+void __fastcall PrepareDrawLists_BLV(IndoorLocation_drawstru *_this)
+{
+  //int *v1; // ecx@1
+  //double v2; // ST30_8@3
+  //double v3; // ST30_8@6
+  //double v4; // ST28_8@6
+  int v5; // eax@4
+  int v6; // eax@7
+  unsigned int v7; // ebx@8
+  BLVSector *v8; // esi@8
+  unsigned __int16 *v9; // edi@8
+  int i; // [sp+18h] [bp-8h]@7
+  //unsigned __int8 v11; // [sp+1Ch] [bp-4h]@3
+  signed int v12; // [sp+1Ch] [bp-4h]@8
+
+  pBLVRenderParams->Reset(_this);
+  pMobileLightsStack->uNumLightsActive = 0;
+  //uNumMobileLightsApplied = 0;
+  uNumDecorationsDrawnThisFrame = 0;
+  _unused000 = 0;
+  uNumSpritesDrawnThisFrame = 0;
+  uNumBillboardsToDraw = 0;
+  if ( !byte_4D864C || !(pGame->uFlags & 0x1000) )
+  {
+    //v2 = pParty->flt_TorchlightColorB + 6.7553994e15;
+    //v11 = LOBYTE(v2);
+    v5 = 800;
+    if (pParty->TorchlightActive())
+      v5 *= pParty->pPartyBuffs[16].uPower;
+    //LOBYTE(v1) = byte_4E94D0;
+    //v4 = pParty->flt_TorchlightColorR + 6.7553994e15;
+    //v3 = pParty->flt_TorchlightColorG + 6.7553994e15;
+    pMobileLightsStack->AddLight(
+      pBLVRenderParams->vPartyPos.x,
+      pBLVRenderParams->vPartyPos.y,
+      pBLVRenderParams->vPartyPos.z,
+      pBLVRenderParams->uPartySectorID,
+      v5,
+      floorf(pParty->flt_TorchlightColorR + 0.5f),
+      floorf(pParty->flt_TorchlightColorG + 0.5f),
+      floorf(pParty->flt_TorchlightColorB + 0.5f),
+      byte_4E94D0);
+  }
+  PrepareBspRenderList_BLV();
+  PrepareItemsRenderList_BLV();
+  PrepareActorRenderList_BLV();
+  v6 = 0;
+  for ( i = 0; i < pBspRenderer->uNumVisibleNotEmptySectors; ++i )
+  {
+    v7 = pBspRenderer->pVisibleSectorIDs_toDrawDecorsActorsEtcFrom[v6];
+    v12 = 0;
+    v8 = &pIndoor->pSectors[pBspRenderer->pVisibleSectorIDs_toDrawDecorsActorsEtcFrom[v6]];
+    v9 = v8->pDecorationIDs;
+    if ( v8->uNumDecorations > 0 )
+    {
+      do
+        PrepareDecorationsRenderList_BLV(v9[v12++], v7);
+      while ( v12 < v8->uNumDecorations );
+    }
+    v6 = i + 1;
+  }
+  MessWithBillboards_BLV();
+  pGame->PrepareBloodsplats();
+}
+
+
+
+//----- (004407D9) --------------------------------------------------------
+int BLVRenderParams::Reset(IndoorLocation_drawstru *a2)
+{
+  IndoorLocation_drawstru *v2; // ebx@1
+  BLVRenderParams *v3; // esi@1
+  int v4; // ST08_4@1
+  int v5; // ST04_4@1
+  int v6; // ST00_4@1
+  int v7; // eax@1
+  int v8; // ST08_4@2
+  int v9; // ST04_4@2
+  int v10; // ST00_4@2
+  unsigned int v11; // edi@4
+  unsigned int v12; // ecx@4
+  int v13; // edx@4
+  signed int v14; // ecx@4
+  unsigned int v15; // edx@4
+  unsigned int v16; // eax@4
+  double v17; // st7@5
+  int v18; // eax@5
+  double v19; // st7@5
+  int v20; // eax@5
+  double v21; // st7@5
+  int v22; // eax@5
+  unsigned int v23; // edx@5
+  unsigned int v24; // ecx@5
+  int v25; // eax@5
+  int v26; // eax@5
+  signed int v27; // eax@6
+  int result; // eax@6
+  int v29; // [sp+24h] [bp+8h]@5
+
+  v2 = a2;
+  v3 = this;
+  this->field_0_timer_ = a2->field_0_timer;
+  this->uFlags = a2->uFlags;
+  this->vPartyPos.x = a2->vPosition.x;
+  this->vPartyPos.y = a2->vPosition.y;
+  this->vPartyPos.z = a2->vPosition.z;
+  v4 = this->vPartyPos.z;
+  v5 = this->vPartyPos.y;
+  this->sPartyRotY = a2->sRotationY;
+  v6 = this->vPartyPos.x;
+  this->sPartyRotX = a2->sRotationX;
+  v7 = pIndoor->GetSector(v6, v5, v4);
+  v3->uPartySectorID = v7;
+  if ( !v7 )
+  {
+    v8 = v3->vPartyPos.z;
+    v3->vPartyPos.x = pParty->vPosition.x;
+    v9 = pParty->vPosition.y;
+    v10 = v3->vPartyPos.x;
+    v3->vPartyPos.y = pParty->vPosition.y;
+    v3->uPartySectorID = pIndoor->GetSector(v10, v9, v8);
+  }
+  if ( pRenderer->pRenderD3D )
+  {
+    v3->sCosineY = stru_5C6E00->SinCos(v3->sPartyRotY);
+    v3->sSineY = stru_5C6E00->SinCos(v3->sPartyRotY - stru_5C6E00->uIntegerHalfPi);
+    v3->sCosineNegX = stru_5C6E00->SinCos(-v3->sPartyRotX);
+    v3->sSineNegX = stru_5C6E00->SinCos(-v3->sPartyRotX - stru_5C6E00->uIntegerHalfPi);
+    v3->fCosineY = cos((3.141592653589793 + 3.141592653589793) * (double)v3->sPartyRotY * 0.00048828125);
+    v3->fSineY = sin((3.141592653589793 + 3.141592653589793) * (double)v3->sPartyRotY * 0.00048828125);
+    v3->fCosineNegX = cos((3.141592653589793 + 3.141592653589793) * (double)-v3->sPartyRotX * 0.00048828125);
+    v3->fSineNegX = sin((3.141592653589793 + 3.141592653589793) * (double)-v3->sPartyRotX * 0.00048828125);
+    v3->field_64 = a2->field_3C;
+    v11 = v3->uViewportW;
+    v12 = v3->uViewportX;
+    v13 = v3->uViewportZ - v12;
+    v14 = v3->uViewportZ + v12;
+    v3->field_70 = v13 + 1;
+    v15 = v3->uViewportY;
+    v3->uViewportHeight = v11 - v15 + 1;
+    v16 = v3->uViewportW;
+    v3->uViewportCenterX = v14 >> 1;
+    v3->uViewportCenterY = (signed int)(v16 + v15) >> 1;
+  }
+  else
+  {
+    v3->sCosineY = stru_5C6E00->SinCos(-v3->sPartyRotY);
+    v3->sSineY = stru_5C6E00->SinCos(-v3->sPartyRotY - stru_5C6E00->uIntegerHalfPi);
+    v3->sCosineNegX = stru_5C6E00->SinCos(-v3->sPartyRotX);
+    v3->sSineNegX = stru_5C6E00->SinCos(-v3->sPartyRotX - stru_5C6E00->uIntegerHalfPi);
+    v17 = cos((double)-v3->sPartyRotY * 0.0030664064);
+    v18 = v3->sPartyRotY;
+    v3->fCosineY = v17;
+    v19 = sin((double)-v18 * 0.0030664064);
+    v20 = v3->sPartyRotX;
+    v3->fSineY = v19;
+    v21 = cos((double)-v20 * 0.0030664064);
+    v22 = v3->sPartyRotX;
+    v3->fCosineNegX = v21;
+    v3->fSineNegX = sin((double)-v22 * 0.0030664064);
+    v23 = v3->uViewportX;
+    v3->field_64 = a2->field_3C;
+    v24 = v3->uViewportZ;
+    v3->field_70 = v3->uViewportZ - v23 + 1;
+    v25 = v3->uViewportW - v3->uViewportY + 1;
+    v3->uViewportHeight = v25;
+    v29 = v25;
+    v26 = v3->field_64;
+    v3->uViewportCenterX = (signed int)(v24 + v23) >> 1;
+    v3->uViewportCenterY = v3->uViewportW - ((unsigned __int64)(v26 * (signed __int64)v29) >> 16);
+  }
+  v27 = (unsigned int)(signed __int64)((double)v3->field_70 * 0.5 / tan((double)(v2->field_1C_mb_fov >> 1) * 0.01745329)
+                                     + 0.5) << 16;
+  v3->field_40 = v27;
+  LODWORD(v3->field_44) = 4294967296i64 / v27;
+  v3->pRenderTarget = v2->pRenderTarget;
+  v3->uTargetWidth = v2->uTargetWidth;
+  v3->uTargetHeight = v2->uTargetHeight;
+  v3->uViewportX = v2->uViewportX;
+  v3->uViewportY = v2->uViewportY;
+  v3->uViewportZ = v2->uViewportZ;
+  v3->uViewportW = v2->uViewportW;
+  v3->pTargetZBuffer = v2->pTargetZ;
+  result = 0;
+  v3->field_8C = 0;
+  v3->field_84 = 0;
+  v3->uNumFacesRenderedThisFrame = 0;
+  v3->field_88 = 0;
+  pBLVRenderParams->field_90 = 64;
+  pBLVRenderParams->field_94 = 6;
+  return result;
+}
+
+//----- (00440B44) --------------------------------------------------------
+void IndoorLocation::ExecDraw(bool bD3D)
+{
+  int v2; // eax@3
+  IndoorCameraD3D_Vec4 *v3; // edx@4
+  unsigned int v5; // ecx@9
+  RenderVertexSoft *v6; // [sp-4h] [bp-8h]@4
+
+  if (bD3D)
+  {
+    pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
+    for (uint i = 0; i < pBspRenderer->uNumFaceIDs; ++i)
+    {
+      v2 = pBspRenderer->pFaceIDs[2 * i + 1];
+      if ( pBspRenderer->field_FA8[v2].std__vector_0007A8 == -1 )
+      {
+        v6 = 0;
+        v3 = 0;
+      }
+      else
+      {
+        v3 = pBspRenderer->field_FA8[v2].std__vector_0007AC;
+        v6 = pBspRenderer->field_FA8[v2].pVertices;
+      }
+      IndoorLocation::ExecDraw_d3d(pBspRenderer->pFaceIDs[2 * i], v3, 4, v6);
+    }
+  }
+  else
+  {
+    for (uint j = 0; j < pBspRenderer->uNumFaceIDs; ++j )
+    {
+      v5 = pBspRenderer->pFaceIDs[2 * j];
+      pBLVRenderParams->field_7C = &pBspRenderer->field_FA8[pBspRenderer->pFaceIDs[2 * j + 1]].field_C;
+      IndoorLocation::ExecDraw_sw(v5);
+    }
+  }
+}
+
+//----- (00440BED) --------------------------------------------------------
+void __fastcall sub_440BED(IndoorLocation_drawstru *_this)
+{
+  unsigned __int16 *v1; // edi@7
+  char *v2; // esi@8
+  int v3; // ecx@9
+  unsigned int v4; // edx@9
+  char *v5; // eax@10
+  signed int v6; // [sp+8h] [bp-8h]@7
+  int v7; // [sp+Ch] [bp-4h]@8
+
+  PrepareDrawLists_BLV(_this);
+  if (pBLVRenderParams->uPartySectorID)
+    IndoorLocation::ExecDraw(pRenderer->pRenderD3D != 0);
+  pRenderer->DrawBillboardList_BLV();
+  if ( !pRenderer->pRenderD3D )
+  {
+    if ( pBLVRenderParams->uFlags & 2 )
+      stru170_sub_4B0967();
+    if ( pBLVRenderParams->uFlags & 1 )
+    {
+      v1 = pBLVRenderParams->pRenderTarget;
+      v6 = 0;
+      if ( (signed int)pBspRenderer->std__vector_000FA8 > 0 )
+      {
+        v7 = 0;
+        v2 = (char *)&pBspRenderer->field_FA8[0].field_C._viewport_space_w;
+        do
+        {
+          v3 = *((int *)v2 - 1);
+          v4 = pRenderer->uTargetSurfacePitch * *((int *)v2 - 1);
+          if ( v3 <= *(int *)v2 )
+          {
+            v5 = (char *)&pBspRenderer->field_FA8[0].field_C.array_3D8[v3 + v7];
+            do
+            {
+              v1[v4 + *((short *)v5 - 480)] = 255;
+              ++v3;
+              v1[v4 + *(short *)v5] = 255;
+              v4 += pRenderer->uTargetSurfacePitch;
+              v5 += 2;
+            }
+            while ( v3 <= *(int *)v2 );
+          }
+          ++v6;
+          v7 += 1126;
+          v2 += 2252;
+        }
+        while ( v6 < (signed int)pBspRenderer->std__vector_000FA8 );
+      }
+    }
+  }
+}
+
+
+
+
+
+//----- (00441BD4) --------------------------------------------------------
+void IndoorLocation::Draw()
+{
+  int v0; // eax@1
+  IndoorLocation_drawstru _this; // [sp+0h] [bp-4Ch]@5
+  int v2; // [sp+44h] [bp-8h]@5
+  int v3; // [sp+48h] [bp-4h]@5
+
+  v0 = 0;
+  if ( viewparams->field_50_draw_debug_outlines )
+    v0 = 1;
+  if ( viewparams->field_54 )
+    LOBYTE(v0) = v0 | 2;
+  _this.field_0_timer = pEventTimer->uTotalGameTimeElapsed;
+  _this.uFlags = v0;
+  _this.vPosition.x = pParty->vPosition.x
+                   - ((unsigned __int64)(stru_5C6E00->SinCos(pParty->sRotationY)
+                                       * (signed __int64)pParty->field_18) >> 16);
+  v2 = stru_5C6E00->SinCos(pParty->sRotationY - stru_5C6E00->uIntegerHalfPi);
+  v3 = (unsigned __int64)(v2 * (signed __int64)pParty->field_18) >> 16;
+  _this.field_1C_mb_fov = 65;
+  _this.vPosition.y = pParty->vPosition.y - v3;
+  _this.sRotationY = pParty->sRotationY;
+  _this.sRotationX = pParty->sRotationX;
+  _this.pRenderTarget = pRenderer->pTargetSurface;
+  _this.uViewportX = pViewport->uScreenX;
+  _this.uViewportY = pViewport->uScreenY;
+  _this.uViewportZ = pViewport->uScreenZ;
+  _this.uViewportW = pViewport->uScreenW;
+  _this.field_3C = pViewport->field_30;
+  _this.vPosition.z = pParty->vPosition.z + pParty->sEyelevel;
+  _this.uTargetWidth = 640;
+  _this.uTargetHeight = 480;
+  _this.pTargetZ = pRenderer->pActiveZBuffer;
+  sub_440BED(&_this);
+  pParty->uFlags &= 0xFFFFFFFDu;
+  pGame->DrawParticles();
+  array_5118E8._440F07();
+}
+
+//----- (004C0EF2) --------------------------------------------------------
+void BLVFace::FromODM(ODMFace *a2)
+{
+  this->pFacePlane_old.vNormal.x = a2->pFacePlane.vNormal.x;
+  this->pFacePlane_old.vNormal.y = a2->pFacePlane.vNormal.y;
+  this->pFacePlane_old.vNormal.z = a2->pFacePlane.vNormal.z;
+  this->pFacePlane_old.dist = a2->pFacePlane.dist;
+  this->pFacePlane.vNormal.x = (double)(a2->pFacePlane.vNormal.x & 0xFFFF) * 0.000015259022
+                             + (double)(a2->pFacePlane.vNormal.x >> 16);
+  this->pFacePlane.vNormal.y = (double)(a2->pFacePlane.vNormal.y & 0xFFFF) * 0.000015259022
+                             + (double)(a2->pFacePlane.vNormal.y >> 16);
+  this->pFacePlane.vNormal.z = (double)(a2->pFacePlane.vNormal.z & 0xFFFF) * 0.000015259022
+                             + (double)(a2->pFacePlane.vNormal.z >> 16);
+  this->pFacePlane.dist = (double)(a2->pFacePlane.dist & 0xFFFF) * 0.000015259022 + (double)(a2->pFacePlane.dist >> 16);
+  this->uAttributes = a2->uAttributes;
+  this->pBounding.x1 = a2->pBoundingBox.x1;
+  this->pBounding.y1 = a2->pBoundingBox.y1;
+  this->pBounding.z1 = a2->pBoundingBox.z1;
+  this->pBounding.x2 = a2->pBoundingBox.x2;
+  this->pBounding.y2 = a2->pBoundingBox.y2;
+  this->pBounding.z2 = a2->pBoundingBox.z2;
+  this->zCalc1 = a2->zCalc1;
+  this->zCalc2 = a2->zCalc2;
+  this->zCalc3 = a2->zCalc3;
+  this->pXInterceptDisplacements = a2->pXInterceptDisplacements;
+  this->pYInterceptDisplacements = a2->pYInterceptDisplacements;
+  this->pZInterceptDisplacements = a2->pZInterceptDisplacements;
+  this->uPolygonType = (PolygonType)a2->uPolygonType;
+  this->uNumVertices = a2->uNumVertices;
+  this->uBitmapID = a2->uTextureID;
+  this->pVertexIDs = a2->pVertexIDs;
+}
+
+//----- (004B0A25) --------------------------------------------------------
+void IndoorLocation::ExecDraw_d3d(unsigned int uFaceID, IndoorCameraD3D_Vec4 *pVertices, unsigned int uNumVertices, RenderVertexSoft *a4)
+{
+  //unsigned int v4; // esi@1
+  char *v5; // eax@4
+  signed int v6; // ecx@4
+  char *v7; // eax@8
+  signed int v8; // ecx@8
+  //BLVFace *v9; // esi@13
+  //IndoorCameraD3D *v10; // edi@16
+  //int v11; // ebx@17
+  //Vec3_short_ *v12; // ecx@18
+  //char *v13; // edx@18
+  //int v14; // eax@19
+  //unsigned __int8 v15; // sf@19
+  //unsigned __int8 v16; // of@19
+  int v17; // ebx@25
+  //double v18; // st7@27
+  //double v19; // st6@27
+  //double v20; // st5@27
+  //char v21; // dl@27
+  //unsigned int v22; // eax@44
+  unsigned int v23; // eax@35
+  //DWORD v24; // eax@37
+  //int v25; // eax@38
+  //char *v26; // edi@38
+  IDirect3DTexture2 *v27; // eax@42
+  Texture *v28; // [sp+Ch] [bp-1Ch]@15
+  //int i; // [sp+10h] [bp-18h]@38
+  //LightmapBuilder *pStru4; // [sp+14h] [bp-14h]@16
+  //IndoorCameraD3D *v31; // [sp+18h] [bp-10h]@16
+  //IndoorCameraD3D_Vec4 *a7; // [sp+1Ch] [bp-Ch]@1
+  //unsigned int uFaceID_; // [sp+20h] [bp-8h]@1
+  unsigned int uNumVerticesa; // [sp+24h] [bp-4h]@17
+  int a4a; // [sp+34h] [bp+Ch]@25
+  //unsigned int a4b; // [sp+34h] [bp+Ch]@38
+
+  //v4 = uFaceID;
+  //a7 = pVertices;
+  //uFaceID_ = uFaceID;
+  if (uFaceID >= pIndoor->uNumFaces)
+    return;
+
+  static RenderVertexSoft static_vertices_F7C228[64];
+  static RenderVertexSoft static_vertices_F7B628[64];
+  static stru154 stru_F7B60C; // idb
+
+    //v9 = &pIndoor->pFaces[uFaceID];
+  auto pFace = &pIndoor->pFaces[uFaceID];
+  if (pFace->uNumVertices < 3)
+    return;
+
+
+  if (pFace->Invisible())
+    return;
+  
+  ++pBLVRenderParams->uNumFacesRenderedThisFrame;
+  pFace->uAttributes |= 0x80u;
+
+  if (!pFace->GetTexture())
+    return;
+
+  v28 = pFace->GetTexture();
+
+  if (!pGame->pIndoorCameraD3D->IsCulled(pFace))
+  {
+    uNumVerticesa = pFace->uNumVertices;
+    for (uint i = 0; i < pFace->uNumVertices; ++i)
+    {
+      static_vertices_F7C228[i].vWorldPosition.x = pIndoor->pVertices[pFace->pVertexIDs[i]].x;
+      static_vertices_F7C228[i].vWorldPosition.y = pIndoor->pVertices[pFace->pVertexIDs[i]].y;
+      static_vertices_F7C228[i].vWorldPosition.z = pIndoor->pVertices[pFace->pVertexIDs[i]].z;
+      static_vertices_F7C228[i].u = (signed short)pFace->pVertexUIDs[i];
+      static_vertices_F7C228[i].v = (signed short)pFace->pVertexVIDs[i];
+    }
+
+    if (!pVertices ||
+        (pGame->pStru9Instance->_498377(a4, 4u, pVertices, static_vertices_F7C228, &uNumVerticesa), uNumVerticesa) )
+    {
+      if (pGame->pIndoorCameraD3D->_437285_prolly_colide_vertices_against_frustrum(
+                     static_vertices_F7C228,
+                     &uNumVerticesa,
+                     static_vertices_F7B628,
+                     pGame->pIndoorCameraD3D->std__vector_000034_prolly_frustrum,
+                     4,
+                     false,
+                     0) != 1
+                || uNumVerticesa )
+      {
+        a4a = SHIWORD(stru_F8AD28.uCurrentAmbientLightLevel);
+        v17 = (248 - 8 * SHIWORD(stru_F8AD28.uCurrentAmbientLightLevel)) | (((248 - 8 * SHIWORD(stru_F8AD28.uCurrentAmbientLightLevel)) | ((248 - 8 * SHIWORD(stru_F8AD28.uCurrentAmbientLightLevel)) << 8)) << 8);
+        sub_4B0E07(uFaceID);
+        pGame->pLightmapBuilder->ApplyLights_IndoorFace(uFaceID);
+        pDecalBuilder->ApplyBloodsplatDecals_IndoorFace(uFaceID);
+        pGame->pIndoorCameraD3D->ViewTransfrom_OffsetUV(static_vertices_F7B628, uNumVerticesa, array_507D30, &stru_F8AD28);
+        pGame->pIndoorCameraD3D->Project(array_507D30, uNumVerticesa, 0);
+        pGame->pLightmapBuilder->std__vector_000004_size = 0;
+        if (stru_F8AD28.uNumLightsApplied > 0 ||
+            pDecalBuilder->uNumDecals > 0)
+        {
+          stru_F7B60C.face_plane.vNormal.x = pFace->pFacePlane.vNormal.x;
+          stru_F7B60C.polygonType = pFace->uPolygonType;
+          stru_F7B60C.face_plane.vNormal.y = pFace->pFacePlane.vNormal.y;
+          stru_F7B60C.face_plane.vNormal.z = pFace->pFacePlane.vNormal.z;
+          stru_F7B60C.face_plane.dist = pFace->pFacePlane.dist;
+        }
+
+        if (stru_F8AD28.uNumLightsApplied > 0 &&
+            !(pFace->uAttributes & 0x400000))
+          pGame->pLightmapBuilder->ApplyLights(
+                    &stru_F8AD28,
+                    &stru_F7B60C,
+                    uNumVerticesa,
+                    array_507D30,
+                    pVertices,
+                    0);
+
+        if (pDecalBuilder->uNumDecals > 0)
+          pDecalBuilder->ApplyDecals(
+                    a4a,
+                    1,
+                    &stru_F7B60C,
+                    uNumVerticesa,
+                    array_507D30,
+                    pVertices,
+                    0,
+                    pFace->uSectorID);
+
+        if (pFace->Animated() &&
+            pFace->uBitmapID == pRenderer->field_1036AC_bitmapid )
+        {
+          __debugbreak();
+          v23 = pRenderer->pHDWaterBitmapIDs[pRenderer->field_1036A8_bitmapid];
+          goto LABEL_42;
+        }
+
+        if (pFace->Animated())
+        {
+          //auto v24 = GetTickCount() / 4;
+          //auto v25 = v24 - stru_5C6E00->uIntegerHalfPi;
+          uint eightSeconds = GetTickCount() % 8000;
+          float angle = (eightSeconds / 8000.0f) * 2 * 3.1415f;
+
+          //animte lava back and forth
+          for (uint i = 0; i < uNumVerticesa; ++i)
+            //array_507D30[i].v += (double)(pBitmaps_LOD->pTextures[pFace->uBitmapID].uHeightMinus1 & (unsigned int)(stru_5C6E00->SinCos(v25) >> 8));
+            array_507D30[i].v += pBitmaps_LOD->pTextures[pFace->uBitmapID].uHeightMinus1 * cosf(angle);
+
+          v23 = pFace->uBitmapID;
+          goto LABEL_42;
+        }
+        else if (pFace->uAttributes & 0x4000)
+        {
+            v23 = pTextureFrameTable->GetFrameTexture(
+                            pFace->uBitmapID,
+                            pBLVRenderParams->field_0_timer_);
+LABEL_42:
+                    v27 = pBitmaps_LOD->pHardwareTextures[v23];
+                    if (pFace->uAttributes & 0x400000)
+                      _479A53_draw_some_blv_poly(uNumVerticesa, uFaceID);
+                    else
+                      pRenderer->DrawIndoorPolygon(uNumVerticesa, pFace, v27, v28, 8 * uFaceID | 6, v17, 0);
+                    return;
+        }
+      }
+    }
+  }
+}
+
+//----- (004AFF79) --------------------------------------------------------
+void IndoorLocation::ExecDraw_sw(unsigned int uFaceID)
+{
+  unsigned int v1; // ebx@1
+  BLVFace *v2; // esi@3
+  unsigned int v3; // eax@3
+  Texture *v4; // eax@8
+  Texture *v5; // edi@8
+  int v6; // eax@9
+  int v7; // eax@9
+  int v8; // ecx@17
+  int v9; // ebx@17
+  int v10; // eax@17
+  int v11; // esi@17
+  unsigned int v12; // eax@17
+  int j; // ecx@19
+  int v14; // edx@20
+  int v15; // eax@20
+  int v16; // edx@20
+  int i; // ebx@22
+  int v18; // ecx@23
+  int v19; // eax@23
+  int v20; // eax@23
+  int v21; // eax@24
+  unsigned __int8 *v22; // ecx@24
+  int v23; // ebx@24
+  int v24; // esi@25
+  int v25; // eax@28
+  unsigned __int16 *v26; // eax@28
+  unsigned int v27; // eax@29
+  int v28; // eax@30
+  char *v29; // esi@31
+  int v30; // eax@33
+  int v31; // eax@33
+  int v32; // eax@35
+  int v33; // edx@35
+  signed int v34; // ebx@35
+  int v35; // eax@35
+  int v36; // ebx@35
+  signed int v37; // ebx@35
+  signed int v38; // edi@35
+  unsigned int v39; // edi@36
+  int v40; // edx@40
+  int v41; // ecx@40
+  signed int v42; // edx@40
+  int v43; // edx@42
+  int v44; // eax@42
+  unsigned __int16 *v45; // eax@43
+  int *v46; // esi@44
+  unsigned __int16 *v47; // edi@44
+  unsigned int v48; // edx@44
+  int v49; // ebx@44
+  char v50; // cl@44
+  char v51; // ch@44
+  unsigned int v52; // ebx@46
+  int v53; // edx@46
+  unsigned int v54; // ebx@46
+  int v55; // edx@46
+  unsigned int v56; // ebx@47
+  int v57; // edx@47
+  int v58; // ebx@47
+  int v59; // edx@47
+  unsigned __int16 *v60; // eax@50
+  int *v61; // esi@51
+  unsigned __int16 *v62; // edi@51
+  unsigned int v63; // edx@51
+  int v64; // ebx@51
+  char v65; // cl@51
+  char v66; // ch@51
+  unsigned int v67; // ebx@53
+  int v68; // edx@53
+  unsigned int v69; // ebx@53
+  int v70; // edx@53
+  unsigned int v71; // ebx@54
+  int v72; // edx@54
+  int v73; // ebx@54
+  int v74; // edx@54
+  unsigned __int16 *v75; // eax@58
+  int *v76; // esi@59
+  int v77; // edi@59
+  unsigned int v78; // edx@59
+  int v79; // ebx@59
+  char v80; // cl@59
+  char v81; // ch@59
+  int v82; // ebx@61
+  int v83; // edx@61
+  unsigned int v84; // ebx@62
+  int v85; // edx@62
+  unsigned __int16 *v86; // eax@65
+  int *v87; // esi@66
+  int v88; // edi@66
+  unsigned int v89; // edx@66
+  int v90; // ebx@66
+  char v91; // cl@66
+  char v92; // ch@66
+  int v93; // ebx@68
+  int v94; // edx@68
+  unsigned __int16 v95; // bx@69
+  int v96; // edx@69
+  unsigned __int8 *v97; // [sp+Ch] [bp-9Ch]@24
+  unsigned __int8 *v98; // [sp+10h] [bp-98h]@24
+  unsigned __int8 *v99; // [sp+14h] [bp-94h]@24
+  unsigned __int8 *v100; // [sp+18h] [bp-90h]@24
+  int v101; // [sp+1Ch] [bp-8Ch]@40
+  int v102; // [sp+20h] [bp-88h]@31
+  BLVFace *v103; // [sp+24h] [bp-84h]@3
+  unsigned __int16 *v104; // [sp+28h] [bp-80h]@24
+  int v105; // [sp+2Ch] [bp-7Ch]@30
+  int v106; // [sp+30h] [bp-78h]@24
+  int v107; // [sp+34h] [bp-74h]@9
+  Texture *v108; // [sp+38h] [bp-70h]@8
+  int v109; // [sp+3Ch] [bp-6Ch]@9
+  unsigned int v110; // [sp+40h] [bp-68h]@24
+  unsigned int v111; // [sp+44h] [bp-64h]@1
+  int *k; // [sp+48h] [bp-60h]@31
+  int v113; // [sp+4Ch] [bp-5Ch]@35
+  int v114; // [sp+50h] [bp-58h]@35
+  int v115; // [sp+54h] [bp-54h]@42
+  unsigned __int8 *v116; // [sp+58h] [bp-50h]@35
+  int v117; // [sp+5Ch] [bp-4Ch]@33
+  int a1; // [sp+60h] [bp-48h]@27
+  int v119; // [sp+64h] [bp-44h]@17
+  int v120; // [sp+68h] [bp-40h]@23
+  unsigned int v121; // [sp+6Ch] [bp-3Ch]@40
+  unsigned int v122; // [sp+70h] [bp-38h]@35
+  int v123; // [sp+74h] [bp-34h]@30
+  int v124; // [sp+78h] [bp-30h]@17
+  int v125; // [sp+7Ch] [bp-2Ch]@35
+  unsigned int v126; // [sp+80h] [bp-28h]@9
+  int v127; // [sp+84h] [bp-24h]@17
+  int v128; // [sp+88h] [bp-20h]@9
+  int *pZPixel; // [sp+8Ch] [bp-1Ch]@28
+  int a2; // [sp+90h] [bp-18h]@16
+  unsigned int v131; // [sp+94h] [bp-14h]@17
+  unsigned __int16 *pColorPixel; // [sp+98h] [bp-10h]@28
+  int v133; // [sp+9Ch] [bp-Ch]@17
+  int v134; // [sp+A0h] [bp-8h]@17
+  int v135; // [sp+A4h] [bp-4h]@24
+
+  v1 = uFaceID;
+  v111 = pRenderer->uTargetSurfacePitch;
+  if ( (uFaceID & 0x80000000u) == 0 )
+  {
+    if ( (signed int)uFaceID < (signed int)pIndoor->uNumFaces )
+    {
+      v2 = &pIndoor->pFaces[uFaceID];
+      v103 = v2;
+      v3 = v2->uAttributes;
+      if ( !(BYTE1(v3) & 0x20) )
+      {
+        if ( v3 & 0x400000 )
+        {
+          sub_4ADD1D(uFaceID);
+          return;
+        }
+        if ( !(v3 & 0x10) || (sub_4AD504(uFaceID), pRenderer->pRenderD3D) )
+        {
+          v4 = v2->GetTexture();
+          ++pBLVRenderParams->uNumFacesRenderedThisFrame;
+          v5 = v4;
+          v108 = v4;
+          if ( v4 )
+          {
+            v6 = v4->palette_id2;
+            LOBYTE(v2->uAttributes) |= 0x80u;
+            v109 = v6;
+            sub_4AE5F1(v1);
+            v126 = stru_F8AD28.pDeltaUV[0];
+            v128 = stru_F8AD28.pDeltaUV[1];
+            v107 = bUseLoResSprites;
+            v7 = sub_423B5D(v1);
+            if ( v7 )
+            {
+              if ( sub_424829(v7, &stru_F8A590, pBLVRenderParams->field_7C, v1) )
+              {
+                if ( v2->uPolygonType == 1 )
+                {
+                  for ( i = 0; i < stru_F8AD28.uNumLightsApplied; stru_F8AD28._blv_lights_ys[v18] = v20 )
+                  {
+                    v18 = i;
+                    v120 = stru_F8AD28._blv_lights_xs[i];
+                    v134 = (unsigned __int64)(v120 * (signed __int64)-stru_F8AD28.plane_4.vNormal.y) >> 16;
+                    v133 = stru_F8AD28.plane_4.vNormal.x;
+                    v120 = stru_F8AD28._blv_lights_ys[i];
+                    v133 = (unsigned __int64)(v120 * (signed __int64)stru_F8AD28.plane_4.vNormal.x) >> 16;
+                    v19 = v128;
+                    stru_F8AD28._blv_lights_xs[i] = v126
+                                                  + v134
+                                                  + ((unsigned __int64)(v120
+                                                                      * (signed __int64)stru_F8AD28.plane_4.vNormal.x) >> 16);
+                    v20 = v19 - stru_F8AD28._blv_lights_zs[i++];
+                  }
+                }
+                else
+                {
+                  if ( v2->uPolygonType != 3 )
+                  {
+                    if ( v2->uPolygonType == 4 )
+                    {
+LABEL_16:
+                      a2 = 0;
+                      if ( stru_F8AD28.uNumLightsApplied > 0 )
+                      {
+                        do
+                        {
+                          v8 = a2;
+                          v9 = stru_F8AD28._blv_lights_xs[a2];
+                          v131 = stru_F8AD28._blv_lights_ys[a2];
+                          v10 = stru_F8AD28._blv_lights_zs[a2];
+                          v11 = (signed int)(v10 * stru_F8AD28.plane_4.vNormal.z
+                                           + stru_F8AD28.plane_4.dist
+                                           + v9 * stru_F8AD28.plane_4.vNormal.x
+                                           + v131 * stru_F8AD28.plane_4.vNormal.y) >> 16;
+                          v119 = v9
+                               - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
+                                                   * (signed __int64)((signed int)(v10 * stru_F8AD28.plane_4.vNormal.z
+                                                                                 + stru_F8AD28.plane_4.dist
+                                                                                 + v9 * stru_F8AD28.plane_4.vNormal.x
+                                                                                 + v131 * stru_F8AD28.plane_4.vNormal.y) >> 16)) >> 16);
+                          v131 -= (unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)v11) >> 16;
+                          v127 = v10 - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.z * (signed __int64)v11) >> 16);
+                          stru_F8AD28._blv_lights_xs[a2] = ((unsigned __int64)(v119
+                                                                             * (signed __int64)stru_F8AD28.vec_14.x) >> 16)
+                                                         + ((unsigned __int64)((signed int)v131
+                                                                             * (signed __int64)stru_F8AD28.vec_14.y) >> 16);
+                          v124 = (unsigned __int64)(v119 * (signed __int64)stru_F8AD28.vec_20.x) >> 16;
+                          v134 = (unsigned __int64)((signed int)v131 * (signed __int64)stru_F8AD28.vec_20.y) >> 16;
+                          v133 = (unsigned __int64)(v127 * (signed __int64)stru_F8AD28.vec_20.z) >> 16;
+                          v12 = v126;
+                          stru_F8AD28._blv_lights_ys[v8] = v124
+                                                         + ((unsigned __int64)((signed int)v131
+                                                                             * (signed __int64)stru_F8AD28.vec_20.y) >> 16)
+                                                         + ((unsigned __int64)(v127
+                                                                             * (signed __int64)stru_F8AD28.vec_20.z) >> 16);
+                          stru_F8AD28._blv_lights_xs[v8] += v12;
+                          stru_F8AD28._blv_lights_ys[v8] += v128;
+                          ++a2;
+                        }
+                        while ( a2 < stru_F8AD28.uNumLightsApplied );
+                        v2 = v103;
+                      }
+                      goto LABEL_24;
+                    }
+                    if ( v2->uPolygonType != 5 )
+                    {
+                      if ( v2->uPolygonType != 6 )
+                        goto LABEL_24;
+                      goto LABEL_16;
+                    }
+                  }
+                  for ( j = 0; j < stru_F8AD28.uNumLightsApplied; *(int *)v15 = v16 )
+                  {
+                    v14 = v128;
+                    stru_F8AD28._blv_lights_xs[j] += v126;
+                    v15 = 4 * j + 16297672;
+                    v16 = v14 - stru_F8AD28._blv_lights_ys[j++];
+                  }
+                }
+LABEL_24:
+                v135 = 1;
+                pGame->_44ED0A(v2, &v135, 31);
+                v104 = sr_sub_47C24C_get_palette(v2, v109, 0, 1);
+                v134 = stru_F8AD28.field_44;
+                v106 = stru_F8AD28.field_48;
+                v21 = stru_F8A590._viewport_space_y;
+                a2 = stru_F8A590._viewport_space_y;
+                v110 = v111 * stru_F8A590._viewport_space_y;
+                v97 = v5->pLevelOfDetail0;
+                v98 = v5->pLevelOfDetail1;
+                v99 = v5->pLevelOfDetail2;
+                v22 = v5->pLevelOfDetail3;
+                v23 = 640 * stru_F8A590._viewport_space_y;
+                v119 = 640 * stru_F8A590._viewport_space_y;
+                v100 = v22;
+                if ( stru_F8A590._viewport_space_y <= stru_F8A590._viewport_space_w )
+                {
+                  v24 = 2 * stru_F8A590._viewport_space_y;
+                  v120 = 2 * stru_F8A590._viewport_space_y;
+                  while ( 1 )
+                  {
+                    a1 = *(__int16 *)((char *)stru_F8A590.array_18 + v24);
+                    sub_4AE313(a1, v21, &stru_F81018.field_0);
+                    if ( LOBYTE(viewparams->field_20) )
+                    {
+                      v27 = v111 * (v24 - pBLVRenderParams->uViewportY);
+                      pZPixel = &pBLVRenderParams->pTargetZBuffer[2
+                                                               * (*(__int16 *)((char *)stru_F8A590.array_18 + v24)
+                                                                + 320 * (v24 - pBLVRenderParams->uViewportY))
+                                                               - pBLVRenderParams->uViewportX];
+                      pColorPixel = &pBLVRenderParams->pRenderTarget[v27
+                                                                  + 2 * *(__int16 *)((char *)stru_F8A590.array_18 + v24)
+                                                                  - pBLVRenderParams->uViewportX];
+                      v26 = &pBLVRenderParams->pRenderTarget[v27
+                                                          + 2 * *(__int16 *)((char *)stru_F8A590.array_3D8 + v24)
+                                                          - pBLVRenderParams->uViewportX];
+                      v23 = v119;
+                    }
+                    else
+                    {
+                      v25 = *(__int16 *)((char *)stru_F8A590.array_18 + v24);
+                      pZPixel = &pBLVRenderParams->pTargetZBuffer[v25 + v23];
+                      pColorPixel = &pBLVRenderParams->pRenderTarget[v25 + v110];
+                      v26 = &pBLVRenderParams->pRenderTarget[v110 + *(__int16 *)((char *)stru_F8A590.array_3D8 + v24)];
+                    }
+                    v131 = (unsigned int)v26;
+                    HIWORD(v28) = HIWORD(stru_F81018.field_0.field_0);
+                    LOWORD(v28) = 0;
+                    v105 = stru_F8AD28.field_0 | v28;
+                    v123 = sub_4AE491(SHIWORD(stru_F81018.field_0.field_4), SHIWORD(stru_F81018.field_0.field_8));
+                    if ( (unsigned int)pColorPixel < v131 )
+                    {
+                      v102 = v107 + v106;
+                      v29 = (char *)&stru_F81018.field_34.field_8;
+                      a1 += v134;
+                      for ( k = &stru_F81018.field_34.field_8; ; v29 = (char *)k )
+                      {
+                        sub_4AE313(a1, a2, (stru337_stru0 *)(v29 - 8));
+                        v30 = *((int *)v29 - 2);
+                        LOWORD(v30) = 0;
+                        v117 = v105;
+                        v31 = stru_F8AD28.field_0 | v30;
+                        if ( v105 <= (unsigned int)v31 )
+                          v117 = v31;
+                        v105 = v31;
+                        v32 = *((int *)v29 - 14);
+                        v122 = *((int *)v29 - 14) >> v107;
+                        v33 = *((int *)v29 - 13);
+                        v125 = *((int *)v29 - 13) >> v107;
+                        v34 = *((int *)v29 - 1) - v32;
+                        v113 = (*(int *)v29 - v33) >> v102;
+                        v35 = *((int *)v29 - 11);
+                        v114 = v34 >> v102;
+                        v116 = (&v97)[4 * v35];
+                        v36 = v35 + 16 - v5->uWidthLn2;
+                        v133 = v35 + 16;
+                        v127 = v35 + v36;
+                        v37 = v5->uWidthMinus1 >> v35;
+                        v38 = v5->uHeightMinus1 >> v35 << (v35 + 16);
+                        v128 = v37;
+                        v126 = v38;
+                        v39 = (unsigned int)(LOBYTE(viewparams->field_20) ? &pColorPixel[2 * v134] : &pColorPixel[v134]);
+                        if ( v39 > v131 )
+                          v39 = v131;
+                        v40 = *((short *)v29 + 1);
+                        v41 = *((short *)v29 - 1);
+                        v121 = v39;
+                        v42 = sub_4AE491(v41, v40);
+                        v101 = v42;
+                        v124 = (signed int)(v39 - (int)pColorPixel) >> 1;
+                        if ( v123 >> 16 == v42 >> 16 || v135 & 2 )
+                        {
+                          v123 = (int)sr_sub_47C24C_get_palette(v103, v109, v123 >> 16, 1);
+                          if ( LOBYTE(viewparams->field_20) )
+                          {
+                            v86 = pColorPixel;
+                            if ( (unsigned int)pColorPixel < v121 )
+                            {
+                              v87 = pZPixel;
+                              v88 = v123;
+                              v89 = v122;
+                              v90 = v125;
+                              v91 = v133;
+                              v92 = v127;
+                              if ( v124 & 2 )
+                              {
+                                *pZPixel = v117;
+                                v87 -= 2;
+                                v86 = pColorPixel + 2;
+                                goto LABEL_69;
+                              }
+                              do
+                              {
+                                v86 += 4;
+                                v93 = *(&v116[v128 & (v89 >> v91)] + ((v126 & v90) >> v92));
+                                v94 = v117;
+                                LOWORD(v93) = *(short *)(v88 + 2 * v93);
+                                *v87 = v117;
+                                v87[1] = v94;
+                                v87[640] = v94;
+                                v87[641] = v94;
+                                *(v86 - 4) = v93;
+                                *(v86 - 3) = v93;
+                                v86[636] = v93;
+                                v86[637] = v93;
+                                v87[2] = v94;
+                                v87[3] = v94;
+                                v87[642] = v94;
+                                v87[643] = v94;
+                                v122 += v114;
+                                v125 += v113;
+                                v89 = v122;
+                                v90 = v125;
+LABEL_69:
+                                v87 += 4;
+                                v95 = *(short *)(v88 + 2 * *(&v116[v128 & (v89 >> v91)] + ((v126 & v90) >> v92)));
+                                v96 = v114;
+                                *(v86 - 2) = v95;
+                                *(v86 - 1) = v95;
+                                v86[638] = v95;
+                                v86[639] = v95;
+                                v122 += v96;
+                                v125 += v113;
+                                v89 = v122;
+                                v90 = v125;
+                              }
+                              while ( (unsigned int)v86 < v121 );
+                              pColorPixel = v86;
+                              pZPixel = v87;
+                            }
+                          }
+                          else
+                          {
+                            v75 = pColorPixel;
+                            if ( (unsigned int)pColorPixel < v121 )
+                            {
+                              v76 = pZPixel;
+                              v77 = v123;
+                              v78 = v122;
+                              v79 = v125;
+                              v80 = v133;
+                              v81 = v127;
+                              if ( v124 & 1 )
+                              {
+                                *pZPixel = v117;
+                                --v76;
+                                v75 = pColorPixel + 1;
+                                goto LABEL_62;
+                              }
+                              do
+                              {
+                                v75 += 2;
+                                v82 = *(&v116[v128 & (v78 >> v80)] + ((v126 & v79) >> v81));
+                                v83 = v117;
+                                LOWORD(v82) = *(short *)(v77 + 2 * v82);
+                                *v76 = v117;
+                                *(v75 - 2) = v82;
+                                v76[1] = v83;
+                                v122 += v114;
+                                v125 += v113;
+                                v78 = v122;
+                                v79 = v125;
+LABEL_62:
+                                v84 = (unsigned int)(&v116[v128 & (v78 >> v80)] + ((v126 & v79) >> v81));
+                                v76 += 2;
+                                v85 = v114;
+                                *(v75 - 1) = *(short *)(v77 + 2 * *(char *)v84);
+                                v122 += v85;
+                                v125 += v113;
+                                v78 = v122;
+                                v79 = v125;
+                              }
+                              while ( (unsigned int)v75 < v121 );
+                              pColorPixel = v75;
+                              pZPixel = v76;
+                            }
+                          }
+                        }
+                        else
+                        {
+                          v43 = (v42 - v123) >> v106;
+                          v44 = v123 - v43;
+                          v123 = v43;
+                          v115 = v44;
+                          if ( LOBYTE(viewparams->field_20) )
+                          {
+                            v60 = pColorPixel;
+                            if ( (unsigned int)pColorPixel < v121 )
+                            {
+                              v61 = pZPixel;
+                              v62 = v104;
+                              v63 = v122;
+                              v64 = v125;
+                              v65 = v133;
+                              v66 = v127;
+                              if ( v124 & 2 )
+                              {
+                                *pZPixel = v117;
+                                v61 += 2;
+                                v60 = pColorPixel + 2;
+                                goto LABEL_54;
+                              }
+                              do
+                              {
+                                v67 = (v128 & (v63 >> v65)) + ((v126 & v64) >> v66);
+                                v68 = v123 + v115;
+                                v60 += 4;
+                                v115 = v68;
+                                v69 = ((v68 & 0xFFFF0000u) >> 8) + v116[v67];
+                                v70 = v117;
+                                LOWORD(v69) = v62[v69];
+                                *v61 = v117;
+                                v61[1] = v70;
+                                v61[640] = v70;
+                                v61[641] = v70;
+                                *(v60 - 4) = v69;
+                                *(v60 - 3) = v69;
+                                v60[636] = v69;
+                                v60[637] = v69;
+                                v61[2] = v70;
+                                v61[3] = v70;
+                                v61[642] = v70;
+                                v61[643] = v70;
+                                v122 += v114;
+                                v125 += v113;
+                                v63 = v122;
+                                v64 = v125;
+                                v61 += 4;
+LABEL_54:
+                                v71 = (v128 & (v63 >> v65)) + ((v126 & v64) >> v66);
+                                v72 = v123 + v115;
+                                v73 = v116[v71];
+                                v115 = v72;
+                                LOWORD(v73) = v62[((v72 & 0xFFFF0000u) >> 8) + v73];
+                                v74 = v114;
+                                *(v60 - 2) = v73;
+                                *(v60 - 1) = v73;
+                                v60[638] = v73;
+                                v60[639] = v73;
+                                v122 += v74;
+                                v125 += v113;
+                                v63 = v122;
+                                v64 = v125;
+                              }
+                              while ( (unsigned int)v60 < v121 );
+                              pColorPixel = v60;
+                              pZPixel = v61;
+                            }
+                          }
+                          else
+                          {
+                            v45 = pColorPixel;
+                            if ( (unsigned int)pColorPixel < v121 )
+                            {
+                              v46 = pZPixel;
+                              v47 = v104;
+                              v48 = v122;
+                              v49 = v125;
+                              v50 = v133;
+                              v51 = v127;
+                              if ( v124 & 1 )
+                              {
+                                *pZPixel = v117;
+                                ++v46;
+                                v45 = pColorPixel + 1;
+                                goto LABEL_47;
+                              }
+                              do
+                              {
+                                v52 = (v128 & (v48 >> v50)) + ((v126 & v49) >> v51);
+                                v53 = v123 + v115;
+                                v45 += 2;
+                                v115 = v53;
+                                v54 = ((v53 & 0xFFFF0000u) >> 8) + v116[v52];
+                                v55 = v117;
+                                LOWORD(v54) = v47[v54];
+                                *v46 = v117;
+                                *(v45 - 2) = v54;
+                                v46[1] = v55;
+                                v122 += v114;
+                                v125 += v113;
+                                v48 = v122;
+                                v49 = v125;
+                                v46 += 2;
+LABEL_47:
+                                v56 = (v128 & (v48 >> v50)) + ((v126 & v49) >> v51);
+                                v57 = v123 + v115;
+                                v58 = v116[v56];
+                                v115 = v57;
+                                LOWORD(v58) = v47[((v57 & 0xFFFF0000u) >> 8) + v58];
+                                v59 = v114;
+                                *(v45 - 1) = v58;
+                                v122 += v59;
+                                v125 += v113;
+                                v48 = v122;
+                                v49 = v125;
+                              }
+                              while ( (unsigned int)v45 < v121 );
+                              pColorPixel = v45;
+                              pZPixel = v46;
+                            }
+                          }
+                        }
+                        k += 13;
+                        v5 = v108;
+                        v123 = v101;
+                        a1 += v134;
+                        if ( (unsigned int)pColorPixel >= v131 )
+                          break;
+                      }
+                      v23 = v119;
+                      v24 = v120;
+                    }
+                    ++a2;
+                    v110 += v111;
+                    v23 += 640;
+                    v24 += 2;
+                    v120 = v24;
+                    v119 = v23;
+                    if ( a2 > stru_F8A590._viewport_space_w )
+                      break;
+                    v21 = a2;
+                  }
+                }
+                return;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+// 4AE491: using guessed type int __fastcall sub_4AE491(int, int);
+
+
+
+
+//----- (004B0E07) --------------------------------------------------------
+unsigned int __fastcall sub_4B0E07(unsigned int uFaceID)
+{
+  BLVFace *v1; // edi@1
+  BLVFaceExtra *v2; // ecx@1
+  Texture *v3; // esi@1
+  unsigned int v4; // eax@1
+  unsigned int v5; // ecx@1
+  unsigned int result; // eax@1
+  unsigned int v7; // ecx@5
+
+  v1 = &pIndoor->pFaces[uFaceID];
+  v2 = &pIndoor->pFaceExtras[v1->uFaceExtraID];
+  v3 = (Texture *)(v1->uBitmapID != -1 ? (int)&pBitmaps_LOD->pTextures[v1->uBitmapID] : 0);
+  stru_F8AD28.pDeltaUV[0] = v2->sTextureDeltaU;
+  stru_F8AD28.pDeltaUV[1] = v2->sTextureDeltaV;
+  v4 = GetTickCount();
+  v5 = v1->uAttributes;
+  result = v4 >> 3;
+  if ( v5 & 4 )
+  {
+    stru_F8AD28.pDeltaUV[1] -= result & v3->uHeightMinus1;
+  }
+  else
+  {
+    if ( v5 & 0x20 )
+      stru_F8AD28.pDeltaUV[1] += result & v3->uHeightMinus1;
+  }
+  v7 = v1->uAttributes;
+  if ( BYTE1(v7) & 8 )
+  {
+    stru_F8AD28.pDeltaUV[0] -= result & v3->uWidthMinus1;
+  }
+  else
+  {
+    if ( v7 & 0x40 )
+      stru_F8AD28.pDeltaUV[0] += result & v3->uWidthMinus1;
+  }
+  return result;
+}
+
+
+
+//----- (004B0EA8) --------------------------------------------------------
+void BspRenderer::PrepareFaceRenderList_d3d(int a2, unsigned int uFaceID)
+{
+  //unsigned int v3; // edx@1
+  //stru170 *v4; // ebx@1
+  //BLVFace *v5; // eax@1
+  //int v6; // ecx@2
+  unsigned __int16 v7; // ax@11
+  Vec3_short_ *v8; // esi@15
+  int v9; // edx@15
+  signed int v10; // eax@18
+  signed int v11; // edi@19
+  signed int v12; // ecx@19
+  signed int v13; // esi@19
+  signed int v14; // edx@20
+  int v15; // edx@24
+  //int v16; // esi@29
+  //BLVFace *v17; // edi@34
+  unsigned __int16 v18; // ax@34
+  char *v19; // eax@38
+  signed int v20; // ecx@38
+  char *v21; // eax@42
+  signed int v22; // ecx@42
+  //signed int v23; // edx@45
+  //char *v24; // ecx@46
+  //int v25; // eax@47
+  //Vec3_short_ *v26; // eax@47
+  //double v27; // st7@47
+  //signed int v28; // ST28_4@47
+  char v29; // al@48
+  signed int v30; // eax@51
+  int v31; // eax@52
+  //unsigned int v32; // eax@55
+  //__int16 v33; // cx@56
+  signed int v34; // [sp+Ch] [bp-14h]@18
+  //int a0; // [sp+14h] [bp-Ch]@2
+  //IndoorCameraD3D *a0a; // [sp+14h] [bp-Ch]@36
+  signed int v37; // [sp+18h] [bp-8h]@19
+  //stru10 *v38; // [sp+18h] [bp-8h]@36
+  //BLVFace *v39; // [sp+1Ch] [bp-4h]@1
+
+  //v3 = uFaceID;
+  //v4 = this;
+  //v5 = &pIndoor->pFaces[uFaceID];
+  field_FA8[std__vector_000FA8].std__vector_0007A8 = -1;
+  //v39 = &pIndoor->pFaces[uFaceID];
+
+  auto pFace = &pIndoor->pFaces[uFaceID];
+
+  if (pFace->uAttributes & 1)
+  {
+    auto p = &field_FA8[a2];
+    //v6 = (int)((char *)this + 2252 * a2);
+    //a0 = v6;
+    if (p->uFaceID == uFaceID)
+      return;
+    if (!a2 &&
+        pBLVRenderParams->vPartyPos.x >= pFace->pBounding.x1 - 16 &&
+        pBLVRenderParams->vPartyPos.x <= pFace->pBounding.x2 + 16 &&
+        pBLVRenderParams->vPartyPos.y >= pFace->pBounding.y1 - 16 &&
+        pBLVRenderParams->vPartyPos.y <= pFace->pBounding.y2 + 16 &&
+        pBLVRenderParams->vPartyPos.z >= pFace->pBounding.z1 - 16 &&
+        pBLVRenderParams->vPartyPos.z <= pFace->pBounding.z2 + 16 )
+    {
+      if ( abs(pFace->pFacePlane_old.dist + pBLVRenderParams->vPartyPos.x * pFace->pFacePlane_old.vNormal.x
+                                       + pBLVRenderParams->vPartyPos.y * pFace->pFacePlane_old.vNormal.y
+                                       + pBLVRenderParams->vPartyPos.z * pFace->pFacePlane_old.vNormal.z) <= 589824 )
+      {
+        v7 = pFace->uSectorID;
+        if ( field_FA8[0].uSectorID == v7 )
+          v7 = pFace->uBackSectorID;
+        field_FA8[std__vector_000FA8].uSectorID = v7;
+        field_FA8[std__vector_000FA8].uFaceID = uFaceID;
+        field_FA8[std__vector_000FA8].uViewportX = pBLVRenderParams->uViewportX;
+        field_FA8[std__vector_000FA8].uViewportZ = pBLVRenderParams->uViewportZ;
+        field_FA8[std__vector_000FA8].uViewportY = pBLVRenderParams->uViewportY;
+        field_FA8[std__vector_000FA8].uViewportW = pBLVRenderParams->uViewportW;
+        field_FA8[std__vector_000FA8++].field_C._43F9E1(
+          pBLVRenderParams->uViewportX,
+          pBLVRenderParams->uViewportY,
+          pBLVRenderParams->uViewportZ,
+          pBLVRenderParams->uViewportW);
+        sub_440639(std__vector_000FA8 - 1);
+        return;
+      }
+      //v5 = v39;
+      //v6 = a0;
+    }
+    v8 = &pIndoor->pVertices[pFace->pVertexIDs[0]];
+    v9 = pFace->pFacePlane_old.vNormal.x * (v8->x - pBLVRenderParams->vPartyPos.x)
+       + pFace->pFacePlane_old.vNormal.y * (v8->y - pBLVRenderParams->vPartyPos.y)
+       + pFace->pFacePlane_old.vNormal.z * (v8->z - pBLVRenderParams->vPartyPos.z);
+    if (p->uSectorID != pFace->uSectorID)
+      v9 = -v9;
+    if ( v9 < 0 )
+    {
+      v10 = sub_423B5D(uFaceID);
+      v34 = v10;
+      if ( v10 )
+      {
+        v11 = dword_50BAC8[0];
+        v12 = dword_50B9D8_ys[0];
+        a2 = dword_50BAC8[0];
+        v13 = 1;
+        v37 = dword_50B9D8_ys[0];
+        if ( v10 > 1 )
+        {
+          do
+          {
+            v14 = dword_50BAC8[v13];
+            if ( v14 < a2 )
+              a2 = dword_50BAC8[v13];
+            if ( v14 > v11 )
+              v11 = v14;
+            v15 = dword_50B9D8_ys[v13];
+            if ( v15 < v37 )
+              v37 = dword_50B9D8_ys[v13];
+            if ( v15 > v12 )
+              v12 = dword_50B9D8_ys[v13];
+            v10 = v34;
+            ++v13;
+          }
+          while ( v13 < v34 );
+        }
+        //v16 = a0;
+        if (v11 >= p->uViewportX &&
+            a2 <= p->uViewportZ &&
+            v12 >= p->uViewportY &&
+            v37 <= p->uViewportW &&
+            sub_424829(v10, &field_FA8[std__vector_000FA8].field_C, &p->field_C, uFaceID))
+        {
+          //v17 = v39;
+          v18 = pFace->uSectorID;
+          if (p->uSectorID == v18 )
+            v18 = pFace->uBackSectorID;
+          field_FA8[std__vector_000FA8].uSectorID = v18;
+          field_FA8[std__vector_000FA8].uFaceID = uFaceID;
+          field_FA8[std__vector_000FA8].uViewportX = pBLVRenderParams->uViewportX;
+          field_FA8[std__vector_000FA8].uViewportZ = pBLVRenderParams->uViewportZ;
+          field_FA8[std__vector_000FA8].uViewportY = pBLVRenderParams->uViewportY;
+          field_FA8[std__vector_000FA8].uViewportW = pBLVRenderParams->uViewportW;
+          //v38 = pGame->pStru10Instance;
+          //a0a = pGame->pIndoorCameraD3D;
+          if (p->std__vector_0007A8 == -1 )
+          {
+            v29 = pGame->pStru10Instance->_49C681_DrawDebugStuff(
+                    pFace,
+                    field_FA8[std__vector_000FA8].std__vector_0007AC,
+                    field_FA8[std__vector_000FA8].pVertices);
+          }
+          else
+          {
+            static RenderVertexSoft static_subPrepareFaceRenderList_d3d_stru_F7AA08[64];
+            static RenderVertexSoft static_subPrepareFaceRenderList_d3d_stru_F79E08[64];
+
+            //v23 = 0;
+            a2 = pFace->uNumVertices;
+            for (uint k = 0; k < pFace->uNumVertices; ++k)
+            {
+              //v24 = (char *)&static_subPrepareFaceRenderList_d3d_stru_F7AA08[0].vWorldPosition.z;
+              //do
+              //{
+                //v25 = pFace->pVertexIDs[k];
+                //v26 = &pIndoor->pVertices[pFace->pVertexIDs[k]];
+                auto pVertex = &pIndoor->pVertices[pFace->pVertexIDs[k]];
+                //v27 = (double)v26->z;
+                //v28 = v26->y;
+                //v17 = v39;
+                static_subPrepareFaceRenderList_d3d_stru_F7AA08[k].vWorldPosition.x = pVertex->x;
+                static_subPrepareFaceRenderList_d3d_stru_F7AA08[k].vWorldPosition.y = pVertex->y;
+                static_subPrepareFaceRenderList_d3d_stru_F7AA08[k].vWorldPosition.z = pVertex->z;
+                //v24 += 48;
+              //}
+              //while ( v23 < a2 );
+            }
+            pGame->pIndoorCameraD3D->_437285_prolly_colide_vertices_against_frustrum(
+              static_subPrepareFaceRenderList_d3d_stru_F7AA08,
+              (unsigned int *)&a2,
+              static_subPrepareFaceRenderList_d3d_stru_F79E08,
+              p->std__vector_0007AC,
+              4,
+              0,
+              0);
+            v29 = pGame->pStru10Instance->_49C5DA(
+                    pFace,
+                    static_subPrepareFaceRenderList_d3d_stru_F79E08,
+                    &a2,
+                    field_FA8[std__vector_000FA8].std__vector_0007AC,
+                    field_FA8[std__vector_000FA8].pVertices);
+          }
+          if ( v29 )
+          {
+            field_FA8[std__vector_000FA8].std__vector_0007A8 = uFaceID;
+            v30 = std__vector_000FA8;
+            if ( v30 < 150 )
+            {
+              v31 = v30 + 1;
+              std__vector_000FA8 = v31;
+              sub_440639(v31 - 1);
+            }
+          }
+          if ( pBLVRenderParams->uFlags & 1 )
+            pGame->pIndoorCameraD3D->PrepareAndDrawDebugOutline(pFace, 0x1E1EFF);
+        }
+      }
+    }
+  }
+  else
+  {
+    if (uNumFaceIDs < 1000 )
+    {
+      pFaceIDs[2 * uNumFaceIDs] = uFaceID;
+      pFaceIDs[2 * uNumFaceIDs++ + 1] = a2;
+    }
+  }
+}
+
+
+//----- (004AFB86) --------------------------------------------------------
+void BspRenderer::PrepareFaceRenderList_sw(int a2, unsigned int uFaceID)
+{
+  BspRenderer *v3; // ebx@1
+  BLVFace *v4; // eax@1
+  char *v5; // ecx@2
+  unsigned __int16 v6; // ax@11
+  int v7; // ecx@13
+  Vec3_short_ *v8; // esi@16
+  int v9; // edx@16
+  signed int v10; // eax@19
+  signed int v11; // edi@20
+  signed int v12; // ecx@20
+  signed int v13; // esi@20
+  int v14; // edx@21
+  int v15; // edx@25
+  unsigned __int16 v16; // ax@35
+  signed int v17; // eax@37
+  int v18; // eax@38
+  signed int v19; // [sp+Ch] [bp-14h]@19
+  char *v20; // [sp+14h] [bp-Ch]@2
+  BLVFace *v21; // [sp+18h] [bp-8h]@1
+  signed int v22; // [sp+1Ch] [bp-4h]@20
+  signed int v23; // [sp+28h] [bp+8h]@20
+
+  v3 = this;
+  v4 = &pIndoor->pFaces[uFaceID];
+  v21 = v4;
+  if ( v4->uAttributes & 1 )
+  {
+    v5 = (char *)this + 2252 * a2;
+    v20 = v5;
+    if ( uFaceID == *((short *)v5 + 2982) )
+      return;
+    if ( !a2
+      && pBLVRenderParams->vPartyPos.x >= v4->pBounding.x1 - 16
+      && pBLVRenderParams->vPartyPos.x <= v4->pBounding.x2 + 16
+      && pBLVRenderParams->vPartyPos.y >= v4->pBounding.y1 - 16
+      && pBLVRenderParams->vPartyPos.y <= v4->pBounding.y2 + 16
+      && pBLVRenderParams->vPartyPos.z >= v4->pBounding.z1 - 16
+      && pBLVRenderParams->vPartyPos.z <= v4->pBounding.z2 + 16 )
+    {
+      if ( abs(v4->pFacePlane_old.dist + pBLVRenderParams->vPartyPos.x * v4->pFacePlane_old.vNormal.x
+                                       + pBLVRenderParams->vPartyPos.y * v4->pFacePlane_old.vNormal.y
+                                       + pBLVRenderParams->vPartyPos.z * v4->pFacePlane_old.vNormal.z) <= 589824 )
+      {
+        v6 = v21->uSectorID;
+        if ( v3->field_FA8[0].uSectorID == v6 )
+          v6 = v21->uBackSectorID;
+        v3->field_FA8[v3->std__vector_000FA8].uSectorID = v6;
+        v3->field_FA8[v3->std__vector_000FA8].uFaceID = uFaceID;
+        v3->field_FA8[v3->std__vector_000FA8].uViewportX = LOWORD(pBLVRenderParams->uViewportX);
+        v3->field_FA8[v3->std__vector_000FA8].uViewportZ = LOWORD(pBLVRenderParams->uViewportZ);
+        v3->field_FA8[v3->std__vector_000FA8].uViewportY = LOWORD(pBLVRenderParams->uViewportY);
+        v3->field_FA8[v3->std__vector_000FA8].uViewportW = LOWORD(pBLVRenderParams->uViewportW);
+        v3->field_FA8[v3->std__vector_000FA8++].field_C._43F9E1(
+          SLOWORD(pBLVRenderParams->uViewportX),
+          pBLVRenderParams->uViewportY,
+          SLOWORD(pBLVRenderParams->uViewportZ),
+          pBLVRenderParams->uViewportW);
+        v7 = v3->std__vector_000FA8 - 1;
+        goto LABEL_14;
+      }
+      v4 = v21;
+      v5 = v20;
+    }
+    v8 = &pIndoor->pVertices[*v4->pVertexIDs];
+    v9 = v4->pFacePlane_old.vNormal.x * ((signed __int16)*(int *)&v8->x - pBLVRenderParams->vPartyPos.x)
+       + v4->pFacePlane_old.vNormal.y * ((signed __int16)(*(int *)&v8->x >> 16) - pBLVRenderParams->vPartyPos.y)
+       + v4->pFacePlane_old.vNormal.z * (v8->z - pBLVRenderParams->vPartyPos.z);
+    if ( *((short *)v5 + 2004) != v4->uSectorID )
+      v9 = -v9;
+    if ( v9 < 0 )
+    {
+      v10 = sub_423B5D(uFaceID);
+      v19 = v10;
+      if ( v10 )
+      {
+        v11 = dword_50BAC8[0];
+        v12 = dword_50B9D8_ys[0];
+        v23 = dword_50BAC8[0];
+        v13 = 1;
+        v22 = dword_50B9D8_ys[0];
+        if ( v10 > 1 )
+        {
+          do
+          {
+            v14 = dword_50BAC8[v13];
+            if ( v14 < v23 )
+              v23 = dword_50BAC8[v13];
+            if ( v14 > v11 )
+              v11 = dword_50BAC8[v13];
+            v15 = dword_50B9D8_ys[v13];
+            if ( v15 < v22 )
+              v22 = dword_50B9D8_ys[v13];
+            if ( v15 > v12 )
+              v12 = dword_50B9D8_ys[v13];
+            v10 = v19;
+            ++v13;
+          }
+          while ( v13 < v19 );
+        }
+        if ( v11 >= *((short *)v20 + 2005)
+          && v23 <= *((short *)v20 + 2007)
+          && v12 >= *((short *)v20 + 2006)
+          && v22 <= *((short *)v20 + 2008)
+          && sub_424829(v10, &v3->field_FA8[v3->std__vector_000FA8].field_C, (BspRenderer_stru2 *)(v20 + 4020), uFaceID) )
+        {
+          v16 = v21->uSectorID;
+          if ( *((short *)v20 + 2004) == v16 )
+            v16 = v21->uBackSectorID;
+          v3->field_FA8[v3->std__vector_000FA8].uSectorID = v16;
+          v3->field_FA8[v3->std__vector_000FA8].uFaceID = uFaceID;
+          v3->field_FA8[v3->std__vector_000FA8].uViewportX = LOWORD(pBLVRenderParams->uViewportX);
+          v3->field_FA8[v3->std__vector_000FA8].uViewportZ = LOWORD(pBLVRenderParams->uViewportZ);
+          v3->field_FA8[v3->std__vector_000FA8].uViewportY = LOWORD(pBLVRenderParams->uViewportY);
+          v3->field_FA8[v3->std__vector_000FA8].uViewportW = LOWORD(pBLVRenderParams->uViewportW);
+          v17 = v3->std__vector_000FA8;
+          if ( v17 < 150 )
+          {
+            v18 = v17 + 1;
+            v3->std__vector_000FA8 = v18;
+            v7 = v18 - 1;
+LABEL_14:
+            sub_440639(v7);
+            return;
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    if ( (signed int)this->uNumFaceIDs < 1000 )
+    {
+      this->pFaceIDs[2 * this->uNumFaceIDs] = uFaceID;
+      this->pFaceIDs[2 * this->uNumFaceIDs++ + 1] = a2;
+    }
+  }
+}
+
+//----- (004B0967) --------------------------------------------------------
+void __cdecl stru170_sub_4B0967()
+{
+  signed int i; // edi@1
+  int v1; // esi@2
+  unsigned int v2; // ecx@4
+  int v3; // eax@4
+  int v4; // eax@6
+  unsigned __int16 *v5; // edx@6
+  int v6; // ecx@7
+  int v7; // esi@8
+
+  for ( i = 0; i < (signed int)pBspRenderer->uNumFaceIDs; ++i )
+  {
+    v1 = pBspRenderer->pFaceIDs[2 * i];
+    if ( v1 >= 0 )
+    {
+      if ( v1 < (signed int)pIndoor->uNumFaces )
+      {
+        v2 = pBspRenderer->pFaceIDs[2 * i];
+        pBLVRenderParams->field_7C = &pBspRenderer->field_FA8[pBspRenderer->pFaceIDs[2 * i + 1]].field_C;
+        v3 = sub_423B5D(v2);
+        if ( v3 )
+        {
+          if ( sub_424829(v3, &stru_F8A590, pBLVRenderParams->field_7C, v1) )
+          {
+            v4 = stru_F8A590._viewport_space_y;
+            v5 = pBLVRenderParams->pRenderTarget;
+            if ( stru_F8A590._viewport_space_y <= stru_F8A590._viewport_space_w )
+            {
+              v6 = 640 * stru_F8A590._viewport_space_y;
+              do
+              {
+                v5[v6 + stru_F8A590.array_18[v4]] = -1;
+                v7 = v6 + stru_F8A590.array_3D8[v4];
+                v6 += 640;
+                v5[v7] = -1;
+                ++v4;
+              }
+              while ( v4 <= stru_F8A590._viewport_space_w );
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+
+//----- (004AE5BA) --------------------------------------------------------
+Texture *BLVFace::GetTexture()
+{
+  unsigned int v1; // ecx@2
+
+  if ( uAttributes & 0x4000 )
+    v1 = pTextureFrameTable->GetFrameTexture(this->uBitmapID, pBLVRenderParams->field_0_timer_);
+  else
+    v1 = uBitmapID;
+  return (Texture *)(v1 != -1 ? (int)&pBitmaps_LOD->pTextures[v1] : 0);
+}
+
+
+//----- (00498B15) --------------------------------------------------------
+void IndoorLocation::Release()
+{
+  IndoorLocation *v1; // esi@1
+  char *v2; // ebp@1
+  void *v3; // ST00_4@1
+
+  v1 = this;
+  v2 = (char *)&this->ptr_0002B4_doors_ddata;
+  pAllocator->FreeChunk(this->ptr_0002B4_doors_ddata);
+  *(int *)v2 = 0;
+  pAllocator->FreeChunk(v1->ptr_0002B0_sector_rdata);
+  v1->ptr_0002B0_sector_rdata = 0;
+  pAllocator->FreeChunk(v1->ptr_0002B8_sector_lrdata);
+  v1->ptr_0002B8_sector_lrdata = 0;
+  pAllocator->FreeChunk(v1->ptr_2AC);
+  v1->ptr_2AC = 0;
+  pAllocator->FreeChunk(v1->pSpawnPoints);
+  v3 = v1->pVertices;
+  v1->pSpawnPoints = 0;
+  v1->uNumSectors = 0;
+  v1->uNumFaces = 0;
+  v1->uNumVertices = 0;
+  v1->uNumNodes = 0;
+  v1->uNumDoors = 0;
+  v1->uNumLights = 0;
+  pAllocator->FreeChunk(v3);
+  pAllocator->FreeChunk(v1->pFaces);
+  pAllocator->FreeChunk(v1->pFaceExtras);
+  pAllocator->FreeChunk(v1->pSectors);
+  pAllocator->FreeChunk(v1->pLights);
+  pAllocator->FreeChunk(v1->pDoors);
+  pAllocator->FreeChunk(v1->pNodes);
+  pAllocator->FreeChunk(v1->pMapOutlines);
+  v1->pVertices = 0;
+  v1->pFaces = 0;
+  v1->pFaceExtras = 0;
+  v1->pSectors = 0;
+  v1->pLights = 0;
+  v1->pDoors = 0;
+  v1->pNodes = 0;
+  v1->pMapOutlines = 0;
+  v1->bLoaded = 0;
+}
+
+//----- (00498C45) --------------------------------------------------------
+int IndoorLocation::Alloc()
+{
+  IndoorLocation *v1; // esi@1
+  void *v2; // eax@1
+  const void *v3; // ST3C_4@1
+  void *v4; // eax@1
+  const void *v5; // ST3C_4@1
+  void *v6; // eax@1
+  const void *v7; // ST3C_4@1
+  void *v8; // eax@1
+  const void *v9; // ST3C_4@1
+  void *v10; // eax@1
+  const void *v11; // ST3C_4@1
+  void *v12; // eax@1
+  const void *v13; // ST3C_4@1
+  void *v14; // eax@1
+  const void *v15; // ST3C_4@1
+  void *v16; // eax@1
+  void *v17; // ecx@1
+  signed int result; // eax@9
+
+  v1 = this;
+  v2 = pAllocator->AllocNamedChunk(this->pVertices, 0x15F90u, "L.V");
+  v3 = v1->pFaces;
+  v1->pVertices = (Vec3_short_ *)v2;
+  v4 = pAllocator->AllocNamedChunk(v3, 0xEA600u, "L.F");
+  v5 = v1->pFaceExtras;
+  v1->pFaces = (BLVFace *)v4;
+  v6 = pAllocator->AllocNamedChunk(v5, 0x2BF20u, "L.FX");
+  v7 = v1->pSectors;
+  v1->pFaceExtras = (BLVFaceExtra *)v6;
+  v8 = pAllocator->AllocNamedChunk(v7, 0xE800u, "L.R");
+  v9 = v1->pLights;
+  v1->pSectors = (BLVSector *)v8;
+  v10 = pAllocator->AllocNamedChunk(v9, 0x1900u, "L.L");
+  v11 = v1->pDoors;
+  v1->pLights = (BLVLightMM7 *)v10;
+  v12 = pAllocator->AllocNamedChunk(v11, 0x3E80u, "L.D");
+  v13 = v1->pNodes;
+  v1->pDoors = (BLVDoor *)v12;
+  v14 = pAllocator->AllocNamedChunk(v13, 0x9C40u, "L.BSP");
+  v15 = v1->pMapOutlines;
+  v1->pNodes = (BSPNode *)v14;
+  v16 = pAllocator->AllocNamedChunk(v15, 0x14824u, "L.Map");
+  v17 = v1->pVertices;
+  v1->pMapOutlines = (BLVMapOutlines *)v16;
+  if ( v17 && v1->pFaces && v1->pFaceExtras && v1->pSectors && v1->pLights && v1->pDoors && v1->pNodes && v16 )
+  {
+    memset(v17, 90000, 0);
+    memset(v1->pFaces, 960000, 0);
+    memset(v1->pFaceExtras, 180000, 0);
+    memset(v1->pSectors, 59392, 0);
+    memset(v1->pLights, 6400, 0);
+    memset(v1->pDoors, 16000, 0);
+    memset(v1->pNodes, 40000, 0);
+    memset(v1->pMapOutlines, 84004, 0);
+    result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+
+
+//----- (00444810) --------------------------------------------------------
+unsigned int IndoorLocation::GetLocationIndex(const char *Str1)
+{
+  const char *v1; // edi@1
+  signed int v2; // esi@1
+
+  v1 = Str1;
+  v2 = 0;
+  while ( _strcmpi(v1, _4E6BDC_loc_names[v2]) )
+  {
+    ++v2;
+    if ( v2 >= 11 )
+      return 0;
+  }
+  return v2 + 1;
+}
+
+
+
+//----- (004488F7) --------------------------------------------------------
+void IndoorLocation::ToggleLight(unsigned int uLightID, unsigned int bToggle)
+{
+  char *v2; // eax@4
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor && (signed int)uLightID <= pIndoor->uNumLights - 1 && (uLightID & 0x80000000u) == 0 )
+  {
+    v2 = (char *)&pIndoor->pLights[uLightID].uAtributes;
+    if ( bToggle )
+      *v2 &= 0xF7u;
+    else
+      *v2 |= 8u;
+    pParty->uFlags |= 2u;
+  }
+}
+
+
+//----- (00498E0A) --------------------------------------------------------
+bool IndoorLocation::Load(char *pFilename, int a3, size_t _i, char *pDest)
+{
+  /*unsigned int v5; // ebx@1
+  //IndoorLocation *v6; // esi@1
+  FILE *v7; // edi@3
+  bool result; // eax@3
+  char *v9; // ecx@4
+  void *v10; // eax@4
+  //unsigned __int8 v11; // zf@4
+  //unsigned __int8 v12; // sf@4
+  int v13; // eax@5
+  size_t v14; // ecx@6
+  char *v15; // ecx@6
+  int v16; // edx@6
+  size_t v17; // ecx@6
+  char *v18; // ecx@6
+  int v19; // edx@6
+  unsigned __int16 *v20; // edx@6
+  unsigned __int16 *v21; // edx@6
+  unsigned __int16 *v22; // edx@6
+  __int16 v23; // ax@10
+  char *v24; // ecx@10
+  __int16 v25; // cx@10
+  __int16 v26; // ax@11
+  char *v27; // ecx@11
+  unsigned __int16 v28; // ax@17
+  BLVFaceExtra *v29; // ecx@17
+  char *v30; // edx@17
+  int v31; // ecx@20
+  void *v32; // eax@25
+  int v33; // eax@26
+  unsigned __int16 *v34; // edx@27
+  size_t v35; // ecx@27
+  char *v36; // ecx@27
+  int v37; // edx@27
+  size_t v38; // ecx@27
+  char *v39; // ecx@27
+  int v40; // edx@27
+  unsigned __int16 *v41; // edx@27
+  unsigned __int16 *v42; // edx@27
+  unsigned __int16 *v43; // edx@27
+  unsigned __int16 *v44; // edx@27
+  size_t v45; // ecx@27
+  unsigned __int16 *v46; // edx@27
+  void *v47; // eax@28
+  BLVSector *v48; // eax@29
+  size_t v49; // ecx@29
+  unsigned __int16 *v50; // edx@31
+  void *v51; // eax@32
+  int v52; // eax@33
+  unsigned __int16 *v53; // edx@34
+  size_t v54; // ecx@34
+  char *v55; // ecx@34
+  int v56; // edx@34
+  size_t v57; // ecx@34
+  char *v58; // ecx@34
+  int v59; // edx@34
+  unsigned __int16 *v60; // edx@34
+  unsigned __int16 *v61; // edx@34
+  unsigned __int16 *v62; // edx@34
+  unsigned __int16 *v63; // edx@34
+  int v64; // ecx@34
+  BLVDoor *v65; // ecx@36
+  char *v66; // eax@37
+  int v67; // edx@38
+  int v68; // ecx@38
+  BLVFace *v69; // edx@38
+  int v70; // ecx@38
+  int v71; // edx@38
+  int v72; // eax@38
+  unsigned __int16 v73; // ax@42
+  char *v74; // ecx@42
+  LayingItem *v75; // ecx@44
+  size_t v76; // eax@45
+  int j; // edx@46
+  unsigned __int16 v78; // ax@50
+  void *v79; // eax@52
+  void **v80; // esi@52
+  unsigned int v145; // eax@103
+  void *v146; // eax@103
+  unsigned int v147; // ecx@103
+  int v148; // ebx@103
+  unsigned int *v149; // ecx@103*/
+  //size_t v150; // eax@103
+  //unsigned int v151; // ebx@109
+  //unsigned int v152; // ecx@116
+  //unsigned int v153; // eax@117
+  //size_t v154; // ebx@126
+  //unsigned int v155; // ebx@134
+  //size_t v156; // eax@140
+  //signed int v157; // ebx@142
+  //int v158; // ebx@148
+  //BLVFace *v159; // eax@149
+//  BLVFaceExtra *v160; // ecx@149
+  //BLVFaceExtra *v161; // ecx@149
+  //signed int v162; // ebx@154
+  //unsigned int v163; // ebx@157
+  //unsigned int v164; // ebx@157
+  //unsigned int v165; // edx@158
+  //char *v166; // ecx@158
+  //unsigned __int16 v167; // ax@161
+  //__int16 v168; // ax@165
+  //unsigned int v169; // ebx@168
+  //void *v170; // eax@168
+  //size_t v171; // ebx@168
+  //int v172; // edx@168
+  //BLVDoor *v173; // ecx@169
+  //int k; // eax@169
+  //BLVDoor *v175; // ecx@172
+  //int v176; // edx@172
+  //BLVDoor *v177; // ecx@172
+  //int v178; // edx@172
+  //BLVDoor *v179; // ecx@172
+  //int v180; // edx@172
+  //BLVDoor *v181; // ecx@172
+  //int v182; // edx@172
+  //BLVDoor *v183; // ecx@172
+  //int v184; // edx@172
+  //BLVDoor *v185; // ecx@172
+  //int v186; // edx@172
+  //BLVDoor *v187; // ecx@172
+  //int v188; // edx@172
+  //unsigned __int16 *v189; // ebx@172
+  //char *v190; // edx@173
+  //BLVDoor *v191; // ecx@174
+  //BLVDoor *l; // eax@175
+  //signed int v193; // ebx@176
+  //int v194; // ecx@176
+  //BLVFaceExtra *v195; // ecx@176
+  //BLVFace *v196; // ebx@178
+  //std::string v197; // [sp-18h] [bp-680h]@66
+  //void *v198; // [sp-14h] [bp-67Ch]@72
+  //size_t v199; // [sp-10h] [bp-678h]@72
+  //size_t v200; // [sp-Ch] [bp-674h]@72
+  //const char *v201; // [sp-8h] [bp-670h]@4
+  //int v202; // [sp-4h] [bp-66Ch]@4
+  char v203[875]; // [sp+Ch] [bp-65Ch]@130
+  char FileName[260]; // [sp+378h] [bp-2F0h]@1
+  //char DstBuf; // [sp+47Ch] [bp-1ECh]@4
+  __int32 Offset; // [sp+480h] [bp-1E8h]@4
+  __int32 v207; // [sp+48Ch] [bp-1DCh]@4
+  __int32 v208; // [sp+498h] [bp-1D0h]@4
+  __int32 v209; // [sp+4A4h] [bp-1C4h]@4
+  __int32 v210; // [sp+4B0h] [bp-1B8h]@4
+  __int32 v211; // [sp+4BCh] [bp-1ACh]@15
+  __int32 v212; // [sp+4C8h] [bp-1A0h]@15
+  __int32 v213; // [sp+4D4h] [bp-194h]@25
+  __int32 v214; // [sp+4E0h] [bp-188h]@25
+  __int32 v215; // [sp+4ECh] [bp-17Ch]@32
+  __int32 v216; // [sp+4F8h] [bp-170h]@32
+  __int32 v217; // [sp+504h] [bp-164h]@40
+  __int32 v218; // [sp+510h] [bp-158h]@40
+  __int32 v219; // [sp+51Ch] [bp-14Ch]@43
+  __int32 v220; // [sp+528h] [bp-140h]@43
+  __int32 v221; // [sp+534h] [bp-134h]@52
+  __int32 v222; // [sp+540h] [bp-128h]@52
+  __int32 v223; // [sp+54Ch] [bp-11Ch]@52
+  __int32 v224; // [sp+558h] [bp-110h]@52
+  __int32 v225; // [sp+564h] [bp-104h]@52
+  __int32 v226; // [sp+570h] [bp-F8h]@52
+  __int32 v227; // [sp+57Ch] [bp-ECh]@52
+  __int32 v228; // [sp+588h] [bp-E0h]@52
+  __int32 v229; // [sp+594h] [bp-D4h]@52
+  __int32 v230; // [sp+5A0h] [bp-C8h]@52
+  __int32 v231; // [sp+5ACh] [bp-BCh]@52
+  __int32 v232; // [sp+5B8h] [bp-B0h]@52
+  __int32 v233; // [sp+5C4h] [bp-A4h]@52
+  __int32 v234; // [sp+5D0h] [bp-98h]@52
+  //char pName[40]; // [sp+5FCh] [bp-6Ch]@42
+  //size_t pSource; // [sp+624h] [bp-44h]@67
+  //char Dst[12]; // [sp+628h] [bp-40h]@9
+  //char *v238; // [sp+634h] [bp-34h]@38
+  ODMHeader header; // [sp+638h] [bp-30h]@61
+  //void *ptr; // [sp+648h] [bp-20h]@66
+  //size_t Count; // [sp+64Ch] [bp-1Ch]@109
+  //int uSourceLen; // [sp+653h] [bp-15h]@66
+  FILE *File; // [sp+658h] [bp-10h]@56
+  //BLVSector *v244; // [sp+65Ch] [bp-Ch]@72
+  //int v245; // [sp+660h] [bp-8h]@72
+  //BLVFace *Src; // [sp+664h] [bp-4h]@73
+  signed int Argsa; // [sp+670h] [bp+8h]@4
+  signed int Argsb; // [sp+670h] [bp+8h]@7
+  signed int Argsc; // [sp+670h] [bp+8h]@15
+  signed int Argsd; // [sp+670h] [bp+8h]@18
+  int Argse; // [sp+670h] [bp+8h]@25
+  int Argsf; // [sp+670h] [bp+8h]@28
+  int Argsg; // [sp+670h] [bp+8h]@32
+  int Argsh; // [sp+670h] [bp+8h]@35
+  signed int Argsi; // [sp+670h] [bp+8h]@40
+  signed int Argsj; // [sp+670h] [bp+8h]@45
+  //int Argsk; // [sp+670h] [bp+8h]@143
+  //void *Argsl; // [sp+670h] [bp+8h]@155
+  //signed int Argsm; // [sp+670h] [bp+8h]@161
+  //signed int Argsn; // [sp+670h] [bp+8h]@175
+
+  //v5 = 0;
+  //v6 = this;
+  _6807E0_num_decorations_with_sounds_6807B8 = 0;
+
+  #pragma region "loading from txt"
+  /*sprintf(FileName, "levels\\%s", pFilename);
+  if ( GetFileAttributesA(FileName) != -1 )
+  {
+    Release();
+    if ( Alloc() )
+    {
+      v7 = fopen(FileName, "rb");
+      result = 1;
+      if ( !v7 )
+        return result;
+      v9 = pDest;
+      bLoaded = 1;
+      v202 = (int)v7;
+      v201 = (const char *)1;
+      *(int *)v9 = 1;
+      fread(&DstBuf, 0x180u, (size_t)v201, (FILE *)v202);
+      fseek(v7, Offset, 0);
+      fread(&blv, 0x88u, 1u, v7);
+      fseek(v7, v207, 0);
+      fread(&uNumVertices, 1u, 4u, v7);
+      fseek(v7, v208, 0);
+      fread(pVertices, 6u, uNumVertices, v7);
+      fseek(v7, v209, 0);
+      fread(&uNumFaces, 4u, 1u, v7);
+      fseek(v7, v210, 0);
+      fread(pFaces, 0x60u, uNumFaces, v7);
+      v10 = pAllocator->AllocNamedChunk(ptr_2AC, blv.uFaces_fdata_Size, "L.FData");
+      v202 = (int)v7;
+      ptr_2AC = (unsigned __int16 *)v10;
+      fread(v10, 1u, blv.uFaces_fdata_Size, (FILE *)v202);
+      v11 = uNumFaces == 0;
+      v12 = (uNumFaces & 0x80000000u) != 0;
+      pDest = 0;
+      Argsa = 0;
+      if ( !(v12 | v11) )
+      {
+        v13 = 0;
+        do
+        {
+          pFaces[v13].pVertexIDs = (unsigned __int16 *)&pDest[(unsigned int)ptr_2AC];
+          v14 = (size_t)&pFaces[v13];
+          i = v14;
+          v15 = &pDest[2 * *(char *)(v14 + 93) + 2];
+          v16 = (int)&v15[(unsigned int)ptr_2AC];
+          pDest = v15;
+          *(int *)(i + 52) = v16;
+          v17 = (size_t)&pFaces[v13];
+          i = v17;
+          v18 = &pDest[2 * *(char *)(v17 + 93) + 2];
+          v19 = (int)&v18[(unsigned int)ptr_2AC];
+          pDest = v18;
+          *(int *)(i + 56) = v19;
+          i = (size_t)&pFaces[v13];
+          v20 = ptr_2AC;
+          pDest += 2 * *(char *)(i + 93) + 2;
+          *(int *)(i + 60) = (int)(char *)v20 + (int)pDest;
+          i = (size_t)&pFaces[v13];
+          v21 = ptr_2AC;
+          pDest += 2 * *(char *)(i + 93) + 2;
+          *(int *)(i + 64) = (int)(char *)v21 + (int)pDest;
+          i = (size_t)&pFaces[v13];
+          ++v13;
+          v22 = ptr_2AC;
+          pDest += 2 * *(char *)(i + 93) + 2;
+          ++Argsa;
+          *(int *)(i + 68) = (int)(char *)v22 + (int)pDest;
+          pDest += 2 * *((char *)&pFaces[v13] - 3) + 2;
+        }
+        while ( Argsa < (signed int)uNumFaces );
+      }
+      Argsb = 0;
+      if ( (signed int)uNumFaces > 0 )
+      {
+        pDest = 0;
+        do
+        {
+          fread(Dst, 1u, 0xAu, v7);
+          if ( pDest[(unsigned int)pFaces + 45] & 0x40 )
+          {
+            v23 = pTextureFrameTable->FindTextureByName(Dst);
+            v24 = pDest;
+            *(short *)&pDest[(unsigned int)pFaces + 74] = v23;
+            v25 = *(short *)&v24[(unsigned int)pFaces + 74];
+            if ( v25 )
+            {
+              pTextureFrameTable->LoadAnimationSequenceAndPalettes(v25);
+            }
+            else
+            {
+              v26 = pBitmaps_LOD->LoadTexture(Dst);
+              v27 = pDest;
+              *(short *)&pDest[(unsigned int)pFaces + 74] = v26;
+              v27[(unsigned int)pFaces + 45] &= 0xBFu;
+            }
+          }
+          else
+          {
+            *(short *)&pDest[(unsigned int)pFaces + 74] = pBitmaps_LOD->LoadTexture(Dst);
+          }
+          ++Argsb;
+          pDest += 96;
+        }
+        while ( Argsb < (signed int)uNumFaces );
+      }
+      fseek(v7, v211, 0);
+      fread(&uNumFaceExtras, 4u, 1u, v7);
+      fseek(v7, v212, 0);
+      fread(pFaceExtras, 0x24u, uNumFaceExtras, v7);
+      Argsc = 0;
+      if ( (signed int)uNumFaceExtras > 0 )
+      {
+        pDest = 0;
+        do
+        {
+          fread(Dst, 1u, 0xAu, v7);
+          v28 = pBitmaps_LOD->LoadTexture(Dst);
+          v29 = pFaceExtras;
+          v30 = pDest;
+          ++Argsc;
+          pDest += 36;
+          *(unsigned __int16 *)((char *)&v29->uAdditionalBitmapID + (int)v30) = v28;
+        }
+        while ( Argsc < (signed int)uNumFaceExtras );
+      }
+      Argsd = 0;
+      if ( (signed int)uNumFaces > 0 )
+      {
+        pDest = 0;
+        do
+        {
+          v31 = (int)&pFaceExtras[*(short *)&pDest[(unsigned int)pFaces + 72]];
+          if ( *(short *)(v31 + 26) )
+          {
+            if ( ((BLVFaceExtra *)v31)->HasEventint() )
+              pDest[(unsigned int)pFaces + 46] |= 0x10u;
+            else
+              pDest[(unsigned int)pFaces + 46] &= 0xEFu;
+          }
+          ++Argsd;
+          pDest += 96;
+        }
+        while ( Argsd < (signed int)uNumFaces );
+      }
+      fseek(v7, v213, 0);
+      fread(&uNumSectors, 4u, 1u, v7);
+      fseek(v7, v214, 0);
+      fread(pSectors, 0x74u, uNumSectors, v7);
+      v32 = pAllocator->AllocNamedChunk(ptr_0002B0_sector_rdata, blv.uSector_rdata_Size, "L.RData");
+      v202 = (int)v7;
+      ptr_0002B0_sector_rdata = (unsigned __int16 *)v32;
+      fread(v32, 1u, blv.uSector_rdata_Size, (FILE *)v202);
+      v11 = uNumSectors == 0;
+      v12 = uNumSectors < 0;
+      pDest = 0;
+      Argse = 0;
+      if ( !(v12 | v11) )
+      {
+        v33 = 0;
+        do
+        {
+          pSectors[v33].pFloors = (unsigned __int16 *)&pDest[(unsigned int)ptr_0002B0_sector_rdata];
+          i = (size_t)&pSectors[v33];
+          v34 = ptr_0002B0_sector_rdata;
+          pDest += 2 * *(short *)(i + 4);
+          *(int *)(i + 16) = (int)(char *)v34 + (int)pDest;
+          v35 = (size_t)&pSectors[v33];
+          i = v35;
+          v36 = &pDest[2 * *(short *)(v35 + 12)];
+          v37 = (int)&v36[(unsigned int)ptr_0002B0_sector_rdata];
+          pDest = v36;
+          *(int *)(i + 24) = v37;
+          v38 = (size_t)&pSectors[v33];
+          i = v38;
+          v39 = &pDest[2 * *(short *)(v38 + 20)];
+          v40 = (int)&v39[(unsigned int)ptr_0002B0_sector_rdata];
+          pDest = v39;
+          *(int *)(i + 32) = v40;
+          i = (size_t)&pSectors[v33];
+          v41 = ptr_0002B0_sector_rdata;
+          pDest += 2 * *(short *)(i + 28);
+          *(int *)(i + 40) = (int)(char *)v41 + (int)pDest;
+          i = (size_t)&pSectors[v33];
+          v42 = ptr_0002B0_sector_rdata;
+          pDest += 2 * *(short *)(i + 36);
+          *(int *)(i + 48) = (int)(char *)v42 + (int)pDest;
+          i = (size_t)&pSectors[v33];
+          v43 = ptr_0002B0_sector_rdata;
+          pDest += 2 * *(short *)(i + 44);
+          *(int *)(i + 64) = (int)(char *)v43 + (int)pDest;
+          i = (size_t)&pSectors[v33];
+          v44 = ptr_0002B0_sector_rdata;
+          pDest += 2 * *(short *)(i + 60);
+          *(int *)(i + 72) = (int)(char *)v44 + (int)pDest;
+          v45 = (size_t)&pSectors[v33];
+          ++v33;
+          i = v45;
+          v46 = ptr_0002B0_sector_rdata;
+          pDest += 2 * *(short *)(v45 + 68);
+          ++Argse;
+          *(int *)(v45 + 80) = (int)(char *)v46 + (int)pDest;
+          pDest += 2 * *((short *)&pSectors[v33] - 20);
+        }
+        while ( Argse < uNumSectors );
+      }
+      v47 = pAllocator->AllocNamedChunk(
+              ptr_0002B8_sector_lrdata,
+              blv.uSector_lrdata_Size,
+              "L.RLData");
+      v202 = (int)v7;
+      ptr_0002B8_sector_lrdata = (unsigned __int16 *)v47;
+      fread(v47, 1u, blv.uSector_lrdata_Size, (FILE *)v202);
+      v11 = uNumSectors == 0;
+      v12 = uNumSectors < 0;
+      pDest = 0;
+      Argsf = 0;
+      if ( !(v12 | v11) )
+      {
+        v48 = pSectors;
+        v49 = 0;
+        for ( i = 0; ; v49 = i )
+        {
+          v50 = ptr_0002B8_sector_lrdata;
+          i += 116;
+          ++Argsf;
+          *(BLVLightMM7 **)((char *)&v48->pLights + v49) = (BLVLightMM7 *)((char *)v50 + (int)pDest);
+          v48 = pSectors;
+          pDest += 2 * *(__int16 *)((char *)&v48->uNumLights + v49);
+          if ( Argsf >= uNumSectors )
+            break;
+        }
+      }
+      fseek(v7, v215, 0);
+      fread(&uNumDoors, 4u, 1u, v7);
+      fseek(v7, v216, 0);
+      fread(pDoors, 0x50u, 0xC8u, v7);
+      v51 = pAllocator->AllocNamedChunk(ptr_0002B4_doors_ddata, blv.uDoors_ddata_Size, "L.DData");
+      v202 = (int)v7;
+      ptr_0002B4_doors_ddata = (unsigned __int16 *)v51;
+      fread(v51, 1u, blv.uDoors_ddata_Size, (FILE *)v202);
+      v11 = uNumDoors == 0;
+      v12 = uNumDoors < 0;
+      pDest = 0;
+      Argsg = 0;
+      if ( !(v12 | v11) )
+      {
+        v52 = 0;
+        do
+        {
+          pDoors[v52].pVertexIDs = (unsigned __int16 *)&pDest[(unsigned int)ptr_0002B4_doors_ddata];
+          i = (size_t)&pDoors[v52];
+          v53 = ptr_0002B4_doors_ddata;
+          pDest += 2 * *(short *)(i + 68);
+          *(int *)(i + 40) = (int)(char *)v53 + (int)pDest;
+          v54 = (size_t)&pDoors[v52];
+          i = v54;
+          v55 = &pDest[2 * *(short *)(v54 + 70)];
+          v56 = (int)&v55[(unsigned int)ptr_0002B4_doors_ddata];
+          pDest = v55;
+          *(int *)(i + 44) = v56;
+          v57 = (size_t)&pDoors[v52];
+          i = v57;
+          v58 = &pDest[2 * *(short *)(v57 + 72)];
+          v59 = (int)&v58[(unsigned int)ptr_0002B4_doors_ddata];
+          pDest = v58;
+          *(int *)(i + 48) = v59;
+          i = (size_t)&pDoors[v52];
+          v60 = ptr_0002B4_doors_ddata;
+          pDest += 2 * *(short *)(i + 70);
+          *(int *)(i + 52) = (int)(char *)v60 + (int)pDest;
+          i = (size_t)&pDoors[v52];
+          v61 = ptr_0002B4_doors_ddata;
+          pDest += 2 * *(short *)(i + 70);
+          *(int *)(i + 56) = (int)(char *)v61 + (int)pDest;
+          i = (size_t)&pDoors[v52];
+          v62 = ptr_0002B4_doors_ddata;
+          pDest += 2 * *(short *)(i + 74);
+          *(int *)(i + 60) = (int)(char *)v62 + (int)pDest;
+          i = (size_t)&pDoors[v52];
+          v63 = ptr_0002B4_doors_ddata;
+          pDest += 2 * *(short *)(i + 74);
+          *(int *)(i + 64) = (int)(char *)v63 + (int)pDest;
+          ++Argsg;
+          v64 = pDoors[v52].uNumOffsets;
+          ++v52;
+          pDest += 2 * v64;
+        }
+        while ( Argsg < uNumDoors );
+      }
+      Argsh = 0;
+      if ( uNumDoors > 0 )
+      {
+        v65 = pDoors;
+        pDest = 0;
+        do
+        {
+          i = 0;
+          v66 = &pDest[(int)v65];
+          if ( *(short *)&pDest[(int)v65 + 70] > 0 )
+          {
+            do
+            {
+              v67 = *((int *)v66 + 10);
+              a3 = 2 * i;
+              v68 = *(short *)(v67 + 2 * i);
+              v69 = pFaces;
+              ++i;
+              v70 = (int)&pFaceExtras[v69[v68].uFaceExtraID];
+              v71 = *((int *)v66 + 12);
+              v72 = a3;
+              v238 = (char *)v70;
+              *(short *)(a3 + v71) = *(short *)(v70 + 20);
+              *(__int16 *)(*(char **)((char *)&pDoors->pDeltaVs + (unsigned int)pDest) + v72) = *((short *)v238 + 11);
+              v65 = pDoors;
+              v66 = &pDest[(int)v65];
+            }
+            while ( (signed int)i < *(short *)&pDest[(int)v65 + 70] );
+          }
+          ++Argsh;
+          pDest += 80;
+        }
+        while ( Argsh < uNumDoors );
+      }
+      fseek(v7, v217, 0);
+      fread(&uNumLevelDecorations, 4u, 1u, v7);
+      fseek(v7, v218, 0);
+      fread(pLevelDecorations, 0x20u, uNumLevelDecorations, v7);
+      Argsi = 0;
+      if ( (signed int)uNumLevelDecorations > 0 )
+      {
+        pDest = (char *)pLevelDecorations;
+        do
+        {
+          fread(pName, 1u, 0x20u, v7);
+          v73 = pDecorationList->GetDecorIdByName(pName);
+          v74 = pDest;
+          ++Argsi;
+          pDest += 32;
+          *(short *)v74 = v73;
+        }
+        while ( Argsi < (signed int)uNumLevelDecorations );
+      }
+      fseek(v7, v219, 0);
+      fread(&uNumLayingItems, 4u, 1u, v7);
+      fseek(v7, v220, 0);
+      fread(pLayingItems, 0x70u, uNumLayingItems, v7);
+      if ( (signed int)uNumLayingItems > 0 )
+      {
+        v75 = pLayingItems;
+        pDest = (char *)uNumLayingItems;
+        do
+        {
+          Argsj = 0;
+          v76 = 48 * v75->stru_24.uItemID;
+          v11 = pObjectList->uNumObjects == 0;
+          v12 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+          LOWORD(v76) = *(unsigned __int16 *)((char *)&pItemsTable->pItems[0].uSpriteID + v76);
+          i = v76;
+          v75->uItemType = v76;
+          if ( v12 | v11 )
+          {
+LABEL_50:
+            v78 = 0;
+          }
+          else
+          {
+            for ( j = (int)&pObjectList->pObjects->uObjectID; (short)v76 != *(short *)j; j = a3 )
+            {
+              ++Argsj;
+              a3 = j + 56;
+              if ( Argsj >= (signed int)pObjectList->uNumObjects )
+                goto LABEL_50;
+              LOWORD(v76) = i;
+            }
+            v78 = Argsj;
+          }
+          v75->uObjectDescID = v78;
+          ++v75;
+          --pDest;
+        }
+        while ( pDest );
+      }
+      fseek(v7, v221, 0);
+      fread(&uNumActors, 4u, 1u, v7);
+      fseek(v7, v222, 0);
+      fread(pActors, 0x344u, uNumActors, v7);
+      fseek(v7, v228, 0);
+      fread(&uNumChests, 4u, 1u, v7);
+      fseek(v7, v229, 0);
+      fread(pChests, 0x14CCu, uNumChests, v7);
+      fseek(v7, v224, 0);
+      fread(&uNumLights, 4u, 1u, v7);
+      fseek(v7, v225, 0);
+      fread(pLights, 0x10u, uNumLights, v7);
+      fseek(v7, v226, 0);
+      fread(&uNumNodes, 4u, 1u, v7);
+      fseek(v7, v227, 0);
+      fread(pNodes, 8u, uNumNodes, v7);
+      fseek(v7, v230, 0);
+      fread(&uNumSpawnPoints, 4u, 1u, v7);
+      v79 = pAllocator->AllocNamedChunk(pSpawnPoints, 24 * uNumSpawnPoints, "Spawn");
+      v202 = 0;
+      pSpawnPoints = (SpawnPointMM7 *)v79;
+      fseek(v7, v231, v202);
+      fread(pSpawnPoints, 0x18u, uNumSpawnPoints, v7);
+      fseek(v7, v232, 0);
+      fread(&dlv, 0x28u, 1u, v7);
+      fseek(v7, v233, 0);
+      fread(&stru_5E4C90, 1u, 0xC8u, v7);
+      fseek(v7, v234, 0);
+      fread(&uLastVisitDay, 1u, 0x38u, v7);
+      fseek(v7, v223, 0);
+      v80 = (void **)&pMapOutlines;
+      fread(*v80, 4u, 1u, v7);
+      fread((char *)*v80 + 4, 0xCu, *(int *)*v80, v7);
+      fclose(v7);
+      goto LABEL_179;
+    }
+    return 4;
+  }*/
+  #pragma endregion
+
+  if (bLoaded)
+  {
+    Log::Warning(L"BLV is already loaded");
+    return 3;
+  }
+
+  if ( !pGames_LOD->DoesContainerExist(pFilename) )
+    Abortf("Unable to find %s in Games.LOD", pFilename);
+
+  //v238 = pFilename - 4;
+  //v81 = strlen(pFilename);
+  strcpy(this->pFilename, pFilename);
+  strcpy(&pFilename[strlen(pFilename) - 4], ".blv");
+  File = pGames_LOD->FindContainer(pFilename, 1);
+  //File = v82;
+
+  Release();
+  if ( !Alloc() )
+    return 4;
+  
+  header.uVersion = 91969;
+  header.pMagic[0] = 'm';
+  header.pMagic[1] = 'v';
+  header.pMagic[2] = 'i';
+  header.pMagic[3] = 'i';
+  header.uCompressedSize = 0;
+  header.uDecompressedSize = 0;
+  fread(&header, sizeof(ODMHeader), 1u, File);
+  if (header.uVersion != 91969 ||
+      header.pMagic[0] != 'm'  ||
+      header.pMagic[1] != 'v'  ||
+      header.pMagic[2] != 'i'  ||
+      header.pMagic[3] != 'i' )
+  {
+    MessageBoxW(nullptr, L"Can't load file!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Polydata.cpp:792", 0);
+  }
+  //v83 = header.uCompressedSize;
+  //pSource = header.uDecompressedSize;
+  //v84 = malloc(header.uDecompressedSize);
+  //v85 = v84;
+  //ptr = v84;
+  auto pRawBLV = malloc(header.uDecompressedSize);
+  memset(pRawBLV, 0, header.uDecompressedSize);
+
+  if (header.uCompressedSize == header.uDecompressedSize)
+    fread(pRawBLV, header.uDecompressedSize, 1, File);
+  else if (header.uCompressedSize < header.uDecompressedSize)
+  {
+    auto pTmpMem = malloc(header.uCompressedSize);
+    {
+      fread(pTmpMem, header.uCompressedSize, 1, File);
+
+      uint uDecompressedSize = header.uDecompressedSize;
+      zlib::MemUnzip(pRawBLV, &uDecompressedSize, pTmpMem, header.uCompressedSize);
+
+      if (uDecompressedSize != header.uDecompressedSize)
+        Log::Warning(L"uDecompressedSize != header.uDecompressedSize in BLV");
+    }
+    free(pTmpMem);
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"Can't load file!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Polydata.cpp:803", 0);
+    return 0;
+  }
+
+  assert(sizeof(Vec3_short_) == 6);
+  assert(sizeof(BLVFace) == 96);
+  assert(sizeof(BLVFaceExtra) == 36);
+  assert(sizeof(BLVSector) == 116);
+  assert(sizeof(LevelDecoration) == 32);
+  assert(sizeof(BLVLightMM7) == 16);
+  assert(sizeof(BSPNode) == 8);
+  assert(sizeof(SpawnPointMM7) == 24);
+  assert(sizeof(DDM_DLV_Header) == 40);
+  assert(sizeof(Actor) == 836);
+  assert(sizeof(LayingItem) == 112);
+  assert(sizeof(Chest) == 5324);
+  assert(sizeof(stru123) == 0xC8);
+  assert(sizeof(BLVMapOutline) == 12);
+  
+  bLoaded = true;
+
+  auto pData = (char *)pRawBLV;
+  
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&blv, pData, 136);
+  memcpy(&uNumVertices, pData += 136, 4);
+  memcpy(pVertices, pData += 4, uNumVertices * sizeof(Vec3_short_));
+  
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumFaces, pData += uNumVertices * sizeof(Vec3_short_), 4);
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(pFaces, pData += 4, uNumFaces * sizeof (BLVFace));
+  ptr_2AC = (unsigned __int16 *)pAllocator->AllocNamedChunk(ptr_2AC, blv.uFaces_fdata_Size, "L.FData");
+
+  memcpy(ptr_2AC, pData += uNumFaces * sizeof (BLVFace), blv.uFaces_fdata_Size);
+
+  for (uint i = 0, j = 0; i < uNumFaces; ++i)
+  {
+    auto pFace = pFaces + i;
+
+    pFace->pVertexIDs = ptr_2AC + j;
+    
+    j += pFace->uNumVertices + 1;
+    pFace->pXInterceptDisplacements = ptr_2AC + j;
+
+    j += pFace->uNumVertices + 1;
+    pFace->pYInterceptDisplacements = ptr_2AC + j;
+
+    j += pFace->uNumVertices + 1;
+    pFace->pZInterceptDisplacements = ptr_2AC + j;
+
+    j += pFace->uNumVertices + 1;
+    pFace->pVertexUIDs = (__int16 *)(ptr_2AC + j);
+
+    j += pFace->uNumVertices + 1;
+    pFace->pVertexVIDs = (__int16 *)(ptr_2AC + j);
+
+    j += pFace->uNumVertices + 1;
+      /*v93 = &pFaces[v92];
+      Src = v93;
+      v94 = (BLVSector *)((char *)v244 + 2 * v93->uNumVertices + 2);
+      v95 = (unsigned __int16 *)((char *)v94 + (unsigned int)ptr_2AC);
+      v244 = v94;
+      Src->pXInterceptDisplacements = v95;
+      v96 = (int)&pFaces[v92];
+      Src = (BLVFace *)v96;
+      v97 = (BLVSector *)((char *)v244 + 2 * *(char *)(v96 + 93) + 2);
+      v98 = (unsigned __int16 *)((char *)v97 + (unsigned int)ptr_2AC);
+      v244 = v97;
+      Src->pYInterceptDisplacements = v98;
+      Src = &pFaces[v92];
+      v99 = ptr_2AC;
+      v244 = (BLVSector *)((char *)v244 + 2 * Src->uNumVertices + 2);
+      Src->pZInterceptDisplacements = (unsigned __int16 *)((char *)v99 + (int)v244);
+      Src = &pFaces[v92];
+      v100 = ptr_2AC;
+      v244 = (BLVSector *)((char *)v244 + 2 * Src->uNumVertices + 2);
+      Src->pVertexUIDs = (unsigned __int16 *)((char *)v100 + (int)v244);
+      Src = &pFaces[v92];
+      ++v92;
+      v101 = ptr_2AC;
+      v244 = (BLVSector *)((char *)v244 + 2 * Src->uNumVertices + 2);
+      ++v245;
+      Src->pVertexVIDs = (unsigned __int16 *)((char *)v101 + (int)v244);
+      v244 = (BLVSector *)((char *)v244 + 2 * *((char *)&pFaces[v92] - 3) + 2);*/
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  pData += blv.uFaces_fdata_Size;
+
+  for (uint i = 0; i < uNumFaces; ++i)
+  {
+    auto pFace = pFaces + i;
+
+    char pTexName[16];
+    strncpy(pTexName, pData, 10);
+    pData += 10;
+
+    if (pFace->uAttributes & 0x4000)
+    {
+      pFace->uBitmapID = pTextureFrameTable->FindTextureByName(pTexName);
+      if (pFace->uBitmapID)
+        pTextureFrameTable->LoadAnimationSequenceAndPalettes(pFace->uBitmapID);
+      else
+      {
+        pFace->uBitmapID = pBitmaps_LOD->LoadTexture(pTexName);
+        pFace->uAttributes &= ~0x4000;
+      }
+    }
+    else
+      pFace->uBitmapID = pBitmaps_LOD->LoadTexture(pTexName);
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumFaceExtras, pData, 4u);
+  memcpy(pFaceExtras, pData += 4, uNumFaceExtras * sizeof(BLVFaceExtra));
+  pData += uNumFaceExtras * sizeof(BLVFaceExtra);
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  //v108 = (char *)v107 + 36 * uNumFaceExtras;
+  //v245 = 0;
+  //*(int *)((char *)&uSourceLen + 1) = 0;
+  for (uint i = 0; i < uNumFaceExtras; ++i)
+  {
+    char pTexName[32];
+    strncpy(pTexName, pData, 10);
+    pData += 10;
+
+    if (!strcmp(pTexName, ""))
+      pFaceExtras[i].uAdditionalBitmapID = -1;
+    else
+      pFaceExtras[i].uAdditionalBitmapID = pBitmaps_LOD->LoadTexture(pTexName);
+  }
+
+
+  for (uint i = 0; i < uNumFaces; ++i)
+  {
+    auto pFace = pFaces + i;
+    auto pFaceExtra = pFaceExtras + pFace->uFaceExtraID;
+
+    if (pFaceExtra->uEventID)
+    {
+      if (pFaceExtra->HasEventint())
+        pFace->uAttributes |= 0x100000;
+      else
+        pFace->uAttributes &= ~0x100000;
+    }
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumSectors, pData, 4);
+  memcpy(pSectors, pData + 4, uNumSectors * sizeof(BLVSector));
+  pData += 4 + uNumSectors * sizeof(BLVSector);
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  ptr_0002B0_sector_rdata = (unsigned short *)pAllocator->AllocNamedChunk(ptr_0002B0_sector_rdata, blv.uSector_rdata_Size, "L.RData");
+  memcpy(ptr_0002B0_sector_rdata, pData, blv.uSector_rdata_Size);
+  pData += blv.uSector_rdata_Size;
+
+  for (uint i = 0, j = 0; i < uNumSectors; ++i)
+  {
+    auto pSector = pSectors + i;
+
+    pSector->pFloors = ptr_0002B0_sector_rdata + j;
+    j += pSector->uNumFloors;
+
+    pSector->pWalls = ptr_0002B0_sector_rdata + j;
+    j += pSector->field_C;
+
+    pSector->pCeilings = ptr_0002B0_sector_rdata + j;
+    j += pSector->field_14;
+
+    pSector->pFluids = ptr_0002B0_sector_rdata + j;
+    j += pSector->field_1C;
+
+    pSector->pPortals = ptr_0002B0_sector_rdata + j;
+    j += pSector->uNumPortals;
+
+    pSector->pFaceIDs = ptr_0002B0_sector_rdata + j;
+    j += pSector->field_2C;
+
+    pSector->pCogs = ptr_0002B0_sector_rdata + j;
+    j += pSector->field_3C;
+
+    pSector->pDecorationIDs = ptr_0002B0_sector_rdata + j;
+    j += pSector->uNumDecorations;
+
+    pSector->pMarkers = ptr_0002B0_sector_rdata + j;
+    j += pSector->field_4C;
+
+
+    //do
+    //{
+      /*pSectors[v118].pFloors = (unsigned __int16 *)((char *)Src + (unsigned int)ptr_0002B0_sector_rdata);
+      v244 = &pSectors[v118];
+      v119 = ptr_0002B0_sector_rdata;
+      Src = (BLVFace *)((char *)Src + 2 * v244->field_4);
+      v244->pWalls = (unsigned __int16 *)((char *)v119 + (int)Src);
+      v120 = (int)&pSectors[v118];
+      v244 = (BLVSector *)v120;
+      v121 = (BLVFace *)((char *)Src + 2 * *(short *)(v120 + 12));
+      v122 = (unsigned __int16 *)((char *)v121 + (unsigned int)ptr_0002B0_sector_rdata);
+      Src = v121;
+      v244->pCeilings = v122;
+      v123 = (int)&pSectors[v118];
+      v244 = (BLVSector *)v123;
+      v124 = (BLVFace *)((char *)Src + 2 * *(short *)(v123 + 20));
+      v125 = (unsigned __int16 *)((char *)v124 + (unsigned int)ptr_0002B0_sector_rdata);
+      Src = v124;
+      v244->pFluids = v125;
+      v244 = &pSectors[v118];
+      v126 = ptr_0002B0_sector_rdata;
+      Src = (BLVFace *)((char *)Src + 2 * v244->field_1C);
+      v244->pPortals = (unsigned __int16 *)((char *)v126 + (int)Src);
+      v244 = &pSectors[v118];
+      v127 = ptr_0002B0_sector_rdata;
+      Src = (BLVFace *)((char *)Src + 2 * v244->uNumPortals);
+      v244->pFaceIDs = (unsigned __int16 *)((char *)v127 + (int)Src);
+      v244 = &pSectors[v118];
+      v128 = ptr_0002B0_sector_rdata;
+      Src = (BLVFace *)((char *)Src + 2 * v244->field_2C);
+      v244->pCogs = (unsigned __int16 *)((char *)v128 + (int)Src);
+      v244 = &pSectors[v118];
+      v129 = ptr_0002B0_sector_rdata;
+      Src = (BLVFace *)((char *)Src + 2 * v244->field_3C);
+      v244->pDecorationIDs = (unsigned __int16 *)((char *)v129 + (int)Src);
+      v130 = (int)&pSectors[v118];
+      ++v118;
+      v244 = (BLVSector *)v130;
+      v131 = ptr_0002B0_sector_rdata;
+      Src = (BLVFace *)((char *)Src + 2 * *(short *)(v130 + 68));
+      ++v245;
+      *(int *)(v130 + 80) = (int)(char *)v131 + (int)Src;
+      Src = (BLVFace *)((char *)Src + 2 * *((short *)&pSectors[v118] - 20));*/
+    //}
+    //while ( v245 < uNumSectors );
+  }
+
+  ptr_0002B8_sector_lrdata = (unsigned __int16 *)pAllocator->AllocNamedChunk(ptr_0002B8_sector_lrdata, blv.uSector_lrdata_Size, "L.RLData");
+  memcpy(ptr_0002B8_sector_lrdata, pData, blv.uSector_lrdata_Size);
+  pData += blv.uSector_lrdata_Size;
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  for (uint i = 0, j = 0; i < uNumSectors; ++i)
+  {
+    pSectors->pLights = (unsigned __int16 *)(ptr_0002B8_sector_lrdata + j);
+    j += pSectors->uNumLights;
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumDoors, pData, 4);
+  pData += 4;
+
+  pGameLoadingUI_ProgressBar->Progress();
+  pGameLoadingUI_ProgressBar->Progress();
+  
+  memcpy(&uNumLevelDecorations, pData, 4);
+  memcpy(pLevelDecorations, pData + 4, uNumLevelDecorations * sizeof(LevelDecoration));
+  pData += 4 + uNumLevelDecorations * sizeof(LevelDecoration);
+
+  for (uint i = 0; i < uNumLevelDecorations; ++i)
+  {
+    pLevelDecorations[i].uDecorationDescID = pDecorationList->GetDecorIdByName(pData);
+
+    pData += 32;
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumLights, pData, 4);
+  memcpy(pLights, pData + 4, uNumLights * sizeof(BLVLightMM7));
+  pData += 4 + uNumLights * sizeof(BLVLightMM7);
+
+  pGameLoadingUI_ProgressBar->Progress();
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumNodes, pData, 4);
+  memcpy(pNodes, pData + 4, uNumNodes * sizeof(BSPNode));
+  pData += 4 + uNumNodes * sizeof(BSPNode);
+  
+  pGameLoadingUI_ProgressBar->Progress();
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumSpawnPoints, pData, 4);
+  pSpawnPoints = (SpawnPointMM7 *)pAllocator->AllocNamedChunk(pSpawnPoints, uNumSpawnPoints * sizeof(SpawnPointMM7), "Spawn");
+  memcpy(pSpawnPoints, pData + 4, uNumSpawnPoints * sizeof(SpawnPointMM7));
+  pData += 4 + uNumSpawnPoints * sizeof(SpawnPointMM7);
+  
+  pGameLoadingUI_ProgressBar->Progress();
+  pGameLoadingUI_ProgressBar->Progress();
+
+  //v201 = (const char *)v148;
+  //v200 = (size_t)pMapOutlines;
+  memcpy(&pMapOutlines->uNumOutlines, pData, 4);
+  memcpy(pMapOutlines->pOutlines, pData + 4, pMapOutlines->uNumOutlines * sizeof(BLVMapOutline));
+  //v149 = pMapOutlines;
+  //v199 = 12 * *v149;
+  //memcpy(v149 + 1, (const void *)(v148 + 4), v199);
+  free(pRawBLV);
+  pRawBLV = nullptr;
+
+  void *pRawDLV = nullptr;
+  strcpy(&pFilename[strlen(pFilename) - 4], ".dlv");
+  File = pNew_LOD->FindContainer(pFilename, 1);
+  fread(&header, 0x10u, 1u, File);//(FILE *)v245);
+  bool _v244 = false;
+  if (header.uVersion != 91969 ||
+      header.pMagic[0] != 'm'  ||
+      header.pMagic[1] != 'v'  ||
+      header.pMagic[2] != 'i'  ||
+      header.pMagic[3] != 'i' )
+  {
+    MessageBoxW(nullptr, L"Can't load file!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Polydata.cpp:1090", 0);
+    _v244 = true;
+  }
+  else
+  {
+    pRawDLV = malloc(header.uDecompressedSize);
+    if (header.uCompressedSize == header.uDecompressedSize)
+      fread(pRawDLV, 1, header.uCompressedSize, File);
+    else if (header.uCompressedSize < header.uDecompressedSize)
+    {
+      auto pTmpMem = malloc(header.uCompressedSize);
+      {
+        fread(pTmpMem, header.uCompressedSize, 1, File);
+
+        uint uDecompressedSize = header.uDecompressedSize;
+        zlib::MemUnzip(pRawDLV, &uDecompressedSize, pTmpMem, header.uCompressedSize);
+
+        if (uDecompressedSize != header.uDecompressedSize)
+          Log::Warning(L"uDecompressedSize != header.uDecompressedSize in DLV");
+      }
+      free(pTmpMem);
+    }
+    else
+      MessageBoxW(nullptr, L"Can't load file!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Polydata.cpp:1108", 0);
+
+    pData = (char *)pRawDLV;
+  }
+  
+  memcpy(&dlv, pData, 40);
+  pData += 40;
+
+  //v152 = dlv.uNumFacesInBModels;
+  if (dlv.uNumFacesInBModels)
+  {
+    //v153 = dlv.uNumDecorations;
+    if (dlv.uNumDecorations)
+    {
+      if (dlv.uNumFacesInBModels != uNumFaces ||
+          dlv.uNumDecorations != uNumLevelDecorations)
+        _v244 = true;
+    }
+  }
+
+  if (dword_6BE364_game_settings_1 & 0x2000 )
+    _i = 29030400;
+  bool _a = false;
+  if ( a3 - dlv.uLastRepawnDay >= _i && strcmpi(pCurrentMapName, "d29.dlv") )
+    _a = true;
+
+  //v154 = 875;
+  if (_v244)
+  {
+    memset(v203, 0, 0x36B);
+    goto LABEL_132;
+  }
+  if (_a || !dlv.uLastRepawnDay )
+  {
+    memcpy(v203, pData, 0x36B);
+LABEL_132:
+    free(File);
+    dlv.uLastRepawnDay = a3;
+    if (_v244)
+      ++dlv.uNumRespawns;
+    //v201 = pFilename;
+    *(int *)pDest = 1;
+    File = pGames_LOD->FindContainer(pFilename, 0);
+    fread(&header, 0x10u, 1u, File);
+    auto v155 = header.uCompressedSize;
+    auto Count = header.uDecompressedSize;
+    auto Src = (BLVFace *)malloc(header.uDecompressedSize);
+    File = (FILE *)Src;
+    if ( v155 <= Count )
+    {
+      if ( v155 == Count )
+      {
+        fread(Src, 1u, Count, File);
+      }
+      else
+      {
+        auto _uSourceLen = malloc(v155);
+        fread(_uSourceLen, v155, 1u, File);
+        zlib::MemUnzip(Src, &Count, _uSourceLen, v155);
+        free(_uSourceLen);
+      }
+    }
+    else
+    {
+    MessageBoxW(nullptr, L"Can't load file!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Polydata.cpp:1195", 0);
+    }
+    pData = ((char *)Src + 40);
+    //v154 = 875;
+    goto LABEL_140;
+  }
+  *(int *)pDest = 0;
+LABEL_140:
+  //v202 = (int)".blv";
+  //v156 = strlen(pFilename);
+  strcpy(&pFilename[strlen(pFilename) - 4], ".blv");
+  memcpy(_visible_outlines, pData, 875);
+  pData += 875;
+
+  if ( *(int *)pDest )
+    memcpy(_visible_outlines, v203, 875);
+
+  for (uint i = 0; i < pMapOutlines->uNumOutlines; ++i)
+  {
+    auto pVertex = pMapOutlines->pOutlines + i;
+    if ((unsigned __int8)(1 << (7 - i % 8)) & _visible_outlines[i / 8])
+      pVertex->uFlags |= 1;
+  }
+
+
+  for (uint i = 0; i < uNumFaces; ++i)
+  {
+    auto pFace = pFaces + i;
+    auto pFaceExtra = pFaceExtras + pFace->uFaceExtraID;
+
+    memcpy(&pFace->uAttributes, pData, 4);
+    pData += 4;
+
+    if (pFaceExtra->uEventID)
+    {
+      if (pFaceExtra->HasEventint())
+        pFace->uAttributes |= 0x100000;
+      else
+        pFace->uAttributes &= ~0x100000;
+    }
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  for (uint i = 0; i < uNumLevelDecorations; ++i)
+  {
+    memcpy(&pLevelDecorations[i].field_2, pData, 2);
+    pData += 2;
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumActors, pData, 4);
+  memcpy(pActors, pData + 4, uNumActors * sizeof(Actor));
+  pData += 4 + uNumActors * sizeof(Actor);
+
+  pGameLoadingUI_ProgressBar->Progress();
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumLayingItems, pData, 4);
+  memcpy(pLayingItems, pData + 4, uNumLayingItems * sizeof(LayingItem));
+  pData += 4 + uNumLayingItems * sizeof(LayingItem);
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  for (uint i = 0; i < uNumLayingItems; ++i)
+  {
+    auto pItem = pLayingItems + i;
+ 
+    if (pItem->stru_24.uItemID && !(pItem->uAttributes & 0x0100))
+    {
+      pItem->uItemType = pItemsTable->pItems[pItem->stru_24.uItemID - 1].uSpriteID;
+
+      uint uObjectID = 0;
+      for (uint j = 0; j < pObjectList->uNumObjects; ++j)
+        if (pItem->uItemType == pObjectList->pObjects[j].uObjectID)
+        {
+          pItem->uObjectDescID = j;
+          break;
+        }
+    }
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumChests, pData, 4);
+  memcpy(pChests, pData + 4, uNumChests * sizeof(Chest));
+  pData += 4 + uNumChests * sizeof(Chest);
+
+  pGameLoadingUI_ProgressBar->Progress();
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(pDoors, pData, 0x3E80);
+  pData += 0x3E80;
+
+  //v201 = (const char *)blv.uDoors_ddata_Size;
+  //v200 = (size_t)ptr_0002B4_doors_ddata;
+  //v170 = pAllocator->AllocNamedChunk(ptr_0002B4_doors_ddata, blv.uDoors_ddata_Size, "L.DData");
+  //v171 = blv.uDoors_ddata_Size;
+  ptr_0002B4_doors_ddata = (unsigned __int16 *)pAllocator->AllocNamedChunk(ptr_0002B4_doors_ddata, blv.uDoors_ddata_Size, "L.DData");
+  memcpy(ptr_0002B4_doors_ddata, pData, blv.uDoors_ddata_Size);
+  pData += blv.uDoors_ddata_Size;
+
+  //Src = (BLVFace *)((char *)Src + v171);
+  //v172 = 0;
+  //v245 = 0;
+  //if (uNumDoors > 0)
+  for (uint i = 0, j = 0; i < uNumDoors; ++i)
+  {
+    auto pDoor = pDoors + i;
+
+    pDoor->pVertexIDs = ptr_0002B4_doors_ddata + j;
+    j += pDoor->uNumVertices;
+
+    pDoor->pFaceIDs = ptr_0002B4_doors_ddata + j;
+    j += pDoor->uNumFaces;
+
+    pDoor->pSectorIDs = ptr_0002B4_doors_ddata + j;
+    j += pDoor->field_48;
+
+    pDoor->pDeltaUs = (short *)(ptr_0002B4_doors_ddata + j);
+    j += pDoor->uNumFaces;
+
+    pDoor->pDeltaVs = (short *)(ptr_0002B4_doors_ddata + j);
+    j += pDoor->uNumFaces;
+
+    pDoor->pXOffsets = ptr_0002B4_doors_ddata + j;
+    j += pDoor->uNumOffsets;
+
+    pDoor->pYOffsets = ptr_0002B4_doors_ddata + j;
+    j += pDoor->uNumOffsets;
+
+    pDoor->pZOffsets = ptr_0002B4_doors_ddata + j;
+    j += pDoor->uNumOffsets;
+    /*v173 = pDoors;
+    for ( k = 0; ; v172 = v188 + 2 * *((short *)&v173[k] - 3) )
+    {
+      v173[k].pVertexIDs = (unsigned __int16 *)((char *)ptr_0002B4_doors_ddata + v172);
+      v175 = &pDoors[k];
+      v176 = v172 + 2 * v175->uNumVertices;
+      v175->pFaceIDs = (unsigned __int16 *)((char *)ptr_0002B4_doors_ddata + v176);
+      v177 = &pDoors[k];
+      v178 = v176 + 2 * v177->uNumFaces;
+      v177->pSectorIDs = (unsigned __int16 *)((char *)ptr_0002B4_doors_ddata + v178);
+      v179 = &pDoors[k];
+      v180 = v178 + 2 * v179->field_48;
+      v179->pDeltaUs = (__int16 *)((char *)ptr_0002B4_doors_ddata + v180);
+      v181 = &pDoors[k];
+      v182 = v180 + 2 * v181->uNumFaces;
+      v181->pDeltaVs = (__int16 *)((char *)ptr_0002B4_doors_ddata + v182);
+      v183 = &pDoors[k];
+      v184 = v182 + 2 * v183->uNumFaces;
+      v183->pXOffsets = (unsigned __int16 *)((char *)ptr_0002B4_doors_ddata + v184);
+      v185 = &pDoors[k];
+      v186 = v184 + 2 * v185->uNumOffsets;
+      v185->pYOffsets = (unsigned __int16 *)((char *)ptr_0002B4_doors_ddata + v186);
+      v187 = &pDoors[k];
+      ++k;
+      v188 = v186 + 2 * v187->uNumOffsets;
+      v189 = (unsigned __int16 *)((char *)ptr_0002B4_doors_ddata + v188);
+      ++v245;
+      v187->pZOffsets = v189;
+      v173 = pDoors;
+      if ( v245 >= uNumDoors )
+        break;
+    }*/
+  }
+  //v190 = 0;
+  //v245 = 0;
+  for (uint i = 0; i < uNumDoors; ++i)
+  {
+    auto pDoor = pDoors + i;
+
+    for (uint j = 0; j < pDoor->uNumFaces; ++j)
+    {
+      auto pFace = pFaces + pDoor->pFaceIDs[j];
+      auto pFaceExtra = pFaceExtras + pFace->uFaceExtraID;
+
+      pDoor->pDeltaUs[j] = pFaceExtra->sTextureDeltaU;
+      pDoor->pDeltaVs[j] = pFaceExtra->sTextureDeltaV;
+    }
+    //v191 = pDoors;
+    //pDest = 0;
+    //do
+   // {
+      /*Argsn = 0;
+      for ( l = (BLVDoor *)&v190[(int)v191];
+            Argsn < *(short *)&v190[(int)v191 + 70];
+            l = (BLVDoor *)&v190[(int)v191] )
+      {
+        v193 = Argsn;
+        v194 = l->pFaceIDs[Argsn++];
+        v195 = &pFaceExtras[pFaces[v194].uFaceExtraID];
+        l->pDeltaUs[v193] = v195->sTextureDeltaU;
+        v190 = pDest;
+        *(short *)(v193 * 2 + *(int *)&pDest[(unsigned int)pDoors + 52]) = v195->sTextureDeltaV;
+        v191 = pDoors;
+      }
+      ++v245;
+      v190 += 80;
+      pDest = v190;*/
+    //}
+    //while ( v245 < uNumDoors );
+  }
+
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&stru_5E4C90, pData, 0xC8);
+  pData += 0xC8;
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&stru1, pData, 0x38u);
+  pData += 0x38;
+
+  free(pRawDLV);
+  //v5 = 0;
+
+  pSoundList->LoadSound(64, 0);
+  pSoundList->LoadSound(103, 0);
+  pSoundList->LoadSound(63, 0);
+  pSoundList->LoadSound(102, 0);
+  pSoundList->LoadSound(50, 0);
+  pSoundList->LoadSound(89, 0);
+
+  return 0;
+}
+
+
+//----- (0049AC17) --------------------------------------------------------
+int IndoorLocation::GetSector(int sX, int sY, int sZ)
+{
+  int v4; // esi@1
+  //unsigned __int8 v5; // zf@1
+  //unsigned __int8 v6; // sf@1
+  //unsigned __int8 v7; // of@1
+  //BLVSector *v8; // eax@3
+  //int v9; // edi@9
+  //int v10; // eax@9
+  //int v11; // edx@9
+  //int v12; // eax@10
+  //unsigned __int16 v13; // ax@12
+  //int v14; // edi@14
+  //BLVFace *v15; // eax@14
+  //BLVFace *v16; // edi@14
+  //PolygonType v17; // al@14
+  //unsigned __int16 *pVertexIDs; // esi@16
+  //Vec3_short_ *v19; // eax@16
+  //int v20; // edx@16
+  //unsigned __int16 *v21; // esi@17
+  //int v22; // edi@19
+  //int v23; // edi@20
+  //Vec3_short_ *v24; // edx@20
+  signed int v25; // edx@21
+  int v26; // ebx@23
+  //int v27; // edx@26
+  //signed __int64 v28; // qtt@26
+  ///Vec3_short_ *v29; // eax@26
+  //Vec3_short_ *v30; // edx@26
+  //int v31; // edx@26
+  signed int v32; // edi@27
+  signed __int64 v33; // qtt@27
+  //Vec3_short_ *v34; // edx@27
+  int v35; // edx@32
+  int v37; // edi@38
+  int v38; // ebx@40
+  int v39; // eax@41
+  BLVFace *v40; // esi@42
+  PolygonType v41; // dl@42
+  int v42; // edx@43
+  int v43[50]; // [sp+Ch] [bp-108h]@1
+  //int v44; // [sp+D4h] [bp-40h]@9
+  //int v45; // [sp+D8h] [bp-3Ch]@14
+  //int v46; // [sp+DCh] [bp-38h]@14
+  //int v47; // [sp+E0h] [bp-34h]@19
+  //int v48; // [sp+E4h] [bp-30h]@9
+  //Vec3_short_ *v49; // [sp+E8h] [bp-2Ch]@19
+  bool v50; // [sp+ECh] [bp-28h]@19
+  int v51; // [sp+F0h] [bp-24h]@9
+  //unsigned int v52; // [sp+F4h] [bp-20h]@2
+  int v53; // [sp+F8h] [bp-1Ch]@10
+  int v54; // [sp+FCh] [bp-18h]@16
+  int v55; // [sp+100h] [bp-14h]@1
+  int v56; // [sp+104h] [bp-10h]@1
+  int v57; // [sp+108h] [bp-Ch]@16
+  //Vec3_short_ *v58; // [sp+10Ch] [bp-8h]@20
+  int v59; // [sp+110h] [bp-4h]@16
+
+  v4 = 0;
+  //v7 = __OFSUB__(this->uNumSectors, 1);
+  //v5 = this->uNumSectors == 1;
+  //v6 = this->uNumSectors - 1 < 0;
+  v55 = 0;
+  v43[0] = 0;
+  //v56 = 1;
+  if (uNumSectors < 2)
+    return 0;
+
+  for (uint i = 1; i < uNumSectors; ++i)
+  {
+    auto pSector = pSectors + i;
+
+    if (pSector->pBounding.x1 <= sX  && pSector->pBounding.x2 >= sX)
+      if (pSector->pBounding.y1 <= sY  && pSector->pBounding.y2 >= sY)
+        if (pSector->pBounding.z1 - 64 <= sZ && pSector->pBounding.z2 + 64 >= sZ)
+        {
+          Log::Warning(L"Sector[%u]", i);
+          v51 = pSector->uNumFloors + pSector->uNumPortals;
+          if (!v51)
+            continue;
+
+          //v9 = pSector->uNumFloors;
+                //v10 = v9 + pSector->uNumPortals;
+                //v11 = 0;
+                //v44 = v9;
+                //v48 = 0;
+
+                  //v12 = -2 * v9;
+                  //v53 = -2 * v9;
+           for (uint j = 0; j < v51; ++j)
+           {
+             unsigned int uFaceID;
+             if (j < pSector->uNumFloors)
+               uFaceID = pSector->pFloors[j];
+             else
+               uFaceID = pSector->pPortals[j - pSector->uNumFloors];
+
+             auto pFace = pFaces + uFaceID;
+                    //v14 = (signed __int16)v13;
+                    //v15 = this->pFaces;
+                    //v46 = v13;
+                    //v14 *= 96;
+                    //v45 = v13 * sizeof(BLVFace);
+                    //v16 = pFaces + uFaceID;
+                    //v17 = v16->uPolygonType;
+             if (pFace->uPolygonType == POLYGON_Floor ||
+                 pFace->uPolygonType == POLYGON_InBetweenFloorAndWall)
+             {
+               //pVertexIDs = pFace->pVertexIDs;
+                      //v19 = this->pVertices;
+               //v20 = pVertices[pFace->pVertexIDs[0]].y;
+                      v54 = 0;
+                      //v57 = 0;
+                      //v5 = v16->uNumVertices == 0;
+                      v59 = pVertices[pFace->pVertexIDs[0]].y >= sY;
+
+                        //v21 = pFace->pVertexIDs + 1;
+               for (uint k = 1; k < pFace->uNumVertices; ++k)
+               {
+                 if (v54 >= 2)
+                   break;
+
+                 //v49 = &pVertices[pFace->pVertexIDs[k]];
+                 auto v2 = &pVertices[pFace->pVertexIDs[k]];
+                          //v22 = pVertex->y;
+                          //v47 = pVertex->y;
+                 v50 = v2->y >= sY;
+                 if ( v59 ^ v50 )
+                 {
+                            //v58 = &pVertices[pFace->pVertexIDs[k - 1]];
+                   auto v1 = &pVertices[pFace->pVertexIDs[k - 1]];
+                            //v23 = v58->x;
+                            //HIWORD(v24) = HIWORD(v49);
+                            //LOWORD(v24) = v49->x;
+                            //v49 = v24;
+                            //v59 = v49->x;
+                   v25 = v1->x >= sX ? 0 : 2;  // BUG TODO TROLOLO
+                   v26 = v25 | v2->x < sX;     // SWAP v1 and v2 till the result's correct
+                   if ( v26 != 3 )
+                   {
+                    if (!v26)
+                      ++v54;
+                    else
+                    {
+                      if (v1->x >= v2->x)
+                      {
+                        int _a58;
+                        int _a59;
+
+                        v32 = v1->x - v2->x;
+                        LODWORD(v33) = v32 << 16;
+                        HIDWORD(v33) = v32 >> 16;
+                        _a58 = v33 / (v1->y - v2->y);
+                        _a59 = (unsigned __int64)(_a58 * (__int64)(sY - v2->y)) >> 16;
+
+                        if (v59 + pVertices[k].x > sX)
+                          ++v54;
+                      }
+                      else
+                      {
+                        int _a58;
+                        int _a59;
+                        v32 = v2->x - v1->x;
+                        LODWORD(v33) = v32 << 16;
+                        HIDWORD(v33) = v32 >> 16;
+                        _a58 = v33 / (v2->y - v1->y);
+                        _a59 = (unsigned __int64)(_a58 * (signed __int64)(sY - v1->y)) >> 16;
+
+                        if (_a59 + pVertices[k - 1].x > sX)
+                          ++v54;
+                      }
+                    }
+                   }
+                 }
+
+                 v59 = v50;
+               }
+
+               if (pFace->uNumVertices)
+               {
+                 if (v54 == 1)
+                 {
+                   v35 = v55++;
+                   v43[v35] = uFaceID;
+                 }
+               }
+             }
+            }
+            v4 = v43[0];
+          }
+  }
+
+  if ( v55 == 1 )
+    return this->pFaces[v4].uSectorID;
+  v37 = 0;
+  if ( !v55 )
+    return 0;
+  v38 = 0;
+  v53 = 0xFFFFFFu;
+  if ( v55 > 0 )
+  {
+    v39 = sY;
+    while ( 1 )
+    {
+      v40 = &this->pFaces[v43[v37]];
+      v41 = v40->uPolygonType;
+      if ( v41 == 3 )
+        break;
+      if ( v41 == 4 )
+      {
+        v51 = v40->zCalc1;
+        v57 = (unsigned __int64)(v51 * (signed __int64)(sX << 16)) >> 16;
+        v56 = sY << 16;
+        v51 = v40->zCalc2;
+        v56 = (unsigned __int64)(v51 * (signed __int64)(sY << 16)) >> 16;
+        v42 = (v56 + v40->zCalc3 + v57 + 32768) >> 16;
+        goto LABEL_46;
+      }
+LABEL_47:
+      if ( v39 >= 0 )
+      {
+        if ( v39 < v53 )
+        {
+          v38 = v40->uSectorID;
+          v53 = v39;
+        }
+      }
+      ++v37;
+      if ( v37 >= v55 )
+        return v38;
+    }
+    v42 = this->pVertices[*v40->pVertexIDs].z;
+LABEL_46:
+    v39 = sZ - v42;
+    goto LABEL_47;
+  }
+  return v38;
+}
+// 49AC17: using guessed type int var_108[50];
+
+
+//----- (00498A41) --------------------------------------------------------
+char BLVFace::_get_normals(Vec3_int_ *a2, Vec3_int_ *a3)
+{
+  BLVFace *v3; // ebx@1
+  int v4; // eax@1
+  signed __int64 v5; // qax@2
+  double v6; // st7@8
+  Vec3_float_ a1; // [sp+Ch] [bp-Ch]@8
+
+  v3 = this;
+  LOBYTE(v4) = this->uPolygonType;
+  if ( (char)v4 == POLYGON_VerticalWall )
+  {
+    a2->x = -this->pFacePlane_old.vNormal.y;
+    LODWORD(v5) = this->pFacePlane_old.vNormal.x;
+LABEL_9:
+    a2->y = v5;
+    v4 = 0;
+    a2->z = 0;
+    a3->y = 0;
+    a3->z = 0xFFFF0000u;
+LABEL_11:
+    a3->x = v4;
+    goto LABEL_12;
+  }
+  if ( (char)v4 == POLYGON_Floor || (char)v4 == POLYGON_Ceiling )
+  {
+LABEL_10:
+    v4 = 0;
+    a2->x = 0x10000u;
+    a2->z = 0;
+    a2->y = 0;
+    a3->y = 0xFFFF0000u;
+    a3->z = 0;
+    goto LABEL_11;
+  }
+  if ( (char)v4 == POLYGON_InBetweenFloorAndWall || (char)v4 == POLYGON_InBetweenCeilingAndWall )
+  {
+    if ( abs(this->pFacePlane_old.vNormal.z) < 46441 )
+    {
+      a1.x = (double)-v3->pFacePlane_old.vNormal.y;
+      a1.y = (double)v3->pFacePlane_old.vNormal.x;
+      a1.z = 0.0;
+      a1.Normalize();
+      v6 = a1.y * 65536.0;
+      a2->x = (signed __int64)(a1.x * 65536.0);
+      v5 = (signed __int64)v6;
+      goto LABEL_9;
+    }
+    goto LABEL_10;
+  }
+LABEL_12:
+  if ( BYTE2(v3->uAttributes) & 0x80 )
+  {
+    a2->x = -a2->x;
+    a2->y = -a2->y;
+    a2->z = -a2->z;
+  }
+  if ( BYTE3(v3->uAttributes) & 1 )
+  {
+    a3->x = -a3->x;
+    a3->y = -a3->y;
+    a3->z = -a3->z;
+  }
+  return v4;
+}
+
+//----- (0044C23B) --------------------------------------------------------
+int BLVFaceExtra::HasEventint()
+{
+  signed int v1; // eax@1
+  Event *v2; // esi@2
+  signed int result; // eax@5
+  signed int v4; // eax@6
+
+  v1 = 0;
+  if ( (signed int)(uLevelEVT_NumEvents - 1) <= 0 )
+    goto LABEL_5;
+  v2 = pLevelEVT_Events;
+  while ( v2->uEventID != this->uEventID )
+  {
+    ++v1;
+    ++v2;
+    if ( v1 >= (signed int)(uLevelEVT_NumEvents - 1) )
+      goto LABEL_5;
+  }
+  v4 = v1;
+  if ( pLevelEVT[pLevelEVT_Events[v4 + 1].uEventOffsetInEVT + 4] != 1
+    || pLevelEVT[pLevelEVT_Events[v4].uEventOffsetInEVT + 4] != 4 )
+LABEL_5:
+    result = 0;
+  else
+    result = 1;
+  return result;
+}
+
+
+
+
+//----- (0046F228) --------------------------------------------------------
+void __cdecl BLV_UpdateDoors()
+{
+  int v0; // ebx@1
+  int v1; // edi@1
+  BLVDoor *v2; // esi@3
+  unsigned __int16 v3; // ax@3
+  unsigned int v4; // ecx@5
+  int v5; // eax@8
+  int v6; // ecx@8
+  int v7; // eax@12
+  int v8; // eax@16
+  unsigned __int8 v9; // zf@18
+  char v10; // sf@18
+  unsigned __int8 v11; // of@18
+  int v12; // edi@19
+  int v13; // ecx@19
+  __int16 v14; // ax@19
+  BLVFace *v15; // ebx@24
+  unsigned __int16 *v16; // ecx@24
+  Vec3_short_ *v17; // esi@24
+  int v18; // eax@24
+  int v19; // edx@24
+  signed int v20; // eax@24
+  Vec3_short_ *v21; // ecx@24
+  double v22; // st7@24
+  double v23; // st6@24
+  int v24; // esi@25
+  int v25; // eax@25
+  BLVDoor *v26; // edi@25
+  signed __int64 v27; // qtt@27
+  BLVFaceExtra *v28; // esi@32
+  int v29; // ecx@34
+  int v30; // edx@34
+  unsigned __int64 v31; // qax@34
+  int v32; // eax@34
+  unsigned __int16 *v33; // eax@35
+  Vec3_short_ *v34; // eax@35
+  int v35; // ecx@35
+  int v36; // edx@35
+  signed int v37; // eax@35
+  signed int v38; // edx@35
+  int v39; // eax@35
+  int v40; // edx@35
+  unsigned __int8 v41; // cf@35
+  unsigned __int16 *v42; // edi@36
+  Vec3_short_ *v43; // edi@36
+  int v44; // ecx@36
+  int v45; // edi@36
+  int v46; // ecx@36
+  __int16 *v47; // edx@44
+  int v48; // ecx@44
+  unsigned int v49; // ecx@46
+  unsigned __int16 v50; // ax@48
+  unsigned int v51; // eax@51
+  unsigned __int16 v52; // ax@54
+  int v53; // ecx@57
+  int v54; // edx@57
+  unsigned __int64 v55; // qax@57
+  int v56; // ecx@58
+  int v57; // eax@58
+  int v58; // eax@59
+  SoundID v59; // [sp-24h] [bp-88h]@12
+  signed int v60; // [sp-20h] [bp-84h]@12
+  unsigned int v61; // [sp-1Ch] [bp-80h]@12
+  signed int v62; // [sp-18h] [bp-7Ch]@12
+  signed int v63; // [sp-14h] [bp-78h]@12
+  int v64; // [sp-10h] [bp-74h]@12
+  unsigned int v65; // [sp-Ch] [bp-70h]@12
+  int v66; // [sp-8h] [bp-6Ch]@12
+  int v67; // [sp+8h] [bp-5Ch]@31
+  int v68; // [sp+Ch] [bp-58h]@34
+  int v69; // [sp+10h] [bp-54h]@34
+  int v70; // [sp+14h] [bp-50h]@31
+  int v71; // [sp+18h] [bp-4Ch]@34
+  int v72; // [sp+1Ch] [bp-48h]@34
+  int v73; // [sp+20h] [bp-44h]@24
+  __int16 v74; // [sp+24h] [bp-40h]@24
+  int v75; // [sp+28h] [bp-3Ch]@36
+  int v76; // [sp+2Ch] [bp-38h]@36
+  int v77; // [sp+30h] [bp-34h]@36
+  int v78; // [sp+34h] [bp-30h]@36
+  int v79; // [sp+38h] [bp-2Ch]@19
+  unsigned int v80; // [sp+3Ch] [bp-28h]@2
+  int v81; // [sp+40h] [bp-24h]@1
+  int v82; // [sp+44h] [bp-20h]@35
+  int v83; // [sp+48h] [bp-1Ch]@34
+  int v84; // [sp+4Ch] [bp-18h]@34
+  int v85; // [sp+50h] [bp-14h]@19
+  SoundID eDoorSoundID; // [sp+54h] [bp-10h]@1
+  BLVDoor *v87; // [sp+58h] [bp-Ch]@3
+  int v88; // [sp+5Ch] [bp-8h]@18
+  int v89; // [sp+60h] [bp-4h]@6
+
+  v0 = 0;
+  v1 = 0;
+  eDoorSoundID = (SoundID)pDoorSoundIDsByLocationID[dword_6BE13C_uCurrentlyLoadedLocationID];
+  v81 = 0;
+  if ( pIndoor->uNumDoors > 0 )
+  {
+    v80 = 0;
+    do
+    {
+      v2 = &pIndoor->pDoors[v80 / 0x50];
+      v87 = &pIndoor->pDoors[v80 / 0x50];
+      v3 = pIndoor->pDoors[v80 / 0x50].uState;
+      if ( v3 == (short)v0 || v3 == 2 )
+      {
+        v2->uAttributes &= 0xFFFFFFFDu;
+        goto LABEL_62;
+      }
+      v2->uTimeSinceTriggered += pEventTimer->uTimeElapsed;
+      v4 = v2->uTimeSinceTriggered;
+      if ( v2->uState == 1 )
+      {
+        v89 = (signed int)(v4 * v2->uCloseSpeed) / 128;
+        if ( v89 >= v2->uMoveLength )
+        {
+          v89 = v2->uMoveLength;
+          v2->uState = BLVDoor::Open;
+LABEL_10:
+          if ( !(v2->uAttributes & 6) && v2->uNumVertices != (short)v0 )
+          {
+            v66 = v0;
+            v65 = v0;
+            v64 = v0;
+            v7 = 8 * v1;
+            v63 = v0;
+            v62 = -1;
+            LOBYTE(v7) = 8 * v1 | 1;
+            v61 = v0;
+            v60 = v7;
+            v59 = (SoundID)((int)eDoorSoundID + 1);
+LABEL_17:
+            pAudioPlayer->PlaySound(v59, v60, v61, v62, v63, v64, v65, v66);
+            goto LABEL_18;
+          }
+          goto LABEL_18;
+        }
+      }
+      else
+      {
+        v5 = (signed int)(v4 * v2->uOpenSpeed) / 128;
+        v6 = v2->uMoveLength;
+        if ( v5 >= v6 )
+        {
+          v89 = v0;
+          v2->uState = (BLVDoor::State)v0;
+          goto LABEL_10;
+        }
+        v89 = v6 - v5;
+      }
+      if ( !(v2->uAttributes & 6) && v2->uNumVertices != (short)v0 )
+      {
+        v66 = v0;
+        v65 = v0;
+        v64 = v0;
+        v8 = 8 * v1;
+        v63 = v0;
+        v62 = -1;
+        LOBYTE(v8) = 8 * v1 | 1;
+        v61 = 1;
+        v60 = v8;
+        v59 = eDoorSoundID;
+        goto LABEL_17;
+      }
+LABEL_18:
+      v11 = __OFSUB__(v2->uNumVertices, (short)v0);
+      v9 = v2->uNumVertices == (short)v0;
+      v10 = (signed __int16)(v2->uNumVertices - v0) < 0;
+      v88 = v0;
+      if ( !((unsigned __int8)(v10 ^ v11) | v9) )
+      {
+        do
+        {
+          v12 = v88;
+          v13 = v2->pVertexIDs[v88];
+          v85 = v89;
+          v79 = v2->vDirection.x;
+          v85 = (unsigned __int64)(v79 * (signed __int64)v89) >> 16;
+          v13 *= 6;
+          *(__int16 *)((char *)&pIndoor->pVertices->x + v13) = ((unsigned int)(v79 * v89) >> 16) + v2->pXOffsets[v88];
+          v85 = v89;
+          v79 = v2->vDirection.y;
+          v85 = (unsigned __int64)(v79 * (signed __int64)v89) >> 16;
+          *(__int16 *)((char *)&pIndoor->pVertices->y + v13) = ((unsigned int)(v79 * v89) >> 16) + v2->pYOffsets[v12];
+          v85 = v89;
+          v79 = v2->vDirection.z;
+          v85 = (unsigned __int64)(v79 * (signed __int64)v89) >> 16;
+          v14 = ((unsigned int)(v79 * v89) >> 16) + v2->pZOffsets[v12];
+          ++v88;
+          *(__int16 *)((char *)&pIndoor->pVertices->z + v13) = v14;
+        }
+        while ( v88 < v2->uNumVertices );
+        v1 = v81;
+      }
+      v11 = __OFSUB__(v2->uNumFaces, (short)v0);
+      v9 = v2->uNumFaces == (short)v0;
+      v10 = (signed __int16)(v2->uNumFaces - v0) < 0;
+      v88 = v0;
+      if ( !((unsigned __int8)(v10 ^ v11) | v9) )
+      {
+        while ( 1 )
+        {
+          v15 = &pIndoor->pFaces[v2->pFaceIDs[v88]];
+          v16 = v15->pVertexIDs;
+          v17 = &pIndoor->pVertices[*v16];
+          v18 = v15->pFacePlane_old.vNormal.y;
+          v73 = *(int *)&v17->x;
+          v74 = v17->z;
+          v19 = v15->pFacePlane_old.vNormal.z;
+          v20 = -(v19 * v74 + (signed __int16)v73 * v15->pFacePlane_old.vNormal.x + SHIWORD(v73) * v18);
+          v15->pFacePlane_old.dist = v20;
+          v21 = &pIndoor->pVertices[*v16];
+          v79 = v21->x;
+          v22 = (double)v79;
+          v23 = (double)v21->y;
+          v79 = v21->z;
+          v15->pFacePlane.dist = -((double)v79 * v15->pFacePlane.vNormal.z
+                                 + v23 * v15->pFacePlane.vNormal.y
+                                 + v22 * v15->pFacePlane.vNormal.x);
+          if ( v19 )
+          {
+            v24 = abs(v20 >> 15);
+            v25 = abs(v15->pFacePlane_old.vNormal.z);
+            v26 = v87;
+            if ( v24 > v25 )
+              Abortf(
+                "Door Error\ndoor id: %i\nfacet no: %i\n\nOverflow dividing facet->d [%i] by facet->nz [%i]",
+                v87->uDoorID,
+                v87->pFaceIDs[v88],
+                v15->pFacePlane_old.dist,
+                v15->pFacePlane_old.vNormal.z);
+            v79 = v15->pFacePlane_old.vNormal.z;
+            v85 = v15->pFacePlane_old.dist;
+            LODWORD(v27) = v85 << 16;
+            HIDWORD(v27) = v85 >> 16;
+            v85 = v27 / v79;
+            v15->zCalc3 = -(v27 / v79);
+          }
+          else
+          {
+            v26 = v87;
+          }
+          if ( BYTE2(v15->uAttributes) & 4 || pRenderer->pRenderD3D )
+            v15->_get_normals((Vec3_int_ *)&v70, (Vec3_int_ *)&v67);
+          v28 = &pIndoor->pFaceExtras[v15->uFaceExtraID];
+          if ( !pRenderer->pRenderD3D )
+          {
+            if ( !(BYTE2(v15->uAttributes) & 4) )
+              goto LABEL_59;
+            v79 = v26->vDirection.x;
+            v83 = (unsigned __int64)(v79 * (signed __int64)v70) >> 16;
+            v85 = v71;
+            v79 = v26->vDirection.y;
+            v85 = (unsigned __int64)(v79 * (signed __int64)v71) >> 16;
+            v84 = v72;
+            v79 = v26->vDirection.z;
+            v84 = (unsigned __int64)(v79 * (signed __int64)v72) >> 16;
+            v79 = v83 + v85 + ((unsigned __int64)(v79 * (signed __int64)v72) >> 16);
+            v29 = v89;
+            v83 = (unsigned __int64)(v79 * (signed __int64)v89) >> 16;
+            v28->sTextureDeltaU = -((unsigned int)(v79 * v89) >> 16);
+            v79 = v26->vDirection.x;
+            v85 = (unsigned __int64)(v79 * (signed __int64)v67) >> 16;
+            v83 = v68;
+            v79 = v26->vDirection.y;
+            v83 = (unsigned __int64)(v79 * (signed __int64)v68) >> 16;
+            v84 = v69;
+            v79 = v26->vDirection.z;
+            v84 = (unsigned __int64)(v79 * (signed __int64)v69) >> 16;
+            v30 = v83 + ((unsigned __int64)(v79 * (signed __int64)v69) >> 16);
+            v79 = v85 + v30;
+            v31 = (v85 + v30) * (signed __int64)v29;
+            v83 = v31 >> 16;
+            v32 = v31 >> 16;
+            goto LABEL_58;
+          }
+          v28->sTextureDeltaU = 0;
+          v28->sTextureDeltaV = 0;
+          v33 = v15->pVertexIDs;
+          v85 = 1;
+          v34 = &pIndoor->pVertices[*v33];
+          v35 = v34->z;
+          v36 = v34->y;
+          v82 = v34->x;
+          v79 = v36;
+          v37 = v70 * v82 + v71 * v36 + v72 * v35;
+          v38 = v67 * v82 + v68 * v36 + v35 * v69;
+          v39 = v37 >> 16;
+          *v15->pVertexUIDs = v39;
+          v40 = v38 >> 16;
+          *v15->pVertexVIDs = v40;
+          v41 = v15->uNumVertices < 1u;
+          v9 = v15->uNumVertices == 1;
+          v83 = v40;
+          v84 = v39;
+          v82 = v40;
+          if ( !(v41 | v9) )
+          {
+            do
+            {
+              v42 = v15->pVertexIDs;
+              v75 = 2 * v85;
+              v43 = &pIndoor->pVertices[v42[v85]];
+              v79 = v43->z;
+              v44 = v43->y;
+              v45 = v43->x;
+              v78 = v44;
+              v76 = (v72 * v79 + v70 * v45 + v71 * v44) >> 16;
+              v46 = (v67 * v45 + v68 * v44 + v79 * v69) >> 16;
+              v77 = v46;
+              if ( v76 < v39 )
+                v39 = v76;
+              if ( v46 < v40 )
+                v83 = v46;
+              if ( v76 > v84 )
+                v84 = v76;
+              if ( v46 > v82 )
+                v82 = v46;
+              v47 = v15->pVertexUIDs;
+              v48 = v75;
+              ++v85;
+              *(unsigned __int16 *)((char *)v47 + v75) = v76;
+              *(unsigned __int16 *)((char *)v15->pVertexVIDs + v48) = v77;
+              v40 = v83;
+            }
+            while ( v85 < v15->uNumVertices );
+            v26 = v87;
+          }
+          v49 = v15->uAttributes;
+          if ( BYTE1(v49) & 0x10 )
+            goto LABEL_50;
+          if ( SBYTE1(v49) < 0 )
+          {
+            v50 = v15->uBitmapID;
+            if ( v50 != -1 )
+              break;
+          }
+LABEL_51:
+          v51 = v15->uAttributes;
+          if ( v51 & 8 )
+          {
+            v28->sTextureDeltaV -= v40;
+          }
+          else
+          {
+            if ( v51 & 0x20000 )
+            {
+              v52 = v15->uBitmapID;
+              if ( v52 != -1 )
+                v28->sTextureDeltaV -= v82
+                                     + *(short *)((signed __int16)v52 != -1 ? 72 * (signed __int16)v52 + 7278780 + 0x1A : 26);
+            }
+          }
+          if ( BYTE2(v15->uAttributes) & 4 )
+          {
+            v75 = v26->vDirection.x;
+            v84 = (unsigned __int64)(v75 * (signed __int64)v70) >> 16;
+            v82 = v71;
+            v75 = v26->vDirection.y;
+            v82 = (unsigned __int64)(v75 * (signed __int64)v71) >> 16;
+            v83 = v72;
+            v75 = v26->vDirection.z;
+            v83 = (unsigned __int64)(v75 * (signed __int64)v72) >> 16;
+            v75 = v84 + v82 + ((unsigned __int64)(v75 * (signed __int64)v72) >> 16);
+            v53 = v89;
+            v82 = (unsigned __int64)(v75 * (signed __int64)v89) >> 16;
+            v28->sTextureDeltaU = -((unsigned int)(v75 * v89) >> 16);
+            v75 = v26->vDirection.x;
+            v84 = (unsigned __int64)(v75 * (signed __int64)v67) >> 16;
+            v82 = v68;
+            v75 = v26->vDirection.y;
+            v82 = (unsigned __int64)(v75 * (signed __int64)v68) >> 16;
+            v83 = v69;
+            v75 = v26->vDirection.z;
+            v83 = (unsigned __int64)(v75 * (signed __int64)v69) >> 16;
+            v54 = v82 + ((unsigned __int64)(v75 * (signed __int64)v69) >> 16);
+            v75 = v84 + v54;
+            v55 = (v84 + v54) * (signed __int64)v53;
+            v82 = v55 >> 16;
+            v32 = v55 >> 16;
+LABEL_58:
+            v56 = v88;
+            v57 = -v32;
+            v28->sTextureDeltaV = v57;
+            v28->sTextureDeltaU += v26->pDeltaUs[v56];
+            v28->sTextureDeltaV = v57 + v26->pDeltaVs[v56];
+          }
+LABEL_59:
+          v58 = v26->uNumFaces;
+          ++v88;
+          if ( v88 >= v58 )
+          {
+            v1 = v81;
+            v0 = 0;
+            goto LABEL_62;
+          }
+          v2 = v87;
+        }
+        LOWORD(v39) = v84
+                    + ((signed __int16)v39 != -1 ? pBitmaps_LOD->pTextures[(signed __int16)v39].uTextureWidth : 24);
+LABEL_50:
+        v28->sTextureDeltaU -= v39;
+        goto LABEL_51;
+      }
+LABEL_62:
+      v80 += 80;
+      ++v1;
+      v81 = v1;
+    }
+    while ( v1 < pIndoor->uNumDoors );
+  }
+}
+// 6BE13C: using guessed type int dword_6BE13C_uCurrentlyLoadedLocationID;
+
+//----- (0046F90C) --------------------------------------------------------
+void __cdecl UpdateActors_BLV()
+{
+  Actor *v0; // esi@2
+  unsigned __int16 v1; // ax@2
+  int v2; // edi@6
+  int v3; // eax@6
+  int v4; // eax@8
+  __int16 v5; // ax@11
+  signed int v6; // ebx@14
+  unsigned __int8 v7; // zf@14
+  unsigned __int8 v8; // sf@14
+  signed __int16 v9; // ax@17
+  signed __int64 v10; // qax@18
+  unsigned __int16 v11; // ax@21
+  int v12; // eax@29
+  unsigned __int64 v13; // qax@29
+  int v14; // eax@30
+  unsigned __int64 v15; // qax@30
+  int v16; // ecx@33
+  BLVFace *v17; // edx@33
+  int v18; // ecx@33
+  BLVFace *v19; // eax@34
+  int v20; // ecx@46
+  int v21; // eax@46
+  int v22; // edi@46
+  int v23; // eax@48
+  unsigned int v24; // eax@51
+  int v25; // eax@52
+  int v26; // ebx@54
+  int v27; // ST08_4@54
+  int v28; // edi@54
+  int v29; // eax@54
+  int v30; // ecx@62
+  int v31; // ebx@62
+  int v32; // eax@62
+  int v33; // eax@64
+  unsigned int v34; // ecx@64
+  int v35; // ecx@64
+  signed int v36; // edx@85
+  signed int v37; // ebx@85
+  BLVFace *v38; // edi@89
+  int v39; // ecx@90
+  int v40; // ebx@90
+  PolygonType v41; // al@94
+  int v42; // eax@96
+  __int16 v43; // dx@96
+  int v44; // ecx@96
+  int v45; // edi@101
+  int v46; // edi@101
+  int v47; // eax@101
+  unsigned __int64 v48; // qax@101
+  unsigned __int8 v49; // zf@103
+  unsigned __int8 v50; // sf@103
+  unsigned __int8 v51; // of@103
+  AIDirection v52; // [sp+0h] [bp-60h]@75
+  AIDirection v53; // [sp+1Ch] [bp-44h]@116
+  int v54; // [sp+38h] [bp-28h]@53
+  unsigned int uSectorID; // [sp+3Ch] [bp-24h]@6
+  int v56; // [sp+40h] [bp-20h]@6
+  unsigned int _this; // [sp+44h] [bp-1Ch]@51
+  int v58; // [sp+48h] [bp-18h]@51
+  int v59; // [sp+4Ch] [bp-14h]@8
+  unsigned int uFaceID; // [sp+50h] [bp-10h]@6
+  int v61; // [sp+54h] [bp-Ch]@14
+  int v62; // [sp+58h] [bp-8h]@6
+  unsigned int v63; // [sp+5Ch] [bp-4h]@1
+
+  v63 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    while ( 1 )
+    {
+      v0 = &pActors[v63];
+      v1 = v0->uAIState;
+      if ( v1 == 11 || v1 == 19 || v1 == 17 || !v0->uMovementSpeed )
+        goto LABEL_123;
+      uSectorID = v0->uSectorID;
+      v2 = _46ED1B_collide_against_floor(v0->vPosition.x, v0->vPosition.y, v0->vPosition.z, &uSectorID, &uFaceID);
+      v0->uSectorID = uSectorID;
+      v3 = v0->pMonsterInfo.uFlying;
+      v56 = v2;
+      v62 = v3;
+      if ( !v0->CanAct() )
+        v62 = 0;
+      v4 = v0->vPosition.z;
+      v59 = 0;
+      if ( v4 > v2 + 1 )
+        v59 = 1;
+      if ( v2 <= -30000 )
+      {
+        v5 = pIndoor->GetSector(v0->vPosition.x, v0->vPosition.y, v4);
+        v0->uSectorID = v5;
+        if ( !v5
+          || (v56 = _46CEC3_get_floor_level(v0->vPosition.x, v0->vPosition.y, v0->vPosition.z, v5, &uFaceID), v56 == -30000) )
+          goto LABEL_123;
+      }
+      if ( v0->uCurrentActionAnimation == 1 )
+      {
+        v6 = v0->uMovementSpeed;
+        v7 = HIDWORD(v0->pActorBuffs[7].uExpireTime) == 0;
+        v8 = SHIDWORD(v0->pActorBuffs[7].uExpireTime) < 0;
+        v61 = v0->uMovementSpeed;
+        if ( !v8 && (!(v8 | v7) || LODWORD(v0->pActorBuffs[7].uExpireTime)) )
+        {
+          v9 = v0->pActorBuffs[7].uPower;
+          if ( v9 )
+            LODWORD(v10) = v6 / (unsigned __int16)v9;
+          else
+            v10 = (signed __int64)((double)v61 * 0.5);
+          v6 = v10;
+          v61 = v10;
+        }
+        v11 = v0->uAIState;
+        if ( v11 == 6 || v11 == 7 )
+        {
+          v6 *= 2;
+          v61 = v6;
+        }
+        if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 1 )
+          v6 = (signed __int64)((double)v61 * flt_6BE3AC_debug_recmod1_x_1_6);
+        if ( v6 > 1000 )
+          v6 = 1000;
+        v12 = stru_5C6E00->SinCos(v0->uYawAngle);
+        uSectorID = v12;
+        v13 = v12 * (signed __int64)v6;
+        v61 = v13 >> 16;
+        v0->vVelocity.x = WORD1(v13);
+        uSectorID = stru_5C6E00->SinCos(v0->uYawAngle - stru_5C6E00->uIntegerHalfPi);
+        v61 = (unsigned __int64)(uSectorID * (signed __int64)v6) >> 16;
+        v7 = v62 == 0;
+        v0->vVelocity.y = (unsigned int)(uSectorID * v6) >> 16;
+        if ( !v7 )
+        {
+          v14 = stru_5C6E00->SinCos(v0->uPitchAngle - stru_5C6E00->uIntegerHalfPi);
+          uSectorID = v14;
+          v15 = v14 * (signed __int64)v6;
+          v61 = v15 >> 16;
+          v0->vVelocity.z = WORD1(v15);
+        }
+      }
+      else
+      {
+        v61 = v0->vVelocity.x;
+        uSectorID = 55000;
+        v61 = (unsigned __int64)(55000i64 * v61) >> 16;
+        v0->vVelocity.x = v61;
+        v61 = v0->vVelocity.y;
+        v61 = (unsigned __int64)(uSectorID * (signed __int64)v61) >> 16;
+        v7 = v62 == 0;
+        v0->vVelocity.y = v61;
+        if ( !v7 )
+        {
+          uSectorID = 55000;
+          v61 = v0->vVelocity.z;
+          v61 = (unsigned __int64)(55000i64 * v61) >> 16;
+          v0->vVelocity.z = v61;
+        }
+      }
+      v16 = v0->vPosition.z;
+      v17 = pIndoor->pFaces;
+      v51 = __OFSUB__(v16, v56);
+      v8 = v16 - v56 < 0;
+      v18 = uFaceID;
+      if ( v8 ^ v51 )
+      {
+        v0->vPosition.z = v56 + 1;
+        v19 = &v17[v18];
+        if ( v19->uPolygonType == 3 )
+        {
+          if ( v0->vVelocity.z < 0 )
+            v0->vVelocity.z = 0;
+        }
+        else
+        {
+          if ( v19->pFacePlane_old.vNormal.z < 45000 )
+            v0->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
+        }
+      }
+      else
+      {
+        if ( v59 && !v62 )
+          v0->vVelocity.z += -8 * LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
+      }
+      if ( v0->vVelocity.x * v0->vVelocity.x + v0->vVelocity.y * v0->vVelocity.y + v0->vVelocity.z * v0->vVelocity.z >= 400 )
+        break;
+      v0->vVelocity.z = 0;
+      v0->vVelocity.y = 0;
+      v0->vVelocity.x = 0;
+      if ( BYTE2(v17[v18].uAttributes) & 0x40 )
+      {
+        if (v0->uAIState == Dead)
+          v0->uAIState = Removed;
+      }
+LABEL_123:
+      ++v63;
+      if ( (signed int)v63 >= (signed int)uNumActors )
+        return;
+    }
+    v20 = v0->uActorRadius;
+    v21 = v0->uActorHeight;
+    stru_721530.field_84 = -1;
+    stru_721530.field_70 = 0;
+    uSectorID = 0;
+    stru_721530.field_0 = 1;
+    stru_721530.field_8 = v20;
+    stru_721530.prolly_normal_d = v20;
+    stru_721530.field_C = v21;
+    v22 = 0;
+    while ( 1 )
+    {
+      stru_721530.field_34.x = v0->vPosition.x;
+      stru_721530.normal.x = stru_721530.field_34.x;
+      stru_721530.field_34.y = v0->vPosition.y;
+      stru_721530.normal.y = stru_721530.field_34.y;
+      v23 = v0->vPosition.z;
+      stru_721530.normal.z = v23 + v20 + 1;
+      stru_721530.field_34.z = v23 - v20 + stru_721530.field_C - 1;
+      if ( stru_721530.field_34.z < stru_721530.normal.z )
+        stru_721530.field_34.z = v23 + v20 + 1;
+      stru_721530.field_1C = v0->vVelocity.x;
+      stru_721530.field_20 = v0->vVelocity.y;
+      stru_721530.field_24 = v0->vVelocity.z;
+      stru_721530.uSectorID = v0->uSectorID;
+      if ( !stru_721530._47050A(v22) )
+      {
+        v58 = v22;
+        v24 = 8 * v63;
+        LOBYTE(v24) = 8 * v63 | 3;
+        v61 = v22;
+        _this = v24;
+        do
+        {
+          _46E44E_collide_against_faces_and_portals(1u);
+          _46E0B2_collide_against_decorations();
+          _46EF01_collision_chech_player(0);
+          _46ED8A_collide_against_layingItems(_this);
+          v25 = 0;
+          v56 = 0;
+          if ( ai_arrays_size > v22 )
+          {
+            do
+            {
+              v54 = ai_array_4F7DB0_actor_ids[v25];
+              if ( v54 != v63 )
+              {
+                v26 = v54;
+                v27 = abs(pActors[v54].vPosition.z - v0->vPosition.z);
+                v28 = abs(pActors[v26].vPosition.y - v0->vPosition.y);
+                v29 = abs(pActors[v26].vPosition.x - v0->vPosition.x);
+                if ( sub_4621DA(v29, v28, v27) >= v0->uActorRadius + (signed int)pActors[v26].uActorRadius
+                  && _46DF1A_collide_against_actor(v54, 40) )
+                  ++v58;
+                v22 = 0;
+              }
+              v25 = v56++ + 1;
+            }
+            while ( v56 < ai_arrays_size );
+          }
+          if ( _46F04E_collide_against_portals() )
+            break;
+          ++v61;
+        }
+        while ( v61 < 100 );
+        v56 = v58 > 1;
+        if ( stru_721530.field_7C >= stru_721530.field_6C )
+        {
+          v30 = stru_721530.normal2.x;
+          v31 = stru_721530.normal2.y;
+          v32 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+        }
+        else
+        {
+          v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
+          v30 = v58 + v0->vPosition.x;
+          v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
+          v31 = v58 + v0->vPosition.y;
+          v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
+          v32 = v58 + v0->vPosition.z;
+        }
+        v33 = _46ED1B_collide_against_floor(v30, v31, v32, &stru_721530.uSectorID, &uFaceID);
+        v34 = pIndoor->pFaces[uFaceID].uAttributes;
+        v35 = v34 & 0x400000;
+        if (v35 && v0->uAIState == Dead)
+        {
+          v0->uAIState = Removed;
+          goto LABEL_120;
+        }
+        if ( v59 != v22 || v62 != v22 || v35 == v22 )
+        {
+          if ( v33 == -30000 )
+            goto LABEL_120;
+          if ( v0->uCurrentActionAnimation != 1 || v33 >= v0->vPosition.z - 100 || v59 != v22 || v62 != v22 )
+          {
+            if ( stru_721530.field_7C >= stru_721530.field_6C )
+            {
+              v0->vPosition.x = LOWORD(stru_721530.normal2.x);
+              v0->vPosition.y = LOWORD(stru_721530.normal2.y);
+              v0->vPosition.z = LOWORD(stru_721530.normal2.z) - LOWORD(stru_721530.prolly_normal_d) - 1;
+              v0->uSectorID = LOWORD(stru_721530.uSectorID);
+              goto LABEL_123;
+            }
+            v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
+            v0->vPosition.x += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.x) >> 16;
+            v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
+            v0->vPosition.y += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.y) >> 16;
+            v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
+            v36 = stru_721530.uFaceID;
+            v0->vPosition.z += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.z) >> 16;
+            v0->uSectorID = LOWORD(stru_721530.uSectorID);
+            stru_721530.field_70 += stru_721530.field_7C;
+            v37 = v36 >> 3;
+            if ( (v36 & 7) != 3 )
+            {
+              if ( (v36 & 7) != 4 )
+              {
+                if ( (v36 & 7) == 5 )
+                {
+                  _this = sub_452A9E(v0->vVelocity.x * v0->vVelocity.x + v0->vVelocity.y * v0->vVelocity.y);
+                  v45 = stru_5C6E00->Atan2(
+                          v0->vPosition.x - pLevelDecorations[v37].vPosition.x,
+                          v0->vPosition.y - pLevelDecorations[v37].vPosition.y);
+                  v54 = stru_5C6E00->SinCos(v45);
+                  v56 = (unsigned __int64)(v54 * (signed __int64)(signed int)_this) >> 16;
+                  v46 = v45 - stru_5C6E00->uIntegerHalfPi;
+                  v0->vVelocity.x = v54 * _this >> 16;
+                  v47 = stru_5C6E00->SinCos(v46);
+                  v54 = v47;
+                  v48 = v47 * (signed __int64)(signed int)_this;
+                  v56 = v48 >> 16;
+                  v0->vVelocity.y = WORD1(v48);
+                  goto LABEL_119;
+                }
+                if ( (v36 & 7) == 6 )
+                {
+                  stru_721530.field_84 = v36 >> 3;
+                  v38 = &pIndoor->pFaces[v37];
+                  if ( v38->uPolygonType == 3 )
+                  {
+                    v39 = v0->vVelocity.x;
+                    v40 = v0->vVelocity.y * v0->vVelocity.y;
+                    v0->vVelocity.z = 0;
+                    v0->vPosition.z = pIndoor->pVertices[*v38->pVertexIDs].z + 1;
+                    if ( v39 * v39 + v40 < 400 )
+                    {
+                      v0->vVelocity.y = 0;
+                      v0->vVelocity.x = 0;
+                      goto LABEL_119;
+                    }
+                  }
+                  else
+                  {
+                    v61 = abs(v38->pFacePlane_old.vNormal.x * v0->vVelocity.x + v38->pFacePlane_old.vNormal.y
+                                                                              * v0->vVelocity.y
+                                                                              + v38->pFacePlane_old.vNormal.z
+                                                                              * v0->vVelocity.z) >> 16;
+                    if ( stru_721530.field_64 >> 3 > v61 )
+                      v61 = stru_721530.field_64 >> 3;
+                    v58 = v38->pFacePlane_old.vNormal.x;
+                    v58 = (unsigned __int64)(v61 * (signed __int64)v58) >> 16;
+                    _this = v38->pFacePlane_old.vNormal.y;
+                    _this = (unsigned __int64)(v61 * (signed __int64)(signed int)_this) >> 16;
+                    v56 = v38->pFacePlane_old.vNormal.z;
+                    v56 = (unsigned __int64)(v61 * (signed __int64)v56) >> 16;
+                    v0->vVelocity.x += v58;
+                    v0->vVelocity.y += _this;
+                    v0->vVelocity.z += v56;
+                    v41 = v38->uPolygonType;
+                    if ( v41 != 4 && v41 != 3 )
+                    {
+                      v42 = v38->pFacePlane_old.vNormal.x;
+                      v43 = v0->vPosition.z;
+                      v44 = stru_721530.prolly_normal_d
+                          - ((v38->pFacePlane_old.dist
+                            + v38->pFacePlane_old.vNormal.z * v0->vPosition.z
+                            + v38->pFacePlane_old.vNormal.y * v0->vPosition.y
+                            + v42 * v0->vPosition.x) >> 16);
+                      if ( v44 > 0 )
+                      {
+                        v0->vPosition.x += (unsigned int)(v44 * v42) >> 16;
+                        v0->vPosition.y += (unsigned int)(v44 * v38->pFacePlane_old.vNormal.y) >> 16;
+                        v0->vPosition.z = v43 + ((unsigned int)(v44 * v38->pFacePlane_old.vNormal.z) >> 16);
+                      }
+                      v0->uYawAngle = stru_5C6E00->Atan2(v0->vVelocity.x, v0->vVelocity.y);
+                    }
+                  }
+                  if ( BYTE3(v38->uAttributes) & 8 )
+                    EventProcessor(pIndoor->pFaceExtras[v38->uFaceExtraID].uEventID, 0, 1);
+                }
+LABEL_119:
+                v56 = v0->vVelocity.x;
+                v54 = 58500;
+                v56 = (unsigned __int64)(58500i64 * v56) >> 16;
+                v0->vVelocity.x = v56;
+                v56 = v0->vVelocity.y;
+                v56 = (unsigned __int64)(v54 * (signed __int64)v56) >> 16;
+                v54 = 58500;
+                v0->vVelocity.y = v56;
+                v56 = v0->vVelocity.z;
+                v56 = (unsigned __int64)(v54 * (signed __int64)v56) >> 16;
+                v22 = 0;
+                v0->vVelocity.z = v56;
+                goto LABEL_120;
+              }
+              if ( v0->GetActorsRelation(0) )
+              {
+                v51 = __OFSUB__(HIDWORD(pParty->pPartyBuffs[11].uExpireTime), v22);
+                v49 = HIDWORD(pParty->pPartyBuffs[11].uExpireTime) == v22;
+                v50 = HIDWORD(pParty->pPartyBuffs[11].uExpireTime) - v22 < 0;
+                v0->vVelocity.y = v22;
+                v0->vVelocity.x = v22;
+                if ( !(v50 ^ v51)
+                  && (!((unsigned __int8)(v50 ^ v51) | v49) || LODWORD(pParty->pPartyBuffs[11].uExpireTime) > v22) )
+                  pParty->pPartyBuffs[11].Reset();
+                viewparams->bRedrawGameUI = 1;
+                goto LABEL_119;
+              }
+              v36 = stru_721530.uFaceID;
+LABEL_118:
+              Actor::FaceObject(v63, v36, v22, (AIDirection *)v22);
+              goto LABEL_119;
+            }
+            if ( pParty->bTurnBasedModeOn == 1 && (pTurnEngine->field_4 == 2 || pTurnEngine->field_4 == 3) )
+              goto LABEL_119;
+            if ( v0->pMonsterInfo.uHostilityType )
+            {
+              if ( v56 == v22 )
+                goto LABEL_114;
+            }
+            else
+            {
+              if ( v56 == v22 )
+              {
+                if ( !pActors[v37].pMonsterInfo.uHostilityType )
+                  goto LABEL_118;
+LABEL_114:
+                Actor::_402968(v63, v36, v22, (AIDirection *)v22);
+                goto LABEL_119;
+              }
+            }
+            Actor::_403F58(v63, 4, v22, &v53);
+            goto LABEL_119;
+          }
+          if ( v0->vPosition.x & 1 )
+            v0->uYawAngle += 100;
+          else
+            v0->uYawAngle -= 100;
+        }
+        else
+        {
+          if ( pParty->bTurnBasedModeOn == 1 && (pTurnEngine->field_4 == 2 || pTurnEngine->field_4 == 3) )
+            goto LABEL_123;
+          if ( !v0->pMonsterInfo.uHostilityType || v56 != v22 )
+          {
+            Actor::_403F58(v63, 4, v22, &v52);
+            goto LABEL_123;
+          }
+        }
+      }
+LABEL_120:
+      ++uSectorID;
+      if ( uSectorID >= 100 )
+        goto LABEL_123;
+      v20 = stru_721530.prolly_normal_d;
+    }
+  }
+}
+// 46DF1A: using guessed type int __fastcall 46DF1A_collide_against_actor(int, int);
+// 4F75D8: using guessed type int ai_arrays_size;
+
+
+
+
+
+
+//----- (00460A78) --------------------------------------------------------
+void __thiscall PrepareToLoadBLV(unsigned int bLoading)
+{
+  unsigned int v1; // ebx@1
+  unsigned int v2; // eax@8
+  MapInfo *v3; // edi@9
+  int v4; // eax@11
+  int v5; // eax@12
+  int v6; // eax@13
+  int v7; // esi@27
+  SpawnPointMM7 *v8; // edx@28
+  //char v9; // bl@33
+  //int v10; // eax@34
+  //char *v11; // ecx@37
+  //int v12; // edi@44
+  //unsigned int v13; // edi@48
+  char *v14; // esi@49
+  __int16 v15; // ax@50
+  int v16; // ecx@52
+  DecorationDesc *v17; // eax@54
+  int v18; // ecx@55
+  //int *v19; // edi@58
+  //unsigned char v20; // dl@58
+  int v21; // eax@64
+  char v22; // cl@64
+  //signed int v23; // ebx@67
+  //char *v24; // esi@68
+  //int v25; // eax@70
+  //char *v26; // esi@78
+  //int v27; // eax@79
+  char v28; // zf@81
+  __int16 v29; // ax@85
+  signed int v30; // edi@94
+  int v31; // esi@94
+  char Args; // [sp+350h] [bp-C4h]@16
+  int v34[4]; // [sp+3E8h] [bp-2Ch]@96
+  int v35; // [sp+3F8h] [bp-1Ch]@1
+  //char b[4]; // [sp+3FCh] [bp-18h]@58
+  MapInfo *v37; // [sp+400h] [bp-14h]@1
+  int v38; // [sp+404h] [bp-10h]@1
+  unsigned int v39; // [sp+408h] [bp-Ch]@8
+  int pDest; // [sp+40Ch] [bp-8h]@1
+  //int i; // [sp+410h] [bp-4h]@27
+
+  v37 = (MapInfo *)bLoading;
+  v1 = 0;
+  v35 = 0;
+  pGameLoadingUI_ProgressBar->Reset(0x20u);
+  bUnderwater = 0;
+  bNoNPCHiring = 0;
+  v38 = 0;
+  pDest = 1;
+  uCurrentlyLoadedLevelType = LEVEL_Indoor;
+  pGame->uFlags2 &= 0xFFFFFFF7u;
+  if ( Is_out15odm_underwater() )
+  {
+    bUnderwater = 1;
+    pGame->uFlags2 |= 8u;
+  }
+  if ( !_strcmpi(pCurrentMapName, "out15.odm") || !_strcmpi(pCurrentMapName, "d23.blv") )
+    bNoNPCHiring = 1;
+  pPaletteManager->pPalette_tintColor[0] = 0;
+  pPaletteManager->pPalette_tintColor[1] = 0;
+  pPaletteManager->pPalette_tintColor[2] = 0;
+  pPaletteManager->RecalculateAll();
+  if ( qword_A750D8 )
+    qword_A750D8 = 0i64;
+  v2 = pMapStats->GetMapInfo(pCurrentMapName);
+  v39 = v2;
+  if ( v2 )
+  {
+    v3 = &pMapStats->pInfos[v2];
+    v1 = v3->uRespawnIntervalDays;
+    v38 = GetAlertStatus();
+  }
+  else
+  {
+    v3 = v37;
+  }
+  dword_6BE13C_uCurrentlyLoadedLocationID = v39;
+  pAllocator->FreeChunk(ptr_6A0D08);
+  ptr_6A0D08 = 0;
+  _6A0D0C_txt_lod_loading = 0;
+  TryLoadLevelFromLOD();
+  pStationaryLightsStack->uNumLightsActive = 0;
+  v4 = pIndoor->Load(
+         pCurrentMapName,
+         (unsigned int)(signed __int64)((double)pParty->uTimePlayed * 0.234375) / 60 / 60 / 24 + 1,
+         v1,
+         (char *)&pDest)
+     - 1;
+  if ( !v4 )
+  {
+    sprintf(&Args, "Unable to open %s", pCurrentMapName);
+    Abortf(&Args);
+  }
+  v5 = v4 - 1;
+  if ( !v5 )
+  {
+    sprintf(&Args, "File %s is not a BLV File", pCurrentMapName);
+    Abortf(&Args);
+  }
+  v6 = v5 - 1;
+  if ( !v6 )
+    Abortf("Attempt to open new level before clearing old");
+  if ( v6 == 1 )
+    Abortf("Out of memory loading indoor level");
+  if ( !(dword_6BE364_game_settings_1 & 0x2000) )
+  {
+    InitializeActors();
+    InitializeLayingItems();
+  }
+  BYTE1(dword_6BE364_game_settings_1) &= 0xDFu;
+  if ( !v39 )
+    pDest = 0;
+  if ( pDest == 1 )
+  {
+    v7 = 0;
+    for (uint i = 0; i < pIndoor->uNumSpawnPoints; ++v7 )
+    {
+      v8 = &pIndoor->pSpawnPoints[v7];
+      if ( pIndoor->pSpawnPoints[v7].uKind == 3 )
+        SpawnEncounter(v3, v8, 0, 0, 0);
+      else
+        v3->SpawnRandomTreasure(v8);
+      ++i;
+    }
+    RespawnGlobalDecorations();
+  }
+
+  pSoundList->LoadSound(pDoorSoundIDsByLocationID[v39], 0);
+  pSoundList->LoadSound(pDoorSoundIDsByLocationID[v39] + 1, 0);
+
+  for (uint i = 0; i < pIndoor->uNumDoors; ++i)
+  {
+    auto pDoor = pIndoor->pDoors + i;
+
+    if (pDoor->uAttributes & 0x01)
+    {
+      pDoor->uState = BLVDoor::Opening;
+      pDoor->uTimeSinceTriggered = 15360;
+      pDoor->uAttributes = 2;
+    }
+
+    if (pDoor->uState == BLVDoor::Closed)
+    {
+      pDoor->uState = BLVDoor::Closing;
+      pDoor->uTimeSinceTriggered = 15360;
+      pDoor->uAttributes = 2;
+    }
+    else if (pDoor->uState == BLVDoor::Open)
+    {
+      pDoor->uState = BLVDoor::Opening;
+      pDoor->uTimeSinceTriggered = 15360;
+      pDoor->uAttributes = 2;
+    }
+  }
+
+/*
+  i = 0;
+  v9 = 2;
+  if ( pIndoor->uNumDoors > 0 )
+  {
+    v10 = 0;
+    while ( 1 )
+    {
+      if ( pIndoor->pDoors[v10].uAttributes & 1 )
+      {
+        pIndoor->pDoors[v10].uState = 1;
+        pIndoor->pDoors[v10].uTimeSinceTriggered = 15360;
+        pIndoor->pDoors[v10].uAttributes = 2;
+      }
+      v11 = (char *)&pIndoor->pDoors[v10].uState;
+      if ( !*(short *)v11 )
+        break;
+      if ( *(short *)v11 == 2 )
+      {
+        *(short *)v11 = 1;
+        goto LABEL_41;
+      }
+LABEL_42:
+      ++i;
+      ++v10;
+      if ( i >= pIndoor->uNumDoors )
+        goto LABEL_43;
+    }
+    *(short *)v11 = 3;
+LABEL_41:
+    pIndoor->pDoors[v10].uTimeSinceTriggered = 15360;
+    pIndoor->pDoors[v10].uAttributes = 2;
+    goto LABEL_42;
+  }
+LABEL_43:
+*/
+
+  for (uint i = 0; i < pIndoor->uNumFaces; ++i)
+  {
+    auto pFace = pIndoor->pFaces + i;
+    if (!pFace->uBitmapID != -1)
+      pBitmaps_LOD->pTextures[pFace->uBitmapID].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[pFace->uBitmapID].palette_id1);
+ }
+
+  /*i = 0;
+  if ( (signed int)pIndoor->uNumFaces > 0 )
+  {
+    v12 = 0;
+    do
+    {
+      if ( pIndoor->pFaces[v12].uBitmapID != -1 )
+        pBitmaps_LOD->pTextures[pIndoor->pFaces[v12].uBitmapID].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[pIndoor->pFaces[v12].uBitmapID].palette_id1);
+      ++i;
+      ++v12;
+    }
+    while ( i < (signed int)pIndoor->uNumFaces );
+  }*/
+
+  
+  pGameLoadingUI_ProgressBar->Progress();
+  
+  for (uint i = 0; i < uNumLevelDecorations; ++i)
+  {
+    auto pDecortaion = pLevelDecorations + i;
+    
+    pDecorationList->InitializeDecorationSprite(pDecortaion->uDecorationDescID);
+
+    v15 = pDecorationList->pDecorations[pDecortaion->uDecorationDescID].uSoundID;
+    if (v15 && _6807E0_num_decorations_with_sounds_6807B8 < 9)
+    {
+        pSoundList->LoadSound(v15, 0);
+        v16 = _6807E0_num_decorations_with_sounds_6807B8++;
+        _6807B8_level_decorations_ids[v16] = i;
+    }
+
+    if ( !(pDecortaion->field_2 & 0x20) )
+    {
+      v17 = &pDecorationList->pDecorations[pDecortaion->uDecorationDescID];
+      if ( !((unsigned __int8)2 & v17->uFlags) )
+        {
+          v18 = v17->uLightRadius;
+          if ( v18 )
+          {
+            unsigned char r = 255,
+                          g = 255,
+                          b = 255;
+            if (pRenderer->pRenderD3D && pRenderer->bUseColoredLights)
+            {
+              r = v17->uColoredLightRed;
+              g = v17->uColoredLightGreen;
+              b = v17->uColoredLightBlue;
+            }
+            pStationaryLightsStack->AddLight(pDecortaion->vPosition.x,
+                                             pDecortaion->vPosition.y,
+                                             pDecortaion->vPosition.z + v17->uDecorationHeight,
+              v18,
+              r,
+              g,
+              b,
+              byte_4E94D0);
+          }
+        }
+      }
+
+      if (!pDecortaion->field_16_event_id)
+      {
+        if (pDecortaion->IsInteractive())
+        {
+          if ( v35 < 124 )
+          {
+            v21 = v35 + 1;
+            pDecortaion->_idx_in_stru123 = v35 + 75;
+            v22 = stru_5E4C90._decor_events[v21 + 74 - 75];
+            v35 = v21;
+            if ( !v22 )
+              pDecortaion->field_2 |= 0x20;
+          }
+        }
+      }
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  for (uint i = 0; i < uNumLayingItems; ++i)
+  {
+    auto p = pLayingItems + i;
+    if (p->uObjectDescID)
+    {
+      auto uItemID = p->stru_24.uItemID;
+      if (uItemID)
+      {
+        if (uItemID != 220 && pItemsTable->pItems[uItemID].uEquipType == EQUIP_POTION &&
+            !p->stru_24._bonus_type)
+          p->stru_24._bonus_type = rand() % 15 + 5;
+        pItemsTable->SetSpecialBonus(&p->stru_24);
+      }
+    }
+  }
+
+  for (uint i = 0; i < uNumActors; ++i)
+  //if ( (signed int)uNumActors > (signed int)v13 )
+  {
+    Actor *pActor = pActors + i;
+    //v26 = (char *)&pActors[0].uAttributes;
+    //do
+    //{
+      //v27 = *(int *)v26;
+      if (pActor->uAttributes & 0x100000)
+      {
+        if ( !v39 )
+        {
+          pActor->pMonsterInfo.field_3E = 19;
+          pActor->uAttributes |= 0x10000;
+          continue;
+        }
+        v28 = v38 == 0;
+      }
+      else
+      {
+        v28 = v38 == 1;
+      }
+
+      if ( !v28 )
+      {
+        pActor->PrepareSprites(0);
+        v29 = pActor->pMonsterInfo.field_3E;
+        pActor->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+        if ( v29 != 11 && v29 != 19 && (!pActor->sCurrentHP || !pActor->pMonsterInfo.uHP) )
+        {
+          pActor->pMonsterInfo.field_3E = 5;
+          pActor->UpdateAnimation();
+        }
+      }
+      else
+      {
+          pActor->pMonsterInfo.field_3E = 19;
+          pActor->uAttributes |= 0x10000;
+      }
+    //}
+    //while ( i < (signed int)uNumActors );
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  Actor this_;
+  this_.pMonsterInfo.uID = 45;
+  this_.PrepareSprites(0);
+  if ( !v37 )
+  {
+    pParty->sRotationX = 0;
+    pParty->sRotationY = 0;
+    pParty->vPosition.z = 0;
+    pParty->vPosition.y = 0;
+    pParty->vPosition.x = 0;
+    pParty->uFallStartY = 0;
+    pParty->uFallSpeed = 0;
+    TeleportToStartingPoint(uLevel_StartingPointType);
+  }
+  viewparams->_443365();
+  PlayLevelMusic();
+  if ( !v37 )
+  {
+    v30 = 0;
+    v31 = 1;
+    do
+    {
+      if ( pPlayers[v31]->CanAct() )
+        v34[v30++] = v31;
+      ++v31;
+    }
+    while ( v31 <= 4 );
+    if ( v30 )
+    {
+      if ( pDest )
+      {
+        qword_A750D8 = 256i64;
+        word_A750E0 = 46;
+        word_A750E2 = LOWORD(v34[rand() % v30]);
+      }
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Indoor.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,575 @@
+#pragma once
+#include "VectorTypes.h"
+#include "IndoorCameraD3D.h"
+
+
+
+
+/*  319 */
+enum LEVEL_TYPE
+{
+  LEVEL_null = 0,
+  LEVEL_Indoor = 0x1,
+  LEVEL_Outdoor = 0x2,
+};
+extern LEVEL_TYPE uCurrentlyLoadedLevelType;
+
+
+
+
+
+/*   74 */
+#pragma pack(push, 1)
+struct LevelDecoration
+{
+  LevelDecoration();
+  int GetGlobalEvent();
+  int IsInteractive();
+  bool _47A825();
+
+
+  unsigned __int16 uDecorationDescID;
+  __int16 field_2;
+  struct Vec3_int_ vPosition;
+  int field_10_y_rot;
+  __int16 uCog;
+  __int16 field_16_event_id;
+  __int16 field_18;
+  __int16 field_1A;
+  __int16 _idx_in_stru123;
+  __int16 field_1E;
+};
+#pragma pack(pop)
+extern LevelDecoration pLevelDecorations[3000];
+extern size_t uNumLevelDecorations;
+extern LevelDecoration *_5C3420_pDecoration;
+
+
+
+
+
+
+
+
+/*   86 */
+#pragma pack(push, 1)
+struct SpawnPointMM6
+{
+  Vec3_int_ vPosition;
+  unsigned __int16 uRadius;
+  unsigned __int16 uKind;
+  unsigned __int16 uIndex;
+  unsigned __int16 uAttributes;
+};
+#pragma pack(pop)
+
+
+
+/*  102 */
+#pragma pack(push, 1)
+struct SpawnPointMM7
+{
+  //----- (00448DD6) --------------------------------------------------------
+  SpawnPointMM7()
+  {
+    uRadius = 32;
+    uAttributes = 0;
+    uIndex = 0;
+    uKind = 0;
+    uGroup = 0;
+  }
+
+
+  Vec3_int_ vPosition;
+  unsigned __int16 uRadius;
+  unsigned __int16 uKind;
+  unsigned __int16 uIndex;
+  unsigned __int16 uAttributes;
+  unsigned int uGroup;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+
+#pragma pack(push, 1)
+struct DDM_DLV_Header
+{
+  //----- (00462607) --------------------------------------------------------
+  inline DDM_DLV_Header()
+  {
+    this->uLastRepawnDay = 0;
+    this->uNumRespawns = 0;
+    this->uReputation = 0;
+    this->field_C_alert = 0;
+    this->uNumFacesInBModels = 0;
+    this->uNumDecorations = 0;
+    this->uNumBModels = 0;
+  }
+
+
+  int uNumRespawns;
+  int uLastRepawnDay;
+  int uReputation;
+  int field_C_alert;
+  unsigned int uNumFacesInBModels;
+  unsigned int uNumDecorations;
+  unsigned int uNumBModels;
+  int field_1C;
+  int field_20;
+  int field_24;
+};
+#pragma pack(pop)
+
+
+
+/*  291 */
+enum PolygonType : __int8
+{
+  POLYGON_Invalid = 0x0,
+  POLYGON_VerticalWall = 0x1,
+  POLYGON_unk = 0x2,
+  POLYGON_Floor = 0x3,
+  POLYGON_InBetweenFloorAndWall = 0x4,
+  POLYGON_Ceiling = 0x5,
+  POLYGON_InBetweenCeilingAndWall = 0x6,
+};
+
+/*   90 */
+#pragma pack(push, 1)
+struct BLVHeader
+{
+  char field_0[104];
+  unsigned int uFaces_fdata_Size;
+  unsigned int uSector_rdata_Size;
+  unsigned int uSector_lrdata_Size;
+  unsigned int uDoors_ddata_Size;
+  char field_78[16];
+};
+#pragma pack(pop)
+
+
+
+/*   96 */
+#pragma pack(push, 1)
+struct BLVSectorMM8
+{
+  int dword_000074;
+};
+#pragma pack(pop)
+
+/*   97 */
+#pragma pack(push, 1)
+struct BLVLightMM6
+{
+  Vec3_short_ vPosition;
+  __int16 uRadius;
+  __int16 uAttributes;
+  unsigned __int16 uBrightness;
+};
+#pragma pack(pop)
+
+/*   98 */
+#pragma pack(push, 1)
+struct BLVLightMM7
+{
+  struct Vec3_short_ vPosition;
+  __int16 uRadius;
+  char uRed;
+  char uGreen;
+  char uBlue;
+  char uType;
+  __int16 uAtributes;           // & 0x08    doesn't light faces
+  __int16 uBrightness;
+};
+#pragma pack(pop)
+
+/*   99 */
+#pragma pack(push, 1)
+struct BLVLightMM8
+{
+  int uID;
+};
+#pragma pack(pop)
+
+
+
+/*  100 */
+#pragma pack(push, 1)
+struct BLVDoor
+{
+  enum State: unsigned __int16
+  {
+    Closed = 0,
+    Opening = 1,
+    Open = 2,
+    Closing = 3
+  };
+
+  unsigned int uAttributes;
+  unsigned int uDoorID;
+  unsigned int uTimeSinceTriggered;
+  Vec3_int_ vDirection;
+  int uMoveLength;
+  int uOpenSpeed;
+  int uCloseSpeed;
+  unsigned __int16 *pVertexIDs;
+  unsigned __int16 *pFaceIDs;
+  unsigned __int16 *pSectorIDs;
+  __int16 *pDeltaUs;
+  __int16 *pDeltaVs;
+  unsigned __int16 *pXOffsets;
+  unsigned __int16 *pYOffsets;
+  unsigned __int16 *pZOffsets;
+  unsigned __int16 uNumVertices;
+  unsigned __int16 uNumFaces;
+  __int16 field_48;
+  unsigned __int16 uNumOffsets;
+  State uState;
+  __int16 field_4E;
+};
+#pragma pack(pop)
+
+/*  101 */
+#pragma pack(push, 1)
+struct BLVMapOutline
+{
+  unsigned __int16 uVertex1ID;
+  unsigned __int16 uVertex2ID;
+  unsigned __int16 uFace1ID;
+  unsigned __int16 uFace2ID;
+  __int16 sZ;
+  unsigned __int16 uFlags;
+};
+#pragma pack(pop)
+
+
+#define FACE_TWO_SIDED        0x00000001 // portal/two-sided
+// 0x02  color is saturated against lights
+#define FACE_TEXTURE_ANIMATED 0x00000010 // like wavy water
+#define FACE_INVISIBLE        0x00002000
+#define FACE_TEXTURE_FRAME    0x00004000 // Texture ID is a frameset from TextureFrameTable, otherwise BitmapID
+#define FACE_TEXTURE_FLOW     0x00040000 // The texture moves slowly. For horizontal facets only.
+#define FACE_CLICKABLE        0x02000000 // Event can be triggered by clicking on the facet.
+#define FACE_PRESSURE_PLATE   0x04000000 // Event can be triggered by stepping on the facet.
+#define FACE_ETHEREAL         0x20000000 // Untouchable. You can pass through it.
+
+/*   93 */
+#pragma pack(push, 1)
+struct BLVFace
+{
+  //----- (0046ED02) --------------------------------------------------------
+  inline BLVFace()
+  {
+    this->uNumVertices = 0;
+    this->uAttributes = 0;
+    this->uFaceExtraID = 0;
+    this->pVertexIDs = 0;
+    this->pZInterceptDisplacements = 0;
+    this->pYInterceptDisplacements = 0;
+    this->pXInterceptDisplacements = 0;
+  }
+
+  char _get_normals(Vec3_int_ *a2, Vec3_int_ *a3);
+  struct Texture *GetTexture();
+  void FromODM(struct ODMFace *a2);
+
+  inline bool Invisible() const {return uAttributes & FACE_INVISIBLE;}
+  inline bool Visible() const   {return !Invisible();}
+  inline bool TwoSided() const  {return uAttributes & FACE_TWO_SIDED;}
+  inline bool Animated() const  {return uAttributes & FACE_TEXTURE_ANIMATED;}
+  inline bool Clickable() const {return uAttributes & FACE_CLICKABLE;}
+
+
+  struct Plane_float_ pFacePlane;
+  struct Plane_int_ pFacePlane_old;
+  int zCalc1;
+  int zCalc2;
+  int zCalc3;
+  unsigned int uAttributes;
+  unsigned __int16 *pVertexIDs;
+  unsigned __int16 *pXInterceptDisplacements;
+  unsigned __int16 *pYInterceptDisplacements;
+  unsigned __int16 *pZInterceptDisplacements;
+  signed __int16   *pVertexUIDs;
+  signed __int16   *pVertexVIDs;
+  unsigned __int16  uFaceExtraID;
+  unsigned __int16  uBitmapID;
+  unsigned __int16  uSectorID;
+  __int16 uBackSectorID;
+  struct BBox_short_ pBounding;
+  PolygonType uPolygonType;
+  unsigned __int8 uNumVertices;
+  char field_5E;
+  char field_5F;
+};
+#pragma pack(pop)
+
+/*   94 */
+#pragma pack(push, 1)
+struct BLVFaceExtra
+{
+  int HasEventint();
+
+  __int16 field_0;
+  __int16 field_2;
+  __int16 field_4;
+  __int16 field_6;
+  __int16 field_8;
+  __int16 field_A;
+  __int16 field_C;
+  unsigned __int16 uAdditionalBitmapID;
+  __int16 field_10;
+  __int16 field_12;
+  __int16 sTextureDeltaU;
+  __int16 sTextureDeltaV;
+  __int16 sCogNumber;
+  unsigned __int16 uEventID;
+  __int16 field_1C;
+  __int16 field_1E;
+  __int16 field_20;
+  __int16 field_22;
+};
+#pragma pack(pop)
+
+/*   95 */
+#pragma pack(push, 1)
+struct BLVSector
+{
+  int field_0;
+  unsigned __int16 uNumFloors;
+  __int16 field_6;
+  unsigned __int16 *pFloors;
+  __int16 field_C;
+  __int16 field_E;
+  unsigned __int16 *pWalls;
+  __int16 field_14;
+  __int16 field_16;
+  unsigned __int16 *pCeilings;
+  __int16 field_1C;
+  __int16 field_1E;
+  unsigned __int16 *pFluids;
+  __int16 uNumPortals;
+  __int16 field_26;
+  unsigned __int16 *pPortals;
+  __int16 field_2C;
+  __int16 uNumNonBSPFaces;
+  unsigned __int16 *pFaceIDs;
+  __int16 uNumCylinderFaces;
+  __int16 field_36;
+  int pCylinderFaces;
+  __int16 field_3C;
+  __int16 field_3E;
+  unsigned __int16 *pCogs;
+  unsigned __int16 uNumDecorations;
+  __int16 field_46;
+  unsigned __int16 *pDecorationIDs;
+  __int16 field_4C;
+  __int16 field_4E;
+  unsigned __int16 *pMarkers;
+  __int16 uNumLights;
+  __int16 field_56;
+  unsigned __int16 *pLights;
+  __int16 uWaterLevel;
+  __int16 uMistLevel;
+  __int16 uLightDistanceMultiplier;
+  __int16 uMinAmbientLightLevel;
+  __int16 uFirstBSPNode;
+  __int16 exit_tag;
+  BBox_short_ pBounding;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct BLVMapOutlines
+{
+  uint          uNumOutlines;
+  BLVMapOutline pOutlines[1];
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct IndoorLocation_stru1
+{
+  unsigned __int64 uLastVisitDay;
+  char field_2F4[48];
+};
+#pragma pack(pop)
+
+
+
+/*   89 */
+#pragma pack(push, 1)
+struct IndoorLocation
+{
+  //----- (00462592) --------------------------------------------------------
+  inline IndoorLocation()
+  {
+    bLoaded = 0;
+    ptr_0002B8_sector_lrdata = 0;
+    ptr_0002B4_doors_ddata = 0;
+    ptr_0002B0_sector_rdata = 0;
+    ptr_2AC = 0;
+    pVertices = 0;
+    pFaces = 0;
+    pFaceExtras = 0;
+    pSectors = 0;
+    pLights = 0;
+    pDoors = 0;
+    pNodes = 0;
+    pMapOutlines = 0;
+    uNumSpawnPoints = 0;
+    pSpawnPoints = 0;
+  }
+
+  int GetSector(int sX, int sY, int sZ);
+  void Release();
+  int Alloc();
+  bool Load(char *pFilename, int a3, size_t i, char *pDest);
+  void Draw();
+  void ToggleLight(unsigned int uLightID, unsigned int bToggle);
+
+  static unsigned int GetLocationIndex(const char *Str1);
+  static void ExecDraw(bool bD3D);
+  static void ExecDraw_sw(unsigned int uFaceID);
+  static void ExecDraw_d3d(unsigned int uFaceID, struct IndoorCameraD3D_Vec4 *pVertices, unsigned int uNumVertices, struct RenderVertexSoft *a4);
+
+  char pFilename[32];
+  char field_20[48];
+  unsigned int bLoaded;
+  char field_54[404];
+  struct BLVHeader blv;
+  unsigned int uNumVertices;
+  struct Vec3_short_ *pVertices;
+  unsigned int uNumFaces;
+  struct BLVFace *pFaces;
+  unsigned int uNumFaceExtras;
+  struct BLVFaceExtra *pFaceExtras;
+  int uNumSectors;
+  struct BLVSector *pSectors;
+  int uNumLights;
+  struct BLVLightMM7 *pLights;
+  int uNumDoors;
+  struct BLVDoor *pDoors;
+  unsigned int uNumNodes;
+  struct BSPNode *pNodes;
+  BLVMapOutlines *pMapOutlines;
+  unsigned __int16 *ptr_2AC;
+  unsigned __int16 *ptr_0002B0_sector_rdata;
+  unsigned __int16 *ptr_0002B4_doors_ddata;
+  unsigned __int16 *ptr_0002B8_sector_lrdata;
+  unsigned int uNumSpawnPoints;
+  struct SpawnPointMM7 *pSpawnPoints;
+  struct DDM_DLV_Header dlv;
+  IndoorLocation_stru1 stru1;
+  char _visible_outlines[876];
+};
+#pragma pack(pop)
+
+extern IndoorLocation *pIndoor;
+
+
+
+
+
+
+
+
+
+
+
+
+/*  263 */
+#pragma pack(push, 1)
+struct IndoorLocation_drawstru
+{
+  int field_0_timer;
+  int uFlags;
+  Vec3_int_ vPosition;
+  int sRotationY;
+  int sRotationX;
+  int field_1C_mb_fov;
+  unsigned __int16 *pRenderTarget;
+  unsigned int uTargetWidth;
+  unsigned int uTargetHeight;
+  unsigned int uViewportX;
+  unsigned int uViewportY;
+  unsigned int uViewportZ;
+  unsigned int uViewportW;
+  int field_3C;
+  int *pTargetZ;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+
+
+
+/*  162 */
+#pragma pack(push, 1)
+struct BLVRenderParams
+{
+  int Reset(struct IndoorLocation_drawstru *a2);
+
+  int field_0_timer_;
+  int uFlags;
+  Vec3_int_ vPartyPos;
+  int sPartyRotY;
+  int sPartyRotX;
+  int uPartySectorID;
+  int sCosineY;
+  int sSineY;
+  int sCosineNegX;
+  int sSineNegX;
+  float fCosineY;
+  float fSineY;
+  float fCosineNegX;
+  float fSineNegX;
+  int field_40;
+  float field_44;
+  unsigned __int16 *pRenderTarget;
+  unsigned int uTargetWidth;
+  unsigned int uTargetHeight;
+  unsigned int uViewportX;
+  unsigned int uViewportY;
+  unsigned int uViewportZ;
+  unsigned int uViewportW;
+  int field_64;
+  int *pTargetZBuffer;
+  int uViewportHeight;
+  int field_70;
+  int uViewportCenterX;
+  int uViewportCenterY;
+  struct BspRenderer_stru2 *field_7C;
+  unsigned int uNumFacesRenderedThisFrame;
+  int field_84;
+  int field_88;
+  int field_8C;
+  int field_90;
+  int field_94;
+};
+#pragma pack(pop)
+
+extern struct BLVRenderParams *pBLVRenderParams;
+
+
+
+
+
+#include "Indoor_stuff.h"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IndoorCamera.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,112 @@
+#include "IndoorCamera.h"
+#include "Render.h"
+#include "Game.h"
+#include "Indoor.h"
+#include "Math.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+IndoorCamera *pIndoorCamera; // idb
+
+
+
+
+
+//----- (00481CCE) --------------------------------------------------------
+float IndoorCamera::ViewTransform(RenderVertexSoft *a1)
+{
+  float result; // eax@1
+  double vCamToVertexZ; // st7@1
+  double v3; // st6@1
+  double v4; // st5@1
+  double v5; // st4@1
+  float v6; // ST04_4@3
+  float v7; // [sp+0h] [bp-14h]@1
+  float v8; // [sp+8h] [bp-Ch]@1
+  float vCamToVertexX; // [sp+Ch] [bp-8h]@1
+  float vCamToVertexY; // [sp+10h] [bp-4h]@1
+
+  v8 = fRotationXCosine;
+  result = fRotationXSine;
+  v7 = fRotationXSine;
+  vCamToVertexX = a1->vWorldPosition.x - (double)pos.x;
+  vCamToVertexY = a1->vWorldPosition.y - (double)pos.y;
+  vCamToVertexZ = a1->vWorldPosition.z - (double)pos.z;
+  v3 = fRotationYCosine;
+  v4 = fRotationYSine;
+  v5 = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+  if ( sRotationX )
+  {
+    v6 = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+    a1->vWorldViewPosition.x = v5 * fRotationXCosine + fRotationXSine * vCamToVertexZ;
+    a1->vWorldViewPosition.y = v3 * vCamToVertexY - v4 * vCamToVertexX;
+    a1->vWorldViewPosition.z = v8 * vCamToVertexZ - v6 * v7;
+  }
+  else
+  {
+    a1->vWorldViewPosition.x = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+    a1->vWorldViewPosition.y = v3 * vCamToVertexY - v4 * vCamToVertexX;
+    a1->vWorldViewPosition.z = vCamToVertexZ;
+  }
+  return result;
+}
+
+
+
+//----- (0042394D) --------------------------------------------------------
+void IndoorCamera::Initialize(int degFov, unsigned int uViewportWidth, unsigned int uViewportHeight)
+{
+  IndoorCamera *v4; // esi@1
+  double v5; // st7@1
+
+  v4 = this;
+  v5 = (double)(signed int)(signed __int64)((double)(signed int)uViewportWidth
+                                          * 0.5
+                                          / tan((double)(degFov >> 1) * 0.01745329)
+                                          + 0.5);
+  v4->flt_1C_fov = v5;
+  v4->flt_20_inv_1C = 65536.0 / v5;
+}
+
+//----- (004239A7) --------------------------------------------------------
+void IndoorCamera::Initialize2()
+{
+  //IndoorCamera *v1; // esi@1
+  double v2; // st7@4
+  //double v3; // st7@6
+  //int v4; // eax@6
+  //int v5; // eax@6
+  //int v6; // ST04_4@6
+  //int v7; // eax@6
+  //int v8; // ST04_4@6
+
+  //v1 = this;
+  fRotationYSine = sin((3.141592653589793 + 3.141592653589793) * (double)sRotationY * 0.00048828125);
+  fRotationYCosine = cos((3.141592653589793 + 3.141592653589793) * (double)sRotationY * 0.00048828125);
+  if ( byte_4D864C && pGame->uFlags & 0x80 || uCurrentlyLoadedLevelType == LEVEL_Indoor)
+  {
+    fRotationXSine = sin((3.141592653589793 + 3.141592653589793) * (double)-sRotationX * 0.00048828125);
+    v2 = (3.141592653589793 + 3.141592653589793) * (double)-sRotationX;
+  }
+  else
+  {
+    fRotationXSine = sin((3.141592653589793 + 3.141592653589793) * (double)sRotationX * 0.00048828125);
+    v2 = (3.141592653589793 + 3.141592653589793) * (double)sRotationX;
+  }
+  //v3 = cos(v2 * 0.00048828125);
+  //v4 = sRotationY;
+  fRotationXCosine = cos(v2 * 0.00048828125);
+  //v5 = stru_5C6E00->SinCos(sRotationY - stru_5C6E00->uIntegerHalfPi);
+  //v6 = sRotationY;
+  _int_sine = stru_5C6E00->SinCos(sRotationY - stru_5C6E00->uIntegerHalfPi);
+  _int_cosine = stru_5C6E00->SinCos(sRotationY);
+  //v7 = stru_5C6E00->SinCos(sRotationX - stru_5C6E00->uIntegerHalfPi);
+  //v8 = sRotationX;
+  _int_sine_2 = stru_5C6E00->SinCos(sRotationX - stru_5C6E00->uIntegerHalfPi);
+  _int_cosine_2 = stru_5C6E00->SinCos(sRotationX);
+}
+// 4D864C: using guessed type char byte_4D864C;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IndoorCamera.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,46 @@
+#pragma once
+#include "VectorTypes.h"
+
+/*  157 */
+#pragma pack(push, 1)
+struct IndoorCamera
+{
+  //----- (0042391F) --------------------------------------------------------
+  IndoorCamera()
+  {
+    sRotationX = 0;
+    sRotationY = 0;
+    flt_1C_fov = 2000.0f;
+    flt_20_inv_1C = 32.768002f;
+
+    field_4C = 0;
+  }
+  void Initialize(int degFov, unsigned int uViewportWidth, unsigned int uViewportHeight);
+  void Initialize2();
+  float ViewTransform(struct RenderVertexSoft *a1);
+
+
+  Vec3_int_ pos;
+  unsigned int uMapGridCellX;
+  unsigned int uMapGridCellZ;
+  int sRotationX;
+  int sRotationY;
+  float flt_1C_fov;
+  float flt_20_inv_1C;
+  int field_24;
+  int field_28;
+  float fRotationYSine;
+  float fRotationYCosine;
+  float fRotationXSine;
+  float fRotationXCosine;
+  int _int_sine;
+  int _int_cosine;
+  int _int_sine_2;
+  int _int_cosine_2;
+  int field_4C;
+};
+#pragma pack(pop)
+
+
+
+extern IndoorCamera *pIndoorCamera; // idb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IndoorCameraD3D.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1749 @@
+#include "IndoorCameraD3D.h"
+#include "VectorTypes.h"
+#include "Game.h"
+#include "Indoor.h"
+#include "Viewport.h"
+#include "IndoorCamera.h"
+#include "OutdoorCamera.h"
+#include "Render.h"
+#include "LOD.h"
+
+#include "mm7_data.h"
+
+
+
+//----- (004364C5) --------------------------------------------------------
+void IndoorCameraD3D::ViewTransfrom_OffsetUV(RenderVertexSoft *pVertices, unsigned int uNumVertices, RenderVertexSoft *pOutVertices, stru320 *a5)
+{
+  for (uint i = 0; i < uNumVertices; ++i)
+  {
+    pOutVertices[i].vWorldPosition.x = pVertices[i].vWorldPosition.x;
+    pOutVertices[i].vWorldPosition.y = pVertices[i].vWorldPosition.y;
+    pOutVertices[i].vWorldPosition.z = pVertices[i].vWorldPosition.z;
+
+    pOutVertices[i].u = pVertices[i].u + a5->pDeltaUV[0];
+    pOutVertices[i].v = pVertices[i].v + a5->pDeltaUV[1];
+  }
+  ViewTransform(pOutVertices, uNumVertices);
+}
+
+//----- (0043669D) --------------------------------------------------------
+char IndoorCameraD3D::ApplyViewTransform_TrueIfStillVisible(int x, int y, int z, signed int *pOutX, int *pOutZ, int *pOutY, char bDoNotShow)
+{
+  int to_z; // esi@2
+  int v9; // ecx@3
+  signed int *v10; // esi@5
+  int pOutY_; // ecx@5
+  signed int v12; // esi@7
+  int v14; // [sp+8h] [bp-4h]@3
+  int to_x; // [sp+14h] [bp+8h]@1
+  int to_y; // [sp+18h] [bp+Ch]@1
+  int a2b; // [sp+18h] [bp+Ch]@5
+  int a3a; // [sp+1Ch] [bp+10h]@5
+
+  to_x = (x - pBLVRenderParams->vPartyPos.x) << 16;
+  to_y = (y - pBLVRenderParams->vPartyPos.y) << 16;
+  if ( pBLVRenderParams->sPartyRotX )
+  {
+    to_z = (z - pBLVRenderParams->vPartyPos.z) << 16;
+    if ( pRenderer->pRenderD3D )
+    {
+      v14 = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+          + ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+      v9 = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+         - ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    }
+    else
+    {
+      v14 = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+          - ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+      v9 = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+         + ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    }
+    a3a = (z - pBLVRenderParams->vPartyPos.z) << 16;
+    a2b = (unsigned __int64)(to_z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+    v10 = pOutX;
+    *pOutX = ((unsigned __int64)(v14 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - a2b;
+    *pOutZ = v9;
+    pOutY_ = ((unsigned __int64)(v14 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+           + ((unsigned __int64)(a3a * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+  }
+  else
+  {
+    pOutY_ = (z - pBLVRenderParams->vPartyPos.z) << 16;
+    if ( pRenderer->pRenderD3D )
+    {
+      v10 = pOutX;
+      *pOutX = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+             + ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+      *pOutZ = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+             - ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    }
+    else
+    {
+      v10 = pOutX;
+      *pOutX = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+             - ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+      *pOutZ = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+             + ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    }
+  }
+  *pOutY = pOutY_;
+  return !bDoNotShow || (v12 = *v10, v12 >= (signed int)0x40000u) && v12 <= (signed int)0x1F400000u;
+}
+
+
+
+//----- (00436455) --------------------------------------------------------
+bool IndoorCameraD3D::IsCulled(BLVFace *pFace)
+{
+  RenderVertexSoft v; // [sp+8h] [bp-30h]@1
+
+  Vec3_short__to_RenderVertexSoft(&v, &pIndoor->pVertices[*pFace->pVertexIDs]);
+  return is_face_faced_to_camera(pFace, &v);
+}
+
+//----- (00436523) --------------------------------------------------------
+void IndoorCameraD3D::ViewTransform(RenderVertexSoft *a1a, unsigned int uNumVertices)
+{
+  if (byte_4D864C && pGame->uFlags & 0x80 ||
+      uCurrentlyLoadedLevelType == LEVEL_Indoor)
+  {
+    float sin_x = pIndoorCamera->fRotationXSine,
+          cos_x = pIndoorCamera->fRotationXCosine;
+    float sin_y = pIndoorCamera->fRotationYSine,
+          cos_y = pIndoorCamera->fRotationYCosine;
+
+    //v4 = uNumVertices;
+    //v7 = pIndoorCamera->fRotationXSine;
+    if ( pIndoorCamera->sRotationX )
+    {
+
+        //_EAX = a1a;
+    for (uint i = 0; i < uNumVertices; ++i)
+    {
+          float st0, st1, st2;
+          if ( pRenderer->pRenderD3D )
+          {
+            /*__asm
+            {
+              fld     [ebp+uNumVertices] // [(a1a[i].y - pIndoorCamera->pos.y)]   [(a1a[i].z - pIndoorCamera->pos.z)]   [pIndoorCamera->fRotationXCosine]   [pIndoorCamera->fRotationYSine]   [pIndoorCamera->fRotationYCosine]
+              fmul    st, st(3)          // [pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]   [(a1a[i].z - pIndoorCamera->pos.z)]   [pIndoorCamera->fRotationXCosine]   [pIndoorCamera->fRotationYSine]   [pIndoorCamera->fRotationYCosine]
+              fld     [ebp+a1]           // [(a1a[i].x - pIndoorCamera->pos.x)]   [pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]   [(a1a[i].z - pIndoorCamera->pos.z)]   [pIndoorCamera->fRotationXCosine]   [pIndoorCamera->fRotationYSine]   [pIndoorCamera->fRotationYCosine]
+              fmul    st, st(5)          // 0[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 1[pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 3[pIndoorCamera->fRotationXCosine]
+                                         // 4[pIndoorCamera->fRotationYSine]
+                                         // 5[pIndoorCamera->fRotationYCosine]
+              faddp   st(1), st          // [pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) + pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]   [(a1a[i].z - pIndoorCamera->pos.z)]   [pIndoorCamera->fRotationXCosine]   [pIndoorCamera->fRotationYSine]   [pIndoorCamera->fRotationYCosine]
+              fld     [ebp+a1]           // [(a1a[i].x - pIndoorCamera->pos.x)]   [pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) + pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]   [(a1a[i].z - pIndoorCamera->pos.z)]   [pIndoorCamera->fRotationXCosine]   [pIndoorCamera->fRotationYSine]   [pIndoorCamera->fRotationYCosine]
+              fmul    st, st(4)          // [pIndoorCamera->fRotationYSine * (a1a[i].x - pIndoorCamera->pos.x)]   [pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) + pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]   [(a1a[i].z - pIndoorCamera->pos.z)]   [pIndoorCamera->fRotationXCosine]   [pIndoorCamera->fRotationYSine]   [pIndoorCamera->fRotationYCosine]
+
+              fld     [ebp+uNumVertices] // 0[a1a[i].y - pIndoorCamera->pos.y]
+                                         // 1[pIndoorCamera->fRotationYSine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 2[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) + pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 3[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 4[pIndoorCamera->fRotationXCosine]
+                                         // 5[pIndoorCamera->fRotationYSine]
+                                         // 6[pIndoorCamera->fRotationYCosine]
+
+              fmul    st, st(6)          // 0[pIndoorCamera->fRotationYCosine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 1[pIndoorCamera->fRotationYSine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 2[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) + pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 3[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 4[pIndoorCamera->fRotationXCosine]
+                                         // 5[pIndoorCamera->fRotationYSine]
+                                         // 6[pIndoorCamera->fRotationYCosine]
+
+              fsubp   st(1), st          // 0[pIndoorCamera->fRotationYSine * (a1a[i].x - pIndoorCamera->pos.x) - pIndoorCamera->fRotationYCosine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 1[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) + pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 3[pIndoorCamera->fRotationXCosine]
+                                         // 4[pIndoorCamera->fRotationYSine]
+                                         // 5[pIndoorCamera->fRotationYCosine]
+            }*/
+            st0 = sin_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) - cos_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
+            st1 = cos_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) + sin_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
+            st2 = (a1a[i].vWorldPosition.z - pIndoorCamera->pos.z);
+          }
+          else
+          {
+            /*__asm
+            {
+              fld     [ebp+a1]           // 0[(a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 2[pIndoorCamera->fRotationXCosine]
+                                         // 3[pIndoorCamera->fRotationYSine]
+                                         // 4[pIndoorCamera->fRotationYCosine]
+              fmul    st, st(4)          // 0[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 2[pIndoorCamera->fRotationXCosine]
+                                         // 3[pIndoorCamera->fRotationYSine]
+                                         // 4[pIndoorCamera->fRotationYCosine]
+              fld     [ebp+uNumVertices] // 0[(a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 1[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 3[pIndoorCamera->fRotationXCosine]
+                                         // 4[pIndoorCamera->fRotationYSine]
+                                         // 5[pIndoorCamera->fRotationYCosine]
+              fmul    st, st(4)          // 0[pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 1[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 3[pIndoorCamera->fRotationXCosine]
+                                         // 4[pIndoorCamera->fRotationYSine]
+                                         // 5[pIndoorCamera->fRotationYCosine]
+              fsubp   st(1), st          // 0[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) - pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 2[pIndoorCamera->fRotationXCosine]
+                                         // 3[pIndoorCamera->fRotationYSine]
+                                         // 4[pIndoorCamera->fRotationYCosine]
+              fld     [ebp+a1]           // 0[(a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 1[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) - pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 3[pIndoorCamera->fRotationXCosine]
+                                         // 4[pIndoorCamera->fRotationYSine]
+                                         // 5[pIndoorCamera->fRotationYCosine]
+              fmul    st, st(4)          // 0[pIndoorCamera->fRotationYSine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 1[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) - pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 3[pIndoorCamera->fRotationXCosine]
+                                         // 4[pIndoorCamera->fRotationYSine]
+                                         // 5[pIndoorCamera->fRotationYCosine]
+              fld     [ebp+uNumVertices] // 0[(a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 1[pIndoorCamera->fRotationYSine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 2[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) - pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 3[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 4[pIndoorCamera->fRotationXCosine]
+                                         // 5[pIndoorCamera->fRotationYSine]
+                                         // 6[pIndoorCamera->fRotationYCosine]
+              fmul    st, st(6)          // 0[pIndoorCamera->fRotationYCosine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 1[pIndoorCamera->fRotationYSine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 2[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) - pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 3[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 4[pIndoorCamera->fRotationXCosine]
+                                         // 5[pIndoorCamera->fRotationYSine]
+                                         // 6[pIndoorCamera->fRotationYCosine]
+              faddp   st(1), st          // 0[pIndoorCamera->fRotationYCosine * (a1a[i].y - pIndoorCamera->pos.y) + pIndoorCamera->fRotationYSine * (a1a[i].x - pIndoorCamera->pos.x)]
+                                         // 1[pIndoorCamera->fRotationYCosine * (a1a[i].x - pIndoorCamera->pos.x) - pIndoorCamera->fRotationYSine * (a1a[i].y - pIndoorCamera->pos.y)]
+                                         // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                         // 3[pIndoorCamera->fRotationXCosine]
+                                         // 4[pIndoorCamera->fRotationYSine]
+                                         // 5[pIndoorCamera->fRotationYCosine]
+            }*/
+            st0 = cos_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y) + sin_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x);
+            st1 = cos_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) - sin_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
+            st2 = (a1a[i].vWorldPosition.z - pIndoorCamera->pos.z);
+          }
+
+          a1a[i].vWorldViewPosition.x = st1*cos_x - st2*sin_x;
+          a1a[i].vWorldViewPosition.y = st0;
+          a1a[i].vWorldViewPosition.z = st2*cos_x + st1*sin_x;
+      }
+    }
+    else
+    {
+      for (uint i = 0; i < uNumVertices; ++i)
+      {
+          if ( pRenderer->pRenderD3D )
+          {
+            /*__asm
+            {
+              fld     [ebp+uNumVertices]   // 0[(a1a[i].y - pIndoorCamera->pos.y)]
+                                           // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 2[sin_y]
+                                           // 3[cos_y]
+              fmul    st, st(2)            // 0[sin_y * (a1a[i].y - pIndoorCamera->pos.y)]
+                                           // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 2[sin_y]
+                                           // 3[cos_y]
+              fld     [ebp+a1]             // 0[(a1a[i].x - pIndoorCamera->pos.x)]
+                                           // 1[sin_y * (a1a[i].y - pIndoorCamera->pos.y)]
+                                           // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 3[sin_y]
+                                           // 4[cos_y]
+              fmul    st, st(4)            // 0[cos_y * (a1a[i].x - pIndoorCamera->pos.x)]
+                                           // 1[sin_y * (a1a[i].y - pIndoorCamera->pos.y)]
+                                           // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 3[sin_y]
+                                           // 4[cos_y]
+              faddp   st(1), st            // 0[cos_y * (a1a[i].x - pIndoorCamera->pos.x) + sin_y * (a1a[i].y - pIndoorCamera->pos.y)]
+                                           // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 2[sin_y]
+                                           // 3[cos_y]
+              fstp    dword ptr [eax+0Ch]
+              fld     [ebp+a1]             // 0[(a1a[i].x - pIndoorCamera->pos.x)]
+                                           // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 2[sin_y]
+                                           // 3[cos_y]
+              fmul    st, st(2)            // 0[sin_y * (a1a[i].x - pIndoorCamera->pos.x)]
+                                           // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 2[sin_y]
+                                           // 3[cos_y]
+              fld     [ebp+uNumVertices]   // 0[(a1a[i].y - pIndoorCamera->pos.y)]
+                                           // 1[sin_y * (a1a[i].x - pIndoorCamera->pos.x)]
+                                           // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 3[sin_y]
+                                           // 4[cos_y]
+              fmul    st, st(4)            // 0[cos_y * (a1a[i].y - pIndoorCamera->pos.y)]
+                                           // 1[sin_y * (a1a[i].x - pIndoorCamera->pos.x)]
+                                           // 2[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 3[sin_y]
+                                           // 4[cos_y]
+              fsubp   st(1), st            // 0[sin_y * (a1a[i].x - pIndoorCamera->pos.x) - cos_y * (a1a[i].y - pIndoorCamera->pos.y)]
+                                           // 1[(a1a[i].z - pIndoorCamera->pos.z)]
+                                           // 2[sin_y]
+                                           // 3[cos_y]
+              fstp    dword ptr [eax+10h]
+              fstp    dword ptr [eax+14h]
+            }*/
+            a1a[i].vWorldViewPosition.x = cos_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) + sin_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
+            a1a[i].vWorldViewPosition.y = sin_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) - cos_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
+            a1a[i].vWorldViewPosition.z = (a1a[i].vWorldPosition.z - pIndoorCamera->pos.z);
+          }
+          else
+          {
+            __debugbreak();
+            /*__asm
+            {
+              fld     [ebp+a1]
+              fmul    st, st(3)
+              fld     [ebp+uNumVertices]
+              fmul    st, st(3)
+              fsubp   st(1), st
+              fstp    dword ptr [eax+0Ch]
+              fld     [ebp+a1]
+              fmul    st, st(2)
+              fld     [ebp+uNumVertices]
+              fmul    st, st(4)
+              faddp   st(1), st
+
+              fstp    dword ptr [eax+10h]
+              fstp    dword ptr [eax+14h]
+            }*/
+          }
+      }
+    }
+  }
+  else for (uint i = 0; i < uNumVertices; ++i)
+    pIndoorCamera->ViewTransform(a1a + i);
+}
+
+
+//----- (00436932) --------------------------------------------------------
+bool IndoorCameraD3D::GetFacetOrientation(char polyType, Vec3_float_ *a2, Vec3_float_ *a3, Vec3_float_ *a4)
+{
+  switch ((PolygonType)polyType)
+  {
+    case POLYGON_VerticalWall:
+    {
+      a4->x = -a2->y;
+      a4->y = a2->x;
+      a4->z = 0.0;
+
+      a3->x = 0.0;
+      a3->y = 0.0;
+      a3->z = 1.0f;
+    }
+    return true;
+
+    case POLYGON_Floor:
+    case POLYGON_Ceiling:
+    {
+      a4->x = 1.0;
+      a4->y = 0.0;
+      a4->z = 0.0;
+
+      a3->x = 0.0;
+      a3->y = 1.0;
+      a3->z = 0.0;
+    }
+    return true;
+
+    case POLYGON_InBetweenFloorAndWall:
+    case POLYGON_InBetweenCeilingAndWall:
+    {
+      if (fabs(a2->z) < 0.70811361)
+      {
+        a4->x = -a2->y;
+        a4->y = a2->x;
+        a4->z = 0.0;
+        a4->Normalize();
+
+        a3->x = 0.0;
+        a3->y = 0.0;
+        a3->z = 1.0;
+      }
+      else
+      {
+        a4->x = 1.0;
+        a4->y = 0.0;
+        a4->z = 0.0;
+
+        a3->x = 0.0;
+        a3->y = 1.0;
+        a3->z = 0.0;
+      }
+    }
+    return true;
+
+    default:
+      return false;
+  }
+}
+
+
+//----- (00438258) --------------------------------------------------------
+bool IndoorCameraD3D::is_face_faced_to_camera(BLVFace *pFace, RenderVertexSoft *a2)
+{
+  if (pFace->TwoSided())
+    return false;
+
+  //really strange cull; dot(to_cam, normal) < 0 means we see the BACK face, not font %_%
+  if ( (a2->vWorldPosition.z - (double)pIndoorCamera->pos.z) * (double)pFace->pFacePlane_old.vNormal.z
+     + (a2->vWorldPosition.y - (double)pIndoorCamera->pos.y) * (double)pFace->pFacePlane_old.vNormal.y
+     + (a2->vWorldPosition.x - (double)pIndoorCamera->pos.x) * (double)pFace->pFacePlane_old.vNormal.x < 0.0)
+    return false;
+
+  return true;
+}
+
+//----- (00438250) --------------------------------------------------------
+void IndoorCameraD3D::Reset_list_0037C()
+{
+  this->list_0037C_size = 0;
+}
+
+
+//----- (00438240) --------------------------------------------------------
+void IndoorCameraD3D::_438240_draw_lits()
+{
+  IndoorCameraD3D *v1; // ebp@1
+  int v2; // edi@2
+  int v3; // ebx@3
+  int v4; // esi@4
+  double v5; // st7@6
+  float v6; // ST00_4@8
+  IndoorCameraD3D *v7; // esi@1
+  float v8; // [sp+4h] [bp-28h]@6
+  float v9; // [sp+8h] [bp-24h]@6
+  unsigned int v10; // [sp+Ch] [bp-20h]@6
+  char v11; // [sp+10h] [bp-1Ch]@6
+  float v12; // [sp+14h] [bp-18h]@6
+  int v13; // [sp+28h] [bp-4h]@1
+
+  v7 = this;
+  _438141_draw_list_0037C();
+  v13 = 0;
+  v1 = v7;
+  if ( v7->list_E0380_size > 0 )
+  {
+    v2 = (int)&v7->list_E0380[0].field_C04;
+    do
+    {
+      v3 = 0;
+      if ( *(int *)v2 > 0 )
+      {
+        v4 = v2 - 3048;
+        do
+        {
+          if ( *(char *)(v2 - 3076) & 1 )
+          {
+            LODWORD(v12) = 1;
+            v11 = 1;
+            v10 = *(int *)(v2 + 4);
+            v9 = 0.0;
+            v8 = *(float *)(v4 + 4);
+            v5 = *(float *)v4;
+          }
+          else
+          {
+            LODWORD(v12) = 0;
+            v11 = 1;
+            v10 = *(int *)(v2 + 4);
+            v9 = *(float *)(v4 - 16);
+            v8 = *(float *)(v4 - 20);
+            v5 = *(float *)(v4 - 24);
+          }
+          v6 = v5;
+          _437D4A_draw_some_vertices(v6, v8, v9, v10, v11, v12);
+          ++v3;
+          v4 += 48;
+        }
+        while ( v3 < *(int *)v2 );
+      }
+      ++v13;
+      v2 += 3088;
+    }
+    while ( v13 < v1->list_E0380_size );
+  }
+}
+
+
+//----- (00438141) --------------------------------------------------------
+void IndoorCameraD3D::_438141_draw_list_0037C()
+{
+  IndoorCameraD3D *v1; // edi@1
+  signed int v2; // ebx@1
+  char *v3; // esi@2
+  double v4; // st7@4
+  float v5; // ST00_4@6
+  float v6; // [sp+4h] [bp-20h]@4
+  float v7; // [sp+8h] [bp-1Ch]@4
+  unsigned int v8; // [sp+Ch] [bp-18h]@4
+  char v9; // [sp+10h] [bp-14h]@4
+  float v10; // [sp+14h] [bp-10h]@4
+
+  v1 = this;
+  v2 = 0;
+  if ( (signed int)this->list_0037C_size > 0 )
+  {
+    v3 = (char *)&this->list_0037C[0].field_20;
+    do
+    {
+      if ( *(v3 - 32) & 1 )
+      {
+        LODWORD(v10) = 1;
+        v9 = 1;
+        v8 = *((int *)v3 + 5);
+        v7 = 0.0;
+        v6 = *(float *)v3;
+        v4 = *((float *)v3 - 1);
+      }
+      else
+      {
+        LODWORD(v10) = 0;
+        v9 = 1;
+        v8 = *((int *)v3 + 5);
+        v7 = *((float *)v3 - 5);
+        v6 = *((float *)v3 - 6);
+        v4 = *((float *)v3 - 7);
+      }
+      v5 = v4;
+      _437D4A_draw_some_vertices(v5, v6, v7, v8, v9, v10);
+      ++v2;
+      v3 += 56;
+    }
+    while ( v2 < (signed int)v1->list_0037C_size );
+  }
+}
+
+
+//----- (00437D4A) --------------------------------------------------------
+void IndoorCameraD3D::_437D4A_draw_some_vertices(float x, float y, float z, unsigned int a5, char a6, float a7)
+{
+  IndoorCameraD3D *v7; // edx@1
+  char *v8; // eax@1
+  signed int v9; // ecx@1
+  signed int v10; // edx@10
+  char *v11; // ecx@10
+  signed int uNumD3DVertices; // edi@16
+  char *v13; // ecx@24
+  unsigned int v14; // edx@25
+  unsigned int v15; // eax@25
+  int v16; // ebx@25
+  int v17; // eax@26
+  int v18; // edx@26
+  IDirect3DDevice3 *v19; // ST24_4@27
+  HRESULT v20; // eax@27
+  RenderVertexSoft vert[20]; // [sp+0h] [bp-680h]@1
+  RenderVertexD3D3 pD3DVertices[5]; // [sp+3C0h] [bp-2C0h]@15
+  RenderVertexSoft a1; // [sp+640h] [bp-40h]@1
+  //double v24; // [sp+670h] [bp-10h]@25
+  //double v25; // [sp+678h] [bp-8h]@1
+
+  v7 = this;
+  a1.flt_2C = 0.0;
+  //HIDWORD(v25) = (int)this;
+  v8 = (char *)&vert[0].flt_2C;
+  v9 = 20;
+  do
+  {
+    *(float *)v8 = 0.0;
+    v8 += 48;
+    --v9;
+  }
+  while ( v9 );
+  if ( LOBYTE(a7) )
+  {
+    vert[0].vWorldViewProjX = x;
+    vert[0].vWorldViewProjY = y;
+    goto LABEL_15;
+  }
+  a1.vWorldPosition.x = x;
+  a1.vWorldPosition.y = y;
+  a1.vWorldPosition.z = z;
+  if ( pRenderer->pRenderD3D )
+  {
+    LODWORD(a7) = 1;
+    if ( v7->_437285_prolly_colide_vertices_against_frustrum(
+           &a1,
+           (unsigned int *)&a7,
+           vert,
+           v7->std__vector_000034_prolly_frustrum,
+           4,
+           1,
+           0) == 1
+      && SLODWORD(a7) < 1 )
+      return;
+  }
+  else
+  {
+    vert[0].vWorldPosition.x = x;
+    vert[0].vWorldPosition.y = y;
+    vert[0].vWorldPosition.z = z;
+  }
+  ViewTransform(vert, 1u);
+  v10 = 0;
+  v11 = (char *)&vert[0].vWorldViewPosition;
+  do
+  {
+    if ( *(float *)v11 >= 8.0 )
+      break;
+    ++v10;
+    v11 += 48;
+  }
+  while ( v10 < 1 );
+  if ( v10 < 1 )
+  {
+    Project(vert, 1u, 0);
+LABEL_15:
+    pD3DVertices[0].pos.x = vert[0].vWorldViewProjX;
+    pD3DVertices[0].pos.y = vert[0].vWorldViewProjY;
+    pD3DVertices[0].specular = 0;
+    pD3DVertices[0].diffuse = a5;
+    if ( a6 )
+    {
+      pD3DVertices[0].pos.z = 0.000099999997;
+      pD3DVertices[1].pos.x = vert[0].vWorldViewProjX;
+      pD3DVertices[2].pos.x = vert[0].vWorldViewProjX;
+      pD3DVertices[0].rhw = 0.001;
+      uNumD3DVertices = 5;
+      pD3DVertices[0].texcoord.x = 0.0;
+      pD3DVertices[1].diffuse = a5;
+      pD3DVertices[1].specular = 0;
+      pD3DVertices[0].texcoord.y = 0.0;
+      pD3DVertices[2].diffuse = a5;
+      pD3DVertices[2].specular = 0;
+      pD3DVertices[3].pos.y = vert[0].vWorldViewProjY;
+      pD3DVertices[3].diffuse = a5;
+      pD3DVertices[3].specular = 0;
+      pD3DVertices[4].pos.y = vert[0].vWorldViewProjY;
+      pD3DVertices[1].pos.y = vert[0].vWorldViewProjY - 1.0;
+      pD3DVertices[4].diffuse = a5;
+      pD3DVertices[4].specular = 0;
+      pD3DVertices[1].pos.z = 0.000099999997;
+      pD3DVertices[1].rhw = 0.001;
+      pD3DVertices[1].texcoord.x = 0.0;
+      pD3DVertices[1].texcoord.y = 0.0;
+      pD3DVertices[2].pos.y = vert[0].vWorldViewProjY + 1.0;
+      pD3DVertices[2].pos.z = 0.000099999997;
+      pD3DVertices[2].rhw = 0.001;
+      pD3DVertices[2].texcoord.x = 0.0;
+      pD3DVertices[2].texcoord.y = 0.0;
+      pD3DVertices[3].pos.x = vert[0].vWorldViewProjX - 1.0;
+      pD3DVertices[3].pos.z = 0.000099999997;
+      pD3DVertices[3].rhw = 0.001;
+      pD3DVertices[3].texcoord.x = 0.0;
+      pD3DVertices[3].texcoord.y = 0.0;
+      pD3DVertices[4].pos.x = vert[0].vWorldViewProjX + 1.0;
+      pD3DVertices[4].pos.z = 0.000099999997;
+      pD3DVertices[4].rhw = 0.001;
+      pD3DVertices[4].texcoord.x = 0.0;
+      pD3DVertices[4].texcoord.y = 0.0;
+    }
+    else
+    {
+      uNumD3DVertices = 1;
+      __debugbreak(); // make things right
+      *(unsigned int *)(&pD3DVertices[0].pos.z) = 0x38D1B717u;
+      pD3DVertices[0].texcoord.x = 0.0;
+      *(unsigned int *)(&pD3DVertices[0].rhw) = 0x3A83126Fu;
+      pD3DVertices[0].texcoord.y = 0.0;
+    }
+    if ( pRenderer->pRenderD3D )
+    {
+      __debugbreak(); // decompilation bug
+      //v19 = pRenderer->pRenderD3D->pDevice;
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, nullptr));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_POINTLIST,
+              D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+              pD3DVertices,
+              uNumD3DVertices,
+              16));
+    }
+    else
+    {
+      if ( (double)(signed int)pViewport->uViewportX <= vert[0].vWorldViewProjX - 1.0
+        && (double)(signed int)pViewport->uViewportZ > vert[0].vWorldViewProjX + 2.0
+        && (double)(signed int)pViewport->uViewportY <= vert[0].vWorldViewProjY - 1.0
+        && (double)(signed int)pViewport->uViewportW > vert[0].vWorldViewProjY + 2.0
+        && uNumD3DVertices > 0 )
+      {
+        v13 = (char *)&pD3DVertices[0].diffuse;
+        do
+        {
+          LODWORD(a7) = *((int *)v13 - 3);
+          //v25 = a7 + 6.7553994e15;
+          auto _v25 = floorf(a7 + 0.5f);
+
+          //v24 = *((float *)v13 - 4) + 6.7553994e15;
+          auto _v24 = floorf(*((float *)v13 - 4) + 0.5f);
+
+          v14 = *(int *)v13;
+          v15 = *(int *)v13;
+          v16 = (*(int *)v13 >> 3) & 0x1F;
+          if ( pRenderer->uTargetGBits == 5 )
+          {
+            v17 = (v15 >> 6) & 0x3E0;
+            v18 = (v14 >> 9) & 0x7C00;
+          }
+          else
+          {
+            v17 = (v15 >> 5) & 0x7E0;
+            v18 = (v14 >> 8) & 0xF800;
+          }
+          v13 += 32;
+          --uNumD3DVertices;
+          pRenderer->pTargetSurface[(uint)_v24 + pRenderer->uTargetSurfacePitch * (uint)_v25] = v18 | v16 | (unsigned __int16)v17;
+        }
+        while ( uNumD3DVertices );
+      }
+    }
+  }
+}
+
+
+//----- (00437C96) --------------------------------------------------------
+void IndoorCameraD3D::do_draw_debug_line_d3d(const RenderVertexD3D3 *pLineBegin, unsigned int uDiffuseBegin, const RenderVertexD3D3 *pLineEnd, unsigned int uDiffuseEnd, float z_stuff)
+{
+  double v6; // st7@2
+  IDirect3DDevice3 *v7; // eax@2
+  HRESULT v8; // eax@2
+  std::string v9; // [sp-18h] [bp-60h]@3
+  const char *v10; // [sp-Ch] [bp-54h]@2
+  const char *v11; // [sp-8h] [bp-50h]@2
+  int v12; // [sp-4h] [bp-4Ch]@2
+  RenderVertexD3D3 v13[2]; // [sp+8h] [bp-40h]@2
+
+  if ( pRenderer->pRenderD3D )
+  {
+    v6 = 0.001 - z_stuff;
+    memcpy(v13, pLineBegin, 0x20u);
+    memcpy(&v13[1], pLineEnd, sizeof(v13[1]));
+    v13[0].pos.z = v6;
+    v13[1].pos.z = v6;
+    v12 = 0;
+    v13[0].diffuse = uDiffuseBegin;
+    v13[1].diffuse = uDiffuseEnd;
+    v7 = pRenderer->pRenderD3D->pDevice;
+    v11 = 0;
+    //v10 = (const char *)v7;
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, nullptr));
+    ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(
+           D3DPT_LINELIST,
+           452,
+           v13,
+           2,
+           16));
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"draw_debug_line() not implemented for SW rendering", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Core3D.cpp:1415", 0);
+  }
+}
+
+//----- (00437AB5) --------------------------------------------------------
+void IndoorCameraD3D::do_draw_debug_line_sw(RenderVertexSoft *pLineBegin, unsigned int uStartDiffuse, RenderVertexSoft *pLineEnd, unsigned int uEndDiffuse, unsigned int uOutNumVertices, float z_stuff)
+{
+  char *v7; // eax@2
+  signed int v8; // edx@2
+  float v9; // ecx@5
+  float v10; // eax@5
+  char *v11; // eax@6
+  signed int v12; // edx@6
+  float v13; // edx@8
+  float v14; // eax@8
+  float v15; // eax@8
+  double v16; // st7@11
+  HRESULT v17; // eax@11
+  std::string v18; // [sp-18h] [bp-7E4h]@12
+  IDirect3DDevice3 *v19; // [sp-Ch] [bp-7D8h]@8
+  const char *v20; // [sp-8h] [bp-7D4h]@8
+  int v21; // [sp-4h] [bp-7D0h]@8
+  RenderVertexSoft a1[20]; // [sp+8h] [bp-7C4h]@6
+  RenderVertexSoft pVertices[20]; // [sp+3C8h] [bp-404h]@2
+  RenderVertexD3D3 v24[2]; // [sp+788h] [bp-44h]@11
+  IndoorCameraD3D *v25; // [sp+7C8h] [bp-4h]@1
+
+  v25 = this;
+  if ( pRenderer->pRenderD3D )
+  {
+    v7 = (char *)&pVertices[0].flt_2C;
+    v8 = 20;
+    do
+    {
+      *(float *)v7 = 0.0;
+      v7 += 48;
+      --v8;
+    }
+    while ( v8 );
+    if ( (char)uOutNumVertices )
+    {
+      v9 = pLineBegin->vWorldViewProjX;
+      pVertices[0].vWorldViewProjY = pLineBegin->vWorldViewProjY;
+      pVertices[0].vWorldViewProjX = v9;
+      v10 = pLineEnd->vWorldViewProjY;
+      pVertices[1].vWorldViewProjX = pLineEnd->vWorldViewProjX;
+      pVertices[1].vWorldViewProjY = v10;
+LABEL_11:
+      v16 = 0.001 - z_stuff;
+      v24[0].specular = 0;
+      v24[0].pos.x = pVertices[0].vWorldViewProjX;
+      v24[0].pos.y = pVertices[0].vWorldViewProjY;
+      v24[0].pos.z = v16;
+      v24[0].diffuse = uStartDiffuse;
+      v24[0].rhw = 0.001;
+      v24[1].pos.x = pVertices[1].vWorldViewProjX;
+      v24[0].texcoord.x = 0.0;
+      v24[1].pos.y = pVertices[1].vWorldViewProjY;
+      v24[0].texcoord.y = 0.0;
+      v24[1].diffuse = uEndDiffuse;
+      v24[1].pos.z = v16;
+      v24[1].specular = 0;
+      v21 = 0;
+      v24[1].rhw = 0.001;
+      v20 = 0;
+      v24[1].texcoord.x = 0.0;
+      v24[1].texcoord.y = 0.0;
+      //v19 = pRenderer->pRenderD3D->pDevice;
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, nullptr));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(
+              D3DPT_LINELIST,
+              D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+              v24,
+              2,
+              16));
+      return;
+    }
+    v11 = (char *)&a1[0].flt_2C;
+    v12 = 20;
+    do
+    {
+      *(float *)v11 = 0.0;
+      v11 += 48;
+      --v12;
+    }
+    while ( v12 );
+    v21 = 0;
+    v20 = (const char *)1;
+    v19 = (IDirect3DDevice3 *)4;
+    v13 = pLineBegin->vWorldPosition.x;
+    uOutNumVertices = 2;
+    a1[0].vWorldPosition.x = v13;
+    v14 = pLineBegin->vWorldPosition.z;
+    a1[0].vWorldPosition.y = pLineBegin->vWorldPosition.y;
+    a1[0].vWorldPosition.z = v14;
+    a1[1].vWorldPosition.x = pLineEnd->vWorldPosition.x;
+    v15 = pLineEnd->vWorldPosition.z;
+    a1[1].vWorldPosition.y = pLineEnd->vWorldPosition.y;
+    a1[1].vWorldPosition.z = v15;
+    if ( _437285_prolly_colide_vertices_against_frustrum(
+           a1,
+           &uOutNumVertices,
+           pVertices,
+           this->std__vector_000034_prolly_frustrum,
+           4,
+           1,
+           0) != 1
+      || (signed int)uOutNumVertices >= 2 )
+    {
+      ViewTransform(pVertices, 2u);
+      Project(pVertices, 2u, 0);
+      goto LABEL_11;
+    }
+  }
+  else
+    MessageBoxW(nullptr, L"draw_debug_line() not implemented for SW rendering", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Core3D.cpp:1383", 0);
+}
+
+
+//----- (00437A55) --------------------------------------------------------
+void IndoorCameraD3D::debug_outline_d3d(const RenderVertexD3D3 *pLineVertices, unsigned int uNumLines, int uDiffuse, float z_stuff)
+{
+  unsigned int v5; // esi@1
+  const RenderVertexD3D3 *v6; // ecx@2
+  unsigned int v7; // ebx@2
+  const RenderVertexD3D3 *v8; // edi@3
+  IndoorCameraD3D *thisa; // [sp+10h] [bp-4h]@1
+
+  v5 = 0;
+  thisa = this;
+  if ( (signed int)(uNumLines - 1) > 0 )
+  {
+    v6 = pLineVertices;
+    v7 = uNumLines - 1;
+    v5 = uNumLines - 1;
+    do
+    {
+      v8 = v6 + 1;
+      do_draw_debug_line_d3d(v6, uDiffuse, v6 + 1, uDiffuse, z_stuff);
+      --v7;
+      v6 = v8;
+    }
+    while ( v7 );
+  }
+  do_draw_debug_line_d3d(&pLineVertices[v5], uDiffuse, pLineVertices, uDiffuse, z_stuff);
+}
+
+
+//----- (004379EE) --------------------------------------------------------
+void IndoorCameraD3D::debug_outline_sw(RenderVertexSoft *a2, unsigned int uNumVertices, unsigned int uDiffuse, float a5)
+{
+  unsigned int v5; // esi@1
+  RenderVertexSoft *v6; // eax@2
+  RenderVertexSoft *v7; // edi@3
+  char v8; // zf@3
+  IndoorCameraD3D *v9; // [sp+10h] [bp-4h]@1
+  unsigned int uNumVerticesa; // [sp+20h] [bp+Ch]@2
+
+  v9 = this;
+  v5 = 0;
+  if ( (signed int)(uNumVertices - 1) > 0 )
+  {
+    v6 = a2;
+    v5 = uNumVertices - 1;
+    uNumVerticesa = uNumVertices - 1;
+    do
+    {
+      v7 = v6 + 1;
+      do_draw_debug_line_sw(v6, uDiffuse, v6 + 1, uDiffuse, 0, a5);
+      v8 = uNumVerticesa-- == 1;
+      v6 = v7;
+    }
+    while ( !v8 );
+  }
+  do_draw_debug_line_sw(&a2[v5], uDiffuse, a2, uDiffuse, 0, a5);
+}
+
+
+//----- (00437906) --------------------------------------------------------
+void IndoorCameraD3D::PrepareAndDrawDebugOutline(BLVFace *pFace, unsigned int uDiffuse)
+{
+  char *v3; // eax@2
+  signed int v4; // ecx@2
+  signed int v5; // ebx@5
+  Vec3_short_ *v6; // edx@6
+  char *v7; // esi@6
+  signed int v8; // ecx@7
+  IndoorCameraD3D *thisa; // [sp+8h] [bp-4h]@1
+
+  thisa = this;
+
+  
+  static RenderVertexSoft static_sub_437906_array_50CDD0[64];
+  static bool __init_flag1 = false;
+  if (!__init_flag1)
+  {
+    __init_flag1 = true;
+
+    for (uint i = 0; i < 64; ++i)
+      static_sub_437906_array_50CDD0[i].flt_2C = 0.0f;
+  }
+
+  v5 = 0;
+  if ( pFace->uNumVertices )
+  {
+    v6 = pIndoor->pVertices;
+    v7 = (char *)&static_sub_437906_array_50CDD0[0].vWorldPosition.y;
+    do
+    {
+      v8 = v5++;
+      *((float *)v7 - 1) = (double)v6[pFace->pVertexIDs[v8]].x;
+      *(float *)v7 = (double)v6[pFace->pVertexIDs[v8]].y;
+      v7 += 48;
+      *((float *)v7 - 11) = (double)v6[pFace->pVertexIDs[v8]].z;
+      *((float *)v7 - 4) = (double)pFace->pVertexUIDs[v8];
+      *((float *)v7 - 3) = (double)pFace->pVertexVIDs[v8];
+    }
+    while ( v5 < pFace->uNumVertices );
+  }
+  debug_outline_sw(static_sub_437906_array_50CDD0, pFace->uNumVertices, uDiffuse, 0.0);
+}
+// 50D9D0: using guessed type char static_sub_437906_byte_50D9D0_init_flag;
+
+
+//----- (004378BA) --------------------------------------------------------
+void IndoorCameraD3D::MatrixMultiply(Matrix3x3_float_ *a1, Matrix3x3_float_ *a2, Matrix3x3_float_ *out)
+{
+  float *v4; // ecx@1
+  float *v5; // eax@1
+  signed int v6; // ebx@1
+  float *v7; // edx@2
+  float *v8; // ecx@2
+  signed int v9; // edi@2
+  double v10; // st7@3
+  double v11; // st6@3
+
+  v4 = (float *)out;
+  v5 = &a1->_12;
+  v6 = 3;
+  do
+  {
+    v7 = v4;
+    v8 = &a2->_21;
+    v9 = 3;
+    do
+    {
+      v10 = v8[3] * v5[1] + *(v8 - 3) * *(v5 - 1);
+      v11 = *v8 * *v5;
+      ++v8;
+      *v7 = v10 + v11;
+      ++v7;
+      --v9;
+    }
+    while ( v9 );
+    v5 += 3;
+    --v6;
+    v4 = v7;
+  }
+  while ( v6 );
+}
+
+
+//----- (004376E7) --------------------------------------------------------
+void IndoorCameraD3D::CreateWorldMatrixAndSomeStuff()
+{
+  //IndoorCameraD3D *v1; // esi@1
+  double v2; // st7@1
+  //signed int v3; // edi@1
+  //int v4; // eax@1
+  //double v5; // st7@2
+  //double v6; // st7@3
+  Matrix3x3_float_ m1; // [sp+10h] [bp-B8h]@1
+  Matrix3x3_float_ m2; // [sp+34h] [bp-94h]@1
+  Matrix3x3_float_ m3; // [sp+58h] [bp-70h]@1
+  Matrix3x3_float_ m4; // [sp+7Ch] [bp-4Ch]@1
+  Matrix3x3_float_ m5; // [sp+A0h] [bp-28h]@1
+  float v12; // [sp+C4h] [bp-4h]@1
+
+ //RotationZ(0)
+  m5._11 = cosf(0);         m5._12 = sinf(0);        m5._13 = 0;
+  m5._21 = -sinf(0);        m5._22 = cosf(0);        m5._23 = 0;
+  m5._31 = 0;               m5._32 = 0;              m5._33 = 1;
+
+  float cos_x1 = pIndoorCamera->fRotationXCosine,
+        sin_x1 = pIndoorCamera->fRotationXSine;
+ //RotationX(x)
+  m4._11 = 1;               m4._12 = 0;              m4._13 = 0;
+  m4._21 = 0;               m4._22 = cos_x1;         m4._23 = sin_x1;
+  m4._31 = 0;               m4._32 = -sin_x1;        m4._33 = cos_x1;
+  
+  float cos_y1 = pIndoorCamera->fRotationYCosine,
+        sin_y1 = pIndoorCamera->fRotationYSine;
+ //RotationY(some_angle)
+  m3._11 = cos_y1;          m3._12 = 0;              m3._13 = -sin_y1;
+  m3._21 = 0;               m3._22 = 1;              m3._23 = 0;
+  m3._31 = sin_y1;          m3._32 = 0;              m3._33 = cos_y1;
+
+  MatrixMultiply(&m5, &m3, &m1);
+  MatrixMultiply(&m4, &m1, &m2);
+
+  for (uint i = 0; i < 3; ++i)
+  {
+    field_4[0].v[i] = m2.v[1][i];
+    field_4[1].v[i] = m2.v[0][i];
+    field_4[2].v[i] = m2.v[2][i];
+  }
+
+  inv_fov = 1.1344639;
+  fov_x = (double)pViewport->uScreenWidth * 0.8814736;
+
+  fov_y = 0.8814736 * (double)pViewport->uScreenHeight;
+  fov = fov_y;
+  if ( fov_x > fov )
+    fov = fov_x;
+  screenCenterX = (double)pViewport->uScreenCenterX;
+  screenCenterY = (double)(pViewport->uScreenCenterY - pViewport->uScreenY);
+}
+
+
+//----- (00437691) --------------------------------------------------------
+void IndoorCameraD3D::Vec3Transform(const IndoorCameraD3D_Vec3 *pVector, IndoorCameraD3D_Vec3 *pOut)
+{
+  pOut->y = field_4[1].x * pVector->x + field_4[0].x * pVector->y + field_4[2].x * pVector->z;
+  pOut->z = field_4[1].y * pVector->x + field_4[0].y * pVector->y + field_4[2].y * pVector->z;
+  pOut->x = field_4[1].z * pVector->x + field_4[0].z * pVector->y + field_4[2].z * pVector->z;
+}
+
+//----- (00437607) --------------------------------------------------------
+void IndoorCameraD3D::_437607(IndoorCameraD3D_Vec3 *a1, IndoorCameraD3D_Vec4 *a2)
+{
+  double v4; // st7@1
+  IndoorCameraD3D_Vec3 v8; // [sp+8h] [bp-1Ch]@1
+
+  v8.x = (double)pIndoorCamera->pos.x;
+  v8.y = (double)pIndoorCamera->pos.y;
+  v8.z = (double)pIndoorCamera->pos.z;
+  Vec3Transform(a1, a2);
+
+  v4 = v8.x * a2->x + v8.y * a2->y + v8.z * a2->z;
+  a2->dot = v4 + 0.000099999997;
+}
+
+//----- (004374E8) --------------------------------------------------------
+void IndoorCameraD3D::_4374E8_ProllyBuildFrustrum()
+{
+  //IndoorCameraD3D *v1; // esi@1
+  //double v2; // st7@1
+  double v3; // st7@1
+  //double v4; // st7@1
+  double v5; // st7@1
+  //double v6; // st7@1
+  IndoorCameraD3D_Vec3 v7; // [sp+Ch] [bp-24h]@1
+  //float v8; // [sp+10h] [bp-20h]@1
+  //float v9; // [sp+14h] [bp-1Ch]@1
+  //float v10; // [sp+18h] [bp-18h]@1
+  //float v11; // [sp+1Ch] [bp-14h]@1
+  //float v12; // [sp+20h] [bp-10h]@1
+  //int v13; // [sp+2Ch] [bp-4h]@1
+
+  //v1 = this;
+  //IndoorCameraD3D_Vec3::IndoorCameraD3D_Vec3(&v7);
+  //v2 = 2.0 / inv_fov;
+  //v13 = 0;
+  v3 = atan(2.0 / inv_fov * fov / fov_x);
+  //v12 = v3;
+  //v11 = sin(v3);
+  //v4 = cos(v3);
+  v7.x = -sin(v3);
+  v7.y = 0.0;
+  v7.z = cos(v3);
+  _437607(&v7, std__vector_000034_prolly_frustrum);
+  v7.x = sin(v3);
+  _437607(&v7, &std__vector_000034_prolly_frustrum[1]);
+  v5 = atan(2.0 / inv_fov * fov / (fov_y + 0.5));
+  //v12 = v5;
+  //v11 = sin(v5);
+  //v6 = cos(v5);
+  v7.y = sin(v5);
+  v7.x = 0.0;
+  v7.z = cos(v5);
+  _437607(&v7, &std__vector_000034_prolly_frustrum[2]);
+  v7.y = -sin(v5);
+  _437607(&v7, &std__vector_000034_prolly_frustrum[3]);
+  //v13 = -1;
+  //IndoorCameraD3D_Vec3::dtor(&v7);
+}
+
+//----- (00437376) --------------------------------------------------------
+char IndoorCameraD3D::_437376(stru154 *thisa, RenderVertexSoft *a2, unsigned int *pOutNumVertices)
+{
+  unsigned int v4; // ebx@1
+  RenderVertexSoft *v5; // edx@2
+  double v6; // st7@3
+  unsigned int v7; // edi@5
+  signed int v8; // esi@6
+  int v9; // ebx@8
+  int v10; // eax@8
+  int v11; // ecx@14
+  int v12; // eax@14
+  int v13; // eax@15
+  signed int v14; // ebx@17
+  RenderVertexSoft *v15; // eax@18
+  unsigned int *v16; // eax@20
+  char result; // al@24
+  RenderVertexSoft v18; // [sp+Ch] [bp-34h]@2
+  int v19; // [sp+3Ch] [bp-4h]@8
+  signed int thisb; // [sp+48h] [bp+8h]@6
+  char a2_3; // [sp+4Fh] [bp+Fh]@5
+
+  v4 = *pOutNumVertices;
+  if ( (signed int)*pOutNumVertices <= 3
+    || ((v5 = a2,
+         memcpy(&v18, a2, sizeof(v18)),
+         (v18.vWorldPosition.z - (double)pBLVRenderParams->vPartyPos.z) * thisa->face_plane.vNormal.z
+       + (v18.vWorldPosition.y - (double)pBLVRenderParams->vPartyPos.y) * thisa->face_plane.vNormal.y
+       + (v18.vWorldPosition.x - (double)pBLVRenderParams->vPartyPos.x) * thisa->face_plane.vNormal.x < 0.0) ? (v6 = 1.0) : (v6 = -1.0),
+        a2_3 = 0,
+        memcpy(&v5[v4], v5, sizeof(v5[v4])),
+        memcpy(&v5[*pOutNumVertices + 1], &v5[1], sizeof(v5[*pOutNumVertices + 1])),
+        v7 = *pOutNumVertices,
+        (signed int)*pOutNumVertices <= 0) )
+    goto LABEL_28;
+  v8 = 1;
+  for ( thisb = 1; ; v8 = thisb )
+  {
+    v9 = v8 - 1;
+    v10 = v8 + 1;
+    v19 = v8 + 1;
+    if ( v8 - 1 >= (signed int)v7 )
+      v9 -= v7;
+    if ( v8 >= (signed int)v7 )
+      v8 -= v7;
+    if ( v19 >= (signed int)v7 )
+      v10 = v19 - v7;
+    v11 = (int)&v5[v10];
+    v12 = (int)&v5[v9];
+    if ( -0.009999999776482582 > ((v5[v8].vWorldViewProjX - *(float *)(v12 + 24))
+                                * (*(float *)(v11 + 28) - *(float *)(v12 + 28))
+                                - (v5[v8].vWorldViewProjY - *(float *)(v12 + 28))
+                                * (*(float *)(v11 + 24) - *(float *)(v12 + 24)))
+                               * v6 )
+    {
+      thisb = v19;
+      v16 = pOutNumVertices;
+    }
+    else
+    {
+      v13 = thisb;
+      if ( thisb >= (signed int)v7 )
+        v13 = thisb - v7;
+      v14 = v13;
+      if ( v13 < (signed int)v7 )
+      {
+        v15 = &v5[v13];
+        do
+        {
+          memcpy(v15, &v15[1], 0x30u);
+          ++v14;
+          ++v15;
+        }
+        while ( v14 < (signed int)*pOutNumVertices );
+      }
+      v16 = pOutNumVertices;
+      a2_3 = 1;
+      --*v16;
+    }
+    v7 = *v16;
+    if ( thisb - 1 >= (signed int)*v16 )
+      break;
+  }
+  if ( a2_3 )
+    result = 1;
+  else
+LABEL_28:
+    result = 0;
+  return result;
+}
+
+//----- (00437285) --------------------------------------------------------
+bool IndoorCameraD3D::_437285_prolly_colide_vertices_against_frustrum(RenderVertexSoft *a1, unsigned int *pOutNumVertices, RenderVertexSoft *pVertices, IndoorCameraD3D_Vec4 *a4, signed int uNumVertices, char a6, int _unused)
+{
+  char *v8; // eax@2
+  signed int v9; // ecx@2
+  //bool result; // eax@5
+  int v11; // ecx@5
+  //signed int v12; // ecx@6
+  //char *v13; // esi@6
+  RenderVertexSoft *v14; // eax@8
+  RenderVertexSoft *v15; // edx@8
+  Vec3_float_ a5; // [sp+18h] [bp-3Ch]@12
+  float v17; // [sp+44h] [bp-10h]@1
+  int v18; // [sp+48h] [bp-Ch]@5
+  //stru9 *thisa; // [sp+4Ch] [bp-8h]@1
+  int a7a; // [sp+53h] [bp-1h]@5
+  //bool a6a; // [sp+70h] [bp+1Ch]@5
+
+  v17 = 0.0;
+  //thisa = pGame->pStru9Instance;
+
+  
+  static RenderVertexSoft sr_vertices_50D9D8[64];
+
+  //result = 0;
+  a7a = 0;
+  v11 = 2 * (a6 == 0) + 1;
+  //a6a = 0;
+  v18 = v11;
+  if (uNumVertices <= 0)
+    return false;
+
+    //v12 = *pOutNumVertices;
+    //v13 = (char *)&a4->y;
+  uint i = 0;
+    while ( 1 )
+    {
+      if (i % 2)
+      {
+        v14 = a1;
+        v15 = sr_vertices_50D9D8;
+      }
+      else
+      {
+        v15 = a1;
+        v14 = sr_vertices_50D9D8;
+      }
+      if (i == uNumVertices - 1)
+        v14 = pVertices;
+      a5.x = a4[i].x;
+      a5.y = a4[i].y;
+      a5.z = a4[i].z;
+      pGame->pStru9Instance->_4985FB(v15, *pOutNumVertices, v14, pOutNumVertices, &a5, a4[i].dot, (char *)&a7a, _unused);
+      //v12 = *pOutNumVertices;
+      if (*pOutNumVertices < v18)
+        break;
+      //result = a6a;
+      //v13 += 24;
+      if (++i >= uNumVertices)
+        return a7a;
+    }
+    *pOutNumVertices = 0;
+  return true;
+}
+
+//----- (004371C3) --------------------------------------------------------
+bool IndoorCameraD3D::_4371C3(RenderVertexSoft *pVertices, unsigned int *pOutNumVertices, int _unused)
+{
+  char *v4; // eax@2
+  signed int v5; // ecx@2
+  RenderVertexSoft *v6; // esi@5
+  unsigned int *v7; // edi@5
+  char *v8; // ecx@6
+  int v9; // eax@6
+  IndoorCameraD3D *thisa; // [sp+0h] [bp-Ch]@1
+  signed int v12; // [sp+4h] [bp-8h]@5
+  unsigned int pVerticesa; // [sp+14h] [bp+8h]@6
+  unsigned int pOutNumVerticesa; // [sp+18h] [bp+Ch]@6
+
+  thisa = this;
+
+  
+  static RenderVertexSoft static_4371C3_array_50E5E0[64];
+  static bool __init_flag1 = false;
+  if (!__init_flag1)
+  {
+    __init_flag1 = true;
+
+    for (uint i = 0; i < 64; ++i)
+      static_4371C3_array_50E5E0[i].flt_2C = 0.0f;
+  }
+
+  v12 = 0;
+  v6 = pVertices;
+  v7 = pOutNumVertices;
+  if ( (signed int)*pOutNumVertices > 0 )
+  {
+    pOutNumVerticesa = (char *)static_4371C3_array_50E5E0 - (char *)pVertices;
+    pVerticesa = (char *)&static_4371C3_array_50E5E0[0].vWorldViewProjY - (char *)pVertices;
+    v8 = (char *)&static_4371C3_array_50E5E0[0].vWorldPosition.y;
+    v9 = (int)&v6->vWorldPosition.z;
+    do
+    {
+      ++v12;
+      *((int *)v8 - 1) = *(int *)(v9 - 8);
+      *(int *)v8 = *(int *)(v9 - 4);
+      v8 += 48;
+      *(float *)(pOutNumVerticesa + v9) = *(float *)v9;
+      *(float *)(pVerticesa + v9) = *(float *)(v9 + 28);
+      *(float *)((char *)&static_4371C3_array_50E5E0[0].flt_20 - (char *)v6 + v9) = *(float *)(v9 + 32);
+      v9 += 48;
+    }
+    while ( v12 < (signed int)*v7 );
+  }
+  return _437285_prolly_colide_vertices_against_frustrum(
+           static_4371C3_array_50E5E0,
+           v7,
+           v6,
+           thisa->std__vector_000034_prolly_frustrum,
+           4,
+           0,
+           _unused);
+}
+// 50F1E0: using guessed type char static_sub_4371C3_byte_50F1E0_init_flags;
+
+//----- (00437143) --------------------------------------------------------
+int IndoorCameraD3D::_437143(unsigned int uNumInVertices, RenderVertexSoft *pOutVertices, RenderVertexSoft *pInVertices, unsigned int *pOutNumVertices)
+{
+  unsigned int v5; // edi@1
+  char *pOutVertices_; // edx@2
+  char *v7; // eax@2
+  unsigned int v8; // ebx@2
+  double v9; // st7@3
+  double v10; // st6@3
+  int result; // eax@5
+  unsigned int a2a; // [sp+10h] [bp+Ch]@2
+
+  v5 = uNumInVertices;
+  if ( (signed int)uNumInVertices > 0 )
+  {
+    pOutVertices_ = (char *)&pOutVertices->vWorldViewProjY;
+    v7 = (char *)&pInVertices->flt_20;
+    v8 = (char *)pOutVertices - (char *)pInVertices;
+    a2a = uNumInVertices;
+    do
+    {
+      *(float *)v7 = 1.0 / (*((float *)v7 - 5) + 0.0000001);
+      memcpy(pOutVertices_ - 28, v7 - 32, 0x30u);
+      v9 = (double)pOutdoorCamera->int_fov_rad * *(float *)&v7[v8];
+      v10 = (double)pViewport->uScreenCenterX - v9 * *((float *)v7 - 4);
+      v7 += 48;
+      *((float *)pOutVertices_ - 1) = v10;
+      *(float *)pOutVertices_ = (double)pViewport->uScreenCenterY - v9 * *((float *)v7 - 15);
+      pOutVertices_ += 48;
+      --a2a;
+    }
+    while ( a2a );
+    v5 = uNumInVertices;
+  }
+  result = (int)pOutNumVertices;
+  *pOutNumVertices = v5;
+  return result;
+}
+//----- (00436F09) --------------------------------------------------------
+void IndoorCameraD3D::_436F09_mess_with_lightmap__clipflag_4(RenderVertexSoft *pInVertices, int uNumInVertices, RenderVertexSoft *pOutVertices, unsigned int *pOutNumVertices)
+{
+  unsigned int *pOutNumVertices_; // ebx@1
+  double v6; // st7@2
+  signed int v7; // esi@2
+  char *v8; // edx@5
+  unsigned int v9; // eax@10
+  RenderVertexSoft *v10; // ecx@11
+  double v11; // st6@11
+  double v12; // st6@12
+  unsigned int v13; // edi@14
+  unsigned __int8 v14; // c2@16
+  unsigned __int8 v15; // c3@16
+  unsigned int v16; // edi@17
+  bool a1a; // [sp+Ch] [bp+8h]@7
+  int a4a; // [sp+18h] [bp+14h]@5
+
+  pOutNumVertices_ = pOutNumVertices;
+  *pOutNumVertices = 0;
+  if ( uNumInVertices )
+  {
+    memcpy(&pInVertices[uNumInVertices], pInVertices, sizeof(pInVertices[uNumInVertices]));
+    v6 = (double)pOutdoorCamera->shading_dist_mist;
+    v7 = 0;
+    if ( v6 >= pInVertices->vWorldViewPosition.x )
+      v7 = 1;
+    if ( uNumInVertices + 1 > 1 )
+    {
+      a4a = uNumInVertices;
+      v8 = (char *)&pInVertices[1].u;
+      do
+      {
+        a1a = v6 >= *((float *)v8 - 6);
+        if ( v7 == a1a )
+        {
+          v10 = pOutVertices;
+          goto LABEL_23;
+        }
+        v9 = *pOutNumVertices_;
+        if ( a1a )
+        {
+          v10 = pOutVertices;
+          v11 = (v6 - *((float *)v8 - 18)) / (*((float *)v8 - 6) - *((float *)v8 - 18));
+          pOutVertices[v9].vWorldViewPosition.y = (*((float *)v8 - 5) - *((float *)v8 - 17)) * v11 + *((float *)v8 - 17);
+          pOutVertices[*pOutNumVertices_].vWorldViewPosition.z = (*((float *)v8 - 4) - *((float *)v8 - 16)) * v11
+                                                               + *((float *)v8 - 16);
+          pOutVertices[*pOutNumVertices_].u = (*(float *)v8 - *((float *)v8 - 12)) * v11 + *((float *)v8 - 12);
+          pOutVertices[*pOutNumVertices_].v = (*((float *)v8 + 1) - *((float *)v8 - 11)) * v11 + *((float *)v8 - 11);
+        }
+        else
+        {
+          v12 = (v6 - *((float *)v8 - 6)) / (*((float *)v8 - 18) - *((float *)v8 - 6));
+          pOutVertices[v9].vWorldViewPosition.y = (*((float *)v8 - 17) - *((float *)v8 - 5)) * v12 + *((float *)v8 - 5);
+          pOutVertices[*pOutNumVertices_].vWorldViewPosition.z = (*((float *)v8 - 16) - *((float *)v8 - 4)) * v12
+                                                               + *((float *)v8 - 4);
+          pOutVertices[*pOutNumVertices_].u = (*((float *)v8 - 12) - *(float *)v8) * v12 + *(float *)v8;
+          pOutVertices[*pOutNumVertices_].v = (*((float *)v8 - 11) - *((float *)v8 + 1)) * v12 + *((float *)v8 + 1);
+          v10 = pOutVertices;
+        }
+        v10[*pOutNumVertices_].vWorldViewPosition.x = v6;
+        v10[*pOutNumVertices_].flt_20 = 1.0 / v6;
+        if ( v7 )
+        {
+          v13 = (unsigned int)&v10[*pOutNumVertices_];
+          if ( *(float *)(v13 + 12) != *((float *)v8 - 18) || *(float *)(v13 + 16) != *((float *)v8 - 17) )
+            goto LABEL_21;
+          v14 = 0;
+          v15 = *(float *)(v13 + 20) == *((float *)v8 - 16);
+        }
+        else
+        {
+          v16 = (unsigned int)&v10[*pOutNumVertices_];
+          if ( *(float *)(v16 + 12) != *((float *)v8 - 6) || *(float *)(v16 + 16) != *((float *)v8 - 5) )
+          {
+LABEL_21:
+            ++*pOutNumVertices_;
+            goto LABEL_23;
+          }
+          v14 = 0;
+          v15 = *(float *)(v16 + 20) == *((float *)v8 - 4);
+        }
+        if ( !(v15 | v14) )
+          goto LABEL_21;
+LABEL_23:
+        if ( a1a )
+        {
+          memcpy(&v10[*pOutNumVertices_], v8 - 36, sizeof(v10[*pOutNumVertices_]));
+          pOutVertices[*pOutNumVertices_].flt_20 = 1.0 / (*((float *)v8 - 6) + 0.0000001);
+          pOutVertices[(*pOutNumVertices_)++].flt_2C = *((float *)v8 + 2);
+        }
+        v7 = a1a;
+        v8 += 48;
+        --a4a;
+      }
+      while ( a4a );
+    }
+    if ( (signed int)*pOutNumVertices_ < 3 )
+      *pOutNumVertices_ = 0;
+  }
+}
+
+
+//----- (00436CDC) --------------------------------------------------------
+void IndoorCameraD3D::_436CDC_mess_with_lightmap__clipflag_2(RenderVertexSoft *pInVertices, int uNumInVertices, RenderVertexSoft *pOutVertices, unsigned int *pOutNumVertices)
+{
+  signed int v5; // esi@2
+  char *v6; // edx@5
+  unsigned int v7; // eax@10
+  RenderVertexSoft *v8; // ecx@11
+  double v9; // st6@11
+  double v10; // st6@12
+  unsigned int v11; // edi@14
+  unsigned __int8 v12; // c2@16
+  unsigned __int8 v13; // c3@16
+  unsigned int v14; // edi@17
+  bool a1a; // [sp+Ch] [bp+8h]@7
+
+  if ( uNumInVertices )
+  {
+    *pOutNumVertices = 0;
+    memcpy(&pInVertices[uNumInVertices], pInVertices, sizeof(pInVertices[uNumInVertices]));
+    v5 = 0;
+    if ( pInVertices->vWorldViewPosition.x >= 8.0 )
+      v5 = 1;
+    if ( uNumInVertices + 1 > 1 )
+    {
+      v6 = (char *)&pInVertices[1].u;
+      do
+      {
+        a1a = *((float *)v6 - 6) >= 8.0;
+        if ( v5 == a1a )
+        {
+          v8 = pOutVertices;
+          goto LABEL_23;
+        }
+        v7 = *pOutNumVertices;
+        if ( a1a )
+        {
+          v8 = pOutVertices;
+          v9 = (8.0 - *((float *)v6 - 18)) / (*((float *)v6 - 6) - *((float *)v6 - 18));
+          pOutVertices[v7].vWorldViewPosition.y = (*((float *)v6 - 5) - *((float *)v6 - 17)) * v9 + *((float *)v6 - 17);
+          pOutVertices[*pOutNumVertices].vWorldViewPosition.z = (*((float *)v6 - 4) - *((float *)v6 - 16)) * v9
+                                                              + *((float *)v6 - 16);
+          pOutVertices[*pOutNumVertices].u = (*(float *)v6 - *((float *)v6 - 12)) * v9 + *((float *)v6 - 12);
+          pOutVertices[*pOutNumVertices].v = (*((float *)v6 + 1) - *((float *)v6 - 11)) * v9 + *((float *)v6 - 11);
+        }
+        else
+        {
+          v10 = (8.0 - *((float *)v6 - 6)) / (*((float *)v6 - 18) - *((float *)v6 - 6));
+          pOutVertices[v7].vWorldViewPosition.y = (*((float *)v6 - 17) - *((float *)v6 - 5)) * v10 + *((float *)v6 - 5);
+          pOutVertices[*pOutNumVertices].vWorldViewPosition.z = (*((float *)v6 - 16) - *((float *)v6 - 4)) * v10
+                                                              + *((float *)v6 - 4);
+          pOutVertices[*pOutNumVertices].u = (*((float *)v6 - 12) - *(float *)v6) * v10 + *(float *)v6;
+          pOutVertices[*pOutNumVertices].v = (*((float *)v6 - 11) - *((float *)v6 + 1)) * v10 + *((float *)v6 + 1);
+          v8 = pOutVertices;
+        }
+        v8[*pOutNumVertices].vWorldViewPosition.x = 8.0;
+        v8[*pOutNumVertices].flt_20 = 0.125;
+        if ( v5 )
+        {
+          v11 = (unsigned int)&v8[*pOutNumVertices];
+          if ( *(float *)(v11 + 12) != *((float *)v6 - 18) || *(float *)(v11 + 16) != *((float *)v6 - 17) )
+            goto LABEL_21;
+          v12 = 0;
+          v13 = *(float *)(v11 + 20) == *((float *)v6 - 16);
+        }
+        else
+        {
+          v14 = (unsigned int)&v8[*pOutNumVertices];
+          if ( *(float *)(v14 + 12) != *((float *)v6 - 6) || *(float *)(v14 + 16) != *((float *)v6 - 5) )
+          {
+LABEL_21:
+            ++*pOutNumVertices;
+            goto LABEL_23;
+          }
+          v12 = 0;
+          v13 = *(float *)(v14 + 20) == *((float *)v6 - 4);
+        }
+        if ( !(v13 | v12) )
+          goto LABEL_21;
+LABEL_23:
+        if ( a1a )
+        {
+          memcpy(&v8[*pOutNumVertices], v6 - 36, sizeof(v8[*pOutNumVertices]));
+          pOutVertices[(*pOutNumVertices)++].flt_20 = 1.0 / (*((float *)v6 - 6) + 0.0000001);
+        }
+        v5 = a1a;
+        v6 += 48;
+        --uNumInVertices;
+      }
+      while ( uNumInVertices );
+    }
+    if ( (signed int)*pOutNumVertices < 3 )
+      *pOutNumVertices = 0;
+  }
+}
+
+
+//----- (00436BB7) --------------------------------------------------------
+void IndoorCameraD3D::Project(RenderVertexSoft *pVertices, unsigned int uNumVertices, char a4)
+{
+  double v7; // st7@7
+  double v8; // st7@9
+  double v9; // st6@10
+  double v10; // st5@12
+  double v11; // st7@16
+  double v12; // st6@17
+  double v13; // st5@19
+  float uNumVerticesa; // [sp+14h] [bp+Ch]@13
+  float uNumVerticesb; // [sp+14h] [bp+Ch]@20
+
+  for (uint i = 0; i < uNumVertices; ++i)
+  {
+    if (byte_4D864C && pGame->uFlags & 0x80 || uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    {
+      v7 = 1.0 / pVertices[i].vWorldViewPosition.x;
+
+      pVertices[i].vWorldViewProjX = pVertices[i].vWorldViewPosition.y * fov * v7 + screenCenterX;
+      pVertices[i].vWorldViewProjY = (signed int)pViewport->uViewportW - (pVertices[i].vWorldViewPosition.z * fov * v7 + screenCenterY);
+    }
+    else
+    {
+      extern void _outdoor_project(RenderVertexSoft *v);
+      _outdoor_project(pVertices + i);
+    }
+
+      if ( a4 )
+      {
+        __debugbreak();
+        v8 = (double)(signed int)pViewport->uViewportZ;
+        if ( v8 >= pVertices[i].vWorldViewProjX )
+          v9 = pVertices[i].vWorldViewProjX;
+        else
+          v9 = v8;
+        v10 = (double)(signed int)pViewport->uViewportX;
+        if ( v10 <= v9 )
+        {
+          if ( v8 >= pVertices[i].vWorldViewProjX)
+            v8 = pVertices[i].vWorldViewProjX;
+        }
+        else
+        {
+          uNumVerticesa = v10;
+          v8 = uNumVerticesa;
+        }
+        pVertices[i].vWorldViewProjX = v8;
+        v11 = (double)(signed int)pViewport->uViewportW;
+        if ( v11 >= pVertices[i].vWorldViewProjY)
+          v12 = pVertices[i].vWorldViewProjY;
+        else
+          v12 = v11;
+        v13 = (double)(signed int)pViewport->uViewportY;
+        if ( v13 <= v12 )
+        {
+          if ( v11 >= pVertices[i].vWorldViewProjY)
+            v11 = pVertices[i].vWorldViewProjY;
+        }
+        else
+        {
+          uNumVerticesb = v13;
+          v11 = uNumVerticesb;
+        }
+        pVertices[i].vWorldViewProjY = v11;
+      }
+  }
+}
+
+
+//----- (00436A9A) --------------------------------------------------------
+void IndoorCameraD3D::Project(signed int x, signed int y, signed int z, int *a5, int *a6)
+{
+  double v6; // ST00_8@2
+  //double v7; // ST08_8@2
+  //double v8; // ST00_8@2
+  signed __int64 v9; // qtt@3
+  int v10; // ST04_4@3
+  float a2a; // [sp+18h] [bp+8h]@2
+  float a2b; // [sp+18h] [bp+8h]@2
+
+  if ( pRenderer->pRenderD3D )
+  {
+    v6 = 1.0 / (double)x;
+    a2a = (double)y * fov * v6 + screenCenterX;
+    //v7 = a2a + 6.7553994e15;
+    *a5 = floorf(a2a + 0.5f);
+    a2b = (double)z * fov * v6 + screenCenterY;
+    //v8 = a2b + 6.7553994e15;
+    *a6 = pViewport->uViewportW - floorf(a2b + 0.5f);
+  }
+  else
+  {
+    LODWORD(v9) = pBLVRenderParams->field_40 << 16;
+    HIDWORD(v9) = pBLVRenderParams->field_40 >> 16;
+    v10 = v9 / x;
+    LODWORD(v9) = pBLVRenderParams->field_40 << 16;
+    HIDWORD(v9) = pBLVRenderParams->field_40 >> 16;
+    *a5 = pBLVRenderParams->uViewportCenterX
+        - ((signed int)(((unsigned __int64)(v10 * (signed __int64)y) >> 16) + 32768) >> 16);
+    *a6 = pBLVRenderParams->uViewportCenterY - ((signed int)(((unsigned __int64)(v9 / x * z) >> 16) + 32768) >> 16);
+  }
+}
+
+//----- (00436A6D) --------------------------------------------------------
+double IndoorCameraD3D::GetPolygonMinZ(RenderVertexSoft *pVertices, unsigned int uStripType)
+{
+  unsigned int v3; // edx@1
+  double result; // st7@1
+  float *v5; // ecx@2
+
+  v3 = uStripType;
+  result = 3.4028235e38;
+  if ( (signed int)uStripType > 0 )
+  {
+    v5 = &pVertices->vWorldPosition.z;
+    do
+    {
+      if ( *v5 < result )
+        result = *v5;
+      v5 += 12;
+      --v3;
+    }
+    while ( v3 );
+  }
+  return result;
+}
+
+
+//----- (00436A24) --------------------------------------------------------
+struct IDirect3DTexture2 *IndoorCameraD3D::LoadTextureAndGetHardwarePtr(char *Str1)
+{
+  return pBitmaps_LOD->pHardwareTextures[pBitmaps_LOD->LoadTexture(Str1)];
+}
+
+//----- (00436A40) --------------------------------------------------------
+double IndoorCameraD3D::GetPolygonMaxZ(RenderVertexSoft *pVertex, unsigned int uStripType)
+{
+  unsigned int v3; // edx@1
+  double result; // st7@1
+  float *v5; // ecx@2
+
+  v3 = uStripType;
+  result = 1.1754944e-38;
+  if ( (signed int)uStripType > 0 )
+  {
+    v5 = &pVertex->vWorldPosition.z;
+    do
+    {
+      if ( *v5 > result )
+        result = *v5;
+      v5 += 12;
+      --v3;
+    }
+    while ( v3 );
+  }
+  return result;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IndoorCameraD3D.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,222 @@
+#pragma once
+
+
+
+
+/*  124 */
+#pragma pack(push, 1)
+struct IndoorCameraD3D_Vec3
+{
+  //----- (004C0376) --------------------------------------------------------
+  inline IndoorCameraD3D_Vec3() {}
+  //----- (004C037F) --------------------------------------------------------
+  virtual ~IndoorCameraD3D_Vec3() {}
+  //----- (004C039C) --------------------------------------------------------
+  //void ~IndoorCameraD3D_Vec3() {}
+
+  void (__thiscall ***vdestructor_ptr)(IndoorCameraD3D_Vec3 *, bool);
+
+  union
+  {
+    struct
+    {
+      float x;
+      float y;
+      float z;
+    };
+    float v[3];
+  };
+};
+#pragma pack(pop)
+
+/*  125 */
+#pragma pack(push, 1)
+struct IndoorCameraD3D_Vec4: public IndoorCameraD3D_Vec3
+{
+  //----- (00498038) --------------------------------------------------------
+  inline IndoorCameraD3D_Vec4():
+    IndoorCameraD3D_Vec3()
+  {}
+
+  //----- (00498069) --------------------------------------------------------
+  virtual ~IndoorCameraD3D_Vec4()
+  {}
+
+  float dot;
+};
+#pragma pack(pop)
+
+
+
+/*  199 */
+#pragma pack(push, 1)
+struct IndoorCameraD3D_stru3
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+  int field_2C;
+  float flt_30;
+  int field_34;
+};
+#pragma pack(pop)
+
+
+
+/*  197 */
+#pragma pack(push, 1)
+struct IndoorCameraD3D_stru1
+{
+  //----- (004363A2) --------------------------------------------------------
+  IndoorCameraD3D_stru1()
+  {
+    this->flt_2C = 0.0;
+  }
+
+
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+  float flt_2C;
+};
+#pragma pack(pop)
+
+/*  198 */
+#pragma pack(push, 1)
+struct IndoorCameraD3D_stru2
+{
+  unsigned int mm7__vector_000004_size;
+  IndoorCameraD3D_stru1 mm7__vector_000004[64];
+  int field_C04;
+  int field_C08;
+  int field_C0C;
+};
+#pragma pack(pop)
+
+/*  123 */
+#pragma pack(push, 1)
+struct IndoorCameraD3D
+{
+  IndoorCameraD3D();
+
+  //----- (004363C6) --------------------------------------------------------
+  virtual ~IndoorCameraD3D()
+  {
+    //this->vdestructor_ptr = &stru8_pvdtor;
+    //_eh_vector_destructor_iterator_(this->std__vector_000034_prolly_frustrum, 24, 6, IndoorCameraD3D_Vec4::dtor);
+    //IndoorCameraD3D_Vec3::dtor(&v1->field_24);
+    //IndoorCameraD3D_Vec3::dtor(&v1->field_14);
+    //IndoorCameraD3D_Vec3::dtor(&v1->field_4);
+  }
+
+  double GetPolygonMaxZ(struct RenderVertexSoft *pVertex, unsigned int uStripType);
+  double GetPolygonMinZ(struct RenderVertexSoft *pVertices, unsigned int uStripType);
+  struct IDirect3DTexture2 *LoadTextureAndGetHardwarePtr(char *Str1);
+  void Project(signed int x, signed int y, signed int z, int *a5, int *a6);
+  void Project(struct RenderVertexSoft *pVertices, unsigned int uNumVertices, char a4);
+  void _436CDC_mess_with_lightmap__clipflag_2(struct RenderVertexSoft *pInVertices, int uNumInVertices, struct RenderVertexSoft *pOutVertices, unsigned int *pOutNumVertices);
+  void _436F09_mess_with_lightmap__clipflag_4(struct RenderVertexSoft *pInVertices, int uNumInVertices, struct RenderVertexSoft *pOutVertices, unsigned int *pOutNumVertices);
+  int _437143(unsigned int uNumInVertices, struct RenderVertexSoft *pOutVertices, struct RenderVertexSoft *pInVertices, unsigned int *pOutNumVertices);
+  bool _4371C3(struct RenderVertexSoft *pVertices, unsigned int *pOutNumVertices, int _unused);
+  bool _437285_prolly_colide_vertices_against_frustrum(struct RenderVertexSoft *a1, unsigned int *pOutNumVertices, struct RenderVertexSoft *pVertices, IndoorCameraD3D_Vec4 *a4, signed int uNumVertices, char a6, int _unused);
+  char _437376(struct stru154 *thisa, struct RenderVertexSoft *a2, unsigned int *pOutNumVertices);
+  void _4374E8_ProllyBuildFrustrum();
+  void _437607(IndoorCameraD3D_Vec3 *a1, IndoorCameraD3D_Vec4 *a2);
+  void Vec3Transform(const IndoorCameraD3D_Vec3 *pVector, IndoorCameraD3D_Vec3 *pOut);
+  void CreateWorldMatrixAndSomeStuff();
+  void MatrixMultiply(struct Matrix3x3_float_ *a1, struct Matrix3x3_float_ *a2, struct Matrix3x3_float_ *a3);
+  void PrepareAndDrawDebugOutline(struct BLVFace *pFace, unsigned int uDiffuse);
+  void debug_outline_sw(struct RenderVertexSoft *a2, unsigned int uNumVertices, unsigned int uDiffuse, float a5);
+  void debug_outline_d3d(const struct RenderVertexD3D3 *pLineVertices, unsigned int uNumLines, int uDiffuse, float z_stuff);
+  void do_draw_debug_line_sw(struct RenderVertexSoft *pLineBegin, unsigned int uStartDiffuse, struct RenderVertexSoft *pLineEnd, unsigned int uEndDiffuse, unsigned int uOutNumVertices, float z_stuff);
+  void do_draw_debug_line_d3d(const struct RenderVertexD3D3 *pLineBegin, unsigned int uDiffuseBegin, const RenderVertexD3D3 *pLineEnd, unsigned int uDiffuseEnd, float z_stuff);
+  void _437D4A_draw_some_vertices(float x, float y, float z, unsigned int a5, char a6, float a7);
+  void _438141_draw_list_0037C();
+  void _438240_draw_lits();
+  void Reset_list_0037C();
+  bool is_face_faced_to_camera(struct BLVFace *pFace, struct RenderVertexSoft *a2);
+  bool GetFacetOrientation(char polyType, struct Vec3_float_ *a2, struct Vec3_float_ *a3, struct Vec3_float_ *a4);
+  void ViewTransform(struct RenderVertexSoft *a1a, unsigned int uNumVertices);
+  bool IsCulled(struct BLVFace *pFace);
+  void ViewTransfrom_OffsetUV(struct RenderVertexSoft *pVertices, unsigned int uNumVertices, struct RenderVertexSoft *pOutVertices, struct stru320 *a5);
+  char ApplyViewTransform_TrueIfStillVisible(int x, int y, int z, signed int *pOutX, int *pOutZ, int *pOutY, char bDoNotShow);
+
+  void (__thiscall ***vdestructor_ptr)(IndoorCameraD3D *, bool);
+  IndoorCameraD3D_Vec3 field_4[3];
+  //IndoorCameraD3D_Vec3 field_14;
+  //IndoorCameraD3D_Vec3 field_24;
+  IndoorCameraD3D_Vec4 std__vector_000034_prolly_frustrum[6];
+  float fov;
+  float screenCenterX;
+  float screenCenterY;
+  float fov_x;
+  float fov_y;
+  float inv_fov;
+  float field_DC;
+  float field_E0;
+  float field_E4;
+  char field_E8[32];
+  float field_108;
+  float field_10C;
+  float field_110;
+  float field_114;
+  char field_118[32];
+  float field_138;
+  char field_13C[44];
+  float field_168;
+  char field_16C[44];
+  float field_198;
+  char field_19C[44];
+  float field_1C8;
+  char field_1CC[44];
+  float field_1F8;
+  char field_1FC[44];
+  float field_228;
+  char field_22C[44];
+  float field_258;
+  char field_25C[44];
+  float field_288;
+  char field_28C[44];
+  float field_2B8;
+  float field_2BC;
+  float field_2C0;
+  float field_2C4;
+  char field_2C8[32];
+  float field_2E8;
+  float field_2EC;
+  float field_2F0;
+  float field_2F4;
+  char field_2F8[32];
+  float field_318;
+  float field_31C;
+  float field_320;
+  float field_324;
+  char field_328[32];
+  float field_348;
+  float field_34C;
+  float field_350;
+  float field_354;
+  char field_358[32];
+  float field_378;
+  IndoorCameraD3D_stru3 list_0037C[16384];
+  unsigned int list_0037C_size;
+  IndoorCameraD3D_stru2 list_E0380[256];
+  int list_E0380_size;
+};
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Indoor_stuff.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,415 @@
+#pragma once
+#include "Render.h"
+
+
+
+
+/*  165 */
+#pragma pack(push, 1)
+struct BspRenderer_stru2
+{
+  void _43F9E1(__int16 x, int y, __int16 z, int w);
+
+  int _viewport_space_y;
+  int _viewport_space_w;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  __int16 array_18[480];
+  __int16 array_3D8[480];
+};
+#pragma pack(pop)
+extern BspRenderer_stru2 stru_F8A590;
+
+
+
+
+/*  164 */
+#pragma pack(push, 1)
+struct BspRenderer_stru0
+{
+  //----- (0043F2BF) --------------------------------------------------------
+  inline BspRenderer_stru0()
+  {
+    //_eh_vector_constructor_iterator_(std__vector_0007AC, 24, 4,
+    //    (void (__thiscall *)(void *))IndoorCameraD3D_Vec4::IndoorCameraD3D_Vec4,
+    //    (void (__thiscall *)(void *))IndoorCameraD3D_Vec4::dtor);
+    //for (int i = 0; i < 4; ++i)
+    //  pVertices[i].flt_2C = 0.0f;
+  }
+
+  //----- (0043F2A9) --------------------------------------------------------
+  ~BspRenderer_stru0()
+  {
+    //_eh_vector_destructor_iterator_(this->std__vector_0007AC, 24, 4, IndoorCameraD3D_Vec4::dtor);
+  }
+
+  unsigned __int16 uSectorID;
+  unsigned __int16 uViewportX;
+  unsigned __int16 uViewportY;
+  unsigned __int16 uViewportZ;
+  unsigned __int16 uViewportW;
+  __int16 field_A;
+  BspRenderer_stru2 field_C;
+  unsigned __int16 uFaceID;
+  __int16 field_7A6;
+  unsigned int std__vector_0007A8;
+  IndoorCameraD3D_Vec4 std__vector_0007AC[4];
+  RenderVertexSoft pVertices[4];
+};
+#pragma pack(pop)
+
+
+
+
+
+/*  163 */
+#pragma pack(push, 1)
+struct BspRenderer
+{
+  //----- (0043F282) --------------------------------------------------------
+  inline BspRenderer()
+  {
+   // _eh_vector_constructor_iterator_(field_FA8, 2252, 150,
+   //    (void (__thiscall *)(void *))stru170_stru0::stru170_stru0,
+   //    (void (__thiscall *)(void *))stru170_stru0::dtor);
+    uNumFaceIDs = 0;
+    std__vector_000FA8 = 0;
+    uNumVisibleNotEmptySectors = 0;
+  }
+
+  void PrepareFaceRenderList_sw(int a2, unsigned int uFaceID);
+  void PrepareFaceRenderList_d3d(signed int a2, unsigned int uFaceID);
+  void MakeVisibleSectorList();
+
+  unsigned int uNumFaceIDs;
+  __int16 pFaceIDs[150];
+  char field_130[3700];
+  unsigned int std__vector_000FA8;
+  BspRenderer_stru0 field_FA8[150];
+  unsigned int uNumVisibleNotEmptySectors;
+  unsigned __int16 pVisibleSectorIDs_toDrawDecorsActorsEtcFrom[6];
+};
+#pragma pack(pop)
+
+
+extern struct BspRenderer *pBspRenderer; // idb
+
+
+
+
+
+
+/*  160 */
+#pragma pack(push, 1)
+struct stru167
+{
+  char field_0;
+  char field_1;
+  char field_2;
+  char field_3;
+  char field_4;
+  char field_5;
+  __int16 field_6_rnd_value;
+  __int16 field_8_rnd_value;
+  __int16 field_A_rnd_value;
+  __int16 field_C_time_left;
+  __int16 field_E_time_to_live;
+  char field_10;
+  char field_11;
+  char field_12;
+  char field_13;
+  __int16 bgr16;
+  char field_16;
+  char field_17;
+};
+#pragma pack(pop)
+
+
+
+/*  363 */
+#pragma pack(push, 1)
+struct stru167_wrap
+{
+  void _440F07();
+  int Push(__int16 a2, __int16 a3, __int16 a4, int a5, __int16 bgr);
+  void _440E91(__int16 x, int y, int z, int a5, __int16 bgr);
+
+  stru167 pElements[100];
+  int uNumElements;
+  int field_964;
+};
+#pragma pack(pop)
+extern stru167_wrap array_5118E8;
+
+
+
+
+
+
+
+
+
+
+
+/*  358 */
+#pragma pack(push, 1)
+struct stru320
+{
+  int field_0;
+  Plane_int_ plane_4;
+  Vec3_int_ vec_14;
+  Vec3_int_ vec_20;
+  unsigned int uCurrentAmbientLightLevel;
+  int field_30;
+  int field_34;
+  int field_38;
+  int pDeltaUV[2];
+  int field_44;
+  int field_48;
+  char field_4C[8];
+  Vec3_int_ rotated_normal;
+  Vec3_int_ vec_60;
+  int field_6C;
+  Vec3_int_ vec_70;
+  int field_7C;
+  Vec3_int_ vec_80;
+  Vec3_int_ vec_8C;
+  int field_98;
+  Vec3_int_ vec_9C;
+  int field_A8;
+  unsigned int uNumLightsApplied;
+  int _blv_lights_radii[20];
+  int _blv_lights_inv_radii[20];
+  int _blv_lights_xs[20];
+  int _blv_lights_ys[20];
+  int _blv_lights_light_dot_faces[20];
+  int field_240;
+  int field_244;
+  int field_248;
+  int field_24C;
+  int field_250;
+  int field_254;
+  int field_258;
+  int field_25C;
+  int field_260;
+  int field_264;
+  int field_268;
+  int field_26C;
+  int field_270;
+  int field_274;
+  int field_278;
+  int field_27C;
+  int field_280;
+  int field_284;
+  int field_288;
+  int field_28C;
+  int _blv_lights_zs[20];
+  float _blv_lights_rs[20];
+  float _blv_lights_gs[20];
+  float _blv_lights_bs[20];
+  char _blv_lights_types[20];
+  int field_3E4;
+  int field_3E8;
+  int field_3EC;
+  int field_3F0;
+  int field_3F4;
+  unsigned int uDefaultAmbientLightLevel;
+};
+#pragma pack(pop)
+
+extern stru320 stru_F8AD28; // idb
+
+
+
+
+
+
+
+
+/*  345 */
+#pragma pack(push, 1)
+struct stru315
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+  int field_2C;
+  int field_30;
+  unsigned __int16 *field_34_palette;
+  unsigned __int16 *pTextureLOD;
+  unsigned int *pDepthBuffer;
+  unsigned __int16 *pColorBuffer;
+};
+#pragma pack(pop)
+
+
+
+
+
+/*  346 */
+#pragma pack(push, 1)
+struct stru316
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  unsigned __int16 *field_24_palette;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+/*  134 */
+#pragma pack(push, 1)
+struct stru141
+{
+  int _47050A(int a2);
+
+  int field_0;
+  int prolly_normal_d;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  Vec3_int_ normal;
+  Vec3_int_ field_34;
+  Vec3_int_ normal2;
+  int field_4C;
+  int field_50;
+  int field_54;
+  Vec3_int_ field_58;
+  int field_64;
+  int field_68;
+  int field_6C;
+  int field_70;
+  unsigned int uSectorID;
+  unsigned int uFaceID;
+  int field_7C;
+  int field_80;
+  int field_84;
+  int field_88;
+  int sMaxX;
+  int sMinX;
+  int sMaxY;
+  int sMinY;
+  int sMaxZ;
+  int sMinZ;
+  int field_A4;
+};
+#pragma pack(pop)
+extern stru141 stru_721530;
+
+
+
+
+
+
+/*  378 */
+#pragma pack(push, 1)
+struct stru337_stru0
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+};
+#pragma pack(pop)
+
+
+
+/*  377 */
+#pragma pack(push, 1)
+struct stru337
+{
+  stru337_stru0 field_0;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+  int field_2C;
+  int field_30;
+  stru337_stru0 field_34;
+};
+#pragma pack(pop)
+extern stru337 stru_F81018;
+
+
+
+
+/*  147 */
+#pragma pack(push, 1)
+struct stru154
+{
+  //----- (0049B001) --------------------------------------------------------
+  inline stru154()
+  {}
+  
+  //----- (0049B027) --------------------------------------------------------
+  inline ~stru154()
+  {}
+
+  int _49B04D(struct ODMFace *a2, struct BSPVertexBuffer *a3);
+  int _49B0C9(struct Vec3_float_ *pNormal, float dist);
+  int _49B13D(struct ODMFace *pFace, struct BSPVertexBuffer *pVertices, struct Vec3_float_ *a3, float *a4);
+
+
+  void (__thiscall ***vdestructor_ptr)(stru154 *, bool);
+  Plane_float_ face_plane;
+  PolygonType polygonType;
+  char field_15;
+  char field_16;
+  char field_17;
+};
+#pragma pack(pop)
+
+
+
+
+
+/*  392 */
+#pragma pack(push, 1)
+struct stru352
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+  int field_2C;
+  int field_30;
+  int field_34;
+};
+#pragma pack(pop)
+extern stru352 stru_F83B80[480];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Items.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2284 @@
+#include <stdlib.h>
+
+#include "Items.h"
+#include "MapInfo.h"
+#include "FrameTableInc.h"
+#include "Allocator.h"
+#include "LOD.h"
+#include "Monsters.h"
+#include "Party.h"
+#include "FactionTable.h"
+#include "StorylineTextTable.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+ItemGen *ptr_50C9A4;
+
+struct ItemsTable *pItemsTable;
+
+
+
+
+
+//----- (00439DF3) --------------------------------------------------------
+int ItemGen::_439DF3_get_additional_damage(int *a2, int *a3)
+{
+  int *v3; // edi@1
+  ItemGen *v4; // ebx@1
+  signed int v5; // esi@1
+  unsigned int v7; // ecx@5
+  signed int v8; // ebx@7
+  int v9; // edx@22
+  int v10; // eax@24
+  int v11; // edx@25
+  int v12; // ebx@28
+  int v13; // ebx@29
+  int v14; // ebx@30
+  int v15; // ebx@31
+  int v16; // ebx@32
+  signed int v17; // [sp-4h] [bp-10h]@24
+
+  auto a1 = this;
+  v3 = a2;
+  v4 = a1;
+  v5 = 0;
+  *a2 = 0;
+  if ( !a1->uItemID )
+    return 0;
+  UpdateTempBonus(pParty->uTimePlayed);
+  if ( v4->uItemID == 501 )
+  {
+LABEL_45:
+    *v3 = 1;
+    v10 = rand();
+    v17 = 10;
+    return v10 % v17 + 6;
+  }
+  if ( v4->uItemID == 507 )
+  {
+    *v3 = 0;
+    v11 = rand() % 16;
+    return v11 + 3;
+  }
+  v7 = 3;
+  if ( v4->uItemID == 510 )
+  {
+    *v3 = 2;
+    v9 = rand() % 4;
+    return v9 + 9;
+  }
+  if ( v4->uItemID == 517 )
+    goto LABEL_36;
+  v8 = v4->uAdditionalValue;
+  if ( v8 > 46 )
+  {
+LABEL_42:
+    v5 = 0;
+    goto LABEL_37;
+  }
+  if ( v8 == 46 )
+  {
+    *v3 = 0;
+    return rand() % 11 + 10;
+  }
+  if ( v8 > 11 )
+  {
+    v12 = v8 - 12;
+    if ( !v12 )
+    {
+      *v3 = 0;
+      return GetDiceResult(v7, 6u);
+    }
+    v13 = v12 - 1;
+    if ( !v13 )
+    {
+      *v3 = 8;
+      return 5;
+    }
+    v14 = v13 - 1;
+    if ( v14 )
+    {
+      v15 = v14 - 1;
+      if ( v15 )
+      {
+        v16 = v15 - 1;
+        if ( !v16 || v16 == 25 )
+        {
+          *v3 = 10;
+          *a3 = 1;
+          return v5;
+        }
+        goto LABEL_42;
+      }
+      *v3 = 2;
+      return 12;
+    }
+LABEL_36:
+    v5 = 8;
+LABEL_37:
+    *v3 = v5;
+    return v5;
+  }
+  if ( v8 == 11 )
+  {
+    *v3 = 0;
+    v7 = 2;
+    return GetDiceResult(v7, 6u);
+  }
+  if ( v8 == 4 )
+  {
+    *v3 = 2;
+    v11 = rand() % 2;
+    return v11 + 3;
+  }
+  if ( v8 == 5 )
+  {
+    *v3 = 2;
+    v10 = rand();
+    v17 = 3;
+    return v10 % v17 + 6;
+  }
+  if ( v8 == 6 )
+  {
+    *v3 = 2;
+    v9 = rand() % 4;
+    return v9 + 9;
+  }
+  if ( v8 == 7 )
+  {
+    *v3 = 1;
+    return rand() % 4 + 2;
+  }
+  if ( v8 == 8 )
+  {
+    *v3 = 1;
+    return rand() % 7 + 4;
+  }
+  if ( v8 == 9 )
+    goto LABEL_45;
+  if ( v8 != 10 )
+    goto LABEL_42;
+  *v3 = 0;
+  v7 = 1;
+  return GetDiceResult(v7, 6u);
+}
+
+
+//----- (00402F07) --------------------------------------------------------
+void ItemGen::Reset()
+{
+  this->field_1A = 0;
+  this->uAttributes = 0;
+  this->uNumCharges = 0;
+  this->uAdditionalValue = 0;
+  this->_bonus_strength = 0;
+  this->_bonus_type = 0;
+  this->uItemID = 0;
+  this->uBodyAnchor = 0;
+  this->uExpireTime = 0i64;
+}
+
+//----- (00458260) --------------------------------------------------------
+void ItemGen::UpdateTempBonus(__int64 uTimePlayed)
+{
+  unsigned int v2; // eax@1
+
+  v2 = this->uAttributes;
+  if ( v2 & ITEM_TEMP_BONUS )
+  {
+    if ( uTimePlayed > (signed __int64)this->uExpireTime )
+    {
+      this->_bonus_type = 0;
+      LOBYTE(v2) = v2 & 0xF7;
+      this->uAdditionalValue = 0;
+      this->uAttributes = v2;
+    }
+  }
+}
+
+//----- (0045814E) --------------------------------------------------------
+char *ItemsTable::Release()
+{
+  ItemsTable *v1; // edi@1
+  char *result; // eax@23
+
+  v1 = this;
+  if ( pMonstersTXT_Raw )
+    pAllocator->FreeChunk(pMonstersTXT_Raw);
+  if ( pMonsterPlacementTXT_Raw )
+    pAllocator->FreeChunk(pMonsterPlacementTXT_Raw);
+  if ( pSkillDescTXT_Raw )
+    pAllocator->FreeChunk(pSkillDescTXT_Raw);
+  if ( v1->pSpcItemsTXT_Raw )
+    pAllocator->FreeChunk(v1->pSpcItemsTXT_Raw);
+  if ( v1->pStdItemsTXT_Raw )
+    pAllocator->FreeChunk(v1->pStdItemsTXT_Raw);
+  if ( v1->pRndItemsTXT_Raw )
+    pAllocator->FreeChunk(v1->pRndItemsTXT_Raw);
+  if ( v1->pItemsTXT_Raw )
+    pAllocator->FreeChunk(v1->pItemsTXT_Raw);
+  if ( pHostileTXT_Raw )
+    pAllocator->FreeChunk(pHostileTXT_Raw);
+  if ( pHistoryTXT_Raw )
+    pAllocator->FreeChunk(pHistoryTXT_Raw);
+  if ( pPotionsTXT_Raw )
+    pAllocator->FreeChunk(pPotionsTXT_Raw);
+  if ( pPotionNotesTXT_Raw )
+    pAllocator->FreeChunk(pPotionNotesTXT_Raw);
+  v1->pSpcItemsTXT_Raw = 0;
+  pSkillDescTXT_Raw = 0;
+  v1->pStdItemsTXT_Raw = 0;
+  v1->pRndItemsTXT_Raw = pSkillDescTXT_Raw;
+  result = pSkillDescTXT_Raw;
+  v1->pItemsTXT_Raw = pSkillDescTXT_Raw;
+  return result;
+}
+
+
+//----- (00456D84) --------------------------------------------------------
+void ItemsTable::Initialize()
+{
+  //ItemsTable *v1; // edi@1
+  char *v2; // eax@1
+  char *v3; // eax@2
+  char v4; // cl@3
+  int v5; // esi@3
+  char *v6; // esi@21
+  char *v7; // eax@21
+  char *v8; // ecx@22
+  char *v9; // eax@26
+  char v10; // dl@27
+  int v11; // ecx@27
+  int v12; // esi@31
+  char *v13; // eax@39
+  int v14; // esi@40
+  char v15; // cl@41
+  int v16; // eax@41
+  char v17; // zf@53
+  int v18; // eax@57
+  int *v19; // esi@66
+  char *v20; // edx@66
+  int v21; // eax@66
+  char *v22; // ecx@68
+  char *v23; // eax@71
+  int v24; // esi@71
+  char *v25; // ebx@72
+  char v26; // cl@73
+  int v27; // eax@73
+  char *v28; // ST3C_4@160
+  char *v29; // ST3C_4@163
+  char *v30; // eax@175
+  char *v31; // eax@188
+  char v32; // al@190
+  char *v33; // eax@199
+  const char *v34; // ebx@199
+  int v35; // esi@199
+  char *v36; // eax@200
+  char v37; // dl@201
+  int v38; // ecx@201
+  char *v39; // esi@229
+  char *v40; // eax@229
+  char *v41; // ecx@230
+  char *v42; // esi@233
+  char *v43; // eax@234
+  char v44; // dl@235
+  int v45; // ecx@235
+  signed int v46; // edi@287
+  char *v47; // ecx@288
+  char v48; // dl@289
+  int v49; // eax@289
+  int v50; // esi@293
+  signed int v51; // edi@312
+  char *v52; // ecx@312
+  char v53; // dl@313
+  int v54; // eax@313
+  int v55; // esi@317
+  signed int v56; // edi@348
+  char *v57; // eax@348
+  char v58; // dl@349
+  int v59; // ecx@349
+  int v60; // esi@353
+  char *Str; // [sp+Ch] [bp-18h]@1
+  signed int Stra; // [sp+Ch] [bp-18h]@22
+  signed int Strb; // [sp+Ch] [bp-18h]@25
+  signed int Strc; // [sp+Ch] [bp-18h]@39
+  signed int Strd; // [sp+Ch] [bp-18h]@66
+  signed int Stre; // [sp+Ch] [bp-18h]@156
+  const char **Strf; // [sp+Ch] [bp-18h]@176
+  const char **Strg; // [sp+Ch] [bp-18h]@182
+  signed int Strh; // [sp+Ch] [bp-18h]@230
+  signed int Stri; // [sp+Ch] [bp-18h]@311
+  char **Strj; // [sp+Ch] [bp-18h]@347
+  int v72; // [sp+10h] [bp-14h]@7
+  signed int v73; // [sp+10h] [bp-14h]@21
+  int v74; // [sp+10h] [bp-14h]@45
+  int v75; // [sp+10h] [bp-14h]@77
+  int v76; // [sp+10h] [bp-14h]@205
+  signed int v77; // [sp+10h] [bp-14h]@229
+  int v78; // [sp+10h] [bp-14h]@239
+  signed int v79; // [sp+14h] [bp-10h]@1
+  char *v80; // [sp+14h] [bp-10h]@39
+  char *v81; // [sp+14h] [bp-10h]@175
+  char *v82; // [sp+14h] [bp-10h]@188
+  int v83; // [sp+18h] [bp-Ch]@67
+  size_t v84; // [sp+18h] [bp-Ch]@156
+  signed int v85; // [sp+18h] [bp-Ch]@176
+  signed int v86; // [sp+18h] [bp-Ch]@182
+  signed int v87; // [sp+18h] [bp-Ch]@233
+  signed int v88; // [sp+1Ch] [bp-8h]@2
+  signed int v89; // [sp+1Ch] [bp-8h]@26
+  signed int v90; // [sp+1Ch] [bp-8h]@40
+  signed int v91; // [sp+1Ch] [bp-8h]@72
+  signed int v92; // [sp+1Ch] [bp-8h]@200
+  signed int v93; // [sp+1Ch] [bp-8h]@234
+  signed int v94; // [sp+1Ch] [bp-8h]@288
+  signed int v95; // [sp+1Ch] [bp-8h]@312
+  signed int v96; // [sp+1Ch] [bp-8h]@348
+  signed int v97; // [sp+20h] [bp-4h]@2
+  signed int v98; // [sp+20h] [bp-4h]@26
+  signed int v99; // [sp+20h] [bp-4h]@40
+  signed int v100; // [sp+20h] [bp-4h]@72
+  signed int v101; // [sp+20h] [bp-4h]@200
+  signed int v102; // [sp+20h] [bp-4h]@234
+  signed int v103; // [sp+20h] [bp-4h]@288
+
+  //v1 = this;
+
+  pMapStats = new MapStats;
+  pMapStats->Initialize();
+
+  pMonsterStats = new MonsterStats;
+  pMonsterStats->Initialize();
+  pMonsterStats->InitializePlacements();
+
+  pSpellStats = new SpellStats;
+  pSpellStats->Initialize();
+
+  LoadPotions();
+  LoadPotionNotes();
+
+  pFactionTable = new FactionTable;
+  pFactionTable->Initialize();
+
+  pStorylineText = new StorylineText;
+  pStorylineText->Initialize();
+
+  pStdItemsTXT_Raw = 0;
+  v2 = (char *)pEvents_LOD->LoadRaw("stditems.txt", 0);
+  pStdItemsTXT_Raw = v2;
+  strtok(v2, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  Str = (char *)&pEnchantments[0].pParam;
+  v79 = 24;
+  do
+  {
+    v3 = strtok(0, "\r") + 1;
+    v97 = 0;
+    v88 = 0;
+    do
+    {
+      v4 = *v3;
+      v5 = 0;
+      while ( v4 != 9 && v4 )
+      {
+        ++v5;
+        v4 = v3[v5];
+      }
+      v72 = (int)&v3[v5];
+      if ( !v3[v5] )
+        v88 = 1;
+      v3[v5] = 0;
+      if ( v5 )
+      {
+        if ( v97 )
+        {
+          if ( v97 == 1 )
+          {
+            *(unsigned int *)Str = (int)RemoveQuotes(v3);
+          }
+          else
+          {
+            if ( v97 > 1 )
+              Str[v97 + 6] = atoi(v3);
+          }
+        }
+        else
+        {
+          *((char **)Str + 1) = RemoveQuotes(v3);
+        }
+      }
+      else
+      {
+        if ( !v97 )
+          v88 = 1;
+      }
+      ++v97;
+      v3 = (char *)(v72 + 1);
+    }
+    while ( v97 <= 10 && !v88 );
+    Str += 20;
+    --v79;
+  }
+  while ( v79 );
+  v6 = (char *)&field_116D8[3];
+  memset(&field_116D8[3], 0, 0x24u);
+  v7 = &pEnchantments[0].field_8[4];
+  v73 = 9;
+  do
+  {
+    v8 = v7;
+    Stra = 24;
+    do
+    {
+      *(unsigned int *)v6 += (unsigned __int8)*v8;
+      v8 += 20;
+      --Stra;
+    }
+    while ( Stra );
+    v6 += 4;
+    ++v7;
+    --v73;
+  }
+  while ( v73 );
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  Strb = 17856;
+  do
+  {
+    v9 = strtok(0, "\r") + 1;
+    v98 = 0;
+    v89 = 0;
+    do
+    {
+      v10 = *v9;
+      v11 = 0;
+      while ( v10 != 9 && v10 )
+      {
+        ++v11;
+        v10 = v9[v11];
+      }
+      v12 = (int)&v9[v11];
+      if ( !v9[v11] )
+        v89 = 1;
+      *(unsigned char *)v12 = 0;
+      if ( v11 && v98 > 1 )
+        *(&pItems[0].uItemID + v98 + Strb) = atoi(v9);
+      ++v98;
+      v9 = (char *)(v12 + 1);
+    }
+    while ( v98 < 4 && !v89 );
+    Strb += 2;
+  }
+  while ( Strb < 17868 );
+  pSpcItemsTXT_Raw = 0;
+  v13 = (char *)pEvents_LOD->LoadRaw("spcitems.txt", 0);
+  pSpcItemsTXT_Raw = v13;
+  strtok(v13, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  v80 = (char *)&pSpecialEnchantments[0].pParam;
+  Strc = 72;
+  do
+  {
+    v99 = 0;
+    v14 = (int)(strtok(0, "\r") + 1);
+    v90 = 0;
+    do
+    {
+      v15 = *(unsigned char *)v14;
+      v16 = 0;
+      while ( v15 != 9 && v15 )
+      {
+        ++v16;
+        v15 = *(unsigned char *)(v16 + v14);
+      }
+      v74 = v16 + v14;
+      if ( !*(unsigned char *)(v16 + v14) )
+        v90 = 1;
+      *(unsigned char *)(v16 + v14) = 0;
+      if ( v16 )
+      {
+        if ( v99 )
+        {
+          if ( v99 == 1 )
+          {
+            *(char **)v80 = RemoveQuotes((char *)v14);
+          }
+          else
+          {
+            if ( v99 <= 1 )
+            {
+              v17 = v99 == 14;
+            }
+            else
+            {
+              v17 = v99 == 14;
+              if ( v99 < 14 )
+              {
+                v80[v99 + 6] = atoi((const char *)v14);
+                goto LABEL_63;
+              }
+            }
+            if ( v17 )
+            {
+              v18 = atoi((const char *)v14);
+              *((unsigned int *)v80 + 5) = v18;
+              if ( !v18 )
+                *((unsigned int *)v80 + 5) = atoi((const char *)(v14 + 1));
+            }
+            else
+            {
+              if ( v99 == 15 )
+                v80[24] = tolower(*(unsigned char *)v14) - 97;
+            }
+          }
+        }
+        else
+        {
+          *((char **)v80 + 1) = RemoveQuotes((char *)v14);
+        }
+      }
+      else
+      {
+        if ( !v99 )
+          v90 = 1;
+      }
+LABEL_63:
+      ++v99;
+      v14 = v74 + 1;
+    }
+    while ( v99 <= 15 && !v90 );
+    v80 += 28;
+    --Strc;
+  }
+  while ( Strc );
+  v19 = field_11738;
+  memset(field_11738, 0, 0x60u);
+  v20 = &pSpecialEnchantments[0].field_8[4];
+  Strd = 12;
+  v21 = 71;
+  field_11798 = 71;
+  do
+  {
+    v83 = 0;
+    if ( v21 > 0 )
+    {
+      v22 = v20;
+      do
+      {
+        *v19 += (unsigned __int8)*v22;
+        ++v83;
+        v21 = field_11798;
+        v22 += 28;
+      }
+      while ( v83 < v21 );
+    }
+    ++v19;
+    ++v20;
+    --Strd;
+  }
+  while ( Strd );
+  Initialize2DA();
+  pItemsTXT_Raw = 0;
+  v23 = (char *)pEvents_LOD->LoadRaw("items.txt", 0);
+  pItemsTXT_Raw = v23;
+  strtok(v23, "\r");
+  v24 = 0;
+  strtok(0, "\r");
+  pItems[0].uItemID = 0;
+  while ( 2 )
+  {
+    v100 = 0;
+    v25 = strtok(0, "\r") + 1;
+    v91 = 0;
+    while ( 2 )
+    {
+      v26 = *v25;
+      v27 = 0;
+      while ( v26 != 9 && v26 )
+      {
+        ++v27;
+        v26 = v25[v27];
+      }
+      v75 = (int)&v25[v27];
+      if ( !v25[v27] )
+        v91 = 1;
+      v25[v27] = 0;
+      if ( v27 )
+      {
+        switch ( v100 )
+        {
+          case 0:
+            v24 = atoi(v25);
+            break;
+          case 1:
+            pItems[v24].pIconName = (char *)RemoveQuotes(v25);
+            break;
+          case 2:
+            pItems[v24].pName = (char *)RemoveQuotes(v25);
+            break;
+          case 3:
+            pItems[v24].uValue = atoi(v25);
+            break;
+          case 4:
+            if ( !_strcmpi(v25, "weapon") )
+              goto LABEL_89;
+            if ( _strcmpi(v25, "weapon2") )
+            {
+              if ( _strcmpi(v25, "weapon1or2") )
+              {
+                if ( _strcmpi(v25, "missile") && _strcmpi(v25, "bow") )
+                {
+                  if ( _strcmpi(v25, "armor") )
+                  {
+                    if ( _strcmpi(v25, "shield") )
+                    {
+                      if ( _strcmpi(v25, "helm") )
+                      {
+                        if ( _strcmpi(v25, "belt") )
+                        {
+                          if ( _strcmpi(v25, "cloak") )
+                          {
+                            if ( _strcmpi(v25, "gauntlets") )
+                            {
+                              if ( _strcmpi(v25, "boots") )
+                              {
+                                if ( _strcmpi(v25, "ring") )
+                                {
+                                  if ( _strcmpi(v25, "amulet") )
+                                  {
+                                    if ( _strcmpi(v25, "weaponw") )
+                                    {
+                                      if ( _strcmpi(v25, "herb") && _strcmpi(v25, "reagent") )
+                                      {
+                                        if ( _strcmpi(v25, "bottle") )
+                                        {
+                                          if ( _strcmpi(v25, "sscroll") )
+                                          {
+                                            if ( _strcmpi(v25, "book") )
+                                            {
+                                              if ( _strcmpi(v25, "mscroll") )
+                                              {
+                                                if ( _strcmpi(v25, "gold") )
+                                                {
+                                                  if ( _strcmpi(v25, "gem") )
+                                                    pItems[v24].uEquipType = 20;
+                                                  else
+                                                    pItems[v24].uEquipType = 19;
+                                                }
+                                                else
+                                                {
+                                                  pItems[v24].uEquipType = 18;
+                                                }
+                                              }
+                                              else
+                                              {
+                                                pItems[v24].uEquipType = 17;
+                                              }
+                                            }
+                                            else
+                                            {
+                                              pItems[v24].uEquipType = 16;
+                                            }
+                                          }
+                                          else
+                                          {
+                                            pItems[v24].uEquipType = 15;
+                                          }
+                                        }
+                                        else
+                                        {
+                                          pItems[v24].uEquipType = 14;
+                                        }
+                                      }
+                                      else
+                                      {
+                                        pItems[v24].uEquipType = 13;
+                                      }
+                                    }
+                                    else
+                                    {
+                                      pItems[v24].uEquipType = 12;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    pItems[v24].uEquipType = 11;
+                                  }
+                                }
+                                else
+                                {
+                                  pItems[v24].uEquipType = 10;
+                                }
+                              }
+                              else
+                              {
+                                pItems[v24].uEquipType = 9;
+                              }
+                            }
+                            else
+                            {
+                              pItems[v24].uEquipType = 8;
+                            }
+                          }
+                          else
+                          {
+                            pItems[v24].uEquipType = 7;
+                          }
+                        }
+                        else
+                        {
+                          pItems[v24].uEquipType = 6;
+                        }
+                      }
+                      else
+                      {
+                        pItems[v24].uEquipType = 5;
+                      }
+                    }
+                    else
+                    {
+                      pItems[v24].uEquipType = 4;
+                    }
+                  }
+                  else
+                  {
+                    pItems[v24].uEquipType = 3;
+                  }
+                }
+                else
+                {
+                  pItems[v24].uEquipType = 2;
+                }
+              }
+              else
+              {
+LABEL_89:
+                pItems[v24].uEquipType = 0;
+              }
+            }
+            else
+            {
+              pItems[v24].uEquipType = 1;
+            }
+            break;
+          case 5:
+            if ( _strcmpi(v25, "staff") )
+            {
+              if ( _strcmpi(v25, "sword") )
+              {
+                if ( _strcmpi(v25, "dagger") )
+                {
+                  if ( _strcmpi(v25, "axe") )
+                  {
+                    if ( _strcmpi(v25, "spear") )
+                    {
+                      if ( _strcmpi(v25, "bow") )
+                      {
+                        if ( _strcmpi(v25, "mace") )
+                        {
+                          if ( _strcmpi(v25, "blaster") )
+                          {
+                            if ( _strcmpi(v25, "shield") )
+                            {
+                              if ( _strcmpi(v25, "leather") )
+                              {
+                                if ( _strcmpi(v25, "chain") )
+                                {
+                                  if ( _strcmpi(v25, "plate") )
+                                  {
+                                    if ( _strcmpi(v25, "club") )
+                                      pItems[v24].uSkillType = 38;
+                                    else
+                                      pItems[v24].uSkillType = 37;
+                                  }
+                                  else
+                                  {
+                                    pItems[v24].uSkillType = 11;
+                                  }
+                                }
+                                else
+                                {
+                                  pItems[v24].uSkillType = 10;
+                                }
+                              }
+                              else
+                              {
+                                pItems[v24].uSkillType = 9;
+                              }
+                            }
+                            else
+                            {
+                              pItems[v24].uSkillType = 8;
+                            }
+                          }
+                          else
+                          {
+                            pItems[v24].uSkillType = 7;
+                          }
+                        }
+                        else
+                        {
+                          pItems[v24].uSkillType = 6;
+                        }
+                      }
+                      else
+                      {
+                        pItems[v24].uSkillType = 5;
+                      }
+                    }
+                    else
+                    {
+                      pItems[v24].uSkillType = 4;
+                    }
+                  }
+                  else
+                  {
+                    pItems[v24].uSkillType = 3;
+                  }
+                }
+                else
+                {
+                  pItems[v24].uSkillType = 2;
+                }
+              }
+              else
+              {
+                pItems[v24].uSkillType = 1;
+              }
+            }
+            else
+            {
+              pItems[v24].uSkillType = 0;
+            }
+            break;
+          case 6:
+            Stre = 0;
+            v84 = strlen(v25);
+            if ( (signed int)v84 > 0 )
+            {
+              while ( tolower((unsigned __int8)v25[Stre]) != 'd' )
+              {
+                ++Stre;
+                if ( Stre >= (signed int)v84 )
+                  goto LABEL_161;
+              }
+              v25[Stre] = 0;
+              v28 = (char *)&pItems[v24];
+              v28[34] = atoi(v25);
+              v28[35] = atoi(&v25[Stre + 1]);
+              v25[Stre] = 'd';
+            }
+LABEL_161:
+            if ( Stre == v84 && tolower((unsigned __int8)*v25) != 115 )
+            {
+              v29 = (char *)&pItems[v24];
+              v29[34] = atoi(v25);
+              v29[35] = 1;
+            }
+            break;
+          case 7:
+            pItems[v24].uDamageMod = atoi(v25);
+            break;
+          case 8:
+            if ( _strcmpi(v25, "artifact") )
+            {
+              if ( _strcmpi(v25, "relic") )
+              {
+                if ( _strcmpi(v25, "special") )
+                  pItems[v24].uMaterial = 0;
+                else
+                  pItems[v24].uMaterial = 3;
+              }
+              else
+              {
+                pItems[v24].uMaterial = 2;
+              }
+            }
+            else
+            {
+              pItems[v24].uMaterial = 1;
+            }
+            break;
+          case 9:
+            BYTE2(pItems[v24 + 1].uItemID) = atoi(v25);
+            break;
+          case 10:
+            pItems[v24].pUnidentifiedName = (char *)RemoveQuotes(v25);
+            break;
+          case 11:
+            pItems[v24].uSpriteID = atoi(v25);
+            break;
+          case 12:
+            v30 = (char *)&pItems[v24];
+            v81 = v30;
+            if ( v30[37] == 3 )
+            {
+              v85 = 0;
+              Strf = (const char **)&pEnchantments[0].pParam;
+              while ( _strcmpi(*Strf, v25) )
+              {
+                ++v85;
+                Strf += 5;
+                if ( v85 >= 24 )
+                  goto LABEL_181;
+              }
+              v81[39] = v85 + 1;
+LABEL_181:
+              if ( !v81[39] )
+              {
+                v86 = 0;
+                Strg = (const char **)&pSpecialEnchantments[0].pParam;
+                while ( _strcmpi(*Strg, v25) )
+                {
+                  ++v86;
+                  Strg += 7;
+                  if ( v86 >= 72 )
+                    goto LABEL_196;
+                }
+                v81[38] = v86 + 1;
+              }
+            }
+            else
+            {
+              v30[38] = 0;
+              v30[39] = 0;
+            }
+            break;
+          case 13:
+            v31 = (char *)&pItems[v24];
+            v82 = v31;
+            if ( v31[37] == 3 && v31[39] )
+            {
+              v32 = atoi(v25);
+              v82[40] = v32;
+              if ( !v32 )
+                v82[40] = 1;
+            }
+            else
+            {
+              v31[40] = 0;
+            }
+            break;
+          case 14:
+            pItems[v24].uEquipX = atoi(v25);
+            break;
+          case 15:
+            pItems[v24].uEquipY = atoi(v25);
+            break;
+          case 16:
+            pItems[v24].pDescription = (char *)RemoveQuotes(v25);
+            break;
+          default:
+            break;
+        }
+      }
+LABEL_196:
+      ++v100;
+      v25 = (char *)(v75 + 1);
+      if ( v100 <= 16 && !v91 )
+        continue;
+      break;
+    }
+    ++v24;
+    if ( v24 < 800 )
+      continue;
+    break;
+  }
+  pRndItemsTXT_Raw = 0;
+  pItems[0].uItemID = v24;
+  v33 = (char *)pEvents_LOD->LoadRaw("rnditems.txt", 0);
+  v34 = "\r";
+  pRndItemsTXT_Raw = v33;
+  strtok(v33, "\r");
+  v35 = 0;
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  do
+  {
+    v101 = 0;
+    v36 = strtok(0, "\r") + 1;
+    v92 = 0;
+    do
+    {
+      v37 = *v36;
+      v38 = 0;
+      while ( v37 != 9 && v37 )
+      {
+        ++v38;
+        v37 = v36[v38];
+      }
+      v76 = (int)&v36[v38];
+      if ( !v36[v38] )
+        v92 = 1;
+      *(unsigned char *)v76 = 0;
+      if ( v38 )
+      {
+        if ( v101 )
+        {
+          switch ( v101 )
+          {
+            case 2:
+              pItems[v35].field_2C = atoi(v36);
+              break;
+            case 3:
+              pItems[v35].field_2D = atoi(v36);
+              break;
+            case 4:
+              pItems[v35].field_2E = atoi(v36);
+              break;
+            case 5:
+              pItems[v35].field_2F = atoi(v36);
+              break;
+            case 6:
+              *((unsigned char *)&pItems[0].uItemID + 16 * (3 * v35 + 3)) = atoi(v36);
+              break;
+            case 7:
+              BYTE1(pItems[v35 + 1].uItemID) = atoi(v36);
+              break;
+          }
+        }
+        else
+        {
+          v35 = atoi(v36);
+        }
+      }
+      else
+      {
+        if ( !v101 )
+          v92 = 1;
+      }
+      ++v101;
+      v36 = (char *)(v76 + 1);
+    }
+    while ( v101 <= 7 && !v92 );
+    ++v35;
+  }
+  while ( v35 < 619 );
+  if ( pRndItemsTXT_Raw )
+  {
+    pAllocator->FreeChunk(pRndItemsTXT_Raw);
+    pRndItemsTXT_Raw = 0;
+  }
+  v39 = (char *)field_11684;
+  memset(field_11684, 0, 0x18u);
+  v40 = &pItems[0].field_2C;
+  v77 = 6;
+  do
+  {
+    v41 = v40;
+    Strh = 800;
+    do
+    {
+      *(unsigned int *)v39 += (unsigned __int8)*v41;
+      v41 += 48;
+      --Strh;
+    }
+    while ( Strh );
+    v39 += 4;
+    ++v40;
+    --v77;
+  }
+  while ( v77 );
+  v42 = 0;
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  v87 = 0;
+  do
+  {
+    v43 = strtok(v42, "\r") + 1;
+    v102 = (signed int)v42;
+    v93 = (signed int)v42;
+    do
+    {
+      v44 = *v43;
+      v45 = 0;
+      while ( v44 != 9 && v44 )
+      {
+        ++v45;
+        v44 = v43[v45];
+      }
+      v78 = (int)&v43[v45];
+      if ( !v43[v45] )
+        v93 = 1;
+      v42 = 0;
+      *(unsigned char *)v78 = 0;
+      if ( v45 )
+      {
+        switch ( v102 )
+        {
+          case 2:
+            if ( v87 )
+            {
+              if ( v87 == 1 )
+              {
+                *(unsigned int *)&field_1169C[24] = atoi(v43);
+              }
+              else
+              {
+                if ( v87 == 2 )
+                  *(unsigned int *)&field_1169C[48] = atoi(v43);
+              }
+            }
+            else
+            {
+              *(unsigned int *)&field_1169C[0] = atoi(v43);
+            }
+            break;
+          case 3:
+            if ( v87 )
+            {
+              if ( v87 == 1 )
+              {
+                *(unsigned int *)&field_1169C[28] = atoi(v43);
+              }
+              else
+              {
+                if ( v87 == 2 )
+                  *(unsigned int *)&field_1169C[52] = atoi(v43);
+              }
+            }
+            else
+            {
+              *(unsigned int *)&field_1169C[4] = atoi(v43);
+            }
+            break;
+          case 4:
+            if ( v87 )
+            {
+              if ( v87 == 1 )
+              {
+                *(unsigned int *)&field_1169C[32] = atoi(v43);
+              }
+              else
+              {
+                if ( v87 == 2 )
+                  *(unsigned int *)&field_1169C[56] = atoi(v43);
+              }
+            }
+            else
+            {
+              *(unsigned int *)&field_1169C[8] = atoi(v43);
+            }
+            break;
+          case 5:
+            if ( v87 )
+            {
+              if ( v87 == 1 )
+              {
+                *(unsigned int *)&field_1169C[36] = atoi(v43);
+              }
+              else
+              {
+                if ( v87 == 2 )
+                  field_116D8[0] = atoi(v43);
+              }
+            }
+            else
+            {
+              *(unsigned int *)&field_1169C[12] = atoi(v43);
+            }
+            break;
+          case 6:
+            if ( v87 )
+            {
+              if ( v87 == 1 )
+              {
+                *(unsigned int *)&field_1169C[40] = atoi(v43);
+              }
+              else
+              {
+                if ( v87 == 2 )
+                  field_116D8[1] = atoi(v43);
+              }
+            }
+            else
+            {
+              *(unsigned int *)&field_1169C[16] = atoi(v43);
+            }
+            break;
+          case 7:
+            if ( v87 )
+            {
+              if ( v87 == 1 )
+              {
+                *(unsigned int *)&field_1169C[44] = atoi(v43);
+              }
+              else
+              {
+                if ( v87 == 2 )
+                  field_116D8[2] = atoi(v43);
+              }
+            }
+            else
+            {
+              *(unsigned int *)&field_1169C[20] = atoi(v43);
+            }
+            break;
+        }
+      }
+      ++v102;
+      v43 = (char *)(v78 + 1);
+    }
+    while ( v102 <= 7 && !v93 );
+    ++v87;
+  }
+  while ( v87 < 3 );
+  pSkillDescTXT_Raw = 0;
+  pSkillDescTXT_Raw = (char *)pEvents_LOD->LoadRaw("skilldes.txt", 0);
+  strtok(pSkillDescTXT_Raw, "\r");
+  v46 = 0;
+  do
+  {
+    v103 = 0;
+    v94 = 0;
+    v47 = strtok(0, "\r") + 1;
+    do
+    {
+      v48 = *v47;
+      v49 = 0;
+      while ( v48 != 9 && v48 )
+      {
+        ++v49;
+        v48 = v47[v49];
+      }
+      v50 = (int)&v47[v49];
+      if ( !v47[v49] )
+        v94 = 1;
+      *(unsigned char *)v50 = 0;
+      if ( v49 )
+      {
+        switch ( v103 )
+        {
+          case 1:
+            pSkillDesc[v46] = (char *)RemoveQuotes(v47);
+            break;
+          case 2:
+            pNormalSkillDesc[v46] = (char *)RemoveQuotes(v47);
+            break;
+          case 3:
+            pExpertSkillDesc[v46] = (char *)RemoveQuotes(v47);
+            break;
+          case 4:
+            pMasterSkillDesc[v46] = (char *)RemoveQuotes(v47);
+            break;
+          case 5:
+            pGrandSkillDesc[v46] = (char *)RemoveQuotes(v47);
+            break;
+        }
+      }
+      else
+      {
+        if ( !v103 )
+          v94 = 1;
+      }
+      ++v103;
+      v47 = (char *)(v50 + 1);
+    }
+    while ( v103 <= 5 && !v94 );
+    ++v46;
+  }
+  while ( v46 < 37 );
+  pStatsTXT_Raw = 0;
+  pStatsTXT_Raw = (char *)pEvents_LOD->LoadRaw("stats.txt", 0);
+  strtok(pStatsTXT_Raw, "\r");
+  Stri = 0;
+  do
+  {
+    v51 = 0;
+    v95 = 0;
+    v52 = strtok(0, v34) + 1;
+    do
+    {
+      v53 = *v52;
+      v54 = 0;
+      if ( *v52 != 9 )
+      {
+        do
+        {
+          if ( !v53 )
+            break;
+          ++v54;
+          v53 = v52[v54];
+        }
+        while ( v53 != 9 );
+        v34 = "\r";
+      }
+      v55 = (int)&v52[v54];
+      if ( !v52[v54] )
+        v95 = 1;
+      *(unsigned char *)v55 = 0;
+      if ( v54 )
+      {
+        if ( v51 )
+        {
+          switch ( Stri )
+          {
+            case 0:
+            case 1:
+            case 2:
+            case 3:
+            case 4:
+            case 5:
+            case 6:
+              pAttributeDescriptions[Stri] = (char *)RemoveQuotes(v52);
+              break;
+            case 7:
+              pHealthPointsAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 8:
+              pArmourClassAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 9:
+              pSpellPointsAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 10:
+              pPlayerConditionAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 11:
+              pFastSpellAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 12:
+              pPlayerAgeAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 13:
+              pPlayerLevelAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 14:
+              pPlayerExperienceAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 15:
+              pAttackBonusAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 16:
+              pAttackDamageAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 17:
+              pMissleBonusAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 18:
+              pMissleDamageAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 19:
+              pFireResistanceAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 20:
+              pAirResistanceAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 21:
+              pWaterResistanceAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 22:
+              pEarthResistanceAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 23:
+              pMindResistanceAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 24:
+              pBodyResistanceAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            case 25:
+              pSkillPointsAttributeDescription = (char *)RemoveQuotes(v52);
+              break;
+            default:
+              break;
+          }
+        }
+      }
+      else
+      {
+        if ( !v51 )
+          v95 = 1;
+      }
+      ++v51;
+      v52 = (char *)(v55 + 1);
+    }
+    while ( v51 < 2 && !v95 );
+    ++Stri;
+  }
+  while ( Stri < 26 );
+  pClassTXT_Raw = 0;
+  pClassTXT_Raw = (char *)pEvents_LOD->LoadRaw("class.txt", 0);
+  strtok(pClassTXT_Raw, v34);
+  Strj = pClassDescriptions;
+  do
+  {
+    v56 = 0;
+    v57 = strtok(0, v34) + 1;
+    v96 = 0;
+    do
+    {
+      v58 = *v57;
+      v59 = 0;
+      if ( *v57 != 9 )
+      {
+        do
+        {
+          if ( !v58 )
+            break;
+          ++v59;
+          v58 = v57[v59];
+        }
+        while ( v58 != 9 );
+        v34 = "\r";
+      }
+      v60 = (int)&v57[v59];
+      if ( !v57[v59] )
+        v96 = 1;
+      *(unsigned char *)v60 = 0;
+      if ( v59 )
+      {
+        if ( v56 )
+          *Strj = (char *)RemoveQuotes(v57);
+      }
+      else
+      {
+        if ( !v56 )
+          v96 = 1;
+      }
+      ++v56;
+      v57 = (char *)(v60 + 1);
+    }
+    while ( v56 < 2 && !v96 );
+    ++Strj;
+  }
+  while ( (signed int)Strj <= (signed int)&pClassDescriptions[35] );
+}
+
+//----- (00456D17) --------------------------------------------------------
+void ItemsTable::SetSpecialBonus(ItemGen *pItem)
+{
+  ItemDesc *v2; // eax@1
+
+  v2 = &this->pItems[pItem->uItemID];
+  if ( v2->uMaterial == 3 )
+  {
+    pItem->_bonus_type = v2->_bonus_type;
+    pItem->uAdditionalValue = v2->_additional_value;
+    pItem->_bonus_strength = v2->_bonus_strength;
+  }
+}
+
+//----- (00456D43) --------------------------------------------------------
+bool ItemsTable::_456D43_is_material_equals_3(ItemGen *pItem)
+{
+  return this->pItems[pItem->uItemID].uMaterial == 3;
+}
+
+//----- (00456D5E) --------------------------------------------------------
+bool ItemsTable::_456D5E_is_some_material(ItemGen *pItem)
+{
+  unsigned __int8 v2; // al@1
+
+  v2 = this->pItems[pItem->uItemID].uMaterial;
+  return v2 == 3 || v2 == 1 || v2 == 2;
+}
+
+
+//----- (00453B3C) --------------------------------------------------------
+void ItemsTable::LoadPotions()
+{
+  char *i; // eax@3
+  signed int v2; // esi@11
+  char *v3; // eax@16
+  char *v4; // edi@16
+  __int16 v5; // ax@17
+  char *v6; // esi@17
+  CHAR Text; // [sp+Ch] [bp-6Ch]@26
+  ItemsTable *v8; // [sp+68h] [bp-10h]@1
+  int v9; // [sp+6Ch] [bp-Ch]@10
+  int v10; // [sp+70h] [bp-8h]@10
+  char *v11; // [sp+74h] [bp-4h]@4
+
+  v8 = this;
+  if ( pPotionsTXT_Raw )
+    pAllocator->FreeChunk(pPotionsTXT_Raw);
+  pPotionsTXT_Raw = 0;
+  pPotionsTXT_Raw = (char *)pEvents_LOD->LoadRaw("potion.txt", 0);
+  for ( i = strtok(pPotionsTXT_Raw, "\t\r\n"); ; i = strtok(0, "\t\r\n") )
+  {
+    v11 = i;
+    if ( !strcmp(i, "222") )
+      break;
+    if ( !v11 )
+    {
+LABEL_20:
+      MessageBoxA(0, "Error Pre-Parsing Potion Table", "Load Error", 0x10u);
+      return;
+    }
+  }
+  while ( 1 )
+  {
+    v11 = strtok(0, "\t\r\n");
+    if ( !strcmp(v11, "222") )
+      break;
+    if ( !v11 )
+      goto LABEL_20;
+  }
+  v9 = 0;
+  v10 = 30642;
+  do
+  {
+    v11 = 0;
+    v2 = 0;
+    do
+    {
+      if ( !strtok(0, "\r\t\n") )
+        break;
+      ++v2;
+    }
+    while ( v2 < 6 );
+    if ( v2 != 6 )
+      break;
+    v11 = 0;
+    do
+    {
+      v3 = strtok(0, "\r\t\n");
+      v4 = v3;
+      if ( !v3 )
+        break;
+      v5 = atoi(v3);
+      v6 = (char *)v8 + 2 * (uint)&v11[v10];
+      *(_WORD *)v6 = v5;
+      if ( !v5 )
+      {
+        if ( tolower((unsigned __int8)*v4) == 101 )
+          *(_WORD *)v6 = atoi(v4 + 1);
+        else
+          *(_WORD *)v6 = 0;
+      }
+      ++v11;
+    }
+    while ( (signed int)v11 < 50 );
+    if ( v11 != (char *)50 )
+      break;
+    strtok(0, "\r\t\n");
+    v10 += 50;
+    ++v9;
+  }
+  while ( v10 < 33142 );
+  if ( v9 != 50 )
+  {
+    wsprintfA(&Text, "Error Parsing Potion Table at Row: %d Column: %d", v9, v11);
+    MessageBoxA(0, &Text, "Parsing Error", 0x10u);
+  }
+  if ( pPotionsTXT_Raw )
+  {
+    pAllocator->FreeChunk(pPotionsTXT_Raw);
+    pPotionsTXT_Raw = 0;
+  }
+}
+
+//----- (00453CE5) --------------------------------------------------------
+void ItemsTable::LoadPotionNotes()
+{
+  char *i; // eax@3
+  signed int v2; // esi@11
+  char *v3; // eax@16
+  char *v4; // edi@16
+  __int16 v5; // ax@17
+  char *v6; // esi@17
+  CHAR *v7; // [sp-Ch] [bp-84h]@20
+  const CHAR *v8; // [sp-8h] [bp-80h]@20
+  UINT v9; // [sp-4h] [bp-7Ch]@20
+  CHAR Text; // [sp+Ch] [bp-6Ch]@26
+  ItemsTable *v11; // [sp+68h] [bp-10h]@1
+  int v12; // [sp+6Ch] [bp-Ch]@10
+  int v13; // [sp+70h] [bp-8h]@10
+  char *v14; // [sp+74h] [bp-4h]@4
+
+  v11 = this;
+  if ( pPotionNotesTXT_Raw )
+    pAllocator->FreeChunk(pPotionNotesTXT_Raw);
+  pPotionNotesTXT_Raw = 0;
+  pPotionNotesTXT_Raw = (char *)pEvents_LOD->LoadRaw("potnotes.txt", 0);
+  for ( i = strtok(pPotionNotesTXT_Raw, "\t\r\n"); ; i = strtok(0, "\t\r\n") )
+  {
+    v14 = i;
+    if ( !strcmp(i, "222") )
+      break;
+    if ( !v14 )
+    {
+LABEL_20:
+      v9 = 16;
+      v8 = "Load Error";
+      v7 = "Error Pre-Parsing Potion Table";
+LABEL_27:
+      MessageBoxA(0, v7, v8, v9);
+      return;
+    }
+  }
+  while ( 1 )
+  {
+    v14 = strtok(0, "\t\r\n");
+    if ( !strcmp(v14, "222") )
+      break;
+    if ( !v14 )
+      goto LABEL_20;
+  }
+  v12 = 0;
+  v13 = 33142;
+  do
+  {
+    v14 = 0;
+    v2 = 0;
+    do
+    {
+      if ( !strtok(0, "\r\t\n") )
+        break;
+      ++v2;
+    }
+    while ( v2 < 6 );
+    if ( v2 != 6 )
+      break;
+    v14 = 0;
+    do
+    {
+      v3 = strtok(0, "\r\t\n");
+      v4 = v3;
+      if ( !v3 )
+        break;
+      v5 = atoi(v3);
+      v6 = (char *)v11 + 2 * (unsigned int)&v14[v13];
+      *(unsigned short *)v6 = v5;
+      if ( !v5 )
+      {
+        if ( tolower((unsigned __int8)*v4) == 101 )
+          *(unsigned short *)v6 = atoi(v4 + 1);
+        else
+          *(unsigned short *)v6 = 0;
+      }
+      ++v14;
+    }
+    while ( (signed int)v14 < 50 );
+    if ( v14 != (char *)50 )
+      break;
+    strtok(0, "\r\t\n");
+    v13 += 50;
+    ++v12;
+  }
+  while ( v13 < 35642 );
+  if ( v12 != 50 )
+  {
+    wsprintfA(&Text, "Error Parsing Potion Autonote Table at Row: %d Column: %d", v12, v14);
+    v9 = 16;
+    v8 = "Parsing Error";
+    v7 = &Text;
+    goto LABEL_27;
+  }
+}
+
+
+//----- (00456442) --------------------------------------------------------
+unsigned int ItemGen::GetValue()
+{
+  ItemGen *v1; // esi@1
+  unsigned int uBaseValue; // edi@1
+  int v3; // eax@4
+  int v4; // esi@5
+  unsigned int result; // eax@7
+
+  v1 = this;
+  uBaseValue = pItemsTable->pItems[this->uItemID].uValue;
+  if ( this->uAttributes & ITEM_TEMP_BONUS || pItemsTable->_456D5E_is_some_material(this) )
+    goto LABEL_12;
+  if ( v1->_bonus_type )
+  {
+    v3 = 100 * v1->_bonus_strength;
+    return uBaseValue + v3;
+  }
+  v4 = v1->uAdditionalValue;
+  if ( !v4 )
+  {
+LABEL_12:
+    result = uBaseValue;
+  }
+  else
+  {
+    v3 = *(unsigned int *)&pItemsTable->pEnchantments[23].field_8[28 * v4 + 8];
+    if ( (unsigned int)v3 > 0xA )
+      return uBaseValue + v3;
+    result = uBaseValue * v3;
+  }
+  return result;
+}
+
+//----- (00456499) --------------------------------------------------------
+const char *ItemGen::GetDisplayName()
+{
+  const char *result; // eax@2
+
+  if ( this->uAttributes & ITEM_IDENTIFIED )
+    result = GetIdentifiedName();
+  else
+    result = pItemsTable->pItems[uItemID].pUnidentifiedName;
+  return result;
+}
+
+//----- (004564B3) --------------------------------------------------------
+const char *ItemGen::GetIdentifiedName()
+{
+  ItemGen *v1; // esi@1
+  unsigned int v2; // eax@1
+  unsigned __int8 v3; // cl@1
+  char *v4; // edi@4
+  char v5; // al@6
+  const char *v6; // esi@8
+  int v7; // eax@15
+  const char *v9; // [sp-Ch] [bp-14h]@14
+  const char *v10; // [sp-8h] [bp-10h]@4
+  char *v11; // [sp-4h] [bp-Ch]@4
+
+  v1 = this;
+  v2 = this->uItemID;
+  v3 = pItemsTable->pItems[v2].uEquipType;
+  if ( v3 >= EQUIP_REAGENT && (v3 <= EQUIP_POTION || v3 == EQUIP_GOLD) )
+  {
+    v11 = pItemsTable->pItems[v2].pName;
+    v4 = item__getname_buffer;
+    v10 = "%s";
+LABEL_10:
+    sprintf(v4, v10, v11);
+    return v4;
+  }
+  v4 = item__getname_buffer;
+  sprintf(item__getname_buffer, "%s", pItemsTable->pItems[v2].pName);
+  if ( v1->uItemID == 601 )
+  {
+    v5 = v1->field_1A;
+    if ( (unsigned __int8)v5 >= 1u )
+    {
+      if ( (unsigned __int8)v5 <= 4u )
+      {
+        v6 = pPlayers[(unsigned __int8)v5]->pName;
+        strlen(pPlayers[(unsigned __int8)v5]->pName);
+        v11 = (char *)v6;
+        if ( v6[strlen(v6) - 1] == 115 )
+          v10 = pGlobalTXT_LocalizationStrings[655];
+        else
+          v10 = pGlobalTXT_LocalizationStrings[654];
+        goto LABEL_10;
+      }
+    }
+  }
+  if ( !pItemsTable->_456D5E_is_some_material(v1) )
+  {
+    if ( v1->_bonus_type )
+    {
+      strcat(item__getname_buffer, " ");
+      v9 = (const char *)*((unsigned int *)&pItemsTable->pItems[799].uEquipType + 5 * v1->_bonus_type);
+    }
+    else
+    {
+      v7 = v1->uAdditionalValue;
+      if ( !v7 )
+        return v4;
+      if ( v7 == 16
+        || v7 == 39
+        || v7 == 40
+        || v7 == 45
+        || v7 == 56
+        || v7 == 57
+        || v7 == 58
+        || v7 == 60
+        || v7 == 61
+        || v7 == 59
+        || v7 == 63
+        || v7 == 64
+        || v7 == 67
+        || v7 == 68 )
+      {
+        sprintf(
+          item__getname_buffer,
+          "%s %s",
+          *(unsigned int *)&pItemsTable->pEnchantments[22].field_8[28 * v7 + 8],
+          pItemsTable->pItems[v1->uItemID].pName);
+        return v4;
+      }
+      strcat(item__getname_buffer, " ");
+      v9 = *(const char **)&pItemsTable->pEnchantments[22].field_8[28 * v1->uAdditionalValue + 8];
+    }
+    strcat(item__getname_buffer, v9);
+  }
+  return v4;
+}
+
+
+//----- (00456620) --------------------------------------------------------
+void ItemsTable::GenerateItem(int a2, int a3, ItemGen *pItem)
+{
+  ItemGen *v4; // esi@1
+  ItemsTable *v5; // edi@1
+  int v6; // ebx@3
+  int *v7; // ecx@33
+  int v8; // eax@34
+  int v9; // eax@39
+  int v10; // ebx@43
+  int v11; // ecx@47
+  unsigned int *v12; // edx@48
+  unsigned int v13; // eax@49
+  signed int v14; // ebx@52
+  int v15; // eax@53
+  signed int v16; // eax@55
+  int v17; // ebx@57
+  int v18; // edx@62
+  signed int v19; // ebx@70
+  unsigned __int8 v20; // al@81
+  int v21; // eax@84
+  int v22; // ebx@85
+  int v23; // eax@86
+  int v24; // ebx@86
+  int v25; // edx@86
+  int v26; // edx@89
+  unsigned int v27; // eax@89
+  int i; // ebx@89
+  unsigned int v29; // ecx@90
+  int v30; // ebx@91
+  int v31; // eax@91
+  int v32; // ecx@91
+  int v33; // eax@91
+  int v34; // eax@97
+  unsigned __int8 v35; // sf@97
+  unsigned __int8 v36; // of@97
+  int v37; // ebx@98
+  int v38; // edx@99
+  signed int v39; // ebx@101
+  int v40; // ecx@102
+  char v41; // zf@107
+  char v42; // al@108
+  char v43; // al@111
+  int *v44; // edx@118
+  int v45; // eax@120
+  int v46; // edx@120
+  int *j; // eax@121
+  unsigned int v48; // ecx@123
+  int v49; // eax@123
+  int v50; // eax@123
+  unsigned char Dst[0xC80]; // [sp+Ch] [bp-C88h]@33
+  int v52; // [sp+C8Ch] [bp-8h]@33
+  int v53; // [sp+C90h] [bp-4h]@1
+  int v54; // [sp+C9Ch] [bp+8h]@3
+  int v55; // [sp+CA0h] [bp+Ch]@34
+  signed int v56; // [sp+CA0h] [bp+Ch]@55
+  int v57; // [sp+CA0h] [bp+Ch]@62
+  int *v58; // [sp+CA0h] [bp+Ch]@102
+  int v59; // [sp+CA0h] [bp+Ch]@123
+  signed int a2a; // [sp+CA4h] [bp+10h]@33
+  int a2b; // [sp+CA4h] [bp+10h]@101
+  int a2c; // [sp+CA4h] [bp+10h]@120
+
+  v53 = -1;
+  v4 = pItem;
+  v5 = this;
+  if ( !pItem )
+    v4 = (ItemGen *)pAllocator->AllocNamedChunk(pItem, 0x24u, "newItemGen");
+  memset(v4, 0, 0x24u);
+  v6 = a2 - 1;
+  v54 = a2 - 1;
+  if ( a3 )
+  {
+    switch ( a3 )
+    {
+      case 20:
+        a3 = EQUIP_ONE_OR_TWO_HANDS;
+        break;
+      case 21:
+        a3 = 3;
+        break;
+      case 22:
+        v53 = 38;
+        break;
+      case 23:
+        v53 = 1;
+        break;
+      case 24:
+        v53 = 2;
+        break;
+      case 25:
+        v53 = 3;
+        break;
+      case 26:
+        v53 = 4;
+        break;
+      case 27:
+        v53 = 5;
+        break;
+      case 28:
+        v53 = 6;
+        break;
+      case 30:
+        v53 = 0;
+        break;
+      case 31:
+        v53 = 9;
+        break;
+      case 32:
+        v53 = 10;
+        break;
+      case 33:
+        v53 = 0xBu;
+        break;
+      case 34:
+        a3 = 4;
+        break;
+      case 35:
+        a3 = 5;
+        break;
+      case 36:
+        a3 = 6;
+        break;
+      case 37:
+        a3 = 7;
+        break;
+      case 38:
+        a3 = 8;
+        break;
+      case 39:
+        a3 = EQUIP_BOOTS;
+        break;
+      case 40:
+        a3 = EQUIP_RING;
+        break;
+      case 41:
+        a3 = 0xBu;
+        break;
+      case 42:
+        a3 = EQUIP_C;
+        break;
+      case 43:
+        a3 = EQUIP_F;
+        break;
+      case 44:
+        a3 = EQUIP_POTION;
+        break;
+      case 45:
+        a3 = EQUIP_REAGENT;
+        break;
+      case 46:
+        a3 = EQUIP_GEM;
+        break;
+      case 29:
+        v53 = 37;
+        break;
+      default:
+        --a3;
+        break;
+    }
+    memset(&Dst, 0, 0xC80u);
+    v52 = 0;
+    v7 = (int *)&Dst;
+    a2a = 1;
+    if ( v53 == -1 )
+    {
+      v53 = (int)&v5->pItems[1].uEquipType;
+      v9 = (int)(&v5->pItems[1].field_2C + v6);
+      do
+      {
+        if ( *(unsigned char *)v53 == a3 )
+        {
+          *v7 = a2a;
+          ++v7;
+          v52 += *(unsigned char *)v9;
+        }
+        ++a2a;
+        v53 += 48;
+        v9 += 48;
+      }
+      while ( a2a < 500 );
+    }
+    else
+    {
+      v55 = (int)&v5->pItems[1].uSkillType;
+      v8 = (int)(&v5->pItems[1].field_2C + v6);
+      do
+      {
+        if ( *(unsigned char *)v55 == v53 )
+        {
+          *v7 = a2a;
+          ++v7;
+          v52 += *(unsigned char *)v8;
+        }
+        ++a2a;
+        v55 += 48;
+        v8 += 48;
+      }
+      while ( a2a < 500 );
+    }
+    v10 = 0;
+    if ( v52 )
+      v10 = rand() % v52;
+    v4->uItemID = *(uint *)Dst;
+    if ( !Dst )
+      v4->uItemID = 1;
+    v11 = *(&v5->pItems[v4->uItemID].field_2C + v54);
+    if ( v11 < v10 )
+    {
+      v12 = (uint *)Dst;
+      do
+      {
+        ++v12;
+        v13 = *v12;
+        v4->uItemID = *v12;
+        v11 += *(&v5->pItems[v13].field_2C + v54);
+      }
+      while ( v11 < v10 );
+    }
+    if ( v5->pItems[v4->uItemID].uEquipType == EQUIP_POTION && v4->uItemID != ITEM_POTION_BOTTLE )
+    {
+      v4->_bonus_type = 0;
+      v14 = 2;
+      do
+      {
+        v4->_bonus_type += rand() % 4 + 1;
+        v15 = v4->_bonus_type;
+        --v14;
+      }
+      while ( v14 );
+LABEL_72:
+      v4->_bonus_type = v15 * (v54 + 1);
+      goto LABEL_73;
+    }
+  }
+  else
+  {
+    v16 = 0;
+    v56 = 0;
+    do
+      v56 += pParty->field_7BA[v16++];
+    while ( v16 < 29 );
+    v17 = rand() % 29;
+    if ( v54 == 5 && rand() % 100 < 5 && !pParty->field_7BA[v17] && v56 < 13 )
+    {
+      pParty->field_7BA[v17] = 1;
+      v4->uAttributes = 0;
+      v4->uItemID = v17 + 500;
+      v5->SetSpecialBonus(v4);
+      return;
+    }
+    v57 = 0;
+    v18 = rand() % v5->field_11684[v54];
+    v4->uItemID = 0;
+    if ( v18 > 0 )
+    {
+      do
+        v57 += *(&v5->pItems[v4->uItemID++ + 1].field_2C + v54);
+      while ( v57 < v18 );
+    }
+    if ( !v18 )
+      v4->uItemID = 1;
+    if ( !v4->uItemID )
+      v4->uItemID = 1;
+    if ( v5->pItems[v4->uItemID].uEquipType == EQUIP_POTION && v4->uItemID != ITEM_POTION_BOTTLE )
+    {
+      v4->_bonus_type = 0;
+      v19 = 2;
+      do
+      {
+        v4->_bonus_type += rand() % 4 + 1;
+        v15 = v4->_bonus_type;
+        --v19;
+      }
+      while ( v19 );
+      goto LABEL_72;
+    }
+  }
+LABEL_73:
+  if ( v4->uItemID == ITEM_SPELLBOOK_LIGHT_DIVINE_INTERVENTION
+    && !(unsigned __int16)_449B57_test_bit(pParty->_award_bits, 239) )
+    v4->uItemID = ITEM_SPELLBOOK_LIGHT_SUN_BURST;
+  if ( BYTE2(pItemsTable->pItems[v4->uItemID + 1].uItemID) )
+    v4->uAttributes = 0;
+  else
+    v4->uAttributes = 1;
+  if ( v5->pItems[v4->uItemID].uEquipType != EQUIP_POTION )
+  {
+    v4->uAdditionalValue = 0;
+    v4->_bonus_type = 0;
+  }
+  v20 = v5->pItems[v4->uItemID].uEquipType;
+  if ( v20 <= EQUIP_BOW )
+  {
+    v37 = (int)&v5->field_1169C[4 * v54 + 48];
+    if ( !*(unsigned int *)v37 )
+      return;
+    v38 = rand() % 100;
+    v36 = __OFSUB__(v38, *(unsigned int *)v37);
+    v35 = v38 - *(unsigned int *)v37 < 0;
+  }
+  else
+  {
+    if ( v20 > EQUIP_AMULET )
+    {
+      if ( v20 == EQUIP_C )
+      {
+        v21 = rand() % 6 + pItemsTable->pItems[v4->uItemID].uDamageMod + 1;
+        v4->uNumCharges = v21;
+        v4->uMaxCharges = v21;
+      }
+      return;
+    }
+    v22 = (int)&v5->field_1169C[4 * v54];
+    if ( !*(unsigned int *)v22 )
+      return;
+    v23 = rand();
+    v24 = *(unsigned int *)v22;
+    v25 = v23 % 100;
+    if ( v23 % 100 < v24 )
+      goto LABEL_127;
+    if ( !*(unsigned int *)&v5->field_1169C[4 * v54 + 24] )
+      return;
+    if ( v25 < v24 )
+    {
+LABEL_127:
+      v26 = rand() % v5->field_116D8[v5->pItems[v4->uItemID].uEquipType];
+      v27 = v4->uItemID;
+      v4->_bonus_type = 0;
+      for ( i = v5->pEnchantments[0].field_8[v5->pItems[v27].uEquipType + 1];
+            i < v26;
+            i += v5->pEnchantments[v4->_bonus_type].field_8[v5->pItems[v29].uEquipType + 1] )
+      {
+        v29 = v4->uItemID;
+        ++v4->_bonus_type;
+      }
+      ++v4->_bonus_type;
+      v30 = v5->field_116D8[2 * v54 + 12];
+      v31 = rand();
+      v32 = v4->_bonus_type - 1;
+      v33 = v31 % (v5->field_116D8[2 * v54 + 13] - v30 + 1) + v30;
+      v4->_bonus_strength = v33;
+      if ( v32 == 21 || v32 == 22 || v32 == 23 )
+        v4->_bonus_strength = v33 >> 1;
+      if ( v4->_bonus_strength <= 0 )
+        v4->_bonus_strength = 1;
+      return;
+    }
+    v34 = v24 + *(unsigned int *)&v5->field_1169C[4 * v54 + 24];
+    v36 = __OFSUB__(v25, v34);
+    v35 = v25 - v34 < 0;
+  }
+  if ( !(v35 ^ v36) )
+    return;
+  memset(&Dst, 0, 0xC80u);
+  v39 = 0;
+  a2b = 0;
+  if ( v5->field_11798 > 0 )
+  {
+    v52 = -16 - (uint)v5;
+    v58 = (int *)&Dst;
+    v40 = (int)&v5->pSpecialEnchantments[1];
+    do
+    {
+      switch ( v54 )
+      {
+        case 2:
+          if ( !*(unsigned char *)v40 )
+            goto LABEL_117;
+          v41 = *(unsigned char *)v40 == 1;
+          break;
+        case 3:
+          v43 = *(unsigned char *)v40;
+          if ( !*(unsigned char *)v40 || v43 == 1 )
+          {
+LABEL_117:
+            v39 += *((unsigned char *)&v5->pItems[0].uItemID + v40 + v52 + v5->pItems[v4->uItemID].uEquipType);
+            if ( *((unsigned char *)&v5->pItems[0].uItemID + v40 + v52 + v5->pItems[v4->uItemID].uEquipType) )
+            {
+              v44 = v58;
+              ++v58;
+              *v44 = a2b;
+            }
+            goto LABEL_119;
+          }
+          v41 = v43 == 2;
+          break;
+        case 4:
+          v42 = *(unsigned char *)v40;
+          if ( *(unsigned char *)v40 == 1 || v42 == 2 )
+            goto LABEL_117;
+          v41 = v42 == 3;
+          break;
+        default:
+          if ( v54 != 5 )
+            goto LABEL_119;
+          v41 = *(unsigned char *)v40 == 3;
+          break;
+      }
+      if ( v41 )
+        goto LABEL_117;
+LABEL_119:
+      ++a2b;
+      v40 += 28;
+    }
+    while ( a2b < v5->field_11798 );
+  }
+  v45 = rand();
+  v4->uAdditionalValue = *(uint *)Dst;
+  v46 = v45 % v39 + 1;
+  a2c = *((unsigned char *)&v5->pItems[0].uItemID + 28 * (*(uint *)Dst + 1389) + v5->pItems[v4->uItemID].uEquipType);
+  if ( a2c < v46 )
+  {
+    for ( j = (int *)&Dst; ; j = (int *)v59 )
+    {
+      v48 = v4->uItemID;
+      v49 = (int)(j + 1);
+      v59 = v49;
+      v50 = *(unsigned int *)v49;
+      v4->uAdditionalValue = v50;
+      a2c += *((unsigned char *)&v5->pItems[0].uItemID + 28 * (v50 + 1389) + v5->pItems[v48].uEquipType);
+      if ( a2c >= v46 )
+        break;
+    }
+  }
+  ++v4->uAdditionalValue;
+}
+
+//----- (004505CC) --------------------------------------------------------
+bool ItemGen::GenerateArtifact()
+{
+  ItemGen *v1; // edi@1
+  signed int uNumArtifactsNotFound; // esi@1
+  int v3; // eax@1
+  bool result; // eax@6
+  int v5[32]; // [sp+8h] [bp-A0h]@3
+  char Dst[32]; // [sp+88h] [bp-20h]@1
+
+  auto a2 = this;
+  v1 = a2;
+  memset(Dst, 0, 0x20u);
+  uNumArtifactsNotFound = 0;
+  v3 = 500;
+  do
+  {
+    if ( !pParty->field_3C.pIsArtifactFound[v3] )
+      v5[uNumArtifactsNotFound++] = v3;
+    ++v3;
+  }
+  while ( v3 < 529 );
+  v1->Reset();
+  if ( uNumArtifactsNotFound )
+  {
+    v1->uItemID = v5[rand() % uNumArtifactsNotFound];
+    pItemsTable->SetSpecialBonus(v1);
+    result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+// 4505CC: using guessed type int var_A0[32];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Items.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,223 @@
+#pragma once
+
+
+
+
+
+
+/*  338 */
+enum ITEM_FLAGS
+{
+  ITEM_IDENTIFIED = 0x1,
+  ITEM_BROKEN = 0x2,
+  ITEM_TEMP_BONUS = 0x8,
+  ITEM_STOLEN = 0x100,
+  ITEM_ENCHANTED = 0x200,
+};
+
+
+/*  330 */
+enum ITEM_TYPE
+{
+  ITEM_LONGSWORD_1 = 0x1,
+  ITEM_DAGGER_1 = 0xF,
+  ITEM_AXE_1 = 0x17,
+  ITEM_SPEAR_1 = 0x1F,
+  ITEM_CROSSBOW_1 = 0x2F,
+  ITEM_MACE_1 = 0x32,
+  ITEM_STAFF_1 = 0x3D,
+  ITEM_LEATHER_1 = 0x42,
+  ITEM_CHAINMAIL_1 = 0x47,
+  ITEM_PLATE_1 = 0x4C,
+  ITEM_BUCKLER_1 = 0x54,
+  ITEM_GAUNTLETS_1 = 0x6E,
+  ITEM_BOOTS_1 = 0x73,
+  ITEM_WAND_FIRE = 0x87,
+  ITEM_WAND_STUN = 0x8A,
+  ITEM_WAND_INCENERATION = 0x9F,
+  ITEM_TROLL_BLOOD = 0xCA,
+  ITEM_DRAGON_EYE = 0xCC,
+  ITEM_HARPY_FEATHER = 0xCF,
+  ITEM_DEVIL_ICHOR = 0xD6,
+  ITEM_OOZE_ECTOPLASM_BOTTLE = 0xD9,
+  ITEM_POTION_BOTTLE = 0xDC,
+  ITEM_SPELLBOOK_FIRE_STRIKE = 0x191,
+  ITEM_SPELLBOOK_AIR_FEATHER_FALL = 0x19C,
+  ITEM_SPELLBOOK_WATER_POISON_SPRAY = 0x1A7,
+  ITEM_SPELLBOOK_EARTH_SLOW = 0x1B2,
+  ITEM_SPELLBOOK_SPIRIT_BLESS = 0x1BD,
+  ITEM_SPELLBOOK_MIND_MIND_BLAST = 0x1C8,
+  ITEM_SPELLBOOK_BODY_FIRST_AID = 0x1D3,
+  ITEM_SPELLBOOK_BODY_HEAL = 0x1D6,
+  ITEM_SPELLBOOK_BODY_BREAK_POISON = 0x1D7,
+  ITEM_SPELLBOOK_LIGHT_LIGHT_BOLT = 0x1DD,
+  ITEM_SPELLBOOK_LIGHT_SUN_BURST = 0x1E6,
+  ITEM_SPELLBOOK_LIGHT_DIVINE_INTERVENTION = 0x1E7,
+  ITEM_ARTIFACT_PUCK = 0x1F4,
+  ITEM_RELIC_MEKORIGS_HAMMER = 0x210,
+};
+
+/*  331 */
+enum ITEM_EQUIP_TYPE
+{
+  EQUIP_ONE_OR_TWO_HANDS = 0x0,
+  EQUIP_TWO_HANDED = 0x1,
+  EQUIP_BOW = 0x2,
+  EQUIP_ARMOUR = 0x3,
+  EQUIP_SHIELD = 0x4,
+  EQUIP_HELMET = 0x5,
+  EQUIP_BELT = 0x6,
+  EQUIP_CLOAK = 0x7,
+  EQUIP_GAUNTLETS = 0x8,
+  EQUIP_BOOTS = 0x9,
+  EQUIP_RING = 0xA,
+  EQUIP_AMULET = 0xB,
+  EQUIP_C = 0xC,
+  EQUIP_REAGENT = 0xD,
+  EQUIP_POTION = 0xE,
+  EQUIP_F = 0xF,
+  EQUIP_BOOK = 0x10,
+  EQUIP_11 = 0x11,
+  EQUIP_GOLD = 0x12,
+  EQUIP_GEM = 0x13,
+};
+
+
+
+/*   64 */
+#pragma pack(push, 1)
+struct ItemGen
+{
+  //----- (0042EB25) --------------------------------------------------------
+  inline ItemGen()
+  {
+    Reset();
+  }
+
+  bool GenerateArtifact();
+  unsigned int GetValue();
+  const char *GetDisplayName();
+  const char *GetIdentifiedName();
+  void UpdateTempBonus(__int64 uTimePlayed);
+  void Reset();
+  int _439DF3_get_additional_damage(int *a2, int *a3);
+
+
+
+  unsigned int uItemID;
+  int _bonus_type;
+  int _bonus_strength;
+  int uAdditionalValue;
+  int uNumCharges;
+  unsigned int uAttributes;
+  unsigned __int8 uBodyAnchor;
+  char uMaxCharges;
+  char field_1A;
+  char field_1B;
+  unsigned __int64 uExpireTime;
+};
+#pragma pack(pop)
+
+
+
+/*  175 */
+#pragma pack(push, 1)
+struct ItemDesc
+{
+  unsigned int uItemID;
+  char *pIconName;
+  char *pName;
+  char *pUnidentifiedName;
+  char *pDescription;
+  unsigned int uValue;
+  unsigned __int16 uSpriteID;
+  __int16 field_1A;
+  unsigned __int16 uEquipX;
+  unsigned __int16 uEquipY;
+  unsigned __int8 uEquipType;
+  unsigned __int8 uSkillType;
+  unsigned __int8 uDamageDice;
+  unsigned __int8 uDamageRoll;
+  unsigned __int8 uDamageMod;
+  unsigned __int8 uMaterial;
+  char _additional_value;
+  char _bonus_type;
+  char _bonus_strength;
+  char field_29;
+  char field_2A;
+  char field_2B;
+  char field_2C;
+  char field_2D;
+  char field_2E;
+  char field_2F;
+};
+#pragma pack(pop)
+
+
+
+/*  177 */
+#pragma pack(push, 1)
+struct ItemEnchantment
+{
+  char *pName;
+  char *pParam;
+  char field_8[12];
+};
+#pragma pack(pop)
+
+/*  178 */
+#pragma pack(push, 1)
+struct ItemSpecialEnchantment
+{
+  char *pName;
+  char *pParam;
+  char field_8[12];
+  int field_14;
+  int field_18;
+};
+#pragma pack(pop)
+
+
+/*  176 */
+#pragma pack(push, 1)
+struct ItemsTable
+{
+  void Initialize();
+  void LoadPotions();
+  void LoadPotionNotes();
+  void GenerateItem(int a2, int a3, ItemGen *pItem);
+  void SetSpecialBonus(ItemGen *pItem);
+  bool _456D43_is_material_equals_3(ItemGen *pItem);
+  bool _456D5E_is_some_material(ItemGen *pItem);
+  char *Release();
+
+
+  ItemDesc pItems[800];
+  ItemEnchantment pEnchantments[24];
+  ItemSpecialEnchantment pSpecialEnchantments[72];
+  char field_9FC0[5000];
+  char field_B348[5000];
+  char field_C6D0[5000];
+  char field_DA58[5000];
+  char field_EDE0[5000];
+  char field_10168[5000];
+  char field_114F0[388];
+  char *pItemsTXT_Raw;
+  char *pRndItemsTXT_Raw;
+  char *pStdItemsTXT_Raw;
+  char *pSpcItemsTXT_Raw;
+  int field_11684[6];
+  char field_1169C[60];
+  int field_116D8[24];
+  int field_11738[24];
+  int field_11798;
+  char field_1179C;
+};
+#pragma pack(pop)
+
+
+
+
+extern ItemGen *ptr_50C9A4;
+
+extern struct ItemsTable *pItemsTable;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Keyboard.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1847 @@
+#include "OSAPI.h"
+
+#include "Keyboard.h"
+#include "GUIWindow.h"
+#include "Game.h"
+#include "OSInfo.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+struct KeyboardActionMapping *pKeyActionMap;
+struct AsyncKeyboard *pAsyncKeyboard;
+
+
+
+
+
+//----- (00459C68) --------------------------------------------------------
+void KeyboardActionMapping::SetKeyMapping(int uAction, int vKey, KeyToggleType type)
+{
+  pVirtualKeyCodesMapping[uAction] = vKey;
+  pToggleTypes[uAction] = type;
+}
+
+//----- (00459C82) --------------------------------------------------------
+unsigned int KeyboardActionMapping::GetActionVKey(enum InputAction eAction)
+{
+  return this->pVirtualKeyCodesMapping[eAction];
+}
+
+//----- (00459C8D) --------------------------------------------------------
+KeyboardActionMapping::KeyboardActionMapping()
+{
+  uLastKeyPressed = 0;
+
+  SetDefaultMapping();
+  ReadMappings();
+
+  ResetKeys();
+
+  dword_506E68 = -1;
+}
+// 506E68: using guessed type int dword_506E68;
+
+//----- (00459CC4) --------------------------------------------------------
+void KeyboardActionMapping::SetDefaultMapping()
+{
+  pVirtualKeyCodesMapping[0] = VK_UP;
+  pToggleTypes[0] = TOGGLE_Continuously;
+  pVirtualKeyCodesMapping[1] = VK_DOWN;
+  pToggleTypes[1] = TOGGLE_Continuously;
+  pVirtualKeyCodesMapping[2] = VK_LEFT;
+  pToggleTypes[2] = TOGGLE_Continuously;
+  pVirtualKeyCodesMapping[3] = VK_RIGHT;
+  pToggleTypes[3] = TOGGLE_Continuously;
+  pVirtualKeyCodesMapping[8] = 'A';
+  pToggleTypes[8] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[7] = 'S';
+  pToggleTypes[7] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[4] = 'Y';
+  pToggleTypes[4] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[5] = 'X';
+  pToggleTypes[5] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[6] = VK_RETURN;
+  pToggleTypes[6] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[9] = VK_SPACE;
+  pToggleTypes[9] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[10] = 'C';
+  pToggleTypes[10] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[11] = 'B';
+  pToggleTypes[11] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[12] = VK_TAB;
+  pToggleTypes[12] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[13] = 'Q';
+  pToggleTypes[13] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[14] = 'Z';
+  pToggleTypes[14] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[15] = 'R';
+  pToggleTypes[15] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[16] = 'T';
+  pToggleTypes[16] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[17] = 'N';
+  pToggleTypes[17] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[18] = 'M';
+  pToggleTypes[18] = TOGGLE_OneTimePress;
+  pVirtualKeyCodesMapping[20] = VK_NEXT;
+  pToggleTypes[20] = TOGGLE_Continuously;
+  pVirtualKeyCodesMapping[21] = VK_DELETE;
+  pToggleTypes[21] = TOGGLE_Continuously;
+
+  SetKeyMapping(INPUT_CenterView, VK_END, TOGGLE_Continuously);
+  SetKeyMapping(INPUT_ZoomIn, VK_ADD, TOGGLE_OneTimePress);
+  SetKeyMapping(INPUT_ZoomOut, VK_SUBTRACT, TOGGLE_OneTimePress);
+  SetKeyMapping(INPUT_FlyUp, VK_PRIOR, TOGGLE_Continuously);
+  SetKeyMapping(INPUT_FlyDown, VK_INSERT, TOGGLE_Continuously);
+  SetKeyMapping(INPUT_Land, VK_HOME, TOGGLE_OneTimePress);
+  SetKeyMapping(INPUT_AlwaysRun, 'U', TOGGLE_OneTimePress);
+  SetKeyMapping(INPUT_StrafeLeft, VK_OEM_4, TOGGLE_Continuously);
+  SetKeyMapping(INPUT_StrafeRight, VK_OEM_6, TOGGLE_Continuously);
+}
+
+//----- (00459E3F) --------------------------------------------------------
+void KeyboardActionMapping::ResetKeys()
+{
+  for (uint i = 0; i < 30; ++i)
+    GetAsyncKeyState(pVirtualKeyCodesMapping[i]);
+}
+
+//----- (00459E5A) --------------------------------------------------------
+void KeyboardActionMapping::_459E5A(int a2, int a3, GUIWindow *pWindow)
+{
+  KeyboardActionMapping *v4; // esi@1
+
+  v4 = this;
+  memset(this->pPressedKeysBuffer, 0, 0x101u);
+  v4->uNumKeysPressed = 0;
+  if ( a2 )
+    v4->field_204 = 2;
+  else
+    v4->field_204 = 1;
+  v4->field_FC = a3;
+  v4->pWindow = pWindow;
+  pWindow->field_40 = 1;
+  if ( LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) )
+  {
+    if ( pAsyncKeyboard )
+      pAsyncKeyboard->Suspend();
+  }
+}
+
+//----- (00459ED1) --------------------------------------------------------
+void KeyboardActionMapping::_459ED1(int a2)
+{
+  KeyboardActionMapping *v2; // esi@1
+  GUIWindow *v3; // esi@4
+
+  v2 = this;
+  if (pGame->pKeyboardInstance->bUsingAsynKeyboard && pAsyncKeyboard)
+    pAsyncKeyboard->Resume();
+  v2->field_204 = 0;
+  v3 = v2->pWindow;
+  if ( v3 )
+    v3->field_40 = a2;
+}
+
+//----- (00459F10) --------------------------------------------------------
+bool KeyboardActionMapping::_459F10(unsigned int a2)
+{
+  int v3; // [sp-4h] [bp-4h]@3
+
+  pKeyActionMap->uLastKeyPressed = a2;
+  if ( dword_506E68 == -1 )
+  {
+    if ( pKeyActionMap->field_204 == 1 )
+    {
+      if ( a2 != 8 )
+      {
+        if ( a2 == 9 )
+          return 1;
+        if ( a2 == 13 )
+          goto LABEL_3;
+        if ( a2 == 27 )
+          goto LABEL_15;
+        if ( this->uNumKeysPressed >= this->field_FC )
+          return 1;
+        pKeyActionMap->pPressedKeysBuffer[pKeyActionMap->uNumKeysPressed] = a2;
+        ++pKeyActionMap->uNumKeysPressed;
+LABEL_24:
+        pKeyActionMap->pPressedKeysBuffer[pKeyActionMap->uNumKeysPressed] = 0;
+        return 1;
+      }
+    }
+    else
+    {
+      if ( pKeyActionMap->field_204 != 2 )
+        return 0;
+      if ( a2 != 8 )
+      {
+        if ( a2 == 13 )
+          goto LABEL_3;
+        if ( a2 != 27 )
+        {
+          if ( (signed int)a2 >= 48 && (signed int)a2 <= 57 )
+          {
+            if ( pKeyActionMap->uNumKeysPressed < this->field_FC )
+            {
+              pKeyActionMap->pPressedKeysBuffer[pKeyActionMap->uNumKeysPressed] = a2;
+              ++pKeyActionMap->uNumKeysPressed;
+            }
+          }
+          return 1;
+        }
+LABEL_15:
+        v3 = 3;
+        goto LABEL_4;
+      }
+    }
+    if ( !pKeyActionMap->uNumKeysPressed )
+      return 1;
+    --pKeyActionMap->uNumKeysPressed;
+    goto LABEL_24;
+  }
+  pKeyActionMap->pPressedKeysBuffer[pKeyActionMap->uNumKeysPressed] = a2;
+  ++pKeyActionMap->uNumKeysPressed;
+  pKeyActionMap->pPressedKeysBuffer[pKeyActionMap->uNumKeysPressed] = 0;
+LABEL_3:
+  v3 = 2;
+LABEL_4:
+  pKeyActionMap->_459ED1(v3);
+  return 1;
+}
+// 506E68: using guessed type int dword_506E68;
+
+//----- (00459FFC) --------------------------------------------------------
+void KeyboardActionMapping::ReadMappings()
+{
+  //KeyboardActionMapping *v1; // esi@1
+  int v2; // eax@2
+  unsigned int v3; // eax@3
+  int v4; // eax@6
+  unsigned int v5; // eax@7
+  int v6; // eax@10
+  unsigned int v7; // eax@11
+  int v8; // eax@14
+  unsigned int v9; // eax@15
+  int v10; // eax@18
+  unsigned int v11; // eax@19
+  int v12; // eax@22
+  //unsigned int v13; // eax@23
+  int v14; // eax@26
+  //unsigned int v15; // eax@27
+  int v16; // eax@30
+  //unsigned int v17; // eax@31
+  int v18; // eax@34
+  //unsigned int v19; // eax@35
+  int v20; // eax@38
+  //unsigned int v21; // eax@39
+  int v22; // eax@42
+  //unsigned int v23; // eax@43
+  int v24; // eax@46
+  //unsigned int v25; // eax@47
+  int v26; // eax@50
+  //unsigned int v27; // eax@51
+  int v28; // eax@54
+  //unsigned int v29; // eax@55
+  int v30; // eax@58
+  //unsigned int v31; // eax@59
+  int v32; // eax@62
+  //unsigned int v33; // eax@63
+  int v34; // eax@66
+  //unsigned int v35; // eax@67
+  int v36; // eax@70
+  //unsigned int v37; // eax@71
+  int v38; // eax@74
+  //unsigned int v39; // eax@75
+  int v40; // eax@78
+  //unsigned int v41; // eax@79
+  int v42; // eax@82
+  //unsigned int v43; // eax@83
+  int v44; // eax@86
+  //unsigned int v45; // eax@87
+  int v46; // eax@90
+  //unsigned int v47; // eax@91
+  int v48; // eax@94
+  //unsigned int v49; // eax@95
+  int v50; // eax@98
+  //unsigned int v51; // eax@99
+  int v52; // eax@102
+  //unsigned int v53; // eax@103
+  int v54; // eax@106
+  //unsigned int v55; // eax@107
+  int v56; // eax@110
+  unsigned int v57; // eax@111
+  int v58; // eax@114
+  unsigned int v59; // eax@115
+  int v60; // eax@118
+  unsigned int v61; // eax@119
+  //char str[32]; // [sp+Ch] [bp-20h]@1
+
+  char str[32];
+
+  ReadWindowsRegistryString("KEY_FORWARD", str, 32, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v2) = GetActionDefaultVKey(str), v2 != -1) )
+  {
+    pVirtualKeyCodesMapping[0] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[0] = VK_UP;
+  }
+  pToggleTypes[0] = TOGGLE_Continuously;
+  ReadWindowsRegistryString("KEY_BACKWARD", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v4) = GetActionDefaultVKey(str), v4 != -1) )
+  {
+    pVirtualKeyCodesMapping[1] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[1] = VK_DOWN;
+  }
+  pToggleTypes[1] = TOGGLE_Continuously;
+
+  ReadWindowsRegistryString("KEY_LEFT", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v6) = GetActionDefaultVKey(str), v6 != -1) )
+  {
+    pVirtualKeyCodesMapping[2] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[2] = VK_LEFT;
+  }
+  pToggleTypes[2] = TOGGLE_Continuously;
+
+  ReadWindowsRegistryString("KEY_RIGHT", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v8) = GetActionDefaultVKey(str), v8 != -1) )
+  {
+    pVirtualKeyCodesMapping[3] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[3] = VK_RIGHT;
+  }
+  pToggleTypes[3] = TOGGLE_Continuously;
+
+  ReadWindowsRegistryString("KEY_ATTACK", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v10) = GetActionDefaultVKey(str), v10 != -1) )
+  {
+    pVirtualKeyCodesMapping[8] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[8] = 'A';
+  }
+  pToggleTypes[8] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_CASTREADY", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v12) = GetActionDefaultVKey(str), v12 != -1) )
+  {
+    pVirtualKeyCodesMapping[7] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[7] = 'S';
+  }
+  pToggleTypes[7] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_YELL", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v14) = GetActionDefaultVKey(str), v14 != -1) )
+  {
+    pVirtualKeyCodesMapping[4] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[4] = 'Y';
+  }
+  pToggleTypes[4] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_JUMP", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v16) = GetActionDefaultVKey(str), v16 != -1) )
+  {
+    pVirtualKeyCodesMapping[5] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[5] = 'X';
+  }
+  pToggleTypes[5] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_COMBAT", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v18) = GetActionDefaultVKey(str), v18 != -1) )
+  {
+    pVirtualKeyCodesMapping[6] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[6] = VK_RETURN;
+  }
+  pToggleTypes[6] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_EVENTTRIGGER", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v20) = GetActionDefaultVKey(str), v20 != -1) )
+  {
+    pVirtualKeyCodesMapping[9] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[9] = VK_SPACE;
+  }
+  pToggleTypes[9] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_CAST", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v22) = GetActionDefaultVKey(str), v22 != -1) )
+  {
+    pVirtualKeyCodesMapping[10] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[10] = 'C';
+  }
+  pToggleTypes[10] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_PASS", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v24) = GetActionDefaultVKey(str), v24 != -1) )
+  {
+    pVirtualKeyCodesMapping[11] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[11] = 'B';
+  }
+  pToggleTypes[11] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_CHARCYCLE", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v26) = GetActionDefaultVKey(str), v26 != -1) )
+  {
+    pVirtualKeyCodesMapping[12] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[12] = VK_TAB;
+  }
+  pToggleTypes[12] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_QUEST", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v28) = GetActionDefaultVKey(str), v28 != -1) )
+  {
+    pVirtualKeyCodesMapping[13] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[13] = 'Q';
+  }
+  pToggleTypes[13] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_QUICKREF", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v30) = GetActionDefaultVKey(str), v30 != -1) )
+  {
+    pVirtualKeyCodesMapping[14] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[14] = 'Z';
+  }
+  pToggleTypes[14] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_REST", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v32) = GetActionDefaultVKey(str), v32 != -1) )
+  {
+    pVirtualKeyCodesMapping[15] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[15] = 'R';
+  }
+  pToggleTypes[15] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_TIMECAL", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v34) = GetActionDefaultVKey(str), v34 != -1) )
+  {
+    pVirtualKeyCodesMapping[16] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[16] = 'T';
+  }
+  pToggleTypes[16] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_AUTONOTES", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v36) = GetActionDefaultVKey(str), v36 != -1) )
+  {
+    pVirtualKeyCodesMapping[17] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[17] = 'N';
+  }
+  pToggleTypes[17] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_MAPBOOK", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v38) = GetActionDefaultVKey(str), v38 != -1) )
+  {
+    pVirtualKeyCodesMapping[18] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[18] = 'M';
+  }
+  pToggleTypes[18] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_LOOKUP", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v40) = GetActionDefaultVKey(str), v40 != -1) )
+  {
+    pVirtualKeyCodesMapping[20] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[20] = VK_NEXT;
+  }
+  pToggleTypes[20] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_LOOKDOWN", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v42) = GetActionDefaultVKey(str), v42 != -1) )
+  {
+    pVirtualKeyCodesMapping[21] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[21] = VK_DELETE;
+  }
+  pToggleTypes[21] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_CENTERVIEWPT", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v44) = GetActionDefaultVKey(str), v44 != -1) )
+  {
+    pVirtualKeyCodesMapping[22] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[22] = VK_END;
+  }
+  pToggleTypes[22] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_ZOOMIN", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v46) = GetActionDefaultVKey(str), v46 != -1) )
+  {
+    pVirtualKeyCodesMapping[23] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[23] = VK_ADD;
+  }
+  pToggleTypes[23] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_ZOOMOUT", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v48) = GetActionDefaultVKey(str), v48 != -1) )
+  {
+    pVirtualKeyCodesMapping[24] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[24] = VK_SUBTRACT;
+  }
+  pToggleTypes[24] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_FLYUP", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v50) = GetActionDefaultVKey(str), v50 != -1) )
+  {
+    pVirtualKeyCodesMapping[25] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[25] = VK_PRIOR;
+  }
+  pToggleTypes[25] = TOGGLE_Continuously;
+
+  ReadWindowsRegistryString("KEY_FLYDOWN", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v52) = GetActionDefaultVKey(str), v52 != -1) )
+  {
+    pVirtualKeyCodesMapping[26] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[26] = VK_INSERT;
+  }
+  pToggleTypes[26] = TOGGLE_Continuously;
+
+  ReadWindowsRegistryString("KEY_LAND", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v54) = GetActionDefaultVKey(str), v54 != -1) )
+  {
+    pVirtualKeyCodesMapping[27] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[27] = VK_HOME;
+  }
+  pToggleTypes[27] = TOGGLE_OneTimePress;
+
+  ReadWindowsRegistryString("KEY_ALWAYSRUN", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v56) = GetActionDefaultVKey(str), v56 != -1) )
+  {
+    pVirtualKeyCodesMapping[19] = GetActionDefaultVKey(str);
+  }
+  else
+  {
+    pVirtualKeyCodesMapping[19] = 'U';
+  }
+  pToggleTypes[19] = TOGGLE_OneTimePress;
+
+  bAlwaysRun = ReadWindowsRegistryInt("valAlwaysRun", 0) != 0;
+  bFlipOnExit = ReadWindowsRegistryInt("FlipOnExit", 0) != 0;
+  ReadWindowsRegistryString("KEY_STEPLEFT", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v58) = GetActionDefaultVKey(str), v58 != -1) )
+  {
+    pVirtualKeyCodesMapping[28] = GetActionDefaultVKey(str);
+    pToggleTypes[28] = TOGGLE_OneTimePress;
+  }
+  else
+  {
+    pToggleTypes[28] = TOGGLE_Continuously;
+    pVirtualKeyCodesMapping[28] = VK_OEM_4;
+  }
+
+  ReadWindowsRegistryString("KEY_STEPRIGHT", str, 0x20u, "DEFAULT");
+  if ( strcmp(str, "DEFAULT") && (LOBYTE(v60) = GetActionDefaultVKey(str), v60 != -1) )
+  {
+    pVirtualKeyCodesMapping[29] = GetActionDefaultVKey(str);
+    pToggleTypes[29] = TOGGLE_OneTimePress;
+  }
+  else
+  {
+    pToggleTypes[29] = TOGGLE_Continuously;
+    pVirtualKeyCodesMapping[29] = VK_OEM_6;
+  }
+}
+
+//----- (0045A960) --------------------------------------------------------
+void KeyboardActionMapping::StoreMappings()
+{
+  const char *v2; // eax@1
+  const char *v3; // eax@1
+  const char *v4; // eax@1
+  const char *v5; // eax@1
+  const char *v6; // eax@1
+  const char *v7; // eax@1
+  const char *v8; // eax@1
+  const char *v9; // eax@1
+  const char *v10; // eax@1
+  const char *v11; // eax@1
+  const char *v12; // eax@1
+  const char *v13; // eax@1
+  const char *v14; // eax@1
+  const char *v15; // eax@1
+  const char *v16; // eax@1
+  const char *v17; // eax@1
+  const char *v18; // eax@1
+  const char *v19; // eax@1
+  const char *v20; // eax@1
+  const char *v21; // eax@1
+  const char *v22; // eax@1
+  const char *v23; // eax@1
+  const char *v24; // eax@1
+  const char *v25; // eax@1
+  const char *v26; // eax@1
+  const char *v27; // eax@1
+  const char *v28; // eax@1
+  const char *v29; // eax@1
+
+  v2 = GetVKeyDisplayName(this->pVirtualKeyCodesMapping[0]);
+  WriteWindowsRegistryString("KEY_FORWARD", v2);
+  v3 = GetVKeyDisplayName(pVirtualKeyCodesMapping[1]);
+  WriteWindowsRegistryString("KEY_BACKWARD", v3);
+  v4 = GetVKeyDisplayName(pVirtualKeyCodesMapping[2]);
+  WriteWindowsRegistryString("KEY_LEFT", v4);
+  v5 = GetVKeyDisplayName(pVirtualKeyCodesMapping[3]);
+  WriteWindowsRegistryString("KEY_RIGHT", v5);
+  v6 = GetVKeyDisplayName(pVirtualKeyCodesMapping[8]);
+  WriteWindowsRegistryString("KEY_ATTACK", v6);
+  v7 = GetVKeyDisplayName(pVirtualKeyCodesMapping[7]);
+  WriteWindowsRegistryString("KEY_CASTREADY", v7);
+  v8 = GetVKeyDisplayName(pVirtualKeyCodesMapping[4]);
+  WriteWindowsRegistryString("KEY_YELL", v8);
+  v9 = GetVKeyDisplayName(pVirtualKeyCodesMapping[5]);
+  WriteWindowsRegistryString("KEY_JUMP", v9);
+  v10 = GetVKeyDisplayName(pVirtualKeyCodesMapping[6]);
+  WriteWindowsRegistryString("KEY_COMBAT", v10);
+  v11 = GetVKeyDisplayName(pVirtualKeyCodesMapping[9]);
+  WriteWindowsRegistryString("KEY_EVENTTRIGGER", v11);
+  v12 = GetVKeyDisplayName(pVirtualKeyCodesMapping[10]);
+  WriteWindowsRegistryString("KEY_CAST", v12);
+  v13 = GetVKeyDisplayName(pVirtualKeyCodesMapping[11]);
+  WriteWindowsRegistryString("KEY_PASS", v13);
+  v14 = GetVKeyDisplayName(pVirtualKeyCodesMapping[12]);
+  WriteWindowsRegistryString("KEY_CHARCYCLE", v14);
+  v15 = GetVKeyDisplayName(pVirtualKeyCodesMapping[13]);
+  WriteWindowsRegistryString("KEY_QUEST", v15);
+  v16 = GetVKeyDisplayName(pVirtualKeyCodesMapping[14]);
+  WriteWindowsRegistryString("KEY_QUICKREF", v16);
+  v17 = GetVKeyDisplayName(pVirtualKeyCodesMapping[15]);
+  WriteWindowsRegistryString("KEY_REST", v17);
+  v18 = GetVKeyDisplayName(pVirtualKeyCodesMapping[16]);
+  WriteWindowsRegistryString("KEY_TIMECAL", v18);
+  v19 = GetVKeyDisplayName(pVirtualKeyCodesMapping[17]);
+  WriteWindowsRegistryString("KEY_AUTONOTES", v19);
+  v20 = GetVKeyDisplayName(pVirtualKeyCodesMapping[18]);
+  WriteWindowsRegistryString("KEY_MAPBOOK", v20);
+  v21 = GetVKeyDisplayName(pVirtualKeyCodesMapping[20]);
+  WriteWindowsRegistryString("KEY_LOOKUP", v21);
+  v22 = GetVKeyDisplayName(pVirtualKeyCodesMapping[21]);
+  WriteWindowsRegistryString("KEY_LOOKDOWN", v22);
+  v23 = GetVKeyDisplayName(pVirtualKeyCodesMapping[22]);
+  WriteWindowsRegistryString("KEY_CENTERVIEWPT", v23);
+  v24 = GetVKeyDisplayName(pVirtualKeyCodesMapping[23]);
+  WriteWindowsRegistryString("KEY_ZOOMIN", v24);
+  v25 = GetVKeyDisplayName(pVirtualKeyCodesMapping[24]);
+  WriteWindowsRegistryString("KEY_ZOOMOUT", v25);
+  v26 = GetVKeyDisplayName(pVirtualKeyCodesMapping[25]);
+  WriteWindowsRegistryString("KEY_FLYUP", v26);
+  v27 = GetVKeyDisplayName(pVirtualKeyCodesMapping[26]);
+  WriteWindowsRegistryString("KEY_FLYDOWN", v27);
+  v28 = GetVKeyDisplayName(pVirtualKeyCodesMapping[27]);
+  WriteWindowsRegistryString("KEY_LAND", v28);
+  v29 = GetVKeyDisplayName(pVirtualKeyCodesMapping[19]);
+  WriteWindowsRegistryString("KEY_ALWAYSRUN", v29);
+}
+
+//----- (0045ABCA) --------------------------------------------------------
+const unsigned __int8 KeyboardActionMapping::GetActionDefaultVKey(const char *Str)
+{
+  unsigned __int8 result; // al@3
+
+  if ( !strcmp(Str, "UP") )
+    return VK_UP;
+  if ( !strcmp(Str, "DOWN") )
+    return VK_DOWN;
+  if (!strcmp(Str, "ÂËÅÂÎ") || !strcmp(Str, "LEFT"))
+    return VK_LEFT;
+  if (!strcmp(Str, "ÂÏÐÀÂÎ") || !strcmp(Str, "RIGHT"))
+    return VK_RIGHT;
+  if ( !strcmp(Str, "RETURN") )
+    return VK_RETURN;
+  if ( !strcmp(Str, "SPACE") )
+    return VK_SPACE;
+  if ( !strcmp(Str, "PAGE_DOWN") )
+    return VK_NEXT;
+  if ( !strcmp(Str, "PAGE_UP") )
+    return VK_PRIOR;
+  if ( !strcmp(Str, "TAB") )
+    return VK_TAB;
+  if ( !strcmp(Str, "SUBTRACT") )
+    return VK_SUBTRACT;
+  if ( !strcmp(Str, "ADD") )
+    return VK_ADD;
+  if ( !strcmp(Str, "END") )
+    return VK_END;
+  if ( !strcmp(Str, "DELETE") )
+    return VK_DELETE;
+  if ( !strcmp(Str, "HOME") )
+    return VK_HOME;
+  if ( !strcmp(Str, "INSERT") )
+    return VK_INSERT;
+  if ( strcmp(Str, "COMMA") )
+  {
+    if ( !strcmp(Str, "DECIMAL") )
+      return VK_DECIMAL;
+    if ( strcmp(Str, "SEMICOLON") )
+    {
+      if ( strcmp(Str, "PERIOD") )
+      {
+        if ( strcmp(Str, "SLASH") )
+        {
+          if ( strcmp(Str, "SQUOTE") )
+          {
+            if ( strcmp(Str, "BACKSLASH") )
+            {
+              if ( !strcmp(Str, "BACKSPACE") )
+                return VK_BACK;
+              if ( !strcmp(Str, "CONTROL") )
+                return VK_CONTROL;
+              if ( strlen(Str) != 1 || (result = *Str, (unsigned __int8)*Str < 0x41u) || result > 0x5Au )
+                result = -1;
+            }
+            else
+            {
+              result = -36;
+            }
+          }
+          else
+          {
+            result = -34;
+          }
+        }
+        else
+        {
+          result = -65;
+        }
+      }
+      else
+      {
+        result = -66;
+      }
+    }
+    else
+    {
+      result = -70;
+    }
+  }
+  else
+  {
+    result = -68;
+  }
+  return result;
+}
+
+//----- (0045AE2C) --------------------------------------------------------
+const char *KeyboardActionMapping::GetVKeyDisplayName(signed int a1)
+{
+  char *v3; // [sp-4h] [bp-8h]@2
+
+  static char static_sub_45AE2C_string_69ADE0[32];
+
+  if ( a1 == VK_UP )
+  {
+    v3 = "UP";
+LABEL_53:
+    strcpy(static_sub_45AE2C_string_69ADE0, v3);
+    return static_sub_45AE2C_string_69ADE0;
+  }
+  if ( a1 == VK_DOWN )
+  {
+    v3 = "DOWN";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_LEFT )
+  {
+    v3 = ascii_4E2D48;
+    goto LABEL_53;
+  }
+  if ( a1 == VK_RIGHT )
+  {
+    v3 = ascii_4E2D40;
+    goto LABEL_53;
+  }
+  if ( a1 == VK_RETURN )
+  {
+    v3 = "RETURN";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_SPACE )
+  {
+    v3 = "SPACE";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_NEXT )
+  {
+    v3 = "PAGE_DOWN";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_PRIOR )
+  {
+    v3 = "PAGE_UP";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_TAB )
+  {
+    v3 = "TAB";
+    goto LABEL_53;
+  }
+  if ( a1 == 'm' )
+  {
+    v3 = "SUBTRACT";
+    goto LABEL_53;
+  }
+  if ( a1 == 'k' )
+  {
+    v3 = "ADD";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_END )
+  {
+    v3 = "END";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_DELETE )
+  {
+    v3 = "DELETE";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_HOME )
+  {
+    v3 = "HOME";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_INSERT )
+  {
+    v3 = "INSERT";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_DECIMAL )
+  {
+    v3 = "DECIMAL";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_OEM_COMMA )
+  {
+    v3 = "COMMA";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_OEM_1 )
+  {
+    v3 = "SEMICOLON";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_OEM_PERIOD )
+  {
+    v3 = "PERIOD";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_OEM_2 )
+  {
+    v3 = "SLASH";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_OEM_7 )
+  {
+    v3 = "SQUOTE";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_OEM_5 )
+  {
+    v3 = "BACKSLASH";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_CONTROL )
+  {
+    v3 = "CONTROL";
+    goto LABEL_53;
+  }
+  if ( a1 == VK_BACK )
+  {
+    v3 = "BACKSPACE";
+    goto LABEL_53;
+  }
+  if ( a1 < 65 || a1 > 90 )
+  {
+    v3 = "-ÍÅÒ -";
+    goto LABEL_53;
+  }
+  *(unsigned short *)static_sub_45AE2C_string_69ADE0 = (unsigned __int8)a1;
+  return static_sub_45AE2C_string_69ADE0;
+}
+
+//----- (0045AFD9) --------------------------------------------------------
+Keyboard::Keyboard()
+{
+  bUsingAsynKeyboard = false;
+
+  if (pVersion->pVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+      pVersion->pVersionInfo.dwMajorVersion == 4)
+    bUsingAsynKeyboard = false;
+}
+
+//----- (0045B019) --------------------------------------------------------
+void Keyboard::EnterCriticalSection()
+{
+  if (bUsingAsynKeyboard)
+    AsyncKeyboard::EnterCriticalSection();
+}
+
+//----- (0045B06E) --------------------------------------------------------
+bool Keyboard::IsShiftHeld()
+{
+  bool result; // eax@2
+  char v2; // zf@3
+
+  if (bUsingAsynKeyboard)
+  {
+    if ( pAsyncKeyboard->_45B4EC(0x2Au) )
+    {
+LABEL_6:
+      LOBYTE(result) = 1;
+      return result;
+    }
+    v2 = pAsyncKeyboard->_45B4EC(0x36u) == 0;
+  }
+  else
+  {
+    LOWORD(result) = GetAsyncKeyState(VK_SHIFT);
+    v2 = result == 0;
+  }
+  if ( !v2 )
+    goto LABEL_6;
+  LOBYTE(result) = 0;
+  return result;
+}
+
+//----- (0045B0A9) --------------------------------------------------------
+bool Keyboard::IsKeyBeingHeld(int vKey)
+{
+  void *v2; // esi@2
+  char v3; // bl@2
+
+  if (bUsingAsynKeyboard)
+  {
+    __debugbreak();
+    /*
+    v2 = pAsyncKeyboard;
+    EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+    v3 = *((unsigned char *)v2 + (unsigned __int8)AsyncKeyboard::map_key(v2, vKey) + 265) >> 7;
+    LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+    return v3;*/
+  }
+  else
+    return (GetAsyncKeyState(vKey) & 0x8001) != 0;
+}
+
+//----- (0045B0CE) --------------------------------------------------------
+bool Keyboard::WasKeyPressed(int vKey)
+{
+  void *v2; // esi@2
+  char v3; // bl@2
+  bool result; // eax@2
+
+  if ( LOBYTE(this->bUsingAsynKeyboard) )
+  {
+    __debugbreak();
+    /*v2 = pAsyncKeyboard;
+    EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+    v3 = *((unsigned char *)v2 + (unsigned __int8)AsyncKeyboard::map_key(v2, vKey) + 521) >> 7;
+    LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+    LOBYTE(result) = v3;*/
+  }
+  else
+  {
+    LOWORD(result) = GetAsyncKeyState(vKey);
+    LOBYTE(result) = result & 1;
+  }
+  return result;
+}
+
+//----- (0045B10A) --------------------------------------------------------
+AsyncKeyboard::AsyncKeyboard()
+{
+  *(unsigned int *)(this + 4) = 0;
+  *(unsigned char *)(this + 8) = 0;
+
+  if (!Initialize())
+    MessageBoxW(nullptr, L"Could not initialize asynchronos keyboard object", nullptr, 0);
+}
+// 4D86B8: using guessed type int (__stdcall *AsyncKeyboard_pvdtor)(char);
+// 4DBD94: using guessed type int dword_4DBD94;
+
+
+//----- (0045B15E) --------------------------------------------------------
+AsyncKeyboard::~AsyncKeyboard()
+{
+  __debugbreak();
+  /*
+  void *v1; // esi@1
+  char *v2; // edi@1
+  int v3; // ecx@1
+
+  v1 = this;
+  v2 = (char *)this + 1804;
+  v3 = *((unsigned int *)this + 451);
+  if ( v3 )
+    (**(void (__stdcall ***)(unsigned int))v3)(1);
+  *(unsigned int *)v2 = 0;
+  return TerminateThread(*((HANDLE *)v1 + 1), 0x1F4u);*/
+}
+// 4D86B8: using guessed type int (__stdcall *AsyncKeyboard_pvdtor)(char);
+
+//----- (0045B18E) --------------------------------------------------------
+bool AsyncKeyboard::Initialize()
+{
+  _45B1B1();
+  if (_45B229())
+    return CreateDirectInputKeyboard() != 0;
+  return false;
+}
+
+//----- (0045B1B1) --------------------------------------------------------
+void AsyncKeyboard::_45B1B1()
+{
+  void *v1; // esi@1
+
+  v1 = this;
+  memset((char *)this + 9, 0, 0x100u);
+  memset((char *)v1 + 265, 0, 0x100u);
+  memset((char *)v1 + 521, 0, 0x100u);
+  memset((char *)v1 + 780, 0, 0x400u);
+}
+
+//----- (0045B1FD) --------------------------------------------------------
+void AsyncKeyboard::EnterCriticalSection()
+{
+  __debugbreak();
+  //EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+}
+
+//----- (0045B213) --------------------------------------------------------
+void AsyncKeyboard::LeaveCriticalSection()
+{
+  __debugbreak();
+  //LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+}
+
+//----- (0045B229) --------------------------------------------------------
+char AsyncKeyboard::_45B229()
+{
+  __debugbreak();
+  return 0;
+  /*void *v1; // esi@1
+  HANDLE v2; // eax@1
+  char result; // al@2
+  DWORD ThreadId; // [sp+0h] [bp-4h]@1
+
+  ThreadId = (DWORD)this;
+  v1 = this;
+  v2 = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)AsyncKeyboardThread, this, 4u, &ThreadId);
+  *((unsigned int *)v1 + 1) = v2;
+  if ( v2 )
+    result = SetThreadPriority(v2, 15) != 0;
+  else
+    result = 0;
+  return result;*/
+}
+
+//----- (0045B260) --------------------------------------------------------
+char AsyncKeyboard::CreateDirectInputKeyboard()
+{
+  __debugbreak();
+  return 0;
+  /*v1 = this;
+  v2 = new DirectInputKeyboard;
+  *((void **)v1 + 451) = v2;
+
+  return v2 != 0;*/
+}
+
+//----- (0045B2A7) --------------------------------------------------------
+void AsyncKeyboard::Resume()
+{
+  __debugbreak();
+  /*void *v1; // esi@1
+  std::string v2; // [sp-18h] [bp-24h]@2
+  const char *v3; // [sp-8h] [bp-14h]@2
+  int v4; // [sp-4h] [bp-10h]@2
+  std::string *v5; // [sp+4h] [bp-8h]@2
+  int a3; // [sp+Bh] [bp-1h]@2
+
+  v1 = this;
+  if ( *((unsigned int *)this + 451) )
+  {
+    EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+    _45B1B1();
+    DirectInputKeyboard::set_acquire(*((DirectInputKeyboard **)v1 + 451), (int *)1);
+    ResumeThread(*((HANDLE *)v1 + 1));
+    LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"Invalid DI_Keyboard, bailing out of resume()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\KeyboardAsync.cpp:97", 0);
+  }*/
+}
+
+//----- (0045B329) --------------------------------------------------------
+void AsyncKeyboard::Suspend()
+{
+  __debugbreak();
+  /*void *v1; // esi@1
+  std::string v2; // [sp-18h] [bp-24h]@2
+  const char *v3; // [sp-8h] [bp-14h]@2
+  int v4; // [sp-4h] [bp-10h]@2
+  std::string *v5; // [sp+4h] [bp-8h]@2
+  int a3; // [sp+Bh] [bp-1h]@2
+
+  v1 = this;
+  if ( *((unsigned int *)this + 451) )
+  {
+    EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+    SuspendThread(*((HANDLE *)v1 + 1));
+    DirectInputKeyboard::set_acquire(*((DirectInputKeyboard **)v1 + 451), 0);
+    LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"Invalid DI_Keyboard, bailing out of suspend()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\KeyboardAsync.cpp:115", 0);
+  }*/
+}
+
+//----- (0045B3A4) --------------------------------------------------------
+char AsyncKeyboard::_45B3A4()
+{
+  __debugbreak();
+  return 0;
+  /**((unsigned char *)this + 8) = 1;
+  Sleep(0x85u);
+  return 1;*/
+}
+
+
+//----- (00465C53) --------------------------------------------------------
+void AsyncKeyboard::Release()
+{
+  __debugbreak();
+  /*if ( LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) )
+  {
+    if ( pAsyncKeyboard )
+    {
+      pAsyncKeyboard->Suspend();
+      if ( pAsyncKeyboard )
+        (**(void (__stdcall ***)(int))pAsyncKeyboard)(1);
+    }
+    pAsyncKeyboard = 0;
+  }*/
+}
+
+//----- (0045B3B6) --------------------------------------------------------
+void AsyncKeyboard::Thread()
+{
+  __debugbreak();
+  /*void *v1; // esi@1
+  signed int v2; // ecx@3
+  int v3; // eax@3
+  DWORD v4; // edx@6
+  std::string v5; // [sp-18h] [bp-2Ch]@2
+  const char *v6; // [sp-8h] [bp-1Ch]@2
+  int v7; // [sp-4h] [bp-18h]@2
+  DWORD v8; // [sp+Ch] [bp-8h]@2
+  int a3; // [sp+13h] [bp-1h]@2
+
+  v1 = this;
+  if ( *((unsigned int *)this + 451) )
+  {
+    ::EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+    v8 = timeGetTime();
+    memcpy((char *)v1 + 9, (const void *)(*((unsigned int *)v1 + 451) + 29), 0x100u);
+    (*((DirectInputKeyboard **)v1 + 451)->_43B8EC();
+    memcpy((char *)v1 + 265, (const void *)(*((unsigned int *)v1 + 451) + 29), 0x100u);
+    v2 = 0;
+    v3 = (int)((char *)v1 + 780);
+    do
+    {
+      if ( *((unsigned char *)v1 + v2 + 265) & 0x80 )
+      {
+        if ( v8 - *(unsigned int *)v3 > 0xC8 )
+        {
+          v4 = v8;
+          *((unsigned char *)v1 + v2 + 521) |= 0x80u;
+          *(unsigned int *)v3 = v4;
+        }
+      }
+      ++v2;
+      v3 += 4;
+    }
+    while ( v2 < 256 );
+    ::LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"Invalid DI_Keyboard, bailing out of update_keyboard_data()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\KeyboardAsync.cpp:169", 0);
+  }*/
+}
+
+//----- (0045B4EC) --------------------------------------------------------
+char AsyncKeyboard::_45B4EC(unsigned __int8 a2)
+{
+  __debugbreak();
+  return 0;
+  /*void *v2; // esi@1
+  char v3; // bl@1
+
+  v2 = this;
+  EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+  v3 = *((unsigned char *)v2 + a2 + 265) >> 7;
+  LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncKeyboard);
+  return v3;*/
+}
+
+//----- (0045B57D) --------------------------------------------------------
+char AsyncKeyboard::map_key(int key)
+{
+  __debugbreak();
+  return 0;
+  /*char result; // al@2
+  std::string v3; // [sp-18h] [bp-1Ch]@99
+  const char *v4; // [sp-8h] [bp-Ch]@99
+  int v5; // [sp-4h] [bp-8h]@99
+  void *v6; // [sp+0h] [bp-4h]@1
+
+  v6 = this;
+  switch ( key )
+  {
+    case 8:
+      result = 14;
+      break;
+    case 9:
+      result = 15;
+      break;
+    case 13:
+      result = 28;
+      break;
+    case 16:
+    case 161:
+      result = 54;
+      break;
+    case 160:
+      result = 42;
+      break;
+    case 17:
+    case 163:
+      result = -99;
+      break;
+    case 162:
+      result = 29;
+      break;
+    case 18:
+      result = -72;
+      break;
+    case 20:
+      result = 58;
+      break;
+    case 21:
+      result = 112;
+      break;
+    case 25:
+      result = -108;
+      break;
+    case 27:
+      result = 1;
+      break;
+    case 28:
+      result = 121;
+      break;
+    case 29:
+      result = 123;
+      break;
+    case 32:
+      result = 57;
+      break;
+    case 33:
+      result = -55;
+      break;
+    case 34:
+      result = -47;
+      break;
+    case 35:
+      result = -49;
+      break;
+    case 36:
+      result = -57;
+      break;
+    case 37:
+      result = -53;
+      break;
+    case 38:
+      result = -56;
+      break;
+    case 39:
+      result = -51;
+      break;
+    case 40:
+      result = -48;
+      break;
+    case 42:
+      result = -73;
+      break;
+    case 45:
+      result = -46;
+      break;
+    case 46:
+      result = -45;
+      break;
+    case 48:
+      result = 11;
+      break;
+    case 49:
+      result = 2;
+      break;
+    case 50:
+      result = 3;
+      break;
+    case 51:
+      result = 4;
+      break;
+    case 52:
+      result = 5;
+      break;
+    case 53:
+      result = 6;
+      break;
+    case 54:
+      result = 7;
+      break;
+    case 55:
+      result = 8;
+      break;
+    case 56:
+      result = 9;
+      break;
+    case 57:
+      result = 10;
+      break;
+    case 65:
+      result = 30;
+      break;
+    case 66:
+      result = 48;
+      break;
+    case 67:
+      result = 46;
+      break;
+    case 68:
+      result = 32;
+      break;
+    case 69:
+      result = 18;
+      break;
+    case 70:
+      result = 33;
+      break;
+    case 71:
+      result = 34;
+      break;
+    case 72:
+      result = 35;
+      break;
+    case 73:
+      result = 23;
+      break;
+    case 74:
+      result = 36;
+      break;
+    case 75:
+      result = 37;
+      break;
+    case 76:
+      result = 38;
+      break;
+    case 77:
+      result = 50;
+      break;
+    case 78:
+      result = 49;
+      break;
+    case 79:
+      result = 24;
+      break;
+    case 80:
+      result = 25;
+      break;
+    case 81:
+      result = 16;
+      break;
+    case 82:
+      result = 19;
+      break;
+    case 83:
+      result = 31;
+      break;
+    case 84:
+      result = 20;
+      break;
+    case 85:
+      result = 22;
+      break;
+    case 86:
+      result = 47;
+      break;
+    case 87:
+      result = 17;
+      break;
+    case 88:
+      result = 45;
+      break;
+    case 89:
+      result = 21;
+      break;
+    case 90:
+      result = 44;
+      break;
+    case 91:
+      result = -37;
+      break;
+    case 92:
+      result = -36;
+      break;
+    case 93:
+      result = -35;
+      break;
+    case 96:
+      result = 82;
+      break;
+    case 97:
+      result = 79;
+      break;
+    case 98:
+      result = 80;
+      break;
+    case 99:
+      result = 81;
+      break;
+    case 100:
+      result = 75;
+      break;
+    case 101:
+      result = 76;
+      break;
+    case 102:
+      result = 77;
+      break;
+    case 103:
+      result = 71;
+      break;
+    case 104:
+      result = 72;
+      break;
+    case 105:
+      result = 73;
+      break;
+    case 106:
+      result = 55;
+      break;
+    case 107:
+      result = 78;
+      break;
+    case 109:
+      result = 74;
+      break;
+    case 110:
+      result = 83;
+      break;
+    case 111:
+      result = -75;
+      break;
+    case 112:
+      result = 59;
+      break;
+    case 113:
+      result = 60;
+      break;
+    case 114:
+      result = 61;
+      break;
+    case 115:
+      result = 62;
+      break;
+    case 116:
+      result = 63;
+      break;
+    case 117:
+      result = 64;
+      break;
+    case 118:
+      result = 65;
+      break;
+    case 119:
+      result = 66;
+      break;
+    case 120:
+      result = 67;
+      break;
+    case 121:
+      result = 68;
+      break;
+    case 122:
+      result = 87;
+      break;
+    case 123:
+      result = 88;
+      break;
+    case 124:
+      result = 100;
+      break;
+    case 125:
+      result = 101;
+      break;
+    case 126:
+      result = 102;
+      break;
+    case 144:
+      result = 69;
+      break;
+    case 145:
+      result = 70;
+      break;
+    default:
+      MessageBoxW(nullptr, L"Uknown key detected!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\KeyboardAsync.cpp:999", 0);
+      goto LABEL_100;
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 12:
+    case 19:
+    case 23:
+    case 24:
+    case 30:
+    case 31:
+    case 41:
+    case 43:
+    case 44:
+    case 47:
+    case 108:
+    case 127:
+    case 128:
+    case 129:
+    case 130:
+    case 131:
+    case 132:
+    case 133:
+    case 134:
+    case 135:
+LABEL_100:
+      result = -1;
+      break;
+  }
+  return result;*/
+}
+
+//----- (0045BA60) --------------------------------------------------------
+int __stdcall AsyncKeyboard::ThreadStarter(AsyncKeyboard *pInstance)
+{
+  __debugbreak();
+  return 0;
+  /*while ( 1 )
+  {
+    while ( !pAsyncKeyboard )
+      ;
+    if ( *((unsigned char *)pAsyncKeyboard + 8) )
+      ExitThread(0);
+    pAsyncKeyboard->Thread();
+    Sleep(0x21u);
+  }*/
+}
+
+
+
+
+
+
+
+
+/*
+//----- (0043B76D) --------------------------------------------------------
+DirectInputKeyboard *__thiscall DirectInputKeyboard::DirectInputKeyboard(DirectInputKeyboard *this)
+{
+  DirectInputKeyboard *v1; // esi@1
+  HRESULT v2; // eax@5
+  unsigned int uVersion; // [sp-18h] [bp-20h]@3
+  IDirectInput **ppDirectInput; // [sp-14h] [bp-1Ch]@3
+  int v6; // [sp-10h] [bp-18h]@3
+  const char *v7; // [sp-Ch] [bp-14h]@3
+  int v8; // [sp-8h] [bp-10h]@3
+  unsigned int v9; // [sp-4h] [bp-Ch]@3
+  CheckHRESULT_stru0 v10; // [sp+4h] [bp-4h]@5
+
+  v1 = this;
+  this->field_8 = 0;
+  LOBYTE(this->field_1C) = 0;
+  this->vdestructor_ptr = &pDirectInputKeyboard_pvdtor;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    v9 = 1;
+    v8 = 28;
+    v7 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp";
+    v6 = 0;
+    ppDirectInput = &this->pDirectInput;
+    uVersion = 0x500u;
+  }
+  else
+  {
+    v9 = 1;
+    v8 = 26;
+    v7 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp";
+    v6 = 0;
+    ppDirectInput = &this->pDirectInput;
+    uVersion = 0x300u;
+  }
+  v2 = DirectInputCreateA(hInstance, uVersion, ppDirectInput, v6);
+  CheckHRESULT(&v10, v2, v7, v8, v9);
+  DirectInputKeyboard::CreateDevice(v1);
+  DirectInputKeyboard::43B87B(v1);
+  return v1;
+}
+// 4C8880: using guessed type int __stdcall DirectInputCreateA(int, int, int, int);
+
+//----- (0043B7E3) --------------------------------------------------------
+void __thiscall DirectInputKeyboard::vdtor(DirectInputKeyboard *this, bool a2)
+{
+  void *v2; // esi@1
+
+  v2 = this;
+  DirectInputKeyboard::dtor(this);
+  if ( a2 & 1 )
+    free(v2);
+}
+
+//----- (0043B7FF) --------------------------------------------------------
+void __thiscall DirectInputKeyboard::dtor(DirectInputKeyboard *this)
+{
+  DirectInputKeyboard *v1; // esi@1
+  int v2; // eax@1
+
+  v1 = this;
+  v2 = this->field_8;
+  this->vdestructor_ptr = &pDirectInputKeyboard_pvdtor;
+  if ( v2 )
+  {
+    (*(void (__stdcall **)(int))(*(int *)v2 + 32))(v2);
+    (*(void (__stdcall **)(int))(*(int *)v1->field_8 + 8))(v1->field_8);
+    v1->field_8 = 0;
+  }
+  v1->pDirectInput->lpVtbl->Release(v1->pDirectInput);
+  v1->pDirectInput = 0;
+}
+
+//----- (0043B831) --------------------------------------------------------
+void __thiscall DirectInputKeyboard::CreateDevice(DirectInputKeyboard *this)
+{
+  DirectInputKeyboard *v1; // esi@1
+  HRESULT v2; // eax@1
+  int v3; // [sp+4h] [bp-4h]@1
+
+  v1 = this;
+  v2 = ((int (__stdcall *)(IDirectInput *, signed int, int (__stdcall *)(int, int), DirectInputKeyboard *, signed int))this->pDirectInput->lpVtbl->field_10)(
+         this->pDirectInput,
+         3,
+         DirectInputKeyboard_enumerator_43B9B9,
+         this,
+         1);
+  CheckHRESULT((CheckHRESULT_stru0 *)&v3, v2, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp", 52, 1u);
+  if ( !LOBYTE(v1->field_1C) )
+  {
+    v3 = (int)"Error: No keyboard found";
+    _CxxThrowException((int)&v3, (int)&dword_4DBD94);
+  }
+}
+// 43B9B9: using guessed type int __stdcall DirectInputKeyboard_enumerator_43B9B9(int, int);
+// 4DBD94: using guessed type int dword_4DBD94;
+
+//----- (0043B87B) --------------------------------------------------------
+void __thiscall DirectInputKeyboard::43B87B(DirectInputKeyboard *ecx0)
+{
+  char *v1; // esi@1
+  HRESULT v2; // eax@1
+  HRESULT v3; // eax@1
+  HRESULT v4; // eax@1
+  unsigned int v5; // [sp+0h] [bp-Ch]@0
+  char this; // [sp+8h] [bp-4h]@1
+
+  v1 = (char *)&ecx0->field_8;
+  v2 = ((int (__stdcall *)(IDirectInput *, int *, int *, int, int))ecx0->pDirectInput->lpVtbl->field_C)(
+         ecx0->pDirectInput,
+         &ecx0->field_C,
+         &ecx0->field_8,
+         0,
+         "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp");
+  CheckHRESULT((CheckHRESULT_stru0 *)&this, v2, (const char *)0x3C, 1, v5);
+  v3 = (*(int (__stdcall **)(int, int))(**(int **)v1 + 44))(*(int *)v1, dword_4C9890);
+  CheckHRESULT((CheckHRESULT_stru0 *)&this, v3, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp", 63, 1u);
+  v4 = (*(int (__stdcall **)(int, HWND, signed int))(**(int **)v1 + 52))(*(int *)v1, hWnd, 6);
+  CheckHRESULT((CheckHRESULT_stru0 *)&this, v4, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp", 64, 1u);
+  (*(void (__cdecl **)(int))(**(int **)v1 + 28))(*(int *)v1);
+}
+// 4C9890: using guessed type int dword_4C9890[10];
+
+//----- (0043B8EC) --------------------------------------------------------
+char __thiscall DirectInputKeyboard::43B8EC(DirectInputKeyboard *this)
+{
+  DirectInputKeyboard *v1; // esi@1
+  int v2; // eax@1
+  char result; // al@2
+  char *v4; // ebx@3
+  int v5; // esi@5
+  HRESULT v6; // eax@5
+  std::string v7; // [sp-18h] [bp-2Ch]@2
+  int v8; // [sp-Ch] [bp-20h]@5
+  const char *v9; // [sp-8h] [bp-1Ch]@2
+  int v10; // [sp-4h] [bp-18h]@2
+  std::string *v13; // [sp+Ch] [bp-8h]@2
+  int a3; // [sp+13h] [bp-1h]@2
+
+  v1 = this;
+  v2 = this->field_8;
+  if ( v2 )
+  {
+    v4 = (char *)&this->field_1C + 1;
+    if ( (*(int (__stdcall **)(int, signed int, char *))(*(int *)v2 + 36))(v2, 256, (char *)&this->field_1C + 1) == -2147024866 )
+    {
+      if ( !(*(int (__stdcall **)(int))(*(int *)v1->field_8 + 28))(v1->field_8) )
+      {
+        v5 = v1->field_8;
+        v10 = 1;
+        v9 = (const char *)79;
+        v8 = (int)"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp";
+        v6 = (*(int (__stdcall **)(int, signed int, char *))(*(int *)v5 + 36))(v5, 256, v4);
+        CheckHRESULT((CheckHRESULT_stru0 *)&v13, v6, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp", 79, 1u);
+      }
+    }
+    result = 1;
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"Invalid Device pointer, bailing out of update_data()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp:72", 0);
+    result = 0;
+  }
+  return result;
+}
+
+//----- (0043B96E) --------------------------------------------------------
+char __thiscall DirectInputKeyboard::set_acquire(DirectInputKeyboard *this, int *a2)
+{
+  int v2; // eax@1
+  char result; // al@2
+  int v4; // ecx@3
+  std::string v5; // [sp-18h] [bp-1Ch]@2
+  const char *v6; // [sp-8h] [bp-Ch]@2
+  int v7; // [sp-4h] [bp-8h]@2
+  DirectInputKeyboard *v8; // [sp+0h] [bp-4h]@1
+
+  v8 = this;
+  v2 = this->field_8;
+  if ( v2 )
+  {
+    v4 = *(int *)v2;
+    v7 = v2;
+    if ( (char)a2 )
+      (*(void (__stdcall **)(int))(v4 + 28))(v7);
+    else
+      (*(void (__stdcall **)(int))(v4 + 32))(v7);
+    result = 1;
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"Invalid Device pointer, bailing out of set_acquire()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputKeyboard.cpp:89", 0);
+    result = 0;
+  }
+  return result;
+}
+
+//----- (0043B9B9) --------------------------------------------------------
+signed int __stdcall DirectInputKeyboard_enumerator_43B9B9(int a1, int a2)
+{
+  signed int result; // eax@2
+
+  if ( *(char *)(a1 + 36) & 3 )
+  {
+    *(int *)(a2 + 12) = *(int *)(a1 + 4);
+    *(int *)(a2 + 16) = *(int *)(a1 + 8);
+    *(int *)(a2 + 20) = *(int *)(a1 + 12);
+    *(int *)(a2 + 24) = *(int *)(a1 + 16);
+    *(char *)(a2 + 28) = 1;
+    result = 0;
+  }
+  else
+  {
+    result = 1;
+  }
+  return result;
+}
+// 43B9B9: using guessed type int __stdcall DirectInputKeyboard_enumerator_43B9B9(int, int);
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Keyboard.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,120 @@
+#pragma once
+
+
+/*  284 */
+enum InputAction : __int32
+{
+  INPUT_MoveForward = 0x0,
+  INPUT_MoveBackwards = 0x1,
+  INPUT_TurnLeft = 0x2,
+  INPUT_TurnRight = 0x3,
+  INPUT_Yell = 0x4,
+  INPUT_Jump = 0x5,
+  INPUT_Combat = 0x6,
+  INPUT_CastReady = 0x7,
+  INPUT_Attack = 0x8,
+  INPUT_EventTrigger = 0x9,
+  INPUT_Cast = 0xA,
+  INPUT_Pass = 0xB,
+  INPUT_CharCycle = 0xC,
+  INPUT_Quest = 0xD,
+  INPUT_QuickRef = 0xE,
+  INPUT_Rest = 0xF,
+  INPUT_TimeCal = 0x10,
+  INPUT_Autonotes = 0x11,
+  INPUT_Mapbook = 0x12,
+  INPUT_AlwaysRun = 0x13,
+  INPUT_LookUp = 0x14,
+  INPUT_LookDown = 0x15,
+  INPUT_CenterView = 0x16,
+  INPUT_ZoomIn = 0x17,
+  INPUT_ZoomOut = 0x18,
+  INPUT_FlyUp = 0x19,
+  INPUT_FlyDown = 0x1A,
+  INPUT_Land = 0x1B,
+  INPUT_StrafeLeft = 0x1C,
+  INPUT_StrafeRight = 0x1D,
+};
+
+
+
+enum KeyToggleType : __int32
+{
+  TOGGLE_Continuously = 0x0,
+  TOGGLE_OneTimePress = 0x1,
+};
+
+#pragma pack(push, 1)
+struct KeyboardActionMapping
+{
+  KeyboardActionMapping();
+
+  void SetKeyMapping(int uAction, int vKey, KeyToggleType type);
+  unsigned int GetActionVKey(enum InputAction eAction);
+  const char *GetVKeyDisplayName(signed int a1);
+  const unsigned __int8 GetActionDefaultVKey(const char *Str);
+  void ReadMappings();
+  void StoreMappings();
+  bool _459F10(unsigned int a2);
+  void _459ED1(int a2);
+  void _459E5A(int a2, int a3, struct GUIWindow *pWindow);
+  void ResetKeys();
+  void SetDefaultMapping();
+
+  unsigned int uLastKeyPressed;
+  int field_4;
+  int field_8;
+  unsigned int pVirtualKeyCodesMapping[30];
+  KeyToggleType pToggleTypes[30];
+  int field_FC;
+  unsigned __int8 pPressedKeysBuffer[257];
+  unsigned __int8 uNumKeysPressed;
+  char field_202;
+  char field_203;
+  int field_204;
+  struct GUIWindow *pWindow;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct Keyboard
+{
+  Keyboard();
+  bool WasKeyPressed(int vKey);
+  bool IsKeyBeingHeld(int vKey);
+  bool IsShiftHeld();
+  void EnterCriticalSection();
+
+  void (__thiscall ***vdestructor_ptr)(Keyboard *, bool);
+  unsigned int bUsingAsynKeyboard;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct AsyncKeyboard
+{
+   AsyncKeyboard();
+  ~AsyncKeyboard();
+
+  bool Initialize();
+  char map_key(int key);
+  char _45B4EC(unsigned __int8 a2);
+  void Thread();
+  char _45B3A4();
+  void Suspend();
+  void Resume();
+  char CreateDirectInputKeyboard();
+  char _45B229();
+  void _45B1B1();
+  void Release();
+
+  static int __stdcall ThreadStarter(AsyncKeyboard *pInstance);
+  static void EnterCriticalSection();
+  static void LeaveCriticalSection();
+};
+#pragma pack(pop)
+
+
+extern struct KeyboardActionMapping *pKeyActionMap;
+extern struct AsyncKeyboard *pAsyncKeyboard;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LOD.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,3175 @@
+#include "LOD.h"
+#include "Render.h"
+#include "Allocator.h"
+#include "PaletteManager.h"
+#include "Viewport.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+
+LODFile_IconsBitmaps *pEvents_LOD;
+LODFile_IconsBitmaps *pIcons_LOD;
+LODFile_Sprites *pSprites_LOD;
+LODFile_IconsBitmaps *pBitmaps_LOD;
+
+LODWriteableFile *pNew_LOD;
+LODWriteableFile *pGames_LOD;
+
+
+
+
+int _6A0CA4_lod_binary_search; // weak
+int _6A0CA8_lod_unused; // weak
+
+
+
+
+
+//----- (004355F7) --------------------------------------------------------
+void LODFile_IconsBitmaps::_4355F7()
+{
+  LODFile_IconsBitmaps *v1; // esi@1
+  int v2; // edi@2
+  Texture *v3; // ebp@3
+  struct IDirect3DTexture2 **v4; // eax@4
+  struct IDirect3DTexture2 *v5; // eax@5
+  struct IDirectDrawSurface **v6; // eax@7
+  struct IDirectDrawSurface *v7; // eax@8
+  int v8; // eax@11
+
+  v1 = this;
+  if ( this->uTexturePacksCount )
+  {
+    v2 = this->uNumLoadedFiles - 1;
+    if ( v2 >= this->uNumPrevLoadedFiles )
+    {
+      v3 = &this->pTextures[v2];
+      do
+      {
+        v3->Release();
+        v4 = v1->pHardwareTextures;
+        if ( v4 )
+        {
+          v5 = v4[v2];
+          if ( v5 )
+          {
+            v5->Release();
+            v1->pHardwareTextures[v2] = 0;
+          }
+        }
+        v6 = v1->pHardwareSurfaces;
+        if ( v6 )
+        {
+          v7 = v6[v2];
+          if ( v7 )
+          {
+            v7->Release();
+            v1->pHardwareSurfaces[v2] = 0;
+          }
+        }
+        --v2;
+        --v3;
+      }
+      while ( v2 >= v1->uNumPrevLoadedFiles );
+    }
+    v8 = v1->uNumPrevLoadedFiles;
+    v1->uNumPrevLoadedFiles = 0;
+    v1->uNumLoadedFiles = v8;
+    v1->uTexturePacksCount = 0;
+  }
+}
+
+//----- (004114F2) --------------------------------------------------------
+void LODFile_IconsBitmaps::_4114F2()
+{
+  LODFile_IconsBitmaps *v1; // esi@1
+  int *pTexturePacksCount; // eax@1
+  int v3; // ecx@1
+  int v4; // ecx@2
+  int v5; // edi@3
+  Texture *v6; // ebx@4
+  struct IDirect3DTexture2 **v7; // eax@5
+  struct IDirect3DTexture2 *v8; // eax@6
+  struct IDirectDrawSurface **v9; // eax@8
+  struct IDirectDrawSurface *v10; // eax@9
+  int v11; // eax@12
+
+  v1 = this;
+  pTexturePacksCount = &this->uTexturePacksCount;
+  v3 = this->uTexturePacksCount;
+  if ( v3 )
+  {
+    v4 = v3 - 1;
+    *pTexturePacksCount = v4;
+    if ( !v4 )
+    {
+      v5 = v1->uNumLoadedFiles - 1;
+      if ( v5 >= v1->uNumPrevLoadedFiles )
+      {
+        v6 = &v1->pTextures[v5];
+        do
+        {
+          v6->Release();
+          v7 = v1->pHardwareTextures;
+          if ( v7 )
+          {
+            v8 = v7[v5];
+            if ( v8 )
+            {
+              v8->Release();
+              v1->pHardwareTextures[v5] = 0;
+            }
+          }
+          v9 = v1->pHardwareSurfaces;
+          if ( v9 )
+          {
+            v10 = v9[v5];
+            if ( v10 )
+            {
+              v10->Release();
+              v1->pHardwareSurfaces[v5] = 0;
+            }
+          }
+          --v5;
+          --v6;
+        }
+        while ( v5 >= v1->uNumPrevLoadedFiles );
+      }
+      v11 = v1->uNumPrevLoadedFiles;
+      v1->uNumPrevLoadedFiles = 0;
+      v1->uNumLoadedFiles = v11;
+    }
+  }
+}
+
+//----- (004AC67E) --------------------------------------------------------
+int LODFile_Sprites::LoadSpriteFromFile(LODSprite *pSpriteHeader, const char *pContainer)
+{
+  FILE *v3; // eax@1
+  FILE *v4; // ebx@1
+  int result; // eax@2
+  LODSprite *v6; // esi@3
+  LODSprite_stru0 *v7; // eax@3
+  size_t v8; // ST10_4@3
+  int *v9; // ebx@3
+  int v10; // eax@3
+  void *v11; // eax@5
+  LODSprite_stru0 *v12; // eax@6
+  void *v13; // ecx@6
+  LODSprite_stru0 *i; // edx@6
+  FILE *File; // [sp+4h] [bp-4h]@1
+  void *DstBufa; // [sp+10h] [bp+8h]@4
+  int Sizea; // [sp+14h] [bp+Ch]@3
+
+  v3 = FindContainer(pContainer, 0);
+  v4 = v3;
+  File = v3;
+  if ( v3 )
+  {
+    v6 = pSpriteHeader;
+    fread(pSpriteHeader, 1u, 0x20u, v3);
+    strcpy(pSpriteHeader->pName, pContainer);
+    Sizea = pSpriteHeader->uSpriteSize;
+    v7 = (LODSprite_stru0 *)pAllocator->AllocNamedChunk(v6->pSpriteLines, 8 * v6->uHeight, v6->pName);
+    v8 = 8 * pSpriteHeader->uHeight;
+    pSpriteHeader->pSpriteLines = v7;
+    fread(v7, 1u, v8, v4);
+    v9 = &pSpriteHeader->uDecompressedSize;
+    v10 = pSpriteHeader->uDecompressedSize;
+    if ( v10 )
+    {
+      pSpriteHeader->pDecompressedBytes = pAllocator->AllocNamedChunk(
+                                            pSpriteHeader->pDecompressedBytes,
+                                            v10,
+                                            pSpriteHeader->pName);
+      DstBufa = pAllocator->AllocNamedChunk(0, Sizea, pSpriteHeader->pName);
+      fread(DstBufa, 1u, Sizea, File);
+      zlib::MemUnzip(v6->pDecompressedBytes, (unsigned int *)&v6->uDecompressedSize, DstBufa, v6->uSpriteSize);
+      v6->uSpriteSize = *v9;
+      pAllocator->FreeChunk(DstBufa);
+    }
+    else
+    {
+      v11 = pAllocator->AllocNamedChunk(pSpriteHeader->pDecompressedBytes, Sizea, pSpriteHeader->pName);
+      pSpriteHeader->pDecompressedBytes = v11;
+      fread(v11, 1u, Sizea, File);
+    }
+    v12 = v6->pSpriteLines;
+    v13 = v6->pDecompressedBytes;
+    for ( i = &v12[v6->uHeight]; v12 < i; i = &v6->pSpriteLines[v6->uHeight] )
+    {
+      v12->ptr_4 = (char *)v12->ptr_4 + (unsigned int)v13;
+      ++v12;
+    }
+    result = 1;
+  }
+  else
+  {
+    result = -1;
+  }
+  return result;
+}
+
+//----- (004AC795) --------------------------------------------------------
+bool LODFile_Sprites::LoadSprites(const char *pFilename)
+{
+  if (LoadHeader(pFilename, 1))
+    return false;
+  else
+    return LoadSubIndices("sprites08") == 0;
+}
+
+//----- (004AC7C0) --------------------------------------------------------
+int LODFile_Sprites::LoadSprite(const char *pContainerName, unsigned int uPaletteID)
+{  signed int v3; // edi@1
+  LODFile_Sprites *v4; // esi@1
+  unsigned int v5; // eax@6
+  signed int v6; // ecx@10
+  Sprite *v7; // eax@11
+  FILE *v8; // eax@12
+  Sprite *v10; // edx@21
+  int v11; // eax@21
+  int v12; // eax@22
+  unsigned __int8 v13; // zf@23
+  unsigned __int8 v14; // sf@23
+  LODSprite DstBuf; // [sp+Ch] [bp-3Ch]@12
+  char *Str1; // [sp+34h] [bp-14h]@24
+  LODSprite *v17; // [sp+38h] [bp-10h]@3
+  int v18; // [sp+44h] [bp-4h]@12
+
+  auto a3 = uPaletteID;
+  v3 = 0;
+  v4 = this;
+  if ( pRenderer->pRenderD3D )
+  {
+    if ( (signed int)this->uNumLoadedSprites > 0 )
+    {
+      v17 = 0;
+      while ( _strcmpi(*(const char **)&v17->pName[(unsigned int)v4->pHardwareSprites], pContainerName) )
+      {
+        ++v17;
+        ++v3;
+        if ( v3 >= (signed int)v4->uNumLoadedSprites )
+          goto LABEL_6;
+      }
+      return v3;
+    }
+  }
+  else
+  {
+    if ( (signed int)this->uNumLoadedSprites > 0 )
+    {
+      v17 = this->pSpriteHeaders;
+      while ( _strcmpi(v17->pName, pContainerName) )
+      {
+        ++v17;
+        ++v3;
+        if ( v3 >= (signed int)v4->uNumLoadedSprites )
+          goto LABEL_6;
+      }
+      return v3;
+    }
+  }
+LABEL_6:
+  v5 = v4->uNumLoadedSprites;
+  if ( v5 == 1500 )
+    return -1;
+  if ( pRenderer->pRenderD3D && v4->field_ECAC )
+  {
+    if ( !v4->pHardwareSprites )
+    {
+      v4->pHardwareSprites = (Sprite *)pAllocator->AllocNamedChunk(0, 0xEA60u, "hardSprites");
+      v6 = 0;
+      do
+      {
+        v7 = &v4->pHardwareSprites[v6];
+        ++v6;
+        v7->pName = 0;
+        v7->pTextureSurface = 0;
+        v7->pTexture = 0;
+      }
+      while ( v6 < 1500 );
+    }
+    DstBuf.uHeight = 0;
+    DstBuf.uPaletteId = 0;
+    DstBuf.word_1A = 0;
+    DstBuf.pSpriteLines = 0;
+    DstBuf.pDecompressedBytes = 0;
+    v18 = 0;
+    v8 = FindContainer(pContainerName, 0);
+    if ( !v8 )
+    {
+      v18 = -1;
+      //LODSprite::dtor(&DstBuf);
+      return -1;
+    }
+    fread(&DstBuf, 1u, 0x20u, v8);
+    v10 = v4->pHardwareSprites;
+    v11 = 5 * v4->uNumLoadedSprites;
+    v18 = -1;
+    pHardwareSprites[uNumLoadedSprites].uBufferWidth = DstBuf.uWidth;
+    pHardwareSprites[uNumLoadedSprites].uBufferHeight = DstBuf.uHeight;
+    pSpriteHeaders[uNumLoadedSprites].uWidth = DstBuf.uWidth;
+    pSpriteHeaders[uNumLoadedSprites].uHeight = DstBuf.uHeight;
+    //LODSprite::dtor(&DstBuf);
+    goto LABEL_29;
+  }
+  v12 = LoadSpriteFromFile( &v4->pSpriteHeaders[v5], pContainerName);
+  v4->pSpriteHeaders[v4->uNumLoadedSprites].word_1A = 0;
+  if ( v12 != -1 )
+  {
+LABEL_28:
+    v4->pSpriteHeaders[v4->uNumLoadedSprites].uPaletteId = pPaletteManager->LoadPalette(
+                                                             v4->pSpriteHeaders[v4->uNumLoadedSprites].uPaletteId);
+LABEL_29:
+    if ( pRenderer->pRenderD3D )
+    {
+      v4->pHardwareSprites[v4->uNumLoadedSprites].pName = (const char *)pAllocator->AllocNamedChunk(
+                                                                          v4->pHardwareSprites[v4->uNumLoadedSprites].pName,
+                                                                          0x14u,
+                                                                          pContainerName);
+      strcpy((char *)pHardwareSprites[uNumLoadedSprites].pName, pContainerName);
+      v4->pHardwareSprites[v4->uNumLoadedSprites].uPaletteID = uPaletteID;
+      pRenderer->MoveSpriteToDevice(&pHardwareSprites[uNumLoadedSprites]);
+    }
+    ++v4->uNumLoadedSprites;
+    return v4->uNumLoadedSprites - 1;
+  }
+  v13 = v4->uNumLoadedSprites == 0;
+  v14 = (v4->uNumLoadedSprites & 0x80000000u) != 0;
+  v17 = 0;
+  if ( v14 | v13 )
+  {
+LABEL_27:
+    if ( LoadSpriteFromFile(&v4->pSpriteHeaders[v4->uNumLoadedSprites], "pending") == -1 )
+      return -1;
+    goto LABEL_28;
+  }
+  Str1 = (char *)v4->pSpriteHeaders;
+  while ( _strcmpi(Str1, "pending") )
+  {
+    v17 = (LODSprite *)((char *)v17 + 1);
+    Str1 += 40;
+    if ( (signed int)v17 >= (signed int)v4->uNumLoadedSprites )
+      goto LABEL_27;
+  }
+  return (int)v17;
+}
+
+//----- (004ACADA) --------------------------------------------------------
+void LODFile_Sprites::ReleaseLostHardwareSprites()
+{
+  LODFile_Sprites *v1; // esi@1
+  signed int v2; // ebx@2
+  int v3; // edi@3
+  IDirectDrawSurface *v4; // eax@4
+  IDirect3DTexture2 *v5; // eax@6
+  IDirectDrawSurface *v6; // ST00_4@8
+
+  v1 = this;
+  if ( this->pHardwareSprites )
+  {
+    v2 = 0;
+    if ( (signed int)this->uNumLoadedSprites > 0 )
+    {
+      v3 = 0;
+      do
+      {
+        v4 = (IDirectDrawSurface *)v1->pHardwareSprites[v3].pTextureSurface;
+        if ( v4 && v4->IsLost() == DDERR_SURFACELOST )
+        {
+          v5 = v1->pHardwareSprites[v3].pTexture;
+          if ( v5 )
+          {
+            v5->Release();
+            v1->pHardwareSprites[v3].pTexture = 0;
+          }
+          v6 = (IDirectDrawSurface *)v1->pHardwareSprites[v3].pTextureSurface;
+          v6->Release();
+          v1->pHardwareSprites[v3].pTextureSurface = 0;
+          pRenderer->MoveSpriteToDevice(&v1->pHardwareSprites[v3]);
+        }
+        ++v2;
+        ++v3;
+      }
+      while ( v2 < (signed int)v1->uNumLoadedSprites );
+    }
+  }
+}
+
+//----- (004ACB70) --------------------------------------------------------
+void LODFile_Sprites::ReleaseAll()
+{
+  LODFile_Sprites *v1; // esi@1
+  signed int v2; // ebx@2
+  int v3; // edi@3
+  Sprite *v4; // eax@4
+  IDirect3DTexture2 *v5; // eax@5
+  Sprite *v6; // eax@7
+  IDirectDrawSurface *v7; // eax@8
+
+  v1 = this;
+  if ( this->pHardwareSprites )
+  {
+    v2 = 0;
+    if ( (signed int)this->uNumLoadedSprites > 0 )
+    {
+      v3 = 0;
+      do
+      {
+        v4 = v1->pHardwareSprites;
+        if ( v4 )
+        {
+          v5 = v4[v3].pTexture;
+          if ( v5 )
+          {
+            v5->Release();
+            v1->pHardwareSprites[v3].pTexture = 0;
+          }
+          v6 = v1->pHardwareSprites;
+          if ( v6 )
+          {
+            v7 = (IDirectDrawSurface *)v6[v3].pTextureSurface;
+            if ( v7 )
+            {
+              v7->Release();
+              v1->pHardwareSprites[v3].pTextureSurface = 0;
+            }
+          }
+        }
+        ++v2;
+        ++v3;
+      }
+      while ( v2 < (signed int)v1->uNumLoadedSprites );
+    }
+  }
+}
+
+//----- (004ACBE0) --------------------------------------------------------
+void LODFile_Sprites::MoveSpritesToVideoMemory()
+{
+  LODFile_Sprites *v1; // esi@1
+  int v2; // ebx@1
+  signed int v3; // edi@2
+
+  v1 = this;
+  v2 = 0;
+  if ( this->pHardwareSprites )
+  {
+    v3 = 0;
+    if ( (signed int)this->uNumLoadedSprites > 0 )
+    {
+      do
+      {
+        pRenderer->MoveSpriteToDevice(&v1->pHardwareSprites[v2]);
+        ++v3;
+        ++v2;
+      }
+      while ( v3 < (signed int)v1->uNumLoadedSprites );
+    }
+  }
+}
+
+//----- (004ACC38) --------------------------------------------------------
+int LODSprite::_4ACC38(RenderBillboardTransform_local0 *a2, char a3)
+{
+  RenderBillboardTransform_local0 *v3; // edi@1
+  int result; // eax@1
+  int v5; // esi@2
+  int v6; // ST18_4@2
+  signed int v7; // eax@2
+  signed int v8; // ebx@2
+  int v9; // ebx@2
+  int *v10; // ecx@2
+  int v11; // esi@2
+  unsigned int v12; // edx@4
+  int v13; // esi@13
+  int v14; // esi@17
+  int v15; // ecx@17
+  char *v16; // edx@17
+  int v17; // esi@17
+  int v18; // ecx@18
+  int v19; // esi@18
+  LODSprite_stru0 *v20; // edx@21
+  int v21; // eax@22
+  int v22; // esi@22
+  int v23; // eax@25
+  int v24; // ecx@25
+  signed __int64 v25; // qtt@27
+  int v26; // eax@27
+  unsigned __int16 *v27; // eax@29
+  LODSprite_stru0 *v28; // edx@29
+  signed int v29; // ecx@30
+  int v30; // ecx@37
+  int v31; // ecx@38
+  signed int v32; // ecx@41
+  int v33; // ecx@47
+  int v34; // ecx@56
+  int v35; // esi@58
+  __int16 v36; // ax@58
+  int v37; // ecx@59
+  int v38; // eax@59
+  int v39; // ecx@62
+  signed int v40; // ST30_4@64
+  signed __int64 v41; // qtt@64
+  int v42; // ecx@64
+  unsigned __int16 *v43; // eax@66
+  LODSprite_stru0 *v44; // ecx@66
+  int v45; // edx@69
+  int v46; // edx@77
+  unsigned __int16 *pTarget; // [sp+Ch] [bp-50h]@2
+  signed int v48; // [sp+10h] [bp-4Ch]@2
+  signed int v49; // [sp+14h] [bp-48h]@2
+  int v50; // [sp+14h] [bp-48h]@19
+  int v51; // [sp+14h] [bp-48h]@57
+  int v52; // [sp+18h] [bp-44h]@13
+  int v53; // [sp+1Ch] [bp-40h]@2
+  int v54; // [sp+1Ch] [bp-40h]@22
+  int v55; // [sp+1Ch] [bp-40h]@32
+  int v56; // [sp+1Ch] [bp-40h]@69
+  int v57; // [sp+20h] [bp-3Ch]@2
+  int v58; // [sp+24h] [bp-38h]@1
+  int v59; // [sp+28h] [bp-34h]@2
+  int v60; // [sp+28h] [bp-34h]@13
+  unsigned __int16 *v61; // [sp+2Ch] [bp-30h]@2
+  int v62; // [sp+30h] [bp-2Ch]@2
+  void *v63; // [sp+30h] [bp-2Ch]@29
+  void *v64; // [sp+30h] [bp-2Ch]@66
+  int v65; // [sp+34h] [bp-28h]@2
+  int v66; // [sp+34h] [bp-28h]@22
+  int v67; // [sp+34h] [bp-28h]@59
+  int v68; // [sp+38h] [bp-24h]@13
+  unsigned int v69; // [sp+3Ch] [bp-20h]@2
+  int v70; // [sp+40h] [bp-1Ch]@2
+  signed int v71; // [sp+40h] [bp-1Ch]@15
+  int v72; // [sp+44h] [bp-18h]@2
+  unsigned __int16 *v73; // [sp+44h] [bp-18h]@29
+  unsigned __int16 *v74; // [sp+44h] [bp-18h]@66
+  int v75; // [sp+48h] [bp-14h]@4
+  int v76; // [sp+48h] [bp-14h]@22
+  int v77; // [sp+48h] [bp-14h]@59
+  LODSprite *v78; // [sp+4Ch] [bp-10h]@1
+  int v79; // [sp+50h] [bp-Ch]@4
+  int v80; // [sp+50h] [bp-Ch]@21
+  int v81; // [sp+50h] [bp-Ch]@62
+  int v82; // [sp+50h] [bp-Ch]@67
+  int v83; // [sp+50h] [bp-Ch]@75
+  int *pTargetZ; // [sp+54h] [bp-8h]@4
+  int v85; // [sp+58h] [bp-4h]@18
+  int v86; // [sp+58h] [bp-4h]@56
+  signed int v87; // [sp+64h] [bp+8h]@2
+  int v88; // [sp+68h] [bp+Ch]@18
+  int v89; // [sp+68h] [bp+Ch]@56
+
+  v3 = a2;
+  v78 = this;
+  result = a2->field_10;
+  v58 = a2->field_10;
+  if ( result <= 0 )
+    return result;
+  v5 = a2->field_14;
+  v6 = a2->field_10;
+  v87 = (signed __int64)0x100000000ui64 / result;
+  v48 = (signed __int64)0x100000000ui64 / result;
+  v62 = (signed __int64)0x100000000ui64 / v5;
+  v7 = this->uHeight;
+  v8 = (signed int)((signed __int64)0x100000000ui64 / v5) >> 1;
+  v53 = v8;
+  v70 = (this->uHeight << 16) - v8;
+  v49 = v7;
+  v69 = v3->uTargetPitch;
+  pTarget = v3->pTarget;
+  v57 = v3->sZValue;
+  v61 = v3->pPalette;
+  v9 = (v6 * this->uWidth + 32768) >> 16;
+  v72 = v3->uScreenSpaceY;
+  result = (v5 * v7 + 32768) >> 16;
+  v10 = (int *)(v72 - result + 1);
+  v11 = v3->uScreenSpaceX - (v9 >> 1) + 1;
+  v65 = v72 - result + 1;
+  v59 = v11 + v9 - 1;
+  if ( BYTE1(v3->uFlags) & 8 )
+  {
+    v10 = (int *)((char *)v10 + (v49 >> 1));
+    v72 += v49 >> 1;
+    v65 = (int)v10;
+  }
+  v12 = v72;
+  pTargetZ = v10;
+  v75 = v3->uScreenSpaceX - (v9 >> 1) + 1;
+  v79 = v11 + v9 - 1;
+  if ( !(v3->uFlags & 8) )
+  {
+    if ( v65 < (signed int)v3->uViewportY )
+      pTargetZ = (int *)v3->uViewportY;
+    if ( v72 > (signed int)v3->uViewportW )
+      v12 = v3->uViewportW;
+    if ( v11 < (signed int)v3->uViewportX )
+      v75 = v3->uViewportX;
+    if ( v59 > (signed int)v3->uViewportZ )
+      v79 = v3->uViewportZ;
+  }
+  v68 = v75 - v11;
+  v13 = -v62;
+  v60 = v59 - v79;
+  v52 = -v62;
+  if ( v3->uFlags & 1 )
+  {
+    v13 = v62;
+    v70 = v53;
+    v52 = v62;
+  }
+  v71 = v13 * (v72 - v12) + v70;
+  if ( LOBYTE(viewparams->field_20) )
+  {
+    if ( a3 )
+      return result;
+  }
+  v14 = 5 * v12;
+  v15 = v69 * v12;
+  result = v12 - v72 + result - 1;
+  v16 = (char *)pTargetZ - v65;
+  v17 = v14 << 7;
+  if ( v3->uFlags & 4 )
+  {
+    v34 = v79 + v15;
+    v89 = v34;
+    v86 = v79 + v17;
+    if ( result < (signed int)v16 )
+      return result;
+    v51 = result - (int)v16 + 1;
+    while ( 1 )
+    {
+      v35 = v71 >> 16;
+      v36 = LOWORD(v78->pSpriteLines[v35].dword_0);
+      if ( v36 == -1 )
+      {
+        v34 -= v69;
+        v89 = v34;
+        goto LABEL_84;
+      }
+      v37 = v9 - ((unsigned __int64)(v36 * (signed __int64)v58) >> 16);
+      v67 = v87 * ((unsigned __int64)(LOWORD(v78->pSpriteLines[v35].dword_0) * (signed __int64)v58) >> 16);
+      v38 = v9 - v60;
+      v77 = v9 - v60;
+      if ( v9 - v60 <= (signed int)(v9
+                                  - ((unsigned __int64)(HIWORD(v78->pSpriteLines[v35].dword_0) * (signed __int64)v58) >> 16))
+        || v68 >= v37 )
+      {
+        v89 -= v69;
+        v34 = v89;
+LABEL_84:
+        v86 -= 640;
+        goto LABEL_85;
+      }
+      if ( v38 < v37 )
+      {
+        v81 = (v87 >> 1) + v87 * (v37 - v38);
+      }
+      else
+      {
+        v77 = v37;
+        v81 = v87 >> 1;
+        v39 = v37 - v9;
+        v89 += v39 + v60;
+        v86 += v60 + v39;
+      }
+      v40 = ((HIWORD(v78->pSpriteLines[v35].dword_0) + 1) << 16) - v81 - v67;
+      LODWORD(v41) = v40 << 16;
+      HIDWORD(v41) = v40 >> 16;
+      v42 = v77 - (((signed int)((unsigned __int64)(v41 / v48) - 32768) >> 16) + 1);
+      if ( v68 >= v42 )
+        v42 = v68;
+      v43 = &pTarget[v89];
+      v74 = &v43[v42 - v77 + 1];
+      v44 = &v78->pSpriteLines[v35];
+      v64 = v44->ptr_4;
+      if ( !v57 )
+      {
+        v83 = v67 + v81;
+        if ( ((v83 - (LOWORD(v44->dword_0) << 16)) & 0xFFFF0000) < 0 )
+        {
+          v83 += v87;
+          --v43;
+          --pTargetZ;
+        }
+        while ( v43 >= v74 )
+        {
+          v46 = (v83 - ((signed int)LOWORD(v78->pSpriteLines[v35].dword_0) << 16)) >> 16;
+          if ( *((char *)v64 + v46) )
+            *v43 = v61[*((char *)v64 + v46)];
+          v83 += v87;
+          --v43;
+        }
+        goto LABEL_81;
+      }
+      pTargetZ = &v3->pTargetZ[v86];
+      v82 = v67 + v81;
+      if ( ((v82 - (LOWORD(v44->dword_0) << 16)) & 0xFFFF0000) < 0 )
+        goto LABEL_72;
+LABEL_73:
+      if ( v43 >= v74 )
+        break;
+LABEL_81:
+      v89 += v9 - v77 - v60 - v69;
+      v34 = v89;
+      v86 = v86 + v9 - v77 - v60 - 640;
+LABEL_85:
+      result = v52;
+      v71 += v52;
+      --v51;
+      if ( !v51 )
+        return result;
+    }
+    v45 = (v82 - ((signed int)LOWORD(v78->pSpriteLines[v35].dword_0) << 16)) >> 16;
+    v56 = *((char *)v64 + v45);
+    if ( *((char *)v64 + v45) && v57 <= (unsigned int)*pTargetZ )
+    {
+      *pTargetZ = v57;
+      *v43 = v61[v56];
+    }
+LABEL_72:
+    v82 += v87;
+    --v43;
+    --pTargetZ;
+    goto LABEL_73;
+  }
+  v18 = v75 + v15;
+  v19 = v75 + v17;
+  v88 = v18;
+  v85 = v19;
+  if ( result >= (signed int)v16 )
+  {
+    v50 = result - (int)v16 + 1;
+    while ( 1 )
+    {
+      v20 = &v78->pSpriteLines[v71 >> 16];
+      v80 = v71 >> 16;
+      if ( LOWORD(v20->dword_0) != -1 )
+        break;
+      v18 -= v69;
+      v85 = v19 - 640;
+      v88 = v18;
+LABEL_54:
+      result = v52;
+      v71 += v52;
+      --v50;
+      if ( !v50 )
+        return result;
+      v19 = v85;
+    }
+    v21 = (v58 * LOWORD(v20->dword_0) + 32768) >> 16;
+    v66 = v21 * v87;
+    v76 = v68;
+    v54 = HIWORD(v20->dword_0);
+    v22 = v9 - v60;
+    if ( v68 >= (v58 * v54 + 32768) >> 16 || v22 <= v21 )
+    {
+      v88 -= v69;
+      v85 -= 640;
+      goto LABEL_51;
+    }
+    if ( v68 > v21 )
+    {
+      v24 = (v87 >> 1) + v87 * (v68 - v21);
+    }
+    else
+    {
+      v76 = (v58 * LOWORD(v20->dword_0) + 32768) >> 16;
+      v23 = v21 - v68;
+      v88 += v23;
+      v24 = v87 >> 1;
+      v85 += v23;
+    }
+    LODWORD(v25) = (((v54 + 1) << 16) - v24 - v66) << 16;
+    HIDWORD(v25) = (((v54 + 1) << 16) - v24 - v66) >> 16;
+    v26 = v76 + ((signed int)(v25 / v48) >> 16) + 1;
+    if ( v22 > v26 )
+      v22 = v26;
+    v27 = &pTarget[v88];
+    v73 = &v27[v22 - v76 - 1];
+    v28 = &v78->pSpriteLines[v80];
+    v63 = v28->ptr_4;
+    if ( v57 )
+    {
+      pTargetZ = &v3->pTargetZ[v85];
+      v29 = v66 - (LOWORD(v28->dword_0) << 16) + v24;
+      if ( (v29 & 0xFFFF0000) >= 0 )
+        goto LABEL_36;
+      while ( 1 )
+      {
+        v29 += v87;
+        ++v27;
+        ++pTargetZ;
+LABEL_36:
+        if ( v27 >= v73 )
+          break;
+        v55 = *((char *)v63 + (v29 >> 16));
+        if ( *((char *)v63 + (v29 >> 16)) && v57 <= (unsigned int)*pTargetZ )
+        {
+          *pTargetZ = v57;
+          *v27 = v61[v55];
+        }
+      }
+      v30 = v29 >> 16;
+      if ( v30 > HIWORD(v78->pSpriteLines[v80].dword_0) - (signed int)LOWORD(v78->pSpriteLines[v80].dword_0)
+        || (v31 = *((char *)v63 + v30)) == 0
+        || v57 > (unsigned int)*pTargetZ )
+        goto LABEL_50;
+      *pTargetZ = v57;
+    }
+    else
+    {
+      v32 = v66 - (LOWORD(v28->dword_0) << 16) + v24;
+      if ( (v32 & 0xFFFF0000) < 0 )
+      {
+        v32 += v87;
+        ++v27;
+        ++pTargetZ;
+      }
+      while ( v27 < v73 )
+      {
+        if ( *((char *)v63 + (v32 >> 16)) )
+          *v27 = v61[*((char *)v63 + (v32 >> 16))];
+        v32 += v87;
+        ++v27;
+      }
+      v33 = v32 >> 16;
+      if ( v33 > HIWORD(v78->pSpriteLines[v80].dword_0) - (signed int)LOWORD(v78->pSpriteLines[v80].dword_0)
+        || (v31 = *((char *)v63 + v33)) == 0 )
+        goto LABEL_50;
+    }
+    *v27 = v61[v31];
+LABEL_50:
+    v88 += v68 - v76 - v69;
+    v85 = v85 + v68 - v76 - 640;
+LABEL_51:
+    v18 = v88;
+    goto LABEL_54;
+  }
+  return result;
+}
+
+//----- (004AD2D1) --------------------------------------------------------
+int LODSprite::_4AD2D1(struct RenderBillboardTransform_local0 *a2, int a3)
+{
+  int result; // eax@1
+  unsigned int v4; // esi@1
+  int v5; // edi@1
+  LODSprite_stru0 *v6; // edx@2
+  __int16 v7; // bx@2
+  int v8; // ecx@3
+  unsigned __int16 *v9; // esi@3
+  int v10; // ebx@3
+  void *v11; // edx@3
+  unsigned __int16 *v12; // ecx@3
+  int v13; // ebx@4
+  LODSprite *v14; // [sp+8h] [bp-10h]@1
+  unsigned __int16 *v15; // [sp+10h] [bp-8h]@1
+  unsigned __int16 *v16; // [sp+14h] [bp-4h]@1
+  int i; // [sp+20h] [bp+8h]@1
+
+  result = (int)a2;
+  v14 = this;
+  v4 = a2->uTargetPitch;
+  v16 = a2->pTarget;
+  v15 = a2->pPalette;
+  v5 = this->uHeight - 1;
+  for ( i = v4 * a2->uScreenSpaceY - (this->uWidth >> 1) + a2->uScreenSpaceX + 1; v5 >= 0; --v5 )
+  {
+    v6 = &this->pSpriteLines[v5];
+    v7 = LOWORD(v6->dword_0);
+    if ( LOWORD(v6->dword_0) != -1 )
+    {
+      v8 = v7;
+      v9 = &v16[v7 + i];
+      v10 = HIWORD(v6->dword_0);
+      v11 = v6->ptr_4;
+      v12 = &v9[v10 - v8];
+      while ( v9 <= v12 )
+      {
+        v13 = *(char *)v11;
+        v11 = (char *)v11 + 1;
+        if ( v13 )
+          *v9 = v15[v13];
+        ++v9;
+      }
+      v4 = *(int *)(result + 48);
+      //this = v14;
+    }
+    i -= v4;
+  }
+  return result;
+}
+
+//----- (0046454B) --------------------------------------------------------
+void LODFile_IconsBitmaps::ReleaseAll2()
+{
+  LODFile_IconsBitmaps *v1; // esi@1
+  int v2; // edi@1
+  Texture *v3; // ebx@2
+  struct IDirect3DTexture2 **v4; // eax@3
+  struct IDirect3DTexture2 *v5; // eax@4
+  struct IDirectDrawSurface **v6; // eax@6
+  struct IDirectDrawSurface *v7; // eax@7
+  int v8; // eax@10
+
+  v1 = this;
+  v2 = this->uNumLoadedFiles - 1;
+  if ( v2 >= this->dword_11B84 )
+  {
+    v3 = &this->pTextures[v2];
+    do
+    {
+      v3->Release();
+      v4 = v1->pHardwareTextures;
+      if ( v4 )
+      {
+        v5 = v4[v2];
+        if ( v5 )
+        {
+          v5->Release();
+          v1->pHardwareTextures[v2] = 0;
+        }
+      }
+      v6 = v1->pHardwareSurfaces;
+      if ( v6 )
+      {
+        v7 = v6[v2];
+        if ( v7 )
+        {
+          v7->Release();
+          v1->pHardwareSurfaces[v2] = 0;
+        }
+      }
+      --v2;
+      --v3;
+    }
+    while ( v2 >= v1->dword_11B84 );
+  }
+  v8 = v1->dword_11B84;
+  v1->uTexturePacksCount = 0;
+  v1->uNumPrevLoadedFiles = 0;
+  v1->uNumLoadedFiles = v8;
+}
+
+//----- (004645DC) --------------------------------------------------------
+void LODFile_Sprites::DeleteSomeOtherSprites()
+{
+  int *v1; // esi@1
+  int *v2; // edi@1
+
+  v1 = (int *)&this->uNumLoadedSprites;
+  v2 = &this->field_ECA0;
+  DeleteSpritesRange(field_ECA0, uNumLoadedSprites);
+  *v1 = *v2;
+}
+
+
+//----- (00461431) --------------------------------------------------------
+void LOD::File::Close()
+{
+  LOD::File *v1; // esi@1
+  LOD::Directory **v2; // edi@2
+  FILE *v3; // ST00_4@2
+
+  v1 = this;
+  if ( this->isFileOpened )
+  {
+    this->pContainerName[0] = 0;
+    this->uCurrentIndexDir = 0;
+    v2 = &this->pSubIndices;
+    pAllocator->FreeChunk(this->pSubIndices);
+    pAllocator->FreeChunk(v1->pRoot);
+    v3 = v1->pFile;
+    *v2 = 0;
+    v1->pRoot = 0;
+    fclose(v3);
+    v1->isFileOpened = 0;
+    _6A0CA8_lod_unused = 0;
+  }
+}
+
+
+
+//----- (00461492) --------------------------------------------------------
+int LODWriteableFile::_461492(LOD::FileHeader *pHeader, LOD::Directory *pDir, const char *Source)
+{
+  if (isFileOpened)
+    return 1;
+  if ( !pDir->pFilename[0] )
+    return 2;
+  strcpy(pHeader->pSignature, "LOD");
+  pHeader->LODSize = 100;
+  pHeader->uNumIndices = 1;
+  pDir->pFilename[15] = 0;
+  pDir->uDataSize = 0;
+  pDir->uOfsetFromSubindicesStart = 288;
+  strcpy(pLODName, Source);
+
+  pFile = fopen(pLODName, "wb+");
+  if (!pFile)
+    return 3;
+
+  fwrite(pHeader, 0x100, 1, pFile);
+  fwrite(pDir, 0x20, 1, pFile);
+  fclose(pFile);
+  pFile = 0;
+  return 0;
+}
+
+//----- (0046153F) --------------------------------------------------------
+void LOD::File::ResetSubIndices()
+{
+  LOD::Directory **pSubIndices_dup2; // esi@2
+  LOD::Directory *pSubIndices_dup; // ST00_4@2
+
+  if ( this->isFileOpened )
+  {
+    pSubIndices_dup2 = &this->pSubIndices;
+    this->pContainerName[0] = 0;
+    this->uCurrentIndexDir = 0;
+    pSubIndices_dup = this->pSubIndices;
+    this->uOffsetToSubIndex = 0;
+    this->uNumSubIndices = 0;
+    this->uLODDataSize = 0;
+    pAllocator->FreeChunk(pSubIndices_dup);
+    *pSubIndices_dup2 = 0;
+  }
+}
+
+
+
+
+
+
+
+//----- (00450C8B) --------------------------------------------------------
+void LODFile_Sprites::DeleteSomeSprites()
+{
+  int *v1; // esi@1
+  int *v2; // edi@1
+
+  v1 = (int *)&this->uNumLoadedSprites;
+  v2 = &this->field_ECA8;
+  DeleteSpritesRange(this->field_ECA8, this->uNumLoadedSprites);
+  *v1 = *v2;
+}
+
+//----- (00450CA9) --------------------------------------------------------
+void LODFile_Sprites::DeleteSpritesRange(int uStartIndex, int uStopIndex)
+{
+  LODFile_Sprites *v3; // edi@1
+  int v4; // esi@3
+  LODSprite *v5; // ebx@3
+  LODSprite *v6; // esi@7
+  int v7; // edi@7
+  int a2a; // [sp+10h] [bp+8h]@3
+
+  v3 = this;
+  if ( this->pHardwareSprites )
+  {
+    if ( uStartIndex < uStopIndex )
+    {
+      v4 = uStartIndex;
+      v5 = &this->pSpriteHeaders[uStartIndex];
+      a2a = uStopIndex - uStartIndex;
+      do
+      {
+        v5->Release();
+        pHardwareSprites[v4].Release();
+        ++v4;
+        ++v5;
+        --a2a;
+      }
+      while ( a2a );
+    }
+  }
+  else
+  {
+    if ( uStartIndex < uStopIndex )
+    {
+      v6 = &this->pSpriteHeaders[uStartIndex];
+      v7 = uStopIndex - uStartIndex;
+      do
+      {
+        v6->Release();
+        ++v6;
+        --v7;
+      }
+      while ( v7 );
+    }
+  }
+}
+
+//----- (00450D1D) --------------------------------------------------------
+void LODSprite::Release()
+{
+  LODSprite *v1; // esi@1
+
+  v1 = this;
+  if ( !(HIBYTE(this->word_1A) & 4) )
+  {
+    pAllocator->FreeChunk(this->pDecompressedBytes);
+    pAllocator->FreeChunk(v1->pSpriteLines);
+  }
+  v1->word_1A = 0;
+  v1->pDecompressedBytes = 0;
+  v1->pSpriteLines = 0;
+  v1->pName[0] = 0;
+  v1->word_16 = 0;
+  v1->uPaletteId = 0;
+  v1->uTexturePitch = 0;
+  v1->uHeight = 0;
+  v1->uWidth = 0;
+  v1->uSpriteSize = 0;
+}
+
+//----- (00450D68) --------------------------------------------------------
+void Sprite::Release()
+{
+  if (pName)
+    pAllocator->FreeChunk((void *)pName);
+  pName = nullptr;
+
+  if (pTextureSurface)
+    pTextureSurface->Release();
+  pTextureSurface = nullptr;
+
+  if (pTexture)
+    pTexture->Release();
+  pTexture = nullptr;
+}
+
+
+
+
+//----- (0040FA2E) --------------------------------------------------------
+bool LODFile_IconsBitmaps::LoadBitmaps(const char *pFilename)
+{
+  ReleaseAll();
+  if (LoadHeader(pFilename, 1))
+    return false;
+  else
+    return LoadSubIndices("bitmaps") == 0;
+}
+
+
+//----- (0040FAEE) --------------------------------------------------------
+bool LODFile_IconsBitmaps::LoadIconsOrEvents(const char *pLODFilename)
+{
+  ReleaseAll();
+
+  if (LoadHeader(pLODFilename, 1))
+    return false;
+  else
+    return LoadSubIndices("icons") == 0;
+}
+
+
+//----- (0040FA60) --------------------------------------------------------
+void LODFile_IconsBitmaps::ReleaseAll()
+{
+  LODFile_IconsBitmaps *v1; // esi@1
+  unsigned int v2; // edi@1
+  Texture *v3; // ebp@2
+  struct IDirect3DTexture2 **v4; // eax@3
+  struct IDirect3DTexture2 *v5; // eax@4
+  struct IDirectDrawSurface **v6; // eax@6
+  struct IDirectDrawSurface *v7; // eax@7
+
+  v1 = this;
+  v2 = this->uNumLoadedFiles - 1;
+  if ( (v2 & 0x80000000u) == 0 )
+  {
+    v3 = &this->pTextures[v2];
+    do
+    {
+      v3->Release();
+      v4 = v1->pHardwareTextures;
+      if ( v4 )
+      {
+        v5 = v4[v2];
+        if ( v5 )
+        {
+          v5->Release();
+          v1->pHardwareTextures[v2] = 0;
+        }
+      }
+      v6 = v1->pHardwareSurfaces;
+      if ( v6 )
+      {
+        v7 = v6[v2];
+        if ( v7 )
+        {
+          v7->Release();
+          v1->pHardwareSurfaces[v2] = 0;
+        }
+      }
+      --v2;
+      --v3;
+    }
+    while ( (v2 & 0x80000000u) == 0 );
+  }
+  v1->uTexturePacksCount = 0;
+  v1->uNumPrevLoadedFiles = 0;
+  v1->dword_11B84 = 0;
+  v1->dword_11B80 = 0;
+  v1->uNumLoadedFiles = 0;
+}
+
+//----- (0040F9F0) --------------------------------------------------------
+unsigned int LODFile_IconsBitmaps::FindTextureByName(const char *pName)
+{
+  LODFile_IconsBitmaps *v2; // esi@1
+  unsigned int v3; // edi@1
+  Texture *v4; // ebx@2
+  unsigned int result; // eax@5
+
+  v2 = this;
+  v3 = 0;
+  if ( (signed int)this->uNumLoadedFiles <= 0 )
+  {
+LABEL_5:
+    result = -1;
+  }
+  else
+  {
+    v4 = this->pTextures;
+    while ( _strcmpi(v4->pName, pName) )
+    {
+      ++v3;
+      ++v4;
+      if ( (signed int)v3 >= (signed int)v2->uNumLoadedFiles )
+        goto LABEL_5;
+    }
+    result = v3;
+  }
+  return result;
+}
+
+//----- (0040F9C5) --------------------------------------------------------
+int LODFile_IconsBitmaps::_40F9C5()
+{
+  signed int result; // eax@1
+  Texture *pTex; // edx@1
+
+  result = this->uNumLoadedFiles;
+  for ( pTex = &this->pTextures[result]; !pTex->pName[0]; --pTex )
+    --result;
+  if ( result < (signed int)this->uNumLoadedFiles )
+  {
+    ++result;
+    this->uNumLoadedFiles = result;
+  }
+  return result;
+}
+
+
+
+//----- (0046249B) --------------------------------------------------------
+LODFile_Sprites::~LODFile_Sprites()
+{
+  LODFile_Sprites *v1; // esi@1
+  signed int v2; // ebx@1
+  LODSprite *v3; // edi@3
+  char *v4; // edi@6
+  int thisa; // [sp+4h] [bp-10h]@3
+  LODSprite *thisb; // [sp+4h] [bp-10h]@7
+
+  v1 = this;
+  v2 = 0;
+  if ( this->pHardwareSprites )
+  {
+    if ( (signed int)this->uNumLoadedSprites > 0 )
+    {
+      thisa = 0;
+      v3 = this->pSpriteHeaders;
+      do
+      {
+        v3->Release();
+        v1->pHardwareSprites[thisa].Release();
+        ++thisa;
+        ++v2;
+        ++v3;
+      }
+      while ( v2 < (signed int)v1->uNumLoadedSprites );
+    }
+  }
+  else
+  {
+    v4 = (char *)&this->uNumLoadedSprites;
+    if ( (signed int)this->uNumLoadedSprites > 0 )
+    {
+      thisb = this->pSpriteHeaders;
+      do
+      {
+        thisb->Release();
+        ++thisb;
+        ++v2;
+      }
+      while ( v2 < *(int *)v4 );
+    }
+  }
+  //_eh_vector_destructor_iterator_(v1->pSpriteHeaders, 40, 1500, LODSprite::dtor);
+  //LOD::File::vdtor((LOD::File *)v1);
+}
+// 4CC2B4: using guessed type int __stdcall _eh vector destructor iterator_(int, int, int, int);
+
+
+//----- (00462463) --------------------------------------------------------
+LODSprite::~LODSprite()
+{
+  LODSprite *v1; // esi@1
+
+  v1 = this;
+  if ( !(HIBYTE(this->word_1A) & 4) )
+  {
+    pAllocator->FreeChunk(this->pDecompressedBytes);
+    pAllocator->FreeChunk(v1->pSpriteLines);
+  }
+  v1->pDecompressedBytes = 0;
+  v1->pSpriteLines = 0;
+}
+
+//----- (004623E5) --------------------------------------------------------
+LODFile_Sprites::LODFile_Sprites():
+  LOD::File()
+{
+  /*_eh_vector_constructor_iterator_(
+    v1->pSpriteHeaders,
+    40,
+    1500,
+    (void (__thiscall *)(void *))LODSprite::LODSprite,
+    (void (__thiscall *)(void *))LODSprite::dtor);*/
+  field_ECA4 = 0;
+  field_ECA0 = 0;
+  pHardwareSprites = 0;
+  field_ECAC = 0;
+  field_ECB4 = 0;
+  uNumLoadedSprites = 0;
+}
+
+//----- (00462303) --------------------------------------------------------
+LODFile_IconsBitmaps::~LODFile_IconsBitmaps()
+{
+  LODFile_IconsBitmaps *v1; // esi@1
+  unsigned int v2; // edi@1
+  struct IDirect3DTexture2 **v3; // eax@3
+  struct IDirect3DTexture2 *v4; // eax@4
+  struct IDirectDrawSurface **v5; // eax@6
+  struct IDirectDrawSurface *v6; // eax@7
+  Texture *thisa; // [sp+4h] [bp-10h]@2
+
+  v1 = this;
+  v2 = this->uNumLoadedFiles - 1;
+  if ( (v2 & 0x80000000u) == 0 )
+  {
+    thisa = &this->pTextures[v2];
+    do
+    {
+      thisa->Release();
+      v3 = v1->pHardwareTextures;
+      if ( v3 )
+      {
+        v4 = v3[v2];
+        if ( v4 )
+        {
+          v4->Release();
+          v1->pHardwareTextures[v2] = 0;
+        }
+      }
+      v5 = v1->pHardwareSurfaces;
+      if ( v5 )
+      {
+        v6 = v5[v2];
+        if ( v6 )
+        {
+          v6->Release();
+          v1->pHardwareSurfaces[v2] = 0;
+        }
+      }
+      --thisa;
+      --v2;
+    }
+    while ( (v2 & 0x80000000u) == 0 );
+  }
+  if ( v1->pHardwareSurfaces )
+    free(v1->pHardwareSurfaces);
+  if ( v1->pHardwareTextures )
+    free(v1->pHardwareTextures);
+  if ( v1->ptr_011BB4 )
+    free(v1->ptr_011BB4);
+  //LOD::File::vdtor((LOD::File *)v1);
+}
+
+//----- (00462272) --------------------------------------------------------
+LODFile_IconsBitmaps::LODFile_IconsBitmaps():
+  LOD::File()
+{
+  LODFile_IconsBitmaps *v1; // esi@1
+  Texture *v2; // ebx@1
+  signed int v3; // [sp+4h] [bp-10h]@1
+
+  v1 = this;
+  /*v2 = v1->pTextures;
+  v3 = 1000;
+  do
+  {
+    Texture::Texture(v2);
+    ++v2;
+    --v3;
+  }
+  while ( v3 );*/
+  v1->uTexturePacksCount = 0;
+  v1->uNumPrevLoadedFiles = 0;
+  v1->dword_11B84 = 0;
+  v1->dword_11B80 = 0;
+  v1->uNumLoadedFiles = 0;
+  v1->dword_011BA4 = 0;
+  v1->dword_011BA8 = 0;
+  v1->pHardwareSurfaces = 0;
+  v1->pHardwareTextures = 0;
+  v1->ptr_011BB4 = 0;
+}
+
+
+//----- (004621A7) --------------------------------------------------------
+bool LODWriteableFile::_4621A7()
+{
+  CloseWriteFile();
+  return LoadFile(pLODName, 0);
+}
+
+
+//----- (00461FD4) --------------------------------------------------------
+int LODWriteableFile::Save()
+{
+  LODWriteableFile *v1; // esi@1
+  int v2; // edi@1
+  unsigned int v3; // edx@1
+  LOD::Directory *v4; // eax@2
+  unsigned int v5; // ecx@2
+  int v6; // eax@2
+  signed int v7; // ebx@5
+  int v8; // ecx@5
+  LOD::Directory **v9; // edi@6
+  int v10; // edx@6
+  LOD::Directory *v11; // eax@6
+  FILE *v12; // eax@9
+  FILE *v13; // ebx@9
+  signed int result; // eax@10
+  unsigned int v15; // eax@11
+  FILE *v16; // ST00_4@11
+  size_t v17; // edi@12
+  char OldFilename[256]; // [sp+Ch] [bp-228h]@9
+  char NewFilename[256]; // [sp+10Ch] [bp-128h]@15
+  //LOD::Directory v0; // [sp+20Ch] [bp-28h]@11
+  unsigned int v21; // [sp+22Ch] [bp-8h]@5
+  int v22; // [sp+230h] [bp-4h]@1
+
+  v1 = this;
+  v2 = 0;
+  v3 = this->uNumSubIndices;
+  v22 = 0;
+  if ( (signed int)v3 > 0 )
+  {
+    v4 = this->pSubIndices;
+    v5 = v3;
+    v6 = (int)&v4->uDataSize;
+    do
+    {
+      v2 += *(int *)v6;
+      v6 += 32;
+      --v5;
+    }
+    while ( v5 );
+    v22 = v2;
+  }
+  v7 = 0;
+  v21 = 32 * v3 + v2;
+  v8 = 32 * v3;
+  if ( (signed int)v3 > 0 )
+  {
+    v9 = &v1->pSubIndices;
+    v10 = 0;
+    v11 = v1->pSubIndices;
+    do
+    {
+      v11[v10].uOfsetFromSubindicesStart = v8;
+      v11 = *v9;
+      v8 += (*v9)[v10].uDataSize;
+      ++v7;
+      ++v10;
+    }
+    while ( v7 < (signed int)v1->uNumSubIndices );
+    v2 = v22;
+  }
+  strcpy(OldFilename, "lod.tmp");
+  v12 = fopen(OldFilename, "wb+");
+  v13 = v12;
+  if ( v12 )
+  {
+    fwrite(&v1->header, 0x100, 1, v12);
+
+    LOD::Directory v0; // [sp+20Ch] [bp-28h]@11
+    //LOD::Directory::LOD::Directory(&v0);
+
+    strcpy((char *)&v0, "chapter");
+    v15 = v1->uOffsetToSubIndex;
+    v0.dword_000018 = 0;
+    v0.uOfsetFromSubindicesStart = v15;
+    v0.word_00001E = 0;
+    v0.uDataSize = v21;
+    v0.uNumSubIndices = LOWORD(v1->uNumSubIndices);
+    fwrite(&v0, 0x20, 1, v13);
+    fwrite(v1->pSubIndices, 0x20, v1->uNumSubIndices, v13);
+    v16 = v1->pOutputFileHandle;
+    v22 = v2;
+    fseek(v16, 0, 0);
+    if ( v2 > 0 )
+    {
+      do
+      {
+        v17 = v1->uIOBufferSize;
+        if ( v22 <= (signed int)v17 )
+          v17 = v22;
+        fread(v1->pIOBuffer, 1, v17, v1->pOutputFileHandle);
+        fwrite(v1->pIOBuffer, 1, v17, v13);
+        v22 -= v17;
+      }
+      while ( v22 > 0 );
+    }
+    strcpy(NewFilename, (const char *)v1->pLODName);
+    fclose(v13);
+    fclose(v1->pOutputFileHandle);
+    v1->CloseWriteFile();
+    remove("lodapp.tmp");
+    remove(NewFilename);
+    rename(OldFilename, NewFilename);
+    v1->CloseWriteFile();
+    v1->LoadFile(v1->pLODName, 0);
+    result = 0;
+  }
+  else
+  {
+    result = 5;
+  }
+  return result;
+}
+
+
+//----- (00461F71) --------------------------------------------------------
+bool LOD::File::AppendDirectory(LOD::Directory *pDir, const void *pData)
+{
+  unsigned int v3; // edi@1
+  bool result; // eax@2
+  FILE *v5; // ST0C_4@3
+
+  v3 = this->uNumSubIndices;
+  if ( (signed int)v3 < 299 )
+  {
+    memcpy(&this->pSubIndices[v3], pDir, sizeof(this->pSubIndices[v3]));
+    v5 = this->pOutputFileHandle;
+    ++this->uNumSubIndices;
+    fwrite(pData, 1u, pDir->uDataSize, v5);
+    result = 1;
+  }
+  else
+  {
+    MessageBoxA(0, "Unable to append item!", "LOD::File", 0x30u);
+    result = 0;
+  }
+  return result;
+}
+
+
+//----- (00461F1E) --------------------------------------------------------
+int LODWriteableFile::CreateTempFile()
+{
+  LODWriteableFile *v1; // esi@1
+  int result; // eax@2
+  FILE *pFile; // eax@5
+  int v4; // eax@5
+
+  v1 = this;
+  if ( this->isFileOpened )
+  {
+    if ( this->pIOBuffer && this->uIOBufferSize )
+    {
+      this->uCurrentIndexDir = 0;
+      this->uNumSubIndices = 0;
+      pFile = fopen("lodapp.tmp", "wb+");
+      v1->pOutputFileHandle = pFile;
+      v4 = -(pFile != 0);
+      LOBYTE(v4) = v4 & 0xF9;
+      result = v4 + 7;
+    }
+    else
+    {
+      result = 5;
+    }
+  }
+  else
+  {
+    result = 1;
+  }
+  return result;
+}
+
+
+
+//----- (00461EE9) --------------------------------------------------------
+void LODWriteableFile::CloseWriteFile()
+{
+  if (isFileOpened)
+  {
+    pContainerName[0] = 0;
+    uCurrentIndexDir = 0;
+    _6A0CA8_lod_unused = 0;
+    
+    isFileOpened = false;
+    fflush(pFile);
+    fclose(pFile);
+    pFile = 0;
+  }
+}
+// 6A0CA8: using guessed type int 6A0CA8_lod_unused;
+
+
+//----- (00461B48) --------------------------------------------------------
+unsigned int LODWriteableFile::Write(const LOD::Directory *pDir, const void *pDirData, int a4)
+{
+  LODWriteableFile *v4; // ebx@1
+  int v5; // esi@1
+  unsigned __int8 v7; // zf@7
+  unsigned __int8 v8; // sf@7
+  const LOD::Directory *v9; // edi@9
+  int v10; // eax@9
+  unsigned __int8 v11; // of@15
+  unsigned __int16 v12; // dx@17
+  LOD::Directory *v13; // eax@17
+  unsigned __int16 v14; // cx@17
+  int v15; // edi@27
+  unsigned int v16; // eax@27
+  int v17; // eax@29
+  int v18; // edx@31
+  int v19; // eax@31
+  void *v20; // edi@32
+  LOD::Directory *v21; // edi@34
+  signed int v22; // esi@34
+  int v23; // eax@34
+  LOD::Directory *v24; // ecx@35
+  int v25; // edx@35
+  __int32 v26; // eax@37
+  int i; // esi@39
+  __int32 v28; // esi@46
+  char pFilename[256]; // [sp+Ch] [bp-230h]@22
+  char NewFilename[256]; // [sp+10Ch] [bp-130h]@51
+  //LOD::Directory Str; // [sp+20Ch] [bp-30h]@27
+  size_t v33; // [sp+22Ch] [bp-10h]@27
+  int v34; // [sp+230h] [bp-Ch]@7
+  __int32 v35; // [sp+234h] [bp-8h]@8
+  int v36; // [sp+238h] [bp-4h]@7
+  size_t Count; // [sp+244h] [bp+8h]@40
+  __int32 Countc; // [sp+244h] [bp+8h]@46
+  size_t Countb; // [sp+244h] [bp+8h]@47
+  FILE *pFile; // [sp+24Ch] [bp+10h]@22
+
+  v4 = this;
+  v5 = 0;
+  if ( !this->isFileOpened )
+    return 1;
+  if ( !this->pSubIndices )
+    return 2;
+  if ( !this->pIOBuffer || !this->uIOBufferSize )
+    return 3;
+  v7 = this->uNumSubIndices == 0;
+  v8 = (this->uNumSubIndices & 0x80000000u) != 0;
+  v36 = 0;
+  v34 = 0;
+  if ( v8 | v7 )
+  {
+    v9 = pDir;
+    goto LABEL_22;
+  }
+  v35 = 0;
+  while ( 1 )
+  {
+    v9 = pDir;
+    v10 = _strcmpi((const char *)v4->pSubIndices + v35, (const char *)pDir);
+    if ( v10 )
+    {
+      if ( v10 > 0 )
+        goto LABEL_22;
+      goto LABEL_15;
+    }
+    if ( !a4 )
+      goto LABEL_20;
+    if ( a4 == 1 )
+      break;
+    if ( a4 == 2 )
+      return 4;
+LABEL_15:
+    v35 += 32;
+    ++v5;
+    v11 = v5 >= v4->uNumSubIndices;
+    v8 = ((v5 - v4->uNumSubIndices) & 0x80000000u) != 0;
+    v34 = v5;
+    if ( !(v8 ^ v11) )
+      goto LABEL_22;
+  }
+  v12 = pDir->uNumSubIndices;
+  v13 = &v4->pSubIndices[v5];
+  v14 = v13->uNumSubIndices;
+  if ( v14 >= v12 && (v14 != v12 || (unsigned __int16)v13->word_00001E >= pDir->word_00001E) )
+    return 4;
+LABEL_20:
+  v36 = 1;
+LABEL_22:
+  strcpy(pFilename, "lod.tmp");
+  pFile = fopen(pFilename, "wb+");
+  if ( !pFile )
+    return 5;
+  if ( v36 )
+    v35 = v4->pSubIndices[v5].uDataSize;
+  else
+    v35 = 0;
+  v33 = v9->uDataSize;
+  v15 = v33 - v35;
+
+  LOD::Directory Str; // [sp+20Ch] [bp-30h]@27
+  //LOD::Directory::LOD::Directory(&Str);
+
+  strcpy((char *)&Str, "chapter");
+  v16 = v4->uLODDataSize;
+  Str.uNumSubIndices = LOWORD(v4->uNumSubIndices);
+  Str.dword_000018 = 0;
+  Str.word_00001E = 0;
+  if ( !v36 )
+  {
+    ++Str.uNumSubIndices;
+    v15 += 32;
+  }
+  v7 = v36 == 0;
+  Str.uDataSize = v15 + v16;
+  Str.uOfsetFromSubindicesStart = 288;
+  v17 = (signed __int16)Str.uNumSubIndices;
+  v4->uNumSubIndices = (signed __int16)Str.uNumSubIndices;
+  if ( v7 && v17 > v5 )
+  {
+    v18 = v17;
+    v19 = v17 - v5;
+    do
+    {
+      v20 = &v4->pSubIndices[v18];
+      --v18;
+      --v19;
+      memcpy(v20, (char *)v20 - 32, 0x20u);
+    }
+    while ( v19 );
+    v5 = v34;
+  }
+  v21 = v4->pSubIndices;
+  v34 = 32 * v5;
+  memcpy(&v21[v5], pDir, sizeof(v21[v5]));
+  v22 = 0;
+  v23 = 32 * v4->uNumSubIndices;
+  if ( (signed int)v4->uNumSubIndices > 0 )
+  {
+    v24 = v4->pSubIndices;
+    v25 = 0;
+    do
+    {
+      v24[v25].uOfsetFromSubindicesStart = v23;
+      v24 = v4->pSubIndices;
+      v23 += v24[v25].uDataSize;
+      ++v22;
+      ++v25;
+    }
+    while ( v22 < (signed int)v4->uNumSubIndices );
+  }
+  fwrite(&v4->header, 0x100u, 1u, pFile);
+  fwrite(&Str, 0x20, 1, pFile);
+  fseek(v4->pFile, Str.uOfsetFromSubindicesStart, 0);
+  fwrite(v4->pSubIndices, 0x20u, v4->uNumSubIndices, pFile);
+  v26 = 32 * v4->uNumSubIndices;
+  if ( !v36 )
+    v26 -= 32;
+  fseek(v4->pFile, v26, 1);
+  for ( i = *(unsigned int *)((char *)&v4->pSubIndices->uOfsetFromSubindicesStart + v34)
+          - v4->pSubIndices->uOfsetFromSubindicesStart; i > 0; i -= Count )
+  {
+    Count = v4->uIOBufferSize;
+    if ( i <= (signed int)v4->uIOBufferSize )
+      Count = i;
+    fread(v4->pIOBuffer, 1u, Count, v4->pFile);
+    fwrite(v4->pIOBuffer, 1u, Count, pFile);
+  }
+  fwrite(pDirData, 1u, v33, pFile);
+  if ( v36 )
+    fseek(v4->pFile, v35, 1);
+  Countc = ftell(v4->pFile);
+  fseek(v4->pFile, 0, 2);
+  v28 = ftell(v4->pFile) - Countc;
+  fseek(v4->pFile, Countc, 0);
+  while ( v28 > 0 )
+  {
+    Countb = v4->uIOBufferSize;
+    if ( v28 <= (signed int)v4->uIOBufferSize )
+      Countb = v28;
+    fread(v4->pIOBuffer, 1u, Countb, v4->pFile);
+    fwrite(v4->pIOBuffer, 1u, Countb, pFile);
+    v28 -= Countb;
+  }
+  strcpy(NewFilename, (const char *)v4->pLODName);
+  fclose(pFile);
+  v4->CloseWriteFile();
+  remove(NewFilename);
+  rename(pFilename, NewFilename);
+  v4->CloseWriteFile();
+  v4->LoadFile(v4->pLODName, 0);
+  return 0;
+}
+
+
+//----- (00461A43) --------------------------------------------------------
+bool LODWriteableFile::LoadFile(const char *pFilename, bool bWriting)
+{
+  LODWriteableFile *v3; // esi@1
+  FILE *pFile_dup; // eax@4
+  unsigned int v5; // ecx@5
+  __int32 v6; // eax@5
+  FILE *v7; // ST00_4@5
+  size_t v8; // edi@5
+  const char *v10; // [sp-4h] [bp-30h]@2
+
+  v3 = this;
+  if ( bWriting & 1 )
+    v10 = "rb";
+  else
+    v10 = "rb+";
+  pFile_dup = fopen(pFilename, v10);
+  v3->pFile = pFile_dup;
+  if ( !pFile_dup )
+  {
+    isFileOpened = false;
+    return 0;
+  }
+  strcpy(pLODName, pFilename);
+  fread(&header, 0x100u, 1u, v3->pFile);
+  
+  LOD::Directory dir; // [sp+Ch] [bp-20h]@5
+  //LOD::Directory::LOD::Directory(&dir);
+
+  fread(&dir, 0x20u, 1u, v3->pFile);
+  fseek(v3->pFile, 0, 0);
+  isFileOpened = 1;
+  strcpy((char *)v3->pContainerName, "chapter");
+  v5 = (signed __int16)dir.uNumSubIndices;
+  v6 = dir.uOfsetFromSubindicesStart;
+  v3->uCurrentIndexDir = 0;
+  v3->uOffsetToSubIndex = v6;
+  v7 = v3->pFile;
+  v3->uNumSubIndices = v5;
+  v3->uLODDataSize = dir.uDataSize;
+  fseek(v7, v6, SEEK_SET);
+  v8 = v3->uNumSubIndices;
+  if ( (signed int)v8 > 300 )
+  {
+    MessageBoxA(0, "LODchapterPages exceed 300", "LOD::File", MB_ICONEXCLAMATION);
+    fclose(v3->pFile);
+    return 0;
+  }
+  fread(pSubIndices, 0x20u, v8, v3->pFile);
+  return 1;
+}
+
+
+//----- (00461A11) --------------------------------------------------------
+void LOD::File::FreeSubIndexAndIO()
+{
+  void *v1; // edi@1
+  LOD::Directory **v2; // esi@1
+
+  v1 = this;
+  v2 = &this->pSubIndices;
+  pAllocator->FreeChunk(this->pSubIndices);
+  v1 = (char *)v1 + 264;
+  pAllocator->FreeChunk(pIOBuffer);// delete [] pIOBuffer;
+  pIOBuffer = nullptr;
+  pSubIndices = nullptr;
+}
+
+
+//----- (00461954) --------------------------------------------------------
+void LOD::File::AllocSubIndicesAndIO(unsigned int uNumSubIndices, unsigned int uBufferSize)
+{
+  //LOD::File *v3; // esi@1
+  LOD::Directory *pSubIndices_dup; // eax@3
+  char v5; // zf@3
+
+  //v3 = this;
+  if (pSubIndices)
+  {
+    MessageBoxA(0, "Attempt to reset a LOD subindex!", "MM6", MB_ICONEXCLAMATION);
+    pAllocator->FreeChunk(pSubIndices);
+    pSubIndices = nullptr;
+  }
+  pSubIndices_dup = (LOD::Directory *)pAllocator->AllocNamedChunk(
+                                      pSubIndices,
+                                      32 * uNumSubIndices,
+                                      "LODsub");
+  v5 = pIOBuffer == 0;
+  pSubIndices = pSubIndices_dup;
+  if ( !v5 )
+  {
+    MessageBoxA(0, "Attempt to reset a LOD IObuffer!", "MM6", MB_ICONEXCLAMATION);
+    pAllocator->FreeChunk(pIOBuffer);
+    pIOBuffer = 0;
+    uIOBufferSize = 0;
+  }
+  if ( uBufferSize )
+  {
+    pIOBuffer = (unsigned __int8 *)pAllocator->AllocNamedChunk(pIOBuffer, uBufferSize, "LODio");
+    uIOBufferSize = uBufferSize;
+  }
+}
+
+
+
+//----- (0046188A) --------------------------------------------------------
+int LOD::File::LoadSubIndices(const char *pContainer)
+{
+  LOD::File *v2; // esi@1
+  unsigned int uDir; // edi@1
+  int uDir_dup; // ebx@2
+  int result; // eax@5
+  LOD::Directory *v6; // eax@7
+  LOD::Directory *v7; // eax@7
+  __int32 v8; // edx@7
+  FILE *v9; // ST00_4@7
+  LOD::Directory *pSubIndices_dup; // eax@7
+
+  v2 = this;
+  ResetSubIndices();
+  uDir = 0;
+  if ( (signed int)v2->header.uNumIndices <= 0 )
+  {
+LABEL_5:
+    result = 3;
+  }
+  else
+  {
+    uDir_dup = 0;
+    while ( _strcmpi(pContainer, (const char *)&v2->pRoot[uDir_dup]) )
+    {
+      ++uDir;
+      ++uDir_dup;
+      if ( (signed int)uDir >= (signed int)v2->header.uNumIndices )
+        goto LABEL_5;
+    }
+    strcpy((char *)v2->pContainerName, pContainer);
+    v6 = v2->pRoot;
+    v2->uCurrentIndexDir = uDir;
+    v7 = &v6[uDir];
+    v8 = v7->uOfsetFromSubindicesStart;
+    v2->uOffsetToSubIndex = v8;
+    v9 = v2->pFile;
+    v2->uNumSubIndices = v7->uNumSubIndices;
+    fseek(v9, v8, 0);
+    pSubIndices_dup = (LOD::Directory *)pAllocator->AllocNamedChunk(
+                                        v2->pSubIndices,
+                                        32 * (v2->uNumSubIndices + 5),
+                                        "LOD Index");
+    v2->pSubIndices = pSubIndices_dup;
+    if ( pSubIndices_dup )
+      fread(pSubIndices_dup, 0x20u, v2->uNumSubIndices, v2->pFile);
+    result = 0;
+  }
+  return result;
+}
+
+//----- (004617D5) --------------------------------------------------------
+bool LOD::File::LoadHeader(const char *pFilename, bool bWriting)
+{
+  LOD::File *this_dup; // esi@1
+  FILE *pFile_dup; // eax@6
+  void *pRoot_dup; // eax@7
+  const char *v6; // [sp-4h] [bp-Ch]@4
+  FILE *v7; // [sp-4h] [bp-Ch]@7
+
+  this_dup = this;
+  if ( this->isFileOpened )
+    Close();
+  if ( bWriting & 1 )
+    v6 = "rb";
+  else
+    v6 = "rb+";
+  pFile_dup = fopen(pFilename, v6);
+  this_dup->pFile = pFile_dup;
+  if ( pFile_dup )
+  {
+    strcpy(this_dup->pLODName, pFilename);
+    fread(&this_dup->header, 0x100u, 1u, this_dup->pFile);
+    pRoot_dup = pAllocator->AllocNamedChunk(this_dup->pRoot, 0xA0u, "LOD CArray");
+    this_dup->pRoot = (LOD::Directory *)pRoot_dup;
+    v7 = this_dup->pFile;
+    if ( pRoot_dup )
+    {
+      fread(pRoot_dup, 0x20u, this_dup->header.uNumIndices, v7);
+      fseek(this_dup->pFile, 0, 0);
+      this_dup->isFileOpened = 1;
+      return false;
+    }
+    else
+    {
+      fclose(v7);
+      return true;
+    }
+  }
+  return true;
+}
+
+
+//----- (004617B6) --------------------------------------------------------
+void LOD::FileHeader::Reset()
+{
+  this->pSignature[0] = 0;
+  this->LodVersion[0] = 0;
+  this->LodDescription[0] = 0;
+  this->LODSize = 0;
+  this->dword_0000A8 = 0;
+  this->uNumIndices = 0;
+}
+
+//----- (00461790) --------------------------------------------------------
+LOD::File::~File()
+{
+  LOD::File *v1; // esi@1
+
+  v1 = this;
+  if ( this->isFileOpened )
+  {
+    fclose(this->pFile);
+    pAllocator->FreeChunk(v1->pSubIndices);
+  }
+}
+
+
+//----- (0046175B) --------------------------------------------------------
+LOD::File::File():
+  pRoot(nullptr),
+  isFileOpened(false)
+{
+  LOD::File *v1; // esi@1
+
+  memset(pLODName, 0, 256);
+  memset(pContainerName, 0, 16);
+  v1 = this;
+  v1->pFile = 0;
+  v1->pSubIndices = 0;
+  v1->pIOBuffer = 0;
+  v1->isFileOpened = 0;
+  v1->uIOBufferSize = 0;
+  Close();
+}
+
+
+//----- (00461743) --------------------------------------------------------
+LOD::Directory *LOD::Directory::Reset()
+{
+  LOD::Directory *result; // eax@1
+
+  result = this;
+  this->pFilename[0] = 0;
+  this->uOfsetFromSubindicesStart = 0;
+  this->uDataSize = 0;
+  this->dword_000018 = 0;
+  this->uNumSubIndices = 0;
+  this->word_00001E = 0;
+  return result;
+}
+
+
+//----- (0046172B) --------------------------------------------------------
+LOD::Directory::Directory()
+{
+  memset(pFilename, 0, 16);
+  this->pFilename[0] = 0;
+  this->uOfsetFromSubindicesStart = 0;
+  this->uDataSize = 0;
+  this->uNumSubIndices = 0;
+  this->dword_000018 = 0;
+  this->word_00001E = 0;
+}
+
+//----- (0046165E) --------------------------------------------------------
+int LOD::File::CalcIndexFast(int startIndex, int maxIndex, const char *pContainerName)
+{
+  int v4; // esi@1
+  int v5; // ebx@2
+  int result; // eax@2
+  int v7; // edi@10
+  int v8; // esi@11
+  int v9; // esi@17
+  LOD::File *v10; // [sp+Ch] [bp-4h]@1
+
+  v4 = startIndex;
+  v10 = this;
+  while ( 1 )                                   // binary search in LOD indices
+  {
+    while ( 1 )
+    {
+      v5 = maxIndex - v4;
+      result = _strcmpi((const char *)pContainerName, (const char *)(&v10->pSubIndices[(maxIndex - v4) / 2] + v4));
+      if ( !result )
+        _6A0CA4_lod_binary_search = (maxIndex - v4) / 2 + v4;
+      if ( v4 == maxIndex )
+        goto LABEL_14;
+      if ( result < 0 )
+        break;
+      if ( v5 <= 4 )
+      {
+        v7 = v4;
+        if ( v4 < maxIndex )
+        {
+          v9 = v4;
+          do
+          {
+            result = _strcmpi((const char *)pContainerName, (const char *)&v10->pSubIndices[v9]);
+            if ( !result )
+              goto LABEL_21;
+            ++v7;
+            ++v9;
+          }
+          while ( v7 < maxIndex );
+        }
+LABEL_14:
+        _6A0CA4_lod_binary_search = -1;
+        return result;
+      }
+      v4 += (maxIndex - v4) / 2;
+    }
+    if ( v5 <= 4 )
+      break;
+    maxIndex = (maxIndex - v4) / 2 + v4;
+  }
+  v7 = v4;
+  if ( v4 >= maxIndex )
+    goto LABEL_14;
+  v8 = v4;
+  while ( 1 )
+  {
+    result = _strcmpi((const char *)pContainerName, (const char *)&v10->pSubIndices[v8]);
+    if ( !result )
+      break;
+    ++v7;
+    ++v8;
+    if ( v7 >= maxIndex )
+      goto LABEL_14;
+  }
+LABEL_21:
+  _6A0CA4_lod_binary_search = v7;
+  return result;
+}
+// 6A0CA4: using guessed type int _6A0CA4_lod_binary_search;
+
+
+//----- (0046161C) --------------------------------------------------------
+bool LOD::File::DoesContainerExist(const char *pContainer)
+{
+  LOD::File *this_dup; // esi@1
+  int i; // ebx@1
+  signed int i_dup; // edi@1
+  bool result; // eax@4
+
+  this_dup = this;
+  i = 0;
+  i_dup = 0;
+  if ( (signed int)this->uNumSubIndices <= 0 )
+  {
+LABEL_4:
+    result = 0;
+  }
+  else
+  {
+    while ( _strcmpi((const char *)pContainer, (const char *)&this_dup->pSubIndices[i]) )
+    {
+      ++i_dup;
+      ++i;
+      if ( i_dup >= (signed int)this_dup->uNumSubIndices )
+        goto LABEL_4;
+    }
+    result = 1;
+  }
+  return result;
+}
+
+
+//----- (00461397) --------------------------------------------------------
+int LODFile_Sprites::_461397()
+{
+  int result; // eax@1
+  int *pfield_ECA0; // edi@1
+  int v3; // esi@1
+  int v4; // ecx@3
+
+  result = this->uNumLoadedSprites;
+  pfield_ECA0 = &this->field_ECA0;
+  v3 = this->field_ECA0;
+  this->field_ECA8 = result;
+  if ( result < v3 )
+    this->field_ECA8 = v3;
+  v4 = this->field_ECA4;
+  if ( v3 < v4 )
+    *pfield_ECA0 = v4;
+  return result;
+}
+
+//----- (00461580) --------------------------------------------------------
+FILE *LOD::File::FindContainer(const char *pContainerName, bool bLinearSearch)
+{
+  unsigned int v4; // eax@4
+  if (!isFileOpened)
+    return 0;
+
+
+  if (bLinearSearch)
+  {
+    for (uint i = 0; i < uNumSubIndices; ++i)
+      if (!strcmpi(pContainerName, pSubIndices[i].pFilename))
+      {
+        v4 = pSubIndices[i].uOfsetFromSubindicesStart;
+        fseek(pFile, uOffsetToSubIndex + v4, SEEK_SET);
+        return pFile;
+      }
+
+    return nullptr;
+  }
+  else
+  {
+    CalcIndexFast(0, uNumSubIndices, pContainerName);
+    if ( _6A0CA4_lod_binary_search < 0 )
+      return 0;
+    v4 = pSubIndices[_6A0CA4_lod_binary_search].uOfsetFromSubindicesStart;
+    fseek(pFile, uOffsetToSubIndex + v4, SEEK_SET);
+    return pFile;
+  }
+}
+
+//----- (0041097D) --------------------------------------------------------
+void LODFile_IconsBitmaps::SetupPalettes(unsigned int uTargetRBits, unsigned int uTargetGBits, unsigned int uTargetBBits)
+{
+  int v4; // edx@1
+  LODFile_IconsBitmaps *v5; // esi@1
+  int v6; // ecx@1
+  unsigned __int8 v7; // zf@4
+  unsigned __int8 v8; // sf@4
+  unsigned __int16 **v9; // edi@5
+  FILE *v10; // eax@7
+  FILE *v11; // ebx@7
+  signed int v12; // ebx@8
+  int v13; // eax@9
+  int v14; // edx@9
+  int v16; // [sp+4Ch] [bp-8h]@4
+  FILE *File; // [sp+50h] [bp-4h]@7
+
+  v4 = uTargetGBits;
+  v5 = this;
+  v6 = uTargetBBits;
+  if ( v5->uTextureRedBits != uTargetRBits
+    || v5->uTextureGreenBits != uTargetGBits
+    || v5->uTextureBlueBits != uTargetBBits )
+  {
+    v16 = 0;
+    v7 = v5->uNumLoadedFiles == 0;
+    v8 = (v5->uNumLoadedFiles & 0x80000000u) != 0;
+    v5->uTextureRedBits = uTargetRBits;
+    v5->uTextureGreenBits = v4;
+    v5->uTextureBlueBits = v6;
+    if ( !(v8 | v7) )
+    {
+      v9 = &v5->pTextures[0].pPalette16;
+      do
+      {
+        Texture DstBuf; // [sp+4h] [bp-50h]@6
+        //Texture::Texture(&DstBuf);
+
+        if ( *v9 )
+        {
+          v10 = FindContainer((const char *)v9 - 64, 0);
+          v11 = v10;
+          File = v10;
+          if ( v10 )
+          {
+            fread(&DstBuf, 1u, 0x30u, v10);
+            fseek(v11, DstBuf.uTextureSize, 1);
+            v12 = 0;
+            do
+            {
+              fread((char *)&uTargetRBits + 3, 1u, 1u, File);
+              fread((char *)&uTargetBBits + 3, 1u, 1u, File);
+              v13 = fread((char *)&uTargetGBits + 3, 1u, 1u, File);
+              LOWORD(v13) = (unsigned __int8)(BYTE3(uTargetRBits) >> (8 - LOBYTE(v5->uTextureRedBits)));
+              (*v9)[v12] = v13 << (LOBYTE(v5->uTextureGreenBits) + LOBYTE(v5->uTextureBlueBits));
+              LOWORD(v14) = (unsigned __int8)(BYTE3(uTargetBBits) >> (8 - LOBYTE(v5->uTextureGreenBits)));
+              (*v9)[v12] |= v14 << v5->uTextureBlueBits;
+              (*v9)[v12] |= BYTE3(uTargetGBits) >> (8 - LOBYTE(v5->uTextureBlueBits));
+              ++v12;
+            }
+            while ( v12 < 256 );
+          }
+        }
+        ++v16;
+        v9 += 18;
+      }
+      while ( v16 < (signed int)v5->uNumLoadedFiles );
+    }
+  }
+}
+
+
+
+//----- (0041088B) --------------------------------------------------------
+void *LOD::File::LoadRaw(const char *pContainer, int a3)
+{
+  LOD::File *v3; // esi@1
+  FILE *v4; // eax@1
+  FILE *v5; // esi@1
+  void *v6; // eax@5
+  void *v7; // ebx@7
+  void *v8; // edi@7
+  void *v9; // eax@9
+  Texture DstBuf; // [sp+Ch] [bp-4Ch]@1
+  FILE *File; // [sp+54h] [bp-4h]@1
+  unsigned int Argsa; // [sp+60h] [bp+8h]@3
+
+  v3 = this;
+  v4 = FindContainer(pContainer, 0);
+  v5 = v4;
+  File = v4;
+  if ( !v4 )
+    Abortf("Unable to load %s", pContainer);
+  fread(&DstBuf, 1u, 0x30u, v4);
+  Argsa = DstBuf.uTextureSize;
+  if ( DstBuf.uDecompressedSize )
+  {
+    if ( a3 )
+      v6 = malloc(DstBuf.uDecompressedSize);
+    else
+      v6 = pAllocator->AllocNamedChunk(0, DstBuf.uDecompressedSize, DstBuf.pName);
+    v7 = v6;
+    v8 = pAllocator->AllocNamedChunk(0, DstBuf.uTextureSize, DstBuf.pName);
+    fread(v8, 1u, Argsa, File);
+    zlib::MemUnzip(v7, &DstBuf.uDecompressedSize, v8, DstBuf.uTextureSize);
+    DstBuf.uTextureSize = DstBuf.uDecompressedSize;
+    pAllocator->FreeChunk(v8);
+  }
+  else
+  {
+    if ( a3 )
+      v9 = malloc(DstBuf.uTextureSize);
+    else
+      v9 = pAllocator->AllocNamedChunk(0, DstBuf.uTextureSize, DstBuf.pName);
+    v7 = v9;
+    fread(v9, 1u, Argsa, v5);
+  }
+  return v7;
+}
+
+
+
+//----- (00410522) --------------------------------------------------------
+int LODFile_IconsBitmaps::_410522(Texture *pDst, const char *pContainer, unsigned int uTextureType)
+{
+  LODFile_IconsBitmaps *v4; // edi@1
+  Texture *v5; // esi@5
+  unsigned int v6; // eax@5
+  void *v7; // eax@6
+  unsigned int v8; // ST28_4@6
+  void *v9; // ST2C_4@6
+  unsigned __int8 *v10; // eax@7
+  FILE *v11; // ST28_4@7
+  void *v12; // eax@9
+  FILE *v13; // ST28_4@9
+  signed int v14; // eax@12
+  int v15; // ecx@12
+  int v16; // ecx@12
+  int v17; // eax@12
+  signed int v18; // ebx@14
+  int v19; // eax@15
+  int v20; // edx@15
+  signed int v21; // ecx@18
+  signed int v22; // ecx@23
+  char Args[100]; // [sp+4h] [bp-68h]@3
+  FILE *File; // [sp+68h] [bp-4h]@1
+
+  v4 = this;
+  File = FindContainer(pContainer, 0);
+  if ( !File )
+  {
+    File = FindContainer("pending", 0);
+    if ( !File )
+    {
+      sprintf(Args, "Can't find %s!", pContainer);
+      Abortf(Args);
+    }
+  }
+  v5 = pDst;
+  fread(pDst, 1u, 0x30u, File);
+  strcpy(v5->pName, pContainer);
+  pDst = (Texture *)v5->uTextureSize;
+  v6 = v5->uDecompressedSize;
+  v5->pLevelOfDetail0 = 0;
+  if ( v6 )
+  {
+    v7 = operator new(v6);
+    v8 = v5->uTextureSize;
+    v5->pLevelOfDetail0 = (unsigned __int8 *)v7;
+    pContainer = (const char *)operator new(v8);
+    fread((void *)pContainer, 1u, (size_t)pDst, File);
+    zlib::MemUnzip(v5->pLevelOfDetail0, &v5->uDecompressedSize, pContainer, v5->uTextureSize);
+    v9 = (void *)pContainer;
+    v5->uTextureSize = v5->uDecompressedSize;
+    free(v9);
+  }
+  else
+  {
+    v10 = (unsigned __int8 *)operator new(0);
+    v11 = File;
+    v5->pLevelOfDetail0 = v10;
+    fread(v10, 1u, (size_t)pDst, v11);
+  }
+  v5->pPalette24 = 0;
+  if ( uTextureType == 1 )
+  {
+    v12 = operator new(0x300u);
+    v13 = File;
+    v5->pPalette24 = (unsigned __int8 *)v12;
+    fread(v12, 1u, 0x300u, v13);
+LABEL_10:
+    v5->pPalette16 = 0;
+    goto LABEL_11;
+  }
+  if ( uTextureType != 2 )
+    goto LABEL_10;
+  v18 = 0;
+  v5->pPalette16 = 0;
+  v5->pPalette16 = (unsigned __int16 *)operator new(0x400u);
+  do
+  {
+    fread((char *)&pContainer + 3, 1u, 1u, File);
+    fread((char *)&uTextureType + 3, 1u, 1u, File);
+    v19 = fread((char *)&pDst + 3, 1u, 1u, File);
+    LOWORD(v19) = (unsigned __int8)(BYTE3(pContainer) >> (8 - LOBYTE(v4->uTextureRedBits)));
+    v5->pPalette16[v18] = v19 << (LOBYTE(v4->uTextureBlueBits) + LOBYTE(v4->uTextureGreenBits));
+    LOWORD(v20) = (unsigned __int8)(BYTE3(uTextureType) >> (8 - LOBYTE(v4->uTextureGreenBits)));
+    v5->pPalette16[v18] += v20 << v4->uTextureBlueBits;
+    v5->pPalette16[v18] += (unsigned __int8)(BYTE3(pDst) >> (8 - LOBYTE(v4->uTextureBlueBits)));
+    ++v18;
+  }
+  while ( v18 < 256 );
+LABEL_11:
+  if ( v5->pBits & 2 )
+  {
+    v14 = v5->uSizeOfMaxLevelOfDetail;
+    v15 = (int)&v5->pLevelOfDetail0[v14];
+    v5->pLevelOfDetail1 = (unsigned __int8 *)v15;
+    v16 = (v14 >> 2) + v15;
+    v5->pLevelOfDetail2 = (unsigned __int8 *)v16;
+    v17 = v16 + (v14 >> 4);
+  }
+  else
+  {
+    v17 = 0;
+    v5->pLevelOfDetail2 = 0;
+    v5->pLevelOfDetail1 = 0;
+  }
+  v5->pLevelOfDetail3 = (unsigned __int8 *)v17;
+  v21 = 1;
+  while ( 1 << v21 != v5->uTextureWidth )
+  {
+    ++v21;
+    if ( v21 >= 15 )
+      goto LABEL_23;
+  }
+  v5->uWidthLn2 = v21;
+LABEL_23:
+  v22 = 1;
+  while ( 1 << v22 != v5->uTextureHeight )
+  {
+    ++v22;
+    if ( v22 >= 15 )
+      goto LABEL_28;
+  }
+  v5->uHeightLn2 = v22;
+LABEL_28:
+  switch ( v5->uWidthLn2 )
+  {
+    case 2:
+      v5->uWidthMinus1 = 3;
+      break;
+    case 3:
+      v5->uWidthMinus1 = 7;
+      break;
+    case 4:
+      v5->uWidthMinus1 = 15;
+      break;
+    case 5:
+      v5->uWidthMinus1 = 31;
+      break;
+    case 6:
+      v5->uWidthMinus1 = 63;
+      break;
+    case 7:
+      v5->uWidthMinus1 = 127;
+      break;
+    case 8:
+      v5->uWidthMinus1 = 255;
+      break;
+    case 9:
+      v5->uWidthMinus1 = 511;
+      break;
+    case 10:
+      v5->uWidthMinus1 = 1023;
+      break;
+    case 11:
+      v5->uWidthMinus1 = 2047;
+      break;
+    case 12:
+      v5->uWidthMinus1 = 4095;
+      break;
+    default:
+      break;
+  }
+  switch ( v5->uHeightLn2 )
+  {
+    case 2:
+      v5->uHeightMinus1 = 3;
+      break;
+    case 3:
+      v5->uHeightMinus1 = 7;
+      break;
+    case 4:
+      v5->uHeightMinus1 = 15;
+      break;
+    case 5:
+      v5->uHeightMinus1 = 31;
+      break;
+    case 6:
+      v5->uHeightMinus1 = 63;
+      break;
+    case 7:
+      v5->uHeightMinus1 = 127;
+      break;
+    case 8:
+      v5->uHeightMinus1 = 255;
+      break;
+    case 9:
+      v5->uHeightMinus1 = 511;
+      break;
+    case 10:
+      v5->uHeightMinus1 = 1023;
+      break;
+    case 11:
+      v5->uHeightMinus1 = 2047;
+      break;
+    case 12:
+      v5->uHeightMinus1 = 4095;
+      break;
+    default:
+      return 1;
+  }
+  return 1;
+}
+
+
+//----- (00410423) --------------------------------------------------------
+void LODFile_IconsBitmaps::_410423_move_textures_to_device()
+{
+  LODFile_IconsBitmaps *v1; // esi@1
+  unsigned int v2; // edi@1
+  char *v3; // ebx@2
+  size_t v4; // eax@9
+  char *v5; // ST1C_4@9
+  void *v6; // eax@12
+  signed int v7; // esi@13
+
+  v1 = this;
+  v2 = this->uNumLoadedFiles - 1;
+  if ( (v2 & 0x80000000u) == 0 )
+  {
+    v3 = &this->pTextures[v2].pName[2];
+    do
+    {
+      if ( v1->ptr_011BB4[v2] )
+      {
+        if ( *(v3 - 2) != 'w' || *(v3 - 1) != 't' || *v3 != 'r' || v3[1] != 'd' || v3[2] != 'r' )
+        {
+          pRenderer->LoadTexture(
+            v3 - 2,
+            *((short *)v3 + 17),
+            (IDirectDrawSurface4 **)&v1->pHardwareSurfaces[v2],
+            &v1->pHardwareTextures[v2]);
+        }
+        else
+        {
+          v4 = strlen(v3 - 2);
+          v5 = (char *)operator new(v4 + 2);
+          *v5 = 'h';
+          strcpy(v5 + 1, v3 - 2);
+          pRenderer->LoadTexture(
+            v5,
+            *((short *)v3 + 17),
+            (IDirectDrawSurface4 **)&v1->pHardwareSurfaces[v2],
+            &v1->pHardwareTextures[v2]);
+          free(v5);
+        }
+      }
+      --v2;
+      v3 -= 72;
+    }
+    while ( (v2 & 0x80000000u) == 0 );
+  }
+  v6 = v1->ptr_011BB4;
+  if ( v6 )
+  {
+    v7 = v1->uNumLoadedFiles;
+    if ( v7 > 1 )
+      memset(v6, 0, v7 - 1);
+  }
+}
+
+
+//----- (004103BB) --------------------------------------------------------
+void LODFile_IconsBitmaps::ReleaseHardwareTextures()
+{
+  LODFile_IconsBitmaps *v1; // esi@1
+  unsigned int v2; // edi@1
+  struct IDirect3DTexture2 **v3; // eax@2
+  struct IDirect3DTexture2 *v4; // eax@3
+  struct IDirectDrawSurface **v5; // eax@5
+  struct IDirectDrawSurface *v6; // eax@6
+
+  v1 = this;
+  v2 = this->uNumLoadedFiles;
+  while ( 1 )
+  {
+    --v2;
+    if ( (v2 & 0x80000000u) != 0 )
+      break;
+    v3 = v1->pHardwareTextures;
+    if ( v3 )
+    {
+      v4 = v3[v2];
+      if ( v4 )
+      {
+        v4->Release();
+        v1->pHardwareTextures[v2] = 0;
+        v1->ptr_011BB4[v2] = 1;
+      }
+    }
+    v5 = v1->pHardwareSurfaces;
+    if ( v5 )
+    {
+      v6 = v5[v2];
+      if ( v6 )
+      {
+        v6->Release();
+        v1->pHardwareSurfaces[v2] = 0;
+        v1->ptr_011BB4[v2] = 1;
+      }
+    }
+  }
+}
+
+
+//----- (0041033D) --------------------------------------------------------
+void LODFile_IconsBitmaps::ReleaseLostHardwareTextures()
+{
+  LODFile_IconsBitmaps *v1; // edi@1
+  unsigned int i; // ebx@1
+  struct IDirectDrawSurface **pHardwareSurfaces; // eax@2
+  int v4; // esi@3
+  struct IDirectDrawSurface *pSurface; // eax@3
+  struct IDirect3DTexture2 **v6; // eax@5
+  struct IDirect3DTexture2 *v7; // eax@6
+
+  v1 = this;
+  for ( i = this->uNumLoadedFiles - 1; (i & 0x80000000u) == 0; --i )
+  {
+    pHardwareSurfaces = v1->pHardwareSurfaces;
+    if ( pHardwareSurfaces )
+    {
+      v4 = i;
+      pSurface = pHardwareSurfaces[i];
+      if ( pSurface )
+      {
+        if ( pSurface->IsLost() == DDERR_SURFACELOST )
+        {
+          v6 = v1->pHardwareTextures;
+          if ( v6 )
+          {
+            v7 = v6[v4];
+            if ( v7 )
+            {
+              v7->Release();
+              v1->pHardwareTextures[v4] = 0;
+            }
+          }
+          v1->pHardwareSurfaces[v4]->Release();
+          v1->pHardwareSurfaces[v4] = 0;
+          v1->ptr_011BB4[i] = 1;
+        }
+      }
+    }
+  }
+}
+
+//----- (004101B1) --------------------------------------------------------
+int LODFile_IconsBitmaps::ReloadTexture(Texture *pDst, const char *pContainer, int mode)
+{
+  LODFile_IconsBitmaps *v4; // edi@1
+  FILE *v5; // eax@1
+  Texture *v6; // esi@2
+  unsigned int v7; // ebx@6
+  unsigned int v8; // ecx@6
+  signed int result; // eax@7
+  size_t *v10; // ebx@8
+  signed int v11; // ebx@12
+  int v12; // eax@13
+  int v13; // edx@13
+  FILE *File; // [sp+Ch] [bp-8h]@1
+  unsigned __int8 v15; // [sp+11h] [bp-3h]@13
+  unsigned __int8 v16; // [sp+12h] [bp-2h]@13
+  unsigned __int8 DstBuf; // [sp+13h] [bp-1h]@13
+  void *DstBufa; // [sp+1Ch] [bp+8h]@10
+  void *Sourcea; // [sp+20h] [bp+Ch]@10
+  unsigned int Counta; // [sp+24h] [bp+10h]@6
+
+  v4 = this;
+  v5 = FindContainer(pContainer, 0);
+  File = v5;
+  if ( v5
+    && (v6 = pDst, pDst->pLevelOfDetail0)
+    && mode == 2
+    && pDst->pPalette16
+    && !pDst->pPalette24
+    && (v7 = pDst->uTextureSize,
+        fread(pDst, 1u, 0x30u, v5),
+        strcpy(pDst->pName, pContainer),
+        v8 = pDst->uTextureSize,
+        Counta = pDst->uTextureSize,
+        (signed int)v8 <= (signed int)v7) )
+  {
+    v10 = &pDst->uDecompressedSize;
+    if ( !pDst->uDecompressedSize || v4->dword_011BA4 )
+    {
+      fread(pDst->pLevelOfDetail0, 1u, v8, File);
+    }
+    else
+    {
+      Sourcea = malloc(pDst->uDecompressedSize);
+      DstBufa = malloc(pDst->uTextureSize);
+      fread(DstBufa, 1u, Counta, File);
+      zlib::MemUnzip(Sourcea, &v6->uDecompressedSize, DstBufa, v6->uTextureSize);
+      v6->uTextureSize = *v10;
+      free(DstBufa);
+      memcpy(v6->pLevelOfDetail0, Sourcea, *v10);
+      free(Sourcea);
+    }
+    v11 = 0;
+    do
+    {
+      fread(&DstBuf, 1u, 1u, File);
+      fread(&v16, 1u, 1u, File);
+      v12 = fread(&v15, 1u, 1u, File);
+      LOWORD(v12) = (unsigned __int8)(DstBuf >> (8 - LOBYTE(v4->uTextureRedBits)));
+      v6->pPalette16[v11] = v12 << (LOBYTE(v4->uTextureBlueBits) + LOBYTE(v4->uTextureGreenBits));
+      LOWORD(v13) = (unsigned __int8)(v16 >> (8 - LOBYTE(v4->uTextureGreenBits)));
+      v6->pPalette16[v11] += v13 << v4->uTextureBlueBits;
+      v6->pPalette16[v11] += (unsigned __int8)(v15 >> (8 - LOBYTE(v4->uTextureBlueBits)));
+      ++v11;
+    }
+    while ( v11 < 256 );
+    result = 1;
+  }
+  else
+  {
+    result = -1;
+  }
+  return result;
+}
+
+
+//----- (0040FC08) --------------------------------------------------------
+int LODFile_IconsBitmaps::LoadTextureFromLOD(Texture *pOutTex, const char *pContainer, enum TEXTURE_TYPE eTextureType)
+{
+  Texture *v8; // esi@3
+  size_t v11; // eax@14
+  enum TEXTURE_TYPE v12; // eax@14
+  signed int v13; // esi@14
+  unsigned int v14; // eax@21
+  unsigned int v15; // ecx@25
+  unsigned int *v16; // ebx@25
+  void *v17; // eax@27
+  unsigned int v18; // ST28_4@27
+  void *v19; // ST3C_4@27
+  Allocator *v20; // ebx@29
+  void *v21; // eax@29
+  size_t v22; // ST2C_4@29
+  const void *v23; // ecx@29
+  unsigned __int16 v24; // ax@29
+  unsigned __int16 v25; // cx@29
+  __int16 v26; // dx@29
+  unsigned int v27; // ecx@29
+  Texture *v28; // eax@29
+  unsigned int v29; // ST28_4@30
+  void *v30; // eax@30
+  unsigned int v31; // ST2C_4@30
+  void *v32; // eax@32
+  void *v33; // eax@34
+  signed int v34; // eax@37
+  unsigned __int8 *v35; // ecx@37
+  unsigned __int8 *v36; // ecx@37
+  unsigned __int8 *v37; // eax@37
+  signed int v38; // ebx@39
+  int v39; // eax@40
+  int v40; // edx@40
+  signed int v41; // ecx@43
+  signed int v42; // ecx@48
+
+  //v4 = pContainer;
+  //v5 = this;
+  //v6 = FindContainer(pContainer, 0);
+  //File = v6;
+  auto pFile = FindContainer(pContainer, false);
+  if (!pFile)
+    return -1;
+  v8 = pOutTex;
+  fread(pOutTex, 1u, 0x30u, pFile);
+  strcpy(v8->pName, pContainer);
+  if (pRenderer->pRenderD3D && v8->pBits & 2 && dword_011BA8)
+  {
+    if (!pHardwareSurfaces || !pHardwareTextures)
+    {
+      pHardwareSurfaces = new IDirectDrawSurface *[1000];
+      memset(pHardwareSurfaces, 0, 1000 * sizeof(IDirectDrawSurface4 *));
+
+      pHardwareTextures = new IDirect3DTexture2 *[1000];
+      memset(pHardwareTextures, 0, 1000 * sizeof(IDirect3DTexture2 *));
+
+      ptr_011BB4 = new char[1000];
+      memset(ptr_011BB4, 0, 1000);
+    }
+    if (strcmp(pContainer, "wtrdr"))//*v4 != 'w' || v4[1] != 't' || v4[2] != 'r' || v4[3] != 'd' || v4[4] != 'r' )
+    {
+      if (strcmp(pContainer, "WtrTyl"))//if ( *v4 != 'W' || v4[1] != 't' || v4[2] != 'r' || v4[3] != 'T' || v4[4] != 'y' || v4[5] != 'l' )
+      {
+        v14 = uNumLoadedFiles;
+      }
+      else
+      {
+        pRenderer->field_1036AC_bitmapid = uNumLoadedFiles;
+        v14 = uNumLoadedFiles;
+      }
+      v13 = pRenderer->LoadTexture(
+              pContainer,
+              v8->palette_id1,
+              (IDirectDrawSurface4 **)&pHardwareSurfaces[v14],
+              &pHardwareTextures[v14]);
+    }
+    else
+    {
+      v11 = strlen(pContainer);
+      v12 = (enum TEXTURE_TYPE)(int)operator new(v11 + 2);
+      eTextureType = v12;
+      *(char *)v12 = 104;
+      strcpy((char *)(v12 + 1), pContainer);
+      v13 = pRenderer->LoadTexture(
+              (const char *)eTextureType,
+              v8->palette_id1,
+              (IDirectDrawSurface4 **)&pHardwareSurfaces[uNumLoadedFiles],
+              &pHardwareTextures[uNumLoadedFiles]);
+      free((void *)eTextureType);
+    }
+    return v13;
+  }
+  v15 = v8->uTextureSize;
+  v16 = &v8->uDecompressedSize;
+  pOutTex = (Texture *)v8->uTextureSize;
+  if ( !v8->uDecompressedSize || dword_011BA4 )
+  {
+    v20 = pAllocator;
+    v32 = pAllocator->AllocNamedChunk(v8->pLevelOfDetail0, v15, v8->pName);
+    v8->pLevelOfDetail0 = (unsigned __int8 *)v32;
+    fread(v32, 1u, (size_t)pOutTex, pFile);
+  }
+  else
+  {
+    v17 = malloc(v8->uDecompressedSize);
+    v18 = v8->uTextureSize;
+    pContainer = (const char *)v17;
+    v19 = malloc(v18);
+    fread(v19, 1u, (size_t)pOutTex, pFile);
+    zlib::MemUnzip((void *)pContainer, &v8->uDecompressedSize, v19, v8->uTextureSize);
+    v8->uTextureSize = *v16;
+    free(v19);
+    if ( bUseLoResSprites && v8->pBits & 2 )
+    {
+      v20 = pAllocator;
+      pOutTex = (Texture *)(((signed int)v8->uSizeOfMaxLevelOfDetail >> 2)
+                          + ((signed int)v8->uSizeOfMaxLevelOfDetail >> 4)
+                          + ((signed int)v8->uSizeOfMaxLevelOfDetail >> 6));
+      v21 = pAllocator->AllocNamedChunk(v8->pLevelOfDetail0, (unsigned int)pOutTex, v8->pName);
+      v22 = (size_t)pOutTex;
+      v23 = &pContainer[v8->uTextureWidth * v8->uTextureHeight];
+      v8->pLevelOfDetail0 = (unsigned __int8 *)v21;
+      memcpy(v21, v23, v22);
+      v8->uTextureWidth = (signed __int16)v8->uTextureWidth >> 1;
+      v24 = v8->uTextureWidth;
+      v8->uTextureHeight = (signed __int16)v8->uTextureHeight >> 1;
+      v25 = v8->uTextureHeight;
+      --v8->uWidthLn2;
+      --v8->uHeightLn2;
+      v8->uWidthMinus1 = v24 - 1;
+      v26 = v25 - 1;
+      v27 = (signed __int16)v24 * (signed __int16)v25;
+      v28 = pOutTex;
+      v8->uHeightMinus1 = v26;
+      v8->uSizeOfMaxLevelOfDetail = v27;
+      v8->uTextureSize = (unsigned int)v28;
+    }
+    else
+    {
+      v29 = *v16;
+      v20 = pAllocator;
+      v30 = pAllocator->AllocNamedChunk(v8->pLevelOfDetail0, v29, v8->pName);
+      v31 = v8->uDecompressedSize;
+      v8->pLevelOfDetail0 = (unsigned __int8 *)v30;
+      memcpy(v30, pContainer, v31);
+    }
+    free((void *)pContainer);
+  }
+  pAllocator->FreeChunk(v8->pPalette16);
+  pAllocator->FreeChunk(v8->pPalette24);
+  if ( eTextureType == TEXTURE_24BIT_PALETTE )
+  {
+    v33 = pAllocator->AllocNamedChunk(v8->pPalette24, 0x300u, v8->pName);
+    v8->pPalette24 = (unsigned __int8 *)v33;
+    fread(v33, 1u, 0x300u, pFile);
+  }
+  else
+  {
+    v8->pPalette24 = 0;
+    if ( eTextureType == TEXTURE_16BIT_PALETTE )
+    {
+      v8->pPalette16 = (unsigned __int16 *)pAllocator->AllocNamedChunk(v8->pPalette16, 0x200u, v8->pName);
+      v38 = 0;
+      do
+      {
+        fread((char *)&eTextureType + 3, 1u, 1u, pFile);
+        fread((char *)&pContainer + 3, 1u, 1u, pFile);
+        v39 = fread((char *)&pOutTex + 3, 1u, 1u, pFile);
+        LOWORD(v39) = (unsigned __int8)(BYTE3(eTextureType) >> (8 - LOBYTE(uTextureRedBits)));
+        v8->pPalette16[v38] = v39 << (LOBYTE(uTextureBlueBits) + LOBYTE(uTextureGreenBits));
+        LOWORD(v40) = (unsigned __int8)(BYTE3(pContainer) >> (8 - LOBYTE(uTextureGreenBits)));
+        v8->pPalette16[v38] += v40 << uTextureBlueBits;
+        v8->pPalette16[v38] += (unsigned __int8)(BYTE3(pOutTex) >> (8 - LOBYTE(uTextureBlueBits)));
+        ++v38;
+      }
+      while ( v38 < 256 );
+      goto LABEL_36;
+    }
+  }
+  v8->pPalette16 = 0;
+LABEL_36:
+  if ( v8->pBits & 2 )
+  {
+    v34 = v8->uSizeOfMaxLevelOfDetail;
+    v35 = &v8->pLevelOfDetail0[v34];
+    v8->pLevelOfDetail1 = v35;
+    v36 = &v35[v34 >> 2];
+    v8->pLevelOfDetail2 = v36;
+    v37 = &v36[v34 >> 4];
+  }
+  else
+  {
+    v37 = 0;
+    v8->pLevelOfDetail2 = 0;
+    v8->pLevelOfDetail1 = 0;
+  }
+  v8->pLevelOfDetail3 = v37;
+  v41 = 1;
+  while ( 1 << v41 != v8->uTextureWidth )
+  {
+    ++v41;
+    if ( v41 >= 15 )
+      goto LABEL_48;
+  }
+  v8->uWidthLn2 = v41;
+LABEL_48:
+  v42 = 1;
+  while ( 1 << v42 != v8->uTextureHeight )
+  {
+    ++v42;
+    if ( v42 >= 15 )
+      goto LABEL_53;
+  }
+  v8->uHeightLn2 = v42;
+LABEL_53:
+  switch ( v8->uWidthLn2 )
+  {
+    case 2:
+      v8->uWidthMinus1 = 3;
+      break;
+    case 3:
+      v8->uWidthMinus1 = 7;
+      break;
+    case 4:
+      v8->uWidthMinus1 = 15;
+      break;
+    case 5:
+      v8->uWidthMinus1 = 31;
+      break;
+    case 6:
+      v8->uWidthMinus1 = 63;
+      break;
+    case 7:
+      v8->uWidthMinus1 = 127;
+      break;
+    case 8:
+      v8->uWidthMinus1 = 255;
+      break;
+    case 9:
+      v8->uWidthMinus1 = 511;
+      break;
+    case 10:
+      v8->uWidthMinus1 = 1023;
+      break;
+    case 11:
+      v8->uWidthMinus1 = 2047;
+      break;
+    case 12:
+      v8->uWidthMinus1 = 4095;
+      break;
+    default:
+      break;
+  }
+  switch ( v8->uHeightLn2 )
+  {
+    case 2:
+      v8->uHeightMinus1 = 3;
+      break;
+    case 3:
+      v8->uHeightMinus1 = 7;
+      break;
+    case 4:
+      v8->uHeightMinus1 = 15;
+      break;
+    case 5:
+      v8->uHeightMinus1 = 31;
+      break;
+    case 6:
+      v8->uHeightMinus1 = 63;
+      break;
+    case 7:
+      v8->uHeightMinus1 = 127;
+      break;
+    case 8:
+      v8->uHeightMinus1 = 255;
+      break;
+    case 9:
+      v8->uHeightMinus1 = 511;
+      break;
+    case 10:
+      v8->uHeightMinus1 = 1023;
+      break;
+    case 11:
+      v8->uHeightMinus1 = 2047;
+      break;
+    case 12:
+      v8->uHeightMinus1 = 4095;
+      break;
+    default:
+      return 1;
+  }
+  return 1;
+}
+
+
+Texture *LODFile_IconsBitmaps::LoadTexturePtr(const char *pContainer, enum TEXTURE_TYPE uTextureType)
+{
+  uint id = LoadTexture(pContainer, uTextureType);
+  if (id == -1)
+  {
+    Log::Warning(L"LOD error\\no container: \"%S\"", pContainer);
+    return nullptr;
+  }
+  return &pTextures[id];
+}
+
+//----- (0040FB20) --------------------------------------------------------
+unsigned int LODFile_IconsBitmaps::LoadTexture(const char *pContainer, enum TEXTURE_TYPE uTextureType)
+{
+  //LODFile_IconsBitmaps *v3; // esi@1
+  //unsigned int v4; // edi@1
+  //Texture *v5; // ebx@2
+  unsigned int v6; // ebx@8
+  const char *Sourcea; // [sp+14h] [bp+8h]@9
+
+  //v3 = this;
+  //v4 = 0;
+  areWeLoadingTexture = 1;
+
+  for (uint i = 0; i < uNumLoadedFiles; ++i)
+    if (!strcmpi(pContainer, pTextures[i].pName))
+      return i;
+
+//  if (!uNumLoadedFiles)
+//  {
+//LABEL_5:
+    if (uNumLoadedFiles >= 1000)
+    {
+      Log::Warning(L"Maximum texture number exceeded");
+      AbortWithError();
+    }
+    if (LoadTextureFromLOD(&pTextures[uNumLoadedFiles], pContainer, uTextureType) == -1)
+    {
+      v6 = 0;
+      if (uNumLoadedFiles > 0)
+      {
+        Sourcea = (const char *)pTextures;
+        while ( _strcmpi(Sourcea, "pending") )
+        {
+          Sourcea += 72;
+          ++v6;
+          if (v6 >= uNumLoadedFiles)
+            goto LABEL_15;
+        }
+        return v6;
+      }
+LABEL_15:
+      LoadTextureFromLOD(&pTextures[uNumLoadedFiles], "pending", uTextureType);
+    }
+    areWeLoadingTexture = 0;
+    ++uNumLoadedFiles;
+    return uNumLoadedFiles - 1;
+//  }
+//  v5 = pTextures;
+//  while ( _strcmpi(v5->pName, pContainer) )
+//  {
+//    ++v4;
+//    ++v5;
+//    if (v4 >= uNumLoadedFiles )
+//      goto LABEL_5;
+//  }
+//  return v4;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LOD.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,300 @@
+#pragma once
+#include <stdio.h>
+#include <memory.h>
+
+#include "Texture.h"
+
+
+/*  354 */
+enum TEXTURE_TYPE
+{
+  TEXTURE_DEFAULT = 0,
+  TEXTURE_24BIT_PALETTE = 0x1,
+  TEXTURE_16BIT_PALETTE = 0x2,
+};
+
+
+
+
+namespace LOD
+{
+  #pragma pack(push, 1)
+  struct FileHeader
+  {
+    inline FileHeader()
+    {
+      memset(pSignature, 0, 4);
+	  memset(LodVersion, 0, 80);
+      memset(LodDescription, 0, 80);
+      memset(array_0000B0, 0, 28);
+      memset(array_0000CC, 0, 52);
+    }
+
+    void Reset();
+
+    char pSignature[4];
+    char LodVersion[80];
+    //char field_C[32];
+    //char field_2C[40];
+    char LodDescription[80];
+    int LODSize;
+    int dword_0000A8;
+    unsigned int uNumIndices;
+    char array_0000B0[28];
+    char array_0000CC[52];
+  };
+  #pragma pack(pop)
+
+
+  #pragma pack(push, 1)
+  struct Directory
+  {
+    Directory();
+    Directory *Reset();
+
+
+    char pFilename[16];
+    unsigned int uOfsetFromSubindicesStart;
+    unsigned int uDataSize;
+    int dword_000018;
+    unsigned __int16 uNumSubIndices;
+    __int16 word_00001E;
+  };
+  #pragma pack(pop)
+
+
+  #pragma pack(push, 1)
+  struct File
+  {
+    File();
+    virtual ~File();
+    void *LoadRaw(const char *pContainer, int a3);
+    FILE *FindContainer(const char *pContainerName, bool bLinearSearch);
+    bool DoesContainerExist(const char *pContainer);
+    int CalcIndexFast(int startIndex, int maxIndex, const char *pContainerName);
+    bool LoadHeader(const char *pFilename, bool bWriting);
+    int LoadSubIndices(const char *pContainer);
+    void AllocSubIndicesAndIO(unsigned int uNumSubIndices, unsigned int uBufferSize);
+    void FreeSubIndexAndIO();
+    bool AppendDirectory(LOD::Directory *pDir, const void *pData);
+    void ResetSubIndices();
+    void Close();
+
+    FILE *pFile;
+    char pLODName[256];
+    unsigned int isFileOpened;
+    unsigned __int8 *pIOBuffer;
+    unsigned int uIOBufferSize;
+    struct FileHeader header;
+    struct Directory *pRoot;
+    char pContainerName[16];
+    unsigned int uCurrentIndexDir;
+    unsigned int uLODDataSize;
+    unsigned int uNumSubIndices;
+    struct Directory *pSubIndices;
+    unsigned int uOffsetToSubIndex;
+    FILE *pOutputFileHandle;
+  };
+  #pragma pack(pop)
+};
+
+
+
+
+
+
+/*    6 */
+#pragma pack(push, 1)
+struct LODWriteableFile: public LOD::File
+{
+  bool LoadFile(const char *pFilename, bool bWriting);
+  unsigned int Write(const LOD::Directory *pDir, const void *pDirData, int a4);
+  void CloseWriteFile();
+  int CreateTempFile();
+  int Save();
+  bool _4621A7();
+  int _461492(LOD::FileHeader *pHeader, LOD::Directory *pDir, const char *Source);
+
+  /*FILE *pFile;
+  char pLODName[256];
+  unsigned int isFileOpened;
+  unsigned __int8 *pIOBuffer;
+  unsigned int uIOBufferSize;
+  struct LOD::FileHeader header;
+  struct LOD::Directory *pRoot;
+  unsigned __int8 pContainerName[16];
+  unsigned int uCurrentIndexDir;
+  unsigned int uLODDataSize;
+  unsigned int uNumSubIndices;
+  struct LOD::Directory *pSubIndices;
+  unsigned int uOffsetToSubIndex;
+  FILE *pOutputFileHandle;*/
+};
+#pragma pack(pop)
+
+
+
+
+#pragma pack(push, 1)
+struct LODFile_IconsBitmaps: public LOD::File
+{
+  LODFile_IconsBitmaps();
+  virtual ~LODFile_IconsBitmaps();
+  int _40F9C5();
+  unsigned int FindTextureByName(const char *pName);
+  bool LoadBitmaps(const char *pFilename);
+  bool LoadIconsOrEvents(const char *pLODFilename);
+  void ReleaseAll();
+  unsigned int LoadTexture(const char *pContainer, enum TEXTURE_TYPE uTextureType = TEXTURE_DEFAULT);
+  Texture *LoadTexturePtr(const char *pContainer, enum TEXTURE_TYPE uTextureType = TEXTURE_DEFAULT);
+  int LoadTextureFromLOD(Texture *pOutTex, const char *pContainer, enum TEXTURE_TYPE eTextureType);
+  int ReloadTexture(Texture *pDst, const char *pContainer, int mode);
+  void ReleaseHardwareTextures();
+  void ReleaseLostHardwareTextures();
+  void _410423_move_textures_to_device();
+  int _410522(Texture *pDst, const char *pContainer, unsigned int uTextureType);
+  void SetupPalettes(unsigned int uTargetRBits, unsigned int uTargetGBits, unsigned int uTargetBBits);
+  void ReleaseAll2();
+  void _4114F2();
+  void _4355F7();
+
+
+  /*FILE *pFile;
+  unsigned __int8 pLODName[256];
+  unsigned int isFileOpened;
+  unsigned __int8 *pIOBuffer;
+  unsigned int uIOBufferSize;
+  struct LOD::FileHeader header;
+  struct LOD::Directory *pRoot;
+  unsigned __int8 pContainerName[16];
+  unsigned int uCurrentIndexDir;
+  unsigned int uLODDataSize;
+  unsigned int uNumSubIndices;
+  struct LOD::Directory *pSubIndices;
+  unsigned int uOffsetToSubIndex;
+  FILE *pOutputFileHandle;*/
+  struct Texture pTextures[1000];
+  unsigned int uNumLoadedFiles;
+  int dword_11B80;
+  int dword_11B84;
+  int dword_11B88;
+  int uTextureRedBits;
+  int uTextureGreenBits;
+  int uTextureBlueBits;
+  int uNumPrevLoadedFiles;
+  int uTexturePacksCount;
+  int dword_011BA0;
+  int dword_011BA4;
+  int dword_011BA8;
+  struct IDirectDrawSurface **pHardwareSurfaces;
+  struct IDirect3DTexture2 **pHardwareTextures;
+  char *ptr_011BB4;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+#pragma pack(push, 1)
+struct LODSprite
+{
+  //----- (0046244C) --------------------------------------------------------
+  inline LODSprite()
+  {
+    uHeight = 0;
+    uPaletteId = 0;
+    word_1A = 0;
+    pSpriteLines = nullptr;
+    pDecompressedBytes = nullptr;
+  }
+  ~LODSprite();
+
+  void Release();
+  int _4ACC38(struct RenderBillboardTransform_local0 *a2, char a3);
+  int _4AD2D1(struct RenderBillboardTransform_local0 *a2, int a3);
+  
+  char pName[12];
+  int uSpriteSize;
+  __int16 uWidth;
+  __int16 uHeight;
+  __int16 uPaletteId;
+  __int16 word_16;
+  __int16 uTexturePitch;
+  __int16 word_1A;
+  int uDecompressedSize;
+  struct LODSprite_stru0 *pSpriteLines;
+  void *pDecompressedBytes;
+};
+#pragma pack(pop)
+
+/*   15 */
+#pragma pack(push, 1)
+struct LODFile_Sprites: public LOD::File
+{
+  LODFile_Sprites();
+  virtual ~LODFile_Sprites();
+
+  void DeleteSomeSprites();
+  void DeleteSpritesRange(int uStartIndex, int uStopIndex);
+  int _461397();
+  void DeleteSomeOtherSprites();
+  int LoadSpriteFromFile(LODSprite *pSpriteHeader, const char *pContainer);
+  bool LoadSprites(const char *pFilename);
+  int LoadSprite(const char *pContainerName, unsigned int uPaletteID);
+  void ReleaseLostHardwareSprites();
+  void ReleaseAll();
+  void MoveSpritesToVideoMemory();
+
+
+  /*FILE *pFile;
+  unsigned __int8 pLODName[256];
+  unsigned int isFileOpened;
+  unsigned __int8 *pIOBuffer;
+  unsigned int uIOBufferSize;
+  struct LOD::FileHeader header;
+  struct LOD::Directory *pRoot;
+  unsigned __int8 pContainerName[16];
+  unsigned int uCurrentIndexDir;
+  unsigned int uLODDataSize;
+  unsigned int uNumSubIndices;
+  struct LOD::Directory *pSubIndices;
+  unsigned int uOffsetToSubIndex;
+  FILE *pOutputFileHandle;*/
+  struct LODSprite pSpriteHeaders[1500];
+  unsigned int uNumLoadedSprites;
+  int field_ECA0;
+  int field_ECA4;
+  int field_ECA8;
+  int field_ECAC;
+  struct Sprite *pHardwareSprites;
+  int field_ECB4;
+};
+#pragma pack(pop)
+
+/*   17 */
+#pragma pack(push, 1)
+struct LODSprite_stru0
+{
+  int dword_0;
+  void *ptr_4;
+};
+#pragma pack(pop)
+
+
+
+
+extern LODFile_IconsBitmaps *pEvents_LOD;
+extern LODFile_IconsBitmaps *pIcons_LOD;
+extern LODFile_Sprites *pSprites_LOD;
+extern LODFile_IconsBitmaps *pBitmaps_LOD;
+
+extern LODWriteableFile *pNew_LOD;
+extern LODWriteableFile *pGames_LOD;
+
+
+
+
+extern int _6A0CA4_lod_binary_search; // weak
+extern int _6A0CA8_lod_unused; // weak
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LayingItem.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,132 @@
+#include "LayingItem.h"
+#include "Party.h"
+#include "TurnEngine.h"
+#include "MapInfo.h"
+
+#include "mm7_data.h"
+
+
+
+
+size_t uNumLayingItems;
+LayingItem pLayingItems[1000];
+
+
+//----- (00438E35) --------------------------------------------------------
+__int16 LayingItem::_438E35()
+{
+  LayingItem *v1; // edi@1
+  MapInfo *pMapInfo; // esi@1
+  int v3; // ebx@1
+  int v4; // eax@1
+  int v5; // ebx@1
+  unsigned int v6; // ecx@1
+  int v7; // edx@2
+  unsigned int v8; // edx@4
+  unsigned int v9; // edx@6
+  unsigned int v10; // eax@7
+  signed int v11; // ebx@8
+  Player **v12; // esi@18
+  signed int v13; // edi@20
+  int v15; // [sp+Ch] [bp-Ch]@1
+  int v16; // [sp+10h] [bp-8h]@1
+  signed int v17; // [sp+14h] [bp-4h]@8
+  int v18; // [sp+14h] [bp-4h]@14
+
+  v1 = this;
+  pMapInfo = &pMapStats->pInfos[pMapStats->GetMapInfo(pCurrentMapName)];
+  v3 = abs(pParty->vPosition.x - v1->vPosition.x);
+  v15 = abs(pParty->vPosition.y - v1->vPosition.y);
+  v16 = abs(pParty->vPosition.z + pParty->sEyelevel - v1->vPosition.z);
+  v4 = v3;
+  v5 = v15;
+  v6 = v16;
+  if ( v4 < v15 )
+  {
+    v7 = v4;
+    v4 = v15;
+    v5 = v7;
+  }
+  if ( v4 < v16 )
+  {
+    v8 = v4;
+    v4 = v16;
+    v6 = v8;
+  }
+  if ( v5 < (signed int)v6 )
+  {
+    v9 = v6;
+    v6 = v5;
+    v5 = v9;
+  }
+  v10 = ((unsigned int)(11 * v5) >> 5) + (v6 >> 2) + v4;
+  if ( (signed int)v10 <= 768 )
+  {
+    v17 = 0;
+    v11 = 5;
+    if ( pMapInfo->field_2E )
+    {
+      do
+      {
+        ++v17;
+        v11 += rand() % 20 + 1;
+      }
+      while ( v17 < pMapInfo->field_2E );
+    }
+    switch ( v1->uItemType )
+    {
+      case 0x32Bu:
+        v18 = 0;
+        break;
+      case 0x32Cu:
+        v18 = 1;
+        break;
+      case 0x32Du:
+        v18 = 2;
+        break;
+      default:
+        LOWORD(v10) = v1->uItemType - 814;
+        if ( v1->uItemType != 814 )
+          return v10;
+        v18 = 8;
+        break;
+    }
+    v12 = &pPlayers[1];
+    do
+    {
+      if ( (*v12)->CanAct() && (v13 = (*v12)->GetPerception() + 20, rand() % v13 > 20) )
+        LOWORD(v10) = (*v12)->PlaySound(6, 0);
+      else
+        LOWORD(v10) = (*v12)->ReceiveDamage(v11, v18);
+      ++v12;
+    }
+    while ( (signed int)v12 <= (signed int)&pPlayers[4] );
+  }
+  return v10;
+}
+
+
+
+//----- (0042F933) --------------------------------------------------------
+void LayingItem::_42F933(unsigned int uLayingItemID)
+{
+  unsigned int v1; // ecx@1
+  unsigned __int16 *pAttributes; // ecx@2
+  unsigned __int16 v3; // ax@2
+
+  __debugbreak(); // find out what's going on
+
+  v1 = uLayingItemID;
+  pLayingItems[v1].uObjectDescID = 0;
+  if ( pParty->bTurnBasedModeOn == 1 )
+  {
+    pAttributes = &pLayingItems[v1].uAttributes;
+    v3 = *pAttributes;
+    if ( *pAttributes & 4 )
+    {
+      LOBYTE(v3) = v3 & 0xFB;
+      --pTurnEngine->field_1C;
+      *pAttributes = v3;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LayingItem.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,47 @@
+#pragma once
+#include "VectorTypes.h"
+#include "Items.h"
+
+
+/*   72 */
+#pragma pack(push, 1)
+struct LayingItem
+{
+  LayingItem();
+  int Create(int yaw, int pitch, int a4, int a5);
+  void _46BEF1_apply_spells();
+  __int16 _438E35();
+
+  static void UpdateObject_fn0_BLV(unsigned int uLayingItemID);
+  static void UpdateObject_fn0_ODM(unsigned int uLayingItemID);
+  static void _42F933(unsigned int uLayingItemID);
+
+
+  unsigned __int16 uItemType;
+  unsigned __int16 uObjectDescID;
+  struct Vec3_int_ vPosition;
+  struct Vec3_short_ vVelocity;
+  unsigned __int16 uFacing;
+  unsigned __int16 uSoundID;
+  unsigned __int16 uAttributes;
+  __int16 uSectorID;
+  unsigned __int16 uSpriteFrameID;
+  __int16 field_20;
+  __int16 field_22;
+  struct ItemGen stru_24;
+  int field_48;
+  int field_4C;
+  int field_50;
+  int field_54;
+  int field_58;
+  int field_5C;
+  char field_60_distance_related_prolly_lod;
+  char field_61;
+  char field_62[14];
+};
+#pragma pack(pop)
+
+
+
+extern size_t uNumLayingItems;
+extern LayingItem pLayingItems[1000];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightmapBuilder.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1804 @@
+#include "LightmapBuilder.h"
+#include "Game.h"
+#include "stru314.h"
+#include "Outdoor.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+
+LightsStack_StationaryLight_ *pStationaryLightsStack = new LightsStack_StationaryLight_;
+//StationaryLight pStationaryLights[400];
+//int uNumStationaryLightsApplied; // weak
+LightsStack_MobileLight_ *pMobileLightsStack = new LightsStack_MobileLight_;
+//MobileLight pMobileLights[400];
+//int uNumMobileLightsApplied;
+
+
+
+
+
+//----- (0045DF13) --------------------------------------------------------
+Lightmap::Lightmap()
+{
+  field_C18 = 0;
+}
+
+
+
+
+
+//----- (0045BB06) --------------------------------------------------------
+LightmapBuilder::LightmapBuilder()
+{
+}
+
+
+
+
+
+//----- (0045BC07) --------------------------------------------------------
+bool LightmapBuilder::ApplyLights(stru320 *a2, stru154 *a3, unsigned int uNumVertices, RenderVertexSoft *a5, IndoorCameraD3D_Vec4 *a6, char uClipFlag)
+{
+  Vec3_int_ pos; // [sp+2Ch] [bp-40h]@21
+  RenderVertexSoft *a9; // [sp+68h] [bp-4h]@8
+
+  if (!uNumVertices)
+    return false;
+
+  static RenderVertexSoft static_69B140[64];
+
+  a9 = a5;
+  if (a6)
+  {
+    for (uint i = 0; i < uNumVertices; ++i)
+      memcpy(static_69B140 + i, a5 + i, sizeof(RenderVertexSoft));
+
+    __debugbreak();
+    if (pGame->pIndoorCameraD3D->_437376(
+           a3,
+           static_69B140,
+           &uNumVertices) == 1)
+    {
+      if ( !uNumVertices )
+        return false;
+      a9 = static_69B140;
+    }
+  }
+
+  static stru314 static_69B110;
+  static_69B110.field_4.x = a3->face_plane.vNormal.x;
+  static_69B110.field_4.y = a3->face_plane.vNormal.y;
+  static_69B110.field_4.z = a3->face_plane.vNormal.z;
+  static_69B110.dist = a3->face_plane.dist;
+  if (!pGame->pIndoorCameraD3D->GetFacetOrientation(
+          a3->polygonType,
+          &static_69B110.field_4,
+          &static_69B110.field_10,
+          &static_69B110.field_1C))
+  {
+    MessageBoxW(nullptr, L"Error: Failed to get the facet orientation", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:119", 0);
+    ExitProcess(0);
+  }
+
+  for (uint i = 0; i < a2->uNumLightsApplied; ++i)
+  {
+    pos.x = a2->_blv_lights_xs[i];
+    pos.y = a2->_blv_lights_ys[i];
+    pos.z = a2->_blv_lights_zs[i];
+
+    uint uColorR = (uint)floorf(a2->_blv_lights_rs[i] * 255.0 + 0.5f) & 0xFF,
+         uColorG = (uint)floorf(a2->_blv_lights_gs[i] * 255.0 + 0.5f) & 0xFF,
+         uColorB = (uint)floorf(a2->_blv_lights_bs[i] * 255.0 + 0.5f) & 0xFF;
+    uint uColor = (uColorR << 16) | (uColorG << 8) | uColorB;
+    if (!uColor)
+      uColor = 0x00FFFFF;
+
+    if (!_45BE86_build_light_polygon(
+              &pos,
+              a2->_blv_lights_radii[i],
+              uColor,
+              a2->_blv_lights_light_dot_faces[i],
+              a2->_blv_lights_types[i],
+              &static_69B110,
+              uNumVertices,
+              a9,
+              uClipFlag) )
+    {
+      MessageBoxW(nullptr, L"Error: Failed to build light polygon", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:138", 0);
+    }
+  }
+  return true;
+}
+
+//----- (0045BE86) --------------------------------------------------------
+bool LightmapBuilder::_45BE86_build_light_polygon(Vec3_int_ *pos, float radius, unsigned int uColorMask, float dot_dist, int uLightType, stru314 *a7, unsigned int uNumVertices, RenderVertexSoft *a9, char uClipFlag)
+{
+  Lightmap *v11; // edi@3
+  double v17; // st7@5
+  double v24; // st7@6
+  int v31; // eax@8
+  int v32; // ebx@8
+  unsigned int v33; // ecx@8
+  int v34; // edx@9
+  int v35; // edx@11
+  unsigned int v36; // edx@13
+  int v37; // ecx@14
+  double v38; // st7@14
+  double v39; // st7@16
+  double v40; // st7@16
+  int v45; // eax@24
+  int v53; // [sp-8h] [bp-54h]@34
+
+  if (fabsf(radius) < 1e-6f)
+    return true;
+
+  v11 = uLightType & 1 ? &std__vector_000004[std__vector_000004_size] :
+                         &std__vector_183808[std__vector_183808_size];
+  flt_3C8C24 = radius - dot_dist;
+  flt_3C8C28 = sqrt((radius + dot_dist) * (radius - dot_dist));
+  flt_3C8C2C_lightmaps_brightness = 1.0 - (radius - flt_3C8C28) / radius;
+  v11->field_C08 = (double)pos->x - dot_dist * a7->field_4.x;
+  v11->field_C0A = (double)pos->y - dot_dist * a7->field_4.y;
+  v11->field_C0C = (double)pos->z - dot_dist * a7->field_4.z;
+
+  v17 = radius * flt_3C8C2C_lightmaps_brightness;
+  flt_3C8C30 = v17;
+  flt_3C8C0C = v17 * a7->field_10.x;
+  flt_3C8C10 = v17 * a7->field_10.y;
+  flt_3C8C14 = v17 * a7->field_10.z;
+  flt_3C8C18 = v17 * a7->field_1C.x;
+  flt_3C8C1C = v17 * a7->field_1C.y;
+  flt_3C8C20 = v17 * a7->field_1C.z;
+
+  /*
+  v11->pVertices[0].vWorldPosition.x = v11->field_C08 - flt_3C8C18 + flt_3C8C0C;
+  v11->pVertices[0].vWorldPosition.y = v11->field_C0A - flt_3C8C1C + flt_3C8C10;
+  v11->pVertices[0].vWorldPosition.z = v11->field_C0C - flt_3C8C20 + flt_3C8C14;
+  v11->pVertices[0].u = 0.0;
+  v11->pVertices[0].v = 0.0;
+
+  v11->pVertices[1].vWorldPosition.x = v11->field_C08 - flt_3C8C18 - flt_3C8C0C;
+  v11->pVertices[1].vWorldPosition.y = v11->field_C0A - flt_3C8C1C - flt_3C8C10;
+  v11->pVertices[1].vWorldPosition.z = v11->field_C0C - flt_3C8C20 - flt_3C8C14;
+  v11->pVertices[1].u = 0.0;
+  v11->pVertices[1].v = 1.0;
+
+  v11->pVertices[2].vWorldPosition.x = v11->field_C08 + flt_3C8C18 - flt_3C8C0C;
+  v11->pVertices[2].vWorldPosition.y = v11->field_C0A + flt_3C8C1C - flt_3C8C10;
+  v11->pVertices[2].vWorldPosition.z = v11->field_C0C + flt_3C8C20 - flt_3C8C14;
+  v11->pVertices[2].u = 1.0;
+  v11->pVertices[2].v = 1.0;
+
+  v11->pVertices[3].vWorldPosition.x = v11->field_C08 + flt_3C8C18 + flt_3C8C0C;
+  v11->pVertices[3].vWorldPosition.y = v11->field_C0A + flt_3C8C1C + flt_3C8C10;
+  v11->pVertices[3].vWorldPosition.z = v11->field_C0C + flt_3C8C20 + flt_3C8C14;
+  v11->pVertices[3].u = 1.0;
+  v11->pVertices[3].v = 0.0;
+  */
+
+  for (uint i = 0; i < 4; ++i)
+  {
+    v11->pVertices[i].vWorldPosition.x = v11->field_C08 - flt_3C8C18 + flt_3C8C0C;
+    v11->pVertices[i].vWorldPosition.y = v11->field_C0A - flt_3C8C1C + flt_3C8C10;
+    v11->pVertices[i].vWorldPosition.z = v11->field_C0C - flt_3C8C20 + flt_3C8C14;
+    v11->pVertices[i].u = 0.0;
+    v11->pVertices[i].v = 0.0;
+
+    v24 = a7->field_4.y * v11->pVertices[i].vWorldPosition.y
+        + a7->field_4.z * v11->pVertices[i].vWorldPosition.z
+        + a7->field_4.x * v11->pVertices[i].vWorldPosition.x
+        + a7->dist;
+
+    v11->pVertices[i].vWorldPosition.x -= v24 * a7->field_4.x;
+    v11->pVertices[i].vWorldPosition.y -= v24 * a7->field_4.y;
+    v11->pVertices[i].vWorldPosition.z -= v24 * a7->field_4.z;
+  }
+
+  v11->uColorMask = uColorMask;
+  v11->uNumVertices = 4;
+
+  if (~pGame->uFlags2 & 4)
+    v11->fBrightness = flt_3C8C2C_lightmaps_brightness;
+  else
+  {
+    Vec3_float_ a1; // [sp+2Ch] [bp-20h]@8
+    a1.x = (double)pos->x - v11->field_C08;
+    a1.y = (double)pos->y - v11->field_C0A;
+    a1.z = (double)pos->z - v11->field_C0C;
+    a1.Normalize();
+
+    auto dist_x = abs(pos->x - v11->field_C08), //v31
+         dist_y = abs(pos->y - v11->field_C0A), //v32  arg0a
+         dist_z = abs(pos->z - v11->field_C0C); //v33  _v64
+    v31 = dist_x;
+    v32 = dist_y;
+    v33 = dist_z;
+    if (v31 < dist_y)
+    {
+      v34 = v31;
+      v31 = dist_y;
+      v32 = v34;
+    }
+    if (v31 < dist_z)//SHIDWORD(v64) )
+    {
+      v35 = v31;
+      v31 = dist_z;//HIDWORD(v64);
+      v33 = v35;
+    }
+    if ( v32 < (signed int)v33 )
+    {
+      v36 = v33;
+      v33 = v32;
+      v32 = v36;
+    }
+    v37 = v33 >> 2;
+    //LODWORD(a5) = ((unsigned int)(11 * v32) >> 5) + v37 + v31;
+    v38 = (double)(signed)(((unsigned int)(11 * v32) >> 5) + v37 + v31);
+    if (v38 > radius)
+      return true;
+    //radius = (1 / radius) * v38;
+    if ( uLightType & 4 )
+    {
+      //v59 = (void *)v37;
+      //uLightType = flt_4D86CC;
+      //v58 = v37;
+      v39 = fabs(a1.x * a7->field_4.x + a1.z * a7->field_4.z + a1.y * a7->field_4.y);
+      v40 = v39 * 1.0 * flt_4D86CC;
+
+      v11->fBrightness = v40 - (1 / radius) * v38 * v40;
+    }
+    else if ( uLightType & 8 )
+    {
+        v40 = 1.0 * 1.0;
+        v11->fBrightness = v40 - (1 / radius) * v38;
+    }
+    else
+    {
+        MessageBoxW(nullptr, L"Invalid light type!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:277", 0);
+    }
+  }
+
+  if (!pGame->pStru9Instance->_4980B9(a9, uNumVertices,
+                                      a7->field_4.x, a7->field_4.y, a7->field_4.z,
+                                      v11->pVertices, &v11->uNumVertices))
+    return false;
+
+  //v44 = &v11->uNumVertices;
+  if (!v11->uNumVertices)
+    return true;
+
+  v45 = _45C6D6(uNumVertices, a9, v11);
+  if ( v45 != uNumVertices && v45 > 0 )
+    _45C4B9(uNumVertices, a9, v11);
+  //v59 = v11->uNumVertices;
+  //v46 = (RenderVertexSoft *)pLightmapVertices_;
+  pGame->pIndoorCameraD3D->ViewTransform(v11->pVertices, v11->uNumVertices);
+  //v59 = 0;
+  //v58 = v11->uNumVertices;
+  pGame->pIndoorCameraD3D->Project(v11->pVertices, v11->uNumVertices, 0);
+
+  unsigned int _a4 = 0;
+  if ( !(uClipFlag & 1) )
+    _a4 = 1;
+  else if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+  {
+    if ( uClipFlag & 2 )
+    {
+      //v59 = &a4;
+      //v58 = (unsigned int)field_3C8C34;
+      //v57 = *v44;
+      pGame->pIndoorCameraD3D->_436CDC_mess_with_lightmap__clipflag_2(v11->pVertices, v11->uNumVertices, field_3C8C34, &_a4);
+
+      //v59 = v44;
+      //v58 = (unsigned int)field_3C8C34;
+      //v57 = (int)v46;
+      //v56 = a4;
+      pGame->pIndoorCameraD3D->_437143(_a4, v11->pVertices, field_3C8C34, &v11->uNumVertices);
+    }
+    else if ( uClipFlag & 4 )
+    {
+      //v59 = &a4;
+      //v58 = (unsigned int)field_3C8C34;
+      //v57 = *v44;
+      pGame->pIndoorCameraD3D->_436F09_mess_with_lightmap__clipflag_4(v11->pVertices, v11->uNumVertices, field_3C8C34, &_a4);
+
+      //v59 = v44;
+      //v58 = (unsigned int)field_3C8C34;
+      //v57 = (int)v46;
+      //v56 = a4;
+      pGame->pIndoorCameraD3D->_437143(_a4, v11->pVertices, field_3C8C34, &v11->uNumVertices);
+    }
+    else
+      MessageBoxW(nullptr, L"Undefined clip flag specified", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:330", 0);
+  }
+  else
+    MessageBoxW(nullptr, L"Lightpoly builder native indoor clipping not implemented", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:335", 0);
+
+  if (_a4)
+  {
+    if (uLightType & 1)
+    {
+      //v48 = (char *)&std__vector_000004_size;
+      //v49 = std__vector_000004_size;
+      //v51 = __OFSUB__(std__vector_000004_size, 511);
+      //v50 = std__vector_000004_size - 511 < 0;
+      if (std__vector_000004_size < 512 - 1)
+        ++std__vector_000004_size;
+    }
+    else
+    {
+      //v48 = (char *)&std__vector_183808_size;
+      //v49 = std__vector_183808_size;
+      //v51 = __OFSUB__(std__vector_183808_size, 767);
+      //v50 = std__vector_183808_size - 767 < 0;
+      if (std__vector_183808_size < 768 - 1)
+        ++std__vector_183808_size;
+    }
+    //if ( v50 ^ v51 )
+    //  *(unsigned int *)v48 = v49 + 1;
+  }
+  return true;
+}
+
+//----- (0045C4B9) --------------------------------------------------------
+int LightmapBuilder::_45C4B9(int a2, RenderVertexSoft *a3, Lightmap *pLightmap)
+{
+  Lightmap *v4; // edi@1
+  int v5; // eax@1
+  signed int v6; // ecx@1
+  RenderVertexSoft *v7; // ebx@2
+  int v8; // edx@3
+  RenderVertexSoft *v9; // esi@3
+  int v10; // eax@6
+  char *v11; // edi@7
+  RenderVertexSoft *v12; // ecx@8
+  char v13; // bl@17
+  signed int v14; // edx@17
+  double v15; // st6@18
+  double v16; // st6@21
+  double v17; // st6@24
+  signed int v18; // edx@33
+  int v20; // [sp+4h] [bp-1Ch]@3
+  int v21; // [sp+8h] [bp-18h]@8
+  float v22; // [sp+Ch] [bp-14h]@23
+  float v23; // [sp+10h] [bp-10h]@20
+  int v24; // [sp+14h] [bp-Ch]@1
+  RenderVertexSoft *v25; // [sp+18h] [bp-8h]@2
+  char v26; // [sp+1Eh] [bp-2h]@17
+  char v27; // [sp+1Fh] [bp-1h]@17
+
+  v4 = pLightmap;
+  v5 = 0;
+  v6 = pLightmap->uNumVertices;
+  v24 = 0;
+  if ( v6 > 0 )
+  {
+    v7 = pLightmap->pVertices;
+    v25 = pLightmap->pVertices;
+    do
+    {
+      v20 = v5 + 1;
+      v8 = (v5 + 1) % v6;
+      v9 = &v4->pVertices[v8];
+      if ( v7->vWorldPosition.x != v9->vWorldPosition.x
+        || v7->vWorldPosition.y != v4->pVertices[v8].vWorldPosition.y
+        || v7->vWorldPosition.z != v4->pVertices[v8].vWorldPosition.z )
+      {
+        v10 = 0;
+        if ( a2 > 0 )
+        {
+          v11 = (char *)&a3->vWorldPosition.z;
+          do
+          {
+            v21 = v10 + 1;
+            v12 = &a3[(v10 + 1) % a2];
+            if ( (*((float *)v11 - 2) != v12->vWorldPosition.x
+               || *((float *)v11 - 1) != v12->vWorldPosition.y
+               || *(float *)v11 != v12->vWorldPosition.z)
+              && v7->vWorldPosition.x == *((float *)v11 - 2)
+              && v7->vWorldPosition.y == *((float *)v11 - 1)
+              && v7->vWorldPosition.z == *(float *)v11
+              && (v9->vWorldPosition.x != v12->vWorldPosition.x
+               || v9->vWorldPosition.y != v12->vWorldPosition.y
+               || v9->vWorldPosition.z != v12->vWorldPosition.z) )
+            {
+              v13 = 0;
+              v14 = 0;
+              v27 = 0;
+              v26 = 0;
+              if ( v9->vWorldPosition.x <= (double)v12->vWorldPosition.x )
+                v15 = v12->vWorldPosition.x - v9->vWorldPosition.x;
+              else
+                v15 = v9->vWorldPosition.x - v12->vWorldPosition.x;
+              v23 = v15;
+              if ( v9->vWorldPosition.y <= (double)v12->vWorldPosition.y )
+                v16 = v12->vWorldPosition.y - v9->vWorldPosition.y;
+              else
+                v16 = v9->vWorldPosition.y - v12->vWorldPosition.y;
+              v22 = v16;
+              if ( v9->vWorldPosition.z <= (double)v12->vWorldPosition.z )
+                v17 = v12->vWorldPosition.z - v9->vWorldPosition.z;
+              else
+                v17 = v9->vWorldPosition.z - v12->vWorldPosition.z;
+              if ( v23 < 1.0 )
+              {
+                v13 = 1;
+                v14 = 1;
+              }
+              if ( v22 < 1.0 )
+              {
+                v27 = 1;
+                ++v14;
+              }
+              if ( v17 < 1.0 )
+              {
+                v26 = 1;
+                ++v14;
+              }
+              if ( v14 > 1 )
+              {
+                v18 = 0;
+                if ( v13 && v9->vWorldPosition.x != v12->vWorldPosition.x )
+                {
+                  v18 = 1;
+                  v9->vWorldPosition.x = v12->vWorldPosition.x;
+                }
+                if ( v27 && v9->vWorldPosition.y != v12->vWorldPosition.y )
+                {
+                  ++v18;
+                  v9->vWorldPosition.y = v12->vWorldPosition.y;
+                }
+                if ( v26 && v9->vWorldPosition.z != v12->vWorldPosition.z )
+                {
+                  ++v18;
+                  v9->vWorldPosition.z = v12->vWorldPosition.z;
+                }
+                if ( v18 > 0 )
+                  ++v24;
+              }
+              v7 = v25;
+            }
+            ++v10;
+            v11 += 48;
+          }
+          while ( v21 < a2 );
+          v4 = pLightmap;
+        }
+      }
+      v5 = v20;
+      v6 = v4->uNumVertices;
+      ++v7;
+      v25 = v7;
+    }
+    while ( v20 < v6 );
+  }
+  return v24;
+}
+
+//----- (0045C6D6) --------------------------------------------------------
+int LightmapBuilder::_45C6D6(int a2, RenderVertexSoft *a3, Lightmap *pLightmap)
+{
+  Lightmap *v4; // edi@1
+  signed int v5; // ebx@1
+  signed int v6; // esi@1
+  RenderVertexSoft *v7; // ecx@2
+  char *v8; // edx@4
+  double v9; // st7@6
+  double v10; // st6@10
+  double v11; // st5@14
+  double v12; // st7@17
+  RenderVertexSoft *v13; // eax@21
+  int v15; // [sp+Ch] [bp-8h]@1
+  float v16; // [sp+10h] [bp-4h]@1
+  int pLightmapa; // [sp+24h] [bp+10h]@3
+
+  v4 = pLightmap;
+  v5 = 0;
+  v6 = -1;
+  v16 = 3.4028235e38;
+  v15 = 0;
+  if ( (signed int)pLightmap->uNumVertices > 0 )
+  {
+    v7 = pLightmap->pVertices;
+    do
+    {
+      pLightmapa = 0;
+      if ( a2 > 0 )
+      {
+        v8 = (char *)&a3->vWorldPosition.z;
+        do
+        {
+          if ( v7->vWorldPosition.x <= (double)*((float *)v8 - 2) )
+            v9 = *((float *)v8 - 2) - v7->vWorldPosition.x;
+          else
+            v9 = v7->vWorldPosition.x - *((float *)v8 - 2);
+          if ( v9 < 2.0 )
+          {
+            v10 = v7->vWorldPosition.y <= (double)*((float *)v8 - 1) ? *((float *)v8 - 1) - v7->vWorldPosition.y : v7->vWorldPosition.y - *((float *)v8 - 1);
+            if ( v10 < 2.0 )
+            {
+              v11 = v7->vWorldPosition.z <= (double)*(float *)v8 ? *(float *)v8 - v7->vWorldPosition.z : v7->vWorldPosition.z - *(float *)v8;
+              if ( v11 < 2.0 )
+              {
+                v12 = v9 + v11 + v10;
+                if ( v12 < v16 )
+                {
+                  v16 = v12;
+                  v6 = pLightmapa;
+                }
+              }
+            }
+          }
+          ++pLightmapa;
+          v8 += 48;
+        }
+        while ( pLightmapa < a2 );
+        if ( v6 != -1 )
+        {
+          v13 = &a3[v6];
+          ++v15;
+          v7->vWorldPosition.x = v13->vWorldPosition.x;
+          v7->vWorldPosition.y = v13->vWorldPosition.y;
+          v7->vWorldPosition.z = v13->vWorldPosition.z;
+        }
+      }
+      v6 = -1;
+      ++v5;
+      ++v7;
+      v16 = 3.4028235e38;
+    }
+    while ( v5 < (signed int)v4->uNumVertices );
+  }
+  return v15;
+}
+
+//----- (0045C7F6) --------------------------------------------------------
+bool LightmapBuilder::ApplyLights_IndoorFace(unsigned int uFaceID)
+{
+  auto pFace = &pIndoor->pFaces[uFaceID];
+  auto pSector = pIndoor->pSectors + pFace->uSectorID;
+
+  stru_F8AD28.uCurrentAmbientLightLevel = (stru_F8AD28.uDefaultAmbientLightLevel + pSector->uMinAmbientLightLevel) << 16;
+
+  uint uNumLightsApplied = 0;
+  for (uint i = 0; i < pMobileLightsStack->uNumLightsActive; ++i)
+  {
+    if (uNumLightsApplied >= 20)
+      break;
+
+    ApplyLight_BLV((StationaryLight *)(pMobileLightsStack->pLights + i), pFace, &uNumLightsApplied, true, 0);
+  }
+
+  for (uint i = 0; i < pSector->uNumLights; ++i)
+  {
+    if (uNumLightsApplied >= 20 )
+      break;
+
+    auto pLight = &pIndoor->pLights[pSector->pLights[i]];
+    if (~pLight->uAtributes & 0x08)
+      ApplyLight_BLV((StationaryLight *)pLight, pFace, &uFaceID, false, &byte_4E94D0);
+  }
+
+  for (uint i = 0; i < pStationaryLightsStack->uNumLightsActive; ++i)
+  {
+    if (uNumLightsApplied >= 20)
+      break;
+
+    ApplyLight_BLV(pStationaryLightsStack->pLights + i, pFace, &uNumLightsApplied, false, &byte_4E94D0);
+  }
+
+  stru_F8AD28.uNumLightsApplied = uNumLightsApplied;
+  return true;
+}
+
+//----- (0045C911) --------------------------------------------------------
+bool LightmapBuilder::ApplyLight_BLV(StationaryLight *pLight, BLVFace *a2, unsigned int *pSlot, bool bLightBackfaces, char *a5)
+{
+  double v13; // st7@8
+
+  if (!pLight->uRadius)
+    return false;
+
+  if (pLight->vPosition.x > a2->pBounding.x1 - pLight->uRadius &&
+      pLight->vPosition.x < a2->pBounding.x2 + pLight->uRadius &&
+      pLight->vPosition.y > a2->pBounding.y1 - pLight->uRadius &&
+      pLight->vPosition.y < a2->pBounding.y2 + pLight->uRadius &&
+      pLight->vPosition.z > a2->pBounding.z1 - pLight->uRadius &&
+      pLight->vPosition.z < a2->pBounding.z2 + pLight->uRadius)
+  {
+    v13 = (double)pLight->vPosition.z * a2->pFacePlane.vNormal.z +
+          (double)pLight->vPosition.y * a2->pFacePlane.vNormal.y +
+          (double)pLight->vPosition.x * a2->pFacePlane.vNormal.x +
+          a2->pFacePlane.dist;
+    if ((bLightBackfaces || v13 >= 0.0f) && fabsf(v13) <= pLight->uRadius)
+    {
+      auto slot = *pSlot;
+
+      stru_F8AD28._blv_lights_radii[slot] = pLight->uRadius;
+      stru_F8AD28._blv_lights_inv_radii[slot] = 65536 / pLight->uRadius;
+      stru_F8AD28._blv_lights_xs[slot] = pLight->vPosition.x;
+      stru_F8AD28._blv_lights_ys[slot] = pLight->vPosition.y;
+      stru_F8AD28._blv_lights_zs[slot] = pLight->vPosition.z;
+      stru_F8AD28._blv_lights_rs[slot] = (double)pLight->uLightColorR / 255.0f;
+      stru_F8AD28._blv_lights_gs[slot] = (double)pLight->uLightColorG / 255.0f;
+      stru_F8AD28._blv_lights_bs[slot] = (double)pLight->uLightColorB / 255.0f;
+      stru_F8AD28._blv_lights_light_dot_faces[slot] = abs((int)floorf(v13 + 0.5f));
+      stru_F8AD28._blv_lights_types[slot] = pLight->uLightType;
+
+      *pSlot += 1;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+//----- (0045CA88) --------------------------------------------------------
+int LightmapBuilder::_45CA88(stru320 *a2, RenderVertexSoft *a3, int a4, Vec3_float_ *pNormal)
+{
+  int result; // eax@1
+  stru320 *v6; // ecx@2
+  RenderVertexSoft *v7; // ebx@2
+  double v8; // st7@2
+  double v9; // st6@2
+  char *v10; // eax@3
+  double v11; // st7@5
+  __int64 v12; // ST2C_8@5
+  float v13; // edx@5
+  int v14; // eax@5
+  float v15; // ST10_4@5
+  Vec3_float_ v16; // ST00_12@5
+  double v17; // st7@5
+  int a5; // [sp+2Ch] [bp-1Ch]@1
+  float v19; // [sp+30h] [bp-18h]@1
+  float v20; // [sp+34h] [bp-14h]@1
+  LightmapBuilder *thisa; // [sp+38h] [bp-10h]@1
+  int v22; // [sp+3Ch] [bp-Ch]@1
+  int *j; // [sp+40h] [bp-8h]@3
+  int i; // [sp+44h] [bp-4h]@1
+  int a3a; // [sp+58h] [bp+10h]@2
+
+  *(float *)&a5 = 0.0;
+  v19 = 0.0;
+  thisa = this;
+  v20 = 0.0;
+  result = _45CBD4(a3, a4, dword_69B010, &v22);
+  for ( i = 0; i < v22; result = i )
+  {
+    v6 = a2;
+    a3a = 0;
+    v7 = &a3[dword_69B010[i]];
+    v8 = v7->vWorldPosition.z;
+    v9 = v7->vWorldPosition.y;
+    *(float *)&a5 = v7->vWorldPosition.x;
+    v19 = v9;
+    v20 = v8;
+    v7->flt_2C = 0.0;
+    if ( a2->uNumLightsApplied > 0 )
+    {
+      v10 = (char *)a2->_blv_lights_ys;
+      for ( j = a2->_blv_lights_ys; ; v10 = (char *)j )
+      {
+        v11 = (double)*((signed int *)v10 - 60);
+        LODWORD(v12) = *((unsigned int *)v10 - 20);
+        HIDWORD(v12) = *(unsigned int *)v10;
+        LODWORD(v13) = *((unsigned int *)v10 + 60);
+        v14 = a3a;
+        LOBYTE(v14) = v6->_blv_lights_types[a3a];
+        v15 = v11;
+        *(_QWORD *)&v16.x = v12;
+        v16.z = v13;
+        v17 = _45CC0C_light(v16/*COERCE_VEC3_FLOAT_(v16.x)*/, 1.0, v15, pNormal, *(float *)&a5/*COERCE_FLOAT(&a5)*/, v14)
+            + v7->flt_2C;
+        ++a3a;
+        ++j;
+        v7->flt_2C = v17;
+        if ( a3a >= a2->uNumLightsApplied )
+          break;
+        v6 = a2;
+      }
+    }
+    ++i;
+  }
+  return result;
+}
+
+//----- (0045CB89) --------------------------------------------------------
+int LightmapBuilder::_45CB89(RenderVertexSoft *a1, int a2)
+{
+  int v3; // edx@1
+  int result; // eax@2
+  char *v5; // ecx@2
+  double v6; // st7@4
+  __int16 v7; // fps@4
+  char v8; // c0@4
+  char v9; // c2@4
+  char v10; // c3@4
+  double v11; // st7@5
+  double v12; // st7@6
+  __int16 v13; // fps@6
+  char v14; // c0@6
+  char v15; // c2@6
+  char v16; // c3@6
+
+  v3 = a2;
+  if ( a2 > 0 )
+  {
+    HIWORD(result) = HIWORD(a1);
+    v5 = (char *)&a1->flt_2C;
+    do
+    {
+      if ( *(float *)v5 < 0.0
+        || (v6 = *(float *)v5, /*UNDEF(v7),*/ v8 = 1.0 < v6, v9 = 0, v10 = 1.0 == v6, LOWORD(result) = v7, v6 <= 1.0) )
+      {
+        v12 = *(float *)v5;
+        //UNDEF(v13);
+        v14 = 0.0 < v12;
+        v15 = 0;
+        v16 = 0.0 == v12;
+        LOWORD(result) = v13;
+        if ( v12 >= 0.0 )
+          v11 = *(float *)v5;
+        else
+          v11 = 0.0;
+      }
+      else
+      {
+        v11 = 1.0;
+      }
+      *(float *)v5 = v11;
+      v5 += 48;
+      --v3;
+    }
+    while ( v3 );
+  }
+  return result;
+}
+
+//----- (0045CBD4) --------------------------------------------------------
+int LightmapBuilder::_45CBD4(RenderVertexSoft *a2, int a3, int *a4, int *a5)
+{
+  int result; // eax@1
+  int v6; // edx@1
+  int v7; // ecx@2
+  int v8; // esi@2
+
+  result = (int)a5;
+  v6 = 0;
+  for ( *a5 = 0; v6 < a3; ++v6 )
+  {
+    v7 = *a5;
+    v8 = 0;
+    if ( *a5 <= 0 )
+    {
+LABEL_5:
+      a4[v7] = v6;
+      ++*a5;
+    }
+    else
+    {
+      while ( a4[v8] != v6 )
+      {
+        ++v8;
+        if ( v8 >= v7 )
+          goto LABEL_5;
+      }
+    }
+  }
+  return result;
+}
+
+//----- (0045CC0C) --------------------------------------------------------
+double LightmapBuilder::_45CC0C_light(Vec3_float_ a1, float a2, float a3, Vec3_float_ *pNormal, float a5, int uLightType)
+{
+  float v7; // esi@1
+  int v8; // eax@1
+  int v9; // ebx@1
+  unsigned int v10; // ecx@1
+  int v11; // edx@2
+  int v12; // edx@4
+  unsigned int v13; // edx@6
+  double v14; // st7@7
+  double result; // st7@8
+  double v16; // st7@9
+  int v17; // esi@9
+  const char *v18; // ecx@9
+  double v19; // st7@10
+  double v20; // st7@10
+  std::string v21; // [sp-10h] [bp-40h]@13
+  const char *v22[6]; // [sp+0h] [bp-30h]@10
+  double v23; // [sp+18h] [bp-18h]@1
+  double v24; // [sp+20h] [bp-10h]@1
+  int v25; // [sp+28h] [bp-8h]@1
+  int v26; // [sp+2Ch] [bp-4h]@1
+
+  v7 = a5;
+  LODWORD(a5) = *(unsigned int *)(LODWORD(a5) + 8);
+  //v24 = a5 + 6.7553994e15;
+  v26 = floorf(a5 + 0.5f);//LODWORD(v24);
+  LODWORD(a5) = *(unsigned int *)(LODWORD(v7) + 4);
+  //v24 = a5 + 6.7553994e15;
+  auto _v24 = floorf(a5 + 0.5f);
+  LODWORD(a5) = *(unsigned int *)LODWORD(v7);
+  //v23 = a5 + 6.7553994e15;
+  auto _v23 = floorf(a5 + 0.5f);
+  //*(_QWORD *)((char *)&v24 + 4) = __PAIR__(LODWORD(v24), LODWORD(v23));
+  v26 = abs((signed)LODWORD(a1.z) - v26);
+  //v25 = abs((signed)LODWORD(a1.y) - (signed)LODWORD(v24));
+  //v8 = abs((int)a1.x - (signed)LODWORD(v23));
+  v25 = abs((signed)LODWORD(a1.y) - (signed)_v24);
+  v8 = abs((int)a1.x - (signed)_v23);
+  LODWORD(a5) = v8;
+  v9 = v25;
+  v10 = v26;
+  if ( v8 < v25 )
+  {
+    v11 = v8;
+    v8 = v25;
+    v9 = v11;
+  }
+  if ( v8 < v26 )
+  {
+    v12 = v8;
+    v8 = v26;
+    v10 = v12;
+  }
+  if ( v9 < (signed int)v10 )
+  {
+    v13 = v10;
+    v10 = v9;
+    v9 = v13;
+  }
+  v14 = (double)(signed int)(((unsigned int)(11 * v9) >> 5) + (v10 >> 2) + v8);
+  if ( v14 <= a3 )
+  {
+    a5 = v14 / a3;
+    v16 = (double)(signed int)a1.x;
+    *(float *)&v23 = (double)SLODWORD(a1.y);
+    LODWORD(a1.x) = *(unsigned int *)LODWORD(v7);
+    v17 = LODWORD(v7) + 4;
+    *((float *)&v23 + 1) = (double)SLODWORD(a1.z);
+    LODWORD(a1.y) = *(unsigned int *)v17;
+    LODWORD(a1.z) = *(unsigned int *)(v17 + 4);
+    a3 = *((float *)&v23 + 1) - a1.z;
+    a1.z = a3;
+    a1.x = v16 - a1.x;
+    a1.y = (float)v23 - a1.y;
+    a1.Normalize();
+    if ( uLightType & 4 )
+    {
+      v22[1] = v18;
+      uLightType = dword_4D86D8;
+      v22[0] = v18;
+      v19 = fabs(a1.z * pNormal->z + a1.y * pNormal->y + a1.x * pNormal->x);
+      v20 = v19 * *(float *)&uLightType * a2;
+    }
+    else
+    {
+      if ( uLightType & 8 )
+      {
+        v20 = 1.3 * a2;
+      }
+      else
+      {
+        MessageBoxW(nullptr, L"Invalid light type detected!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:783", 0);
+        v20 = *(float *)&uLightType;
+      }
+    }
+    result = v20 - a5 * v20;
+  }
+  else
+  {
+    result = 0.0;
+  }
+  return result;
+}
+// 4D86D8: using guessed type int dword_4D86D8;
+
+//----- (0045CDB7) --------------------------------------------------------
+bool LightmapBuilder::ApplyLights_OutdoorFace(ODMFace *pFace)
+{
+  int v2; // esi@1
+  int v3; // eax@1
+  MobileLight *pMobileLight; // ebx@2
+  int v5; // esi@5
+  StationaryLight *pStationaryLight; // ebx@6
+  bool result; // eax@9
+  LightmapBuilder *thisa; // [sp+Ch] [bp-8h]@1
+  int pSlot; // [sp+10h] [bp-4h]@1
+
+  v2 = 0;
+  thisa = this;
+  v3 = stru_F8AD28.uDefaultAmbientLightLevel + pFace->uShadeType;
+  pSlot = 0;
+  stru_F8AD28.uCurrentAmbientLightLevel = v3 << 16;
+  if ( pMobileLightsStack->uNumLightsActive > 0 )
+  {
+    pMobileLight = pMobileLightsStack->pLights;
+    do
+    {
+      if ( pSlot >= 20 )
+        break;
+      ApplyLight_ODM((StationaryLight *)pMobileLight, pFace, (unsigned int *)&pSlot, 1);
+      ++v2;
+      ++pMobileLight;
+    }
+    while ( v2 < pMobileLightsStack->uNumLightsActive );
+  }
+  v5 = 0;
+  if ( pStationaryLightsStack->uNumLightsActive > 0 )
+  {
+    pStationaryLight = pStationaryLightsStack->pLights;
+    do
+    {
+      if ( pSlot >= 20 )
+        break;
+      ApplyLight_ODM(pStationaryLight, pFace, (unsigned int *)&pSlot, 0);
+      ++v5;
+      ++pStationaryLight;
+    }
+    while ( v5 < pStationaryLightsStack->uNumLightsActive );
+  }
+  result = pSlot;
+  stru_F8AD28.uNumLightsApplied = pSlot;
+  return true;
+}
+
+//----- (0045CE50) --------------------------------------------------------
+bool LightmapBuilder::ApplyLight_ODM(StationaryLight *pLight, ODMFace *pFace, unsigned int *pSlot, char a4)
+{
+  int result; // eax@0
+  signed int v6; // ebx@1
+  int v7; // ecx@2
+  int v8; // esi@4
+  int v9; // edx@6
+  int v10; // ecx@8
+  int v11; // eax@11
+  unsigned int v12; // ebx@11
+  RenderD3D *v13; // ecx@11
+  char v14; // dl@11
+
+  __debugbreak();
+
+  v6 = pLight->uRadius;
+  if ( v6 > 0
+    && (result = (int)pFace, v7 = pLight->vPosition.x, v7 > pFace->pBoundingBox.x1 - v6)
+    && v7 < v6 + pFace->pBoundingBox.x2
+    && (v8 = pLight->vPosition.y, v8 > pFace->pBoundingBox.y1 - v6)
+    && v8 < v6 + pFace->pBoundingBox.y2
+    && (v9 = pLight->vPosition.z, v9 > pFace->pBoundingBox.z1 - v6)
+    && v9 < v6 + pFace->pBoundingBox.z2
+    && ((v10 = (pFace->pFacePlane.dist
+              + pLight->vPosition.x * pFace->pFacePlane.vNormal.x
+              + v8 * pFace->pFacePlane.vNormal.y
+              + v9 * pFace->pFacePlane.vNormal.z) >> 16,
+         a4)
+     || v10 >= 0)
+    && v10 <= v6 )
+  {
+    stru_F8AD28._blv_lights_radii[*pSlot] = v6;
+    stru_F8AD28._blv_lights_inv_radii[*pSlot] = 65536 / v6;
+    stru_F8AD28._blv_lights_xs[*pSlot] = pLight->vPosition.x;
+    stru_F8AD28._blv_lights_ys[*pSlot] = pLight->vPosition.y;
+    stru_F8AD28._blv_lights_zs[*pSlot] = pLight->vPosition.z;
+    stru_F8AD28._blv_lights_rs[*pSlot] = (double)pLight->uLightColorR * 0.0039215689;
+    stru_F8AD28._blv_lights_gs[*pSlot] = (double)pLight->uLightColorG * 0.0039215689;
+    stru_F8AD28._blv_lights_bs[*pSlot] = (double)pLight->uLightColorB * 0.0039215689;
+    v11 = abs(v10);
+    v12 = pRenderer->bUsingSpecular;
+    stru_F8AD28._blv_lights_light_dot_faces[*pSlot] = v11;
+    stru_F8AD28._blv_lights_types[*pSlot] = pLight->uLightType;
+    v13 = pRenderer->pRenderD3D;
+    v14 = stru_F8AD28._blv_lights_types[*pSlot];
+    if ( pRenderer->pRenderD3D && v12 && v14 & 4 )
+      v14 = _4E94D2_light_type;
+    stru_F8AD28._blv_lights_types[*pSlot] = v14;
+    result = 4 * *pSlot;
+    if ( v13 && v12 )
+    {
+      if ( stru_F8AD28._blv_lights_types[*pSlot] & 4 )
+      {
+        *(float *)((char *)stru_F8AD28._blv_lights_rs + result) = *(float *)((char *)stru_F8AD28._blv_lights_rs + result)
+                                                                * 0.33000001;
+        *(float *)((char *)stru_F8AD28._blv_lights_gs + result) = *(float *)((char *)stru_F8AD28._blv_lights_gs + result)
+                                                                * 0.33000001;
+        *(float *)((char *)stru_F8AD28._blv_lights_bs + result) = *(float *)((char *)stru_F8AD28._blv_lights_bs + result)
+                                                                * 0.33000001;
+      }
+    }
+    ++*pSlot;
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+    LOBYTE(result) = 0;
+  }
+  return result;
+}
+// 4E94D2: using guessed type char _4E94D2_light_type;
+
+//----- (0045D036) --------------------------------------------------------
+bool LightmapBuilder::StackLights_TerrainFace(Vec3_float_ *pNormal, float *a3, RenderVertexSoft *a1, unsigned int uStripType, bool bLightBackfaces)
+{
+  int v6; // esi@1
+  //LightmapBuilder *v7; // edi@1
+  MobileLight *v8; // ebx@2
+  int v9; // esi@5
+  StationaryLight *v10; // ebx@6
+  //bool result; // eax@9
+  unsigned int a7; // [sp+Ch] [bp-4h]@1
+
+  v6 = 0;
+  //v7 = this;
+  a7 = 0;
+  stru_F8AD28.uCurrentAmbientLightLevel = pOutdoor->field_CBC_terrain_triangles_shade_type;
+  if ( pMobileLightsStack->uNumLightsActive > 0 )
+  {
+    v8 = pMobileLightsStack->pLights;
+    do
+    {
+      if ( (signed int)a7 >= 20 )
+        break;
+      StackLight_TerrainFace((StationaryLight *)v8, pNormal, a3, a1, uStripType, bLightBackfaces, &a7);
+      ++v6;
+      ++v8;
+    }
+    while ( v6 < pMobileLightsStack->uNumLightsActive );
+  }
+  v9 = 0;
+  if ( pStationaryLightsStack->uNumLightsActive > 0 )
+  {
+    v10 = pStationaryLightsStack->pLights;
+    do
+    {
+      if ( (signed int)a7 >= 20 )
+        break;
+      StackLight_TerrainFace(v10, pNormal, a3, a1, uStripType, bLightBackfaces, &a7);
+      ++v9;
+      ++v10;
+    }
+    while ( v9 < pStationaryLightsStack->uNumLightsActive );
+  }
+
+  stru_F8AD28.uNumLightsApplied = a7;
+  return true;
+}
+// 519AB4: using guessed type int uNumStationaryLightsApplied;
+
+//----- (0045D0D5) --------------------------------------------------------
+bool LightmapBuilder::StackLight_TerrainFace(StationaryLight *pLight, Vec3_float_ *pNormal, float *a3, RenderVertexSoft *a1, unsigned int uStripType, int X, unsigned int *pSlot)
+{
+  StationaryLight *v8; // edi@1
+  bool result; // eax@1
+  unsigned int v10; // esi@2
+  RenderVertexSoft *v11; // ebx@2
+  float v12; // eax@3
+  float v13; // eax@4
+  double v14; // st7@11
+  double maxz; // st7@11
+  double v16; // st7@11
+  double v17; // st6@11
+  __int16 v18; // fps@11
+  char v19; // c0@11
+  char v20; // c2@11
+  char v21; // c3@11
+  double v22; // st6@12
+  __int16 v23; // fps@12
+  char v24; // c0@12
+  char v25; // c2@12
+  char v26; // c3@12
+  double v27; // st7@13
+  double v28; // st6@13
+  __int16 v29; // fps@13
+  char v30; // c0@13
+  char v31; // c2@13
+  char v32; // c3@13
+  double v33; // st6@14
+  __int16 v34; // fps@14
+  char v35; // c0@14
+  char v36; // c2@14
+  char v37; // c3@14
+  double v38; // st7@15
+  double v39; // st6@15
+  __int16 v40; // fps@15
+  char v41; // c0@15
+  char v42; // c2@15
+  char v43; // c3@15
+  double v44; // st6@16
+  __int16 v45; // fps@16
+  char v46; // c0@16
+  char v47; // c2@16
+  char v48; // c3@16
+  Vec3_float_ *v49; // esi@17
+  double v50; // st7@17
+  double v51; // st6@17
+  signed int v52; // ecx@17
+  unsigned int *v53; // esi@18
+  int v54; // eax@18
+  unsigned int v55; // ebx@18
+  RenderD3D *v56; // ecx@18
+  char v57; // dl@18
+  std::string v58; // [sp-18h] [bp-38h]@10
+  const char *v59; // [sp-8h] [bp-28h]@10
+  signed int v60; // [sp-4h] [bp-24h]@10
+  double v61; // [sp+Ch] [bp-14h]@11
+  float minz; // [sp+14h] [bp-Ch]@11
+  int v63; // [sp+18h] [bp-8h]@1
+  float v64; // [sp+1Ch] [bp-4h]@5
+
+  v8 = pLight;
+  result = pLight->uRadius;
+  v63 = pLight->uRadius;
+  if ( result <= 0 )
+    goto LABEL_27;
+  v10 = uStripType;
+  v11 = a1;
+  if ( uStripType == 4 )
+  {
+    pLight = (StationaryLight *)LODWORD(a1->vWorldPosition.x);
+    v12 = a1[3].vWorldPosition.x;
+  }
+  else
+  {
+    if ( uStripType != 3 )
+    {
+      MessageBoxW(nullptr, L"Uknown strip type detected!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:981", 0);
+      goto LABEL_11;
+    }
+    if ( (unsigned char)X )
+    {
+      pLight = (StationaryLight *)LODWORD(a1->vWorldPosition.x);
+      uStripType = LODWORD(a1[2].vWorldPosition.x);
+      a1 = (RenderVertexSoft *)LODWORD(a1[1].vWorldPosition.y);
+      v13 = v11[2].vWorldPosition.y;
+      goto LABEL_5;
+    }
+    pLight = (StationaryLight *)LODWORD(a1[1].vWorldPosition.x);
+    v12 = a1[2].vWorldPosition.x;
+  }
+  uStripType = LODWORD(v12);
+  a1 = (RenderVertexSoft *)LODWORD(a1[1].vWorldPosition.y);
+  v13 = v11->vWorldPosition.y;
+LABEL_5:
+  v64 = v13;
+LABEL_11:
+  v60 = v10;
+  v59 = (const char *)v11;
+  v14 = pGame->pIndoorCameraD3D->GetPolygonMinZ(v11, v10);
+  v60 = v10;
+  minz = v14;
+  maxz = pGame->pIndoorCameraD3D->GetPolygonMaxZ(v11, v10);
+  result = v8->vPosition.x;
+  *((float *)&v61 + 1) = maxz;
+  v16 = (double)result;
+  *(float *)&X = (double)v63;
+  v17 = *(float *)&pLight - *(float *)&X;
+  //UNDEF(v18);
+  v19 = v16 < v17;
+  v20 = 0;
+  v21 = v16 == v17;
+  BYTE1(result) = HIBYTE(v18);
+  if ( v16 <= v17
+    || (v22 = *(float *)&X + *(float *)&uStripType,
+        //UNDEF(v23),
+        v24 = v16 < v22,
+        v25 = 0,
+        v26 = v16 == v22,
+        BYTE1(result) = HIBYTE(v23),
+        v16 >= v22)
+    || (result = v8->vPosition.y,
+        pLight = (StationaryLight *)v8->vPosition.y,
+        v27 = (double)(signed int)pLight,
+        v28 = *(float *)&a1 - *(float *)&X,
+        //UNDEF(v29),
+        v30 = v27 < v28,
+        v31 = 0,
+        v32 = v27 == v28,
+        BYTE1(result) = HIBYTE(v29),
+        v27 <= v28)
+    || (v33 = *(float *)&X + v64,
+        //UNDEF(v34),
+        v35 = v27 < v33,
+        v36 = 0,
+        v37 = v27 == v33,
+        BYTE1(result) = HIBYTE(v34),
+        v27 >= v33)
+    || (result = v8->vPosition.z,
+        pLight = (StationaryLight *)v8->vPosition.z,
+        v38 = (double)(signed int)pLight,
+        v39 = minz - *(float *)&X,
+        //UNDEF(v40),
+        v41 = v38 < v39,
+        v42 = 0,
+        v43 = v38 == v39,
+        BYTE1(result) = HIBYTE(v40),
+        v38 <= v39)
+    || (v44 = *(float *)&X + *((float *)&v61 + 1),
+        //UNDEF(v45),
+        v46 = v38 < v44,
+        v47 = 0,
+        v48 = v38 == v44,
+        BYTE1(result) = HIBYTE(v45),
+        v38 >= v44)
+    || (v49 = pNormal,
+        Vec3_float_::NegDot(&v11->vWorldPosition, pNormal, a3),
+        X = v8->vPosition.y,
+        v50 = (double)X * v49->y,
+        X = v8->vPosition.z,
+        v51 = (double)X * v49->z,
+        X = v8->vPosition.x,
+        *(float *)&a3 = v50 + v51 + (double)X * v49->x + *a3,
+        v61 = *(float *)&a3 + 6.7553994e15,
+        result = LODWORD(v61),
+        X = LODWORD(v61),
+        v52 = v63,
+        SLODWORD(v61) > v63) )
+  {
+LABEL_27:
+    LOBYTE(result) = 0;
+    return result;
+  }
+  v53 = pSlot;
+  v60 = X;
+  stru_F8AD28._blv_lights_radii[*pSlot] = v63;
+  stru_F8AD28._blv_lights_inv_radii[*v53] = 65536 / v52;
+  stru_F8AD28._blv_lights_xs[*v53] = v8->vPosition.x;
+  stru_F8AD28._blv_lights_ys[*v53] = v8->vPosition.y;
+  stru_F8AD28._blv_lights_zs[*v53] = v8->vPosition.z;
+  a3 = (float *)v8->uLightColorR;
+  stru_F8AD28._blv_lights_rs[*v53] = (double)(signed int)a3 * 0.0039215689;
+  a3 = (float *)v8->uLightColorG;
+  stru_F8AD28._blv_lights_gs[*v53] = (double)(signed int)a3 * 0.0039215689;
+  a3 = (float *)v8->uLightColorB;
+  stru_F8AD28._blv_lights_bs[*v53] = (double)(signed int)a3 * 0.0039215689;
+  v54 = abs(v60);
+  v55 = pRenderer->bUsingSpecular;
+  stru_F8AD28._blv_lights_light_dot_faces[*v53] = v54;
+  stru_F8AD28._blv_lights_types[*v53] = v8->uLightType;
+  v56 = pRenderer->pRenderD3D;
+  v57 = stru_F8AD28._blv_lights_types[*v53];
+  if ( pRenderer->pRenderD3D && v55 && v57 & 4 )
+    v57 = _4E94D2_light_type;
+  stru_F8AD28._blv_lights_types[*v53] = v57;
+  result = 4 * *v53;
+  if ( v56 && v55 )
+  {
+    if ( stru_F8AD28._blv_lights_types[*v53] & 4 )
+    {
+      *(float *)((char *)stru_F8AD28._blv_lights_rs + result) = *(float *)((char *)stru_F8AD28._blv_lights_rs + result)
+                                                              * 0.33000001;
+      *(float *)((char *)stru_F8AD28._blv_lights_gs + result) = *(float *)((char *)stru_F8AD28._blv_lights_gs + result)
+                                                              * 0.33000001;
+      *(float *)((char *)stru_F8AD28._blv_lights_bs + result) = *(float *)((char *)stru_F8AD28._blv_lights_bs + result)
+                                                              * 0.33000001;
+    }
+  }
+  ++*v53;
+  LOBYTE(result) = 1;
+  return result;
+}
+// 4E94D2: using guessed type char _4E94D2_light_type;
+
+//----- (0045D3C7) --------------------------------------------------------
+bool LightmapBuilder::_45D3C7(stru148 *a1)
+{
+  LightmapBuilder *v2; // ebx@1
+  stru148 *result; // eax@1
+  float v4; // ecx@2
+  Span *i; // edi@5
+
+  v2 = this;
+  result = (stru148 *)a1->prolly_head;
+  if ( result && (v4 = result->field_4, *(int *)&v4) != 0 && *(unsigned int *)(LODWORD(v4) + 60) )
+  {
+    for ( i = a1->prolly_head; ; i = i->pNext )
+    {
+      result = i->pParent;
+      if ( result->field_108 )
+        result = (stru148 *)_45D426(
+                              i,
+                              a1->pEdgeList1,
+                              a1->uEdgeList1Size,
+                              (Edge *)a1->pEdgeList2,
+                              a1->uEdgeList2Size);
+      if ( a1->prolly_tail == i )
+        break;
+    }
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+    LOBYTE(result) = 0;
+  }
+  return (bool)result;
+}
+
+//----- (0045D426) --------------------------------------------------------
+int LightmapBuilder::_45D426(Span *a1, Edge **a2, unsigned int a3, Edge *a4, int a5)
+{
+  int v6; // edi@1
+  signed int v7; // ebx@3
+  signed int v8; // ecx@3
+  Span *v9; // esi@3
+  double v10; // st7@4
+  Edge *v11; // edx@5
+  double v12; // st7@11
+  int v13; // edx@12
+  int v14; // ebx@17
+  Edge *v15; // edi@17
+  float v16; // ST04_4@17
+  float v17; // ST04_4@17
+  double v18; // st7@17
+  int result; // eax@19
+  //double v20; // ST14_8@20
+  //double v21; // ST14_8@20
+  double v22; // st7@20
+  int v23; // ecx@20
+  double v24; // st6@20
+  double v25; // st7@23
+  double v26; // st7@28
+  __int16 v27; // fps@28
+  char v28; // c0@28
+  char v29; // c2@28
+  char v30; // c3@28
+  double v31; // st7@29
+  double v32; // st7@30
+  __int16 v33; // fps@30
+  char v34; // c0@30
+  char v35; // c2@30
+  char v36; // c3@30
+  LightmapBuilder *this_4; // [sp+14h] [bp-8h]@1
+  signed int v38; // [sp+18h] [bp-4h]@3
+  float a1a; // [sp+24h] [bp+8h]@20
+  float a2a; // [sp+28h] [bp+Ch]@17
+  float a3a; // [sp+2Ch] [bp+10h]@17
+  float a5a; // [sp+34h] [bp+18h]@20
+  float a5b; // [sp+34h] [bp+18h]@20
+
+  v6 = 0;
+  this_4 = this;
+  if ( a5 && a3 )
+  {
+    v7 = -1;
+    v8 = 0;
+    v9 = a1;
+    v38 = -1;
+    if ( (signed int)a3 > 0 )
+    {
+      v10 = (double)a1->field_A;
+      while ( 1 )
+      {
+        v11 = a2[v8];
+        if ( v10 >= v11->field_2C )
+        {
+          if ( v10 <= v11->field_30 )
+            break;
+        }
+        ++v8;
+        if ( v8 >= (signed int)a3 )
+          goto LABEL_10;
+      }
+      v38 = v8;
+    }
+LABEL_10:
+    if ( a5 > 0 )
+    {
+      v12 = (double)a1->field_A;
+      while ( 1 )
+      {
+        v13 = *((unsigned int *)&a4->field_0 + v6);
+        if ( v12 >= *(float *)(v13 + 44) )
+        {
+          if ( v12 <= *(float *)(v13 + 48) )
+            break;
+        }
+        ++v6;
+        if ( v6 >= a5 )
+          goto LABEL_17;
+      }
+      v7 = v6;
+    }
+LABEL_17:
+    v14 = *((unsigned int *)&a4->field_0 + v7);
+    v15 = a2[v38];
+    v16 = (double)a1->field_A;
+    a3a = _45D643(a2[v38], v16);
+    v17 = (double)a1->field_A;
+    v18 = _45D643((Edge *)v14, v17);
+    a2a = v18;
+    if ( byte_4D864C && BYTE1(pGame->uFlags) & 0x80 )
+    {
+      HIWORD(result) = HIWORD(a3a);
+      a1->field_14 = v18;
+      a1->field_10 = a3a;
+    }
+    else
+    {
+      a5a = ((double)a1->field_A - v15->field_2C) * v15->field_4 + v15->field_24 - 0.5;
+      //v20 = a5a + 6.7553994e15;
+      //a5b = (double)SLODWORD(v20);
+      a5b = (double)floorf(a5a + 0.5f);
+      a1a = ((double)a1->field_A - *(float *)(v14 + 44)) * *(float *)(v14 + 4) + *(float *)(v14 + 36) + 0.5;
+      //v21 = a1a + 6.7553994e15;
+      //v22 = (double)SLODWORD(v21);
+      v22 = (double)floorf(a1a + 0.5f);
+      result = v9->field_8;
+      v23 = v9->field_C;
+      v24 = -((a3a - a2a) / (v22 - a5b));
+      v9->field_10 = ((double)result - a5b) * v24 + a3a;
+      v9->field_14 = a2a - (v22 - (double)(result + v23)) * v24;
+    }
+    if ( v9->field_10 < 0.0 || v9->field_10 <= 1.0 )
+    {
+      if ( v9->field_10 >= 0.0 )
+        v25 = v9->field_10;
+      else
+        v25 = 0.0;
+    }
+    else
+    {
+      v25 = 1.0;
+    }
+    v9->field_10 = v25;
+    if ( v9->field_14 < 0.0
+      || (v26 = v9->field_14,
+          //UNDEF(v27),
+          v28 = 1.0 < v26,
+          v29 = 0,
+          v30 = 1.0 == v26,
+          BYTE1(result) = HIBYTE(v27),
+          v26 <= 1.0) )
+    {
+      v32 = v9->field_14;
+      //UNDEF(v33);
+      v34 = 0.0 < v32;
+      v35 = 0;
+      v36 = 0.0 == v32;
+      BYTE1(result) = HIBYTE(v33);
+      if ( v32 >= 0.0 )
+        v31 = v9->field_14;
+      else
+        v31 = 0.0;
+    }
+    else
+    {
+      v31 = 1.0;
+    }
+    v9->field_14 = v31;
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+    LOBYTE(result) = 0;
+  }
+  return result;
+}
+// 4D864C: using guessed type char byte_4D864C;
+
+//----- (0045D643) --------------------------------------------------------
+double LightmapBuilder::_45D643(Edge *a1, float a2)
+{
+  double result; // st7@1
+
+  result = (a1->field_1C - a1->field_20) * -1.0 / (a1->field_30 - a1->field_2C) * (a2 - a1->field_2C) + a1->field_1C;
+  if ( result < 0.0 || result <= 1.0 )
+  {
+    if ( result < 0.0 )
+      result = 0.0;
+  }
+  else
+  {
+    result = 1.0;
+  }
+  return result;
+}
+
+//----- (0045D698) --------------------------------------------------------
+bool LightmapBuilder::DrawDebugOutlines(char bit_one_for_list1__bit_two_for_list2)
+{
+  bool result; // eax@1
+  LightmapBuilder *v3; // esi@1
+  RenderVertexSoft *v4; // edi@3
+  RenderVertexSoft *v5; // edi@7
+  IndoorCameraD3D *thisa; // [sp+10h] [bp-8h]@1
+  bool v7; // [sp+14h] [bp-4h]@2
+  bool a2a; // [sp+20h] [bp+8h]@6
+
+  result = (bool)pGame->pIndoorCameraD3D;
+  v3 = this;
+  thisa = pGame->pIndoorCameraD3D;
+  if ( bit_one_for_list1__bit_two_for_list2 & 1 )
+  {
+    v7 = 0;
+    if ( (signed int)this->std__vector_000004_size > 0 )
+    {
+      v4 = this->std__vector_000004[0].pVertices;
+      do
+      {
+        pGame->pIndoorCameraD3D->debug_outline_sw(v4, *((unsigned int *)v4 - 1), 0xFF00u, 0.0);
+        ++v7;
+        v4 = (RenderVertexSoft *)((char *)v4 + 3100);
+        result = v7;
+      }
+      while ( v7 < (signed int)v3->std__vector_000004_size );
+    }
+  }
+  if ( bit_one_for_list1__bit_two_for_list2 & 2 )
+  {
+    a2a = 0;
+    if ( (signed int)v3->std__vector_183808_size > 0 )
+    {
+      v5 = v3->std__vector_183808[0].pVertices;
+      do
+      {
+        pGame->pIndoorCameraD3D->debug_outline_sw(v5, *((unsigned int *)v5 - 1), 0xC04000u, 0.00019999999);
+        ++a2a;
+        v5 = (RenderVertexSoft *)((char *)v5 + 3100);
+        result = a2a;
+      }
+      while ( a2a < (signed int)v3->std__vector_183808_size );
+    }
+  }
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (0045D73F) --------------------------------------------------------
+void LightmapBuilder::DrawLightmaps(int a2)
+{
+  if ( a2 == 2 )
+    DoDrawLightmaps();
+}
+
+//----- (0045D74F) --------------------------------------------------------
+char LightmapBuilder::_45D74F_MessWithLight(int a2, int *a3)
+{
+  char v3; // zf@1
+  IDirect3DDevice3 *v4; // eax@2
+  HRESULT v5; // eax@2
+  //char *v6; // eax@2
+  struct IDirect3DTexture2 *v7; // edi@4
+  HRESULT v8; // eax@8
+  HRESULT v9; // eax@8
+  HRESULT v10; // eax@8
+  HRESULT v11; // eax@8
+  HRESULT v12; // eax@8
+  int *v13; // eax@8
+  float v14; // ecx@15
+  IDirect3DDevice3 *v15; // eax@21
+  HRESULT v16; // eax@21
+  IDirect3DDevice3 *v17; // eax@21
+  HRESULT v18; // eax@21
+  IDirect3DDevice3 *v19; // eax@21
+  HRESULT v20; // eax@21
+  IDirect3DDevice3 *v21; // eax@21
+  HRESULT v22; // eax@21
+  //IDirect3DDevice3 *v23; // eax@23
+  std::string v25; // [sp+44h] [bp-44h]@12
+  signed int v26; // [sp+48h] [bp-40h]@21
+  signed int v27; // [sp+4Ch] [bp-3Ch]@21
+  Lightmap *v28; // [sp+50h] [bp-38h]@2
+  int v29; // [sp+54h] [bp-34h]@2
+  //float v30; // [sp+58h] [bp-30h]@2
+  int arg4; // [sp+68h] [bp-20h]@8
+  float v32; // [sp+6Ch] [bp-1Ch]@8
+  float v33; // [sp+70h] [bp-18h]@8
+  int v34; // [sp+74h] [bp-14h]@19
+  int v35; // [sp+78h] [bp-10h]@2
+  int *v36; // [sp+7Ch] [bp-Ch]@10
+  int a1; // [sp+80h] [bp-8h]@12
+  float v38; // [sp+84h] [bp-4h]@1
+
+  v3 = this->std__vector_000004_size == 0;
+  LODWORD(v38) = (int)this;
+  if ( !v3 )
+  {
+    //v30 = 0.0;
+    //v4 = pRenderer->pRenderD3D->pDevice;
+    ErrD3D(v4->SetTextureStageState(0, D3DTSS_ADDRESS, 3u));
+    //v6 = (char *)stru_69BD44.c_str();
+    //if ( !stru_69BD44.c_str() )
+    //  v6 = (char *)&dword_4D86F0;
+    v7 = pGame->pIndoorCameraD3D->LoadTextureAndGetHardwarePtr("effpar03");
+    if ( pRenderer->bUsingSpecular )
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0);
+    if ( !byte_4D864C || !(pGame->uFlags & 1) )
+    {
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 0));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, v7));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 2u));
+      v13 = a3;
+      v33 = 1.0;
+      v32 = 1.0;
+      *(float *)&arg4 = 1.0;
+      if ( a3 )
+      {
+        if ( *a3 != -1 )
+        {
+          v36 = a3;
+          do
+          {
+            v28 = (Lightmap *)(3100 * *v13 + LODWORD(v38) + 4);
+            if ( !DrawLightmap(v28, (Vec3_float_ *)&arg4, 0.0) )
+            {
+              MessageBoxW(nullptr, L"Invalid lightmap detected!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:1230", 0);
+              a1 = 5080812;
+            }
+            v13 = v36 + 1;
+            v36 = v13;
+          }
+          while ( *v13 != -1 );
+        }
+      }
+      else
+      {
+        v14 = v38;
+        v36 = 0;
+        if ( *(unsigned int *)(LODWORD(v38) + 1587204) > 0 )
+        {
+          a1 = LODWORD(v38) + 4;
+          while ( 1 )
+          {
+            if ( !DrawLightmap((Lightmap *)a1, (Vec3_float_ *)&arg4, 0.0) )
+            {
+              MessageBoxW(nullptr, L"Invalid lightmap detected!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:1238", 0);
+              v35 = 5080812;
+            }
+            v36 = (int *)((char *)v36 + 1);
+            a1 += 3100;
+            if ( (signed int)v36 >= *(unsigned int *)(LODWORD(v38) + 1587204) )
+              break;
+            v14 = v38;
+          }
+        }
+      }
+      v15 = pRenderer->pRenderD3D->pDevice;
+      ErrD3D(v15->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+      ErrD3D(v15->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+      ErrD3D(v15->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0));
+      ErrD3D(v15->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 1u));
+    }
+    if ( pRenderer->bUsingSpecular )
+    {
+      //LODWORD(v30) = 1;
+      //v29 = 28;
+      //v28 = (Lightmap *)pRenderer->pRenderD3D->pDevice;
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1));
+      //v30 = pRenderer->uFogColor;
+      //v23 = pRenderer->pRenderD3D->pDevice;
+      //v29 = 34;
+      //v28 = (Lightmap *)v23;
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, pRenderer->uFogColor));
+      //v28 = (Lightmap *)pRenderer->pRenderD3D->pDevice;
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, false));
+    }
+  }
+  return 1;
+}
+
+
+//----- (0045DA56) --------------------------------------------------------
+bool LightmapBuilder::DrawLightmaps2(float z_bias)
+{
+  Vec3_float_ v; // [sp+Ch] [bp-1Ch]@2
+  v.z = 1.0;
+  v.y = 1.0;
+  v.x = 1.0;
+  
+  for (uint i = 0; i < std__vector_183808_size; ++i)
+    if (!DrawLightmap(std__vector_183808 + i, &v, z_bias))
+      MessageBoxW(nullptr, L"Invalid lightmap detected!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Light.cpp:1288", 0);
+
+  return true;
+}
+
+//----- (0045DAE8) --------------------------------------------------------
+bool LightmapBuilder::DrawLightmap(Lightmap *pLightmap, Vec3_float_ *pColorMult, float z_bias)
+{
+  double v10; // st7@4
+  double v14; // st7@7
+  __int16 v15; // fps@8
+  double v18; // st3@8
+  signed int v24; // [sp-1Ch] [bp-670h]@13
+  const char *v25; // [sp-18h] [bp-66Ch]@13
+  int v26; // [sp-14h] [bp-668h]@13
+  RenderVertexD3D3 a2[32]; // [sp+0h] [bp-654h]@7
+
+
+  if (pLightmap->uNumVertices < 3)
+  {
+    Log::Warning(L"Lightmap uNumVertices < 3");
+    return false;
+  }
+
+  uint uLightmapColorMaskR = (pLightmap->uColorMask >> 16) & 0xFF;
+  uint uLightmapColorR = floorf(uLightmapColorMaskR * pLightmap->fBrightness * pColorMult->x + 0.5f);
+  
+  uint uLightmapColorMaskG = (pLightmap->uColorMask >> 8) & 0xFF;
+  uint uLightmapColorG = floorf(uLightmapColorMaskG * pLightmap->fBrightness * pColorMult->y + 0.5f);
+ 
+  uint uLightmapColorMaskB = pLightmap->uColorMask & 0xFF;
+  uint uLightmapColorB = floorf(uLightmapColorMaskB * pLightmap->fBrightness * pColorMult->z + 0.5f);
+ 
+  uint uLightmapColor = uLightmapColorB | (uLightmapColorMaskG << 8) | (uLightmapColorMaskR << 16);
+
+  if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    v10 = (double)pOutdoorCamera->shading_dist_mist;
+  else
+    v10 = 16192.0;
+  v14 = 1.0 / v10;
+
+  for (uint i = 0; i < pLightmap->uNumVertices; ++i)
+  {
+    v18 = 1.0 - 1.0 / (v14 * pLightmap->pVertices[i].vWorldViewPosition.x * 1000.0);
+    if (fabsf(z_bias) < 1e-5f)
+    {
+      v18 = v18 - z_bias;
+      if (v18 < 0.000099999997)
+        v18 = 0.000099999997;
+    }
+
+    a2[i].pos.x = pLightmap->pVertices[i].vWorldViewProjX;
+    a2[i].pos.z = v18;
+    a2[i].pos.y = pLightmap->pVertices[i].vWorldViewProjY;
+    a2[i].rhw = 1.0 / pLightmap->pVertices[i].vWorldViewPosition.x;
+    a2[i].diffuse = uLightmapColor;
+    a2[i].specular = 0;
+    a2[i].texcoord.x = pLightmap->pVertices[i].u;
+    a2[i].texcoord.y = pLightmap->pVertices[i].v;
+  }
+
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    v24 = D3DDP_DONOTLIGHT | D3DDP_DONOTCLIP | D3DDP_DONOTUPDATEEXTENTS;
+   else
+    v24 = D3DDP_DONOTLIGHT;
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+            D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+            a2,
+            pLightmap->uNumVertices,
+            v24));
+
+  return true;
+}
+
+//----- (0045DCA9) --------------------------------------------------------
+void LightmapBuilder::DoDrawLightmaps()
+{
+  if (!std__vector_183808_size)
+    return;
+
+  if (pRenderer->bUsingSpecular)
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0));
+ 
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 0));
+
+  auto pTex = pGame->pIndoorCameraD3D->LoadTextureAndGetHardwarePtr("effpar03");
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, pTex));
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 2u));
+
+  DrawLightmaps2(0.00050000002);
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 2));
+
+  if (pRenderer->bUsingSpecular)
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1u));
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightmapBuilder.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,90 @@
+#pragma once
+#include <vector>
+#include "Render.h"
+#include "Lights.h"
+
+
+/*  115 */
+#pragma pack(push, 1)
+struct Lightmap
+{
+  Lightmap();
+
+  void (__thiscall ***vdestructor_ptr)(Lightmap *, bool);
+  unsigned int uNumVertices;
+  RenderVertexSoft pVertices[64];
+  __int16 field_C08;
+  __int16 field_C0A;
+  __int16 field_C0C;
+  __int16 field_C0E;
+  unsigned int uColorMask;
+  float fBrightness;
+  int field_C18;
+};
+#pragma pack(pop)
+
+
+/*  114 */
+#pragma pack(push, 1)
+struct LightmapBuilder
+{
+  LightmapBuilder();
+  inline ~LightmapBuilder() //----- (0045BBAA)
+  {}
+
+  void DoDrawLightmaps();
+  bool DrawLightmap(Lightmap *a1, Vec3_float_ *pColorMult, float z_bias);
+  bool DrawLightmaps2(float a2);
+  char _45D74F_MessWithLight(int a2, int *a3);
+  void DrawLightmaps(int a2);
+  bool DrawDebugOutlines(char bit_one_for_list1__bit_two_for_list2);
+  double _45D643(struct Edge *a1, float a2);
+  int _45D426(struct Span *a1, struct Edge **a2, unsigned int a3, struct Edge *a4, int a5);
+  bool _45D3C7(struct stru148 *a1);
+  bool StackLight_TerrainFace(struct StationaryLight *pLight, struct Vec3_float_ *pNormal, float *a3, struct RenderVertexSoft *a1, unsigned int uStripType, int X, unsigned int *pSlot);
+  bool StackLights_TerrainFace(struct Vec3_float_ *pNormal, float *a3, struct RenderVertexSoft *a1, unsigned int uStripType, bool bLightBackfaces);
+  bool ApplyLight_ODM(struct StationaryLight *pLight, struct ODMFace *pFace, unsigned int *pSlot, char a4);
+  bool ApplyLights_OutdoorFace(struct ODMFace *pFace);
+  double _45CC0C_light(struct Vec3_float_ a1, float a2, float a3, struct Vec3_float_ *pNormal, float a5, int uLightType);
+  int _45CBD4(struct RenderVertexSoft *a2, int a3, int *a4, int *a5);
+  int _45CB89(struct RenderVertexSoft *a1, int a2);
+  int _45CA88(struct stru320 *a2, struct RenderVertexSoft *a3, int a4, struct Vec3_float_ *pNormal);
+  bool ApplyLight_BLV(struct StationaryLight *pLight, struct BLVFace *a2, unsigned int *pSlot, bool bLightBackfaces, char *a5);
+  bool ApplyLights_IndoorFace(unsigned int uFaceID);
+  int _45C6D6(int a2, struct RenderVertexSoft *a3, Lightmap *pLightmap);
+  int _45C4B9(int a2, struct RenderVertexSoft *a3, Lightmap *pLightmap);
+  bool _45BE86_build_light_polygon(Vec3_int_ *pos, float radius, unsigned int uColorMask, float dot_dist, int uLightType, struct stru314 *a7, unsigned int uNumVertices, RenderVertexSoft *a9, char uClipFlag);
+  bool ApplyLights(struct stru320 *a2, struct stru154 *a3, unsigned int uNumVertices, struct RenderVertexSoft *a5, struct IndoorCameraD3D_Vec4 *, char uClipFlag);
+
+
+  void (__thiscall ***vdestructor_ptr)(LightmapBuilder *, bool);
+  //std::vector<Lightmap> std__vector_000004;
+  //std::vector<Lightmap> std__vector_183808;
+  Lightmap std__vector_000004[512];
+  unsigned int std__vector_000004_size;
+  Lightmap std__vector_183808[768];
+  unsigned int std__vector_183808_size;
+  float flt_3C8C0C;
+  float flt_3C8C10;
+  float flt_3C8C14;
+  float flt_3C8C18;
+  float flt_3C8C1C;
+  float flt_3C8C20;
+  float flt_3C8C24;
+  float flt_3C8C28;
+  float flt_3C8C2C_lightmaps_brightness;
+  float flt_3C8C30;
+  RenderVertexSoft field_3C8C34[256];
+  int uFlags;
+};
+#pragma pack(pop)
+
+
+
+
+extern LightsStack_StationaryLight_ *pStationaryLightsStack;
+//extern StationaryLight pStationaryLights[400];
+//extern int uNumStationaryLightsApplied; // weak
+extern LightsStack_MobileLight_ *pMobileLightsStack;
+//extern MobileLight pMobileLights[400];
+//extern int uNumMobileLightsApplied;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lights.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,134 @@
+#pragma once
+#include "OSAPI.h" // messagebox
+
+#include "VectorTypes.h"
+
+
+/*  257 */
+#pragma pack(push, 1)
+struct StationaryLight
+{
+  Vec3_short_ vPosition;
+  __int16 uRadius;
+  unsigned __int8 uLightColorR;
+  unsigned __int8 uLightColorG;
+  unsigned __int8 uLightColorB;
+  char uLightType;
+};
+#pragma pack(pop)
+
+
+
+
+#pragma pack(push, 1)
+struct MobileLight
+{
+  Vec3_short_ vPosition;
+  __int16 uRadius;
+  unsigned __int8 uLightColorR;
+  unsigned __int8 uLightColorG;
+  unsigned __int8 uLightColorB;
+  char uLightType;
+  __int16 field_C;
+  __int16 uSectorID;
+  __int16 field_10;
+};
+#pragma pack(pop)
+
+
+
+/*
+#pragma pack(push, 1)
+struct LightStack<T>
+{
+  int field_0;
+  char T[400];
+  unsigned int uNumLightsActive;
+};
+#pragma pack(pop)*/
+
+
+
+/*  260 */
+#pragma pack(push, 1)
+struct LightsStack_StationaryLight_
+{
+  //----- (004AD385) --------------------------------------------------------
+  LightsStack_StationaryLight_()
+  {
+    uNumLightsActive = 0;
+  }
+
+  //----- (004AD395) --------------------------------------------------------
+  virtual ~LightsStack_StationaryLight_()
+  {
+    uNumLightsActive = 0;
+  }
+
+  //----- (004AD39D) --------------------------------------------------------
+  inline unsigned int GetNumLights()
+  {
+    return uNumLightsActive;
+  }
+
+  //----- (004AD3C8) --------------------------------------------------------
+  inline bool AddLight(__int16 x, __int16 y, __int16 z, __int16 a5, unsigned char r, unsigned char g, unsigned char b, char uLightType)
+  {
+    unsigned int v9; // eax@1
+    std::string v11; // [sp-18h] [bp-18h]@3
+
+    v9 = this->uNumLightsActive;
+    if ( (signed int)v9 >= 400 )
+    {
+      MessageBoxW(nullptr, L"Too many stationary lights!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\StationaryLightStack.cpp:45", 0);
+      return false;
+    }
+
+      auto pLight = &pLights[uNumLightsActive++];
+      pLight->vPosition.x = x;
+      pLight->vPosition.y = y;
+      pLight->vPosition.z = z;
+      pLight->uRadius = a5;
+      pLight->uLightColorR = (unsigned __int8)r;
+      pLight->uLightColorG = g;
+      pLight->uLightColorB = b;
+      pLight->uLightType = uLightType;
+      return true;
+  }
+
+
+
+  void (__thiscall ***vdestructor_ptr)(LightsStack_StationaryLight_ *, bool);
+  StationaryLight pLights[400];
+  unsigned int uNumLightsActive;
+};
+#pragma pack(pop)
+
+
+
+
+/*  261 */
+#pragma pack(push, 1)
+struct LightsStack_MobileLight_
+{
+  //----- (00467D45) --------------------------------------------------------
+  inline LightsStack_MobileLight_()
+  {
+    this->uNumLightsActive = 0;
+    //this->vdestructor_ptr = &pLightsStack_MobileLight__pvdtor;
+  }
+  //----- (00467D55) --------------------------------------------------------
+  virtual ~LightsStack_MobileLight_()
+  {
+    this->uNumLightsActive = 0;
+  }
+  
+  bool AddLight(__int16 x, __int16 y, __int16 z, __int16 uSectorID, int uRadius, unsigned __int8 r, unsigned __int8 g, unsigned __int8 b, char a10);
+
+
+
+  void (__thiscall ***vdestructor_ptr)(LightsStack_MobileLight_ *, bool);
+  MobileLight  pLights[400];
+  unsigned int uNumLightsActive;
+};
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightsStack.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,28 @@
+#include <string>
+#include "Lights.h"
+
+#include "mm7_data.h"
+
+//----- (00467D88) --------------------------------------------------------
+bool LightsStack_MobileLight_::AddLight(__int16 x, __int16 y, __int16 z, __int16 uSectorID, int uRadius, unsigned __int8 r, unsigned __int8 g, unsigned __int8 b, char uLightType)
+{
+  if (uNumLightsActive >= 400)
+  {
+    MessageBoxW(nullptr, L"Too many mobile lights!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\MobileLightStack.cpp:51", 0);
+    return false;
+  }
+
+  pLights[uNumLightsActive].vPosition.x = x;
+  pLights[uNumLightsActive].vPosition.y = y;
+  pLights[uNumLightsActive].vPosition.z = z;
+  pLights[uNumLightsActive].uRadius = uRadius;
+  pLights[uNumLightsActive].field_C = (((uRadius < 0) - 1) & 0x3E) - 31;
+  pLights[uNumLightsActive].uSectorID = uSectorID;
+  pLights[uNumLightsActive].field_10 = uRadius * uRadius >> 5;
+  pLights[uNumLightsActive].uLightColorR = r;
+  pLights[uNumLightsActive].uLightColorG = g;
+  pLights[uNumLightsActive].uLightColorB = b;
+  pLights[uNumLightsActive++].uLightType = uLightType;
+
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Log.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,34 @@
+#include "Log.h"
+
+
+#include <stdio.h>
+#include <windows.h>
+HANDLE hStdOut = nullptr;
+
+
+
+
+void Log::Initialize()
+{
+  if (AllocConsole())
+    hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+}
+
+
+void Log::Warning(const wchar_t *pFormat, ...)
+{
+  if (!hStdOut)
+    return;
+
+  va_list args;
+  wchar_t pMsg[8192];
+
+  va_start(args, pFormat);
+  vswprintf_s(pMsg, 8192, pFormat, args);
+  va_end(args);
+
+  DWORD w;
+  WriteConsole(hStdOut, pMsg, lstrlenW(pMsg), &w, nullptr);
+  WriteConsole(hStdOut, L"\r\n", 2, &w, nullptr);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Log.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,11 @@
+#pragma once
+
+
+#define LOG_DECOMPILATION_WARNING()  Log::Warning(L"%S [%S:%u]", __FUNCTION__, __FILE__, __LINE__);
+
+class Log
+{
+  public:
+    static void Initialize();
+    static void Warning(const wchar_t *pFormat, ...);
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MM7.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,440 @@
+#pragma once
+#include "OSAPI.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string>
+
+typedef unsigned int uint;
+#define LOWORD(a) (*((unsigned short *)&a))
+#define HIWORD(a) (*((unsigned short *)&a + 1))
+#define SHIWORD(a) (*((short *)&a + 1))
+
+#define LODWORD(a) (*((unsigned int *)&a))
+#define HIDWORD(a) (*((unsigned int *)&a + 1))
+#define SLODWORD(a) (*((int *)&a))
+#define SHIDWORD(a) (*((int *)&a + 1))
+
+#define LOBYTE(a) (*((unsigned char *)&a))
+#define HIBYTE(a) (*((unsigned char *)&a + sizeof(a) - 1))
+#define BYTE1(a) (*((unsigned char *)&a + 1))
+#define BYTE2(a) (*((unsigned char *)&a + 2))
+#define BYTE3(a) (*((unsigned char *)&a + 3))
+
+
+typedef unsigned __int16 _WORD;
+typedef unsigned __int64 _QWORD;
+
+
+#include "VectorTypes.h"
+#include "IndoorCameraD3D.h"
+/*#include "LOD.h"
+#include "Texture.h"
+#include "Mouse.h"
+#include "Overlays.h"
+#include "Game.h"
+#include "Items.h"
+#include "Actor.h"
+#include "Arcomage.h"
+#include "Render.h"
+#include "Time.h"
+#include "GUIWindow.h"
+#include "GUIButton.h"
+#include "GUIProgressBar.h"
+#include "GUIFont.h"
+#include "NPC.h"
+#include "PaletteManager.h"
+#include "Party.h"
+#include "AudioPlayer.h"
+#include "VideoPlayer.h"
+#include "Chest.h"
+#include "Allocator.h"
+#include "IndoorCamera.h"
+#include "Party.h"
+#include "Outdoor.h"
+
+#include "mm7_data.h"
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*  154 */
+#pragma pack(push, 1)
+struct stru161
+{
+  Vec3_int_ pos;
+  __int16 rot_y;
+  __int16 rot_x;
+  unsigned __int16 uMapInfoID;
+  __int16 field_12;
+};
+#pragma pack(pop)
+extern stru161 stru_4ECBB8[6]; // weak
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*  285 */
+#pragma pack(push, 1)
+struct stru289
+{
+  //----- (0046263C) --------------------------------------------------------
+  inline stru289()
+  {
+    this->field_64 = 2;
+    this->field_74 = 0;
+    this->field_70 = 0;
+    this->field_6C = 0;
+    this->field_68 = 0;
+  }
+
+
+  char field_0[100];
+  int field_64;
+  int field_68;
+  int field_6C;
+  int field_70;
+  int field_74;
+};
+#pragma pack(pop)
+extern stru289 stru_6BE158;
+
+
+
+/*  288 */
+#pragma pack(push, 1)
+struct CheckHRESULT_stru0
+{
+  void CheckHRESULT(HRESULT a2, const char *Str, int a4, unsigned int uType);
+  void *_466D09_xcpt_string(std::string a2, const char *Str, int a4);
+  void ShowMessageBox(std::string *a0, std::string lpCaption, UINT uType, std::string lpText, int line);
+  char ddraw_error(HRESULT hr, char *Str, size_t a3);
+  char dinput_error(int a1, const char *Str, int a3);
+
+  void (__thiscall ***vdestructor_ptr)(CheckHRESULT_stru0 *, bool);
+};
+#pragma pack(pop)
+
+
+
+
+/*  297 */
+enum SoundType
+{
+  SOUND_EndTurnBasedMode = 0xCE,
+  SOUND_StartTurnBasedMode = 0xCF,
+  SOUND_FlipOnExit = 0x4E21,
+};
+
+
+
+
+
+/*  301 */
+enum PlayerSpeech
+{
+  SPEECH_Yell = 0x41,
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*  349 */
+enum HOUSE_TYPE
+{
+  HOUSE_BODY_GUILD_NOVICE_EMERALD_ISLE = 0xA3,
+};
+
+
+
+
+
+
+
+
+
+
+
+/*  362 */
+#pragma pack(push, 1)
+struct TravelInfo
+{
+  char uMapID;
+  char pSchedule[7];
+  char uDaysCount;
+  char field_9[3];
+  int x;
+  int y;
+  int z;
+  int direction;
+  int field_1C;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+/*  369 */
+#pragma pack(push, 1)
+struct stru329
+{
+  int field_0;
+  float field_4;
+  int field_8;
+  int field_C;
+  int equip_x;
+  int equip_y;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+  int field_2C;
+  int field_30;
+  int field_34;
+  int field_38;
+  int field_3C;
+  int field_40;
+  int field_44;
+  int field_48;
+  int field_4C;
+  int field_50;
+  int field_54;
+  int field_58;
+  int field_5C;
+  int field_60;
+  int field_64;
+  int field_68;
+  int field_6C;
+  int field_70;
+  int field_74;
+  int field_78;
+  int field_7C;
+};
+#pragma pack(pop)
+extern stru329 array_4E4C30[4];
+
+/*  371 */
+#pragma pack(push, 1)
+struct stru331
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+  int field_2C;
+  int field_30;
+  int field_34;
+  int field_38;
+  int field_3C;
+};
+#pragma pack(pop)
+
+/*  372 */
+#pragma pack(push, 1)
+struct stru332
+{
+  unsigned int texids[11];
+  stru331 field_2C;
+};
+#pragma pack(pop)
+extern stru332 stru_511698;
+
+
+/*  373 */
+#pragma pack(push, 1)
+struct stru333
+{
+  unsigned int texids[5];
+  unsigned int *texid1;
+  int field_18;
+};
+#pragma pack(pop)
+extern stru333 stru_511718;
+
+
+/*  374 */
+#pragma pack(push, 1)
+struct stru334
+{
+  __int16 field_0;
+  __int16 field_2;
+  __int16 field_4;
+  __int16 field_6;
+};
+#pragma pack(pop)
+extern stru334 array_4E2940[26];
+
+/*  376 */
+#pragma pack(push, 1)
+struct stru336
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  __int16 field_18[480];
+  __int16 field_3D8[480];
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*  388 */
+#pragma pack(push, 1)
+struct stru348
+{
+  __int16 field_0;
+  __int16 field_2;
+  __int16 field_4;
+  __int16 field_6;
+  __int16 field_8;
+  __int16 field_A;
+  __int16 field_C;
+  __int16 field_E;
+  __int16 field_10;
+  __int16 field_12;
+  int field_14;
+};
+#pragma pack(pop)
+
+extern stru348 stru_4E1890[13];
+
+
+
+
+
+
Binary file MM7.sdf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MM7.sln	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MM7", "MM7.vcxproj", "{4CB238C2-3039-4BF6-966A-1ED1285BE23B}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{4CB238C2-3039-4BF6-966A-1ED1285BE23B}.Debug|Win32.ActiveCfg = Debug|Win32
+		{4CB238C2-3039-4BF6-966A-1ED1285BE23B}.Debug|Win32.Build.0 = Debug|Win32
+		{4CB238C2-3039-4BF6-966A-1ED1285BE23B}.Release|Win32.ActiveCfg = Release|Win32
+		{4CB238C2-3039-4BF6-966A-1ED1285BE23B}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Binary file MM7.suo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MM7.vcxproj	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,293 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{4CB238C2-3039-4BF6-966A-1ED1285BE23B}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>MightandMagicTrilogy</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <TargetName>$(ProjectName)</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <ObjectFileName>$(IntDir)/%(RelativeDir)</ObjectFileName>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="Actor.cpp" />
+    <ClCompile Include="AIL.cpp" />
+    <ClCompile Include="Allocator.cpp" />
+    <ClCompile Include="Arcomage.cpp" />
+    <ClCompile Include="AudioPlayer.cpp" />
+    <ClCompile Include="Bink_Smacker.cpp" />
+    <ClCompile Include="BSPModel.cpp" />
+    <ClCompile Include="Chest.cpp" />
+    <ClCompile Include="DecalBuilder.cpp" />
+    <ClCompile Include="Events.cpp" />
+    <ClCompile Include="FrameTableInc.cpp" />
+    <ClCompile Include="Game.cpp" />
+    <ClCompile Include="GameUIs.cpp" />
+    <ClCompile Include="GammaControl.cpp" />
+    <ClCompile Include="GUIButton.cpp" />
+    <ClCompile Include="GUIFont.cpp" />
+    <ClCompile Include="GUIProgressBar.cpp" />
+    <ClCompile Include="GUIWindow.cpp" />
+    <ClCompile Include="Indoor.cpp" />
+    <ClCompile Include="IndoorCamera.cpp" />
+    <ClCompile Include="IndoorCameraD3D.cpp" />
+    <ClCompile Include="Items.cpp" />
+    <ClCompile Include="Keyboard.cpp" />
+    <ClCompile Include="LayingItem.cpp" />
+    <ClCompile Include="lib\zlib\adler32.c" />
+    <ClCompile Include="lib\zlib\compress.c" />
+    <ClCompile Include="lib\zlib\crc32.c" />
+    <ClCompile Include="lib\zlib\deflate.c" />
+    <ClCompile Include="lib\zlib\infblock.c" />
+    <ClCompile Include="lib\zlib\infcodes.c" />
+    <ClCompile Include="lib\zlib\inffast.c" />
+    <ClCompile Include="lib\zlib\inflate.c" />
+    <ClCompile Include="lib\zlib\inftrees.c" />
+    <ClCompile Include="lib\zlib\infutil.c" />
+    <ClCompile Include="lib\zlib\trees.c" />
+    <ClCompile Include="lib\zlib\uncompr.c" />
+    <ClCompile Include="lib\zlib\zutil.c" />
+    <ClCompile Include="LightmapBuilder.cpp" />
+    <ClCompile Include="LightsStack.cpp" />
+    <ClCompile Include="LOD.cpp" />
+    <ClCompile Include="Log.cpp" />
+    <ClCompile Include="mm7_1.cpp">
+      <RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <ClCompile Include="mm7_2.cpp" />
+    <ClCompile Include="mm7_3.cpp" />
+    <ClCompile Include="mm7_4.cpp" />
+    <ClCompile Include="mm7_5.cpp" />
+    <ClCompile Include="mm7_6.cpp" />
+    <ClCompile Include="mm7_data.cpp" />
+    <ClCompile Include="Monsters.cpp" />
+    <ClCompile Include="Mouse.cpp" />
+    <ClCompile Include="OSAPI.cpp" />
+    <ClCompile Include="Outdoor.cpp" />
+    <ClCompile Include="Overlays.cpp" />
+    <ClCompile Include="PaletteManager.cpp" />
+    <ClCompile Include="ParticleEngine.cpp" />
+    <ClCompile Include="Party.cpp" />
+    <ClCompile Include="Player.cpp" />
+    <ClCompile Include="Random.cpp" />
+    <ClCompile Include="Render.cpp" />
+    <ClCompile Include="SaveLoad.cpp" />
+    <ClCompile Include="Spells.cpp" />
+    <ClCompile Include="Sprites.cpp" />
+    <ClCompile Include="stru10.cpp" />
+    <ClCompile Include="stru6.cpp" />
+    <ClCompile Include="stru9.cpp" />
+    <ClCompile Include="Texture.cpp" />
+    <ClCompile Include="TileFrameTable.h" />
+    <ClCompile Include="Time.cpp" />
+    <ClCompile Include="VideoPlayer.cpp" />
+    <ClCompile Include="Vis.cpp" />
+    <ClCompile Include="Weather.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Actor.h" />
+    <ClInclude Include="AIL.h" />
+    <ClInclude Include="Allocator.h" />
+    <ClInclude Include="Arcomage.h" />
+    <ClInclude Include="AudioPlayer.h" />
+    <ClInclude Include="Autonotes.h" />
+    <ClInclude Include="Awards.h" />
+    <ClInclude Include="Bink_Smacker.h" />
+    <ClInclude Include="BSPModel.h" />
+    <ClInclude Include="Chest.h" />
+    <ClInclude Include="CShow.h" />
+    <ClInclude Include="DecalBuilder.h" />
+    <ClInclude Include="DecorationList.h" />
+    <ClInclude Include="Events.h" />
+    <ClInclude Include="Events2D.h" />
+    <ClInclude Include="FactionTable.h" />
+    <ClInclude Include="FrameTableInc.h" />
+    <ClInclude Include="Game.h" />
+    <ClInclude Include="GammaControl.h" />
+    <ClInclude Include="GUIButton.h" />
+    <ClInclude Include="GUIFont.h" />
+    <ClInclude Include="GUIProgressBar.h" />
+    <ClInclude Include="GUIWindow.h" />
+    <ClInclude Include="IconFrameTable.h" />
+    <ClInclude Include="Indoor.h" />
+    <ClInclude Include="IndoorCamera.h" />
+    <ClInclude Include="IndoorCameraD3D.h" />
+    <ClInclude Include="Indoor_stuff.h" />
+    <ClInclude Include="lib\zlib\deflate.h" />
+    <ClInclude Include="lib\zlib\infblock.h" />
+    <ClInclude Include="lib\zlib\infcodes.h" />
+    <ClInclude Include="lib\zlib\inffast.h" />
+    <ClInclude Include="lib\zlib\inffixed.h" />
+    <ClInclude Include="lib\zlib\inftrees.h" />
+    <ClInclude Include="lib\zlib\infutil.h" />
+    <ClInclude Include="lib\zlib\trees.h" />
+    <ClInclude Include="lib\zlib\zconf.h" />
+    <ClInclude Include="lib\zlib\zlib.h" />
+    <ClInclude Include="lib\zlib\zutil.h" />
+    <ClInclude Include="Log.h" />
+    <ClInclude Include="OSAPI.h" />
+    <ClInclude Include="Outdoor_stuff.h" />
+    <ClInclude Include="Items.h" />
+    <ClInclude Include="Keyboard.h" />
+    <ClInclude Include="LayingItem.h" />
+    <ClInclude Include="lib\legacy_dx\d3d.h" />
+    <ClInclude Include="lib\legacy_dx\d3dcaps.h" />
+    <ClInclude Include="lib\legacy_dx\d3drm.h" />
+    <ClInclude Include="lib\legacy_dx\d3drmdef.h" />
+    <ClInclude Include="lib\legacy_dx\d3drmobj.h" />
+    <ClInclude Include="lib\legacy_dx\d3drmwin.h" />
+    <ClInclude Include="lib\legacy_dx\d3dtypes.h" />
+    <ClInclude Include="lib\legacy_dx\ddraw.h" />
+    <ClInclude Include="lib\legacy_dx\dinput.h" />
+    <ClInclude Include="lib\legacy_dx\dinputd.h" />
+    <ClInclude Include="lib\legacy_dx\dmdls.h" />
+    <ClInclude Include="lib\legacy_dx\dmerror.h" />
+    <ClInclude Include="lib\legacy_dx\dmksctrl.h" />
+    <ClInclude Include="lib\legacy_dx\dmplugin.h" />
+    <ClInclude Include="lib\legacy_dx\dmusbuff.h" />
+    <ClInclude Include="lib\legacy_dx\dmusicc.h" />
+    <ClInclude Include="lib\legacy_dx\dmusicf.h" />
+    <ClInclude Include="lib\legacy_dx\dmusici.h" />
+    <ClInclude Include="lib\legacy_dx\dmusics.h" />
+    <ClInclude Include="lib\legacy_dx\dsconf.h" />
+    <ClInclude Include="lib\legacy_dx\dsound.h" />
+    <ClInclude Include="lib\legacy_dx\dvoice.h" />
+    <ClInclude Include="lib\legacy_dx\multimon.h" />
+    <ClInclude Include="lib\legacy_dx\rmxfguid.h" />
+    <ClInclude Include="lib\legacy_dx\rmxftmpl.h" />
+    <ClInclude Include="lib\legacy_dx\strsafe.h" />
+    <ClInclude Include="LightmapBuilder.h" />
+    <ClInclude Include="Lights.h" />
+    <ClInclude Include="LOD.h" />
+    <ClInclude Include="MapInfo.h" />
+    <ClInclude Include="Math.h" />
+    <ClInclude Include="MM7.h" />
+    <ClInclude Include="mm7_data.h" />
+    <ClInclude Include="Monsters.h" />
+    <ClInclude Include="Mouse.h" />
+    <ClInclude Include="NPC.h" />
+    <ClInclude Include="ObjectList.h" />
+    <ClInclude Include="OSInfo.h" />
+    <ClInclude Include="Outdoor.h" />
+    <ClInclude Include="OutdoorCamera.h" />
+    <ClInclude Include="Overlays.h" />
+    <ClInclude Include="PaletteManager.h" />
+    <ClInclude Include="ParticleEngine.h" />
+    <ClInclude Include="Party.h" />
+    <ClInclude Include="Player.h" />
+    <ClInclude Include="PlayerFrameTable.h" />
+    <ClInclude Include="Random.h" />
+    <ClInclude Include="Render.h" />
+    <ClInclude Include="resource.h" />
+    <ClInclude Include="SaveLoad.h" />
+    <ClInclude Include="Spells.h" />
+    <ClInclude Include="Sprites.h" />
+    <ClInclude Include="StorylineTextTable.h" />
+    <ClInclude Include="stru10.h" />
+    <ClInclude Include="stru11.h" />
+    <ClInclude Include="stru12.h" />
+    <ClInclude Include="stru123.h" />
+    <ClInclude Include="stru157.h" />
+    <ClInclude Include="stru159.h" />
+    <ClInclude Include="stru160.h" />
+    <ClInclude Include="stru176.h" />
+    <ClInclude Include="stru179.h" />
+    <ClInclude Include="stru220.h" />
+    <ClInclude Include="stru272.h" />
+    <ClInclude Include="stru277.h" />
+    <ClInclude Include="stru279.h" />
+    <ClInclude Include="stru287.h" />
+    <ClInclude Include="stru298.h" />
+    <ClInclude Include="stru314.h" />
+    <ClInclude Include="stru346.h" />
+    <ClInclude Include="stru351.h" />
+    <ClInclude Include="stru6.h" />
+    <ClInclude Include="stru9.h" />
+    <ClInclude Include="Texture.h" />
+    <ClInclude Include="Time.h" />
+    <ClInclude Include="TurnEngine.h" />
+    <ClInclude Include="VectorTypes.h" />
+    <ClInclude Include="VideoPlayer.h" />
+    <ClInclude Include="Viewport.h" />
+    <ClInclude Include="Vis.h" />
+    <ClInclude Include="Weather.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="lib\legacy_dx\d3dvec.inl" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="Might and Magic Trilogy.rc" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MM7.vcxproj.filters	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,318 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClInclude Include="MM7.h" />
+    <ClInclude Include="lib\legacy_dx\d3d.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\d3dcaps.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\d3drm.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\d3drmdef.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\d3drmobj.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\d3drmwin.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\d3dtypes.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\ddraw.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dinput.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dinputd.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmdls.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmerror.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmksctrl.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmplugin.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmusbuff.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmusicc.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmusicf.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmusici.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dmusics.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dsconf.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dsound.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\dvoice.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\multimon.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\rmxfguid.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\rmxftmpl.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\legacy_dx\strsafe.h">
+      <Filter>lib\legacy_dx</Filter>
+    </ClInclude>
+    <ClInclude Include="AudioPlayer.h" />
+    <ClInclude Include="VideoPlayer.h" />
+    <ClInclude Include="Texture.h" />
+    <ClInclude Include="LOD.h" />
+    <ClInclude Include="Mouse.h" />
+    <ClInclude Include="LightmapBuilder.h" />
+    <ClInclude Include="Vis.h" />
+    <ClInclude Include="Render.h" />
+    <ClInclude Include="Game.h" />
+    <ClInclude Include="VectorTypes.h" />
+    <ClInclude Include="ParticleEngine.h" />
+    <ClInclude Include="IndoorCameraD3D.h" />
+    <ClInclude Include="Keyboard.h" />
+    <ClInclude Include="Party.h" />
+    <ClInclude Include="Player.h" />
+    <ClInclude Include="CShow.h" />
+    <ClInclude Include="stru6.h" />
+    <ClInclude Include="stru9.h" />
+    <ClInclude Include="stru10.h" />
+    <ClInclude Include="stru11.h" />
+    <ClInclude Include="stru12.h" />
+    <ClInclude Include="GammaControl.h" />
+    <ClInclude Include="Indoor.h" />
+    <ClInclude Include="Outdoor.h" />
+    <ClInclude Include="OutdoorCamera.h" />
+    <ClInclude Include="BSPModel.h" />
+    <ClInclude Include="Actor.h" />
+    <ClInclude Include="Items.h" />
+    <ClInclude Include="Monsters.h" />
+    <ClInclude Include="NPC.h" />
+    <ClInclude Include="PaletteManager.h" />
+    <ClInclude Include="GUIButton.h" />
+    <ClInclude Include="GUIFont.h" />
+    <ClInclude Include="GUIWindow.h" />
+    <ClInclude Include="Spells.h" />
+    <ClInclude Include="DecalBuilder.h" />
+    <ClInclude Include="Lights.h" />
+    <ClInclude Include="Arcomage.h" />
+    <ClInclude Include="GUIProgressBar.h" />
+    <ClInclude Include="Events.h" />
+    <ClInclude Include="Sprites.h" />
+    <ClInclude Include="Overlays.h" />
+    <ClInclude Include="Time.h" />
+    <ClInclude Include="Chest.h" />
+    <ClInclude Include="mm7_data.h" />
+    <ClInclude Include="Allocator.h" />
+    <ClInclude Include="IndoorCamera.h" />
+    <ClInclude Include="LayingItem.h" />
+    <ClInclude Include="Viewport.h" />
+    <ClInclude Include="MapInfo.h" />
+    <ClInclude Include="PlayerFrameTable.h" />
+    <ClInclude Include="OSInfo.h" />
+    <ClInclude Include="Math.h" />
+    <ClInclude Include="Weather.h" />
+    <ClInclude Include="IconFrameTable.h" />
+    <ClInclude Include="ObjectList.h" />
+    <ClInclude Include="DecorationList.h" />
+    <ClInclude Include="Outdoor_stuff.h" />
+    <ClInclude Include="Random.h" />
+    <ClInclude Include="Indoor_stuff.h" />
+    <ClInclude Include="stru157.h" />
+    <ClInclude Include="stru123.h" />
+    <ClInclude Include="AIL.h" />
+    <ClInclude Include="Bink_Smacker.h" />
+    <ClInclude Include="TurnEngine.h" />
+    <ClInclude Include="stru220.h" />
+    <ClInclude Include="stru279.h" />
+    <ClInclude Include="stru314.h" />
+    <ClInclude Include="SaveLoad.h" />
+    <ClInclude Include="stru287.h" />
+    <ClInclude Include="stru179.h" />
+    <ClInclude Include="Awards.h" />
+    <ClInclude Include="Autonotes.h" />
+    <ClInclude Include="stru160.h" />
+    <ClInclude Include="FactionTable.h" />
+    <ClInclude Include="StorylineTextTable.h" />
+    <ClInclude Include="stru277.h" />
+    <ClInclude Include="stru298.h" />
+    <ClInclude Include="OSAPI.h" />
+    <ClInclude Include="Events2D.h" />
+    <ClInclude Include="stru176.h" />
+    <ClInclude Include="stru159.h" />
+    <ClInclude Include="stru351.h" />
+    <ClInclude Include="stru272.h" />
+    <ClInclude Include="lib\zlib\deflate.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\infblock.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\infcodes.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\inffast.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\inffixed.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\inftrees.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\infutil.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\trees.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\zconf.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\zlib.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="lib\zlib\zutil.h">
+      <Filter>lib\zlib</Filter>
+    </ClInclude>
+    <ClInclude Include="Log.h" />
+    <ClInclude Include="FrameTableInc.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <Filter Include="lib">
+      <UniqueIdentifier>{674d5845-1afa-4bb4-b0f9-e59bdcf6bf46}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="lib\legacy_dx">
+      <UniqueIdentifier>{7f786ac2-aa3f-48a5-81ef-d5bcf2ee57bf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="lib\zlib">
+      <UniqueIdentifier>{2c8eede3-bdcb-4411-b5e3-86c1c48e8351}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="lib\legacy_dx\d3dvec.inl">
+      <Filter>lib\legacy_dx</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="mm7_2.cpp" />
+    <ClCompile Include="Game.cpp" />
+    <ClCompile Include="GammaControl.cpp" />
+    <ClCompile Include="Monsters.cpp" />
+    <ClCompile Include="Time.cpp" />
+    <ClCompile Include="Actor.cpp" />
+    <ClCompile Include="Items.cpp" />
+    <ClCompile Include="LOD.cpp" />
+    <ClCompile Include="Render.cpp" />
+    <ClCompile Include="Spells.cpp" />
+    <ClCompile Include="Overlays.cpp" />
+    <ClCompile Include="Chest.cpp" />
+    <ClCompile Include="GUIWindow.cpp" />
+    <ClCompile Include="Keyboard.cpp" />
+    <ClCompile Include="LightmapBuilder.cpp" />
+    <ClCompile Include="Arcomage.cpp" />
+    <ClCompile Include="Mouse.cpp" />
+    <ClCompile Include="Texture.cpp" />
+    <ClCompile Include="DecalBuilder.cpp" />
+    <ClCompile Include="Allocator.cpp" />
+    <ClCompile Include="IndoorCameraD3D.cpp" />
+    <ClCompile Include="Sprites.cpp" />
+    <ClCompile Include="Vis.cpp" />
+    <ClCompile Include="IndoorCamera.cpp" />
+    <ClCompile Include="GUIFont.cpp" />
+    <ClCompile Include="Indoor.cpp" />
+    <ClCompile Include="Outdoor.cpp" />
+    <ClCompile Include="Player.cpp" />
+    <ClCompile Include="stru10.cpp" />
+    <ClCompile Include="LightsStack.cpp" />
+    <ClCompile Include="BSPModel.cpp" />
+    <ClCompile Include="PaletteManager.cpp" />
+    <ClCompile Include="ParticleEngine.cpp" />
+    <ClCompile Include="Party.cpp" />
+    <ClCompile Include="stru9.cpp" />
+    <ClCompile Include="stru6.cpp" />
+    <ClCompile Include="AudioPlayer.cpp" />
+    <ClCompile Include="GUIButton.cpp" />
+    <ClCompile Include="LayingItem.cpp" />
+    <ClCompile Include="VideoPlayer.cpp" />
+    <ClCompile Include="GUIProgressBar.cpp" />
+    <ClCompile Include="TileFrameTable.h" />
+    <ClCompile Include="Weather.cpp" />
+    <ClCompile Include="Random.cpp" />
+    <ClCompile Include="SaveLoad.cpp" />
+    <ClCompile Include="mm7_3.cpp" />
+    <ClCompile Include="mm7_data.cpp" />
+    <ClCompile Include="AIL.cpp" />
+    <ClCompile Include="Bink_Smacker.cpp" />
+    <ClCompile Include="Events.cpp" />
+    <ClCompile Include="lib\zlib\adler32.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\compress.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\crc32.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\deflate.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\infblock.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\infcodes.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\inffast.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\inflate.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\inftrees.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\infutil.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\trees.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\uncompr.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="lib\zlib\zutil.c">
+      <Filter>lib\zlib</Filter>
+    </ClCompile>
+    <ClCompile Include="Log.cpp" />
+    <ClCompile Include="OSAPI.cpp" />
+    <ClCompile Include="mm7_4.cpp" />
+    <ClCompile Include="mm7_1.cpp" />
+    <ClCompile Include="mm7_5.cpp" />
+    <ClCompile Include="FrameTableInc.cpp" />
+    <ClCompile Include="mm7_6.cpp" />
+    <ClCompile Include="GameUIs.cpp" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MM7.vcxproj.user	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LocalDebuggerCommandArguments>
+    </LocalDebuggerCommandArguments>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LocalDebuggerWorkingDirectory>..\..\Buka\MMCollection\MM_VII</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
Binary file MM7_manifest.rc has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MapInfo.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,66 @@
+#pragma once
+
+
+
+/*  192 */
+#pragma pack(push, 1)
+struct MapInfo
+{
+  int SpawnRandomTreasure(struct SpawnPointMM7 *a2);
+
+  char *pName;
+  char *pFilename;
+  char *pEncounterMonster1Texture;
+  char *pEncounterMonster2Texture;
+  char *pEncounterMonster3Texture;
+  unsigned int uNumResets;
+  unsigned int uFirstVisitedAt;
+  unsigned int uRespawnIntervalDays;
+  int _alert_days;
+  int _steal_perm;
+  int _per;
+  char field_2C;
+  char field_2D;
+  char field_2E;
+  char field_2F;
+  char field_30;
+  char field_31;
+  char field_32;
+  char field_33;
+  char field_34;
+  unsigned __int8 uEncounterMonster1AtLeast;
+  unsigned __int8 uEncounterMonster1AtMost;
+  char field_37;
+  unsigned __int8 uEncounterMonster2AtLeast;
+  unsigned __int8 uEncounterMonster2AtMost;
+  char field_3A;
+  unsigned __int8 uEncounterMonster3AtLeast;
+  unsigned __int8 uEncounterMonster3AtMost;
+  char field_3D;
+  char field_3E;
+  char field_3F;
+  unsigned __int8 uRedbookTrackID;
+  unsigned __int8 uEAXEnv;
+  char field_42;
+  char field_43;
+};
+#pragma pack(pop)
+
+
+
+/*  193 */
+#pragma pack(push, 1)
+struct MapStats
+{
+  void Initialize();
+  unsigned int GetMapInfo(const char *Str2);
+
+  MapInfo pInfos[77];
+  unsigned int uNumMaps;
+};
+#pragma pack(pop)
+
+
+
+
+extern struct MapStats *pMapStats;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Math.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,28 @@
+#pragma once
+
+
+
+/*  186 */
+#pragma pack(push, 1)
+struct stru193_math
+{
+  stru193_math();
+  int SinCos(int angle);
+  unsigned int Atan2(int x, int y);
+  int _42EBDB(int angle);
+
+  int pTanTable[520];
+  int pCosTable[520];
+  int pInvCosTable[520];
+  unsigned int uIntegerPi;
+  unsigned int uIntegerHalfPi;
+  unsigned int uIntegerDoublePi;
+  unsigned int uDoublePiMask;
+  unsigned int uPiMask;
+  unsigned int uHalfPiMask;
+};
+#pragma pack(pop)
+
+
+
+extern struct stru193_math *stru_5C6E00;
\ No newline at end of file
Binary file Might and Magic Trilogy.rc has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Monsters.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1512 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Monsters.h"
+#include "FrameTableInc.h"
+#include "Allocator.h"
+#include "LOD.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+struct MonsterStats *pMonsterStats;
+struct MonsterList *pMonsterList;
+
+
+//----- (004598FC) --------------------------------------------------------
+bool MonsterList::FromFileTxt(const char *Args)
+{
+  MonsterList *v2; // ebx@1
+  FILE *v3; // eax@1
+  unsigned int v4; // esi@3
+  void *v5; // eax@9
+  FILE *v6; // ST14_4@11
+  char *i; // eax@11
+  signed int v8; // esi@12
+  unsigned __int16 v9; // ax@16
+  const char *v10; // ST18_4@16
+  unsigned __int16 v11; // ax@16
+  const char *v12; // ST14_4@16
+  unsigned __int16 v13; // ax@16
+  const char *v14; // ST10_4@16
+  __int16 v15; // ax@16
+  const char *v16; // ST0C_4@16
+  int v17; // esi@16
+  unsigned __int8 v18; // al@16
+  signed int v19; // esi@16
+  unsigned __int16 v20; // ax@17
+  int v21; // ecx@17
+  char Buf; // [sp+4h] [bp-304h]@3
+  FrameTableTxtLine v24; // [sp+1F8h] [bp-110h]@4
+  FrameTableTxtLine v25; // [sp+274h] [bp-94h]@4
+  int v26; // [sp+2F0h] [bp-18h]@16
+  char v27; // [sp+2F4h] [bp-14h]@14
+  char v28; // [sp+2F5h] [bp-13h]@14
+  char v29; // [sp+2F6h] [bp-12h]@14
+  char v30; // [sp+2F7h] [bp-11h]@14
+  char v31; // [sp+2F8h] [bp-10h]@14
+  char v32; // [sp+2F9h] [bp-Fh]@14
+  char v33; // [sp+2FAh] [bp-Eh]@14
+  char v34; // [sp+2FBh] [bp-Dh]@14
+  char v35; // [sp+2FCh] [bp-Ch]@14
+  char v36; // [sp+2FDh] [bp-Bh]@14
+  char v37; // [sp+2FEh] [bp-Ah]@14
+  char v38; // [sp+2FFh] [bp-9h]@14
+  char v39; // [sp+300h] [bp-8h]@14
+  char v40; // [sp+301h] [bp-7h]@14
+  char v41; // [sp+302h] [bp-6h]@14
+  char v42; // [sp+303h] [bp-5h]@14
+  FILE *File; // [sp+304h] [bp-4h]@1
+  unsigned int Argsa; // [sp+310h] [bp+8h]@3
+  int Argsb; // [sp+310h] [bp+8h]@16
+
+  v2 = this;
+  v3 = fopen(Args, "r");
+  File = v3;
+  if ( !v3 )
+    Abortf("MonsterRaceListStruct::load - Unable to open file: %s.");
+  v4 = 0;
+  Argsa = 0;
+  if ( fgets(&Buf, 490, v3) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v25, frame_table_txt_parser(&Buf, &v24), sizeof(v25));
+      if ( v25.field_0 && *v25.pProperties[0] != 47 )
+        ++Argsa;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v4 = Argsa;
+  }
+  v2->uNumMonsters = v4;
+  v5 = pAllocator->AllocNamedChunk(v2->pMonsters, 152 * v4, "Mon Race");
+  v2->pMonsters = (MonsterDesc *)v5;
+  if ( !v5 )
+    Abortf("MonsterRaceListStruct::load - Out of Memory!");
+  v6 = File;
+  v2->uNumMonsters = 0;
+  fseek(v6, 0, 0);
+  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v25, frame_table_txt_parser(&Buf, &v24), sizeof(v25));
+    v8 = 0;
+    if ( v25.field_0 && *v25.pProperties[0] != 47 )
+    {
+      strcpy(v2->pMonsters[v2->uNumMonsters].pMonsterName, v25.pProperties[0]);
+      v35 = 0;
+      v36 = 1;
+      v37 = 7;
+      v38 = 2;
+      v39 = 3;
+      v40 = 4;
+      v41 = 5;
+      v42 = 6;
+      v27 = 1;
+      v28 = 2;
+      v29 = 3;
+      v30 = 4;
+      v31 = 4;
+      v32 = 5;
+      v33 = 6;
+      v34 = 7;
+      do
+      {
+        strcpy(
+          v2->pMonsters[v2->uNumMonsters].pSpriteNames[(unsigned __int8)*(&v35 + v8)],
+          v25.pProperties[(unsigned __int8)*(&v27 + v8)]);
+        ++v8;
+      }
+      while ( v8 < 8 );
+      v9 = atoi(v25.pProperties[8]);
+      v10 = v25.pProperties[9];
+      v2->pMonsters[v2->uNumMonsters].uMonsterHeight = v9;
+      v11 = atoi(v10);
+      v12 = v25.pProperties[10];
+      v2->pMonsters[v2->uNumMonsters].uMovementSpeed = v11;
+      v13 = atoi(v12);
+      v14 = v25.pProperties[11];
+      v2->pMonsters[v2->uNumMonsters].uMonsterRadius = v13;
+      v15 = atoi(v14);
+      v16 = v25.pProperties[12];
+      v2->pMonsters[v2->uNumMonsters].uToHitRadius = v15;
+      v17 = (unsigned __int8)atoi(v16);
+      Argsb = atoi(v25.pProperties2[0]) & 0xFF;
+      v26 = atoi(v25.pProperties2[1]) & 0xFF;
+      v18 = atoi(v25.pProperties2[2]);
+      v2->pMonsters[v2->uNumMonsters].uTintColor = v18 | ((v26 | ((Argsb | (v17 << 8)) << 8)) << 8);
+      v19 = 0;
+      do
+      {
+        v20 = atoi(v25.pProperties2[v19 + 4]);
+        v21 = v19++ + 76 * v2->uNumMonsters;
+        v2->pMonsters->pSoundSampleIDs[v21] = v20;
+      }
+      while ( v19 < 4 );
+      ++v2->uNumMonsters;
+    }
+  }
+  fclose(File);
+  return 1;
+}
+
+//----- (004598AF) --------------------------------------------------------
+void MonsterList::FromFile(void *pSerialized)
+{
+  uNumMonsters = *(int *)pSerialized;
+  pMonsters = (MonsterDesc *)pAllocator->AllocNamedChunk(pMonsters, 152 * uNumMonsters, "Mon Race");
+  memcpy(pMonsters, (char *)pSerialized + 4, 152 * uNumMonsters);
+}
+
+//----- (00459860) --------------------------------------------------------
+void MonsterList::ToFile()
+{
+  MonsterList *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  v1 = this;
+  v2 = fopen("data\\dmonlist.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dmonlist.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pMonsters, 0x98u, v1->uNumMonsters, v3);
+  fclose(v3);
+}
+
+
+//----- (004563FF) --------------------------------------------------------
+signed int MonsterStats::_4563FF(const char *Str2)
+{
+  MonsterStats *v2; // esi@1
+  signed int v3; // ebx@1
+  MonsterInfo *v4; // edi@2
+  signed int result; // eax@6
+
+  v2 = this;
+  v3 = 1;
+  if ( (signed int)this->uNumMonsters <= 1 )
+  {
+LABEL_6:
+    result = -1;
+  }
+  else
+  {
+    v4 = &this->pInfos[1];
+    while ( !v4->pName || _strcmpi(v4->pTexture, Str2) )
+    {
+      ++v3;
+      ++v4;
+      if ( v3 >= (signed int)v2->uNumMonsters )
+        goto LABEL_6;
+    }
+    result = v3;
+  }
+  return result;
+}
+
+
+//----- (00454F4E) --------------------------------------------------------
+void MonsterStats::InitializePlacements()
+{
+  char *v1; // ebx@1
+  MonsterStats *v2; // edi@1
+  char *v3; // eax@2
+  char v4; // dl@3
+  char *v5; // ecx@3
+  int v6; // esi@7
+  signed int v7; // [sp+Ch] [bp-10h]@1
+  char **v8; // [sp+10h] [bp-Ch]@1
+  signed int v9; // [sp+14h] [bp-8h]@2
+  char *v10; // [sp+18h] [bp-4h]@2
+
+  v1 = 0;
+  v2 = this;
+  pMonsterPlacementTXT_Raw = (char *)pEvents_LOD->LoadRaw("placemon.txt", 0);
+  strtok(pMonsterPlacementTXT_Raw, "\r");
+  v2->uNumPlacements = 31;
+  v8 = v2->pPlacement.pSubstrings;
+  v7 = 30;
+  do
+  {
+    v3 = strtok(v1, "\r") + 1;
+    v10 = v1;
+    v9 = (signed int)v1;
+    do
+    {
+      v4 = *v3;
+      v5 = 0;
+      if ( *v3 != 9 )
+      {
+        v1 = 0;
+        do
+        {
+          if ( !v4 )
+            break;
+          ++v5;
+          v4 = v3[(unsigned int)v5];
+        }
+        while ( v4 != 9 );
+      }
+      v6 = (int)&v3[(unsigned int)v5];
+      if ( v3[(unsigned int)v5] == (unsigned char)v1 )
+        v9 = 1;
+      *(unsigned char *)v6 = (unsigned char)v1;
+      if ( v5 == v1 )
+      {
+        v9 = 1;
+      }
+      else
+      {
+        if ( v10 == (char *)1 )
+          *v8 = (char *)RemoveQuotes(v3);
+      }
+      ++v10;
+      v3 = (char *)(v6 + 1);
+    }
+    while ( (signed int)(v10 - 1) <= 31 && (char *)v9 == v1 );
+    ++v8;
+    --v7;
+  }
+  while ( v7 );
+  v2->uNumPlacements = 31;
+}
+
+//----- (0045501E) --------------------------------------------------------
+void MonsterStats::Initialize()
+{
+  MonsterStats *v1; // ebx@1
+  int v2; // ebx@4
+  char v3; // cl@5
+  int v4; // eax@5
+  size_t v5; // eax@19
+  signed int v6; // edi@19
+  MonsterStats *v7; // ecx@23
+  int v8; // eax@23
+  unsigned int *pHP; // esi@23
+  size_t v10; // eax@29
+  signed int v11; // edi@29
+  MonsterStats *v12; // ecx@33
+  int v13; // eax@33
+  unsigned int *pExp; // esi@33
+  signed int v15; // edi@36
+  size_t v16; // esi@36
+  int v17; // eax@37
+  MonsterInfo *v18; // esi@45
+  size_t v19; // edi@50
+  int v20; // eax@51
+  unsigned __int8 v21; // al@55
+  size_t v22; // edi@59
+  char v23; // cl@63
+  const char *v24; // edi@63
+  unsigned __int16 *v25; // esi@114
+  int v26; // eax@118
+  size_t v27; // eax@136
+  int v28; // edi@137
+  MonsterStats *v29; // esi@137
+  int v30; // eax@138
+  int v31; // eax@142
+  int v32; // eax@143
+  int v33; // eax@144
+  int v34; // eax@151
+  int v35; // eax@152
+  int v36; // eax@153
+  int v37; // eax@162
+  int v38; // eax@163
+  int v39; // eax@164
+  int v40; // eax@171
+  int v41; // eax@172
+  size_t v42; // eax@180
+  int v43; // edi@180
+  MonsterInfo *v44; // esi@180
+  int v45; // edi@184
+  MonsterInfo *v46; // eax@232
+  char *v47; // edx@232
+  char *v48; // ecx@232
+  MonsterInfo *v49; // eax@236
+  FrameTableTxtLine *v50; // esi@240
+  int v51; // eax@240
+  int v52; // eax@241
+  int v53; // esi@242
+  int v54; // edi@242
+  char v55; // al@242
+  char *v56; // edi@242
+  FrameTableTxtLine *v57; // esi@249
+  int v58; // eax@249
+  MonsterInfo *v59; // eax@250
+  MonsterInfo *v60; // esi@251
+  int v61; // edi@251
+  char v62; // al@251
+  char *v63; // edi@251
+  char v64; // al@258
+  char v65; // al@262
+  char v66; // al@266
+  char v67; // al@270
+  char v68; // al@274
+  char v69; // al@278
+  char v70; // al@282
+  char v71; // al@286
+  char v72; // al@290
+  unsigned __int8 v73; // al@294
+  int v74; // edi@298
+  MonsterInfo *v75; // esi@300
+  MonsterInfo *v76; // esi@302
+  char **v77; // edi@306
+  __int16 v78; // ax@316
+  MonsterInfo *v79; // esi@323
+  const char *v80; // ecx@323
+  std::string v81; // [sp-14h] [bp-46Ch]@317
+  const char *v82; // [sp-8h] [bp-460h]@306
+  char *v83; // [sp-4h] [bp-45Ch]@23
+  char *v84; // [sp+0h] [bp-458h]@37
+  FrameTableTxtLine v85; // [sp+10h] [bp-448h]@297
+  FrameTableTxtLine v86; // [sp+8Ch] [bp-3CCh]@249
+  FrameTableTxtLine v87; // [sp+108h] [bp-350h]@240
+  char Src[120]; // [sp+184h] [bp-2D4h]@317
+  FrameTableTxtLine v89; // [sp+1FCh] [bp-25Ch]@249
+  FrameTableTxtLine v90; // [sp+278h] [bp-1E0h]@240
+  char Str[64]; // [sp+2F4h] [bp-164h]@240
+  char Dest[64]; // [sp+334h] [bp-124h]@249
+  char v93[64]; // [sp+374h] [bp-E4h]@297
+  FrameTableTxtLine v94; // [sp+3B4h] [bp-A4h]@297
+  int v95; // [sp+430h] [bp-28h]@317
+  int v96; // [sp+434h] [bp-24h]@9
+  int v97; // [sp+438h] [bp-20h]@4
+  char a3[5]; // [sp+43Fh] [bp-19h]@4
+  int a2; // [sp+444h] [bp-14h]@36
+  int v100; // [sp+448h] [bp-10h]@36
+  size_t v101; // [sp+44Ch] [bp-Ch]@19
+  MonsterStats *v102; // [sp+450h] [bp-8h]@1
+  int v103; // [sp+454h] [bp-4h]@3
+
+  v1 = this;
+  v102 = this;
+  if ( pMonstersTXT_Raw )
+    pAllocator->FreeChunk(pMonstersTXT_Raw);
+  pMonstersTXT_Raw = 0;
+  pMonstersTXT_Raw = (char *)pEvents_LOD->LoadRaw("monsters.txt", 0);
+  strtok(pMonstersTXT_Raw, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  v103 = 0;
+  v1->uNumMonsters = 265;
+  do
+  {
+    v2 = (int)(strtok(0, "\r") + 1);
+    *(_DWORD *)&a3[1] = 0;
+    v97 = 0;
+    do
+    {
+      v3 = *(_BYTE *)v2;
+      v4 = 0;
+      while ( v3 != 9 && v3 )
+      {
+        ++v4;
+        v3 = *(_BYTE *)(v4 + v2);
+      }
+      v96 = v4 + v2;
+      if ( !*(_BYTE *)(v4 + v2) )
+        v97 = 1;
+      *(_BYTE *)(v4 + v2) = 0;
+      if ( v4 )
+      {
+        switch ( *(_DWORD *)&a3[1] )
+        {
+          case 0:
+            v103 = atoi((const char *)v2);
+            v102->pInfos[v103].uID = v103;
+            goto LABEL_325;
+          case 2:
+            v102->pInfos[v103].pTexture = RemoveQuotes((char *)v2);
+            goto LABEL_325;
+          case 1:
+            v102->pInfos[v103].pName = RemoveQuotes((char *)v2);
+            goto LABEL_325;
+          case 3:
+            v102->pInfos[v103].uLevel = atoi((const char *)v2);
+            goto LABEL_325;
+          case 4:
+            if ( *(_BYTE *)v2 == 34 )
+              *(_BYTE *)v2 = 32;
+            v5 = strlen((const char *)v2);
+            v6 = 0;
+            v101 = v5;
+            if ( (signed int)v5 <= 0 )
+              goto LABEL_24;
+            while ( *(_BYTE *)(v6 + v2) != 44 )
+            {
+              ++v6;
+              if ( v6 >= (signed int)v5 )
+                goto LABEL_24;
+            }
+            v7 = v102;
+            v8 = v103;
+            *(_BYTE *)(v6 + v2) = 0;
+            pHP = &v7->pInfos[v8].uHP;
+            *pHP = 1000 * atoi((const char *)v2);
+            v83 = (char *)(v6 + v2 + 1);
+            *(_BYTE *)(v6 + v2) = 44;
+            *pHP += atoi(v83);
+LABEL_24:
+            if ( v6 == v101 )
+              v102->pInfos[v103].uHP = atoi((const char *)v2);
+            goto LABEL_325;
+          case 5:
+            v102->pInfos[v103].uAC = atoi((const char *)v2);
+            goto LABEL_325;
+          case 6:
+            if ( *(_BYTE *)v2 == 34 )
+              *(_BYTE *)v2 = 32;
+            v10 = strlen((const char *)v2);
+            v11 = 0;
+            v101 = v10;
+            if ( (signed int)v10 <= 0 )
+              goto LABEL_34;
+            while ( *(_BYTE *)(v11 + v2) != 44 )
+            {
+              ++v11;
+              if ( v11 >= (signed int)v10 )
+                goto LABEL_34;
+            }
+            v12 = v102;
+            v13 = v103;
+            *(_BYTE *)(v11 + v2) = 0;
+            pExp = &v12->pInfos[v13].uExp;
+            *pExp = 1000 * atoi((const char *)v2);
+            v83 = (char *)(v11 + v2 + 1);
+            *(_BYTE *)(v11 + v2) = 44;
+            *pExp += atoi(v83);
+LABEL_34:
+            if ( v11 == v101 )
+              v102->pInfos[v103].uExp = atoi((const char *)v2);
+            goto LABEL_325;
+          case 7:
+            v15 = 0;
+            a2 = 0;
+            v100 = 0;
+            v16 = 0;
+            v101 = strlen((const char *)v2);
+            if ( (signed int)v101 <= 0 )
+              goto LABEL_325;
+            do
+            {
+              v84 = (char *)*(_BYTE *)(v16 + v2);
+              v17 = tolower((int)v84);
+              switch ( v17 )
+              {
+                case 37:
+                  v15 = 1;
+                  break;
+                case 100:
+                  v100 = 1;
+                  break;
+                case 108:
+                  a2 = 1;
+                  break;
+              }
+              ++v16;
+            }
+            while ( (signed int)v16 < (signed int)v101 );
+            if ( v15 )
+            {
+              v18 = &v102->pInfos[v103];
+              v18->uTreasureDropChance = atoi((const char *)v2);
+            }
+            else
+            {
+              if ( !v100 && !a2 )
+                goto LABEL_325;
+              v18 = &v102->pInfos[v103];
+              v18->uTreasureDropChance = 100;
+            }
+            if ( v100 )
+            {
+              v19 = 0;
+              v100 = 0;
+              do
+              {
+                v84 = (char *)*(_BYTE *)(v19 + v2);
+                v20 = tolower((int)v84);
+                if ( v20 == 37 )
+                {
+                  v84 = (char *)(v19 + v2 + 1);
+                  v18->uTreasureDiceRolls = atoi(v84);
+                  v100 = 1;
+                }
+                else
+                {
+                  if ( v20 == 100 )
+                  {
+                    if ( !v100 )
+                      v18->uTreasureDiceRolls = atoi((const char *)v2);
+                    v84 = (char *)(v19 + v2 + 1);
+                    v21 = atoi(v84);
+                    v19 = v101;
+                    v18->uTreasureDiceSides = v21;
+                  }
+                }
+                ++v19;
+              }
+              while ( (signed int)v19 < (signed int)v101 );
+            }
+            if ( a2 )
+            {
+              v22 = 0;
+              while ( 1 )
+              {
+                v84 = (char *)*(_BYTE *)(v22 + v2);
+                if ( tolower((int)v84) == 108 )
+                  break;
+                ++v22;
+                if ( (signed int)v22 >= (signed int)v101 )
+                  goto LABEL_325;
+              }
+              v23 = *(_BYTE *)(v22 + v2 + 1);
+              v24 = (const char *)(v22 + v2 + 2);
+              v18->uTreasureLevel = v23 - 48;
+              if ( *v24 )
+              {
+                if ( _strcmpi(v24, "WEAPON") )
+                {
+                  if ( _strcmpi(v24, "ARMOR") )
+                  {
+                    if ( _strcmpi(v24, "MISC") )
+                    {
+                      if ( _strcmpi(v24, "SWORD") )
+                      {
+                        if ( _strcmpi(v24, "DAGGER") )
+                        {
+                          if ( _strcmpi(v24, "AXE") )
+                          {
+                            if ( _strcmpi(v24, "SPEAR") )
+                            {
+                              if ( _strcmpi(v24, "BOW") )
+                              {
+                                if ( _strcmpi(v24, "MACE") )
+                                {
+                                  if ( _strcmpi(v24, "CLUB") )
+                                  {
+                                    if ( _strcmpi(v24, "STAFF") )
+                                    {
+                                      if ( _strcmpi(v24, "LEATHER") )
+                                      {
+                                        if ( _strcmpi(v24, "CHAIN") )
+                                        {
+                                          if ( _strcmpi(v24, "PLATE") )
+                                          {
+                                            if ( _strcmpi(v24, "SHIELD") )
+                                            {
+                                              if ( _strcmpi(v24, "HELM") )
+                                              {
+                                                if ( _strcmpi(v24, "BELT") )
+                                                {
+                                                  if ( _strcmpi(v24, "CAPE") )
+                                                  {
+                                                    if ( _strcmpi(v24, "GAUNTLETS") )
+                                                    {
+                                                      if ( _strcmpi(v24, "BOOTS") )
+                                                      {
+                                                        if ( _strcmpi(v24, "RING") )
+                                                        {
+                                                          if ( _strcmpi(v24, "AMULET") )
+                                                          {
+                                                            if ( _strcmpi(v24, "WAND") )
+                                                            {
+                                                              if ( _strcmpi(v24, "SCROLL") )
+                                                              {
+                                                                if ( !_strcmpi(v24, "GEM") )
+                                                                  v18->uTreasureType = 46;
+                                                              }
+                                                              else
+                                                              {
+                                                                v18->uTreasureType = 43;
+                                                              }
+                                                            }
+                                                            else
+                                                            {
+                                                              v18->uTreasureType = 42;
+                                                            }
+                                                          }
+                                                          else
+                                                          {
+                                                            v18->uTreasureType = 41;
+                                                          }
+                                                        }
+                                                        else
+                                                        {
+                                                          v18->uTreasureType = 40;
+                                                        }
+                                                      }
+                                                      else
+                                                      {
+                                                        v18->uTreasureType = 39;
+                                                      }
+                                                    }
+                                                    else
+                                                    {
+                                                      v18->uTreasureType = 38;
+                                                    }
+                                                  }
+                                                  else
+                                                  {
+                                                    v18->uTreasureType = 37;
+                                                  }
+                                                }
+                                                else
+                                                {
+                                                  v18->uTreasureType = 36;
+                                                }
+                                              }
+                                              else
+                                              {
+                                                v18->uTreasureType = 35;
+                                              }
+                                            }
+                                            else
+                                            {
+                                              v18->uTreasureType = 34;
+                                            }
+                                          }
+                                          else
+                                          {
+                                            v18->uTreasureType = 33;
+                                          }
+                                        }
+                                        else
+                                        {
+                                          v18->uTreasureType = 32;
+                                        }
+                                      }
+                                      else
+                                      {
+                                        v18->uTreasureType = 31;
+                                      }
+                                    }
+                                    else
+                                    {
+                                      v18->uTreasureType = 30;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    v18->uTreasureType = 29;
+                                  }
+                                }
+                                else
+                                {
+                                  v18->uTreasureType = 28;
+                                }
+                              }
+                              else
+                              {
+                                v18->uTreasureType = 27;
+                              }
+                            }
+                            else
+                            {
+                              v18->uTreasureType = 26;
+                            }
+                          }
+                          else
+                          {
+                            v18->uTreasureType = 25;
+                          }
+                        }
+                        else
+                        {
+                          v18->uTreasureType = 24;
+                        }
+                      }
+                      else
+                      {
+                        v18->uTreasureType = 23;
+                      }
+                    }
+                    else
+                    {
+                      v18->uTreasureType = 22;
+                    }
+                  }
+                  else
+                  {
+                    v18->uTreasureType = 21;
+                  }
+                }
+                else
+                {
+                  v18->uTreasureType = 20;
+                }
+              }
+            }
+            goto LABEL_325;
+          case 8:
+            v84 = (char *)v2;
+            v25 = &v102->pInfos[v103].bQuestMonster;
+            *v25 = 0;
+            if ( atoi(v84) )
+              *(_BYTE *)v25 |= 1u;
+            goto LABEL_325;
+          case 9:
+            v102->pInfos[v103].uFlying = _strnicmp((const char *)v2, "n", 1u);
+            goto LABEL_325;
+          case 0xA:
+            v84 = (char *)*(_BYTE *)v2;
+            v101 = 4;
+            if ( tolower((int)v84) == 's' )
+            {
+              v84 = (char *)*(_BYTE *)(v2 + 1);
+              v26 = tolower((int)v84) != 'h' ? 5 : 0;
+            }
+            else
+            {
+              v84 = (char *)*(_BYTE *)v2;
+              if ( tolower((int)v84) == 'm' )
+              {
+                v101 = 1;
+              }
+              else
+              {
+                v84 = (char *)*(_BYTE *)v2;
+                if ( tolower((int)v84) == 'l' )
+                {
+                  v101 = 2;
+                }
+                else
+                {
+                  v84 = (char *)*(_BYTE *)v2;
+                  if ( tolower((int)v84) == 'g' )
+                    v101 = 3;
+                }
+              }
+              LOBYTE(v26) = v101;
+            }
+            v102->pInfos[v103].uMovementType = v26;
+            goto LABEL_325;
+          case 0xB:
+            v84 = (char *)*(_BYTE *)v2;
+            v101 = 3;
+            if ( tolower((int)v84) == 's' )
+            {
+              v101 = 0;
+            }
+            else
+            {
+              v84 = (char *)*(_BYTE *)v2;
+              if ( tolower((int)v84) == 'w' )
+              {
+                v101 = 1;
+              }
+              else
+              {
+                v84 = (char *)*(_BYTE *)v2;
+                if ( tolower((int)v84) == 'n' )
+                  v101 = 2;
+              }
+            }
+            v102->pInfos[v103].uAIType = v101;
+            goto LABEL_325;
+          case 0xC:
+            v102->pInfos[v103].uHostilityType = (MonsterInfo::HostilityRadius)atoi((const char *)v2);
+            goto LABEL_325;
+          case 0xD:
+            v102->pInfos[v103].uBaseSpeed = atoi((const char *)v2);
+            goto LABEL_325;
+          case 0xF:
+            v27 = strlen((const char *)v2);
+            v100 = 0;
+            v101 = v27;
+            if ( (signed int)v27 > 0 )
+            {
+              v28 = v103;
+              v29 = v102;
+              do
+              {
+                v84 = (char *)*(_BYTE *)(v100 + v2);
+                v30 = tolower((int)v84);
+                if ( v30 > 107 )
+                {
+                  if ( v30 > 115 )
+                  {
+                    v40 = v30 - 116;
+                    if ( v40 )
+                    {
+                      v41 = v40 - 3;
+                      if ( v41 )
+                      {
+                        if ( v41 == 1 )
+                          BYTE1(v29->pInfos[v28].uAttackPreference) |= 2u;
+                      }
+                      else
+                      {
+                        BYTE1(v29->pInfos[v28].uAttackPreference) |= 0x20u;
+                      }
+                    }
+                    else
+                    {
+                      LOBYTE(v29->pInfos[v28].uAttackPreference) |= 0x80u;
+                    }
+                  }
+                  else
+                  {
+                    if ( v30 == 115 )
+                    {
+                      v29->pInfos[v28].uAttackPreference |= 0x20u;
+                    }
+                    else
+                    {
+                      v37 = v30 - 109;
+                      if ( v37 )
+                      {
+                        v38 = v37 - 2;
+                        if ( v38 )
+                        {
+                          v39 = v38 - 1;
+                          if ( v39 )
+                          {
+                            if ( v39 == 2 )
+                              v29->pInfos[v28].uAttackPreference |= 0x40u;
+                          }
+                          else
+                          {
+                            v29->pInfos[v28].uAttackPreference |= 2u;
+                          }
+                        }
+                        else
+                        {
+                          BYTE1(v29->pInfos[v28].uAttackPreference) |= 4u;
+                        }
+                      }
+                      else
+                      {
+                        BYTE1(v29->pInfos[v28].uAttackPreference) |= 1u;
+                      }
+                    }
+                  }
+                }
+                else
+                {
+                  if ( v30 == 107 )
+                  {
+                    v29->pInfos[v28].uAttackPreference |= 1u;
+                  }
+                  else
+                  {
+                    if ( v30 > 99 )
+                    {
+                      v34 = v30 - 100;
+                      if ( v34 )
+                      {
+                        v35 = v34 - 1;
+                        if ( v35 )
+                        {
+                          v36 = v35 - 2;
+                          if ( v36 )
+                          {
+                            if ( v36 == 1 )
+                              BYTE1(v29->pInfos[v28].uAttackPreference) |= 8u;
+                          }
+                          else
+                          {
+                            BYTE1(v29->pInfos[v28].uAttackPreference) |= 0x40u;
+                          }
+                        }
+                        else
+                        {
+                          BYTE1(v29->pInfos[v28].uAttackPreference) |= 0x10u;
+                        }
+                      }
+                      else
+                      {
+                        v29->pInfos[v28].uAttackPreference |= 8u;
+                      }
+                    }
+                    else
+                    {
+                      if ( v30 == 99 )
+                      {
+                        v29->pInfos[v28].uAttackPreference |= 0x10u;
+                      }
+                      else
+                      {
+                        v31 = v30 - 50;
+                        if ( v31 )
+                        {
+                          v32 = v31 - 1;
+                          if ( v32 )
+                          {
+                            v33 = v32 - 1;
+                            if ( v33 )
+                            {
+                              if ( v33 == 45 )
+                                v29->pInfos[v28].uAttackPreference |= 4u;
+                            }
+                            else
+                            {
+                              v29->pInfos[v28].uNumCharactersAttackedPerSpecialAbility = 4;
+                            }
+                          }
+                          else
+                          {
+                            v29->pInfos[v28].uNumCharactersAttackedPerSpecialAbility = 3;
+                          }
+                        }
+                        else
+                        {
+                          v29->pInfos[v28].uNumCharactersAttackedPerSpecialAbility = 2;
+                        }
+                      }
+                    }
+                  }
+                }
+                ++v100;
+              }
+              while ( v100 < (signed int)v101 );
+            }
+            goto LABEL_325;
+          case 0xE:
+            v102->pInfos[v103].uRecoveryTime = atoi((const char *)v2);
+            goto LABEL_325;
+          case 0x10:
+            v42 = strlen((const char *)v2);
+            v43 = 0;
+            v44 = &v102->pInfos[v103];
+            v100 = v42;
+            v44->uSpecialAttackType = 1;
+            if ( (signed int)v42 <= 0 )
+              goto LABEL_185;
+            break;
+          case 0x11:
+            v102->pInfos[v103].uAttack1Type = ParseAttackType((unsigned __int8 *)v2);
+            goto LABEL_325;
+          case 0x12:
+            v46 = &v102->pInfos[v103];
+            v47 = (char *)&v46->uAttack1DamageDiceRolls;
+            v84 = (char *)&v46->uAttack1DamageBonus;
+            v48 = (char *)&v46->uAttack1DamageDiceSides;
+            goto LABEL_237;
+          case 0x13:
+            v102->pInfos[v103].uMissleAttack1Type = ParseMissleAttackType((const char *)v2);
+            goto LABEL_325;
+          case 0x14:
+            v102->pInfos[v103].uAttack2Chance = atoi((const char *)v2);
+            goto LABEL_325;
+          case 0x15:
+            v102->pInfos[v103].uAttack2Type = ParseAttackType((unsigned __int8 *)v2);
+            goto LABEL_325;
+          case 0x16:
+            v49 = &v102->pInfos[v103];
+            v47 = (char *)&v49->uAttack2DamageDiceRolls;
+            v84 = (char *)&v49->uAttack2DamageBonus;
+            v48 = (char *)&v49->uAttack2DamageDiceSides;
+LABEL_237:
+            ParseDamage((const char *)v2, (int)v47, (int)v48, (int)v84);
+            goto LABEL_325;
+          case 0x17:
+            v102->pInfos[v103].uMissleAttack2Type = ParseMissleAttackType((const char *)v2);
+            goto LABEL_325;
+          case 0x18:
+            v102->pInfos[v103].uSpell1UseChance = atoi((const char *)v2);
+            goto LABEL_325;
+          case 0x19:
+            strcpy(Str, (const char *)v2);
+            Str[0] = ' ';
+            Str[strlen(Str) - 1] = ' ';
+            v50 = texture_frame_table_txt_parser(Str, &v87);
+            v51 = 88 * v103;
+            memcpy(&v90, v50, sizeof(v90));
+            if ( v90.field_0 >= 3 )
+            {
+              v53 = (int)((char *)v102 + v51);
+              a2 = 1;
+              v102->pInfos[v51 / 0x58u].uSpell1ID = ParseSpellType(&v90, (int)&a2);
+              v54 = a2;
+              v84 = (char *)v90.pProperties[a2 + 1];
+              v55 = atoi(v84);
+              v56 = (char *)v90.pProperties[v54];
+              v84 = "E";
+              v83 = v56;
+              *(_WORD *)(v53 + 56) = v55 & 0x3F;
+              if ( _strcmpi(v83, v84) )
+              {
+                if ( _strcmpi(v56, "M") )
+                {
+                  if ( !_strcmpi(v56, "G") )
+                    *(_BYTE *)(v53 + 57) |= 1u;
+                }
+                else
+                {
+                  *(_BYTE *)(v53 + 56) |= 0x80u;
+                }
+              }
+              else
+              {
+                *(_BYTE *)(v53 + 56) |= 0x40u;
+              }
+            }
+            else
+            {
+              v52 = (int)((char *)v102 + v51);
+              *(_BYTE *)(v52 + 33) = 0;
+              *(_WORD *)(v52 + 56) = 0;
+            }
+            goto LABEL_325;
+          case 0x1A:
+            v102->pInfos[v103].uSpell2UseChance = atoi((const char *)v2);
+            goto LABEL_325;
+          case 0x1B:
+            strcpy(Dest, (const char *)v2);
+            Dest[0] = ' ';
+            Dest[strlen(Dest) - 1] = ' ';
+            v57 = texture_frame_table_txt_parser(Dest, &v86);
+            v58 = v103;
+            memcpy(&v89, v57, sizeof(v89));
+            if ( v89.field_0 >= 3 )
+            {
+              v60 = &v102->pInfos[v58];
+              a2 = 1;
+              v102->pInfos[v58].uSpell2ID = ParseSpellType(&v89, (int)&a2);
+              v61 = a2;
+              v84 = (char *)v89.pProperties[a2 + 1];
+              v62 = atoi(v84);
+              v63 = (char *)v89.pProperties[v61];
+              v84 = "E";
+              v83 = v63;
+              v60->uSpellSkillAndMastery2 = v62 & 0x3F;
+              if ( _strcmpi(v83, v84) )
+              {
+                if ( _strcmpi(v63, "M") )
+                {
+                  if ( !_strcmpi(v63, "G") )
+                    HIBYTE(v60->uSpellSkillAndMastery2) |= 1u;
+                }
+                else
+                {
+                  LOBYTE(v60->uSpellSkillAndMastery2) |= 0x80u;
+                }
+              }
+              else
+              {
+                LOBYTE(v60->uSpellSkillAndMastery2) |= 0x40u;
+              }
+            }
+            else
+            {
+              v59 = &v102->pInfos[v58];
+              v59->uSpell2ID = 0;
+              v59->uSpellSkillAndMastery2 = 0;
+            }
+            goto LABEL_325;
+          case 0x1C:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v64 = 200;
+            else
+              v64 = atoi((const char *)v2);
+            v102->pInfos[v103].uResFire = v64;
+            goto LABEL_325;
+          case 0x1D:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v65 = 200;
+            else
+              v65 = atoi((const char *)v2);
+            v102->pInfos[v103].uResAir = v65;
+            goto LABEL_325;
+          case 0x1E:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v66 = 200;
+            else
+              v66 = atoi((const char *)v2);
+            v102->pInfos[v103].uResWater = v66;
+            goto LABEL_325;
+          case 0x1F:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v67 = 200;
+            else
+              v67 = atoi((const char *)v2);
+            v102->pInfos[v103].uResEarth = v67;
+            goto LABEL_325;
+          case 0x20:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v68 = 200;
+            else
+              v68 = atoi((const char *)v2);
+            v102->pInfos[v103].uResMind = v68;
+            goto LABEL_325;
+          case 0x21:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v69 = 200;
+            else
+              v69 = atoi((const char *)v2);
+            v102->pInfos[v103].uResSpirit = v69;
+            goto LABEL_325;
+          case 0x22:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v70 = 200;
+            else
+              v70 = atoi((const char *)v2);
+            v102->pInfos[v103].uResBody = v70;
+            goto LABEL_325;
+          case 0x23:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v71 = 200;
+            else
+              v71 = atoi((const char *)v2);
+            v102->pInfos[v103].uResLight = v71;
+            goto LABEL_325;
+          case 0x24:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v72 = 200;
+            else
+              v72 = atoi((const char *)v2);
+            v102->pInfos[v103].uResDark = v72;
+            goto LABEL_325;
+          case 0x25:
+            v84 = (char *)*(_BYTE *)v2;
+            if ( tolower((int)v84) == 'i' )
+              v73 = 200;
+            else
+              v73 = atoi((const char *)v2);
+            v102->pInfos[v103].uResPhysical = v73;
+            goto LABEL_325;
+          case 0x26:
+            strcpy(v93, (const char *)v2);
+            v93[0] = ' ';
+            v93[strlen(v93) - 1] = ' ';
+            memcpy(&v94, texture_frame_table_txt_parser(v93, &v85), sizeof(v94));
+            if ( v94.field_0 )
+            {
+              v74 = v94.field_0;
+              if ( v94.field_0 < 10 )
+              {
+                if ( _strcmpi(v94.pProperties[0], "shot") )
+                {
+                  if ( _strcmpi(v94.pProperties[0], "summon") )
+                  {
+                    if ( !_strcmpi(v94.pProperties[0], "explode") )
+                    {
+                      v79 = &v102->pInfos[v103];
+                      v80 = v94.pProperties[1];
+                      v84 = (char *)&v79->uSpecialAbilityDamageDiceBonus;
+                      v83 = (char *)&v79->uSpecialAbilityDamageDiceSides;
+                      v79->uSpecialAbilityType = 3;
+                      ParseDamage(v80, (int)&v79->uSpecialAbilityDamageDiceRolls, (int)v83, (int)v84);
+                      v79->field_3C_some_special_attack = ParseAttackType((unsigned __int8 *)v2);
+                    }
+                  }
+                  else
+                  {
+                    v76 = &v102->pInfos[v103];
+                    v76->uSpecialAbilityType = 2;
+                    if ( v74 > 1 )
+                    {
+                      pTmpBuf[0] = 0;
+                      strcpy(pTmpBuf, v94.pProperties[2]);
+                      if ( v74 > 2 )
+                      {
+                        v100 = 3;
+                        if ( v74 > 3 )
+                        {
+                          do
+                          {
+                            strcat(pTmpBuf, " ");
+                            v77 = (char **)v94.pProperties[v100];
+                            v82 = v94.pProperties[v100];
+                            strcat(pTmpBuf, v82);
+                            if ( v100 == v94.field_0 - 1 )
+                            {
+                              v84 = (char *)*(_BYTE *)v77;
+                              if ( tolower((int)v84) == 'a' )
+                              {
+                                v76->uSpecialAbilityDamageDiceRolls = 1;
+                              }
+                              else
+                              {
+                                v84 = (char *)*(_BYTE *)v77;
+                                if ( tolower((int)v84) == 'b' )
+                                {
+                                  v76->uSpecialAbilityDamageDiceRolls = 2;
+                                }
+                                else
+                                {
+                                  v84 = (char *)*(_BYTE *)v77;
+                                  if ( tolower((int)v84) == 'c' )
+                                    v76->uSpecialAbilityDamageDiceRolls = 3;
+                                  else
+                                    v76->uSpecialAbilityDamageDiceRolls = 0;
+                                }
+                              }
+                            }
+                            ++v100;
+                          }
+                          while ( v100 < v94.field_0 );
+                        }
+                      }
+                      else
+                      {
+                        v76->uSpecialAbilityDamageDiceRolls = 0;
+                      }
+                      if ( pMonsterList->uNumMonsters )
+                      {
+                        v78 = pMonsterList->GetMonsterByName(pTmpBuf) + 1;
+                        v76->field_3C_some_special_attack = v78;
+                        if ( v78 == -1 )
+                        {
+                          sprintf(Src, "Can't create random monster: '%s' See MapStats!", Src);
+                          MessageBoxA(nullptr, Src, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Itemdata.cpp:2239", 0);
+                        }
+                      }
+                      v76->uSpecialAbilityDamageDiceSides = 0;
+                      if ( !_strcmpi(v94.pProperties[1], "ground") )
+                        v76->uSpecialAbilityDamageDiceSides = 1;
+                      if ( v76->field_3C_some_special_attack == -1 )
+                        v76->uSpecialAbilityType = 0;
+                    }
+                  }
+                }
+                else
+                {
+                  v75 = &v102->pInfos[v103];
+                  v84 = (char *)(v94.pProperties[1] + 1);
+                  v75->uSpecialAbilityType = 1;
+                  v75->uSpecialAbilityDamageDiceBonus = atoi(v84);
+                }
+              }
+            }
+            goto LABEL_325;
+          default:
+            goto LABEL_325;
+        }
+        while ( 1 )
+        {
+          v84 = (char *)*(_BYTE *)(v43 + v2);
+          if ( tolower((int)v84) == 'x' )
+            break;
+          ++v43;
+          if ( v43 >= v100 )
+            goto LABEL_185;
+        }
+        v45 = v2 + v43;
+        *(_BYTE *)v45 = 0;
+        v44->uSpecialAttackType = atoi((const char *)(v45 + 1));
+        *(_BYTE *)v45 = 100;
+LABEL_185:
+        _strlwr((char *)v2);
+        if ( strstr((const char *)v2, "curse") )
+        {
+          v44->uSpecialAttack = 1;
+        }
+        else
+        {
+          if ( strstr((const char *)v2, "weak") )
+          {
+            v44->uSpecialAttack = 2;
+          }
+          else
+          {
+            if ( strstr((const char *)v2, "asleep") )
+            {
+              v44->uSpecialAttack = 3;
+            }
+            else
+            {
+              if ( strstr((const char *)v2, "afraid") )
+              {
+                v44->uSpecialAttack = 23;
+              }
+              else
+              {
+                if ( strstr((const char *)v2, "drunk") )
+                {
+                  v44->uSpecialAttack = 4;
+                }
+                else
+                {
+                  if ( strstr((const char *)v2, "insane") )
+                  {
+                    v44->uSpecialAttack = 5;
+                  }
+                  else
+                  {
+                    if ( strstr((const char *)v2, "poison1") )
+                    {
+                      v44->uSpecialAttack = 6;
+                    }
+                    else
+                    {
+                      if ( strstr((const char *)v2, "poison2") )
+                      {
+                        v44->uSpecialAttack = 7;
+                      }
+                      else
+                      {
+                        if ( strstr((const char *)v2, "poison3") )
+                        {
+                          v44->uSpecialAttack = 8;
+                        }
+                        else
+                        {
+                          if ( strstr((const char *)v2, "disease1") )
+                          {
+                            v44->uSpecialAttack = 9;
+                          }
+                          else
+                          {
+                            if ( strstr((const char *)v2, "disease2") )
+                            {
+                              v44->uSpecialAttack = 10;
+                            }
+                            else
+                            {
+                              if ( strstr((const char *)v2, "disease3") )
+                              {
+                                v44->uSpecialAttack = 11;
+                              }
+                              else
+                              {
+                                if ( strstr((const char *)v2, "paralyze") )
+                                {
+                                  v44->uSpecialAttack = 12;
+                                }
+                                else
+                                {
+                                  if ( strstr((const char *)v2, "uncon") )
+                                  {
+                                    v44->uSpecialAttack = 13;
+                                  }
+                                  else
+                                  {
+                                    if ( strstr((const char *)v2, "dead") )
+                                    {
+                                      v44->uSpecialAttack = 14;
+                                    }
+                                    else
+                                    {
+                                      if ( strstr((const char *)v2, "stone") )
+                                      {
+                                        v44->uSpecialAttack = 15;
+                                      }
+                                      else
+                                      {
+                                        if ( strstr((const char *)v2, "errad") )
+                                        {
+                                          v44->uSpecialAttack = 16;
+                                        }
+                                        else
+                                        {
+                                          if ( strstr((const char *)v2, "brkitem") )
+                                          {
+                                            v44->uSpecialAttack = 17;
+                                          }
+                                          else
+                                          {
+                                            if ( strstr((const char *)v2, "brkarmor") )
+                                            {
+                                              v44->uSpecialAttack = 18;
+                                            }
+                                            else
+                                            {
+                                              if ( strstr((const char *)v2, "brkweapon") )
+                                              {
+                                                v44->uSpecialAttack = 19;
+                                              }
+                                              else
+                                              {
+                                                if ( strstr((const char *)v2, "steal") )
+                                                {
+                                                  v44->uSpecialAttack = 20;
+                                                }
+                                                else
+                                                {
+                                                  if ( strstr((const char *)v2, "age") )
+                                                  {
+                                                    v44->uSpecialAttack = 21;
+                                                  }
+                                                  else
+                                                  {
+                                                    if ( strstr((const char *)v2, "drainsp") )
+                                                      v44->uSpecialAttack = 22;
+                                                  }
+                                                }
+                                              }
+                                            }
+                                          }
+                                        }
+                                      }
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      else
+      {
+        v97 = 1;
+      }
+LABEL_325:
+      ++*(_DWORD *)&a3[1];
+      v2 = v96 + 1;
+    }
+    while ( *(_DWORD *)&a3[1] - 1 <= (signed int)v102->uNumMonsters && !v97 );
+    ++v103;
+  }
+  while ( v103 < 265 );
+  v102->uNumMonsters = v103;
+}
+
+
+
+
+//----- (0044FA08) --------------------------------------------------------
+unsigned __int16 MonsterList::GetMonsterByName(const char *pMonsterName)
+{
+  signed int v2; // ebx@1
+  MonsterList *v3; // esi@1
+  int v4; // edi@3
+  unsigned __int16 result; // ax@6
+
+  v2 = 0;
+  v3 = this;
+  if ( pMonsterName && (signed int)this->uNumMonsters > 0 )
+  {
+    v4 = 0;
+    while ( _strcmpi(pMonsterName, v3->pMonsters[v4].pMonsterName) )
+    {
+      ++v2;
+      ++v4;
+      if ( v2 >= (signed int)v3->uNumMonsters )
+        goto LABEL_6;
+    }
+    result = v2;
+  }
+  else
+  {
+LABEL_6:
+    result = -1;
+  }
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Monsters.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,206 @@
+#pragma once
+
+
+
+/*  334 */
+enum MONSTER_TYPE
+{
+  MONSTER_DEVIL_1 = 0x16,
+  MONSTER_DEVIL_3 = 0x18,
+  MONSTER_DRAGON_1 = 0x19,
+  MONSTER_DRAGON_3 = 0x1B,
+  MONSTER_ELEMENTAL_WATER_1 = 0x2E,
+  MONSTER_ELEMENTAL_WATER_3 = 0x30,
+  MONSTER_ELF_ARCHER_1 = 0x31,
+  MONSTER_ELF_ARCHER_3 = 0x33,
+  MONSTER_ELF_SPEARMAN_1 = 0x34,
+  MONSTER_ELF_SPEARMAN_3 = 0x36,
+  MONSTER_GHOST_1 = 0x46,
+  MONSTER_GHOST_3 = 0x48,
+  MONSTER_HARPY_1 = 0x55,
+  MONSTER_HARPY_3 = 0x57,
+  MONSTER_LICH_1 = 0x5B,
+  MONSTER_LICH_3 = 0x5D,
+  MONSTER_OOZE_1 = 0x70,
+  MONSTER_OOZE_3 = 0x72,
+  MONSTER_PEASANT_ELF_FEMALE_1_1 = 0x85,
+  MONSTER_PEASANT_ELF_MALE_3_3 = 0x96,
+  MONSTER_SKELETON_1 = 0xC7,
+  MONSTER_SKELETON_3 = 0xC9,
+  MONSTER_TITAN_1 = 0xD3,
+  MONSTER_TITAN_3 = 0xD5,
+  MONSTER_VAMPIRE_1 = 0xD9,
+  MONSTER_VAMPIRE_3 = 0xDB,
+  MONSTER_WIGHT_1 = 0xDF,
+  MONSTER_WIGHT_3 = 0xE1,
+  MONSTER_ZOMBIE_1 = 0xE5,
+  MONSTER_ZOMBIE_3 = 0xE7,
+  MONSTER_PEASANT_GOBLIN_MALE_3_3 = 0xF9,
+  MONSTER_TROLL_3 = 0xFC,
+  MONSTER_TREANT_1 = 0xFD,
+  MONSTER_TREANT_3 = 0xFF,
+  MONSTER_GHOUL_1 = 0x100,
+  MONSTER_GHOUL_3 = 0x102,
+};
+
+/*  335 */
+enum MONSTER_SPECIAL_ABILITY_TYPE
+{
+  MONSTER_SPECIAL_ABILITY_NONE = 0x0,
+  MONSTER_SPECIAL_ABILITY_SHOT = 0x1,
+  MONSTER_SPECIAL_ABILITY_SUMMON = 0x2,
+  MONSTER_SPECIAL_ABILITY_EXPLODE = 0x3,
+};
+
+/*  336 */
+enum MONSTER_SUPERTYPE
+{
+  MONSTER_SUPERTYPE_UNDEAD = 0x1,
+  MONSTER_SUPERTYPE_KREEGAN = 0x2,
+  MONSTER_SUPERTYPE_DRAGON = 0x3,
+  MONSTER_SUPERTYPE_ELF = 0x4,
+  MONSTER_SUPERTYPE_WATER_ELEMENTAL = 0x5,
+  MONSTER_SUPERTYPE_TREANT = 0x6,
+  MONSTER_SUPERTYPE_TITAN = 0x7,
+  MONSTER_SUPERTYPE_8 = 0x8,
+};
+
+
+
+/*  187 */
+#pragma pack(push, 1)
+struct MonsterInfo
+{
+  enum HostilityRadius: unsigned __int8
+  {
+    Hostility_Friendly = 0,
+    Hostility_Close = 1,
+    Hostility_Short = 2,
+    Hostility_Medium = 3,
+    Hostility_Long = 4
+  };
+
+  char *pName;
+  char *pTexture;
+  unsigned __int8 uLevel;
+  unsigned __int8 uTreasureDropChance;
+  unsigned __int8 uTreasureDiceRolls;
+  unsigned __int8 uTreasureDiceSides;
+  unsigned __int8 uTreasureLevel;
+  unsigned __int8 uTreasureType;
+  unsigned __int8 uFlying;
+  unsigned __int8 uMovementType;
+  unsigned __int8 uAIType;
+  HostilityRadius uHostilityType;
+  char field_12;
+  unsigned __int8 uSpecialAttack;
+  unsigned __int8 uSpecialAttackType;
+  unsigned __int8 uAttack1Type;
+  unsigned __int8 uAttack1DamageDiceRolls;
+  unsigned __int8 uAttack1DamageDiceSides;
+  unsigned __int8 uAttack1DamageBonus;
+  unsigned __int8 uMissleAttack1Type;
+  unsigned __int8 uAttack2Chance;
+  unsigned __int8 uAttack2Type;
+  unsigned __int8 uAttack2DamageDiceRolls;
+  unsigned __int8 uAttack2DamageDiceSides;
+  unsigned __int8 uAttack2DamageBonus;
+  unsigned __int8 uMissleAttack2Type;
+  unsigned __int8 uSpell1UseChance;
+  unsigned __int8 uSpell1ID;
+  unsigned __int8 uSpell2UseChance;
+  unsigned __int8 uSpell2ID;
+  unsigned __int8 uResFire;
+  unsigned __int8 uResAir;
+  unsigned __int8 uResWater;
+  unsigned __int8 uResEarth;
+  unsigned __int8 uResMind;
+  unsigned __int8 uResSpirit;
+  unsigned __int8 uResBody;
+  unsigned __int8 uResLight;
+  unsigned __int8 uResDark;
+  unsigned __int8 uResPhysical;
+  unsigned __int8 uSpecialAbilityType;
+  unsigned __int8 uSpecialAbilityDamageDiceRolls;
+  unsigned __int8 uSpecialAbilityDamageDiceSides;
+  unsigned __int8 uSpecialAbilityDamageDiceBonus;
+  unsigned __int8 uNumCharactersAttackedPerSpecialAbility;
+  char field_33;
+  unsigned __int16 uID;
+  unsigned __int16 bQuestMonster;
+  unsigned __int16 uSpellSkillAndMastery1;
+  unsigned __int16 uSpellSkillAndMastery2;
+  __int16 field_3C_some_special_attack;
+  __int16 field_3E;
+  unsigned int uHP;
+  unsigned int uAC;
+  unsigned int uExp;
+  unsigned int uBaseSpeed;
+  unsigned int uRecoveryTime;
+  unsigned int uAttackPreference;
+};
+#pragma pack(pop)
+
+/*  188 */
+#pragma pack(push, 1)
+struct MonsterPlacement
+{
+  unsigned int uNumStrings;
+  char *pSubstrings[30];
+};
+#pragma pack(pop)
+
+/*  189 */
+#pragma pack(push, 1)
+struct MonsterStats
+{
+  void Initialize();
+  void InitializePlacements();
+  signed int _4563FF(const char *Str2);
+
+  static bool BelongsToSupertype(unsigned int uMonsterInfoID, enum MONSTER_SUPERTYPE eSupertype);
+
+  MonsterInfo pInfos[265];
+  MonsterPlacement pPlacement;
+  unsigned int uNumMonsters;
+  unsigned int uNumPlacements;
+  int field_5B9C;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct MonsterDesc
+{
+  unsigned __int16 uMonsterHeight;
+  unsigned __int16 uMonsterRadius;
+  unsigned __int16 uMovementSpeed;
+  __int16 uToHitRadius;
+  unsigned int uTintColor;
+  unsigned __int16 pSoundSampleIDs[4];
+  char pMonsterName[32];
+  char pSpriteNames[10][10];
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct MonsterList
+{
+  inline MonsterList():  //----- (00458429)
+    uNumMonsters(0), pMonsters(nullptr)
+  {}
+  unsigned __int16 GetMonsterByName(const char *pMonsterName);
+  void ToFile();
+  void FromFile(void *pSerialized);
+  bool FromFileTxt(const char *Args);
+
+  unsigned int uNumMonsters;
+  struct MonsterDesc *pMonsters;
+};
+#pragma pack(pop)
+
+
+extern struct MonsterStats *pMonsterStats;
+extern struct MonsterList *pMonsterList;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mouse.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2044 @@
+#include "OSAPI.h"
+
+#include "Mouse.h"
+#include "Items.h"
+#include "Party.h"
+#include "LOD.h"
+#include "Game.h"
+#include "Texture.h"
+
+
+
+
+
+
+
+Mouse *pMouse;
+AsyncMouse *pAsyncMouse;
+
+
+
+
+
+//----- (00469860) --------------------------------------------------------
+void Mouse::GetClickPos(unsigned int *pX, unsigned int *pY)
+{
+  unsigned int v3; // eax@2
+
+  if (pAsyncMouse)
+  {
+    *pX = *((int *)pAsyncMouse + 6);
+    v3 = *((int *)pAsyncMouse + 7);
+  }
+  else
+  {
+    *pX = this->uMouseClickX;
+    v3 = this->uMouseClickY;
+  }
+  *pY = v3;
+}
+
+//----- (004698A6) --------------------------------------------------------
+void Mouse::RemoveHoldingItem()
+{
+  pParty->pPickedItem.Reset();
+  if (strcmpi(pCurrentCursorName, "MICON2"))
+    SetCursorBitmap("MICON1");
+}
+
+//----- (004698D8) --------------------------------------------------------
+void Mouse::SetCursorBitmapFromItemID(unsigned int uItemID)
+{
+  pMouse->SetCursorBitmap(pItemsTable->pItems[uItemID].pIconName);
+}
+
+//----- (004698F6) --------------------------------------------------------
+void Mouse::SetCurrentCursorBitmap()
+{
+  SetCursorBitmap(pCurrentCursorName);
+}
+
+//----- (00469903) --------------------------------------------------------
+void Mouse::SetCursorBitmap(const char *pName)
+{
+  Mouse *v2; // esi@1
+  HCURSOR v3; // eax@10
+  int v4; // ecx@10
+  double v5; // st7@11
+  float v6; // ST04_4@12
+  LONG v7; // eax@14
+  LONG v8; // eax@17
+  unsigned int v9; // eax@21
+  float v10; // [sp+4h] [bp-18h]@11
+  struct tagPOINT Point; // [sp+14h] [bp-8h]@20
+
+  v2 = this;
+  if ( !this->bInitialized || !pName )
+    return;
+  if ( _strcmpi("MICON2", pName) )
+    pGame->uFlags2 &= 0xFFFFFFEFu;
+  else
+    pGame->uFlags2 |= 0x10u;
+  if ( _strcmpi(v2->pCurrentCursorName, pName) )
+    strcpy(v2->pCurrentCursorName, pName);
+  ClearCursor();
+  if ( _strnicmp(pName, "MICON1", 5u) )
+  {
+    v9 = pIcons_LOD->LoadTexture(pName, TEXTURE_16BIT_PALETTE);
+    v2->uCursorTextureID = v9;
+    v2->uCursorTextureID_2 = v9;
+    v2->AllocCursorSystemMem();
+    v2->field_C = 0;
+    v2->field_14 = 1;
+    v2->bActive = 1;
+    if ( !areWeLoadingTexture )
+    {
+      if (uCursorTextureID != -1)
+        pIcons_LOD->pTextures[uCursorTextureID].Release();
+      pIcons_LOD->_40F9C5();
+    }
+    return;
+  }
+  v2->bActive = 0;
+  v2->field_C = 1;
+  if ( !strcmp(pName, "MICON1") )
+  {
+    v3 = LoadCursorA(GetModuleHandleW(nullptr), "Arrow");
+    SetClassLongA(hWnd, GCL_HCURSOR, (LONG)v3);
+    v4 = (int)pAsyncMouse;
+    if (pAsyncMouse)
+    {
+      v10 = 0.0;
+      v5 = 0.0;
+LABEL_12:
+      v6 = v5;
+      pAsyncMouse->SetHotspot(v6, v10);
+      goto LABEL_18;
+    }
+    goto LABEL_20;
+  }
+  if ( !strcmp(pName, "MICON2") )
+  {
+    v7 = (LONG)LoadCursorA(GetModuleHandleW(nullptr), "Target");
+    SetClassLongA(hWnd, -12, v7);
+    v4 = (int)pAsyncMouse;
+    if (pAsyncMouse)
+    {
+      v10 = 14.0;
+      v5 = 14.0;
+      goto LABEL_12;
+    }
+LABEL_20:
+    GetCursorPos(&Point);
+    SetCursorPos(Point.x, Point.y);
+    return;
+  }
+  if ( !strcmp(pName, "MICON3") )
+  {
+    v8 = (LONG)LoadCursorA(0, (LPCSTR)IDC_WAIT);
+    SetClassLongA(hWnd, -12, v8);
+  }
+LABEL_18:
+  if ( !pAsyncMouse || (pAsyncMouse->LoadCursor(pName), !pAsyncMouse) )
+    goto LABEL_20;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (00469AE4) --------------------------------------------------------
+LONG Mouse::_469AE4()
+{
+  Mouse *v1; // esi@1
+  LONG v2; // ecx@2
+  LONG result; // eax@2
+  struct tagPOINT Point; // [sp+Ch] [bp-8h]@2
+
+  v1 = this;
+  this->field_8 = 1;
+  if (pAsyncMouse)
+  {
+    v2 = *((int *)pAsyncMouse + 6);
+    Point.x = *((int *)pAsyncMouse + 6);
+    result = *((int *)pAsyncMouse + 7);
+  }
+  else
+  {
+    GetCursorPos(&Point);
+    if ( pRenderer->bWindowMode )
+      ScreenToClient(hWnd, &Point);
+    result = Point.y;
+    v2 = Point.x;
+  }
+  v1->uMouseClickX = v2;
+  v1->uMouseClickY = result;
+  if ( pRenderer->bWindowMode )
+    goto LABEL_16;
+  if (pAsyncMouse)
+    goto LABEL_24;
+  if ( v2 < 0 )
+    v2 = 0;
+  if ( result < 0 )
+    result = 0;
+  if ( v2 > 639 )
+    v2 = 639;
+  if ( result > 479 )
+  {
+    result = 479;
+LABEL_16:
+    if (pAsyncMouse)
+      goto LABEL_24;
+    if ( pRenderer->bWindowMode && (v2 < 0 || result < 0 || v2 > 639 || result > 479) )
+      goto LABEL_23;
+  }
+  if ( v1->field_C )
+LABEL_23:
+    v1->bActive = 0;
+LABEL_24:
+  v1->field_8 = 0;
+  return result;
+}
+
+//----- (00469BA3) --------------------------------------------------------
+void Mouse::ClearCursor()
+{
+  Mouse *v1; // esi@1
+  void *v2; // eax@1
+  void **v3; // esi@5
+
+  v1 = this;
+  v2 = this->pCursorBitmap_sysmem;
+  this->bActive = 0;
+  if ( v2 )
+  {
+    free(v2);
+    v1->pCursorBitmap_sysmem = 0;
+  }
+  if ( v1->pCursorBitmap2_sysmem )
+  {
+    free(v1->pCursorBitmap2_sysmem);
+    v1->pCursorBitmap2_sysmem = 0;
+  }
+  v3 = &v1->ptr_90;
+  if ( *v3 )
+    free(*v3);
+  *v3 = 0;
+}
+
+//----- (00469BE6) --------------------------------------------------------
+void Mouse::AllocCursorSystemMem()
+{
+  bActive = 0;
+  if (!pCursorBitmap_sysmem)
+    pCursorBitmap_sysmem = (unsigned __int16 *)DoAllocCursorMem();
+  if (!pCursorBitmap2_sysmem)
+    pCursorBitmap2_sysmem = (unsigned __int8 *)DoAllocCursorMem();
+}
+
+//----- (00469C0D) --------------------------------------------------------
+void *Mouse::DoAllocCursorMem()
+{
+  return malloc(4 * (this->uCursorTextureID != -1 ? pIcons_LOD->pTextures[this->uCursorTextureID].uTextureWidth : 24)
+                  * (this->uCursorTextureID != -1 ? pIcons_LOD->pTextures[this->uCursorTextureID].uTextureHeight : 26));
+}
+
+//----- (00469C39) --------------------------------------------------------
+POINT *Mouse::GetCursorPos(POINT *a2)
+{
+  void *v2; // edx@1
+  POINT *result; // eax@1
+  unsigned int v4; // ecx@2
+  unsigned int v5; // edx@3
+
+  v2 = pAsyncMouse;
+  result = a2;
+  if (pAsyncMouse)
+  {
+    a2->x = *((int *)pAsyncMouse + 6);
+    v4 = *((int *)v2 + 7);
+  }
+  else
+  {
+    v5 = this->uMouseClickX;
+    v4 = this->uMouseClickY;
+    a2->x = v5;
+  }
+  a2->y = v4;
+  return result;
+}
+
+//----- (00469C65) --------------------------------------------------------
+void Mouse::Initialize(HWND hWnd)
+{
+  this->hWnd = hWnd;
+  this->bActive = 0;
+  this->bInitialized = 1;
+  this->pCursorBitmapPos.x = 0;
+  this->pCursorBitmapPos.y = 0;
+  this->uMouseClickX = 0;
+  this->uMouseClickY = 0;
+  this->pCursorBitmap_sysmem = 0;
+  this->field_34 = 0;
+  this->pCursorBitmap2_sysmem = 0;
+
+  SetCursorBitmap("MICON3");
+  SetCursorBitmap("MICON2");
+  SetCursorBitmap("MICON1");
+}
+
+//----- (00469CC2) --------------------------------------------------------
+void Mouse::Deactivate()
+{
+  if (bInitialized)
+    bActive = false;
+}
+
+//----- (00469CCD) --------------------------------------------------------
+void Mouse::DrawCursor()
+{
+  Mouse *v1; // esi@1
+  char v11; // zf@6
+  signed int v3; // eax@6
+  signed int v4; // ecx@6
+  Vec4_int_ *v5; // edx@21
+  int v6; // edi@21
+  int v7; // ebx@21
+  int v8; // eax@29
+  unsigned int v9; // eax@31
+
+  v1 = this;
+  if ( this->bInitialized )
+  {
+    if ( !this->field_8 && this->bActive && !this->field_C )
+      pMouse->_469AE4();
+    v11 = v1->field_C == 0;
+    v3 = v1->uMouseClickX;
+    v4 = v1->uMouseClickY;
+    v1->field_F4 = 1;
+    if ( !v11 )
+      goto LABEL_12;
+    if ( pRenderer->bWindowMode )
+    {
+      if ( v3 < 0 || v4 < 0 || v3 > 639 || v4 > 479 )
+      {
+LABEL_12:
+        v1->field_F4 = 0;
+        return;
+      }
+    }
+    else
+    {
+      if ( v3 < 0 )
+        v3 = 0;
+      if ( v4 < 0 )
+        v4 = 0;
+      if ( v3 > 639 )
+        v3 = 639;
+      if ( v4 > 479 )
+        v4 = 479;
+    }
+    v5 = &v1->pCursorBitmapRect;
+    v6 = v3 + v1->uCursorBitmapPitch;
+    v7 = v4 + v1->field_5C[0];
+    v1->pCursorBitmapRect.y = v4;
+    v1->pCursorBitmapRect.x = v3;
+    v1->pCursorBitmapRect.z = v6;
+    v1->pCursorBitmapRect.w = v7;
+    if ( v3 < 0 )
+      v5->x = 0;
+    if ( v4 < 0 )
+      v1->pCursorBitmapRect.y = 0;
+    if ( v6 > 640 )
+      v1->pCursorBitmapRect.z = 640;
+    if ( v7 > 480 )
+      v1->pCursorBitmapRect.w = 480;
+    v8 = v1->pCursorBitmapRect.z;
+    v1->bActive = 0;
+    v1->uCursorBitmapWidth = v8 - v5->x;
+    v11 = v1->field_14 == 0;
+    v1->uCursorBitmapHeight = v1->pCursorBitmapRect.w - v1->pCursorBitmapRect.y;
+    if ( !v11 )
+    {
+      if ( pMouse->ptr_90 )
+        v9 = 2 * pMouse->uCursorBitmapPitch;
+      else
+        v9 = 0;
+      pRenderer->_4A6DF5(
+        v1->pCursorBitmap_sysmem,
+        v9,
+        &v1->pCursorBitmapPos,
+        pRenderer->pTargetSurface,
+        pRenderer->uTargetSurfacePitch,
+        &v1->pCursorBitmapRect);
+      v1->field_14 = 0;
+    }
+  }
+}
+
+//----- (00469E1C) --------------------------------------------------------
+void Mouse::_469E1C()
+{
+  bActive = true;
+}
+
+//----- (00469E24) --------------------------------------------------------
+void Mouse::_469E24()
+{
+  if (pCursorBitmap3_sysmembits_16bit)
+  {
+    free(pCursorBitmap3_sysmembits_16bit);
+    pCursorBitmap3_sysmembits_16bit = 0;
+  }
+}
+
+//----- (00469E3B) --------------------------------------------------------
+void Mouse::DrawCursorToTarget()
+{
+  if (!pCursorBitmap3_sysmembits_16bit)
+    return;
+
+  auto pSrc = pCursorBitmap3_sysmembits_16bit;
+  for (uint y = field_44; y < field_4C; ++y)
+    for (uint x = field_40; x < field_48; ++x)
+      pRenderer->pTargetSurface[y * pRenderer->uTargetSurfacePitch + x] = *pSrc++;
+}
+
+//----- (00469EA4) --------------------------------------------------------
+void Mouse::_469EA4()
+{
+  Mouse *v1; // esi@1
+  unsigned int v2; // eax@2
+  Texture *v3; // edi@2
+  unsigned int v4; // ecx@3
+  unsigned int v5; // eax@3
+  unsigned int v6; // ebx@5
+  int v7; // ecx@15
+  int v8; // ecx@25
+  int v9; // ebx@26
+  unsigned int v10; // eax@26
+  int v11; // edx@27
+  unsigned __int16 *v12; // edx@29
+  unsigned __int16 *v13; // ebx@29
+  unsigned int a2; // [sp+Ch] [bp-1Ch]@5
+  unsigned int v15; // [sp+10h] [bp-18h]@5
+  unsigned int v16; // [sp+14h] [bp-14h]@25
+  unsigned __int16 *v17; // [sp+18h] [bp-10h]@25
+  int v18; // [sp+1Ch] [bp-Ch]@27
+  int v19; // [sp+20h] [bp-8h]@15
+  unsigned __int16 *v20; // [sp+20h] [bp-8h]@28
+  int v21; // [sp+24h] [bp-4h]@12
+  unsigned __int16 *v22; // [sp+24h] [bp-4h]@25
+
+  v1 = this;
+  if ( pParty->pPickedItem.uItemID )
+  {
+    v2 = pIcons_LOD->LoadTexture(
+           pItemsTable->pItems[pParty->pPickedItem.uItemID].pIconName,
+           TEXTURE_16BIT_PALETTE);
+    v3 = (Texture *)(v2 != -1 ? (int)&pIcons_LOD->pTextures[v2] : 0);
+    if (pAsyncMouse)
+    {
+      v4 = *((int *)pAsyncMouse + 6);
+      v5 = *((int *)pAsyncMouse + 7);
+    }
+    else
+    {
+      v4 = pMouse->uMouseClickX;
+      v5 = pMouse->uMouseClickY;
+    }
+    v6 = v5;
+    a2 = v4;
+    v15 = v5;
+    if ( (signed int)v4 <= 639 && (signed int)v5 <= 479 )
+    {
+      if ( (v4 & 0x80000000u) != 0 )
+        a2 = 0;
+      if ( (v5 & 0x80000000u) != 0 )
+      {
+        v6 = 0;
+        v15 = 0;
+      }
+      if ( (signed int)(v3->uTextureWidth + a2) <= 640 )
+        v21 = v3->uTextureWidth;
+      else
+        v21 = 640 - a2;
+      if ( (signed int)(v3->uTextureHeight + v6) <= 480 )
+      {
+        v19 = v3->uTextureHeight;
+        v7 = v3->uTextureHeight;
+      }
+      else
+      {
+        v7 = 480 - v6;
+        v19 = 480 - v6;
+      }
+      if ( !v1->pCursorBitmap3_sysmembits_16bit
+        || a2 != v1->field_40
+        || v6 != v1->field_44
+        || a2 + v21 != v1->field_48
+        || v6 + v7 != v1->field_4C )
+      {
+        if ( v1->pCursorBitmap3_sysmembits_16bit )
+          free(v1->pCursorBitmap3_sysmembits_16bit);
+        v1->pCursorBitmap3_sysmembits_16bit = (unsigned __int16 *)operator new(2 * v3->uTextureHeight
+                                                                                 * v3->uTextureWidth);
+        v1->field_40 = a2;
+        v1->field_48 = a2 + v21;
+        v1->field_44 = v6;
+        v1->field_4C = v6 + v19;
+      }
+      v8 = v1->field_44;
+      v22 = v1->pCursorBitmap3_sysmembits_16bit;
+      v17 = pRenderer->pTargetSurface;
+      v16 = pRenderer->uTargetSurfacePitch;
+      if ( v8 < v1->field_4C )
+      {
+        v9 = v1->field_48;
+        v10 = pRenderer->uTargetSurfacePitch * v8;
+        do
+        {
+          v11 = v1->field_40;
+          v18 = v1->field_40;
+          if ( v11 < v9 )
+          {
+            v20 = &v17[v10 + v11];
+            do
+            {
+              v12 = v20;
+              v13 = v22;
+              ++v18;
+              ++v20;
+              ++v22;
+              *v13 = *v12;
+              v9 = v1->field_48;
+            }
+            while ( v18 < v9 );
+          }
+          v10 += v16;
+          ++v8;
+        }
+        while ( v8 < v1->field_4C );
+        v6 = v15;
+      }
+      if ( pParty->pPickedItem.uAttributes & 2 )
+      {
+        pRenderer->_4A6776(a2, v6, v3);
+      }
+      else
+      {
+        if ( pParty->pPickedItem.uAttributes & 1 )
+          pRenderer->DrawTextureTransparent(a2, v6, v3);
+        else
+          pRenderer->DrawTransparentGreenShade(a2, v6, v3);
+      }
+    }
+  }
+  else
+  {
+    if ( this->pCursorBitmap3_sysmembits_16bit )
+    {
+      free(this->pCursorBitmap3_sysmembits_16bit);
+      v1->pCursorBitmap3_sysmembits_16bit = 0;
+    }
+  }
+}
+
+//----- (0046A080) --------------------------------------------------------
+void Mouse::Activate(int bActive)
+{
+  bActive = bActive;
+}
+
+//----- (0046A08A) --------------------------------------------------------
+void Mouse::SetMouseClick(int x, int y)
+{
+  uMouseClickX = x;
+  uMouseClickY = y;
+}
+
+
+//----- (00409E3D) --------------------------------------------------------
+void AsyncMouse::_409E3D(char a2)
+{
+  if ( *((unsigned char *)this + 128) & 1 )
+    *((unsigned char *)this + 103) = 1;
+  else
+    *((unsigned char *)this + 103) = 0;
+  if ( a2 )
+    *((unsigned int *)this + 32) |= 1u;
+  else
+    *((unsigned int *)this + 32) &= 0xFFFFFFFEu;
+}
+
+//----- (00465C2C) --------------------------------------------------------
+void AsyncMouse::Release()
+{
+  if (pAsyncMouse)
+  {
+    pAsyncMouse->Suspend();
+    if (pAsyncMouse)
+      (**(void (__stdcall ***)(int))pAsyncMouse)(1);
+  }
+  pAsyncMouse = 0;
+}
+
+
+
+
+//----- (0046ACA9) --------------------------------------------------------
+AsyncMouse::AsyncMouse(IDirectDrawSurface *a2)
+{
+  IDirectDrawSurface *v2; // eax@1
+  void *v3; // esi@1
+  char *v4; // edi@1
+  double v5; // ST14_8@3
+  double v6; // ST14_8@3
+
+  v2 = a2;
+  v3 = this;
+  *((int *)this + 16) = -1;
+  *((int *)this + 3) = (int)v2;
+  LOBYTE(v2) = BYTE3(a2);
+  v4 = (char *)this + 104;
+  *((int *)this + 1) = 0;
+  *((char *)this + 20) = 0;
+  *((int *)this + 17) = 0;
+  *((int *)this + 18) = 0;
+  *((char *)this + 88) = 1;
+  *((char *)this + 91) = 0;
+  *((char *)this + 93) = 0;
+  *((char *)this + 94) = 0;
+  *((char *)this + 95) = 0;
+  *((char *)this + 96) = 0;
+  *((char *)this + 97) = 0;
+  *((char *)this + 98) = 0;
+  *((char *)this + 99) = 0;
+  *((char *)this + 100) = 0;
+  *((char *)this + 101) = 0;
+  *((char *)this + 102) = 0;
+  *((char *)this + 104) = (char)v2;
+  *((int *)this + 27) = (int)AsyncMouse::unk_46BD09(0, 0);
+  *((int *)v4 + 2) = 0;
+  *((char *)v3 + 116) = BYTE3(a2);
+  *((int *)v3 + 30) = (int)AsyncMouse::unk_46BD09(0, 0);
+  *((int *)v3 + 31) = 0;
+  *((int *)v3 + 32) = 0;
+  *((int *)v3 + 33) = 0;
+  *(int *)v3 = 5080880;
+  if ( !Initialize(this) )
+  {
+    MessageBoxW(nullptr, L"Could not initialize CMouseAsync object", nullptr, 0);
+  }
+  *((int *)v3 + 12) = 0;
+  *((int *)v3 + 13) = 0;
+  *((int *)v3 + 14) = 0;
+  *((int *)v3 + 15) = 0;
+  v5 = (float)0.0 + 6.7553994e15;
+  *((int *)v3 + 10) = LODWORD(v5);
+  v6 = (float)0.0 + 6.7553994e15;
+  a2 = (IDirectDrawSurface *)LODWORD(v6);
+  *((int *)v3 + 32) |= 1u;
+  *((int *)v3 + 11) = LODWORD(v6);
+  *((char *)v3 + 103) = 1;
+}
+// 4DBD94: using guessed type int dword_4DBD94;
+
+
+
+//----- (0046ADE2) --------------------------------------------------------
+AsyncMouse::~AsyncMouse()
+{
+  void *v1; // esi@1
+  char *v2; // edi@1
+  int v3; // ecx@1
+
+  v1 = this;
+  //*(int *)this = AsyncMouse_pvdtor;
+  v2 = (char *)this + 132;
+  v3 = *((int *)this + 33);
+  if ( v3 )
+    (**(void (__stdcall ***)(int))v3)(1);
+  *(int *)v2 = 0;
+  TerminateThread(*((HANDLE *)v1 + 4), 0xFAu);
+  SetWindowPos(hWnd, (HWND)0xFFFFFFFE, uWindowX, uWindowY, 640, 480, 0);
+  //AsyncMouse::dtor_sub_46BC73((int)((char *)v1 + 116));
+  //AsyncMouse::dtor_sub_46BC73((int)((char *)v1 + 104));
+}
+// 4D8730: using guessed type int (__stdcall *AsyncMouse_pvdtor[2])(char);
+
+
+
+
+
+
+
+
+
+
+
+
+
+//----- (0046AE6E) --------------------------------------------------------
+char AsyncMouse::Initialize(LPVOID lpParameter)
+{
+  void *v1; // esi@1
+  char result; // al@2
+
+  v1 = lpParameter;
+  if ( LoadCursorImage() && _46B072() )
+    result = CreateDisrectInputMouse() != 0;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0046AE97) --------------------------------------------------------
+char AsyncMouse::LoadCursor(const char *pContainer)
+{
+  __debugbreak();
+  return 0;
+  /*
+  void *v2; // esi@1
+  int v3; // eax@1
+  HRESULT v4; // eax@1
+  char result; // al@3
+  HRESULT a2; // [sp+8h] [bp-B0h]@1
+  int v7; // [sp+58h] [bp-60h]@1
+  char v9; // [sp+B4h] [bp-4h]@1
+
+  v2 = this;
+  EnterCriticalSection(&pGame->pThreadWardInstance->cs2);
+  v3 = *((int *)v2 + 1);
+  a2 = 100;
+  v7 = 0;
+  v4 = (*(int (__stdcall **)(int, int, int, int, signed int, HRESULT *))(*(int *)v3 + 20))(
+         v3,
+         0,
+         0,
+         0,
+         1024,
+         &a2);
+  ErrHR(v4, "DirectInput", __FUNCTION__, __FILE__, __LINE__);
+  
+  Texture thisa; // [sp+6Ch] [bp-4Ch]@1
+  //Texture::Texture(&thisa);
+
+  if ( pIcons_LOD->LoadTextureFromLOD(&thisa, pContainer, TEXTURE_16BIT_PALETTE) != -1
+    && DrawCursor(&thisa, *((IDirectDrawSurface4 **)v2 + 1), 0) )
+  {
+    thisa.Release();
+    LeaveCriticalSection(&pGame->pThreadWardInstance->cs2);
+    result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;*/
+}
+
+//----- (0046AF50) --------------------------------------------------------
+char AsyncMouse::LoadCursorImage()
+{
+  void *v1; // ebx@1
+  int v2; // eax@2
+  int v3; // esi@4
+  char result; // al@5
+  //const char *v5; // eax@6
+  //std::string v6; // [sp-18h] [bp-12Ch]@9
+  const char *v7; // [sp-8h] [bp-11Ch]@9
+  int v8; // [sp-4h] [bp-118h]@9
+  DDSURFACEDESC2 Dst; // [sp+Ch] [bp-108h]@1
+  int v10; // [sp+88h] [bp-8Ch]@2
+  int v11; // [sp+8Ch] [bp-88h]@2
+  int v12; // [sp+90h] [bp-84h]@2
+  int v13; // [sp+94h] [bp-80h]@2
+  char v14; // [sp+D0h] [bp-44h]@2
+  int v15; // [sp+F0h] [bp-24h]@2
+  int v16; // [sp+104h] [bp-10h]@4
+  int v17; // [sp+108h] [bp-Ch]@4
+  std::string *v18; // [sp+10Ch] [bp-8h]@9
+  int a3; // [sp+113h] [bp-1h]@9
+
+  v1 = this;
+  memset(&Dst, 0, 0x7Cu);
+  Dst.dwSize = 124;
+  if ( pRenderer->pDirectDraw4->GetDisplayMode(&Dst)
+    || (memset(&v10, 0, 0x7Cu),
+        v10 = 124,
+        v11 = 4103,
+        v15 = 2112,
+        v12 = 32,
+        v13 = 32,
+        v2 = *((int *)v1 + 3),
+        memcpy(&v14, &Dst.ddpfPixelFormat, 0x20u),
+        (*(int (__stdcall **)(int, int *, char *, int))(**(int **)v2 + 24))(
+          *(int *)v2,
+          &v10,
+          (char *)v1 + 4,
+          0))
+    || (*(int (__stdcall **)(int, int *, char *, int))(***((int ***)v1 + 3) + 24))(
+         **((int **)v1 + 3),
+         &v10,
+         (char *)v1 + 8,
+         0)
+    || (v3 = *((int *)v1 + 1),
+        v16 = 0,
+        v17 = 0,
+        (*(int (__stdcall **)(int, signed int, int *))(*(int *)v3 + 116))(v3, 8, &v16)) )
+  {
+    result = 0;
+    return false;
+  }
+  else
+  {
+    if ( !LoadCursor("micon1") )
+    {
+      MessageBoxW(nullptr, L"Could not load async mouse cursor image", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\MouseAsync.cpp:182", 0);
+    }
+    result = 1;
+    return true;
+  }
+  return result;
+}
+// 4D86F0: using guessed type int dword_4D86F0;
+
+//----- (0046B072) --------------------------------------------------------
+char AsyncMouse::_46B072()
+{
+  DWORD v1; // esi@1
+  HANDLE v2; // eax@1
+  char result; // al@2
+  DWORD ThreadId; // [sp+0h] [bp-4h]@1
+
+  ThreadId = (DWORD)this;
+  v1 = (DWORD)this;
+  v2 = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)AsyncMouseThread, this, 4u, &ThreadId);
+  *(int *)(v1 + 16) = (int)v2;
+  if ( v2 )
+    result = SetThreadPriority(v2, 15) != 0;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0046B0A9) --------------------------------------------------------
+char AsyncMouse::CreateDisrectInputMouse()
+{
+  __debugbreak();
+  /*
+  void *v1; // esi@1
+  DirectInputMouse *v2; // ecx@1
+  DirectInputMouse *v3; // eax@2
+
+  v1 = this;
+  v2 = (DirectInputMouse *)operator new(0x2Cu);
+  if ( v2 )
+    v3 = DirectInputMouse::DirectInputMouse(v2);
+  else
+    v3 = 0;
+  *((int *)v1 + 33) = v3;
+  return v3 != 0;*/
+  return 0;
+}
+
+//----- (0046B0ED) --------------------------------------------------------
+int AsyncMouse::_46B0ED()
+{
+  __debugbreak();
+  /*
+  int v1; // esi@1
+  int v2; // ecx@1
+  int result; // eax@2
+
+  v1 = this + 132;
+  v2 = *(int *)(this + 132);
+  if ( v2 )
+    result = (**(int (__stdcall ***)(int))v2)(1);
+  *(int *)v1 = 0;
+  return result;*/
+  return 0;
+}
+// 46B0ED: using guessed type int __thiscall AsyncMouse__46B0ED(int);
+
+//----- (0046B105) --------------------------------------------------------
+void AsyncMouse::Resume()
+{
+  __debugbreak();
+  /*
+  void *v1; // esi@1
+
+  v1 = this;
+  EnterCriticalSection(&pGame->pThreadWardInstance->cs3);
+  AsyncMouse::CreateDisrectInputMouse(v1);
+  AsyncMouse::Clip();
+  ResumeThread(*((HANDLE *)v1 + 4));
+  *((char *)v1 + 88) = 0;
+  LeaveCriticalSection(&pGame->pThreadWardInstance->cs3);*/
+}
+
+//----- (0046B14F) --------------------------------------------------------
+void AsyncMouse::Suspend()
+{
+  void *v1; // esi@1
+  Vis *v2; // eax@3
+  std::string v3; // [sp-18h] [bp-24h]@2
+  const char *v4; // [sp-8h] [bp-14h]@2
+  int v5; // [sp-4h] [bp-10h]@2
+  std::string *v6; // [sp+4h] [bp-8h]@2
+  int a3; // [sp+Bh] [bp-1h]@2
+
+  v1 = this;
+  if ( *((int *)this + 33) )
+  {
+    v2 = pGame->pVisInstance;
+    if ( v2 )
+      v2->stru1.uNumPointers = 0;
+    EnterCriticalSection(&pGame->pThreadWardInstance->cs3);
+    SuspendThread(*((HANDLE *)v1 + 4));
+    _46B0ED();
+    LeaveCriticalSection(&pGame->pThreadWardInstance->cs3);
+  }
+  else
+  {
+      MessageBoxW(nullptr, L"DI_Mouse pointer invalid; bailing out from suspend()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\MouseAsync.cpp:233", 0);
+  }
+}
+// 46B0ED: using guessed type int __thiscall AsyncMouse__46B0ED(int);
+
+//----- (0046B1DD) --------------------------------------------------------
+char AsyncMouse::_46B1DD()
+{
+  *((char *)this + 20) = 1;
+  Sleep(118);
+  return 1;
+}
+
+//----- (0046B1EC) --------------------------------------------------------
+bool AsyncMouse::DrawCursor(Texture *a1, IDirectDrawSurface4 *a2, int a3)
+{
+  __debugbreak();
+  /*
+  bool result; // eax@1
+  unsigned __int16 *v5; // ebx@2
+  unsigned __int8 *v6; // edx@2
+  int v7; // esi@2
+  int v8; // ecx@2
+  LPVOID v9; // edi@2
+  int v10; // ecx@5
+  DDSURFACEDESC2 Dst; // [sp+0h] [bp-84h]@1
+  __int32 v12; // [sp+7Ch] [bp-8h]@3
+  int v13; // [sp+80h] [bp-4h]@3
+
+  Dst.dwSize = 124;
+  result = pRenderer->LockSurface_DDraw4(a2, &Dst, 1u);
+  if ( result )
+  {
+    v5 = a1->pPalette16;
+    v6 = a1->pLevelOfDetail0;
+    v7 = a1->uTextureWidth;
+    v8 = a1->uTextureHeight;
+    v9 = Dst.lpSurface;
+    if ( v8 > 0 )
+    {
+      v12 = 2 * (Dst.lPitch / 2 - v7);
+      v13 = v8;
+      do
+      {
+        if ( v7 > 0 )
+        {
+          v10 = v7;
+          do
+          {
+            if ( v5[*v6] )
+              *(short *)v9 = v5[*v6];
+            v9 = (char *)v9 + 2;
+            ++v6;
+            --v10;
+          }
+          while ( v10 );
+        }
+        v9 = (char *)v9 + v12;
+        --v13;
+      }
+      while ( v13 );
+    }
+    result = a2->Unlock(
+               v6,
+               a2,
+               a3);
+  }
+  LOBYTE(result) = 1;
+  return result;*/
+  return 0;
+}
+
+//----- (0046B289) --------------------------------------------------------
+bool AsyncMouse::_46B289(int a2, char a3)
+{
+  char v3; // dl@1
+  bool result; // eax@33
+  char v5; // [sp+2h] [bp-2h]@1
+  char v6; // [sp+3h] [bp-1h]@1
+
+  v3 = *((char *)this + 93);
+  v6 = *((char *)this + 94);
+  v5 = *((char *)this + 95);
+  if ( a3 & 1 )
+  {
+    *((char *)this + 93) = 1;
+  }
+  else
+  {
+    if ( v3 )
+      *((char *)this + 99) = 1;
+    else
+      *((char *)this + 99) = 0;
+    *((char *)this + 93) = 0;
+  }
+  if ( a3 & 2 )
+  {
+    *((char *)this + 94) = 1;
+  }
+  else
+  {
+    if ( v6 )
+      *((char *)this + 100) = 1;
+    else
+      *((char *)this + 100) = 0;
+    *((char *)this + 94) = 0;
+  }
+  if ( a3 & 4 )
+  {
+    *((char *)this + 95) = 1;
+  }
+  else
+  {
+    if ( v5 )
+      *((char *)this + 101) = 1;
+    else
+      *((char *)this + 101) = 0;
+    *((char *)this + 95) = 0;
+  }
+  *((char *)this + 96) = v3 != *((char *)this + 93);
+  *((char *)this + 97) = v6 != *((char *)this + 94);
+  *((char *)this + 98) = v5 != *((char *)this + 95);
+  if ( *((char *)this + 99) && *((char *)this + 96) || *((char *)this + 100) && *((char *)this + 97) )
+    *((char *)this + 102) = 1;
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (0046B342) --------------------------------------------------------
+void AsyncMouse::SetHotspot(float hotspotx, float hotspoty)
+{
+  double v3; // ST00_8@1
+  double v4; // ST00_8@1
+
+  v3 = hotspotx + 6.7553994e15;
+  *(int *)(this + 40) = LODWORD(v3);
+  v4 = hotspoty + 6.7553994e15;
+  *(int *)(this + 44) = LODWORD(v4);
+}
+
+//----- (0046B37C) --------------------------------------------------------
+int AsyncMouse::UpdateData(int a2)
+{
+  __debugbreak();
+  /*
+  void *v2; // edi@1
+  int result; // eax@2
+  int v4; // eax@3
+  int v5; // esi@3
+  std::string v6; // [sp-18h] [bp-28h]@2
+  const char *v7; // [sp-8h] [bp-18h]@2
+  int v8; // [sp-4h] [bp-14h]@2
+  std::string *v9; // [sp+8h] [bp-8h]@2
+  int a3; // [sp+Fh] [bp-1h]@2
+
+  v2 = this;
+  if ( *((int *)this + 33) )
+  {
+    EnterCriticalSection(&pGame->pThreadWardInstance->cs3);
+    DirectInputMouse::_43BB89(*((DirectInputMouse **)v2 + 33));
+    v4 = *((int *)v2 + 33);
+    v5 = v4 + 32;
+    _46B289(v4 + 32, *(int *)(v4 + 40));
+    LeaveCriticalSection(&pGame->pThreadWardInstance->cs3);
+    result = a2;
+    *(int *)a2 = *(int *)v5;
+    *(int *)(a2 + 4) = *(int *)(v5 + 4);
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"DI_Mouse pointer invalid bailing out from update_mouse_data()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\MouseAsync.cpp:446", 0);
+    result = a2;
+    *(int *)a2 = 0;
+    *(int *)(a2 + 4) = 0;
+  }
+  return result;*/
+  return 0;
+}
+
+//----- (0046B420) --------------------------------------------------------
+char AsyncMouse::Thread()
+{
+  void *v1; // esi@1
+  char result; // al@2
+  int v3; // eax@3
+  int v4; // ecx@3
+  int v5; // eax@3
+  int v6; // ecx@3
+  int v7; // [sp+4h] [bp-8h]@3
+  int v8; // [sp+8h] [bp-4h]@3
+
+  v1 = this;
+  if ( *((char *)this + 20) )
+  {
+    result = 0;
+  }
+  else
+  {
+    UpdateData((int)&v7);
+    _46BA8D(v7, v8);
+    _46B958(v7 - *((int *)v1 + 10), v8 - *((int *)v1 + 11));
+    _46B492((int)&v7);
+    _46B5D5((int)&v7);
+    v3 = v7;
+    v4 = v8;
+    *((int *)v1 + 6) = v7;
+    v5 = v3 - *((int *)v1 + 10);
+    *((int *)v1 + 7) = v4;
+    v6 = v4 - *((int *)v1 + 11);
+    *((int *)v1 + 8) = v5;
+    result = 1;
+    *((int *)v1 + 9) = v6;
+  }
+  return result;
+}
+
+//----- (0046B492) --------------------------------------------------------
+void AsyncMouse::_46B492(int a2)
+{
+  __debugbreak();
+  /*
+  void *v2; // edi@1
+  int v3; // esi@3
+  int v4; // eax@5
+  int v5; // ecx@5
+  int v6; // eax@8
+  int v7; // ecx@8
+  int v8; // eax@11
+  int v9; // esi@11
+  int v10; // [sp+Ch] [bp-1Ch]@5
+  int v11; // [sp+10h] [bp-18h]@5
+  int v12; // [sp+14h] [bp-14h]@5
+  int v13; // [sp+18h] [bp-10h]@5
+  int v14; // [sp+24h] [bp-4h]@5
+
+  v2 = this;
+  EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);
+  if ( *((int *)v2 + 28) > 0x80u )
+    _46BCAB((char *)v2 + 104);
+  v3 = a2;
+  if ( *((char *)v2 + 93) && *((char *)v2 + 96) )
+  {
+    v4 = *(int *)a2;
+    v5 = *(int *)(a2 + 4);
+    v13 = 1;
+    v10 = 5080884;
+    v11 = v4;
+    v12 = v5;
+    v14 = 0;
+    AsyncMouse::unk_46BCD2((char *)v2 + 104, (int)&a2, *((int *)v2 + 27), (int)&v10);
+    v14 = -1;
+  }
+  if ( *((char *)v2 + 94) && *((char *)v2 + 97) )
+  {
+    v6 = *(int *)v3;
+    v7 = *(int *)(v3 + 4);
+    v13 = 2;
+    v10 = 5080884;
+    v11 = v6;
+    v12 = v7;
+    v14 = 1;
+    AsyncMouse::unk_46BCD2((char *)v2 + 104, (int)&a2, *((int *)v2 + 27), (int)&v10);
+    v14 = -1;
+  }
+  if ( *((char *)v2 + 95) && *((char *)v2 + 98) )
+  {
+    v8 = *(int *)v3;
+    v9 = *(int *)(v3 + 4);
+    v13 = 4;
+    v10 = 5080884;
+    v11 = v8;
+    v12 = v9;
+    v14 = 2;
+    AsyncMouse::unk_46BCD2((char *)v2 + 104, (int)&a2, *((int *)v2 + 27), (int)&v10);
+  }
+  LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);*/
+}
+
+//----- (0046B5D5) --------------------------------------------------------
+void AsyncMouse::_46B5D5(int a2)
+{
+  __debugbreak();
+  /*
+  void *v2; // esi@1
+  DWORD v3; // eax@3
+  char v4; // zf@3
+  int v5; // edi@3
+  int v6; // eax@6
+  int v7; // ecx@6
+  int v8; // eax@11
+  int v9; // ecx@11
+  int v10; // eax@16
+  int v11; // edi@16
+  int (__stdcall **v12)(char); // [sp+Ch] [bp-20h]@6
+  int v13; // [sp+10h] [bp-1Ch]@6
+  int v14; // [sp+14h] [bp-18h]@6
+  int v15; // [sp+18h] [bp-14h]@6
+  DWORD v16; // [sp+1Ch] [bp-10h]@3
+  int v17; // [sp+28h] [bp-4h]@6
+
+  v2 = this;
+  EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);
+  if ( *((int *)v2 + 31) > 0x80u )
+    _46BCAB((char *)v2 + 116);
+  v3 = timeGetTime();
+  v4 = *((char *)v2 + 93) == 0;
+  v5 = a2;
+  v16 = v3;
+  if ( !v4 && *((char *)v2 + 96) )
+  {
+    if ( v3 - *((int *)v2 + 19) < 0xFA )
+    {
+      v6 = *(int *)a2;
+      v7 = *(int *)(a2 + 4);
+      v15 = 1;
+      v12 = &AsyncMouse::unk::vdtor_ptr;
+      v13 = v6;
+      v14 = v7;
+      v17 = 0;
+      AsyncMouse::unk_46BCD2((char *)v2 + 116, (int)&a2, *((int *)v2 + 30), (int)&v12);
+      v17 = -1;
+      v3 = v16;
+    }
+    *((int *)v2 + 19) = v3;
+  }
+  if ( *((char *)v2 + 94) && *((char *)v2 + 97) )
+  {
+    if ( v3 - *((int *)v2 + 20) < 0xFA )
+    {
+      v8 = *(int *)v5;
+      v9 = *(int *)(v5 + 4);
+      v15 = 2;
+      //v12 = &AsyncMouse::unk::vdtor_ptr;
+      v13 = v8;
+      v14 = v9;
+      v17 = 1;
+      AsyncMouse::unk_46BCD2((char *)v2 + 116, (int)&a2, *((int *)v2 + 30), (int)&v12);
+      v17 = -1;
+      v3 = v16;
+    }
+    *((int *)v2 + 20) = v3;
+  }
+  if ( *((char *)v2 + 95) && *((char *)v2 + 98) )
+  {
+    if ( v3 - *((int *)v2 + 21) < 0xFA )
+    {
+      v10 = *(int *)v5;
+      v11 = *(int *)(v5 + 4);
+      v15 = 4;
+      //v12 = &AsyncMouse::unk::vdtor_ptr;
+      v13 = v10;
+      v14 = v11;
+      v17 = 2;
+      AsyncMouse::unk_46BCD2((char *)v2 + 116, (int)&a2, *((int *)v2 + 30), (int)&v12);
+      v3 = v16;
+    }
+    *((int *)v2 + 21) = v3;
+  }
+  LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);*/
+}
+
+//----- (0046B736) --------------------------------------------------------
+void AsyncMouse::_46B736_consume_click_lists(char a2)
+{
+  __debugbreak();
+  /*
+  void *v2; // esi@1
+
+  v2 = this;
+  _46B76F();
+  _46B879();
+  if ( a2 )
+  {
+    _46BCAB((char *)v2 + 104);
+    _46BCAB((char *)v2 + 116);
+  }
+  if ( *((char *)v2 + 102) )
+  {
+    back_to_game();
+    *((char *)v2 + 102) = 0;
+  }*/
+}
+
+//----- (0046B76F) --------------------------------------------------------
+void AsyncMouse::_46B76F()
+{
+  __debugbreak();
+  /*
+  char *v0; // ebx@1
+  int v1; // eax@1
+  int v2; // edi@1
+  int v3; // eax@2
+  unsigned int *v4; // esi@2
+  unsigned int v5; // ST08_4@7
+  unsigned int v6; // ST04_4@7
+  float v7; // ST00_4@7
+  unsigned int v8; // ST08_4@9
+  unsigned int v9; // ST04_4@9
+  float v10; // ST00_4@9
+
+  EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);
+  v0 = (char *)pAsyncMouse + 108;
+  v1 = *((int *)pAsyncMouse + 27);
+  v2 = *(int *)v1;
+  if ( *(int *)v1 != v1 )
+  {
+    do
+    {
+      v3 = *(int *)(v2 + 20);
+      v4 = (unsigned int *)(v2 + 12);
+      if ( v3 & 1 )
+      {
+        pGame->PickMouse(512.0, *v4, *(int *)(v2 + 16), 0, &a3, &a4);
+        if ( GetCurrentMenuID() == 6 )
+          sub_41CD4F(0x29u);
+        UI_OnMouseLeftClick((int *)(v2 + 12));
+      }
+      else
+      {
+        if ( v3 & 2 )
+        {
+          v5 = *(int *)(v2 + 16);
+          v6 = *v4;
+          v7 = GetPickDepth();
+          pGame->PickMouse(v7, v6, v5, 0, &stru_F93E30, &a5);
+          sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62((Vec2_int_ *)(v2 + 12));
+        }
+        else
+        {
+          if ( v3 & 4 )
+          {
+            v8 = *(int *)(v2 + 16);
+            v9 = *v4;
+            v10 = GetPickDepth();
+            pGame->PickMouse(v10, v9, v8, 1, &a3, &a5);
+          }
+        }
+      }
+      v2 = *(int *)v2;
+    }
+    while ( v2 != *(int *)v0 );
+  }
+  LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);*/
+}
+
+//----- (0046B879) --------------------------------------------------------
+void AsyncMouse::_46B879()
+{
+  __debugbreak();
+  /*
+  char *v0; // ebx@1
+  int v1; // eax@1
+  int v2; // edi@1
+  int v3; // eax@2
+  unsigned int *v4; // esi@2
+  unsigned int v5; // ST08_4@5
+  unsigned int v6; // ST04_4@5
+  float v7; // ST00_4@5
+
+  EnterCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);
+  v0 = (char *)pAsyncMouse + 120;
+  v1 = *((int *)pAsyncMouse + 30);
+  v2 = *(int *)v1;
+  if ( *(int *)v1 != v1 )
+  {
+    do
+    {
+      v3 = *(int *)(v2 + 20);
+      v4 = (unsigned int *)(v2 + 12);
+      if ( v3 & 1 )
+      {
+        pGame->PickMouse(512.0, *v4, *(int *)(v2 + 16), 0, &a3, &a4);
+        sub_4178C4();
+      }
+      else
+      {
+        if ( v3 & 2 )
+        {
+          v5 = *(int *)(v2 + 16);
+          v6 = *v4;
+          v7 = GetPickDepth();
+          pGame->PickMouse(v7, v6, v5, 0, &stru_F93E30, &a4);
+          sub_4178E1();
+        }
+        else
+        {
+          if ( v3 & 4 )
+            nullsub_1();
+        }
+      }
+      v2 = *(int *)v2;
+    }
+    while ( v2 != *(int *)v0 );
+  }
+  LeaveCriticalSection(&pGame->pThreadWardInstance->csAsyncMouse);*/
+}
+
+//----- (0046B944) --------------------------------------------------------
+int AsyncMouse::_46B944()
+{
+  __debugbreak();
+  /*
+  void *v1; // esi@1
+
+  v1 = this;
+  _46BCAB((char *)this + 104);
+  return _46BCAB((char *)v1 + 116);*/
+  return 0;
+}
+// 46BCAB: using guessed type int __thiscall AsyncMouse__46BCAB(int);
+
+//----- (0046B958) --------------------------------------------------------
+char AsyncMouse::_46B958(int a2, int a3)
+{
+  __debugbreak();
+  /*
+  void *v3; // esi@1
+  char result; // al@3
+  int v5; // edx@6
+  int v6; // eax@6
+  int v7; // eax@12
+  int v8; // edi@13
+  int v9; // eax@19
+  struct IDirectDrawSurface4 *v10; // ST08_4@21
+  DDBLTFX v11; // [sp+4h] [bp-74h]@21
+  RECT v12; // [sp+68h] [bp-10h]@19
+
+  v3 = this;
+  if ( pRenderer->pFrontBuffer4 && !pRenderer->pFrontBuffer4->IsLost() )
+  {
+    EnterCriticalSection(&pGame->pThreadWardInstance->cs2);
+    if ( *((char *)v3 + 88) )
+      pRenderer->pFrontBuffer4->BltFast(
+        *((int *)v3 + 8),
+        *((int *)v3 + 9),
+        (LPDIRECTDRAWSURFACE4)*((int *)v3 + 2),
+        (LPRECT)((char *)v3 + 48),
+        16u);
+    v5 = 640 - a2;
+    v6 = 640 - a2;
+    if ( 640 - a2 >= 31 )
+      v6 = 31;
+    if ( v6 >= 0 )
+    {
+      if ( v5 >= 31 )
+        v5 = 31;
+    }
+    else
+    {
+      v5 = 0;
+    }
+    v7 = 480 - a3;
+    if ( 480 - a3 >= 31 )
+      v8 = 31;
+    else
+      v8 = 480 - a3;
+    if ( v8 >= 0 )
+    {
+      if ( v7 >= 31 )
+        v7 = 31;
+    }
+    else
+    {
+      v7 = 0;
+    }
+    *((int *)v3 + 13) = 0;
+    *((int *)v3 + 14) = v5;
+    v12.right = a2 + v5;
+    *((int *)v3 + 12) = 0;
+    *((int *)v3 + 15) = v7;
+    v12.left = a2;
+    v12.bottom = a3 + v7;
+    v9 = *((int *)v3 + 2);
+    v12.top = a3;
+    (*(void (__stdcall **)(int, int, int, IDirectDrawSurface4 *, RECT *, signed int))(*(int *)v9 + 28))(
+      v9,
+      0,
+      0,
+      pRenderer->pFrontBuffer4,
+      &v12,
+      16);
+    if ( !*((char *)v3 + 90) || *((char *)v3 + 128) & 1 )
+    {
+      v10 = (struct IDirectDrawSurface4 *)*((int *)v3 + 1);
+      v11.dwSize = 100;
+      v11.dwDDFX = 8;
+      pRenderer->pFrontBuffer4->Blt(
+        &v12,
+        v10,
+        (LPRECT)((char *)v3 + 48),
+        16812032u,
+        &v11);
+    }
+    *((char *)v3 + 88) = 1;
+    LeaveCriticalSection(&pGame->pThreadWardInstance->cs2);
+    result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;*/
+  return 0;
+}
+
+//----- (0046BA8D) --------------------------------------------------------
+char AsyncMouse::_46BA8D(int a2, int a3)
+{
+  __debugbreak();
+  /*
+  void *v3; // esi@1
+  DWORD v4; // eax@1
+
+  v3 = this;
+  v4 = timeGetTime();
+  if ( v4 - *((int *)v3 + 16) <= 0x32 )
+  {
+    *((char *)v3 + 91) = *((char *)v3 + 90) == 1;
+    *((char *)v3 + 90) = 0;
+  }
+  else
+  {
+    if ( *((char *)v3 + 90) )
+      *((char *)v3 + 91) = 0;
+    else
+      *((char *)v3 + 91) = 1;
+    *((char *)v3 + 90) = 1;
+  }
+  if ( a2 != *((int *)v3 + 17) || a3 != *((int *)v3 + 18) )
+  {
+    *((int *)v3 + 16) = v4;
+    *((int *)v3 + 17) = a2;
+    *((int *)v3 + 18) = a3;
+  }
+  return *((char *)v3 + 90);*/
+  return 0;
+}
+
+//----- (0046BAEC) --------------------------------------------------------
+void AsyncMouse::_46BAEC()
+{
+  void *v1; // esi@1
+
+  v1 = this;
+  EnterCriticalSection(&pGame->pThreadWardInstance->cs2);
+  *((char *)v1 + 88) = 0;
+}
+
+//----- (0046BB0A) --------------------------------------------------------
+void AsyncMouse::_46BB0A()
+{
+  __debugbreak();
+  /*
+  void *v1; // esi@1
+  int v2; // eax@1
+  int v3; // edx@1
+  int v4; // ecx@1
+  int v5; // edx@1
+  int v6; // eax@1
+  char v7; // zf@1
+  struct IDirectDrawSurface4 *v8; // ST08_4@8
+  int v9; // [sp+8h] [bp-74h]@8
+  int v10; // [sp+Ch] [bp-70h]@8
+  int v11; // [sp+6Ch] [bp-10h]@1
+  int v12; // [sp+70h] [bp-Ch]@1
+  int v13; // [sp+74h] [bp-8h]@1
+  int v14; // [sp+78h] [bp-4h]@1
+
+  v1 = this;
+  v2 = *((int *)this + 17) - *((int *)this + 10);
+  v3 = *((int *)this + 14);
+  v4 = *((int *)this + 18) - *((int *)this + 11);
+  v11 = v2;
+  v5 = v2 + v3;
+  v6 = *((int *)v1 + 15);
+  v12 = v4;
+  v7 = *((char *)v1 + 90) == 0;
+  v13 = v5;
+  v14 = v4 + v6;
+  if ( v7 || *((char *)v1 + 128) & 1 )
+  {
+    if ( *((char *)v1 + 88) )
+      pRenderer->pFrontBuffer4->BltFast(
+        *((int *)v1 + 8),
+        *((int *)v1 + 9),
+        (LPDIRECTDRAWSURFACE4)*((int *)v1 + 2),
+        (LPRECT)((char *)v1 + 48),
+        16u);
+    (*(void (__stdcall **)(int, int, int, IDirectDrawSurface4 *, int *, signed int))(**((int **)v1 + 2) + 28))(
+      *((int *)v1 + 2),
+      0,
+      0,
+      pRenderer->pFrontBuffer4,
+      &v11,
+      16);
+  }
+  if ( *((char *)v1 + 90) && !(*((char *)v1 + 128) & 1) )
+  {
+    v8 = (struct IDirectDrawSurface4 *)*((int *)v1 + 1);
+    v9 = 100;
+    v10 = 8;
+    pRenderer->pFrontBuffer4->Blt(
+      (LPRECT)&v11,
+      v8,
+      (LPRECT)((char *)v1 + 48),
+      16812032u,
+      (LPDDBLTFX)&v9);
+  }
+  LeaveCriticalSection(&pGame->pThreadWardInstance->cs2);*/
+}
+
+//----- (0046BBD0) --------------------------------------------------------
+void *AsyncMouse::Clip()
+{
+  __debugbreak();
+  /*
+  void *result; // eax@1
+  std::string v1; // [sp-18h] [bp-30h]@2
+  const char *v2; // [sp-8h] [bp-20h]@2
+  int v3; // [sp-4h] [bp-1Ch]@2
+  RECT Rect; // [sp+0h] [bp-18h]@1
+  std::string *v5; // [sp+10h] [bp-8h]@2
+  int a3; // [sp+17h] [bp-1h]@2
+
+  SetWindowPos(hWnd, HWND_MESSAGE|0x2, 320, 240, 640, 480, 0);
+  Rect.left = 325;
+  Rect.top = 245;
+  Rect.right = 326;
+  Rect.bottom = 246;
+  result = (void *)ClipCursor(&Rect);
+  if ( !result )
+  {
+          MessageBoxW(nullptr, L"Could not clip cursor to screen!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\MouseAsync.cpp:827", 0);
+  }
+  return result;*/
+  return 0;
+}
+
+//----- (0046BC4E) --------------------------------------------------------
+void __stdcall AsyncMouse::AsyncMouseThread(int a1)
+{
+  __debugbreak();
+  /*
+  while ( 1 )
+  {
+    while ( !pAsyncMouse )
+      Sleep(1);
+    if ( !AsyncMouse::Thread(pAsyncMouse) )
+      ExitThread(0);
+    Sleep(18);
+  }*/
+}
+
+//----- (0046BC73) --------------------------------------------------------
+void AsyncMouse::dtor_sub_46BC73()
+{
+  __debugbreak();
+  /*
+  int v1; // edi@1
+  void **v2; // ebx@1
+  void *v3; // esi@1
+  void *v4; // eax@2
+  int v5; // [sp+0h] [bp-4h]@1
+
+  v5 = this;
+  v1 = this;
+  v2 = *(void ***)(this + 4);
+  v3 = *v2;
+  while ( v3 != v2 )
+  {
+    v4 = v3;
+    v3 = *(void **)v3;
+    AsyncMouse::unk_46BD2D((void *)v1, (int)&v5, v4);
+  }
+  free(*(void **)(v1 + 4));
+  *(int *)(v1 + 4) = 0;
+  *(int *)(v1 + 8) = 0;*/
+}
+
+//----- (0046BCAB) --------------------------------------------------------
+int AsyncMouse::_46BCAB()
+{
+  __debugbreak();
+  /*
+  void *v1; // ebx@1
+  void **v2; // edi@1
+  void *v3; // esi@1
+  void *v4; // eax@2
+  int result; // eax@2
+  int v6; // [sp+0h] [bp-4h]@1
+
+  v6 = this;
+  v1 = (void *)this;
+  v2 = *(void ***)(this + 4);
+  v3 = *v2;
+  while ( v3 != v2 )
+  {
+    v4 = v3;
+    v3 = *(void **)v3;
+    result = AsyncMouse::unk_46BD2D(v1, (int)&v6, v4);
+  }
+  return result;*/
+  return 0;
+}
+// 46BCAB: using guessed type int __thiscall AsyncMouse__46BCAB(int);
+
+//----- (0046BCD2) --------------------------------------------------------
+int AsyncMouse::unk_46BCD2(int a2, int a3, int a4)
+{
+  __debugbreak();
+  /*
+  void *v4; // edi@1
+  void *v5; // eax@1
+  void *v6; // esi@1
+  int result; // eax@1
+
+  v4 = this;
+  v5 = AsyncMouse::unk_46BD09((void *)a3, *(void **)(a3 + 4));
+  v6 = v5;
+  *(int *)(a3 + 4) = v5;
+  **((int **)v5 + 1) = v5;
+  AsyncMouse::unk_46BD66((char *)v5 + 8, a4);
+  result = a2;
+  ++*((int *)v4 + 2);
+  *(int *)a2 = v6;
+  return result;*/
+  return 0;
+}
+// 46BD66: using guessed type int __fastcall AsyncMouse__unk__46BD66(int, int);
+
+//----- (0046BD09) --------------------------------------------------------
+void *AsyncMouse::unk_46BD09(void *a1, void *a2)
+{
+  __debugbreak();
+  /*
+  void *result; // eax@1
+  void *v3; // ecx@1
+  void *v4; // ecx@3
+
+  result = operator new(0x18u);
+  v3 = a1;
+  if ( !a1 )
+    v3 = result;
+  *(int *)result = v3;
+  v4 = a2;
+  if ( !a2 )
+    v4 = result;
+  *((int *)result + 1) = v4;
+  return result;*/
+  return 0;
+}
+
+//----- (0046BD2D) --------------------------------------------------------
+int AsyncMouse::unk_46BD2D(int a2, void *a3)
+{
+  __debugbreak();
+  /*
+  void *v3; // edi@1
+  int v4; // ebx@1
+  int result; // eax@1
+
+  v3 = this;
+  v4 = *(int *)a3;
+  **((int **)a3 + 1) = *(int *)a3;
+  *(int *)(*(int *)a3 + 4) = *((int *)a3 + 1);
+  (**((void (__stdcall ***)(int))a3 + 2))(0);
+  free(a3);
+  result = a2;
+  --*((int *)v3 + 2);
+  *(int *)a2 = v4;
+  return result;*/
+  return 0;
+}
+
+//----- (0046BD66) --------------------------------------------------------
+int AsyncMouse::unk_46BD66(int a1, int a2)
+{
+  int result; // eax@2
+
+  if ( a1 )
+  {
+    *(int *)(a1 + 4) = *(int *)(a2 + 4);
+    *(int *)(a1 + 8) = *(int *)(a2 + 8);
+    result = *(int *)(a2 + 12);
+    *(int *)(a1 + 12) = result;
+    //*(int *)a1 = &AsyncMouse::unk::vdtor_ptr;
+  }
+  return result;
+}
+// 46BD66: using guessed type int __fastcall AsyncMouse__unk__46BD66(int, int);
+// 4D8734: using guessed type int (__stdcall *AsyncMouse__unk__vdtor_ptr)(char);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+//----- (0043B9FF) --------------------------------------------------------
+DirectInputMouse *__thiscall DirectInputMouse::DirectInputMouse(DirectInputMouse *this)
+{
+  DirectInputMouse *v1; // esi@1
+  HRESULT v2; // eax@5
+  signed int v4; // [sp-18h] [bp-24h]@3
+  char *v5; // [sp-14h] [bp-20h]@3
+  int v6; // [sp-10h] [bp-1Ch]@3
+  const char *v7; // [sp-Ch] [bp-18h]@3
+  int v8; // [sp-8h] [bp-14h]@3
+  unsigned int v9; // [sp-4h] [bp-10h]@3
+  CheckHRESULT_stru0 v10; // [sp+8h] [bp-4h]@5
+
+  v1 = this;
+  this->field_8 = 0;
+  LOBYTE(this->field_1C) = 0;
+  this->field_28 = 0;
+  this->vdestructor_ptr = (int)&DirectInputMouse_pvdtor;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    v9 = 1;
+    v8 = 30;
+    v7 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputMouse.cpp";
+    v6 = 0;
+    v5 = (char *)&this->pDirectInput;
+    v4 = 1280;
+  }
+  else
+  {
+    v9 = 1;
+    v8 = 28;
+    v7 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputMouse.cpp";
+    v6 = 0;
+    v5 = (char *)&this->pDirectInput;
+    v4 = 768;
+  }
+  v2 = DirectInputCreateA(hInstance, v4, v5, v6);
+  CheckHRESULT(&v10, v2, v7, v8, v9);
+  DirectInputMouse::CreateDevice(v1);
+  DirectInputMouse::43BB18(v1);
+  v1->field_20 = 0;
+  v1->field_24 = 0;
+  return v1;
+}
+// 4C8880: using guessed type int __stdcall DirectInputCreateA(int, int, int, int);
+// 4D8608: using guessed type int (__stdcall *DirectInputMouse_pvdtor)(char);
+
+//----- (0043BA80) --------------------------------------------------------
+void *__thiscall DirectInputMouse::vdtor(void *this, bool a2)
+{
+  void *v2; // esi@1
+
+  v2 = this;
+  DirectInputMouse::dtor(this);
+  if ( a2 & 1 )
+    free(v2);
+  return v2;
+}
+
+//----- (0043BA9C) --------------------------------------------------------
+int __thiscall DirectInputMouse::dtor(void *this)
+{
+  void *v1; // esi@1
+  int v2; // eax@1
+  int result; // eax@3
+
+  v1 = this;
+  v2 = *((int *)this + 2);
+  *(int *)this = &DirectInputMouse_pvdtor;
+  if ( v2 )
+  {
+    (*(void (__stdcall **)(int))(*(int *)v2 + 32))(v2);
+    (*(void (__stdcall **)(int))(**((int **)v1 + 2) + 8))(*((int *)v1 + 2));
+    *((int *)v1 + 2) = 0;
+  }
+  result = (*(int (__stdcall **)(int))(**((int **)v1 + 1) + 8))(*((int *)v1 + 1));
+  *((int *)v1 + 1) = 0;
+  return result;
+}
+// 4D8608: using guessed type int (__stdcall *DirectInputMouse_pvdtor)(char);
+
+//----- (0043BACE) --------------------------------------------------------
+void __thiscall DirectInputMouse::CreateDevice(DirectInputMouse *this)
+{
+  DirectInputMouse *v1; // esi@1
+  HRESULT v2; // eax@1
+  CheckHRESULT_stru0 v3; // [sp+4h] [bp-4h]@1
+
+  v1 = this;
+  v2 = ((int (__stdcall *)(int, int, int, int, int))this->pDirectInput->lpVtbl->field_10)(
+         this->pDirectInput,
+         2,
+         DirectInputMouse_enumerator,
+         this,
+         1);
+  CheckHRESULT(&v3, v2, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputMouse.cpp", 57, 1u);
+  if ( !LOBYTE(v1->field_1C) )
+  {
+    v3.vdestructor_ptr = (void (__thiscall ***)(CheckHRESULT_stru0 *, bool))"Error: No mouse found";
+    _CxxThrowException((int)&v3, (int)&dword_4DBD94);
+  }
+}
+// 43BC61: using guessed type int __stdcall DirectInputMouse_enumerator(int, int);
+// 4DBD94: using guessed type int dword_4DBD94;
+
+//----- (0043BB18) --------------------------------------------------------
+int __thiscall DirectInputMouse::43BB18(DirectInputMouse *this)
+{
+  char *v1; // esi@1
+  HRESULT v2; // eax@1
+  HRESULT v3; // eax@1
+  HRESULT v4; // eax@1
+  unsigned int v6; // [sp+0h] [bp-Ch]@0
+  CheckHRESULT_stru0 v7; // [sp+8h] [bp-4h]@1
+
+  v1 = (char *)&this->field_8;
+  v2 = ((int (__stdcall *)(int, int, int, int, int))this->pDirectInput->lpVtbl->field_C)(
+         this->pDirectInput,
+         &this->field_C,
+         &this->field_8,
+         0,
+         "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputMouse.cpp");
+  CheckHRESULT(&v7, v2, (const char *)0x40, 1, v6);
+  v3 = (*(int (__stdcall **)(int, int))(**(int **)v1 + 44))(*(int *)v1, dword_4C9920);
+  CheckHRESULT(&v7, v3, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputMouse.cpp", 65, 1u);
+  v4 = (*(int (__stdcall **)(int, int, int))(**(int **)v1 + 52))(*(int *)v1, hWnd, 6);
+  CheckHRESULT(&v7, v4, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputMouse.cpp", 66, 1u);
+  return (*(int (__cdecl **)(int))(**(int **)v1 + 28))(*(int *)v1);
+}
+// 4C9920: using guessed type int dword_4C9920[16];
+
+//----- (0043BB89) --------------------------------------------------------
+bool __thiscall DirectInputMouse::43BB89(DirectInputMouse *this)
+{
+  DirectInputMouse *v1; // esi@1
+  bool result; // eax@1
+  HRESULT v3; // eax@5
+  __int32 v4; // ecx@6
+  __int32 v5; // eax@6
+  __int32 v6; // edx@6
+  int v7; // ecx@12
+  bool v8; // ecx@12
+  signed int v9; // edx@12
+  HRESULT a2; // [sp+4h] [bp-14h]@3
+  int v11; // [sp+8h] [bp-10h]@12
+  char v12; // [sp+10h] [bp-8h]@18
+  char v13; // [sp+11h] [bp-7h]@20
+  char v14; // [sp+12h] [bp-6h]@22
+  char v15; // [sp+13h] [bp-5h]@24
+  char v18; // [sp+14h] [bp-4h]@5
+
+  v1 = this;
+  result = this->field_8;
+  if ( result )
+  {
+    if ( (*(int (__stdcall **)(bool, signed int, HRESULT *))(*(int *)result + 36))(result, 16, &a2) == -2147024866
+      && !(*(int (__stdcall **)(int))(*(int *)v1->field_8 + 28))(v1->field_8) )
+    {
+      v3 = (*(int (__stdcall **)(int, signed int, HRESULT *))(*(int *)v1->field_8 + 36))(v1->field_8, 16, &a2);
+      CheckHRESULT((CheckHRESULT_stru0 *)&v18, v3, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\DirectInputMouse.cpp", 80, 1u);
+    }
+    v4 = v1->field_20 + a2;
+    v5 = 640;
+    v6 = v1->field_20 + a2;
+    if ( v4 >= 640 )
+      v6 = 640;
+    if ( v6 >= 0 )
+    {
+      if ( v4 < 640 )
+        v5 = v1->field_20 + a2;
+    }
+    else
+    {
+      v5 = 0;
+    }
+    v7 = v11;
+    v1->field_20 = v5;
+    v8 = v1->field_24 + v7;
+    result = 480;
+    v9 = v8;
+    if ( v8 >= 480 )
+      v9 = 480;
+    if ( v9 >= 0 )
+    {
+      if ( v8 < 480 )
+        result = v8;
+    }
+    else
+    {
+      result = 0;
+    }
+    v1->field_28 = 0;
+    v1->field_24 = result;
+    if ( v12 & 0x80 )
+      v1->field_28 = 1;
+    if ( v13 & 0x80 )
+      v1->field_28 |= 2u;
+    if ( v14 & 0x80 )
+      v1->field_28 |= 4u;
+    if ( v15 & 0x80 )
+      v1->field_28 |= 8u;
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+    LOBYTE(result) = 0;
+  }
+  return result;
+}
+
+//----- (0043BC61) --------------------------------------------------------
+signed int __stdcall DirectInputMouse_enumerator(int a1, int a2)
+{
+  signed int result; // eax@2
+
+  if ( *(char *)(a1 + 36) & 2 )
+  {
+    *(int *)(a2 + 12) = *(int *)(a1 + 4);
+    *(int *)(a2 + 16) = *(int *)(a1 + 8);
+    *(int *)(a2 + 20) = *(int *)(a1 + 12);
+    *(int *)(a2 + 24) = *(int *)(a1 + 16);
+    *(char *)(a2 + 28) = 1;
+    result = 0;
+  }
+  else
+  {
+    result = 1;
+  }
+  return result;
+}
+// 43BC61: using guessed type int __stdcall DirectInputMouse_enumerator(int, int);
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mouse.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,186 @@
+#pragma once
+#include "OSAPI.h"
+
+#include "VectorTypes.h"
+
+
+
+/*  107 */
+#pragma pack(push, 1)
+struct ThreadWard
+{
+  //----- (00438B0B) --------------------------------------------------------
+  inline ThreadWard()
+  {
+    InitializeCriticalSection(&csAsyncMouse);
+    InitializeCriticalSection(&cs2);
+    InitializeCriticalSection(&cs3);
+    InitializeCriticalSection(&csAsyncKeyboard);
+  }
+
+  //----- (00438B54) --------------------------------------------------------
+  virtual ~ThreadWard()
+  {
+  ThreadWard *v1; // esi@1
+
+  v1 = this;
+  //this->vdestructor_ptr = &ThreadWard_destructors;
+  DeleteCriticalSection(&this->csAsyncKeyboard);
+  DeleteCriticalSection(&v1->cs3);
+  DeleteCriticalSection(&v1->cs2);
+  DeleteCriticalSection(&v1->csAsyncMouse);
+  }
+
+  void (__thiscall ***vdestructor_ptr)(ThreadWard *, bool);
+  _RTL_CRITICAL_SECTION csAsyncMouse;
+  _RTL_CRITICAL_SECTION cs2;
+  _RTL_CRITICAL_SECTION cs3;
+  _RTL_CRITICAL_SECTION csAsyncKeyboard;
+};
+#pragma pack(pop)
+
+/*  106 */
+#pragma pack(push, 1)
+struct Mouse
+{
+  //----- (00467E4E) --------------------------------------------------------
+  inline Mouse(ThreadWard *pWard)
+  {
+    uCursorTextureID = 0;
+    uCursorTextureID_2 = 0;
+    hWnd = 0;
+    pCursorBitmap_sysmem = 0;
+    field_34 = 0;
+    pCursorBitmap2_sysmem = 0;
+    pCursorBitmap3_sysmembits_16bit = 0;
+    ptr_90 = 0;
+    pWard = pWard;
+  }
+
+  void GetClickPos(unsigned int *pX, unsigned int *pY);
+  void RemoveHoldingItem();
+  void SetCursorBitmapFromItemID(unsigned int uItemID);
+  void SetCurrentCursorBitmap();
+  void SetCursorBitmap(const char *pName);
+  LONG _469AE4();
+  void ClearCursor();
+  void AllocCursorSystemMem();
+  void *DoAllocCursorMem();
+  POINT *GetCursorPos(POINT *p);
+  void Initialize(HWND hWnd);
+  void Deactivate();
+  void DrawCursor();
+  void _469E1C();
+  void _469E24();
+  void DrawCursorToTarget();
+  void _469EA4();
+  void Activate(int bActive);
+  void SetMouseClick(int x, int y);
+
+
+  unsigned int uPointingObjectID;
+  unsigned int bActive;
+  int field_8;
+  int field_C;
+  unsigned int bInitialized;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  unsigned int uCursorTextureID;
+  unsigned int uCursorTextureID_2;
+  HWND hWnd;
+  unsigned __int16 *pCursorBitmap_sysmem;
+  int field_34;
+  unsigned __int8 *pCursorBitmap2_sysmem;
+  unsigned __int16 *pCursorBitmap3_sysmembits_16bit;
+  int field_40;
+  int field_44;
+  int field_48;
+  int field_4C;
+  int field_50;
+  int field_54;
+  int uCursorBitmapPitch;
+  int field_5C[13];
+  void *ptr_90;
+  int field_94;
+  int field_98;
+  int field_9C;
+  int field_A0;
+  int field_A4;
+  int field_A8;
+  int field_AC;
+  int field_B0;
+  int field_B4;
+  int field_B8;
+  int field_BC;
+  int field_C0;
+  Vec2_int_ pCursorBitmapPos;
+  int uCursorBitmapWidth;
+  int uCursorBitmapHeight;
+  int field_D4;
+  int field_D8;
+  int field_DC;
+  int field_E0;
+  Vec4_int_ pCursorBitmapRect;
+  char field_F4;
+  char pCurrentCursorName[11];
+  int field_100;
+  int field_104;
+  unsigned int uMouseClickX;
+  unsigned int uMouseClickY;
+  ThreadWard *pWard;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct AsyncMouse
+{
+   AsyncMouse(struct IDirectDrawSurface *);
+  ~AsyncMouse();
+
+  char Initialize(LPVOID lpParameter);
+  char LoadCursor(const char *pContainer);
+  char LoadCursorImage();
+  char _46B072();
+  char CreateDisrectInputMouse();
+  int _46B0ED();
+  void Resume();
+  void Suspend();
+  char _46B1DD();
+  bool DrawCursor(struct Texture *a1, struct IDirectDrawSurface4 *a2, int a3);
+  bool _46B289(int a2, char a3);
+  void SetHotspot(float hotspotx, float hotspoty);
+  int UpdateData(int a2);
+  char Thread();
+  void _46B492(int a2);
+  void _46B5D5(int a2);
+  void _46B736_consume_click_lists(char a2);
+  void _46B76F();
+  void _46B879();
+  int _46B944();
+  char _46B958(int a2, int a3);
+  char _46BA8D(int a2, int a3);
+  void _46BAEC();
+  void _46BB0A();
+  void *Clip();
+  void dtor_sub_46BC73();
+  int _46BCAB();
+  int unk_46BCD2(int a2, int a3, int a4);
+  void *unk_46BD09(void *a1, void *a2);
+  int unk_46BD2D(int a2, void *a3);
+  int unk_46BD66(int a1, int a2);
+
+  static void __stdcall AsyncMouseThread(int a1);
+
+  void _409E3D(char a2);
+  void Release();
+};
+#pragma pack(pop)
+
+
+
+
+extern Mouse *pMouse;
+extern AsyncMouse *pAsyncMouse;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NPC.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,128 @@
+#pragma once
+
+
+struct NPCTopic
+{
+  const char *pTopic;
+  const char *pText;
+};
+
+extern NPCTopic pNPCTopics[789];
+
+
+
+
+
+/*  136 */
+#pragma pack(push, 1)
+struct NPCData
+{
+  char *pName;
+  unsigned int uPortraitID;
+  unsigned int uFlags;
+  int fame;
+  int rep;
+  int house;
+  unsigned int uProfession;
+  int greet;
+  int joins;
+  int field_24;
+  unsigned int bDrawSomeAnim;
+  int evtb;
+  int evtc;
+  int evtd;
+  int evte;
+  int evtf;
+  int uSex;
+  int bHasUsedTheAbility;
+  int news_topic;
+};
+#pragma pack(pop)
+
+
+/*  138 */
+#pragma pack(push, 1)
+struct NPCProfession
+{
+  unsigned int uHirePrice;
+  char *pBenefits;
+  char *pActionText;
+  char *pJoinText;
+  char *pDismissText;
+};
+#pragma pack(pop)
+
+
+/*  139 */
+#pragma pack(push, 1)
+struct NPCStats_stru0
+{
+  int field_0;
+  char field_4[60];
+};
+#pragma pack(pop)
+
+/*  140 */
+#pragma pack(push, 1)
+struct NPCGreeting
+{
+  char *pGreeting1;
+  char *pGreeting2;
+};
+#pragma pack(pop)
+
+
+
+/*  137 */
+#pragma pack(push, 1)
+struct NPCStats
+{
+  inline NPCStats():
+    pNPCTextTXT_Raw(nullptr), pNPCTopicTXT_Raw(nullptr), pNPCDistTXT_Raw(nullptr)
+  {
+    uNumNPCNames[0] = uNumNPCNames[1] = 0;
+  }
+
+  void Initialize2();
+  void Initialize1();
+  void Initialize();
+  void Release();
+  bool InitializeAdditionalNPCs(NPCData *a2, int a3, int a4, int a5);
+  void _476C60();
+
+
+  NPCData pNPCData[501];
+  NPCData pNewNPCData[501];
+  char *pNPCNames[540][2];
+  int field_13A58;
+  int field_13A5C;
+  int field_13A60;
+  int field_13A64;
+  int field_13A68;
+  NPCProfession pProfessions[58];
+  NPCData array_13EF4[100];
+  char *pCatchPhrases[52];
+  char *pNPCNames2[500];
+  NPCStats_stru0 array_16544[77];
+  int field_17884;
+  int field_17888;
+  NPCGreeting pNPCGreetings[205];
+  unsigned __int16 pGroups[51];
+  unsigned __int16 pGroups_copy[51];
+  int field_17FC0;
+  unsigned int uNumNewNPCs;
+  int field_17FC8;
+  unsigned int uNumNPCProfessions;
+  unsigned int uNumNPCNames[2];
+  char *pNPCDataTXT_Raw;
+  char *pNPCNamesTXT_Raw;
+  char *pNPCProfTXT_Raw;
+  char *pNPCNewsTXT_Raw;
+  char *pNPCTopicTXT_Raw;
+  char *pNPCTextTXT_Raw;
+  char *pNPCDistTXT_Raw;
+  char *pNPCGreetTXT_Raw;
+  char *pNCPGroupTXT_Raw;
+};
+#pragma pack(pop)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OSAPI.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,40 @@
+#include "OSAPI.h"
+#include "OSInfo.h"
+#include "Log.h"
+
+
+OSVersion *pVersion = nullptr;
+
+
+//----- (00462C94) --------------------------------------------------------
+int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE, wchar_t *lpCmdLine, int nShowCmd)
+{
+  Log::Initialize();
+  
+  //if (HWND hMM7Window = FindWindowW(L"MM7", 0))
+  if (HWND hMM7Window = FindWindowW(L"M&MTrilogy", 0))
+  {
+    if (IsIconic(hMM7Window))
+      ShowWindow(hMM7Window, SW_RESTORE);
+    SetForegroundWindow(GetLastActivePopup(hMM7Window));
+    return 0;
+  }
+  HWND hPrevWindow = GetActiveWindow();
+
+  pVersion = new OSVersion;
+  {
+    Log::Warning(L"OS init: ok");
+
+    extern bool MM_Main(const wchar_t *pCmdLine);
+    MM_Main(lpCmdLine);
+  }
+  delete pVersion;
+  pVersion = nullptr;
+
+  SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+  if (hPrevWindow)
+    SetActiveWindow(hPrevWindow);
+
+  __debugbreak();
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OSAPI.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,8 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include <MMSystem.h>
+#pragma comment(lib, "winmm.lib")
+
+#undef DrawText
+#undef PlaySound
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OSInfo.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,31 @@
+#pragma once
+#include "OSAPI.h"
+
+/*  293 */
+#pragma pack(push, 1)
+struct OSVersion
+{
+  //----- (004AD48F) --------------------------------------------------------
+  OSVersion()
+  {
+    bInitialized = false;
+    pVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
+    if (GetVersionExA(&pVersionInfo))
+      bInitialized = true;
+  }
+
+  //----- (004AD4BA) --------------------------------------------------------
+  virtual ~OSVersion()
+  {
+    bInitialized = false;
+  }
+
+
+  //void (__thiscall ***vdestructor_ptr)(OSVersion *, bool);
+  OSVERSIONINFOA pVersionInfo;
+  int bInitialized;
+};
+#pragma pack(pop)
+
+
+extern struct OSVersion *pVersion; // idb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ObjectList.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,67 @@
+#pragma once
+
+
+
+
+/*  324 */
+enum OBJECT_DESC_FLAGS
+{
+  OBJECT_DESC_NO_SPRITE = 0x1,
+  OBJECT_DESC_NO_COLLISION = 0x2,
+  OBJECT_DESC_TEMPORARY = 0x4,
+  OBJECT_DESC_SFT_LIFETIME = 0x8,
+  OBJECT_DESC_UNPICKABLE = 0x10,
+  OBJECT_DESC_NO_GRAVITY = 0x20,
+  OBJECT_DESC_INTERACTABLE = 0x40,
+  OBJECT_DESC_BOUNCE = 0x80,
+  OBJECT_DESC_TRIAL_PARTICLE = 0x100,
+  OBJECT_DESC_TRIAL_FIRE = 0x200,
+  OBJECT_DESC_TRIAL_LINE = 0x400,
+};
+
+
+
+
+/*   56 */
+#pragma pack(push, 1)
+struct ObjectDesc
+{
+  char field_0[32];
+  __int16 uObjectID;
+  __int16 uRadius;
+  __int16 uHeight;
+  __int16 uFlags;
+  unsigned __int16 uSpriteID;
+  __int16 uLifetime;
+  unsigned int uParticleTrailColor;
+  __int16 uSpeed;
+  char uParticleTrailColorR;
+  char uParticleTrailColorG;
+  char uParticleTrailColorB;
+  char field_35_clr;
+  char field_36_clr;
+  char field_37_clr;
+};
+#pragma pack(pop)
+
+/*   57 */
+#pragma pack(push, 1)
+struct ObjectList
+{
+  inline ObjectList():  //----- (004583D5)
+    uNumObjects(0), pObjects(nullptr)
+  {}
+
+  void ToFile();
+  void FromFile(void *pSerialized);
+  bool FromFileTxt(const char *Args);
+  void InitializeSprites();
+  __int16 ObjectIDByItemID(unsigned __int16 uItemID);
+
+
+  unsigned int uNumObjects;
+  struct ObjectDesc *pObjects;
+};
+#pragma pack(pop)
+
+extern struct ObjectList *pObjectList;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Outdoor.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,3156 @@
+#include <assert.h>
+
+#include "Outdoor.h"
+#include "Party.h"
+#include "LayingItem.h"
+#include "LOD.h"
+#include "Render.h"
+#include "MapInfo.h"
+#include "Allocator.h"
+#include "Weather.h"
+#include "PaletteManager.h"
+#include "GUIProgressBar.h"
+#include "AudioPlayer.h"
+#include "IndoorCamera.h"
+#include "DecorationList.h"
+#include "TileFrameTable.h"
+#include "Math.h"
+#include "ObjectList.h"
+#include "Game.h"
+#include "Actor.h"
+#include "Chest.h"
+#include "stru123.h"
+#include "Time.h"
+#include "Viewport.h"
+#include "Events.h"
+
+#include "mm7_data.h"
+//#include "MM7.h"
+
+
+
+
+
+OutdoorLocation *pOutdoor = new OutdoorLocation;
+OutdoorCamera *pOutdoorCamera;
+
+
+stru149 stru_8019C8;
+stru148 array_77EC08[2000];
+Surf stru_80C980;
+Edge defaultEdge; // weak
+Edge stru_80C9A4;
+Edge stru_80C9D8;
+
+
+//----- (0047A59E) --------------------------------------------------------
+void OutdoorLocation::ExecDraw(unsigned int bRedraw)
+{
+  int v1; // edi@1
+  unsigned int v2; // ebx@1
+  int v3; // ST18_4@3
+  int v4; // ST04_4@19
+  int v5; // eax@19
+
+  v1 = 0;
+  v2 = bRedraw;
+  if ( viewparams->field_54 )
+    v1 = 2;
+  pIndoorCamera->sRotationX = pParty->sRotationX;
+  pIndoorCamera->sRotationY = pParty->sRotationY;
+  pIndoorCamera->pos.x = pParty->vPosition.x
+                      - ((unsigned __int64)(stru_5C6E00->SinCos(pParty->sRotationY)
+                                          * (signed __int64)pParty->field_18) >> 16);
+  v3 = stru_5C6E00->SinCos(pParty->sRotationY - stru_5C6E00->uIntegerHalfPi);
+  pIndoorCamera->field_4C = v1;
+  pIndoorCamera->pos.y = pParty->vPosition.y - ((unsigned __int64)(v3 * (signed __int64)pParty->field_18) >> 16);
+  pIndoorCamera->pos.z = pParty->vPosition.z + pParty->sEyelevel;
+  if ( v2 || pRenderer->pRenderD3D )
+  {
+    ResetStru148s();
+    pOutdoorCamera->RotationToInts();
+    sub_481ED9_MessWithOutdoorCamera();
+  }
+  pIndoorCamera->uMapGridCellX = WorldPosToGridCellX(pParty->vPosition.x);
+  pIndoorCamera->uMapGridCellZ = WorldPosToGridCellZ(pParty->vPosition.y);
+  if ( v2 )
+  {
+    Software_ResetNewEdges();
+    sub_487DA9();
+    ptr_80C97C_Surfs = pSurfs;
+    ptr_80C978_Edges = pEdges;
+  }
+  if ( pParty->uCurrentMinute != pOutdoor->uLastSunlightUpdateMinute )
+    pOutdoor->UpdateSunlightVectors();
+  pOutdoor->UpdateFog();
+  pGame->pIndoorCameraD3D->Reset_list_0037C();
+  if ( !v2 )
+  {
+    if ( !pRenderer->pRenderD3D )
+    {
+      pRenderer->OnOutdoorRedrawSW();
+      goto LABEL_16;
+    }
+    //goto LABEL_14;
+	pRenderer->DrawSkyD3D();
+    pRenderer->DrawBuildingsD3D();
+    pRenderer->DrawBezierTerrain();
+    goto LABEL_16;
+  }
+  if ( pRenderer->pRenderD3D )
+  {
+//LABEL_14:
+    pRenderer->DrawSkyD3D();
+    pRenderer->DrawBuildingsD3D();
+    pRenderer->DrawBezierTerrain();
+    goto LABEL_16;
+  }
+  pRenderer->DrawBuildingsSW();
+  pRenderer->DrawBezierTerrain();
+  sr_sub_486F92_MessWithEdgesAndSpans();
+  pOutdoorCamera->_487355();
+LABEL_16:
+  pMobileLightsStack->uNumLightsActive = 0;
+  pStationaryLightsStack->uNumLightsActive = 0;
+  if ( !pRenderer->pRenderD3D )
+  {
+    pRenderer->ExecOutdoorDrawSW();
+    pGame->pIndoorCameraD3D->_438240_draw_lits();
+  }
+  pGame->PushStationaryLights(-1);
+  pGame->PrepareBloodsplats();
+  if ( v2 )
+  {
+    v4 = WorldPosToGridCellZ(pParty->vPosition.y);
+    v5 = WorldPosToGridCellX(pParty->vPosition.x);
+    pOutdoor->_47EF60(v5, v4, 1);
+  }
+  pGame->uFlags2 &= 0xFFFFFFFEu;
+  if ( pRenderer->pRenderD3D && pRenderer->bUsingSpecular )
+    pGame->pLightmapBuilder->uFlags |= 1u;
+  else
+    pGame->pLightmapBuilder->uFlags &= 0xFFFFFFFEu;
+  uNumDecorationsDrawnThisFrame = 0;
+  _unused000 = 0;
+  uNumSpritesDrawnThisFrame = 0;
+  uNumBillboardsToDraw = 0;
+  DrawActors();
+  if ( !pOutdoorCamera->bDoNotRenderDecorations )
+    pRenderer->DrawDecorations();
+  pRenderer->DrawLayingItems_Shooting_Magic_ODM();
+  pRenderer->TransformBillboardsAndSetPalettesODM();
+  sub_485F53((Vec2_int_ *)unnamed_6BE060);
+}
+
+
+
+//----- (00441CFF) --------------------------------------------------------
+void OutdoorLocation::Draw()
+{
+  unsigned int v0; // ecx@1
+
+  v0 = 1;
+  if ( !(pParty->uFlags & 2) && !(pGame->uFlags2 & 1) )
+    v0 = 0;
+  pOutdoor->ExecDraw(v0);
+  pGame->DrawParticles();
+  pWeather->Draw();
+  array_5118E8._440F07();
+}
+
+
+//----- (00488E23) --------------------------------------------------------
+double OutdoorLocation::GetFogDensityByTime()
+{
+  int v1; // eax@3
+  double v2; // st7@3
+
+  if ( pParty->uCurrentHour < 5 )
+    goto LABEL_9;
+  if ( pParty->uCurrentHour >= 6 )
+  {
+    if ( pParty->uCurrentHour < 0x14 )
+    {
+      pWeather->field_FA0 = 0;
+      v2 = 0.0;
+      return v2 * 0.016666668;
+    }
+    if ( pParty->uCurrentHour < 0x15 )
+    {
+      v1 = 0;
+      v2 = (double)(pParty->uCurrentHour - 20) * 60.0 + (double)(signed int)pParty->uCurrentMinute;
+      goto LABEL_4;
+    }
+LABEL_9:
+    v2 = 60.0;
+    pWeather->field_FA0 = 1;
+    return v2 * 0.016666668;
+  }
+  v1 = 0;
+  v2 = 60.0 - (double)(60 * pParty->uCurrentHour + pParty->uCurrentMinute - 300);
+LABEL_4:
+  pWeather->field_FA0 = v1;
+  return v2 * 0.016666668;
+}
+
+//----- (00488EB1) --------------------------------------------------------
+int OutdoorLocation::GetSomeOtherTileInfo(int sX, int sY)
+{
+  OutdoorLocation *v3; // esi@1
+  unsigned int v4; // edi@1
+  unsigned int v5; // eax@1
+  int result; // eax@5
+
+  v3 = this;
+  v4 = WorldPosToGridCellZ(sY);
+  v5 = WorldPosToGridCellX(sX);
+  if ( (v5 & 0x80000000u) != 0 || (signed int)v5 > 127 || (v4 & 0x80000000u) != 0 || (signed int)v4 > 127 )
+    result = 0;
+  else
+    result = ActuallyGetSomeOtherTileInfo(v5, v4);
+  return result;
+}
+// 47F44B: using guessed type int __stdcall WorldPosToGridCellX(int);
+// 47F458: using guessed type int __stdcall WorldPosToGridCellZ(int);
+
+//----- (00488EEF) --------------------------------------------------------
+unsigned int OutdoorLocation::GetTileTexture(int sX, int sZ)
+{
+  OutdoorLocation *v3; // esi@1
+  unsigned int v4; // edi@1
+  unsigned int v5; // eax@1
+  unsigned int result; // eax@5
+
+  v3 = this;
+  v4 = WorldPosToGridCellZ(sZ);
+  v5 = WorldPosToGridCellX(sX);
+  if ( (v5 & 0x80000000u) != 0 || (signed int)v5 > 127 || (v4 & 0x80000000u) != 0 || (signed int)v4 > 127 )
+    result = -1;
+  else
+    result = DoGetTileTexture(v5, v4);
+  return result;
+}
+// 47F44B: using guessed type int __stdcall WorldPosToGridCellX(int);
+// 47F458: using guessed type int __stdcall WorldPosToGridCellZ(int);
+
+//----- (00488F2E) --------------------------------------------------------
+int OutdoorLocation::GetHeightOnTerrain(int sX, int sZ)
+{
+  int result; // eax@5
+
+  if ( sX < 0 || sX > 127 || sZ < 0 || sZ > 127 )
+    result = 0;
+  else
+    result = DoGetHeightOnTerrain(sX, sZ);
+  return result;
+}
+
+//----- (00488F5C) --------------------------------------------------------
+bool OutdoorLocation::Initialize(const char *pFilename, int File, size_t uRespawnInterval, int thisa)
+{
+  OutdoorLocation *v5; // esi@1
+  bool result; // eax@2
+
+  v5 = this;
+  if ( pFilename )
+  {
+    Release();
+    pBitmaps_LOD->ReleaseAll2();
+    pSprites_LOD->DeleteSomeOtherSprites();
+    pSpriteFrameTable->ResetSomeSpriteFlags();
+    pIcons_LOD->ReleaseAll2();
+    sub_46080D();
+    TryLoadLevelFromLOD();
+    if ( !Load((char *)pFilename, (ODMFace *)File, uRespawnInterval, thisa) )
+    {
+      MessageBoxA(0, "Error!", "Couldn't Load Map!", 0);
+      CreateDebugLocation();
+    }
+    day_attrib = v5->day_attrib;
+    day_fogrange_1 = v5->day_fogrange_1;
+    day_fogrange_2 = v5->day_fogrange_2;
+    if ( Is_out15odm_underwater() )
+      SetUnderwaterFog();
+    _6BE134_odm_main_tile_group = v5->pTileTypes[0].uTileGroup;
+    result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+//----- (0048901B) --------------------------------------------------------
+bool OutdoorLocation::Release2()
+{
+  Release();
+  pOutdoorCamera->ReleaseSoftwareDrawBuffers();
+  return true;
+}
+
+//----- (0048902E) --------------------------------------------------------
+bool OutdoorLocation::GetTravelDestination(signed int sPartyX, signed int sPartyZ, char *pOut, signed int a5)
+{
+  OutdoorLocation *v5; // esi@1
+  char *v6; // eax@3
+  int v7; // eax@3
+  int v8; // edx@3
+  signed int v9; // esi@7
+  int v10; // esi@23
+  signed int v11; // eax@23
+  int v12; // ST14_4@25
+  signed int v14; // [sp-4h] [bp-84h]@6
+  char Str; // [sp+8h] [bp-78h]@3
+  int a5a; // [sp+94h] [bp+14h]@3
+
+  auto Source = this;
+
+  v5 = Source;
+  if ( a5 < 10
+    || strlen(Source->pLevelFilename) != 9
+    || (strcpy(&Str, v5->pLevelFilename),
+        _strlwr(&Str),
+        v6 = strtok(&Str, "out"),
+        v6[2] = 0,
+        v7 = atoi(v6),
+        v8 = v7,
+        a5a = v7,
+        v7 < 1)
+    || v7 > 15 )
+    return 0;
+  if ( sPartyX < -22528 )
+  {
+    v14 = 4;
+LABEL_7:
+    v9 = v14;
+    goto LABEL_14;
+  }
+  if ( sPartyX > 22528 )
+  {
+    v14 = 3;
+    goto LABEL_7;
+  }
+  if ( sPartyZ < -22528 )
+  {
+    v14 = 2;
+    goto LABEL_7;
+  }
+  if ( sPartyZ <= 22528 )
+    return 0;
+  v9 = 1;
+LABEL_14:
+  if ( v7 == 14 )
+  {
+    if ( v9 == 4 )
+    {
+      if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(0) )
+      {
+        uDefaultTravelTime_ByFoot = 1;
+        strcpy(pOut, "out15.odm");
+        uLevel_StartingPointType = 3;
+LABEL_18:
+        LOWORD(pParty->uFlags) &= 0xFD7Bu;
+        return 1;
+      }
+      v8 = a5a;
+    }
+  }
+  else
+  {
+    if ( v7 == 15 && v9 == 3 )
+    {
+      uDefaultTravelTime_ByFoot = 1;
+      strcpy(pOut, "out14.odm");
+      uLevel_StartingPointType = 4;
+      goto LABEL_18;
+    }
+  }
+  v10 = v9 + 4 * v8;
+  v11 = (unsigned __int8)aTiletableLoadU[v10 + 39];
+  if ( v11 >= 1 && v11 <= 15 )
+  {
+    v12 = (unsigned __int8)aTiletableLoadU[v10 + 39];
+    uDefaultTravelTime_ByFoot = (unsigned __int8)byte_4ECA93[v10];
+    sprintf(pOut, "out%02d.odm", v12);
+    uLevel_StartingPointType = (unsigned __int8)byte_4ECACF[v10];
+    return 1;
+  }
+  return 0;
+}
+// 6BD07C: using guessed type int uDefaultTravelTime_ByFoot;
+// 6BE35C: using guessed type int uLevel_StartingPointType;
+
+//----- (0048917E) --------------------------------------------------------
+void OutdoorLocation::MessWithLUN()
+{
+  OutdoorLocation *v1; // esi@1
+  unsigned int *v2; // ebp@1
+  unsigned int v3; // eax@1
+  unsigned __int16 v4; // ax@1
+  signed int v5; // ebx@1
+
+  v1 = this;
+  v2 = this->pSpriteIDs_LUN;
+  this->pSpriteIDs_LUN[0] = -1;
+  this->pSpriteIDs_LUN[2] = pSpriteFrameTable->FastFindSprite("LUN1-4");
+  v1->pSpriteIDs_LUN[4] = pSpriteFrameTable->FastFindSprite("LUN1-2");
+  v1->pSpriteIDs_LUN[6] = pSpriteFrameTable->FastFindSprite("LUN3-4");
+  v1->uSpriteID_LUNFULL = pSpriteFrameTable->FastFindSprite("LUNFULL");
+  v1->uSpriteID_LUN3_4_cp = pSpriteFrameTable->FastFindSprite("LUN3-4");
+  v1->uSpriteID_LUN1_2_cp = pSpriteFrameTable->FastFindSprite("LUN1-2");
+  v3 = pSpriteFrameTable->FastFindSprite("LUN1-4");
+  v1->field_D60 = -1;
+  v1->uSpriteID_LUN1_4_cp = v3;
+  v1->field_CF0 = 4;
+  v1->field_CF8 = 4;
+  v1->field_D00 = 4;
+  LOWORD(v3) = *(short *)v2;
+  v1->pSpriteIDs_LUN[1] = 0;
+  v1->pSpriteIDs_LUN[3] = 0;
+  v1->pSpriteIDs_LUN[5] = 0;
+  v1->pSpriteIDs_LUN[7] = 0;
+  v1->field_CE8 = 0;
+  LOWORD(v1->field_D3C) = v3;
+  v1->field_D40 = 0;
+  v1->field_D44 = 0;
+  v1->field_D48 = 0;
+  v1->field_D4C = 131072;
+  v1->field_D5C = 0;
+  v1->field_D64 = 0;
+  v4 = pSpriteFrameTable->FastFindSprite("LUN-SUN");
+  v1->field_D28 = -1;
+  v1->field_D08 = 0;
+  v1->field_D0C = 0;
+  v1->field_D10 = 0;
+  v1->field_D24 = 0;
+  v1->field_D2C = 0;
+  v1->uSpriteID_LUN_SUN = v4;
+  v1->field_D14 = -131072;
+  v5 = 8;
+  do
+  {
+    pSpriteFrameTable->InitializeSprite(*v2);
+    v2 += 2;
+    --v5;
+  }
+  while ( v5 );
+  pSpriteFrameTable->InitializeSprite(v1->uSpriteID_LUN_SUN);
+}
+
+//----- (004892E6) --------------------------------------------------------
+unsigned int OutdoorLocation::UpdateSunlightVectors()
+{
+  unsigned int result; // eax@1
+  OutdoorLocation *v2; // esi@1
+  unsigned int v3; // edi@3
+  int v4; // ebx@3
+  int v5; // eax@3
+  int v6; // eax@3
+  int v7; // ecx@3
+  double v8; // st7@4
+
+  result = pParty->uCurrentHour;
+  v2 = this;
+  if ( pParty->uCurrentHour >= 5 && pParty->uCurrentHour < 0x15 )
+  {
+    v3 = pParty->uCurrentMinute + 60 * (pParty->uCurrentHour - 5);
+    v4 = (signed int)(v3 * stru_5C6E00->uIntegerPi) / 960;
+    v5 = stru_5C6E00->SinCos((signed int)(v3 * stru_5C6E00->uIntegerPi) / 960);
+    v2->field_D1C = 0;
+    v2->field_D18 = v5;
+    v6 = stru_5C6E00->SinCos(v4 - stru_5C6E00->uIntegerHalfPi);
+    v7 = v2->field_D18;
+    v2->field_D20 = v6;
+    v2->vSunlight.x = -v7;
+    v2->vSunlight.y = -v2->field_D1C;
+    v2->vSunlight.z = -v6;
+    if ( (signed int)v3 >= 480 )
+      v8 = (double)(signed int)(960 - v3);
+    else
+      v8 = (double)(signed int)v3;
+    v2->field_CBC_terrain_triangles_shade_type = (signed __int64)(20.0 - v8 * 0.002083333333333333 * 20.0);
+    result = pParty->uCurrentMinute;
+    v2->uLastSunlightUpdateMinute = pParty->uCurrentMinute;
+  }
+  return result;
+}
+
+//----- (004893C1) --------------------------------------------------------
+void OutdoorLocation::UpdateFog()
+{
+  fFogDensity = GetFogDensityByTime();
+}
+
+//----- (004893CF) --------------------------------------------------------
+int OutdoorLocation::GetNumFoodRequiredToRestInCurrentPos(int x, signed int y, int z)
+{
+  OutdoorLocation *v4; // ebx@1
+  signed int v5; // edi@4
+  int v6; // eax@4
+  int v7; // eax@4
+  int v8; // eax@4
+  int v9; // eax@5
+  int v10; // eax@6
+  int v11; // eax@7
+  int v12; // eax@8
+  int v15; // [sp+8h] [bp-8h]@2
+  int v16; // [sp+Ch] [bp-4h]@2
+
+  v4 = this;
+  if ( pParty->uFlags & 8
+    || (v15 = 0,
+        v16 = 0,
+        sub_46D49E_prolly_get_world_y_under_party(x, y, z, pParty->uDefaultPartyHeight, &v15, &v16, 0),
+        v16)
+    || v15 )
+    return 2;
+  v5 = WorldPosToGridCellX(pParty->vPosition.x);
+  v6 = WorldPosToGridCellZ(pParty->vPosition.y);
+  v7 = _47ED83(v5, v6 - 1);
+  v8 = pTileTable->pTiles[_47ECC1(v7)].uTerrainType;
+  if ( v8 )
+  {
+    v9 = v8 - 1;
+    if ( !v9 )
+      return 3;
+    v10 = v9 - 1;
+    if ( !v10 )
+      return 5;
+    v11 = v10 - 1;
+    if ( !v11 || (v12 = v11 - 3) == 0 )
+      return 4;
+    if ( v12 == 1 )
+      return 3;
+    return 2;
+  }
+  return 1;
+}
+// 47F44B: using guessed type int __stdcall WorldPosToGridCellX(int);
+// 47F458: using guessed type int __stdcall WorldPosToGridCellZ(int);
+
+//----- (00489487) --------------------------------------------------------
+int OutdoorLocation::SetFog()
+{
+  int result; // eax@1
+  int v2; // esi@1
+  int v3; // edx@5
+  unsigned __int8 *v4; // eax@5
+  int v5; // ecx@5
+  int v6; // esi@7
+  unsigned __int8 v7; // al@9
+
+  strcpy(pOutdoor->pLevelFilename, pCurrentMapName);
+  result = pMapStats->GetMapInfo(pCurrentMapName);
+  v2 = result;
+  if ( result < 1 || result == 7 || result == 8 || result > 15 )
+    return result;
+  day_attrib &= 0xFFFFFFFEu;
+  v3 = rand() % 100;
+  v4 = (unsigned __int8 *)&byte_4ECB0C[4 * v2];
+  v5 = *v4;
+  if ( v3 < v5 )
+  {
+    day_fogrange_1 = 4096;
+    day_fogrange_2 = 8192;
+LABEL_13:
+    day_attrib |= 1u;
+    goto LABEL_14;
+  }
+  v6 = v4[1];
+  if ( v3 < v6 + v5 )
+  {
+    day_fogrange_2 = 4096;
+LABEL_12:
+    day_fogrange_1 = 0;
+    goto LABEL_13;
+  }
+  v7 = v4[2];
+  if ( v7 && v3 < v5 + v6 + v7 )
+  {
+    day_fogrange_2 = 2048;
+    goto LABEL_12;
+  }
+LABEL_14:
+  if ( Is_out15odm_underwater() )
+    SetUnderwaterFog();
+  pOutdoor->day_fogrange_1 = day_fogrange_1;
+  pOutdoor->day_fogrange_2 = day_fogrange_2;
+  result = day_attrib;
+  pOutdoor->day_attrib = day_attrib;
+  return result;
+}
+// 6BE030: using guessed type int day_attrib;
+// 6BE040: using guessed type int day_fogrange_1;
+// 6BE044: using guessed type int day_fogrange_2;
+
+//----- (00482170) --------------------------------------------------------
+bool ODMFace::IsBackfaceCulled(ODMFace *a1, RenderVertexSoft *a2, stru148 *a3)
+{
+  stru148 *v3; // edi@1
+  RenderVertexSoft *v4; // esi@1
+  unsigned int v5; // edx@1
+  RenderVertexSoft *v6; // ecx@2
+  double v7; // st7@5
+  double v8; // st6@5
+  double v9; // st5@5
+  double v10; // st6@9
+  double v11; // st5@9
+  double v12; // st4@9
+  bool result; // eax@16
+  double v14; // ST2C_8@17
+  double v15; // ST20_8@17
+  double v16; // ST0C_8@17
+  double v17; // ST0C_8@17
+  float v18; // [sp+8h] [bp-38h]@5
+  float v19; // [sp+10h] [bp-30h]@5
+  float v20; // [sp+14h] [bp-2Ch]@5
+  float v21; // [sp+18h] [bp-28h]@5
+  float v22; // [sp+1Ch] [bp-24h]@5
+  float v23; // [sp+24h] [bp-1Ch]@5
+  float v24; // [sp+28h] [bp-18h]@5
+  float v25; // [sp+30h] [bp-10h]@5
+  float v26; // [sp+34h] [bp-Ch]@5
+  float v27; // [sp+38h] [bp-8h]@5
+  float v28; // [sp+3Ch] [bp-4h]@5
+  float a3a; // [sp+48h] [bp+8h]@5
+  float a3b; // [sp+48h] [bp+8h]@17
+  float a3c; // [sp+48h] [bp+8h]@17
+  float a3d; // [sp+48h] [bp+8h]@17
+  float a3e; // [sp+48h] [bp+8h]@17
+
+  v3 = a3;
+  v4 = a2;
+  v5 = a3->uNumVertices;
+  if ( (signed int)v5 < 3 )
+    goto LABEL_20;
+  v6 = &v4[v5 - 1];
+  if ( v4->vWorldPosition.z == v4[1].vWorldPosition.z && v4[1].vWorldPosition.z == v6->vWorldPosition.z )
+    *(int *)&a3->flags |= 0x10u;
+  v19 = v4[1].vWorldViewPosition.x - v4->vWorldViewPosition.x;
+  v18 = v4[1].vWorldViewPosition.y - v4->vWorldViewPosition.y;
+  v20 = v4[1].vWorldViewPosition.z - v4->vWorldViewPosition.z;
+  v21 = v6->vWorldViewPosition.x - v4->vWorldViewPosition.x;
+  v22 = v6->vWorldViewPosition.y - v4->vWorldViewPosition.y;
+  v23 = v6->vWorldViewPosition.z - v4->vWorldViewPosition.z;
+  v28 = v4[1].vWorldPosition.x - v4->vWorldPosition.x;
+  v27 = v4[1].vWorldPosition.y - v4->vWorldPosition.y;
+  a3a = v4[1].vWorldPosition.z - v4->vWorldPosition.z;
+  v7 = v6->vWorldPosition.x - v4->vWorldPosition.x;
+  v8 = v6->vWorldPosition.y - v4->vWorldPosition.y;
+  v9 = v6->vWorldPosition.z - v4->vWorldPosition.z;
+  v26 = v27 * v9 - v8 * a3a;
+  v24 = v7 * a3a - v9 * v28;
+  v25 = v8 * v28 - v7 * v27;
+  if ( v26 == 0.0 && v24 == 0.0 && v25 == 0.0 )
+  {
+    while ( 1 )
+    {
+      --v5;
+      if ( (signed int)v5 < 2 )
+        break;
+      v10 = v6->vWorldPosition.x - v4->vWorldPosition.x;
+      v11 = v6->vWorldPosition.y - v4->vWorldPosition.y;
+      v12 = v6->vWorldPosition.z - v4->vWorldPosition.z;
+      v26 = v27 * v12 - v11 * a3a;
+      v24 = v10 * a3a - v12 * v28;
+      v25 = v11 * v28 - v10 * v27;
+      if ( v26 != 0.0 )
+        break;
+      if ( v24 != 0.0 || v25 != 0.0 )
+        break;
+      --v6;
+    }
+    v21 = v6->vWorldViewPosition.x - v4->vWorldViewPosition.x;
+    v22 = v6->vWorldViewPosition.y - v4->vWorldViewPosition.y;
+    v23 = v6->vWorldViewPosition.z - v4->vWorldViewPosition.z;
+  }
+  if ( ((double)pIndoorCamera->pos.x - v4->vWorldPosition.x) * v26
+     + ((double)pIndoorCamera->pos.z - v4->vWorldPosition.z) * v25
+     + ((double)pIndoorCamera->pos.y - v4->vWorldPosition.y) * v24 > 0.0 )
+  {
+    a3b = v23 * v18 - v22 * v20;
+    v14 = a3b + 6.7553994e15;
+    v3->v_18.x = LODWORD(v14);
+    a3c = v21 * v20 - v23 * v19;
+    v15 = a3c + 6.7553994e15;
+    v3->v_18.y = LODWORD(v15);
+    a3d = v22 * v19 - v21 * v18;
+    v16 = a3d + 6.7553994e15;
+    v3->v_18.z = LODWORD(v16);
+    v3->_486089_normalize_v_18();
+    a3e = -((double)v3->v_18.x * v4->vWorldViewPosition.x)
+        - (double)v3->v_18.y * v4->vWorldViewPosition.y
+        - (double)v3->v_18.z * v4->vWorldViewPosition.z;
+    v17 = a3e + 6.7553994e15;
+    v3->field_24 = LODWORD(v17);
+    result = 1;
+  }
+  else
+  {
+LABEL_20:
+    result = 0;
+  }
+  return result;
+}
+
+
+//----- (0047C7A9) --------------------------------------------------------
+void OutdoorLocationTerrain::_47C7A9()
+{
+  this->field_10 = 0;
+  this->field_12 = 0;
+  this->field_16 = 0;
+  this->field_14 = 0;
+  this->field_1C = 0;
+  this->field_18 = 0;
+}
+
+//----- (0047C7C2) --------------------------------------------------------
+void OutdoorLocationTerrain::Release()
+{
+  if (pHeightmap)
+  {
+    pAllocator->FreeChunk(this->pHeightmap);
+    pHeightmap = nullptr;
+  }
+  if (pTilemap)
+  {
+    pAllocator->FreeChunk(pTilemap);
+    pTilemap = nullptr;
+  }
+  if (pAttributemap)
+  {
+    pAllocator->FreeChunk(pAttributemap);
+    pAttributemap = nullptr;
+  }
+  if (ptr_C)
+  {
+    pAllocator->FreeChunk(ptr_C);
+    ptr_C = nullptr;
+  }
+
+  _47C7A9();
+}
+
+//----- (0047C80A) --------------------------------------------------------
+int OutdoorLocationTerrain::_47C80A(int a2, int a3, int a4, int a5)
+{
+  OutdoorLocationTerrain *v5; // ebx@1
+  double v6; // st7@1
+  double v7; // st7@2
+  double v8; // st7@2
+  int result; // eax@3
+  int v10; // eax@4
+  int v11; // ecx@5
+  int v12; // ecx@6
+  int v13; // edi@7
+  int v14; // edx@9
+  int v15; // eax@15
+  unsigned __int8 *v16; // ebx@15
+  int v17; // eax@15
+  int v18; // ecx@15
+  int v19; // esi@15
+  int v20; // edi@15
+  int v21; // edx@15
+  int v22; // ecx@15
+  int v23; // ebx@15
+  int v24; // ecx@15
+  int v25; // ST28_4@15
+  double v26; // st7@15
+  double v27; // st6@15
+  double v28; // st5@15
+  double v29; // st7@15
+  double v30; // st7@16
+  double v31; // st7@17
+  int v32; // eax@21
+  double v33; // st7@21
+  double v34; // st6@21
+  double v35; // st5@21
+  double v36; // st7@21
+  double v37; // st7@22
+  double v38; // st7@23
+  int v39; // [sp+14h] [bp-34h]@8
+  int v40; // [sp+18h] [bp-30h]@15
+  int v41; // [sp+1Ch] [bp-2Ch]@15
+  int v42; // [sp+20h] [bp-28h]@15
+  OutdoorLocationTerrain *v43; // [sp+24h] [bp-24h]@1
+  int v44; // [sp+28h] [bp-20h]@21
+  float v45; // [sp+2Ch] [bp-1Ch]@1
+  float v46; // [sp+30h] [bp-18h]@1
+  float v47; // [sp+34h] [bp-14h]@1
+  int v48; // [sp+38h] [bp-10h]@7
+  int v49; // [sp+3Ch] [bp-Ch]@10
+  int v50; // [sp+40h] [bp-8h]@9
+  float v51; // [sp+44h] [bp-4h]@15
+  float v52; // [sp+44h] [bp-4h]@21
+  float v53; // [sp+50h] [bp+8h]@15
+  float v54; // [sp+50h] [bp+8h]@21
+  int v55; // [sp+54h] [bp+Ch]@15
+  float v56; // [sp+54h] [bp+Ch]@15
+  float v57; // [sp+54h] [bp+Ch]@21
+
+  v46 = -64.0;
+  v47 = -64.0;
+  v5 = this;
+  v45 = 64.0;
+  v43 = this;
+  v6 = sqrt(12288.0);
+  if ( v6 != 0.0 )
+  {
+    v7 = 1.0 / v6;
+    v45 = 64.0 * v7;
+    v8 = v7 * -64.0;
+    v46 = v8;
+    v47 = v8;
+  }
+  result = a3;
+  if ( a3 > a5 )
+  {
+    v10 = a5 ^ a3;
+    a5 ^= a3 ^ a5;
+    result = a5 ^ v10;
+  }
+  v11 = a2;
+  if ( a2 > a4 )
+  {
+    v12 = a4 ^ a2;
+    a4 ^= a2 ^ a4;
+    v11 = a4 ^ v12;
+  }
+  v13 = result - 1;
+  v48 = result - 1;
+  if ( result - 1 <= a5 )
+  {
+    v39 = v11 - 1;
+    do
+    {
+      v14 = v39;
+      v50 = v39;
+      if ( v39 <= a4 )
+      {
+        result = (v39 - 63) << 9;
+        v49 = (v39 - 63) << 9;
+        do
+        {
+          if ( v13 >= 0 && result >= -32256 && v13 <= 127 && result <= 32768 )
+          {
+            v15 = v5->field_10;
+            v55 = v15;
+            v16 = v5->pHeightmap;
+            v17 = (int)(&v16[v13 * v15] + v14);
+            v18 = -v13;
+            v19 = (64 - v13) << 9;
+            v20 = 32 * *(char *)v17;
+            v21 = 32 * *(char *)(v17 + 1);
+            v22 = (v18 + 63) << 9;
+            v41 = v22;
+            v23 = (int)(&v16[v55 * (v48 + 1)] + v50);
+            v24 = v22 - v19;
+            v40 = 32 * *(char *)v23;
+            v42 = 32 * *(char *)(v23 + 1);
+            v25 = v49 - 512 - v49;
+            v26 = (double)-((v20 - v21) * v24);
+            v51 = v26;
+            v27 = (double)-(v25 * (v42 - v21));
+            v53 = v27;
+            v28 = (double)(v25 * v24);
+            v56 = v28;
+            v29 = sqrt(v28 * v28 + v27 * v27 + v26 * v26);
+            if ( v29 != 0.0 )
+            {
+              v30 = 1.0 / v29;
+              v51 = v51 * v30;
+              v53 = v53 * v30;
+              v56 = v30 * v56;
+            }
+            v31 = (v56 * v47 + v53 * v46 + v51 * v45) * 31.0;
+            if ( v31 < 0.0 )
+              v31 = 0.0;
+            if ( v31 > 31.0 )
+              v31 = 31.0;
+            v44 = 2 * (v50 + v48 * v43->field_10);
+            v5 = v43;
+            *((char *)v43->ptr_C + v44 + 1) = (signed __int64)v31;
+            v32 = v49 - (v49 - 512);
+            v33 = (double)-((v42 - v40) * (v19 - v41));
+            v52 = v33;
+            v34 = (double)-(v32 * (v20 - v40));
+            v54 = v34;
+            v35 = (double)(v32 * (v19 - v41));
+            v57 = v35;
+            v36 = sqrt(v35 * v35 + v34 * v34 + v33 * v33);
+            if ( v36 != 0.0 )
+            {
+              v37 = 1.0 / v36;
+              v52 = v52 * v37;
+              v54 = v54 * v37;
+              v57 = v37 * v57;
+            }
+            v38 = (v57 * v47 + v54 * v46 + v52 * v45) * 31.0;
+            if ( v38 < 0.0 )
+              v38 = 0.0;
+            if ( v38 > 31.0 )
+              v38 = 31.0;
+            v13 = v48;
+            *((char *)v43->ptr_C + v44) = (signed __int64)v38;
+            v14 = v50;
+            result = v49;
+          }
+          ++v14;
+          result += 512;
+          v50 = v14;
+          v49 = result;
+        }
+        while ( v14 <= a4 );
+      }
+      ++v13;
+      v48 = v13;
+    }
+    while ( v13 <= a5 );
+  }
+  return result;
+}
+
+//----- (0047CB57) --------------------------------------------------------
+int OutdoorLocationTerrain::_47CB57(int a1, int a2, int a3)
+{
+  signed int result; // eax@2
+  unsigned __int16 *v5; // edx@3
+  double v6; // st7@3
+  char v7; // bl@3
+  int v8; // eax@3
+  int v9; // eax@4
+  int v10; // eax@5
+  double v11; // st6@7
+  signed int v12; // edi@7
+  int v13; // esi@9
+  char *v14; // esi@10
+  signed int v15; // ecx@10
+  char v16[256]; // [sp+4h] [bp-124h]@9
+  unsigned __int16 *v17; // [sp+104h] [bp-24h]@3
+  unsigned int v18; // [sp+108h] [bp-20h]@3
+  unsigned int v19; // [sp+10Ch] [bp-1Ch]@3
+  unsigned int v20; // [sp+110h] [bp-18h]@3
+  unsigned int v21; // [sp+114h] [bp-14h]@3
+  float v22; // [sp+118h] [bp-10h]@3
+  float v23; // [sp+11Ch] [bp-Ch]@3
+  int i; // [sp+120h] [bp-8h]@3
+  unsigned int v25; // [sp+124h] [bp-4h]@5
+  signed int a2a; // [sp+134h] [bp+Ch]@3
+  unsigned int a2b; // [sp+134h] [bp+Ch]@7
+  float a3a; // [sp+138h] [bp+10h]@7
+  int a3b; // [sp+138h] [bp+10h]@9
+
+  if ( pRenderer->pRenderD3D )
+  {
+    result = 0;
+  }
+  else
+  {
+    v5 = PaletteManager::Get_Dark_or_Red_LUT(a2, 0, 1);
+    v6 = 0.0;
+    v7 = LOBYTE(pRenderer->uTargetBBits);
+    v19 = pRenderer->uTargetRMask;
+    v21 = pRenderer->uTargetGMask;
+    v22 = 0.0;
+    v20 = pRenderer->uTargetBMask;
+    v8 = 0;
+    v17 = v5;
+    v23 = 0.0;
+    v18 = pRenderer->uTargetBBits;
+    a2a = 0;
+    for ( i = 0; i < a3; ++i )
+    {
+      v9 = *(char *)(v8 + a1);
+      if ( v9 )
+      {
+        v10 = v5[v9];
+        v6 = v6 + (double)((signed int)(v19 & v10) >> (LOBYTE(pRenderer->uTargetBBits) + LOBYTE(pRenderer->uTargetGBits)));
+        ++a2a;
+        v25 = v20 & v10;
+        v22 = (double)((signed int)(v21 & v10) >> SLOBYTE(pRenderer->uTargetBBits)) + v22;
+        v23 = (double)(signed int)(v20 & v10) + v23;
+      }
+      v8 = i + 1;
+    }
+    v11 = 1.0 / (double)a2a;
+    a3a = v11;
+    v25 = (signed __int64)(a3a * v22);
+    i = (signed __int64)(a3a * v23);
+    v12 = 0;
+    a2b = pRenderer->uTargetBBits + pRenderer->uTargetGBits;
+    while ( 1 )
+    {
+      v13 = v17[v12];
+      a3b = abs((__int64)(signed __int64)(v11 * v6) - ((signed int)(v19 & v17[v12]) >> a2b));
+      BYTE3(a3b) = abs((signed)v25 - ((signed int)(v21 & v13) >> v7)) + a3b;
+      v16[v12++] = abs((signed)i - (signed)(v20 & v13)) + BYTE3(a3b);
+      if ( v12 >= 256 )
+        break;
+      v7 = v18;
+    }
+    result = 0;
+    v14 = (char *)&pPaletteManager->field_D1600[42][23][116];
+    v15 = 0;
+    do
+    {
+      if ( (unsigned __int8)v16[v15] < (signed int)v14 )
+      {
+        v14 = (char *)(unsigned __int8)v16[v15];
+        result = v15;
+      }
+      ++v15;
+    }
+    while ( v15 < 256 );
+  }
+  return result;
+}
+// 47CB57: using guessed type char var_124[256];
+
+//----- (0047CCE2) --------------------------------------------------------
+bool OutdoorLocationTerrain::ZeroLandscape()
+{
+  OutdoorLocationTerrain *v1; // esi@1
+
+  v1 = this;
+  memset(this->pHeightmap, 0, 0x4000u);
+  memset(v1->pTilemap, 90, 0x4000u);
+  memset(v1->pAttributemap, 0, 0x4000u);
+  memset(v1->ptr_C, 0, 0x8000u);
+  v1->field_12 = 128;
+  v1->field_10 = 128;
+  v1->field_16 = 7;
+  v1->field_14 = 7;
+  v1->field_1C = 127;
+  v1->field_18 = 127;
+  return 1;
+}
+
+//----- (0047CD44) --------------------------------------------------------
+bool OutdoorLocationTerrain::Initialize()
+{
+  OutdoorLocationTerrain *v1; // esi@1
+  void *v2; // eax@1
+  bool result; // eax@2
+  void *v4; // eax@3
+  void *v5; // eax@4
+  void *v6; // eax@5
+
+  v1 = this;
+  v2 = pAllocator->AllocNamedChunk(this->pHeightmap, 0x4000u, "HMAP");
+  v1->pHeightmap = (unsigned __int8 *)v2;
+  if ( v2
+    && (v4 = pAllocator->AllocNamedChunk(v1->pTilemap, 0x4000u, "TMAP"),
+        (v1->pTilemap = (unsigned __int8 *)v4) != 0)
+    && (v5 = pAllocator->AllocNamedChunk(v1->pAttributemap, 0x4000u, "AMAP"),
+        (v1->pAttributemap = (unsigned __int8 *)v5) != 0) )
+  {
+    v6 = pAllocator->AllocNamedChunk(v1->ptr_C, 0x8000u, "DMAP");
+    v1->ptr_C = v6;
+    result = v6 != 0;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+//----- (0047CDE2) --------------------------------------------------------
+void OutdoorLocation::CreateDebugLocation()
+{
+  OutdoorLocation *v1; // esi@1
+  void *v2; // eax@1
+  void *v3; // ST14_4@1
+  void *v4; // eax@1
+  void *v5; // ST14_4@1
+  void *v6; // eax@1
+  unsigned int v7; // eax@1
+  char v8; // zf@1
+
+  v1 = this;
+  strcpy(this->pLevelFilename, "blank");
+  strcpy(v1->pLocationFileName, "i6.odm");
+  strcpy(v1->pLocationFileDescription, "MM6 Outdoor v1.00");
+  v1->uNumBModels = 0;
+  v1->pTileTypes[0].uTileGroup = 0;
+  v1->pTileTypes[1].uTileGroup = 5;
+  v1->pTileTypes[2].uTileGroup = 6;
+  v1->pTileTypes[3].uTileGroup = 10;
+  v1->LoadTileGroupIds();
+  v1->_47F3EA();
+  pAllocator->FreeChunk(v1->pBModels);
+  pAllocator->FreeChunk(v1->pSpawnPoints);
+  v1->pBModels = 0;
+  v1->pSpawnPoints = 0;
+  v1->pTerrain.Initialize();
+  v1->pTerrain.ZeroLandscape();
+  v1->pTerrain._47C80A(0, 0, 128, 128);
+  pAllocator->FreeChunk(v1->ptr_D4);
+  v1->ptr_D4 = 0;
+  v2 = pAllocator->AllocNamedChunk(0, 0x8000u, "CMAP");
+  v3 = v1->pOMAP;
+  v1->ptr_D4 = v2;
+  pAllocator->FreeChunk(v3);
+  v1->pOMAP = 0;
+  v4 = pAllocator->AllocNamedChunk(0, 0x10000u, "OMAP");
+  v1->pOMAP = (unsigned int *)v4;
+  memset(v4, 0, 0x10000u);
+  v5 = v1->pFaceIDLIST;
+  v1->numFaceIDListElems = 0;
+  pAllocator->FreeChunk(v5);
+  v1->pFaceIDLIST = 0;
+  v6 = pAllocator->AllocNamedChunk(0, 2u, "IDLIST");
+  v1->pFaceIDLIST = (unsigned __int16 *)v6;
+  *(short *)v6 = 0;
+  strcpy(v1->pSkyTextureName, pDefaultSkyTexture);
+  v1->uSky_TextureID = pBitmaps_LOD->LoadTexture(v1->pSkyTextureName);
+  strcpy(v1->pGroundTileset, byte_6BE124_cfg_textures_DefaultGroundTexture);
+  v7 = pBitmaps_LOD->LoadTexture(v1->pGroundTileset);
+  v8 = v1->uSky_TextureID == -1;
+  v1->uMainTile_BitmapID = v7;
+  if ( v8 )
+    Abortf("Invalid Sky Tex Handle");
+  if ( v1->uMainTile_BitmapID == -1 )
+    Abortf("Invalid Ground Tex Handle");
+}
+
+
+
+//----- (0047CF9C) --------------------------------------------------------
+void OutdoorLocation::Release()
+{
+  //OutdoorLocation *v1; // esi@1
+  //signed int v2; // edi@1
+  //int v3; // ebx@2
+  //void *v4; // ST24_4@4
+  //char *v5; // ebx@4
+  //void **v6; // esi@4
+
+  //v1 = this;
+  strcpy(pLevelFilename, "blank");
+  strcpy(pLocationFileName, "default.odm");
+  strcpy(pLocationFileDescription, "MM6 Outdoor v1.00");
+  strcpy(pSkyTextureName, "sky043");
+  strcpy(pGroundTileset, "hm005");
+
+  if (pBModels)
+  {
+    for (uint i = 0; i < uNumBModels; ++i)
+      pBModels[i].Release();
+
+    pAllocator->FreeChunk(pBModels);
+    pBModels = nullptr;
+    uNumBModels = 0;
+  }
+
+  if (pSpawnPoints)
+  {
+    pAllocator->FreeChunk(pSpawnPoints);
+    pSpawnPoints = nullptr;
+  }
+  uNumSpawnPoints = 0;
+
+  pTerrain.Release();
+
+  if (ptr_D4)
+  {
+    pAllocator->FreeChunk(ptr_D4);
+    ptr_D4 = nullptr;
+  }
+  if (pOMAP)
+  {
+    pAllocator->FreeChunk(pOMAP);
+    pOMAP = nullptr;
+  }
+  if (pFaceIDLIST)
+  {
+    pAllocator->FreeChunk(pFaceIDLIST);
+    pFaceIDLIST = nullptr;
+  }
+  if (pTerrainNormals)
+  {
+    pAllocator->FreeChunk(pTerrainNormals);
+    pTerrainNormals = nullptr;
+  }
+}
+
+//----- (0047D0A6) --------------------------------------------------------
+bool OutdoorLocation::Load(char *pFilename, ODMFace *File, size_t pNumItems, int thisa)
+{
+  //OutdoorLocation *pOutdoorLocation; // esi@1
+  /*bool result; // eax@9
+  bool v7; // ebx@9
+  size_t v8; // eax@10
+  void *v9; // eax@10
+  void *v10; // eax@10
+  void *v11; // eax@10
+  int v12; // ebx@11
+  BSPModel *v13; // eax@12
+  void *v14; // eax@12
+  BSPModel *v15; // ecx@12
+  void *v16; // eax@12
+  BSPModel *v17; // ecx@12
+  BSPModel *v18; // eax@12
+  __int16 v19; // ax@15
+  __int16 v20; // ax@16
+  int v21; // ecx@16
+  ODMFace *v22; // ebx@26
+  LayingItem *pItems; // ecx@27
+  unsigned int v24; // eax@28
+  //unsigned __int8 v25; // zf@28
+  //unsigned __int8 v26; // sf@28
+  ODMFace *v27; // eax@28
+  const char *i; // edx@29
+  unsigned __int16 v29; // ax@33
+  unsigned __int16 v30; // ax@37
+  int v31; // ecx@37
+  int v32; // eax@38
+  void *v33; // eax@38
+  TileDesc *v34; // eax@43
+  unsigned int v35; // eax@43
+  unsigned int v36; // edi@43
+  unsigned int v37; // edi@45*/
+  //size_t v38; // eax@50
+  FILE *v39; // eax@50
+  //unsigned int v40; // edi@56
+  //void *v41; // eax@56
+  //void *v42; // ebx@56
+  //const void *v43; // ebx@59
+  //const void *v44; // ebx@59
+  //unsigned int v45; // eax@59
+  //BSPModel *v46; // eax@59
+  //unsigned int v47; // ecx@59
+  //int v48; // ebx@60
+  //BSPModel *v49; // eax@61
+  //BSPModel *v50; // eax@61
+  //BSPModel *v51; // eax@61
+  //BSPModel *v52; // eax@61
+  //BSPModel *v53; // eax@61
+  //BSPModel *v54; // ecx@61
+  //BSPModel *v55; // ecx@61
+  //BSPModel *v56; // ecx@61
+  //void *v57; // ST24_4@61
+  //BSPModel *v58; // ecx@61
+  //void *v59; // ST18_4@61
+  //BSPModel *v60; // eax@61
+  //__int16 v61; // ax@64
+  unsigned __int16 v62; // ax@65
+  //ODMFace *v63; // ecx@65
+  //unsigned __int16 v64; // ax@80
+  //const char *v65; // ecx@80
+  //int v66; // eax@81
+  //void *v67; // eax@81
+  //int v68; // ecx@81
+  //void *v69; // eax@81
+  //unsigned int v70; // eax@81
+  //SpawnPointMM7 *v71; // eax@81
+  //unsigned int v72; // ecx@81
+  //size_t v73; // eax@81
+  //int v74; // edi@87
+  //void *v75; // edi@88
+  //unsigned int v76; // edx@94
+  //int v77; // ecx@94
+  //char *v78; // eax@95
+  //unsigned int v79; // edx@97
+  //unsigned int v80; // eax@99
+  //int v81; // eax@107
+  //void *v82; // edi@114
+  //size_t v83; // eax@120
+  //const void *v84; // edi@120
+  //const void *v85; // edi@120
+  //BSPModel *v86; // eax@124
+  //unsigned int v87; // eax@124
+  //BSPModel *v88; // eax@126
+  //BSPModel *v89; // eax@127
+  //ODMFace *v90; // eax@129
+  //const void *v91; // edi@138
+  //const void *v92; // edi@141
+  //const void *v93; // edi@141
+  //const void *v94; // edi@144
+  //const void *v95; // edi@144
+  //const char *v96; // edi@147
+  //unsigned int v97; // eax@147
+  //TileDesc *v98; // eax@147
+  //unsigned int v99; // eax@147
+  //int v100; // ecx@150
+  //unsigned int v101; // eax@157
+  int v102; // edi@159
+  //void *v103; // [sp-14h] [bp-B94h]@55
+  //void *v104; // [sp-10h] [bp-B90h]@59
+  //size_t v105; // [sp-Ch] [bp-B8Ch]@59
+  //char *v106; // [sp-8h] [bp-B88h]@59
+  int v107; // [sp-4h] [bp-B84h]@12
+  int v108; // [sp+0h] [bp-B80h]@10
+  char Src[968]; // [sp+10h] [bp-B70h]@110
+  char Dst[968]; // [sp+3D8h] [bp-7A8h]@50
+  char Str[256]; // [sp+7A0h] [bp-3E0h]@50
+  /*char DstBuf; // [sp+8A0h] [bp-2E0h]@10
+  __int32 Offset; // [sp+8A4h] [bp-2DCh]@10
+  __int32 v114; // [sp+8B0h] [bp-2D0h]@10
+  __int32 v115; // [sp+8BCh] [bp-2C4h]@10
+  __int32 v116; // [sp+8C8h] [bp-2B8h]@10
+  __int32 v117; // [sp+8D4h] [bp-2ACh]@10
+  __int32 v118; // [sp+8E0h] [bp-2A0h]@10
+  __int32 v119; // [sp+8ECh] [bp-294h]@10
+  __int32 v120; // [sp+8F8h] [bp-288h]@10
+  __int32 v121; // [sp+904h] [bp-27Ch]@10
+  __int32 v122; // [sp+910h] [bp-270h]@10
+  __int32 v123; // [sp+91Ch] [bp-264h]@10
+  __int32 v124; // [sp+928h] [bp-258h]@26
+  __int32 v125; // [sp+934h] [bp-24Ch]@35
+  __int32 v126; // [sp+940h] [bp-240h]@38
+  __int32 v127; // [sp+94Ch] [bp-234h]@38
+  __int32 v128; // [sp+958h] [bp-228h]@38
+  __int32 v129; // [sp+964h] [bp-21Ch]@38
+  __int32 v130; // [sp+970h] [bp-210h]@38
+  __int32 v131; // [sp+97Ch] [bp-204h]@38
+  __int32 v132; // [sp+988h] [bp-1F8h]@38
+  __int32 v133; // [sp+994h] [bp-1ECh]@38
+  __int32 v134; // [sp+9A0h] [bp-1E0h]@38
+  __int32 v135; // [sp+9ACh] [bp-1D4h]@38
+  __int32 v136; // [sp+9D0h] [bp-1B0h]@10*/
+  //char FileName[8]; // [sp+A20h] [bp-160h]@8
+  //char v138; // [sp+A28h] [bp-158h]@12
+  //int v139; // [sp+B1Ch] [bp-64h]@10
+  //char pContainer[32]; // [sp+B20h] [bp-60h]@1
+  //int *v141; // [sp+B40h] [bp-40h]@50
+  //__int64 v142; // [sp+B44h] [bp-3Ch]@55
+  //size_t pSource; // [sp+B4Ch] [bp-34h]@56
+  //int v144; // [sp+B50h] [bp-30h]@61
+  //int v145; // [sp+B54h] [bp-2Ch]@68
+  ODMHeader header; // [sp+B58h] [bp-28h]@50
+  //unsigned int pDestLen; // [sp+B68h] [bp-18h]@13
+  //FILE *ptr; // [sp+B6Ch] [bp-14h]@12
+  //void *v149; // [sp+B70h] [bp-10h]@19
+  char *Str2; // [sp+B74h] [bp-Ch]@12
+  //int v151; // [sp+B78h] [bp-8h]@59
+  //void *uSourceLen; // [sp+B7Ch] [bp-4h]@59
+
+  //pOutdoorLocation = this;
+  //strcpy(pContainer, pFilename);
+
+  if (bUnderwater)
+  {
+    pPaletteManager->pPalette_tintColor[0] = 0x10;
+    pPaletteManager->pPalette_tintColor[1] = 0xC2;
+    pPaletteManager->pPalette_tintColor[2] = 0x99;
+    pPaletteManager->pPalette_mistColor[0] = 0x25;
+    pPaletteManager->pPalette_mistColor[1] = 0x8F;
+    pPaletteManager->pPalette_mistColor[2] = 0x5C;
+  }
+  else
+  {
+    pPaletteManager->pPalette_tintColor[0] = 0;
+    pPaletteManager->pPalette_tintColor[1] = 0;
+    pPaletteManager->pPalette_tintColor[2] = 0;
+    if (pPaletteManager->pPalette_mistColor[0] != 0x80 ||
+        pPaletteManager->pPalette_mistColor[1] != 0x80 ||
+        pPaletteManager->pPalette_mistColor[2] != 0x80)
+    {
+      pPaletteManager->pPalette_mistColor[0] = 0x80;
+      pPaletteManager->pPalette_mistColor[1] = 0x80;
+      pPaletteManager->pPalette_mistColor[2] = 0x80;
+      pPaletteManager->RecalculateAll();
+    }
+  }
+
+  _6807E0_num_decorations_with_sounds_6807B8 = 0;
+  /*sprintf(FileName, "levels\\%s", pContainer);
+  if ( GetFileAttributesA(FileName) != -1 )
+  {
+    result = (bool)fopen(FileName, "rb");
+    v7 = result;
+    File = (ODMFace *)result;
+    if ( !result )
+      return result;
+    *(int *)thisa = 1;
+    v8 = strlen(pContainer);
+    v108 = 2;
+    *((char *)&v139 + v8) = 0;
+    viewparams->uTextureID_LocationMap = pIcons_LOD->LoadTexture(pContainer, (enum TEXTURE_TYPE)v108);
+    fread(&DstBuf, 0x180u, 1u, (FILE *)v7);
+    fseek((FILE *)v7, Offset, 0);
+    fread(this, 0xB0u, 1u, (FILE *)v7);
+    LoadTileGroupIds();
+    _47F3EA();
+    strcpy(pGroundTileset, "grastyl");
+    fseek((FILE *)v7, v114, 0);
+    fread(&uNumBModels, 4u, 1u, (FILE *)v7);
+    fseek((FILE *)v7, v115, 0);
+    fread(&uNumLayingItems, 4u, 1u, (FILE *)v7);
+    fseek((FILE *)v7, v116, 0);
+    fread(&uNumLevelDecorations, 4u, 1u, (FILE *)v7);
+    fseek((FILE *)v7, v117, 0);
+    fread(&uNumActors, 4u, 1u, (FILE *)v7);
+    fseek((FILE *)v7, v118, 0);
+    fread(&uNumChests, 4u, 1u, (FILE *)v7);
+    pTerrain.Initialize();
+    fseek((FILE *)v7, v119, 0);
+    fread(pTerrain.pHeightmap, 1u, 0x4000u, (FILE *)v7);
+    fseek((FILE *)v7, v120, 0);
+    fread(pTerrain.pTilemap, 1u, 0x4000u, (FILE *)v7);
+    fseek((FILE *)v7, v121, 0);
+    fread(pTerrain.pAttributemap, 1u, 0x4000u, (FILE *)v7);
+    pTerrain._47C80A(0, 0, 128, 128);
+    pAllocator->FreeChunk(ptr_D4);
+    ptr_D4 = 0;
+    v9 = pAllocator->AllocNamedChunk(0, 0x8000u, "CMAP");
+    v108 = (int)pOMAP;
+    ptr_D4 = v9;
+    pAllocator->FreeChunk((void *)v108);
+    pOMAP = 0;
+    v10 = pAllocator->AllocNamedChunk(0, 0x10000u, "OMAP");
+    v108 = 0;
+    pOMAP = (unsigned int *)v10;
+    fseek((FILE *)v7, v136, v108);
+    fread(&uNumTerrainNormals, 4u, 1u, (FILE *)v7);
+    fread(pTerrainSomeOtherData, 1u, 0x20000u, (FILE *)v7);
+    fread(pTerrainNormalIndices, 1u, 0x10000u, (FILE *)v7);
+    pTerrainNormals = (Vec3_float_ *)pAllocator->AllocNamedChunk(pTerrainNormals, 12 * uNumTerrainNormals, "TerNorm");
+    fread(pTerrainNormals, 1u, 12 * uNumTerrainNormals, (FILE *)v7);
+    v11 = pAllocator->AllocNamedChunk(pBModels, 188 * uNumBModels, "BDdata");
+    v108 = 0;
+    pBModels = (BSPModel *)v11;
+    fseek((FILE *)v7, v122, v108);
+    fread(pBModels, 0xBCu, uNumBModels, (FILE *)v7);
+    fseek((FILE *)v7, v123, 0);
+    pNumItems = 0;
+    if ( (signed int)uNumBModels > 0 )
+    {
+      v12 = 0;
+      while ( 1 )
+      {
+        pBModels[v12].pVertices.pVertices = 0;
+        pBModels[v12].pFaces = 0;
+        pBModels[v12].pFacesOrdering = 0;
+        pBModels[v12].pNodes = 0;
+        FileName[0] = 0;
+        v108 = (int)&pBModels[v12];
+        sprintfex(FileName, "%s", v108);
+        v13 = pBModels;
+        v138 = 0;
+        pBModels[v12].pVertices.pVertices = (Vec3_int_ *)pAllocator->AllocNamedChunk(v13[v12].pVertices.pVertices, 12 * v13[v12].pVertices.uNumVertices,
+                                                               FileName);
+        pBModels[v12].pFaces = (ODMFace *)pAllocator->AllocNamedChunk(pBModels[v12].pFaces, 308 * pBModels[v12].uNumFaces,
+                                                FileName);
+        pBModels[v12].pFacesOrdering = (unsigned __int16 *)pAllocator->AllocNamedChunk(pBModels[v12].pFacesOrdering,
+                                                                 2 * pBModels[v12].uNumFaces, FileName);
+        v14 = pAllocator->AllocNamedChunk(pBModels[v12].pNodes, 8 * pBModels[v12].uNumNodes, FileName);
+        v15 = pBModels;
+        v108 = (int)File;
+        v15[v12].pNodes = (BSPNode *)v14;
+        fread(pBModels[v12].pVertices.pVertices, 0xCu, pBModels[v12].pVertices.uNumVertices, (FILE *)v108);
+        fread(pBModels[v12].pFaces, 0x134u, pBModels[v12].uNumFaces, (FILE *)File);
+        fread(pBModels[v12].pFacesOrdering, 2u, pBModels[v12].uNumFaces, (FILE *)File);
+        fread(pBModels[v12].pNodes, 8u, pBModels[v12].uNumNodes, (FILE *)File);
+        v16 = malloc(10 * pBModels[v12].uNumFaces);
+        v107 = (int)File;
+        v17 = pBModels;
+        ptr = (FILE *)v16;
+        fread(v16, 0xAu, v17[v12].uNumFaces, (FILE *)File);
+        v18 = pBModels;
+        Str2 = 0;
+        if ( (signed int)v18[v12].uNumFaces > 0 )
+          break;
+LABEL_25:
+        free(ptr);
+        ++pNumItems;
+        ++v12;
+        if ( (signed int)pNumItems >= (signed int)uNumBModels )
+          goto LABEL_26;
+      }
+      pDestLen = 0;
+      pFilename = (char *)ptr;
+      while ( 1 )
+      {
+        thisa = (int)((char *)v18[v12].pFaces + pDestLen);
+        if ( !(*(char *)(thisa + 29) & 0x40) )
+          break;
+        v19 = pTextureFrameTable->FindTextureByName(pFilename);
+        *(short *)(thisa + 272) = v19;
+        if ( !v19 )
+        {
+          v20 = pBitmaps_LOD->LoadTexture(pFilename);
+          v21 = thisa;
+          *(char *)(v21 + 29) &= 0xBFu;
+LABEL_19:
+          *(short *)(v21 + 272) = v20;
+          v149 = (void *)(v20 != -1 ? &pBitmaps_LOD->pTextures[v20] : 0);
+          auto pTex = (Texture *)v149;
+          if (pTex)
+            pTex->palette_id2 = pPaletteManager->LoadPalette(pTex->palette_id1);
+          goto LABEL_20;
+        }
+        pTextureFrameTable->LoadAnimationSequenceAndPalettes(*(unsigned __int16 *)((char *)&pBModels[v12].pFaces->uTextureID + pDestLen));
+LABEL_20:
+        if ( *(short *)(thisa + 292) )
+        {
+          if ( ((ODMFace *)thisa)->HasEventHint() )
+            *(char *)(thisa + 30) |= 0x10u;
+          else
+            *(char *)(thisa + 30) &= 0xEFu;
+        }
+        ++Str2;
+        v18 = pBModels;
+        pDestLen += 308;
+        pFilename += 10;
+        if ( (signed int)Str2 >= (signed int)v18[v12].uNumFaces )
+          goto LABEL_25;
+      }
+      v20 = pBitmaps_LOD->LoadTexture(pFilename);
+      v21 = thisa;
+      goto LABEL_19;
+    }
+LABEL_26:
+    v22 = File;
+    fseek((FILE *)File, v124, 0);
+    fread(pLayingItems, 0x70u, uNumLayingItems, (FILE *)v22);
+    if ( (signed int)uNumLayingItems > 0 )
+    {
+      pItems = pLayingItems;
+      pNumItems = uNumLayingItems;
+      do
+      {
+        v24 = pItems->stru_24.uItemID;
+        thisa = 0;
+        v27 = (ODMFace *)(48 * v24);
+        v25 = pObjectList->uNumObjects == 0;
+        v26 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+        LOWORD(v27) = *(short *)((char *)&v27->pFacePlane.vNormal.x + (int)((char *)&pItemsTable + 24));
+        File = v27;
+        pItems->uItemType = (unsigned __int16)v27;
+        if ( v26 | v25 )
+        {
+LABEL_33:
+          v29 = 0;
+        }
+        else
+        {
+          for ( i = (const char *)&pObjectList->pObjects->uObjectID; (short)v27 != *(short *)i; i = pFilename )
+          {
+            ++thisa;
+            pFilename = (char *)i + 56;
+            if ( thisa >= (signed int)pObjectList->uNumObjects )
+              goto LABEL_33;
+            LOWORD(v27) = (short)File;
+          }
+          v29 = thisa;
+        }
+        pItems->uObjectDescID = v29;
+        ++pItems;
+        --pNumItems;
+      }
+      while ( pNumItems );
+    }
+    fseek((FILE *)v22, v125, 0);
+    fread(pLevelDecorations, 0x20u, uNumLevelDecorations, (FILE *)v22);
+    pNumItems = 0;
+    if ( (signed int)uNumLevelDecorations > 0 )
+    {
+      thisa = (int)pLevelDecorations;
+      do
+      {
+        fread(FileName, 1u, 0x20u, (FILE *)v22);
+        v30 = pDecorationList->GetDecorIdByName(FileName);
+        v31 = thisa;
+        ++pNumItems;
+        thisa += 32;
+        *(short *)v31 = v30;
+      }
+      while ( (signed int)pNumItems < (signed int)uNumLevelDecorations );
+    }
+    fseek((FILE *)v22, v126, 0);
+    fread(pActors, 0x344u, uNumActors, (FILE *)v22);
+    fseek((FILE *)v22, v127, 0);
+    fread(pChests, 0x14CCu, uNumChests, (FILE *)v22);
+    fseek((FILE *)v22, v128, 0);
+    fread(&field_DC, 4u, 1u, (FILE *)v22);
+    pAllocator->FreeChunk(pFaceIDLIST);
+    v32 = field_DC;
+    pFaceIDLIST = 0;
+    v33 = pAllocator->AllocNamedChunk(0, 2 * v32, "IDLIST");
+    v108 = (int)v22;
+    pFaceIDLIST = (unsigned __int16 *)v33;
+    fread(v33, 2u, field_DC, (FILE *)v108);
+    fseek((FILE *)v22, v129, 0);
+    fread(pOMAP, 4u, 0x4000u, (FILE *)v22);
+    fseek((FILE *)v22, v130, 0);
+    fread(&uNumSpawnPoints, 4u, 1u, (FILE *)v22);
+    pSpawnPoints = (SpawnPointMM7 *)pAllocator->AllocNamedChunk(pSpawnPoints, 24 * uNumSpawnPoints, "Spawn");
+    fseek((FILE *)v22, v131, 0);
+    fread(pSpawnPoints, 0x18u, uNumSpawnPoints, (FILE *)v22);
+    fseek((FILE *)v22, v132, 0);
+    fread(&ddm, 0x28u, 1u, (FILE *)v22);
+    fseek((FILE *)v22, v133, 0);
+    fread(&stru_5E4C90, 1u, 0xC8u, (FILE *)v22);
+    fseek((FILE *)v22, v134, 0);
+    fread(&uLastVisitDay, 1u, 0x38u, (FILE *)v22);
+    fseek((FILE *)v22, v135, 0);
+    fread(&uLastVisitDay, 1u, 4u, (FILE *)v22);
+    thisa = (int)pTileTypes;
+    pTileTable->InitializeTileset(4);
+    pTileTable->InitializeTileset(pTileTypes[0].uTileGroup);
+    pTileTable->InitializeTileset(pTileTypes[1].uTileGroup);
+    pTileTable->InitializeTileset(pTileTypes[2].uTileGroup);
+    pTileTable->InitializeTileset(pTileTypes[3].uTileGroup);
+    if ( this != (OutdoorLocation *)-96 && pSkyTextureName[0] )
+    {
+      v108 = 0;
+      v107 = (int)pSkyTextureName;
+    }
+    else
+    {
+      v108 = 0;
+      v107 = (int)pDefaultSkyTexture;
+    }
+    uSky_TextureID = pBitmaps_LOD->LoadTexture((const char *)v107, (enum TEXTURE_TYPE)v108);
+    strcpy(pGroundTileset, byte_6BE124_cfg_textures_DefaultGroundTexture);
+    v34 = pTileTable->GetTileById(pTileTypes[0].uTileID);
+    v35 = pBitmaps_LOD->LoadTexture(v34->pTileName);
+    v36 = uSky_TextureID;
+    uMainTile_BitmapID = v35;
+    if ( v36 != -1 )
+      pBitmaps_LOD->pTextures[v36].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[v36].palette_id1);
+
+    v37 = uMainTile_BitmapID;
+    if ( v37 != -1 )
+      pBitmaps_LOD->pTextures[v37].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[v37].palette_id1);
+
+    _47F0E2();
+    pGameLoadingUI_ProgressBar->Progress();
+    fclose((FILE *)v22);
+    goto LABEL_150;
+  }*/
+
+  assert(sizeof(BSPModel) == 188);
+
+  if (!pGames_LOD->DoesContainerExist(pFilename))
+    Abortf("Unable to find %s in Games.LOD", pFilename);
+
+  //strcpy(FileName, pContainer);
+  strcpy(Str, pFilename);
+  strcpy(Str + strlen(Str) - 4, ".odm");
+  viewparams->uTextureID_LocationMap = pIcons_LOD->LoadTexture(Str, TEXTURE_16BIT_PALETTE);
+  //v141 = &v139;
+  //v38 = strlen(pFilename);
+  //strcpy((char *)&v139 + v38, ".odm");
+  v39 = pGames_LOD->FindContainer(Str, 1);
+  //Str[strlen(Str) - 4] = 0;
+
+  header.uCompressedSize = 0;
+  header.uDecompressedSize = 0;
+  //ptr = v39;
+  header.uVersion = 91969;
+  header.pMagic[0] = 'm';
+  header.pMagic[1] = 'v';
+  header.pMagic[2] = 'i';
+  header.pMagic[3] = 'i';
+  fread(&header, 0x10u, 1u, v39);
+  if (header.uVersion != 91969 ||
+      header.pMagic[0] != 'm' ||
+      header.pMagic[1] != 'v' ||
+      header.pMagic[2] != 'i' ||
+      header.pMagic[3] != 'i')
+  {
+    MessageBoxW(nullptr, L"Can't load file!",
+                L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odmap.cpp:507", 0);
+  }
+  //v40 = header.uCompressedSize;
+  //pSource = header.uDecompressedSize;
+  //v41 = malloc(header.uDecompressedSize);
+  auto pSrcMem = (unsigned char *)malloc(header.uDecompressedSize);
+  auto pSrc = pSrcMem;
+  //v42 = v41;
+  //HIDWORD(v142) = (uint32)pSrc;
+  if (header.uCompressedSize < header.uDecompressedSize)
+  {
+    auto pComressedSrc = (char *)malloc(header.uCompressedSize);
+    fread(pComressedSrc, header.uCompressedSize, 1, v39);
+
+    uint actualDecompressedSize = header.uDecompressedSize;
+    zlib::MemUnzip(pSrc, &actualDecompressedSize, pComressedSrc, header.uCompressedSize);
+    free(pComressedSrc);
+  }
+  else
+  {
+    fread(pSrc, header.uDecompressedSize, 1, v39);
+  }
+
+  memcpy(pLevelFilename, pSrc, 0x20);
+  memcpy(pLocationFileName, pSrc + 0x20, 0x20);
+  memcpy(pLocationFileDescription, pSrc + 0x40, 0x20);
+  memcpy(pSkyTextureName, pSrc + 0x60, 0x20);
+  memcpy(pGroundTileset, pSrc + 0x80, 0x20);
+  memcpy(pTileTypes, pSrc + 0xA0, 0x10);
+  pSrc += 0xB0;
+
+  //v43 = (char *)pSrc + 176;
+  LoadTileGroupIds();
+  _47F3EA();
+  strcpy(pGroundTileset, "grastyl");
+  pGameLoadingUI_ProgressBar->Progress();
+  pTerrain.Initialize();
+  //v108 = 16384;
+  //v107 = (int)v43;
+  //v106 = (char *)pTerrain.pHeightmap;
+  memcpy(pTerrain.pHeightmap, pSrc, 0x4000);
+  pSrc += 0x4000;
+
+  //v43 = (char *)v43 + 16384;
+  //v105 = 16384;
+  //v104 = (void *)v43;
+  //v103 = pTerrain.pTilemap;
+  memcpy(pTerrain.pTilemap, pSrc, 0x4000);
+  pSrc += 0x4000;
+
+  //v43 = (char *)v43 + 16384;
+  memcpy(pTerrain.pAttributemap, pSrc, 0x4000);
+  pSrc += 0x4000;
+
+  //v43 = (char *)v43 + 16384;
+  //v108 = (int)ptr_D4;
+  if (ptr_D4)
+  {
+    pAllocator->FreeChunk(ptr_D4);
+    ptr_D4 = nullptr;
+  }
+  ptr_D4 = pAllocator->AllocNamedChunk(0, 0x8000u, "CMAP");
+  pTerrain._47C80A(0, 0, 128, 128);
+
+  pGameLoadingUI_ProgressBar->Progress();
+  memcpy(&uNumTerrainNormals, pSrc, 4);
+  //v43 = (char *)v43 + 4;
+  memcpy(pTerrainSomeOtherData, pSrc + 4, 0x20000);
+  pSrc += 4 + 0x20000;
+  //v43 = (char *)v43 + 131072;
+  memcpy(pTerrainNormalIndices, pSrc, 0x10000);
+  pSrc += 0x10000;
+  //v43 = (char *)v43 + 65536;
+
+  //pFilename = (char *)(12 * uNumTerrainNormals);
+  pTerrainNormals = (Vec3_float_ *)pAllocator->AllocNamedChunk(pTerrainNormals, 12 * uNumTerrainNormals, "TerNorm");
+  memcpy(pTerrainNormals, pSrc, 12 * uNumTerrainNormals);
+  pSrc += 12 * uNumTerrainNormals;
+  //v44 = (char *)v43 + (int)pFilename;
+  //v44 = (char *)v44 + 4;
+  //v45 = uNumBModels;
+  //v108 = (int)"BDdata";
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  //v107 = 188 * v45;
+  //v106 = (char *)pBModels;
+  //v46 = (BSPModel *)pAllocator->AllocNamedChunk(v106, 188 * v45, "BDdata");
+  //v47 = uNumBModels;
+  memcpy(&uNumBModels, pSrc, 4);
+  pBModels = (BSPModel *)pAllocator->AllocNamedChunk(pBModels, 188 * uNumBModels, "BDdata");
+  //pFilename = (char *)(188 * v47);
+  memcpy(pBModels, pSrc + 4, 188 * uNumBModels);
+  pSrc += 4 + 188 * uNumBModels;
+  
+  pGameLoadingUI_ProgressBar->Progress();
+
+  //uSourceLen = (char *)v44 + (int)pFilename;
+  //v151 = 0;
+  for (uint i = 0; i < uNumBModels; ++i)
+  {
+    //v48 = 0;
+    auto model = pBModels + i;
+
+    model->pVertices.pVertices = nullptr;
+    model->pFaces = nullptr;
+    model->pFacesOrdering = nullptr;
+    model->pNodes = nullptr;
+      //FileName[0] = 0;
+      //v108 = (int)&pBModels[i];
+      //sprintf(FileName, "%s", v108);
+      //v49 = pBModels;
+      //v138 = 0;
+      //v50 = &pBModels[v48];
+      //v108 = (int)FileName;
+      //v107 = 12 * v50->pVertices.uNumVertices;
+      //v106 = (char *)v50->pVertices.pVertices;
+    assert(sizeof(Vec3_int_) == 12);
+    uint verticesSize = model->pVertices.uNumVertices * sizeof(Vec3_int_);
+    model->pVertices.pVertices = (Vec3_int_ *)pAllocator->AllocNamedChunk(model->pVertices.pVertices, verticesSize, "");
+    memcpy(model->pVertices.pVertices, pSrc, verticesSize);
+    pSrc += verticesSize;
+      //v51 = &pBModels[v48];
+      //v108 = (int)FileName;
+      //v107 = 308 * v51->uNumFaces;
+      //v106 = (char *)v51->pFaces;
+    assert(sizeof(ODMFace) == 308);
+    uint facesSize = model->uNumFaces * sizeof(ODMFace);
+    model->pFaces = (ODMFace *)pAllocator->AllocNamedChunk(model->pFaces, facesSize, "");
+    memcpy(model->pFaces, pSrc, facesSize);
+    pSrc += facesSize;
+      //v52 = &pBModels[v48];
+      //v108 = (int)FileName;
+      //v107 = 2 * v52->uNumFaces;
+      //v106 = (char *)v52->pFacesOrdering;
+    uint facesOrderingSize = model->uNumFaces * sizeof(short);
+    model->pFacesOrdering = (unsigned __int16 *)pAllocator->AllocNamedChunk(model->pFacesOrdering, facesOrderingSize, "");
+    memcpy(model->pFacesOrdering, pSrc, facesOrderingSize);
+    pSrc += facesOrderingSize;
+      //v53 = &pBModels[v48];
+      //v108 = (int)FileName;
+      //v107 = 8 * v53->uNumNodes;
+      //v106 = (char *)v53->pNodes;
+    assert(sizeof(BSPNode) == 8);
+    uint nodesSize = model->uNumNodes * sizeof(BSPNode);
+    model->pNodes = (BSPNode *)pAllocator->AllocNamedChunk(model->pNodes, nodesSize, "");
+    memcpy(model->pNodes, pSrc, nodesSize);
+    pSrc += nodesSize;
+      //v54 = &pBModels[v48];
+      //v108 = 12 * v54->pVertices.uNumVertices;
+      //pFilename = (char *)v108;
+      //v107 = (int)uSourceLen;
+      //v106 = (char *)v54->pVertices.pVertices;
+      //memcpy(v106, uSourceLen, v108);
+      //uSourceLen = (char *)uSourceLen + (int)pFilename;
+      //v55 = &pBModels[v48];
+      //v105 = 308 * v55->uNumFaces;
+      //v104 = uSourceLen;
+      //v103 = v55->pFaces;
+      //pFilename = (char *)v105;
+      //memcpy(v103, uSourceLen, v105);
+      //v56 = &pBModels[v48];
+      //uSourceLen = (char *)uSourceLen + (int)pFilename;
+      //v57 = v56->pFacesOrdering;
+      //pFilename = (char *)(2 * v56->uNumFaces);
+      //memcpy(v57, uSourceLen, (size_t)pFilename);
+      //v58 = &pBModels[v48];
+      //uSourceLen = (char *)uSourceLen + (int)pFilename;
+      //v59 = v58->pNodes;
+      //pFilename = (char *)(8 * v58->uNumNodes);
+      //memcpy(v59, uSourceLen, (size_t)pFilename);
+      //uSourceLen = (char *)uSourceLen + (int)pFilename;
+    //ptr = (FILE *)malloc(10 * model->uNumFaces);
+    auto textureFilenames = (const char *)malloc(10 * model->uNumFaces);
+      //pFilename = (char *)(10 * pBModels[v48].uNumFaces);
+    memcpy((char *)textureFilenames, pSrc, 10 * model->uNumFaces);
+    pSrc += 10 * model->uNumFaces;
+      //v144 = 0;
+      //uSourceLen = (char *)uSourceLen + (int)pFilename;
+      //v60 = pBModels;
+    for (uint j = 0; j < model->uNumFaces; ++j)
+    {
+      auto texFilename = textureFilenames + j * 10;
+    //v149 = 0;
+    //Str2 = (char *)ptr;
+
+      auto face = model->pFaces + j;
+      //pFilename = (char *)v149 + (unsigned int)v60[v48].pFaces;
+      if (~face->uAttributes & 0x40)
+      {
+        v62 = pBitmaps_LOD->LoadTexture(texFilename);
+//        v63 = (ODMFace *)pFilename;
+        goto LABEL_68;
+      }
+      //v61 = pTextureFrameTable->FindTextureByName(texFilename);
+      face->uTextureID = pTextureFrameTable->FindTextureByName(texFilename);
+      if (!face->uTextureID)
+      {
+        v62 = pBitmaps_LOD->LoadTexture(texFilename);
+        //v63 = (ODMFace *)pFilename;
+        BYTE1(face->uAttributes) &= 0xBFu;
+LABEL_68:
+        face->uTextureID = v62;
+        //v145 = (signed __int16)v62 != -1 ? &pBitmaps_LOD->pTextures[(signed __int16)v62] : 0;
+        //v108 = ((signed __int16)v62 != -1 ? pBitmaps_LOD->pTextures[(signed __int16)v62].palette_id1 : 36);
+        if ((signed __int16)v62 != -1)
+          pBitmaps_LOD->pTextures[v62].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[v62].palette_id1);
+        goto LABEL_69;
+      }
+      pTextureFrameTable->LoadAnimationSequenceAndPalettes(face->uTextureID);
+LABEL_69:
+      if (face->sCogTriggeredID)
+      {
+        if (face->HasEventHint())
+          BYTE2(face->uAttributes) |= 0x10u;
+        else
+          BYTE2(face->uAttributes) &= 0xEFu;
+      }
+      //++v144;
+      //v60 = pBModels;
+      //v149 = (char *)v149 + 308;
+      //Str2 += 10;
+      //if ( v144 >= (signed int)v60[v48].uNumFaces )
+        //goto LABEL_74;
+      }
+
+//LABEL_74:
+      free((void *)textureFilenames);
+//      ++v151;
+//      ++v48;
+//      if ( v151 >= (signed int)uNumBModels )
+//        goto LABEL_75;
+  }
+//LABEL_75:
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumLevelDecorations, pSrc, 4u);
+  //uSourceLen = (char *)uSourceLen + 4;
+  if (uNumLevelDecorations > 3000)
+    MessageBoxW(nullptr, L"Can't load file!",
+                L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odmap.cpp:678", 0);
+
+  assert(sizeof(LevelDecoration) == 32);
+  //pFilename = (char *)(32 * uNumLevelDecorations);
+  memcpy(pLevelDecorations, pSrc + 4, uNumLevelDecorations * sizeof(LevelDecoration));
+  pSrc += 4 + 32 * uNumLevelDecorations;
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  //v151 = 0;
+  //uSourceLen = (char *)uSourceLen + (int)pFilename;
+  for (uint i = 0; i < uNumLevelDecorations; ++i)
+  {
+    char name[256];
+    memcpy(name, pSrc, 32);
+    pSrc += 32;
+
+    pLevelDecorations[i].uDecorationDescID = pDecorationList->GetDecorIdByName(name);
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&numFaceIDListElems, pSrc, 4);
+
+  //uSourceLen = (char *)uSourceLen + 4;
+  //v108 = (int)pFaceIDLIST;
+  if (pFaceIDLIST)
+  {
+    pAllocator->FreeChunk(pFaceIDLIST);
+    pFaceIDLIST = nullptr;
+  }
+  //v66 = field_DC;
+  //pFaceIDLIST = 0;
+  //v67 = pAllocator->AllocNamedChunk(0, 2 * v66, "IDLIST");
+  uint faceIDListSize = 2 * numFaceIDListElems;
+  pFaceIDLIST = (unsigned short *)pAllocator->AllocNamedChunk(0, faceIDListSize, "IDLIST");
+  //v68 = field_DC;
+  //pFaceIDLIST = (unsigned __int16 *)v67;
+  //pFilename = (char *)(2 * v68);
+  memcpy(pFaceIDLIST, pSrc + 4, faceIDListSize);
+  pSrc += 4 + faceIDListSize;
+
+  //uSourceLen = (char *)uSourceLen + (int)pFilename;
+  pGameLoadingUI_ProgressBar->Progress();
+
+  //v108 = (int)pOMAP;
+  //pAllocator->FreeChunk((void *)v108);
+  //pOMAP = 0;
+  if (pOMAP)
+  {
+    pAllocator->FreeChunk(pOMAP);
+    pOMAP = nullptr;
+  }
+  //v69 = pAllocator->AllocNamedChunk(0, 0x10000u, "OMAP");
+  pOMAP = (unsigned int *)pAllocator->AllocNamedChunk(0, 0x10000, "OMAP");
+  //v108 = 65536;
+  //pOMAP = (unsigned int *)v69;
+  memcpy(pOMAP, pSrc, 65536);
+  pSrc += 65536;
+
+  //uSourceLen = (char *)uSourceLen + 65536;
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumSpawnPoints, pSrc, 4);
+  //uSourceLen = (char *)uSourceLen + 4;
+  pGameLoadingUI_ProgressBar->Progress();
+  //v70 = uNumSpawnPoints;
+  //v108 = (int)"Spawn";
+  //v107 = 24 * v70;
+  //v106 = (char *)pSpawnPoints;
+  assert(sizeof(SpawnPointMM7) == 24);
+  uint spawnPointsSize = uNumSpawnPoints * sizeof(SpawnPointMM7);
+  pSpawnPoints = (SpawnPointMM7 *)pAllocator->AllocNamedChunk(pSpawnPoints, spawnPointsSize, "Spawn");
+  //v72 = uNumSpawnPoints;
+  //pSpawnPoints = v71;
+  memcpy(pSpawnPoints, pSrc + 4, spawnPointsSize);
+  pSrc += 4 + spawnPointsSize;
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  free(pSrcMem);
+
+  //v108 = (int)".ddm";
+  //v73 = strlen(pContainer);
+  strcpy(Str + strlen(Str) - 4, ".ddm");
+  //strcpy((char *)v141 + v73, (const char *)v108);
+  v39 = pNew_LOD->FindContainer(Str, 1);//
+  fread(&header, 0x10u, 1u, v39);
+  Str2 = 0;
+  if (header.uVersion != 91969 ||
+      header.pMagic[0] != 'm' ||
+      header.pMagic[1] != 'v' ||
+      header.pMagic[2] != 'i' ||
+      header.pMagic[3] != 'i' )
+  {
+    MessageBoxW(nullptr, L"Can't load file!",
+                L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odmap.cpp:746", 0);
+    Str2 = (char *)1;
+  }
+  //v74 = 0;
+  //pFilename = (char *)header.uCompressedSize;
+  //v149 = 0;
+  //pDestLen = header.uDecompressedSize;
+  if ( !Str2 )
+  {
+    pSrcMem = (unsigned char *)malloc(header.uDecompressedSize);
+    pSrc = pSrcMem;
+    //v149 = v75;
+    if (header.uCompressedSize == header.uDecompressedSize)
+      fread(pSrc, header.uDecompressedSize, 1u, v39);
+    else if (header.uCompressedSize < header.uDecompressedSize)
+    {
+      auto compressedMem = malloc(header.uCompressedSize);
+      fread(compressedMem, header.uCompressedSize, 1, v39);
+
+      uint actualDecompressedSize = header.uDecompressedSize;
+      zlib::MemUnzip(pSrc, &actualDecompressedSize, compressedMem, header.uCompressedSize);
+      free(compressedMem);
+    }
+    else
+      MessageBoxW(nullptr, L"Can't load file!",
+                  L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odmap.cpp:765", 0);
+
+    assert(sizeof(DDM_DLV_Header) == 0x28);
+    memcpy(&ddm, pSrc, sizeof(DDM_DLV_Header));
+    pSrc += sizeof(DDM_DLV_Header);
+    //v74 = (int)((char *)v75 + 40);
+  }
+  //v76 = uNumBModels;
+  //v77 = actualNumFacesInLevel = 0;
+  uint actualNumFacesInLevel = 0;
+  for (uint i = 0; i < uNumBModels; ++i)
+    actualNumFacesInLevel += pBModels[i].uNumFaces;
+
+  //v79 = ddm.uNumFacesInBModels;
+  if (ddm.uNumFacesInBModels)
+  {
+    if ( ddm.uNumBModels )
+    {
+      //v80 = ddm.uNumDecorations;
+      if (ddm.uNumDecorations)
+      {
+        if (ddm.uNumFacesInBModels != actualNumFacesInLevel ||
+            ddm.uNumBModels != uNumBModels ||
+            ddm.uNumDecorations != uNumLevelDecorations )
+          Str2 = (char *)1;
+      }
+    }
+  }
+
+  if ( BYTE1(dword_6BE364_game_settings_1) & 0x20 )
+    pNumItems = 29030400;
+  if ( Str2 )
+  {
+    memset(Dst, 0, 0x3C8u);
+    memset(Src, 0, 0x3C8u);
+    goto LABEL_112;
+  }
+  //v81 = ddm.uLastRepawnDay;
+  if ((unsigned int)((char *)File - ddm.uLastRepawnDay) >= pNumItems || !ddm.uLastRepawnDay)
+  {
+    memcpy(Dst, pSrc, 0x3C8u);
+    memcpy(Src, pSrc + 968, 0x3C8u);
+LABEL_112:
+    free(pSrcMem);
+
+    ddm.uLastRepawnDay = (int)File;
+    if (Str2 == 0)
+      ++ddm.uNumRespawns;
+    v108 = 0;
+    *(int *)thisa = 1;
+    v39 = pGames_LOD->FindContainer(Str, 0);
+    fread(&header, 0x10, 1u, v39);
+    //pFilename = (char *)header.uCompressedSize;
+    //pDestLen = header.uDecompressedSize;
+    //v82 = malloc(header.uDecompressedSize);
+    pSrcMem = (unsigned char *)malloc(header.uDecompressedSize);
+    //v149 = v82;
+    if (header.uCompressedSize == header.uDecompressedSize)
+      fread(pSrcMem, header.uDecompressedSize, 1, v39);
+    else if (header.uCompressedSize < header.uDecompressedSize)
+    {
+      auto compressedMem = malloc(header.uCompressedSize);
+      fread(compressedMem, header.uCompressedSize, 1u, v39);
+
+      uint actualDecompressedSize = header.uDecompressedSize;
+      zlib::MemUnzip(pSrcMem, &actualDecompressedSize, compressedMem, header.uCompressedSize);
+      free(compressedMem);
+    }
+    else
+      MessageBoxW(nullptr, L"Can't load file!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odmap.cpp:857", 0);
+
+    pSrc = pSrcMem + 40;
+    goto LABEL_120;
+
+  }
+  *(int *)thisa = 0;
+LABEL_120:
+  //v108 = (int)".odm";
+  //v83 = strlen(pContainer);
+  //strcpy((char *)v141 + v83, (const char *)v108);
+  memcpy(array_528, pSrc, 0x3C8);
+  //v84 = (const void *)(v74 + 968);
+  memcpy(array_8F0, pSrc + 0x3C8, 0x3C8);
+  pSrc += 2 * 0x3C8;
+  //v85 = (char *)v84 + 968;
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  if ( *(int *)thisa )
+  {
+    memcpy(array_528, Dst, 0x3C8u);
+    memcpy(array_8F0, Src, 0x3C8u);
+  }
+
+  //v25 = uNumBModels == 0;
+  //v26 = (uNumBModels & 0x80000000u) != 0;
+  //v151 = 0;
+  for (uint i = 0; i < uNumBModels; ++i)
+  {
+    auto model = pBModels + i;
+    //pNumItems = 0;
+    //do
+    //{
+      //v86 = pBModels;
+      //thisa = 0;
+      //v87 = (unsigned int)((char *)v86 + pNumItems);
+    for (uint j = 0; j < model->uNumFaces; ++j)
+    {
+      auto face = model->pFaces + j;
+
+      //if ( *(int *)(v87 + 76) > 0 )
+      //{
+        //File = 0;
+        //do
+        //{
+          //v106 = (char *)&File->uAttributes + *(int *)(v87 + 84);
+      memcpy(&face->uAttributes, pSrc, 4);
+      pSrc += 4;
+          //v88 = pBModels;
+          //++File;
+          //v85 = (char *)v85 + 4;
+          //++thisa;
+          //v87 = (unsigned int)((char *)v88 + pNumItems);
+        //}
+        //while ( thisa < *(int *)(v87 + 76) );
+    }
+
+      //v89 = pBModels;
+      //thisa = 0;
+    for (uint j = 0; j < model->uNumFaces; ++j)
+    {
+      auto face = model->pFaces + j;
+        //pFilename = 0;
+        //do
+        //{
+          //v90 = (ODMFace *)&pFilename[*(unsigned int *)((char *)&v89->pFaces + pNumItems)];
+          //File = v90;
+      if (face->sCogTriggeredID)
+      {
+        if (face->HasEventHint())
+          BYTE2(face->uAttributes) |= 0x10u;
+        else
+          BYTE2(face->uAttributes) &= 0xEFu;
+      }
+          //++thisa;
+          //v89 = pBModels;
+          //pFilename += 308;
+        //}
+        //while ( thisa < *(signed int *)((char *)&v89->uNumFaces + pNumItems) );
+    }
+      //++v151;
+      //pNumItems += 188;
+    //}
+    //while ( v151 < (signed int)uNumBModels );
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  //v151 = 0;
+  for (uint i = 0; i < uNumLevelDecorations; ++i)
+  {
+    //thisa = (int)&pLevelDecorations[0].field_2;
+    //do
+    //{
+    memcpy(&pLevelDecorations[i].field_2, pSrc, 2);
+    pSrc += 2;
+      //thisa += 32;
+      //v85 = (char *)v85 + 2;
+      //++v151;
+    //}
+    //while ( v151 < (signed int)uNumLevelDecorations );
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumActors, pSrc, 4);
+  //v91 = (char *)v85 + 4;
+  if (uNumActors > 500)
+    MessageBoxW(nullptr, L"Can't load file!",
+                L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odmap.cpp:939", 0);
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  assert(sizeof(Actor) == 836);
+  //pFilename = (char *)(836 * uNumActors);
+  memcpy(pActors, pSrc + 4, uNumActors * sizeof(Actor));
+  pSrc += 4 + uNumActors * sizeof(Actor);
+  //v92 = (char *)v91 + (int)pFilename;
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumLayingItems, pSrc, 4);
+  //v93 = (char *)v92 + 4;
+  if (uNumLayingItems > 1000)
+    MessageBoxW(nullptr, L"Can't load file!",
+                L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odmap.cpp:954", 0);
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  assert(sizeof(LayingItem) == 112);
+  //pFilename = (char *)(112 * uNumLayingItems);
+  memcpy(pLayingItems, pSrc + 4, uNumLayingItems * sizeof(LayingItem));
+  pSrc += 4 + uNumLayingItems * sizeof(LayingItem);
+
+  //v94 = (char *)v93 + (int)pFilename;
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&uNumChests, pSrc, 4);
+  //v95 = (char *)v94 + 4;
+  if (uNumChests > 20)
+    MessageBoxW(nullptr, L"Can't load file!",
+                L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odmap.cpp:968", 0);
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  assert(sizeof(Chest) == 5324);
+  //pFilename = (char *)(5324 * uNumChests);
+  memcpy(pChests, pSrc + 4 , uNumChests * sizeof(Chest));
+  pSrc += 4 + uNumChests * sizeof(Chest);
+  //v96 = (char *)v95 + (int)pFilename;
+  pGameLoadingUI_ProgressBar->Progress();
+
+  memcpy(&stru_5E4C90, pSrc, 0xC8);
+  pSrc += 0xC8;
+
+  pGameLoadingUI_ProgressBar->Progress();
+  memcpy(&uLastVisitDay, pSrc, 0x38u);
+
+  free(pSrcMem);
+
+  pTileTable->InitializeTileset(4);
+  //thisa = (int)pTileTypes;
+  //v108 = pTileTypes[0].uTileGroup;
+  pTileTable->InitializeTileset(pTileTypes[0].uTileGroup);
+  //v108 = pTileTypes[1].uTileGroup;
+  pTileTable->InitializeTileset(pTileTypes[1].uTileGroup);
+  //v108 = pTileTypes[2].uTileGroup;
+  pTileTable->InitializeTileset(pTileTypes[2].uTileGroup);
+  //v108 = pTileTypes[3].uTileGroup;
+  pTileTable->InitializeTileset(pTileTypes[3].uTileGroup);
+  strcpy(pGroundTileset, byte_6BE124_cfg_textures_DefaultGroundTexture);
+  //v97 = pTileTypes[0].uTileID;
+  //v108 = 0;
+  auto v98 = pTileTable->GetTileById(pTileTypes[0].uTileID);
+  //v99 = pBitmaps_LOD->LoadTexture(v98->pTileName, TEXTURE_DEFAULT);
+  uMainTile_BitmapID = pBitmaps_LOD->LoadTexture(v98->pTileName, TEXTURE_DEFAULT);
+  if (uMainTile_BitmapID != -1)
+    pBitmaps_LOD->pTextures[uMainTile_BitmapID].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[uMainTile_BitmapID].palette_id1);
+
+  _47F0E2();
+
+LABEL_150:
+  //v100 = HIDWORD(uLastVisitDay);
+  //LODWORD(v142) = LODWORD(uLastVisitDay);
+  //HIDWORD(v142) = v100;
+  if (uLastVisitDay)
+  {
+    auto v108 = 28;
+    if ( (signed int)((signed int)(signed __int64)((double)uLastVisitDay * 0.234375) / 60 / 60 / 0x18u) % 28 != pParty->uDaysPlayed )
+    {
+      if ( rand() % 100 >= 20 )
+        v108 = dword_4EC268[rand() % dword_4EC2A8];
+      else
+        v108 = dword_4EC28C[rand() % dword_4EC2AC];
+      sprintf(field_4F8, "plansky%d", v108);
+    }
+  }
+  else
+  {
+    strcpy(field_4F8, "plansky3");
+  }
+  //v101 = pBitmaps_LOD->LoadTexture(field_4F8);
+  uSky_TextureID = pBitmaps_LOD->LoadTexture(field_4F8);
+  if (uSky_TextureID != -1)
+    pBitmaps_LOD->pTextures[uSky_TextureID].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[uSky_TextureID].palette_id1);
+
+  pPaletteManager->RecalculateAll();
+  pSoundList->LoadSound(53, 0);
+  pSoundList->LoadSound(92, 0);
+  pSoundList->LoadSound(57, 0);
+  pSoundList->LoadSound(96, 0);
+  pSoundList->LoadSound(64, 0);
+  pSoundList->LoadSound(103, 0);
+  v102 = thisa;
+  thisa = 3;
+  do
+  {
+    if ( *(short *)v102 )
+    {
+      switch ( *(short *)v102 )
+      {
+        case 1:
+          pSoundList->LoadSound(58, 0);
+          v108 = 0;
+          v107 = 97;
+          break;
+        case 2:
+          pSoundList->LoadSound(52, 0);
+          v108 = 0;
+          v107 = 91;
+          break;
+        case 3:
+          pSoundList->LoadSound(51, 0);
+          v108 = 0;
+          v107 = 90;
+          break;
+        case 5:
+          pSoundList->LoadSound(62, 0);
+          v108 = 0;
+          v107 = 101;
+          break;
+        case 6:
+          pSoundList->LoadSound(49, 0);
+          v108 = 0;
+          v107 = 88;
+          break;
+        default:
+          if ( *(short *)v102 != 7 )
+            goto LABEL_175;
+          pSoundList->LoadSound(61, 0);
+          v108 = 0;
+          v107 = 100;
+          break;
+      }
+    }
+    else
+    {
+      pSoundList->LoadSound(54, 0);
+      v108 = 0;
+      v107 = 93;
+    }
+    pSoundList->LoadSound(v107, v108);
+LABEL_175:
+    v102 += 4;
+    --thisa;
+  }
+  while ( thisa );
+  return true;
+}
+
+//----- (0047ECC1) --------------------------------------------------------
+int OutdoorLocation::_47ECC1(signed int a2)
+{
+  signed int result; // eax@2
+  int v3; // eax@3
+
+  if ( a2 >= 90 )
+  {
+    v3 = (a2 - 90) / 36;
+    if ( v3 && v3 != 1 && v3 != 2 )
+    {
+      if ( v3 == 3 )
+        result = this->pTileTypes[3].uTileID;
+      else
+        result = a2;
+    }
+    else
+    {
+      result = this->pTileTypes[v3].uTileID;
+    }
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+//----- (0047ED08) --------------------------------------------------------
+unsigned int OutdoorLocation::DoGetTileTexture(unsigned int uX, unsigned int uZ)
+{
+  int v3; // esi@5
+  unsigned int result; // eax@9
+
+  if ( (uX & 0x80000000u) != 0 || (signed int)uX > 127 || (uZ & 0x80000000u) != 0 || (signed int)uZ > 127 )
+  {
+    result = 0;
+  }
+  else
+  {
+    v3 = *(&this->pTerrain.pTilemap[128 * uZ] + uX);
+    if ( v3 < 198 )
+    {
+      if ( v3 >= 90 )
+        v3 = v3 + this->pTileTypes[(v3 - 90) / 36].uTileID - 36 * (v3 - 90) / 36 - 90;
+    }
+    else
+    {
+      v3 = v3 + this->pTileTypes[3].uTileID - 198;
+    }
+    result = pTileTable->pTiles[v3].uBitmapID;
+  }
+  return result;
+}
+
+//----- (0047ED83) --------------------------------------------------------
+int OutdoorLocation::_47ED83(signed int a2, signed int a3)
+{
+  int result; // eax@5
+
+  if ( a2 < 0 || a2 > 127 || a3 < 0 || a3 > 127 )
+    result = 0;
+  else
+    result = *(&this->pTerrain.pTilemap[128 * a3] + a2);
+  return result;
+}
+
+//----- (0047EDB3) --------------------------------------------------------
+int OutdoorLocation::ActuallyGetSomeOtherTileInfo(unsigned int uX, unsigned int uY)
+{
+  int v3; // esi@5
+  int result; // eax@7
+
+  if ( (uX & 0x80000000u) != 0 || (signed int)uX > 127 || (uY & 0x80000000u) != 0 || (signed int)uY > 127 )
+  {
+    result = 0;
+  }
+  else
+  {
+    v3 = *(&this->pTerrain.pTilemap[128 * uY] + uX);
+    if ( v3 >= 90 )
+      v3 = v3 + this->pTileTypes[(v3 - 90) / 36].uTileID - 36 * (v3 - 90) / 36 - 90;
+    result = pTileTable->pTiles[v3].uAttributes;
+  }
+  return result;
+}
+
+//----- (0047EE16) --------------------------------------------------------
+int OutdoorLocation::DoGetHeightOnTerrain(unsigned int uX, unsigned int uZ)
+{
+  int result; // eax@5
+
+  if ( (uX & 0x80000000u) != 0 || (signed int)uX > 127 || (uZ & 0x80000000u) != 0 || (signed int)uZ > 127 )
+    result = 0;
+  else
+    result = 32 * *(&this->pTerrain.pHeightmap[128 * uZ] + uX);
+  return result;
+}
+
+//----- (0047EE49) --------------------------------------------------------
+int OutdoorLocation::_47EE49(signed int a2, signed int a3, int a4)
+{
+  signed int v4; // eax@5
+  signed int v5; // eax@7
+  int v6; // eax@8
+  signed int v8; // eax@9
+  int v9; // eax@12
+  int v10; // eax@13
+  int v11; // eax@14
+  int v12; // eax@16
+  int v13; // eax@17
+  int v14; // eax@18
+  int v15; // eax@19
+  int v16; // eax@20
+  int v17; // eax@21
+  int v18; // eax@28
+  int v19; // eax@29
+  int v20; // eax@30
+
+  if ( a2 < 0 || a2 > 127 || a3 < 0 || a3 > 127 )
+    v4 = 0;
+  else
+    v4 = *(&this->pTerrain.pTilemap[128 * a3] + a2);
+  v5 = _47ECC1(v4);
+  if ( !v5 )
+  {
+    v6 = -(a4 != 0);
+    LOBYTE(v6) = v6 & 0xD9;
+    return v6 + 92;
+  }
+  v8 = pTileTable->pTiles[v5].uTerrainType;
+  if ( v8 <= 6 )
+  {
+    if ( v8 == 6 )
+    {
+      v17 = -(a4 != 0);
+      LOBYTE(v17) = v17 & 0xD9;
+      return v17 + 88;
+    }
+    if ( v8 )
+    {
+      v9 = v8 - 1;
+      if ( !v9 )
+      {
+        v15 = -(a4 != 0);
+        LOBYTE(v15) = v15 & 0xD9;
+        return v15 + 97;
+      }
+      v10 = v9 - 1;
+      if ( !v10 )
+      {
+        v14 = -(a4 != 0);
+        LOBYTE(v14) = v14 & 0xD9;
+        return v14 + 91;
+      }
+      v11 = v10 - 1;
+      if ( !v11 )
+      {
+        v13 = -(a4 != 0);
+        LOBYTE(v13) = v13 & 0xD9;
+        return v13 + 90;
+      }
+      if ( v11 == 2 )
+      {
+        v12 = -(a4 != 0);
+        LOBYTE(v12) = v12 & 0xD9;
+        return v12 + 101;
+      }
+LABEL_29:
+      v19 = -(a4 != 0);
+      LOBYTE(v19) = v19 & 0xD9;
+      return v19 + 95;
+    }
+    goto LABEL_20;
+  }
+  if ( v8 != 7 )
+  {
+    if ( v8 != 8 )
+    {
+      if ( v8 > 9 && (v8 <= 17 || v8 > 21 && v8 <= 27) )
+      {
+        v18 = -(a4 != 0);
+        LOBYTE(v18) = v18 & 0xD9;
+        return v18 + 96;
+      }
+      goto LABEL_29;
+    }
+LABEL_20:
+    v16 = -(a4 != 0);
+    LOBYTE(v16) = v16 & 0xD9;
+    return v16 + 93;
+  }
+  v20 = -(a4 != 0);
+  LOBYTE(v20) = v20 & 0xD9;
+  return v20 + 100;
+}
+
+//----- (0047EF60) --------------------------------------------------------
+int OutdoorLocation::_47EF60(int a2, int a3, int a4)
+{
+  int v4; // ecx@1
+  int v5; // edx@2
+  int v6; // edi@2
+  int v7; // esi@2
+  int v8; // eax@4
+  int v9; // ebx@4
+  int v10; // eax@5
+  int v11; // eax@7
+  int v12; // esi@12
+  char v13; // al@12
+  int v15; // [sp+4h] [bp-14h]@7
+  int v16; // [sp+8h] [bp-10h]@5
+  int v17; // [sp+Ch] [bp-Ch]@2
+  OutdoorLocation *v18; // [sp+10h] [bp-8h]@1
+  int v19; // [sp+14h] [bp-4h]@2
+  int i; // [sp+24h] [bp+Ch]@5
+
+  v18 = this;
+  v4 = a3 - 10;
+  if ( a3 - 10 < a3 + 10 )
+  {
+    v5 = v4 - a3;
+    v6 = 88 * (a3 - 30);
+    v7 = a2;
+    v19 = v4 - a3;
+    v17 = a3 + 10 - v4;
+    while ( 1 )
+    {
+      v8 = abs(v5);
+      v9 = v7 - 10;
+      if ( v7 - 10 < v7 + 10 )
+      {
+        v16 = v8 * v8;
+        v10 = v9 - v7;
+        for ( i = v9 - v7; ; v10 = i )
+        {
+          v11 = abs(v10);
+          v15 = v11 * v11 + v16;
+          if ( v15 <= 100 && v9 >= 20 && v9 <= 107 && v6 >= 0 && v6 <= 7656 )
+          {
+            v12 = (v6 + v9 - 20) >> 3;
+            v13 = 1 << (8 - (v6 + v9 - 20) % 8 - 1);
+            v18->array_8F0[v12] |= v13;
+            if ( v15 <= 49 )
+              v18->array_528[v12] |= v13;
+            v7 = a2;
+          }
+          ++v9;
+          ++i;
+          if ( v9 >= v7 + 10 )
+            break;
+        }
+      }
+      v6 += 88;
+      ++v19;
+      --v17;
+      if ( !v17 )
+        break;
+      v5 = v19;
+    }
+  }
+  return 1;
+}
+
+//----- (0047F04C) --------------------------------------------------------
+bool OutdoorLocation::_47F04C(signed int a2, signed int a3)
+{
+  bool result; // eax@5
+
+  if ( a2 < 0 || a2 >= 88 || a3 < 0 || a3 >= 88 )
+    result = 0;
+  else
+    result = (this->array_528[(a2 + 88 * a3) / 8] & (unsigned __int8)(1 << (7 - (a2 + 88 * a3) % 8))) != 0;
+  return result;
+}
+
+//----- (0047F097) --------------------------------------------------------
+bool OutdoorLocation::_47F097(signed int a2, signed int a3)
+{
+  bool result; // eax@5
+
+  if ( a2 < 0 || a2 >= 88 || a3 < 0 || a3 >= 88 )
+    result = 0;
+  else
+    result = (this->array_8F0[(a2 + 88 * a3) / 8] & (unsigned __int8)(1 << (7 - (a2 + 88 * a3) % 8))) != 0;
+  return result;
+}
+
+//----- (0047F0E2) --------------------------------------------------------
+bool OutdoorLocation::_47F0E2()
+{
+  signed int v1; // edi@1
+  OutdoorLocation *v2; // ebx@1
+  Texture *v3; // ebp@2
+
+  v1 = 0;
+  v2 = this;
+  if ( (signed int)pBitmaps_LOD->uNumLoadedFiles > 0 )
+  {
+    v3 = pBitmaps_LOD->pTextures;
+    do
+    {
+      if ( v1 != -1 ? (int)v3 : 0 )
+        v3->uDecompressedSize = v2->pTerrain._47CB57((int)v3->pLevelOfDetail0,
+                                                      v3->palette_id2,
+                                                      v3->uTextureWidth * v3->uTextureHeight);
+      ++v1;
+      ++v3;
+    }
+    while ( v1 < (signed int)pBitmaps_LOD->uNumLoadedFiles );
+  }
+  return 1;
+}
+
+//----- (0047F138) --------------------------------------------------------
+bool OutdoorLocation::PrepareDecorations()
+{
+  signed int v1; // ebx@1
+  __int16 v4; // ax@5
+  int v5; // eax@7
+  __int16 v6; // ax@14
+  signed int v8; // [sp+Ch] [bp-4h]@1
+
+  v1 = 0;
+  v8 = 0;
+  if ( !_strcmpi(pCurrentMapName, "out09.odm") )
+    v8 = 1;
+
+  for (uint i = 0; i < uNumLevelDecorations; ++i)
+  {
+    auto decor = pLevelDecorations + i;
+
+      pDecorationList->InitializeDecorationSprite(decor->uDecorationDescID);
+      v4 = pDecorationList->pDecorations[decor->uDecorationDescID].uSoundID;
+      if ( v4 && _6807E0_num_decorations_with_sounds_6807B8 < 9 )
+      {
+        pSoundList->LoadSound(v4, 0);
+        v5 = _6807E0_num_decorations_with_sounds_6807B8++;
+        _6807B8_level_decorations_ids[v5] = i;
+      }
+      if ( v8 && decor->uCog == 20 )
+        LOBYTE(decor->field_2) |= 0x40u;
+      if ( !decor->field_16_event_id )
+      {
+        if ( decor->IsInteractive() )
+        {
+          if ( v1 < 124 )
+          {
+            v6 = v1 + 75;
+            decor->_idx_in_stru123 = v6;
+            if ( !stru_5E4C90._decor_events[v1++] )
+              LOBYTE(decor->field_2) |= 0x20u;
+          }
+        }
+      }
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+  return true;
+}
+// 6807E0: using guessed type int _6807E0_num_decorations_6807B8;
+
+//----- (0047F223) --------------------------------------------------------
+int OutdoorLocation::_47F223_LooksLikeGenerateMonsterLoot()
+{
+  signed int v1; // ebx@1
+  char *v2; // esi@2
+  int v3; // eax@7
+  OutdoorLocation *v5; // [sp+0h] [bp-4h]@1
+
+  v5 = this;
+  v1 = 0;
+  if ( (signed int)uNumLayingItems > 0 )
+  {
+    v2 = (char *)&pLayingItems[0].uObjectDescID;
+    do
+    {
+      if ( *(short *)v2 )
+      {
+        if ( !(v2[24] & 8) && !(pObjectList->pObjects[*(short *)v2].uFlags & 0x10) )
+          *(int *)(v2 + 10) = GetTerrainHeightsAroundParty2(*(int *)(v2 + 2), *(int *)(v2 + 6), (int *)&v5, 0);
+        v3 = *(int *)(v2 + 34);
+        if ( v3 )
+        {
+          if ( v3 != 220 && pItemsTable->pItems[v3].uEquipType == 14 && !*(int *)(v2 + 38) )
+            *(int *)(v2 + 38) = rand() % 15 + 5;
+          pItemsTable->SetSpecialBonus((ItemGen *)(v2 + 34));
+        }
+      }
+      ++v1;
+      v2 += 112;
+    }
+    while ( v1 < (signed int)uNumLayingItems );
+  }
+  pGameLoadingUI_ProgressBar->Progress();
+  return 1;
+}
+
+//----- (0047F2D3) --------------------------------------------------------
+bool OutdoorLocation::InitalizeActors(int a1)
+{
+  int v2; // ebx@1
+  char *v3; // esi@2
+  int v4; // eax@3
+  __int16 v5; // ax@11
+  int v8; // [sp+348h] [bp-8h]@1
+  int v9; // [sp+34Ch] [bp-4h]@1
+
+  v2 = 0;
+  v8 = 0;
+  v9 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v3 = (char *)&pActors[0].uAttributes;
+    while ( 1 )
+    {
+      v4 = *(int *)v3;
+      if ( !(v4 & 0x100000) )
+        break;
+      if ( a1 == v2 )
+        goto LABEL_8;
+      if ( v8 != v2 )
+        goto LABEL_9;
+      *((short *)v3 + 70) = 19;
+      *(int *)v3 = v4 | 0x10000;
+      v8 = GetAlertStatus();
+LABEL_17:
+      ++v9;
+      v3 += 836;
+      if ( v9 >= (signed int)uNumActors )
+        goto LABEL_18;
+    }
+    if ( v8 != 1 )
+    {
+LABEL_9:
+      *((int *)v3 + 37) = v2;
+      *((short *)v3 + 62) = v2;
+      if ( v4 & 0x10000 )
+        *((short *)v3 + 70) = 19;
+      v5 = *((short *)v3 + 70);
+      if ( v5 != 11 && v5 != 19 && (*((short *)v3 + 2) == (short)v2 || *((int *)v3 + 18) == v2) )
+        *((short *)v3 + 70) = 5;
+      *((short *)v3 + 56) = v2;
+      *((short *)v3 + 57) = v2;
+      *((short *)v3 + 58) = v2;
+      ((Actor *)(v3 - 36))->UpdateAnimation();
+      v3[25] = 0;
+      ((Actor *)(v3 - 36))->PrepareSprites(0);
+      v2 = 0;
+      goto LABEL_17;
+    }
+LABEL_8:
+    *((short *)v3 + 70) = 19;
+    *(int *)v3 = v4 | 0x10000;
+    goto LABEL_17;
+  }
+LABEL_18:
+  pGameLoadingUI_ProgressBar->Progress();
+
+  Actor thisa;
+  thisa.pMonsterInfo.uID = 45;
+  thisa.PrepareSprites(v2);
+  return 1;
+}
+
+//----- (0047F3EA) --------------------------------------------------------
+bool OutdoorLocation::_47F3EA()
+{
+  OutdoorLocationTileType *v1; // esi@1
+
+  v1 = &this->pTileTypes[3];
+  this->pTileTypes[3].uTileID = pTileTable->method_487ED6(this->pTileTypes[3].uTileGroup, 1);
+  pTileTable->InitializeTileset(v1->uTileGroup);
+  return 1;
+}
+
+//----- (0047F420) --------------------------------------------------------
+bool OutdoorLocation::LoadTileGroupIds()
+{
+  for (uint i = 0; i < 3; ++i)
+    pTileTypes[i].uTileID = pTileTable->method_487ED6(pTileTypes[i].uTileGroup, 1);
+
+  return true;
+}
+
+//----- (0047B42C) --------------------------------------------------------
+unsigned int OutdoorLocation::DrawActors()
+{
+  unsigned int result; // eax@1
+  char *v1; // edi@2
+  __int16 v2; // ax@3
+  int v3; // esi@5
+  float v4; // ST48_4@8
+  double v5; // ST38_8@8
+  float v6; // ST48_4@10
+  double v7; // ST30_8@10
+  unsigned int v8; // eax@11
+  int v9; // edx@11
+  __int16 v10; // dx@11
+  unsigned int v11; // eax@13
+  signed int v12; // eax@16
+  __int16 v13; // cx@21
+  SpriteFrame *v14; // eax@24
+  SpriteFrame *v15; // ebx@25
+  //int *v16; // eax@25
+  int v17; // eax@35
+  int v18; // ST78_4@36
+  int v19; // eax@36
+  int v20; // ecx@38
+  int v21; // eax@38
+  int v22; // ecx@41
+  int v23; // ST5C_4@43
+  int v24; // esi@44
+  signed __int64 v25; // qtt@45
+  int v26; // ST54_4@45
+  int v27; // ecx@45
+  RenderBillboard *v28; // esi@45
+  __int16 v29; // ax@46
+  unsigned __int8 v30; // zf@46
+  unsigned __int8 v31; // sf@46
+  signed __int16 v32; // ax@49
+  signed int v33; // ecx@50
+  int v34; // ecx@54
+  MonsterDesc *v35; // edx@54
+  int v36; // ecx@54
+  unsigned __int8 v37; // zf@54
+  unsigned __int8 v38; // sf@54
+  unsigned int v39; // [sp-8h] [bp-68h]@23
+  unsigned int v40; // [sp-4h] [bp-64h]@23
+  int v41; // [sp+24h] [bp-3Ch]@11
+  int v42; // [sp+28h] [bp-38h]@38
+  int v43; // [sp+28h] [bp-38h]@45
+  int v44; // [sp+2Ch] [bp-34h]@36
+  int v45; // [sp+2Ch] [bp-34h]@44
+  int v46; // [sp+2Ch] [bp-34h]@45
+  int v47; // [sp+30h] [bp-30h]@36
+  int v48; // [sp+30h] [bp-30h]@41
+  signed int v49; // [sp+34h] [bp-2Ch]@5
+  int v50; // [sp+34h] [bp-2Ch]@36
+  int v51; // [sp+34h] [bp-2Ch]@41
+  int v52; // [sp+34h] [bp-2Ch]@50
+  int v53; // [sp+38h] [bp-28h]@36
+  int v54; // [sp+3Ch] [bp-24h]@2
+  int y; // [sp+40h] [bp-20h]@5
+  int x; // [sp+44h] [bp-1Ch]@5
+  int v57; // [sp+48h] [bp-18h]@45
+  int v58; // [sp+4Ch] [bp-14h]@45
+  signed int v59; // [sp+50h] [bp-10h]@1
+  int X; // [sp+54h] [bp-Ch]@36
+  __int16 v61; // [sp+58h] [bp-8h]@5
+  signed __int16 v62; // [sp+5Ch] [bp-4h]@25
+
+  result = 0;
+  v59 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v54 = 0;
+    v1 = (char *)&pActors[0].vPosition.z;
+    do
+    {
+      v2 = *((short *)v1 + 15);
+      *(int *)(v1 - 110) &= 0xFFFFFFF7u;
+      if ( v2 == 11 || v2 == 19 )
+        goto LABEL_58;
+      v3 = *(short *)v1;
+      v49 = 0;
+      x = *((short *)v1 - 2);
+      y = *((short *)v1 - 1);
+      v61 = *(short *)v1;
+      if ( v2 == 17 )
+      {
+        if ( (v1[666] & 7) != 3 || pActors[*(int *)(v1 + 666) >> 3].pMonsterInfo.uSpecialAbilityDamageDiceSides != 1 )
+        {
+          v6 = (double)*((short *)v1 - 4) * 0.5;
+          v7 = v6 + 6.7553994e15;
+          v3 += LODWORD(v7);
+          v61 = v3;
+        }
+        else
+        {
+          v49 = 1;
+          pGame->pStru6Instance->_4A7F74(*((short *)v1 - 2), *((short *)v1 - 1), v3);
+          v4 = (1.0 - (double)*(signed int *)(v1 + 38) / (double)*((short *)v1 + 7))
+             * (double)(2 * (signed int)*((short *)v1 - 4));
+          v5 = v4 + 6.7553994e15;
+          v3 -= LODWORD(v5);
+          v61 = v3;
+          if ( v3 > *(short *)v1 )
+          {
+            v61 = *(short *)v1;
+            v3 = *(short *)v1;
+          }
+        }
+      }
+      v8 = stru_5C6E00->Atan2(
+             *((short *)v1 - 2) - pIndoorCamera->pos.x,
+             *((short *)v1 - 1) - pIndoorCamera->pos.y);
+      LOWORD(v9) = *((short *)v1 + 4);
+      v41 = ((signed int)(stru_5C6E00->uIntegerPi + ((signed int)stru_5C6E00->uIntegerPi >> 3) + v9 - v8) >> 8) & 7;
+      v10 = *((short *)v1 + 16);
+      if ( pParty->bTurnBasedModeOn )
+      {
+        if ( v10 != 1 )
+        {
+LABEL_17:
+          v12 = *(int *)(v1 + 38);
+          goto LABEL_18;
+        }
+        v11 = pMiscTimer->uTotalGameTimeElapsed;
+      }
+      else
+      {
+        if ( v10 != 1 )
+          goto LABEL_17;
+        v11 = pEventTimer->uTotalGameTimeElapsed;
+      }
+      v12 = v54 + v11;
+LABEL_18:
+      if ( *(_QWORD *)(v1 + 146) > 0i64 || *(_QWORD *)(v1 + 162) > 0i64 )
+        v12 = 0;
+      v13 = *((short *)v1 + 15);
+      if ( v13 == 17 && !v49 )
+      {
+        v40 = v12;
+        v39 = uSpriteID_Spell11;
+LABEL_24:
+        v14 = pSpriteFrameTable->GetFrame(v39, v40);
+        goto LABEL_25;
+      }
+      v40 = v12;
+      v39 = *(short *)&v1[2 * v10 + 42];
+      if ( v13 != 16 )
+        goto LABEL_24;
+      v14 = pSpriteFrameTable->GetFrameBy_x(v39, v12);
+LABEL_25:
+      v62 = 0;
+      v15 = v14;
+      //v16 = (int *)v14->uFlags;
+      if (v14->uFlags & 2)
+        v62 = 2;
+      if (v14->uFlags & 0x40000)
+        v62 |= 0x40u;
+      if (v14->uFlags & 0x20000)
+        LOBYTE(v62) = v62 | 0x80;
+      if ((256 << v41) & v14->uFlags)
+        v62 |= 4u;
+      if ( v15->uGlowRadius )
+      {
+        //LOBYTE(v16) = byte_4E94D3;
+        pMobileLightsStack->AddLight(x, y, v3, 0, v15->uGlowRadius, 0xFFu, 0xFFu, 0xFFu, byte_4E94D3);
+      }
+      v17 = (x - pIndoorCamera->pos.x) << 16;
+      if ( pIndoorCamera->sRotationX )
+      {
+        v18 = (y - pIndoorCamera->pos.y) << 16;
+        v47 = ((unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16)
+            + ((unsigned __int64)(v18 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
+        v50 = (unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+        v53 = (unsigned __int64)(v18 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
+        v44 = (v3 - pIndoorCamera->pos.z) << 16;
+        v19 = ((unsigned __int64)(v44 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16)
+            + ((unsigned __int64)(v47 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16);
+        X = ((unsigned __int64)(v44 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16)
+          + ((unsigned __int64)(v47 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16);
+        if ( v19 < 262144 || v19 > pOutdoorCamera->shading_dist_mist << 16 )
+          goto LABEL_58;
+        v20 = v53 - v50;
+        v42 = v53 - v50;
+        v21 = ((unsigned __int64)(v44 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16)
+            - ((unsigned __int64)(v47 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
+      }
+      else
+      {
+        v48 = (y - pIndoorCamera->pos.y) << 16;
+        v51 = (unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
+        v22 = (unsigned __int64)(v48 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+        X = v22 + v51;
+        if ( v22 + v51 < 262144 || v22 + v51 > pOutdoorCamera->shading_dist_mist << 16 )
+          goto LABEL_58;
+        v23 = (unsigned __int64)(((x - pIndoorCamera->pos.x) << 16)
+                               * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+        v20 = ((unsigned __int64)(v48 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - v23;
+        v42 = ((unsigned __int64)(v48 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - v23;
+        v21 = (v3 - pIndoorCamera->pos.z) << 16;
+      }
+      v45 = v21;
+      v24 = abs(v20);
+      if ( abs(X) >= v24 )
+      {
+        LODWORD(v25) = 0;
+        HIDWORD(v25) = SLOWORD(pOutdoorCamera->int_fov_rad);
+        v58 = v25 / X;
+        v26 = v25 / X;
+        LODWORD(v25) = 0;
+        HIDWORD(v25) = SLOWORD(pOutdoorCamera->int_fov_rad);
+        v57 = v25 / X;
+        v27 = pViewport->uScreenCenterX
+            - ((signed int)(((unsigned __int64)(v26 * (signed __int64)v42) >> 16) + 32768) >> 16);
+        v43 = pViewport->uScreenCenterX
+            - ((signed int)(((unsigned __int64)(v26 * (signed __int64)v42) >> 16) + 32768) >> 16);
+        v46 = pViewport->uScreenCenterY - ((signed int)(((unsigned __int64)(v25 / X * v45) >> 16) + 32768) >> 16);
+        result = uNumBillboardsToDraw;
+        v28 = &pBillboardRenderList[uNumBillboardsToDraw];
+        if ( (signed int)uNumBillboardsToDraw >= 500 )
+          return result;
+        ++uNumBillboardsToDraw;
+        ++uNumSpritesDrawnThisFrame;
+        *(int *)(v1 - 110) |= 8u;
+        v28->uHwSpriteID = v15->pHwSpriteIDs[v41];
+        v29 = v15->uPaletteIndex;
+        v28->uIndoorSectorID = 0;
+        v28->uPalette = v29;
+        v28->field_0 = (unsigned __int64)(v15->scale * (signed __int64)v58) >> 16;
+        v30 = *(int *)(v1 + 118) == 0;
+        v31 = *(int *)(v1 + 118) < 0;
+        v28->field_4 = (unsigned __int64)(v15->scale * (signed __int64)v57) >> 16;
+        if ( v31 || v31 | v30 && *(int *)(v1 + 114) <= 0u )
+        {
+          if ( *(_QWORD *)(v1 + 226) > 0i64 )
+          {
+            v52 = (unsigned __int64)(pGame->pStru6Instance->_4A806F((Actor *)(v1 - 146))
+                                   * (signed __int64)v28->field_4) >> 16;
+LABEL_53:
+            LOWORD(v27) = v43;
+            v28->field_4 = v52;
+          }
+        }
+        else
+        {
+          v32 = *((short *)v1 + 61);
+          if ( v32 )
+          {
+            v33 = *((short *)v1 + 61);
+            v28->field_0 = (unsigned __int64)(65536 / (unsigned __int16)v32 * (signed __int64)v28->field_0) >> 16;
+            v52 = (unsigned __int64)(65536 / v33 * (signed __int64)v28->field_4) >> 16;
+            goto LABEL_53;
+          }
+        }
+        v28->uScreenSpaceX = v27;
+        v28->some_x = x;
+        v28->uScreenSpaceY = v46;
+        v28->some_y = y;
+        v28->some_z = v61;
+        HIWORD(v34) = HIWORD(X);
+        LOWORD(v34) = 0;
+        v28->uPaletteSubindex = 0;
+        v28->sZValue = v34 + (8 * v59 | 3);
+        v28->field_14 = v59;
+        v35 = pMonsterList->pMonsters;
+        v36 = *((short *)v1 - 25);
+        v37 = *(int *)(v1 + 150) == 0;
+        v38 = *(int *)(v1 + 150) < 0;
+        v28->field_1E = v62 | 0x200;
+        v28->pSpriteFrame = v15;
+        v28->uTintColor = *((int *)&v35[v36] - 36);
+        if ( !v38 && (!(v38 | v37) || *(int *)(v1 + 146)) )
+          v28->field_1E = v62 | 0x200;
+      }
+LABEL_58:
+      ++v59;
+      v54 += 32;
+      result = v59;
+      v1 += 836;
+    }
+    while ( v59 < (signed int)uNumActors );
+  }
+  return result;
+}
+// 4E94D3: using guessed type char byte_4E94D3;
+// 5187E4: using guessed type int uNumSpritesDrawnThisFrame;
+
+//----- (0044C1E8) --------------------------------------------------------
+bool ODMFace::HasEventHint()
+{
+  signed int v1; // eax@1
+  Event *v2; // esi@2
+  bool result; // eax@5
+  signed int v4; // eax@6
+
+  v1 = 0;
+  if ( (signed int)(uLevelEVT_NumEvents - 1) <= 0 )
+    goto LABEL_5;
+  v2 = pLevelEVT_Events;
+  while ( v2->uEventID != this->sCogTriggeredID )
+  {
+    ++v1;
+    ++v2;
+    if ( v1 >= (signed int)(uLevelEVT_NumEvents - 1) )
+      goto LABEL_5;
+  }
+  v4 = v1;
+  if ( pLevelEVT[pLevelEVT_Events[v4 + 1].uEventOffsetInEVT + 4] != 1
+    || pLevelEVT[pLevelEVT_Events[v4].uEventOffsetInEVT + 4] != 4 )
+LABEL_5:
+    result = 0;
+  else
+    result = 1;
+  return result;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Outdoor.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,264 @@
+#pragma
+#include "BSPModel.h"
+#include "OutdoorCamera.h"
+#include "Indoor.h"
+
+
+
+/*  256 */
+#pragma pack(push, 1)
+struct ODMHeader
+{
+  int uVersion;
+  char pMagic[4];
+  unsigned int uCompressedSize;
+  unsigned int uDecompressedSize;
+};
+#pragma pack(pop)
+
+
+
+/*   78 */
+#pragma pack(push, 1)
+struct OutdoorLocationTileType
+{
+  unsigned __int16 uTileGroup;
+  unsigned __int16 uTileID;
+};
+#pragma pack(pop)
+
+
+
+
+/*   79 */
+#pragma pack(push, 1)
+struct OutdoorLocationTerrain
+{
+  //----- (0047C794) --------------------------------------------------------
+  inline OutdoorLocationTerrain()
+  {
+    this->pHeightmap = 0;
+    this->pTilemap = 0;
+    this->ptr_C = 0;
+    this->field_10 = 0;
+    this->field_12 = 0;
+
+    pAttributemap = nullptr;
+  }
+
+  void _47C7A9();
+  void Release();
+  int _47C80A(int a2, int a3, int a4, int a5);
+  int _47CB57(int a1, int a2, int a3);
+  bool ZeroLandscape();
+  bool Initialize();
+
+
+  unsigned __int8 *pHeightmap;
+  unsigned __int8 *pTilemap;
+  unsigned __int8 *pAttributemap;
+  void *ptr_C;
+  __int16 field_10;
+  __int16 field_12;
+  __int16 field_14;
+  __int16 field_16;
+  int field_18;
+  int field_1C;
+};
+#pragma pack(pop)
+
+
+/*   81 */
+#pragma pack(push, 1)
+struct ODMFace
+{
+  bool HasEventHint();
+
+  
+  static bool IsBackfaceCulled(struct ODMFace *a1, struct RenderVertexSoft *a2, struct stru148 *a3);
+  
+  inline bool Invisible() const {return uAttributes & FACE_INVISIBLE;}
+  inline bool Visible() const   {return !Invisible();}
+  inline bool TwoSided() const  {return uAttributes & FACE_TWO_SIDED;}
+
+  struct Plane_int_ pFacePlane;
+  int zCalc1;
+  int zCalc2;
+  int zCalc3;
+  unsigned int uAttributes;
+  unsigned __int16 pVertexIDs[20];
+  unsigned __int16 pTextureUIDs[20];
+  unsigned __int16 pTextureVIDs[20];
+  unsigned __int16 pXInterceptDisplacements[20];
+  unsigned __int16 pYInterceptDisplacements[20];
+  unsigned __int16 pZInterceptDisplacements[20];
+  unsigned __int16 uTextureID;
+  __int16 sTextureDeltaU;
+  __int16 sTextureDeltaV;
+  struct BBox_short_ pBoundingBox;
+  __int16 sCogNumber;
+  __int16 sCogTriggeredID;
+  __int16 sCogTriggerType;
+  char field_128;
+  char field_129;
+  unsigned __int8 uGradientVertex1;
+  unsigned __int8 uGradientVertex2;
+  unsigned __int8 uGradientVertex3;
+  unsigned __int8 uGradientVertex4;
+  unsigned __int8 uNumVertices;
+  unsigned __int8 uPolygonType;
+  unsigned __int8 uShadeType;
+  unsigned __int8 bVisible;
+  char field_132;
+  char field_133;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct OutdoorLocation
+{
+  //----- (004626BA) --------------------------------------------------------
+  OutdoorLocation()
+  {
+    subconstuctor();
+    uLastSunlightUpdateMinute = 0;
+  }
+  //----- (004626CD) --------------------------------------------------------
+  void subconstuctor()
+  {
+    //OutdoorLocationTerrain::OutdoorLocationTerrain(&this->pTerrain);
+    field_F0 = 0;
+    field_F4 = 0x40000000u;
+    //DLVHeader::DLVHeader(&v1->ddm);
+    pSpawnPoints = 0;
+    pBModels = 0;
+    ptr_D4 = 0;
+    pFaceIDLIST = 0;
+    pOMAP = 0;
+  }
+
+  void ExecDraw(unsigned int bRedraw);
+  unsigned int DrawActors();
+  void CreateDebugLocation();
+  void Release();
+  bool Load(char *pFilename, ODMFace *File, size_t a4, int thisa);
+  int _47ECC1(signed int a2);
+  unsigned int DoGetTileTexture(unsigned int uX, unsigned int uZ);
+  int _47ED83(signed int a2, signed int a3);
+  int ActuallyGetSomeOtherTileInfo(unsigned int uX, unsigned int uY);
+  int DoGetHeightOnTerrain(unsigned int uX, unsigned int uZ);
+  int _47EE49(signed int a2, signed int a3, int a4);
+  int _47EF60(int a2, int a3, int a4);
+  bool _47F04C(signed int a2, signed int a3);
+  bool _47F097(signed int a2, signed int a3);
+  bool _47F0E2();
+  bool PrepareDecorations();
+  int _47F223_LooksLikeGenerateMonsterLoot();
+  bool InitalizeActors(int a1);
+  bool _47F3EA();
+  bool LoadTileGroupIds();
+  double GetFogDensityByTime();
+  int GetSomeOtherTileInfo(int sX, int sY);
+  unsigned int GetTileTexture(int sX, int sZ);
+  int GetHeightOnTerrain(int sX, int sZ);
+  bool Initialize(const char *pFilename, int File, size_t uRespawnInterval, int thisa);
+  bool Release2();
+  bool GetTravelDestination(signed int sPartyX, signed int sPartyZ, char *pOut, signed int a5);
+  void MessWithLUN();
+  unsigned int UpdateSunlightVectors();
+  void UpdateFog();
+  int GetNumFoodRequiredToRestInCurrentPos(int x, signed int y, int z);
+  int SetFog();
+  void Draw();
+
+
+  char pLevelFilename[32];
+  char pLocationFileName[32];
+  char pLocationFileDescription[32];
+  char pSkyTextureName[32];
+  char pGroundTileset[32];
+  OutdoorLocationTileType pTileTypes[4];
+  unsigned int uNumBModels;
+  struct OutdoorLocationTerrain pTerrain;
+  void *ptr_D4;
+  struct BSPModel *pBModels;
+  unsigned int numFaceIDListElems;
+  unsigned __int16 *pFaceIDLIST;
+  unsigned int *pOMAP;
+  unsigned int uSky_TextureID;
+  unsigned int uMainTile_BitmapID;
+  __int16 field_F0;
+  __int16 field_F2;
+  int field_F4;
+  char field_F8[968];
+  unsigned int uNumSpawnPoints;
+  struct SpawnPointMM7 *pSpawnPoints;
+  struct DDM_DLV_Header ddm;
+  unsigned __int64 uLastVisitDay;
+  char field_4F8[12];
+  int day_attrib;
+  int day_fogrange_1;
+  int day_fogrange_2;
+  char field_510[24];
+  char array_528[968];
+  char array_8F0[968];
+  int field_CB8;
+  int field_CBC_terrain_triangles_shade_type;
+  int field_CC0;
+  unsigned int pSpriteIDs_LUN[8];
+  unsigned int uSpriteID_LUNFULL;
+  int field_CE8;
+  unsigned int uSpriteID_LUN3_4_cp;
+  int field_CF0;
+  unsigned int uSpriteID_LUN1_2_cp;
+  int field_CF8;
+  unsigned int uSpriteID_LUN1_4_cp;
+  int field_D00;
+  unsigned __int16 uSpriteID_LUN_SUN;
+  __int16 field_D06;
+  int field_D08;
+  int field_D0C;
+  int field_D10;
+  int field_D14;
+  int field_D18;
+  int field_D1C;
+  int field_D20;
+  int field_D24;
+  int field_D28;
+  int field_D2C;
+  Vec3_int_ vSunlight;
+  int field_D3C;
+  int field_D40;
+  int field_D44;
+  int field_D48;
+  int field_D4C;
+  float field_D50;
+  int field_D54;
+  int field_D58;
+  int field_D5C;
+  int field_D60;
+  int field_D64;
+  char field_D68[111900];
+  float fFogDensity;
+  int uLastSunlightUpdateMinute;
+};
+#pragma pack(pop)
+
+
+extern struct OutdoorLocation *pOutdoor;
+
+
+
+
+
+
+
+
+
+
+
+
+
+#include "Outdoor_stuff.h"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OutdoorCamera.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,70 @@
+#pragma once
+
+
+/*   88 */
+#pragma pack(push, 1)
+struct OutdoorCamera
+{
+  //----- (00462684) --------------------------------------------------------
+  OutdoorCamera()
+  {
+    uPickDepth = 0;
+    this->shading_dist_shade = 2048;
+    shading_dist_shademist = 4096;
+    shading_dist_mist = 8192;
+    int_fov_rad = 0;
+    this->bNoSky = 0;
+    this->bDoNotRenderDecorations = 0;
+    this->field_5C = 0;
+    this->field_60 = 0;
+    this->outdoor_no_wavy_water = 0;
+    this->outdoor_no_mist = 0;
+  }
+
+  void _485F64();
+  void RotationToInts();
+  void AllocSoftwareDrawBuffers();
+  void ReleaseSoftwareDrawBuffers();
+
+  static void Project(unsigned int uNumVertices);
+  static bool _487355();
+
+
+
+
+  int uPickDepth;
+  int shading_dist_shade;
+  int shading_dist_shademist;
+  int shading_dist_mist;
+  unsigned int uCameraFovInDegrees;
+  int int_fov_rad;
+  int int_fov_rad_inv;
+  int camera_rotation_y_int_sine;
+  int camera_rotation_y_int_cosine;
+  int camera_rotation_x_int_sine;
+  int camera_rotation_x_int_cosine;
+  int numStru148s;
+  unsigned int uNumEdges;
+  unsigned int uNumSurfs;
+  unsigned int uNumSpans;
+  unsigned int uNumBillboards;
+  float field_40;
+  int field_44;
+  int outdoor_grid_band_3;
+  int field_4C;
+  int field_50;
+  unsigned int bNoSky;
+  unsigned int bDoNotRenderDecorations;
+  int field_5C;
+  int field_60;
+  int outdoor_no_wavy_water;
+  int outdoor_no_mist;
+  int building_gamme;
+  int terrain_gamma;
+};
+#pragma pack(pop)
+
+
+
+
+extern struct OutdoorCamera *pOutdoorCamera;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Outdoor_stuff.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,152 @@
+#pragma once
+
+
+
+
+/*  141 */
+#pragma pack(push, 1)
+struct stru148
+{
+  int _479295();
+  void _4811A3();
+  void _48276F_sr();
+  void _486089_normalize_v_18();
+  void _48607B(struct stru149 *a2);
+
+  float field_0;
+  float field_4;
+  float field_8;
+  float field_C;
+  float field_10;
+  unsigned int uNumVertices;
+  Vec3_int_ v_18;
+  int field_24;
+  int sTextureDeltaU;
+  int sTextureDeltaV;
+  __int16 flags;
+  __int16 field_32;
+  int field_34;
+  struct stru149 *ptr_38;
+  Texture *pTexture;
+  struct Span *prolly_head;
+  struct Span *prolly_tail;
+  int **ptr_48;
+  unsigned __int16 uTileBitmapID;
+  __int16 field_4E;
+  __int16 field_50;
+  __int16 field_52;
+  ODMFace *pODMFace;
+  char field_58;
+  char field_59;
+  char field_5A;
+  char field_5B;
+  char field_5C;
+  char field_5D;
+  unsigned __int8 uBModelID;
+  unsigned __int8 uBModelFaceID;
+  struct Edge *pEdgeList1[20];
+  unsigned int uEdgeList1Size;
+  struct Edge *pEdgeList2[20];
+  unsigned int uEdgeList2Size;
+  char field_108;
+  char field_109;
+  char field_10A;
+  char field_10B;
+};
+#pragma pack(pop)
+
+/*  142 */
+#pragma pack(push, 1)
+struct stru149
+{
+  int _48616B(int a2, int a3, int a4, int a5, int a6, int a7);
+  int _48653D(int a2, int a3, int a4, int a5, int a6, int a7);
+  int _48694B();
+
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+};
+#pragma pack(pop)
+extern stru149 stru_8019C8;
+
+
+
+/*  143 */
+#pragma pack(push, 1)
+struct Span
+{
+  Span *pNext;
+  struct stru148 *pParent;
+  __int16 field_8;
+  __int16 field_A;
+  __int16 field_C;
+  __int16 field_E;
+  float field_10;
+  float field_14;
+};
+#pragma pack(pop)
+extern stru148 array_77EC08[2000];
+
+
+
+/*  144 */
+#pragma pack(push, 1)
+struct Surf
+{
+  float field_0;
+  float field_4;
+  float field_8;
+  float field_C;
+  float field_10;
+  Surf *pNext;
+  Surf *pPrev;
+  struct stru148 *pParent;
+  __int16 field_20;
+  __int16 field_22;
+};
+#pragma pack(pop)
+extern Surf stru_80C980;
+
+
+
+
+/*  145 */
+#pragma pack(push, 1)
+struct Edge
+{
+  float field_0;
+  float field_4;
+  int field_8;
+  Surf *pSurf;
+  Edge *pNext;
+  Edge *pPrev;
+  Edge *ptr_18;
+  float field_1C;
+  float field_20;
+  float field_24;
+  float field_28;
+  float field_2C;
+  float field_30;
+};
+#pragma pack(pop)
+extern Edge defaultEdge; // weak
+
+extern Edge stru_80C9A4;
+extern Edge stru_80C9D8;
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Overlays.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,302 @@
+#include <stdlib.h>
+
+#include "Overlays.h"
+#include "Sprites.h"
+#include "FrameTableInc.h"
+#include "Allocator.h"
+#include "IconFrameTable.h"
+#include "Time.h"
+#include "Party.h"
+#include "TurnEngine.h"
+#include "LOD.h"
+#include "Render.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+struct OtherOverlayList *pOtherOverlayList = new OtherOverlayList; // idb
+struct OverlayList *pOverlayList = new OverlayList;
+
+
+
+
+
+
+
+
+//----- (004418B1) --------------------------------------------------------
+int OtherOverlayList::_4418B1(int a2, int a3, int a4, int a5)
+{
+  return 0;
+}
+
+//----- (004418B6) --------------------------------------------------------
+int OtherOverlayList::_4418B6(int uOverlayID, __int16 a3, int a4, int a5, __int16 a6)
+{
+  signed int v6; // edx@1
+  OtherOverlayList *v7; // eax@1
+  signed int result; // eax@4
+  signed int v9; // esi@6
+  __int16 v10; // dx@9
+  __int16 v11; // dx@11
+
+  v6 = 0;
+  v7 = this;
+  while ( v7->pOverlays[0].field_6 > 0 )
+  {
+    ++v6;
+    v7 = (OtherOverlayList *)((char *)v7 + 20);
+    if ( v6 >= 50 )
+      return 0;
+  }
+  v7->pOverlays[0].field_0 = 0;
+  v7->pOverlays[0].field_A = 0;
+  v7->pOverlays[0].field_8 = 0;
+  v7->pOverlays[0].field_C = a3;
+  v9 = 0;
+  if ( (signed int)pOverlayList->uNumOverlays <= 0 )
+  {
+LABEL_9:
+    v10 = 0;
+  }
+  else
+  {
+    while ( uOverlayID != pOverlayList->pOverlays[v9].uOverlayID )
+    {
+      ++v9;
+      if ( v9 >= (signed int)pOverlayList->uNumOverlays )
+        goto LABEL_9;
+    }
+    v10 = v9;
+  }
+  v7->pOverlays[0].field_2 = v10;
+  v7->pOverlays[0].field_4 = 0;
+  if ( a4 )
+    v11 = a4;
+  else
+    v11 = 8 * pSpriteFrameTable->pSpriteSFrames[pOverlayList->pOverlays[v10].uSpriteFramesetID].uAnimLength;
+  v7->pOverlays[0].field_6 = v11;
+  v7->pOverlays[0].field_10 = a5;
+  v7->pOverlays[0].field_E = a6;
+  result = 1;
+  this->field_3EC = 1;
+  return result;
+}
+
+//----- (00441964) --------------------------------------------------------
+unsigned int OtherOverlayList::_441964(int a2)
+{
+  unsigned int result; // eax@1
+  IconFrameTable *v3; // ecx@6
+  void *v4; // eax@12
+  unsigned int v5; // [sp-8h] [bp-Ch]@4
+  int v6; // [sp-4h] [bp-8h]@4
+  Texture *v7; // [sp-4h] [bp-8h]@14
+
+  result = pCurrentScreen;
+  if ( pCurrentScreen
+    || pParty->bTurnBasedModeOn != 1 )
+    return result;
+  if ( pTurnEngine->field_4 == 3 )
+  {
+    v6 = pEventTimer->uStartTime;
+    v5 = pIconIDs_Turn[5 - pTurnEngine->uActionPointsLeft / 26];
+  }
+  else
+  {
+    if ( pTurnEngine->field_4 == 1 )
+    {
+      v6 = dword_50C994;
+      v3 = pIconsFrameTable;
+      if ( dword_50C998_turnbased_icon_1A )
+        v5 = uIconID_TurnStart;
+      else
+        v5 = uIconID_TurnHour;
+      goto LABEL_12;
+    }
+    if ( pTurnEngine->field_4 != 2 )
+    {
+      v4 = this;
+      goto LABEL_14;
+    }
+    v6 = pEventTimer->uStartTime;
+    v5 = uIconID_TurnStop;
+  }
+  v3 = pIconsFrameTable;
+LABEL_12:
+  v4 = pIconsFrameTable->GetFrame(v5, v6);
+LABEL_14:
+  v7 = &pIcons_LOD->pTextures[*((short *)v4 + 15)];
+  if ( pRenderer->pRenderD3D )
+    pRenderer->DrawTextureIndexed(0x18Au, 0x120u, v7);
+  else
+    pRenderer->DrawTextureTransparent(0x18Au, 0x120u, v7);
+  result = dword_50C994;
+  if ( dword_50C994 < dword_50C998_turnbased_icon_1A )
+  {
+    result = pEventTimer->uTimeElapsed + dword_50C994;
+    dword_50C994 = result;
+    if ( (signed int)result >= dword_50C998_turnbased_icon_1A )
+      dword_50C998_turnbased_icon_1A = 0;
+  }
+  return result;
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+// 50C994: using guessed type int dword_50C994;
+// 50C998: using guessed type int dword_50C998_turnbased_icon_1A;
+
+
+//----- (00458D97) --------------------------------------------------------
+void OverlayList::InitializeSprites()
+{
+  OverlayList *v1; // esi@1
+  signed int i; // edi@1
+
+  v1 = this;
+  for ( i = 0; i < (signed int)v1->uNumOverlays; ++i )
+    pSpriteFrameTable->InitializeSprite(v1->pOverlays[i].uSpriteFramesetID);
+}
+
+//----- (00458DBC) --------------------------------------------------------
+void OverlayList::ToFile()
+{
+  OverlayList *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  v1 = this;
+  v2 = fopen("data\\doverlay.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save doverlay.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pOverlays, 8u, v1->uNumOverlays, v3);
+  fclose(v3);
+}
+
+//----- (00458E08) --------------------------------------------------------
+void OverlayList::FromFile(void *pSerialized)
+{
+  uNumOverlays = *(int *)pSerialized;
+  pOverlays = (OverlayDesc *)pAllocator->AllocNamedChunk(pOverlays, 8 * uNumOverlays, "Ovl Des.");
+  memcpy(pOverlays, (char *)pSerialized + 4, 8 * uNumOverlays);
+}
+
+//----- (00458E4F) --------------------------------------------------------
+bool OverlayList::FromFileTxt(const char *Args)
+{
+  OverlayList *v2; // ebx@1
+  __int32 v3; // edi@1
+  FILE *v4; // eax@1
+  unsigned int v5; // esi@3
+  const void *v6; // ST18_4@9
+  void *v7; // eax@9
+  FILE *v8; // ST0C_4@11
+  char *i; // eax@11
+  unsigned __int16 v10; // ax@14
+  const char *v11; // ST1C_4@14
+  int v12; // eax@16
+  OverlayDesc *v13; // ecx@16
+  char v14; // zf@16
+  unsigned int v15; // eax@16
+  char Buf; // [sp+10h] [bp-2F0h]@3
+  FrameTableTxtLine v18; // [sp+204h] [bp-FCh]@4
+  FrameTableTxtLine v19; // [sp+280h] [bp-80h]@4
+  FILE *File; // [sp+2FCh] [bp-4h]@1
+  unsigned int Argsa; // [sp+308h] [bp+8h]@3
+
+  v2 = this;
+  pAllocator->FreeChunk(this->pOverlays);
+  v3 = 0;
+  v2->pOverlays = 0;
+  v2->uNumOverlays = 0;
+  v4 = fopen(Args, "r");
+  File = v4;
+  if ( !v4 )
+    Abortf("ObjectDescriptionList::load - Unable to open file: %s.");
+  v5 = 0;
+  Argsa = 0;
+  if ( fgets(&Buf, 490, v4) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v19, texture_frame_table_txt_parser(&Buf, &v18), sizeof(v19));
+      if ( v19.field_0 && *v19.pProperties[0] != 47 )
+        ++Argsa;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v5 = Argsa;
+    v3 = 0;
+  }
+  v6 = v2->pOverlays;
+  v2->uNumOverlays = v5;
+  v7 = pAllocator->AllocNamedChunk(v6, 8 * v5, "Ovl Des.");
+  v2->pOverlays = (OverlayDesc *)v7;
+  if ( v7 == (void *)v3 )
+    Abortf("OverlayDescriptionList::load - Out of Memory!");
+  memset(v7, v3, 8 * v2->uNumOverlays);
+  v8 = File;
+  v2->uNumOverlays = v3;
+  fseek(v8, v3, v3);
+  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v19, texture_frame_table_txt_parser(&Buf, &v18), sizeof(v19));
+    if ( v19.field_0 && *v19.pProperties[0] != 47 )
+    {
+      v10 = atoi(v19.pProperties[0]);
+      v11 = v19.pProperties[1];
+      v2->pOverlays[v2->uNumOverlays].uOverlayID = v10;
+      if ( _strcmpi(v11, "center") )
+      {
+        v12 = _strcmpi(v19.pProperties[1], "transparent");
+        v13 = v2->pOverlays;
+        v14 = v12 == 0;
+        v15 = v2->uNumOverlays;
+        if ( v14 )
+          v13[v15].uOverlayType = 2;
+        else
+          v13[v15].uOverlayType = 1;
+      }
+      else
+      {
+        v2->pOverlays[v2->uNumOverlays].uOverlayType = 0;
+      }
+      v2->pOverlays[v2->uNumOverlays++].uSpriteFramesetID = pSpriteFrameTable->FastFindSprite(
+                                                              (char *)v19.pProperties[2]);
+    }
+  }
+  fclose(File);
+  return 1;
+}
+
+
+//----- (0045855F) --------------------------------------------------------
+void OtherOverlay::Reset()
+{
+  this->field_10 = 65536;
+  this->field_A = 0;
+  this->field_8 = 0;
+  this->field_6 = 0;
+  this->field_4 = 0;
+  this->field_2 = 0;
+  this->field_C = 0;
+  this->field_E = 0;
+}
+
+//----- (004584B8) --------------------------------------------------------
+OtherOverlay::OtherOverlay()
+{
+  this->field_A = 0;
+  this->field_8 = 0;
+  this->field_6 = 0;
+  this->field_4 = 0;
+  this->field_2 = 0;
+  this->field_C = 0;
+  this->field_E = 0;
+  this->field_10 = 65536;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Overlays.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,79 @@
+#pragma once
+
+
+/*  282 */
+#pragma pack(push, 1)
+struct OtherOverlay
+{
+  OtherOverlay();
+  void Reset();
+
+  __int16 field_0;
+  __int16 field_2;
+  __int16 field_4;
+  __int16 field_6;
+  __int16 field_8;
+  __int16 field_A;
+  __int16 field_C;
+  __int16 field_E;
+  int field_10;
+};
+#pragma pack(pop)
+
+/*   63 */
+#pragma pack(push, 1)
+struct OtherOverlayList
+{
+  inline OtherOverlayList():  //----- (0045848D)
+    field_3E8(0), field_3EC(0)
+  {}
+    
+  int _4418B1(int a2, int a3, int a4, int a5);
+  int _4418B6(int uOverlayID, __int16 a3, int a4, int a5, __int16 a6);
+  unsigned int _441964(int a2);
+
+  OtherOverlay pOverlays[50];
+  int field_3E8;
+  int field_3EC;
+};
+#pragma pack(pop)
+
+
+
+
+/*   52 */
+#pragma pack(push, 1)
+struct OverlayDesc
+{
+  unsigned __int16 uOverlayID;
+  unsigned __int16 uOverlayType;
+  unsigned __int16 uSpriteFramesetID;
+  __int16 field_6;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct OverlayList
+{
+  inline OverlayList():  //----- (00458474)
+    uNumOverlays(0), pOverlays(nullptr)
+  {}
+
+  void ToFile();
+  void FromFile(void *pSerialized);
+  bool FromFileTxt(const char *Args);
+  void InitializeSprites();
+
+
+  unsigned int uNumOverlays;
+  struct OverlayDesc *pOverlays;
+};
+#pragma pack(pop)
+
+
+
+
+extern struct OtherOverlayList *pOtherOverlayList; // idb
+extern struct OverlayList *pOverlayList;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PaletteManager.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,880 @@
+#include "PaletteManager.h"
+#include "Texture.h"
+#include "Game.h"
+#include "LOD.h"
+
+#include "mm7_data.h"
+
+
+
+
+PaletteManager *pPaletteManager = new PaletteManager;
+
+
+
+
+//----- (0048A643) --------------------------------------------------------
+bool __fastcall HSV2RGB(float *a1, float *a2, float *a3, float a4, float a5, float a6)
+{
+  float *v6; // ebx@1
+  float *v7; // edi@1
+  float *v8; // esi@1
+  double v9; // st7@5
+  signed __int64 v10; // qax@5
+  double v11; // st7@5
+  double v12; // st5@5
+  int v13; // eax@6
+  int v14; // eax@7
+  int v15; // eax@8
+  int v16; // eax@9
+  float v17; // eax@11
+  float a3a; // [sp+1Ch] [bp+8h]@14
+  float a4b; // [sp+20h] [bp+Ch]@5
+  float a4c; // [sp+20h] [bp+Ch]@5
+  float a4a; // [sp+20h] [bp+Ch]@5
+
+  v6 = a3;
+  v7 = a2;
+  v8 = a1;
+  if ( a5 == 0.0 )
+  {
+    *a3 = a6;
+    *a2 = a6;
+    *a1 = a6;
+    goto LABEL_20;
+  }
+  if ( a4 == 360.0 )
+    a4 = 0.0;
+  v9 = a4 * 0.01666666666666667;
+  a4b = v9;
+  floor(v9);
+  v10 = (signed __int64)v9;
+  a4c = a4b - (double)(signed int)(signed __int64)v9;
+  v11 = (1.0 - a5) * a6;
+  v12 = (1.0 - a4c * a5) * a6;
+  a4a = (1.0 - (1.0 - a4c) * a5) * a6;
+  if ( (int)v10 )
+  {
+    v13 = v10 - 1;
+    if ( v13 )
+    {
+      v14 = v13 - 1;
+      if ( v14 )
+      {
+        v15 = v14 - 1;
+        if ( v15 )
+        {
+          v16 = v15 - 1;
+          if ( v16 )
+          {
+            if ( v16 != 1 )
+              goto LABEL_20;
+            *v8 = a6;
+            v17 = v12;
+            *v7 = v11;
+            goto LABEL_12;
+          }
+          *(int *)v8 = LODWORD(a4a);
+          *v7 = v11;
+        }
+        else
+        {
+          *v8 = v11;
+          a3a = v12;
+          *(int *)v7 = LODWORD(a3a);
+        }
+        v17 = a6;
+      }
+      else
+      {
+        *v8 = v11;
+        *(int *)v7 = LODWORD(a6);
+        v17 = a4a;
+      }
+LABEL_12:
+      *(int *)v6 = LODWORD(v17);
+      goto LABEL_20;
+    }
+    *v8 = v12;
+    *v7 = a6;
+  }
+  else
+  {
+    *v8 = a6;
+    *(int *)v7 = LODWORD(a4a);
+  }
+  *a3 = v11;
+LABEL_20:
+  if ( *v8 > 1.0 )
+    *v8 = 1.0;
+  if ( *v7 > 1.0 )
+    *v7 = 1.0;
+  if ( *v6 > 1.0 )
+    *v6 = 1.0;
+  if ( *v8 < 0.0 )
+    *v8 = 0.0;
+  if ( *v7 < 0.0 )
+    *v7 = 0.0;
+  if ( *v6 < 0.0 )
+    *v6 = 0.0;
+  return 1;
+}
+
+//----- (0048A7AA) --------------------------------------------------------
+void __fastcall RGB2HSV(float *a1, float *a2, float a3, float a4, float a5, float *a6)
+{
+  double v6; // st7@2
+  double v7; // st6@7
+  double v8; // st5@12
+  double v9; // st7@15
+  double v10; // st7@17
+  double v11; // st7@21
+  __int16 v12; // fps@21
+  unsigned __int8 v13; // c0@21
+  unsigned __int8 v14; // c2@21
+  float a6a; // [sp+14h] [bp+14h]@16
+
+  if ( a3 <= (double)a4 )
+    v6 = a4;
+  else
+    v6 = a3;
+  if ( v6 < a5 )
+    v6 = a5;
+  if ( a3 <= (double)a4 )
+    v7 = a3;
+  else
+    v7 = a4;
+  if ( v7 > a5 )
+    v7 = a5;
+  *a6 = v6;
+  if ( v6 == 0.0 )
+    v8 = 0.0;
+  else
+    v8 = (v6 - v7) / v6;
+  *a2 = v8;
+  if ( v8 == 0.0 )
+  {
+    v9 = 0.0;
+LABEL_23:
+    *a1 = v9;
+    return;
+  }
+  a6a = v6 - v7;
+  if ( a3 == v6 )
+  {
+    v10 = (a4 - a5) / a6a;
+  }
+  else
+  {
+    if ( a4 == v6 )
+      v10 = (a5 - a3) / a6a + 2.0;
+    else
+      v10 = (a3 - a4) / a6a + 4.0;
+  }
+  //*a1 = v10;
+  //v11 = *a1 * 60.0;
+  //UNDEF(v12);
+  *a1 = v10 * 60.0;
+  if (*a1 < 0)
+  {
+    *a1 += 360.0;
+  }
+}
+
+
+
+//----- (0048A8A3) --------------------------------------------------------
+int PaletteManager::LockAll()
+{
+  int *v1; // edx@1
+  signed int v2; // eax@1
+
+  v1 = &this->pPaletteIDs[1];
+  v2 = 1;
+  do
+  {
+    if ( *v1 )
+      this->_num_locked = v2 + 1;
+    ++v2;
+    ++v1;
+  }
+  while ( v2 < 50 );
+  return this->_num_locked;
+}
+
+//----- (0048A8CC) --------------------------------------------------------
+int PaletteManager::LockTestAll()
+{
+  char *v1; // edx@1
+  signed int v2; // eax@1
+
+  v1 = (char *)&this->pPaletteIDs[1];
+  v2 = 1;
+  do
+  {
+    if ( *(int *)v1 )
+      this->_pal_lock_test = v2 + 1;
+    ++v2;
+    v1 += 4;
+  }
+  while ( v2 < 50 );
+  return this->_pal_lock_test;
+}
+
+
+//----- (0048A8F5) --------------------------------------------------------
+void PaletteManager::SetColorChannelInfo(int uNumRBits, int uNumGBits, int uNumBBits)
+{
+  PaletteManager *v4; // esi@1
+  int v5; // edi@1
+  int v6; // eax@1
+  int v7; // ebx@1
+
+  v4 = this;
+  this->uNumTargetRBits = uNumRBits;
+  this->uNumTargetGBits = uNumGBits;
+  v5 = this->uNumTargetGBits;
+  this->uNumTargetBBits = uNumBBits;
+  v6 = MakeColorMaskFromBitDepth(uNumRBits);
+  v7 = v4->uNumTargetBBits;
+  v4->uTargetRMask = v6 << (v5 + v4->uNumTargetBBits);
+  v4->uTargetGMask = MakeColorMaskFromBitDepth(v5) << v7;
+  v4->uTargetBMask = MakeColorMaskFromBitDepth(v7);
+}
+
+
+//----- (00489BE0) --------------------------------------------------------
+int PaletteManager::CalcPalettes_LUT(int a2)
+{
+  PaletteManager *v2; // esi@1
+  char *v3; // edi@1
+  signed int v4; // ebx@4
+  float v5; // ST08_4@5
+  float v6; // ST04_4@5
+  float v7; // ST00_4@5
+  int v8; // eax@7
+  float *v9; // edx@8
+  float *v10; // ST0C_4@8
+  float *v11; // ecx@8
+  int v12; // ebx@8
+  int v13; // eax@8
+  float v14; // ebx@8
+  float v15; // ST08_4@8
+  float v16; // ST04_4@8
+  float v17; // ST00_4@8
+  unsigned __int8 v18; // sf@8
+  unsigned __int8 v19; // of@8
+  int v20; // eax@10
+  double v21; // st5@11
+  float v22; // ST0C_4@13
+  unsigned int v23; // eax@13
+  __int16 v24; // bx@16
+  int v25; // eax@16
+  double v26; // st7@20
+  float v27; // ST0C_4@22
+  unsigned int v28; // eax@22
+  __int16 v29; // bx@25
+  __int16 *v30; // eax@25
+  int v31; // eax@27
+  double v32; // st5@28
+  float v33; // ST0C_4@30
+  float v34; // ST08_4@30
+  unsigned int v35; // ebx@30
+  signed __int64 v36; // qax@33
+  signed int v37; // edx@33
+  char v38; // cl@33
+  unsigned int v39; // ebx@33
+  signed int v40; // edi@33
+  unsigned int v41; // ecx@33
+  unsigned int v42; // ecx@35
+  int v43; // eax@39
+  signed int v44; // edx@39
+  unsigned __int8 v45; // al@40
+  double v46; // st6@43
+  signed int v47; // eax@43
+  int v48; // eax@45
+  double v49; // st6@47
+  float v50; // ST08_4@49
+  unsigned int v51; // ebx@49
+  int v52; // edi@55
+  int v53; // ebx@55
+  signed __int64 v54; // qax@55
+  double v55; // st7@56
+  unsigned int v56; // ecx@57
+  unsigned int v57; // ecx@59
+  //int v58; // edx@61
+  unsigned int v59; // ecx@61
+  unsigned int v60; // eax@63
+  char v61; // cl@63
+  int result; // eax@63
+  float v63[256]; // [sp+1Ch] [bp-C38h]@5
+  float v64[256]; // [sp+41Ch] [bp-838h]@5
+  int a6[256]; // [sp+81Ch] [bp-438h]@5
+  int v66; // [sp+C1Ch] [bp-38h]@43
+  float v67; // [sp+C20h] [bp-34h]@43
+  float v68; // [sp+C24h] [bp-30h]@43
+  PaletteManager *v69; // [sp+C28h] [bp-2Ch]@9
+  float v70; // [sp+C2Ch] [bp-28h]@43
+  double v71; // [sp+C30h] [bp-24h]@10
+  int v72; // [sp+C38h] [bp-1Ch]@9
+  int v73; // [sp+C3Ch] [bp-18h]@9
+  int i; // [sp+C40h] [bp-14h]@7
+  float v75; // [sp+C44h] [bp-10h]@5
+  float a2a; // [sp+C48h] [bp-Ch]@13
+  float a1; // [sp+C4Ch] [bp-8h]@13
+  float a3; // [sp+C50h] [bp-4h]@13
+  signed int v79; // [sp+C5Ch] [bp+8h]@33
+  signed int v80; // [sp+C5Ch] [bp+8h]@43
+  int v81; // [sp+C5Ch] [bp+8h]@57
+
+  v2 = this;
+  v3 = (char *)this + 768 * a2;
+  if (pPalette_tintColor[0] || pPalette_tintColor[1] || pPalette_tintColor[2])
+  {
+    v8 = 0;
+    i = 0;
+    do
+    {
+      v9 = (float *)((char *)v63 + v8);
+      v10 = (float *)((char *)a6 + v8);
+      v11 = (float *)((char *)v64 + v8);
+      v12 = pPalette_tintColor[1];
+      LODWORD(v75) = pPalette_tintColor[2] + (unsigned __int8)v3[2];
+      v13 = v12 + (unsigned __int8)v3[1];
+      LODWORD(v14) = (unsigned __int8)*v3;
+      v15 = (double)SLODWORD(v75) * 0.00196078431372549;
+      LODWORD(v75) = v13;
+      LODWORD(v75) = LODWORD(v14) + pPalette_tintColor[0];
+      v16 = (double)v13 * 0.00196078431372549;
+      v17 = (double)SLODWORD(v75) * 0.00196078431372549;
+      RGB2HSV(v11, v9, v17, v16, v15, v10);
+      v3 += 3;
+      v8 = i + 4;
+      v19 = __OFSUB__(i + 4, 1024);
+      v18 = i - 1020 < 0;
+      i += 4;
+    }
+    while ( v18 ^ v19 );
+  }
+  else
+  {
+    v4 = 0;
+    do
+    {
+      LODWORD(v75) = (unsigned __int8)v3[2];
+      v5 = (double)SLODWORD(v75) * 0.00392156862745098;
+      LODWORD(v75) = (unsigned __int8)v3[1];
+      v6 = (double)SLODWORD(v75) * 0.00392156862745098;
+      LODWORD(v75) = (unsigned __int8)*v3;
+      v7 = (double)SLODWORD(v75) * 0.00392156862745098;
+      RGB2HSV(&v64[v4], &v63[v4], v7, v6, v5, (float *)&a6[v4]);
+      ++v4;
+      v3 += 3;
+    }
+    while ( v4 < 256 );
+  }
+  v69 = (PaletteManager *)((char *)v2 + 16384 * a2);
+  v72 = 0;
+  v73 = (int)v69->pPalette1;
+  do
+  {
+    v20 = 0;
+    i = 0;
+    v71 = 1.0 - (double)v72 * 0.03225806451612903;
+    do
+    {
+      v21 = *(float *)((char *)a6 + v20) * v71;
+      if ( v21 < 0.0 )
+        v21 = 0.0;
+      v22 = v21;
+      HSV2RGB(&a1, &a2a, &a3, *(float *)((char *)v64 + v20), *(float *)((char *)v63 + v20), v22);
+      v23 = v2->uNumTargetGBits;
+      if ( v23 == 6 )
+      {
+        a1 = a1 * 31.0;
+        a2a = a2a * 62.0;
+        a3 = a3 * 31.0;
+      }
+      else
+      {
+        a1 = a1 * 31.0;
+        a2a = a2a * 31.0;
+        a3 = a3 * 31.0;
+      }
+      v24 = (unsigned __int64)(signed __int64)a3 | ((unsigned __int16)(signed __int64)a2a << v2->uNumTargetBBits) | (unsigned __int16)((unsigned __int16)(signed __int64)a1 << (v2->uNumTargetBBits + v23));
+      v25 = v73;
+      v73 += 2;
+      *(short *)v25 = v24;
+      v20 = i + 4;
+      v19 = __OFSUB__(i + 4, 1024);
+      v18 = i - 1020 < 0;
+      i += 4;
+    }
+    while ( v18 ^ v19 );
+    ++v72;
+  }
+  while ( v72 < 32 );
+  v72 = 0;
+  v73 = (int)v69->field_199600_palettes;
+  do
+  {
+    i = 0;
+    v71 = 1.0 - (double)v72 * 0.03225806451612903;
+    do
+    {
+      v26 = *(float *)&a6[i] * v71;
+      if ( v26 < 0.0 )
+        v26 = 0.0;
+      v27 = v26;
+      HSV2RGB(&a1, &a2a, &a3, 1.0, 1.0, v27);
+      v28 = v2->uNumTargetGBits;
+      if ( v28 == 6 )
+      {
+        a1 = a1 * 31.0;
+        a2a = a2a * 62.0;
+        a3 = a3 * 31.0;
+      }
+      else
+      {
+        a1 = a1 * 31.0;
+        a2a = a2a * 31.0;
+        a3 = a3 * 31.0;
+      }
+      v29 = (unsigned __int64)(signed __int64)a3 | ((unsigned __int16)(signed __int64)a2a << v2->uNumTargetBBits) | (unsigned __int16)((unsigned __int16)(signed __int64)a1 << (v2->uNumTargetBBits + v28));
+      v30 = (__int16 *)v73;
+      ++i;
+      v73 += 2;
+      v19 = __OFSUB__(i, 256);
+      v18 = i - 256 < 0;
+      *v30 = v29;
+    }
+    while ( v18 ^ v19 );
+    ++v72;
+  }
+  while ( v72 < 32 );
+  v73 = (int)((char *)v2 + 512 * (a2 + 4875));
+  v31 = 0;
+  i = 0;
+  do
+  {
+    v32 = (*(float *)((char *)a6 + v31) - 0.8) * 0.8387096774193549 + 0.8;
+    if ( v32 < 0.0 )
+      v32 = 0.0;
+    v33 = v32;
+    v34 = *(float *)((char *)v63 + v31) * 0.7034339229968783;
+    HSV2RGB(&a1, &a2a, &a3, *(float *)((char *)v64 + v31), v34, v33);
+    v35 = v2->uNumTargetGBits;
+    if ( v35 == 6 )
+    {
+      a1 = a1 * 31.0;
+      a2a = a2a * 62.0;
+      a3 = a3 * 31.0;
+    }
+    else
+    {
+      a1 = a1 * 31.0;
+      a2a = a2a * 31.0;
+      a3 = a3 * 31.0;
+    }
+    v36 = (signed __int64)((a1 + a2a + a3) * 0.3333333333333333 * 8.0);
+    v37 = (signed int)v36 >> (8 - v2->uNumTargetRBits);
+    v38 = 8 - v35;
+    v39 = v2->uNumTargetBBits;
+    v40 = (signed int)v36 >> v38;
+    v41 = v2->uNumTargetRBits;
+    v79 = (signed int)v36 >> (8 - v39);
+    if ( v37 > (1 << v41) - 1 )
+      v37 = (1 << v41) - 1;
+    v42 = v2->uNumTargetGBits;
+    if ( v40 > (1 << v42) - 1 )
+      v40 = (1 << v42) - 1;
+    if ( v79 > (1 << v39) - 1 )
+      v79 = (1 << v39) - 1;
+    v43 = v73;
+    v44 = v37 << (v39 + v2->uNumTargetGBits);
+    v73 += 2;
+    *(short *)v43 = v79 | ((short)v40 << v39) | (unsigned __int16)v44;
+    v31 = i + 4;
+    v19 = __OFSUB__(i + 4, 1024);
+    v18 = i - 1020 < 0;
+    i += 4;
+  }
+  while ( v18 ^ v19 );
+  v45 = pPalette_mistColor[0];
+  if (v45 || pPalette_mistColor[1] || pPalette_mistColor[2])
+  {
+    v46 = (double)v45;
+    v80 = pPalette_mistColor[1];
+    v47 = pPalette_mistColor[2];
+    v70 = v46 * 0.00392156862745098;
+    *((float *)&v71 + 1) = (double)v80 * 0.00392156862745098;
+    v75 = (double)v47 * 0.00392156862745098;
+    RGB2HSV(&v68, &v67, v70, *((float *)&v71 + 1), v75, (float *)&v66);
+  }
+  v72 = 0;
+  v73 = (int)v69->field_D1600;
+
+
+  do
+  {
+    v48 = 0;
+    for ( i = 0; ; v48 = i )
+    {
+      v49 = *(float *)((char *)v63 + v48);
+      if ( v49 < 0.0 )
+        v49 = 0.0;
+      v50 = v49;
+      HSV2RGB(&a1, &a2a, &a3, *(float *)((char *)v64 + v48), v50, *(float *)((char *)a6 + v48));
+      v51 = v2->uNumTargetGBits;
+      if ( v51 == 6 )
+      {
+        a1 = a1 * 31.0;
+        a2a = a2a * 62.0;
+        a3 = a3 * 31.0;
+      }
+      else
+      {
+        a1 = a1 * 31.0;
+        a2a = a2a * 31.0;
+        a3 = a3 * 31.0;
+      }
+      if (pPalette_mistColor[0] || pPalette_mistColor[1] || pPalette_mistColor[2])
+      {
+        v55 = (double)v72 * 0.03225806451612903;
+        v52 = (signed __int64)((double)(1 << v2->uNumTargetRBits) * v70 * v55 + a1 * (1.0 - v55));
+        v53 = (signed __int64)((double)(1 << v51) * *((float *)&v71 + 1) * v55 + a2a * (1.0 - v55));
+        v54 = (signed __int64)((double)(1 << v2->uNumTargetBBits) * v75 * v55 + a3 * (1.0 - v55));
+      }
+      else
+      {
+        v52 = (signed __int64)a1;
+        v53 = (signed __int64)a2a;
+        v54 = (signed __int64)a3;
+      }
+      v56 = v2->uNumTargetRBits;
+      v81 = v54;
+      if ( v52 > (1 << v56) - 1 )
+        v52 = (1 << v56) - 1;
+      v57 = v2->uNumTargetGBits;
+      if ( v53 > (1 << v57) - 1 )
+        v53 = (1 << v57) - 1;
+      HIDWORD(v54) = v2->uNumTargetBBits;
+      v59 = v2->uNumTargetBBits;
+      if ( (signed int)v54 > (1 << v59) - 1 )
+        v81 = (1 << v59) - 1;
+      v60 = v2->uNumTargetGBits;
+      i += 4;
+      v61 = uNumTargetBBits + v60;
+      result = v73;
+      v73 += 2;
+      v19 = __OFSUB__(i, 1024);
+      v18 = i - 1024 < 0;
+      *(short *)result = v81 | ((short)v53 << uNumTargetBBits) | (v52 << v61);
+      if ( !(v18 ^ v19) )
+        break;
+    }
+    ++v72;
+  }
+  while ( v72 <  32 );
+  return result;
+}
+
+
+//----- (0048A300) --------------------------------------------------------
+PaletteManager::PaletteManager():
+  uNumTargetRBits(0), uNumTargetGBits(0),uNumTargetBBits(0)
+{
+  for (uint i = 0; i < 256; ++i)
+  {
+    pBaseColors[0][i][0] = i;
+    pBaseColors[0][i][1] = i;
+    pBaseColors[0][i][2] = i;
+  }
+
+  CalcPalettes_LUT(0);
+  memset(pPaletteIDs, 0, sizeof(pPaletteIDs));
+}
+
+//----- (0048A336) --------------------------------------------------------
+// make grayscale palette at 0, clear all palettes ids that aren't locked
+int PaletteManager::ResetNonLocked()
+{
+  PaletteManager *v1; // esi@1
+  signed int v2; // ecx@1
+  int v3; // eax@1
+  signed int result; // eax@3
+  void *v5; // edi@4
+  int v6; // ecx@4
+
+  v1 = this;
+  v2 = 0;
+  v3 = (int)&v1->pBaseColors[0][0][1];
+  do
+  {
+    *(char *)(v3 + 1) = v2;
+    *(char *)v3 = v2;
+    *(char *)(v3 - 1) = v2++;
+    v3 += 3;
+  }
+  while ( v2 < 256 );
+  CalcPalettes_LUT(0);
+  result = v1->_num_locked;
+  if ( result < 50 )
+  {
+    v5 = &v1->pPaletteIDs[result];
+    v6 = 50 - result;
+    result = 0;
+    memset(v5, 0, 4 * v6);
+  }
+  return result;
+}
+
+//----- (0048A379) --------------------------------------------------------
+// make grayscale palette at 0, clear all palettes ids that aren't in "lock_test"
+int PaletteManager::ResetNonTestLocked()
+{
+  PaletteManager *v1; // esi@1
+  signed int v2; // ecx@1
+  int v3; // eax@1
+  signed int result; // eax@3
+  void *v5; // edi@4
+  int v6; // ecx@4
+
+  v1 = this;
+  v2 = 0;
+  v3 = (int)&v1->pBaseColors[0][0][1];
+  do
+  {
+    *(char *)(v3 + 1) = v2;
+    *(char *)v3 = v2;
+    *(char *)(v3 - 1) = v2++;
+    v3 += 3;
+  }
+  while ( v2 < 256 );
+  CalcPalettes_LUT(0);
+  result = v1->_pal_lock_test;
+  if ( result < 50 )
+  {
+    v5 = &v1->pPaletteIDs[result];
+    v6 = 50 - result;
+    result = 0;
+    memset(v5, 0, 4 * v6);
+  }
+  return result;
+}
+
+//----- (0048A3BC) --------------------------------------------------------
+int PaletteManager::LoadPalette(unsigned int uPaletteID)
+{
+  unsigned int *v2; // ecx@1
+  signed int result; // eax@1
+  signed int v4; // esi@6
+  double v5; // st7@7
+  double v6; // st7@12
+  double v7; // st6@17
+  signed __int64 v8; // qax@17
+  double v9; // st6@17
+  char v10[768]; // [sp+18h] [bp-388h]@6
+  //char v11; // [sp+19h] [bp-387h]@17
+  //char v12[766]; // [sp+1Ah] [bp-386h]@17
+  char Source[32]; // [sp+360h] [bp-40h]@4
+  PaletteManager *v15; // [sp+380h] [bp-20h]@1
+  float v16; // [sp+384h] [bp-1Ch]@7
+  int v17; // [sp+388h] [bp-18h]@6
+  float v18; // [sp+38Ch] [bp-14h]@7
+  float a2a; // [sp+390h] [bp-10h]@7
+  float a1; // [sp+394h] [bp-Ch]@7
+  int a6; // [sp+398h] [bp-8h]@7
+  int a3; // [sp+39Ch] [bp-4h]@7
+
+  v15 = this;
+  v2 = (unsigned int *)&this->pPaletteIDs[1];
+  result = 1;
+  while ( *v2 != uPaletteID )
+  {
+    ++result;
+    ++v2;
+    if ( result >= 50 )
+    {
+      sprintf(Source, "pal%03i", uPaletteID);
+
+      Texture tex; // [sp+318h] [bp-88h]@4
+      //Texture::Texture(&tex);
+
+      if ( pBitmaps_LOD->LoadTextureFromLOD(&tex, Source, TEXTURE_24BIT_PALETTE) == 1 )
+      {
+        v4 = 0;
+        v17 = 1 - (int)&v10;
+        do
+        {
+          LODWORD(a1) = tex.pPalette24[v4];
+          a1 = (double)SLODWORD(a1) * 0.0039215689;
+          LODWORD(a2a) = (unsigned __int8)*(&v10 + v4 + v17 + (unsigned int)tex.pPalette24);
+          a2a = (double)SLODWORD(a2a) * 0.0039215689;
+          a3 = tex.pPalette24[v4 + 2];
+          *(float *)&a3 = (double)a3 * 0.0039215689;
+          RGB2HSV(&v16, &v18, a1, a2a, *(float *)&a3, (float *)&a6);
+          v5 = *(float *)&a6 * 1.1;
+          if ( v5 >= 0.0 && v5 >= 1.0 )
+          {
+            v5 = 1.0;
+          }
+          else
+          {
+            if ( v5 < 0.0 )
+              v5 = 0.0;
+          }
+          *(float *)&a6 = v5;
+          v6 = v18 * 0.64999998;
+          if ( v6 >= 0.0 && v6 >= 1.0 )
+          {
+            v6 = 1.0;
+          }
+          else
+          {
+            if ( v6 < 0.0 )
+              v6 = 0.0;
+          }
+          v18 = v6;
+          HSV2RGB(&a1, &a2a, (float *)&a3, v16, v18, *(float *)&a6);
+          v7 = a2a * 255.0;
+          v10[v4] = (signed __int64)(a1 * 255.0);
+          v8 = (signed __int64)v7;
+          v9 = *(float *)&a3 * 255.0;
+          v10[v4 + 1] = v8;
+          v10[v4 + 2] = (signed __int64)v9;
+          v4 += 3;
+        }
+        while ( v4 < 768 );
+        tex.Release();
+        result = v15->MakePaletteLUT(uPaletteID, v10);
+      }
+      else
+      {
+        result = 0;
+      }
+      return result;
+    }
+  }
+  return result;
+}
+// 48A3BC: using guessed type char var_386[766];
+
+//----- (0048A5A4) --------------------------------------------------------
+int PaletteManager::MakePaletteLUT(int a2, char *entries)
+{
+  PaletteManager *v3; // edi@1
+  signed int result; // eax@1
+  int *v5; // ecx@1
+  int v6; // eax@4
+  int v7; // esi@4
+  int v8; // eax@9
+  signed int v9; // ecx@9
+  int v10; // edx@9
+
+  v3 = this;
+  result = 0;
+  v5 = this->pPaletteIDs;
+  while ( *v5 != a2 )
+  {
+    ++result;
+    ++v5;
+    if ( result >= 50 )
+    {
+      v6 = (int)&v3->pPaletteIDs[1];
+      v7 = 1;
+      while ( *(int *)v6 )
+      {
+        ++v7;
+        v6 += 4;
+        if ( v7 >= 50 )
+          return 0;
+      }
+      v8 = (int)((char *)v3 + 768 * v7);
+      v9 = 768;
+      v10 = (int)(entries - v8);
+      do
+      {
+        *(char *)v8 = *(char *)(v10 + v8);
+        ++v8;
+        --v9;
+      }
+      while ( v9 );
+      v3->pPaletteIDs[v7] = a2;
+      CalcPalettes_LUT(v7);
+      return v7;
+    }
+  }
+  return result;
+}
+
+//----- (0048A614) --------------------------------------------------------
+void PaletteManager::RecalculateAll()
+{
+  CalcPalettes_LUT(0);
+
+  for (uint i = 1; i < 50; ++i)
+    if (pPaletteIDs[i])
+      CalcPalettes_LUT(i);
+}
+
+
+//----- (0047BE67) --------------------------------------------------------
+unsigned __int16 *PaletteManager::Get(int a1)
+{
+  return (unsigned __int16 *)pPaletteManager->field_199600_palettes[a1];
+}
+
+//----- (0047BE72) --------------------------------------------------------
+unsigned __int16 *PaletteManager::Get_Mist_or_Red_LUT(int a1, int a2, char a3)
+{
+  int v3; // eax@4
+
+  if ( a3 & 2 || byte_4D864C && BYTE2(pGame->uFlags) & 4 )
+    v3 = 32 * a1 + a2 + 3275;
+  else
+    v3 = 32 * a1 + a2 + 1675;
+  return (unsigned __int16 *)((char *)&pPaletteManager + 512 * v3);
+}
+// 4D864C: using guessed type char byte_4D864C;
+
+
+//----- (0041F50D) --------------------------------------------------------
+unsigned __int16 *PaletteManager::Get_Dark_or_Red_LUT(int a1, int a2, char a3)
+{
+  int v3; // eax@4
+
+  if ( a3 & 2 || byte_4D864C && BYTE2(pGame->uFlags) & 4 )
+    v3 = 32 * a1 + a2 + 3275;
+  else
+    v3 = 32 * a1 + a2 + 75;
+  return (unsigned __int16 *)((char *)&pPaletteManager + 512 * v3);
+}
+// 4D864C: using guessed type char byte_4D864C;
+
+
+//----- (0047C30E) --------------------------------------------------------
+unsigned __int16 *PaletteManager::_47C30E_get_palette(int a1, char a2)
+{
+  char *result; // eax@4
+
+  if ( a2 & 2 || byte_4D864C && BYTE2(pGame->uFlags) & 4 )
+    result = (char *)pPaletteManager->field_199600_palettes[a1];
+  else
+    result = (char *)pPaletteManager->field_D1600[a1];
+  return (unsigned __int16 *)result;
+}
+
+
+//----- (0047C33F) --------------------------------------------------------
+unsigned __int16 *PaletteManager::_47C33F_get_palette(int a1, char a2)
+{
+  unsigned __int16 *result; // eax@4
+
+  if ( a2 & 2 || byte_4D864C && BYTE2(pGame->uFlags) & 4 )
+    result = (unsigned __int16 *)pPaletteManager->field_199600_palettes[a1];
+  else
+    result = (unsigned __int16 *)pPaletteManager->pPalette1[a1];
+  return result;
+}
+// 4D864C: using guessed type char byte_4D864C;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PaletteManager.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,49 @@
+#pragma once
+
+
+/*  148 */
+#pragma pack(push, 1)
+struct PaletteManager
+{
+  PaletteManager();
+
+  int ResetNonTestLocked();
+  int CalcPalettes_LUT(int a2);
+  int ResetNonLocked();
+  int LoadPalette(unsigned int uPaletteID);
+  int MakePaletteLUT(int a2, char *entries);
+  void RecalculateAll();
+  int LockAll();
+  int LockTestAll();
+  void SetColorChannelInfo(int uNumRBits, int uNumGBits, int uNumBBits);
+
+  static unsigned __int16 *Get(int a1);
+  static unsigned __int16 *Get_Mist_or_Red_LUT(int paletteIdx, int a2, char a3);
+  static unsigned __int16 *Get_Dark_or_Red_LUT(int paletteIdx, int a2, char a3);
+  static unsigned __int16 *_47C30E_get_palette(int a1, char a2);
+  static unsigned __int16 *_47C33F_get_palette(int a1, char a2);
+
+  char pBaseColors[50][256][3];
+  unsigned __int16 pPalette1[50][32][256];
+  unsigned __int16 field_D1600[50][32][256];
+  unsigned __int16 field_199600_palettes[50][32][256];
+  unsigned __int16 field_261600[50][256];
+  int pPaletteIDs[50];
+  int _num_locked;
+  int _pal_lock_test;
+  unsigned __int8 pPalette_mistColor[3];
+  unsigned char pPalette_tintColor[3];
+  char field_267AD6;
+  char field_267AD7;
+  unsigned int uNumTargetRBits;
+  unsigned int uNumTargetGBits;
+  unsigned int uNumTargetBBits;
+  unsigned int uTargetRMask;
+  unsigned int uTargetGMask;
+  unsigned int uTargetBMask;
+};
+#pragma pack(pop)
+
+
+
+extern PaletteManager *pPaletteManager;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParticleEngine.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,846 @@
+#include "ParticleEngine.h"
+#include "Time.h"
+#include "Render.h"
+#include "Viewport.h"
+#include "Outdoor.h"
+#include "Game.h"
+#include "IndoorCamera.h"
+#include "Math.h"
+#include "LOD.h"
+
+#include "mm7_data.h"
+
+//----- (0048AAC5) --------------------------------------------------------
+ParticleEngine::ParticleEngine()
+{
+  for (uint i = 0; i < 500; ++i)
+    memset(&pParticles[i], 0, sizeof(pParticles[i]));
+
+  ResetParticles();
+}
+
+//----- (0048AAF6) --------------------------------------------------------
+void ParticleEngine::ResetParticles()
+{
+  memset(pParticles, 0, 500 * sizeof(*pParticles));
+  uStartParticle = 500;
+  uEndParticle = 0;
+  uTimeElapsed = 0;
+}
+
+//----- (0048AB23) --------------------------------------------------------
+void ParticleEngine::AddParticle(Particle_ *a2)
+{
+  signed int v2; // eax@2
+  Particle *v3; // edx@2
+  Particle *v4; // esi@10
+  int v5; // ecx@10
+  char v6; // zf@10
+
+  if ( !pMiscTimer->bPaused )
+  {
+    v2 = 0;
+    v3 = (Particle *)this;
+    do
+    {
+      if ( !v3->uType )
+        break;
+      ++v2;
+      ++v3;
+    }
+    while ( v2 < 500 );
+    if ( v2 < 500 )
+    {
+      if ( v2 < this->uStartParticle )
+        this->uStartParticle = v2;
+      if ( v2 > this->uEndParticle )
+        this->uEndParticle = v2;
+      v4 = &this->pParticles[v2];
+      v4->uType = a2->bFree;
+      v4->x = a2->x;
+      v4->y = a2->y;
+      v4->z = a2->z;
+      v4->_x = a2->x;
+      v4->_y = a2->y;
+      v4->_z = a2->z;
+      v4->flt_10 = a2->flt_10;
+      v4->flt_14 = a2->flt_14;
+      v4->flt_18 = a2->flt_18;
+      v5 = a2->uDiffuse;
+      v4->uParticleColor = v5;
+      v4->uLightColor = v5;
+      v6 = (v4->uType & 4) == 0;
+      v4->timeToLive = a2->timeToLive;
+      v4->uTextureID = a2->uTextureID;
+      v4->flt_28 = a2->flt_28;
+      if ( v6 )
+      {
+        v4->field_38 = 0;
+        v4->_rotation = 0;
+      }
+      else
+      {
+        v4->field_38 = (unsigned __int8)rand() - 128;
+        v4->_rotation = rand();
+      }
+    }
+  }
+}
+
+//----- (0048ABF3) --------------------------------------------------------
+void ParticleEngine::Draw()
+{
+  uTimeElapsed += pEventTimer->uTimeElapsed;
+  pLines.uNumLines = 0;
+
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    DrawParticles_BLV();
+  else
+    DrawParticles_ODM();
+
+  if (pRenderer->pRenderD3D)
+  {
+    if (pLines.uNumLines)
+    {
+      pRenderer->pRenderD3D->pDevice->SetTexture(0, 0);
+      pRenderer->pRenderD3D->pDevice->DrawPrimitive(
+        D3DPT_LINELIST,
+        D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+        pLines.pLineVertices,
+        pLines.uNumLines,
+        D3DDP_DONOTLIGHT);
+    }
+  }
+}
+
+//----- (0048AC65) --------------------------------------------------------
+void ParticleEngine::UpdateParticles()
+{
+  unsigned int time; // edi@1
+  int v5; // eax@3
+  char v6; // sf@4
+  float v7; // ST4C_4@11
+  double v8; // st7@12
+  int v9; // eax@12
+  double v10; // st7@14
+  signed int v19; // [sp+38h] [bp-14h]@1
+  int v20; // [sp+3Ch] [bp-10h]@1
+  unsigned int time_; // [sp+40h] [bp-Ch]@1
+  int v22; // [sp+44h] [bp-8h]@12
+
+  v20 = 0;
+  time = pMiscTimer->bPaused == 0 ? pEventTimer->uTimeElapsed : 0;
+  v19 = 500;
+  time_ = pMiscTimer->bPaused == 0 ? pEventTimer->uTimeElapsed : 0;
+
+  for (uint i = uStartParticle; i < uEndParticle; ++i)
+  {
+    auto p = pParticles + i;
+
+      v5 = p->uType;
+      if (!p->uType)
+        continue;
+
+        v6 = (p->timeToLive - time) < 0;
+        p->timeToLive -= time;
+        if (v6)
+          p->uType = 0;
+        else
+        {
+          if ( BYTE1(v5) & 2 )
+          {
+            p->_x = p->x;
+            p->_y = p->y;
+            p->_z = p->z;
+          }
+          if ( v5 & 1 )
+            p->flt_18 = p->flt_18 - (double)(signed int)time_ * 5.0;
+          if ( v5 & 8 )
+          {
+            v7 = (double)(signed int)time_;
+            *(float *)&p->x += (double)(rand() % 5 - 2) * v7 / 16.0f;
+            *(float *)&p->y += (double)(rand() % 5 - 2) * v7 / 16.0f;
+            *(float *)&p->z += (double)(rand() % 5 + 4) * v7 / 16.0f;
+          }
+          v8 = (double)(signed int)time_ / 128.0f;
+          v9 = (signed int)(time * p->field_38) / 16;
+          *(float *)&p->x += v8 * p->flt_10;
+          *(float *)&p->y += v8 * p->flt_14;
+          *(float *)&p->z += v8 * p->flt_18;
+          p->_rotation += v9;
+          v22 = 2 * p->timeToLive;
+          if ( 2 * p->timeToLive >= 255 )
+            v22 = 255;
+          v10 = (double)v22 * 0.0039215689;
+          p->uLightColor = (uint)floorf(p->b + 0.5) |
+                           ((uint)floorf(p->g + 0.5) << 8) |
+                           ((uint)floorf(p->r + 0.5) << 16);
+          if ( i < v19 )
+            v19 = i;
+          if ( i > v20 )
+            v20 = i;
+        }
+  }
+
+  uEndParticle = v20;
+  uStartParticle = v19;
+}
+
+//----- (0048AE74) --------------------------------------------------------
+bool ParticleEngine::ViewProject_TrueIfStillVisible(unsigned int uParticleID)
+{
+  Particle *pParticle; // esi@1
+  double v56; // ST28_8@2
+  float v4; // eax@4
+  double v5; // ST34_8@4
+  signed __int64 v6; // qtt@4
+  double v7; // st7@4
+  float v8; // ST18_4@4
+  int v9; // ecx@4
+  int v10; // eax@4
+  double v11; // ST44_8@7
+  double v12; // ST4C_8@7
+  double v13; // ST4C_8@7
+  int v14; // ecx@7
+  signed __int64 v15; // qtt@7
+  int v16; // eax@7
+  int v17; // edx@7
+  float v18; // edx@7
+  int v19; // eax@7
+  int v20; // edx@7
+  int v21; // ST50_4@8
+  int v22; // ebx@8
+  int v23; // ecx@10
+  int v24; // edi@10
+  double v25; // ST44_8@12
+  double v26; // ST4C_8@12
+  int v27; // edi@12
+  int v28; // ST40_4@12
+  int v29; // ecx@12
+  signed __int64 v30; // qtt@12
+  int v31; // eax@12
+  int v32; // edx@12
+  float v33; // edx@12
+  int v34; // eax@12
+  int v35; // ecx@12
+  int v36; // ST38_4@13
+  int v37; // ST30_4@15
+  int v38; // eax@16
+  signed __int64 v40; // qtt@18
+  int v41; // eax@18
+  int v42; // ecx@18
+  int v43; // eax@18
+  unsigned __int64 v44; // qax@18
+  double v45; // st7@18
+  int v46; // ecx@18
+  float v47; // ST18_4@18
+  unsigned __int64 v48; // qax@18
+  double y_int_; // [sp+10h] [bp-40h]@2
+  int a2; // [sp+18h] [bp-38h]@10
+  int x_int; // [sp+20h] [bp-30h]@2
+  double z_int_; // [sp+24h] [bp-2Ch]@2
+  int z_int_4; // [sp+28h] [bp-28h]@8
+  int z; // [sp+3Ch] [bp-14h]@3
+  double a5; // [sp+40h] [bp-10h]@4
+  int a6; // [sp+48h] [bp-8h]@4
+  int y; // [sp+4Ch] [bp-4h]@3
+
+  pParticle = &this->pParticles[uParticleID];
+  if ( !pParticle->uType )
+    return 0;
+  uParticleID = LODWORD(pParticle->x);
+  v56 = *(float *)&uParticleID + 6.7553994e15;
+  x_int = LODWORD(v56);
+  uParticleID = LODWORD(pParticle->y);
+  y_int_ = *(float *)&uParticleID + 6.7553994e15;
+  uParticleID = LODWORD(pParticle->z);
+  z_int_ = *(float *)&uParticleID + 6.7553994e15;
+  if ( !pRenderer->pRenderD3D )
+  {
+    if ( pBLVRenderParams->sPartyRotX )
+    {
+      if ( BYTE1(pParticle->uType) & 2 )
+      {
+        v11 = pParticle->_x + 6.7553994e15;
+        uParticleID = (LODWORD(v11) - pBLVRenderParams->vPartyPos.x) << 16;
+        v12 = pParticle->_y + 6.7553994e15;
+        y = (LODWORD(v12) - pBLVRenderParams->vPartyPos.y) << 16;
+        z = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+        HIDWORD(a5) = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                    - z;
+        a6 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+        v13 = pParticle->_z + 6.7553994e15;
+        uParticleID = (LODWORD(v13) - pBLVRenderParams->vPartyPos.z) << 16;
+        z = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
+          - ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+        v14 = z;
+        HIDWORD(v13) = (unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+        HIDWORD(a5) = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16;
+        LODWORD(v15) = pBLVRenderParams->field_40 << 16;
+        HIDWORD(v15) = pBLVRenderParams->field_40 >> 16;
+        v16 = v15 / z;
+        v17 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+        pParticle->field_58 = v16;
+        uParticleID = (unsigned __int64)(v16 * (signed __int64)(a6 + v17)) >> 16;
+        LODWORD(v18) = pBLVRenderParams->uViewportCenterX
+                     - ((signed int)((unsigned __int64)(v16 * (signed __int64)(a6 + v17)) >> 16) >> 16);
+        v19 = pParticle->field_58;
+        pParticle->uScreenSpaceZ = v18;
+        uParticleID = (unsigned __int64)(v19 * (signed __int64)(HIDWORD(v13) + HIDWORD(a5))) >> 16;
+        v20 = pBLVRenderParams->uViewportCenterY
+            - ((signed int)((unsigned __int64)(v19 * (signed __int64)(HIDWORD(v13) + HIDWORD(a5))) >> 16) >> 16);
+        pParticle->sZValue2 = v14;
+        pParticle->uScreenSpaceW = v20;
+      }
+      uParticleID = (x_int - pBLVRenderParams->vPartyPos.x) << 16;
+      y = (LODWORD(y_int_) - pBLVRenderParams->vPartyPos.y) << 16;
+      HIDWORD(a5) = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                  - ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+      a6 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+      HIDWORD(z_int_) = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+      uParticleID = (LODWORD(z_int_) - pBLVRenderParams->vPartyPos.z) << 16;
+      v21 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+      v22 = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v21;
+      z = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v21;
+      if ( v22 < (signed int)0x40000u || v22 > (signed int)0x1F400000u )
+        return 0;
+      v23 = a6 + z_int_4;
+      a2 = a6 + z_int_4;
+      v24 = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
+          + ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+    }
+    else
+    {
+      if ( BYTE1(pParticle->uType) & 2 )
+      {
+        v25 = pParticle->_x + 6.7553994e15;
+        uParticleID = (LODWORD(v25) - pBLVRenderParams->vPartyPos.x) << 16;
+        v26 = pParticle->_y + 6.7553994e15;
+        y = (LODWORD(v26) - pBLVRenderParams->vPartyPos.y) << 16;
+        HIDWORD(v25) = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+        v27 = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+            - HIDWORD(v25);
+        z = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+          - HIDWORD(v25);
+        v28 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+        a5 = pParticle->_z + 6.7553994e15;
+        v29 = (LODWORD(a5) - pBLVRenderParams->vPartyPos.z) << 16;
+        LODWORD(v30) = pBLVRenderParams->field_40 << 16;
+        HIDWORD(v30) = pBLVRenderParams->field_40 >> 16;
+        v31 = v30 / z;
+        v32 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+        pParticle->field_58 = v31;
+        uParticleID = (unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16;
+        LODWORD(v33) = pBLVRenderParams->uViewportCenterX
+                     - ((signed int)((unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16) >> 16);
+        v34 = pParticle->field_58;
+        pParticle->uScreenSpaceZ = v33;
+        v35 = pBLVRenderParams->uViewportCenterY
+            - ((signed int)((unsigned __int64)(v34 * (signed __int64)v29) >> 16) >> 16);
+        pParticle->sZValue2 = v27;
+        pParticle->uScreenSpaceW = v35;
+      }
+      uParticleID = (x_int - pBLVRenderParams->vPartyPos.x) << 16;
+      y = (LODWORD(y_int_) - pBLVRenderParams->vPartyPos.y) << 16;
+      v36 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+      v22 = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v36;
+      z = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v36;
+      if ( v22 < 262144 || v22 > 524288000 )
+        return 0;
+      v37 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+      uParticleID = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+      v23 = v37 + ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+      a2 = v37 + ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+      v24 = (LODWORD(z_int_) - pBLVRenderParams->vPartyPos.z) << 16;
+    }
+    uParticleID = abs(v23);
+    v38 = abs(v22);
+    if ( v38 >= (signed int)uParticleID )
+    {
+      LODWORD(v40) = pBLVRenderParams->field_40 << 16;
+      HIDWORD(v40) = pBLVRenderParams->field_40 >> 16;
+      v41 = v40 / z;
+      pParticle->field_58 = v41;
+      uParticleID = (unsigned __int64)(v41 * (signed __int64)a2) >> 16;
+      v42 = pBLVRenderParams->uViewportCenterX - ((signed int)((unsigned __int64)(v41 * (signed __int64)a2) >> 16) >> 16);
+      v43 = pParticle->field_58;
+      pParticle->uScreenSpaceX = v42;
+      v44 = v43 * (signed __int64)v24;
+      uParticleID = v44 >> 16;
+      v45 = pParticle->flt_28;
+      LODWORD(v44) = (signed int)(v44 >> 16) >> 16;
+      v46 = pBLVRenderParams->uViewportCenterY - v44;
+      pParticle->uScreenSpaceY = pBLVRenderParams->uViewportCenterY - v44;
+      v47 = v45;
+      v48 = _48B561_mess_with_scaling_along_z(/*v46, */v47) * (signed __int64)pParticle->field_58;
+      uParticleID = v48 >> 16;
+      pParticle->field_58 = v48 >> 16;
+      v10 = z;
+      goto LABEL_19;
+    }
+    return 0;
+  }
+  if ( !pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(
+          x_int,
+          SLODWORD(y_int_),
+          COERCE_UNSIGNED_INT64(*(float *)&uParticleID + 6.7553994e15),
+          (signed int *)&uParticleID,
+          &y,
+          &z,
+          1) )
+    return 0;
+  pGame->pIndoorCameraD3D->Project(uParticleID, y, z, (int *)&a5 + 1, &a6);
+  pParticle->flt_5C = pGame->pIndoorCameraD3D->fov_x;
+  v4 = pParticle->flt_5C;
+  pParticle->flt_60 = pGame->pIndoorCameraD3D->fov_y;
+  v5 = v4 + 6.7553994e15;
+  LODWORD(v6) = 0;
+  HIDWORD(v6) = SLOWORD(v5);
+  v7 = pParticle->flt_28;
+  pParticle->field_58 = v6 / (signed int)uParticleID;
+  v8 = v7;
+  pParticle->uScreenSpaceX = HIDWORD(a5);
+  pParticle->uScreenSpaceY = a6;
+  pParticle->field_58 = (unsigned __int64)(_48B561_mess_with_scaling_along_z(/*v9, */v8) * (signed __int64)pParticle->field_58) >> 16;
+  v10 = uParticleID;
+LABEL_19:
+  pParticle->sZValue = v10;
+  return 1;
+}
+
+
+
+
+//----- (0048B5B3) --------------------------------------------------------
+bool ParticleEngine::_48B5B3(unsigned int uID)
+{
+  ParticleEngine *v2; // ST18_4@1
+  int v3; // ebx@1
+  int v4; // edi@1
+  int v5; // ecx@1
+  Particle *v6; // esi@1
+  double v7; // ST14_8@2
+  double v8; // ST34_8@4
+  double v9; // ST3C_8@4
+  int v10; // ST50_4@4
+  int v11; // ST44_4@4
+  double v12; // ST48_8@4
+  signed __int64 v13; // qtt@4
+  int v14; // eax@4
+  int v15; // ST28_4@4
+  int v16; // edi@6
+  int v17; // eax@6
+  double v18; // ST2C_8@8
+  double v19; // ST34_8@8
+  int v20; // ST50_4@8
+  double v21; // ST34_8@8
+  signed __int64 v22; // qtt@8
+  int v23; // eax@8
+  int v24; // ST28_4@8
+  int v25; // edx@8
+  int v26; // edx@9
+  int v27; // eax@9
+  int v28; // ebx@12
+  signed __int64 v29; // qtt@13
+  int v30; // eax@13
+  int v31; // ST1C_4@13
+  double v32; // st7@13
+  signed int v33; // eax@13
+  int v34; // ecx@13
+  float v35; // ST04_4@13
+  int v36; // eax@13
+  int v37; // esi@15
+  double v39; // [sp+10h] [bp-40h]@2
+  int v40; // [sp+14h] [bp-3Ch]@12
+  int v41; // [sp+1Ch] [bp-34h]@2
+  double v42; // [sp+20h] [bp-30h]@2
+  int v43; // [sp+24h] [bp-2Ch]@5
+  int v44; // [sp+2Ch] [bp-24h]@1
+  int v45; // [sp+40h] [bp-10h]@5
+  int X_4; // [sp+48h] [bp-8h]@5
+  int v47; // [sp+4Ch] [bp-4h]@5
+  int v48; // [sp+4Ch] [bp-4h]@9
+  int uIDc; // [sp+58h] [bp+8h]@4
+  int uIDd; // [sp+58h] [bp+8h]@4
+  int uIDe; // [sp+58h] [bp+8h]@5
+  int uIDa; // [sp+58h] [bp+8h]@5
+  int uIDf; // [sp+58h] [bp+8h]@8
+  int uIDb; // [sp+58h] [bp+8h]@9
+
+  v2 = this;
+  v3 = stru_5C6E00->SinCos(pIndoorCamera->sRotationX);
+  v44 = stru_5C6E00->SinCos(pIndoorCamera->sRotationX - stru_5C6E00->uIntegerHalfPi);
+  v4 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY);
+  v5 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY - stru_5C6E00->uIntegerHalfPi);
+  v6 = &v2->pParticles[uID];
+  if ( v6->uType )
+  {
+    v7 = v6->x + 6.7553994e15;
+    v41 = LODWORD(v7);
+    v39 = v6->y + 6.7553994e15;
+    v42 = v6->z + 6.7553994e15;
+    if ( v3 )
+    {
+      if ( BYTE1(v6->uType) & 2 )
+      {
+        v8 = v6->_x + 6.7553994e15;
+        uIDc = (LODWORD(v8) - pIndoorCamera->pos.x) << 16;
+        v9 = v6->_y + 6.7553994e15;
+        v10 = (LODWORD(v9) - pIndoorCamera->pos.y) << 16;
+        v11 = ((unsigned __int64)(uIDc * (signed __int64)v4) >> 16)
+            + ((unsigned __int64)(v10 * (signed __int64)v5) >> 16);
+        HIDWORD(v8) = (unsigned __int64)(uIDc * (signed __int64)v5) >> 16;
+        v12 = v6->_z + 6.7553994e15;
+        uIDd = (LODWORD(v12) - pIndoorCamera->pos.z) << 16;
+        HIDWORD(v12) = ((unsigned __int64)(v11 * (signed __int64)v3) >> 16)
+                     + ((unsigned __int64)(uIDd * (signed __int64)v44) >> 16);
+        LODWORD(v13) = 0;
+        HIDWORD(v13) = SLOWORD(pOutdoorCamera->int_fov_rad);
+        v14 = v13 / SHIDWORD(v12);
+        v6->field_58 = v14;
+        v15 = v6->field_58;
+        v6->uScreenSpaceX = pViewport->uScreenCenterX
+                          - ((signed int)((unsigned __int64)(v14
+                                                           * (signed __int64)(signed int)(((unsigned __int64)(v10 * (signed __int64)v4) >> 16)
+                                                                                        - HIDWORD(v8))) >> 16) >> 16);
+        v6->uScreenSpaceY = pViewport->uScreenCenterY
+                          - ((signed int)((unsigned __int64)(v15
+                                                           * (signed __int64)(signed int)(((unsigned __int64)(uIDd * (signed __int64)v3) >> 16)
+                                                                                        - ((unsigned __int64)(v11 * (signed __int64)v44) >> 16))) >> 16) >> 16);
+        v6->sZValue = HIDWORD(v12);
+      }
+      uIDe = (v41 - pIndoorCamera->pos.x) << 16;
+      v47 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
+      v45 = ((unsigned __int64)(uIDe * (signed __int64)v4) >> 16) + ((unsigned __int64)(v47 * (signed __int64)v5) >> 16);
+      HIDWORD(v42) = (unsigned __int64)(uIDe * (signed __int64)v5) >> 16;
+      uIDa = (LODWORD(v42) - pIndoorCamera->pos.z) << 16;
+      X_4 = ((unsigned __int64)(uIDa * (signed __int64)v44) >> 16)
+          + ((unsigned __int64)(v45 * (signed __int64)v3) >> 16);
+      if ( X_4 < 262144 )
+        return 0;
+      v16 = ((unsigned __int64)(v47 * (signed __int64)v4) >> 16) - v43;
+      v17 = ((unsigned __int64)(uIDa * (signed __int64)v3) >> 16)
+          - ((unsigned __int64)(v45 * (signed __int64)v44) >> 16);
+    }
+    else
+    {
+      if ( BYTE1(v6->uType) & 2 )
+      {
+        v18 = v6->_x + 6.7553994e15;
+        uIDf = (LODWORD(v18) - pIndoorCamera->pos.x) << 16;
+        v19 = v6->_y + 6.7553994e15;
+        v20 = (LODWORD(v19) - pIndoorCamera->pos.y) << 16;
+        v21 = v6->_z + 6.7553994e15;
+        LODWORD(v22) = 0;
+        HIDWORD(v22) = SLOWORD(pOutdoorCamera->int_fov_rad);
+        v23 = v22
+            / (signed int)(((unsigned __int64)(v20 * (signed __int64)v5) >> 16)
+                         + ((unsigned __int64)(uIDf * (signed __int64)v4) >> 16));
+        v6->field_58 = v23;
+        v24 = v6->field_58;
+        v6->uScreenSpaceX = pViewport->uScreenCenterX
+                          - ((signed int)((unsigned __int64)(v23
+                                                           * (signed __int64)(signed int)(((unsigned __int64)(v20 * (signed __int64)v4) >> 16)
+                                                                                        - ((unsigned __int64)(uIDf * (signed __int64)v5) >> 16))) >> 16) >> 16);
+        v25 = pViewport->uScreenCenterY
+            - ((signed int)((unsigned __int64)(v24 * (signed __int64)SLODWORD(v21)) >> 16) >> 16);
+        v6->sZValue = ((unsigned __int64)(v20 * (signed __int64)v5) >> 16)
+                     + ((unsigned __int64)(uIDf * (signed __int64)v4) >> 16);
+        v6->uScreenSpaceY = v25;
+      }
+      uIDb = (v41 - pIndoorCamera->pos.x) << 16;
+      v48 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
+      v26 = (unsigned __int64)(v48 * (signed __int64)v5) >> 16;
+      v27 = v26 + ((unsigned __int64)(uIDb * (signed __int64)v4) >> 16);
+      X_4 = v26 + ((unsigned __int64)(uIDb * (signed __int64)v4) >> 16);
+      if ( v27 < 262144 || v27 > (pOutdoorCamera->uPickDepth - 1000) << 16 )
+        return 0;
+      v17 = LODWORD(v42);
+      v16 = ((unsigned __int64)(v48 * (signed __int64)v4) >> 16) - ((unsigned __int64)(uIDb * (signed __int64)v5) >> 16);
+    }
+    v40 = v17;
+    v28 = abs(v16);
+    if ( abs(X_4) >= v28 )
+    {
+      LODWORD(v29) = 0;
+      HIDWORD(v29) = SLOWORD(pOutdoorCamera->int_fov_rad);
+      v30 = v29 / X_4;
+      v6->field_58 = v30;
+      v31 = v6->field_58;
+      v6->uScreenSpaceX = pViewport->uScreenCenterX
+                        - ((signed int)((unsigned __int64)(v30 * (signed __int64)v16) >> 16) >> 16);
+      v32 = v6->flt_28;
+      v33 = (signed int)((unsigned __int64)(v31 * (signed __int64)v40) >> 16) >> 16;
+      v34 = pViewport->uScreenCenterY - v33;
+      v6->uScreenSpaceY = pViewport->uScreenCenterY - v33;
+      v35 = v32;
+      v6->field_58 = (unsigned __int64)(_48B561_mess_with_scaling_along_z(/*v34, */v35) * (signed __int64)v6->field_58) >> 16;
+      v6->sZValue = X_4;
+      v36 = v6->uScreenSpaceX;
+      if ( v36 >= (signed int)pViewport->uViewportX )
+      {
+        if ( v36 < (signed int)pViewport->uViewportZ )
+        {
+          v37 = v6->uScreenSpaceY;
+          if ( v37 >= (signed int)pViewport->uViewportY )
+          {
+            if ( v37 < (signed int)pViewport->uViewportW )
+              return 1;
+          }
+        }
+      }
+    }
+  }
+  return 0;
+}
+
+//----- (0048BBA6) --------------------------------------------------------
+void ParticleEngine::DrawParticles_BLV()
+{
+  int v11; // eax@18
+  int v12; // ecx@20
+  int v13; // edx@20
+  Particle *v14; // eax@28
+  RenderBillboardTransform_local0 v15; // [sp+Ch] [bp-58h]@1
+
+  v15.uParentBillboardID = -1;
+
+  for (uint i = uStartParticle; i < uEndParticle; ++i)
+  {
+    auto p = pParticles + i;
+
+    if (!p->uType)
+      continue;
+
+    if (!ViewProject_TrueIfStillVisible(i))
+      continue;
+
+    if (p->uScreenSpaceX >= pBLVRenderParams->uViewportX &&
+        p->uScreenSpaceX < pBLVRenderParams->uViewportZ &&
+        p->uScreenSpaceY >= pBLVRenderParams->uViewportY &&
+        p->uScreenSpaceY < pBLVRenderParams->uViewportW)
+    {
+      if (pRenderer->pRenderD3D)
+      {
+        if (p->uType & 0x0100)
+        {
+          v14 = &pParticles[i];
+          v15.field_10 = v14->field_58 / 4;
+          v15.field_14 = v14->field_58 / 4;
+          v15.uScreenSpaceX = v14->uScreenSpaceX;
+          v15.uScreenSpaceY = v14->uScreenSpaceY;
+          v15.sZValue = v14->sZValue;
+          pRenderer->MakeParticleBillboardAndPush_BLV(&v15, 0, v14->uLightColor, v14->_rotation);
+          return;
+        }
+        if (p->uType & 0x0200)
+        {
+          if (pLines.uNumLines < 100)
+          {
+            pLines.pLineVertices[2 * pLines.uNumLines].pos.x = p->uScreenSpaceX;
+            pLines.pLineVertices[2 * pLines.uNumLines].pos.y = p->uScreenSpaceY;
+            pLines.pLineVertices[2 * pLines.uNumLines].pos.z = 1.0 - 1.0 / ((short)p->sZValue * 0.061758894);
+            pLines.pLineVertices[2 * pLines.uNumLines].rhw = 1.0;
+            pLines.pLineVertices[2 * pLines.uNumLines].diffuse = p->uLightColor;
+            pLines.pLineVertices[2 * pLines.uNumLines].specular = 0;
+            pLines.pLineVertices[2 * pLines.uNumLines].texcoord.x = 0.0;
+            pLines.pLineVertices[2 * pLines.uNumLines].texcoord.y = 0.0;
+
+            pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.x = p->uScreenSpaceZ;
+            pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.y = p->uScreenSpaceW;
+            pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.z = 1.0 - 1.0 / ((short)p->sZValue2 * 0.061758894);
+            pLines.pLineVertices[2 * pLines.uNumLines + 1].rhw = 1.0;
+            pLines.pLineVertices[2 * pLines.uNumLines + 1].diffuse = p->uLightColor;
+            pLines.pLineVertices[2 * pLines.uNumLines + 1].specular = 0;
+            pLines.pLineVertices[2 * pLines.uNumLines + 1].texcoord.x = 0.0;
+            pLines.pLineVertices[2 * pLines.uNumLines++ + 1].texcoord.y = 0.0;
+          }
+        }
+        if (p->uType & 0x0400)
+        {
+          v15.field_10 = p->field_58;
+          v15.field_14 = p->field_58;
+          v15.uScreenSpaceX = p->uScreenSpaceX;
+          v15.uScreenSpaceY = p->uScreenSpaceY;
+          v15.sZValue = p->sZValue;
+          pRenderer->MakeParticleBillboardAndPush_BLV(&v15,
+                        pBitmaps_LOD->pHardwareTextures[p->uTextureID],
+                        v14->uLightColor,
+                        p->_rotation);
+        }
+        if (p->uType & 0x0800)
+        {
+          v15.field_10 = p->field_58;
+          v15.field_14 = p->field_58;
+          v15.uScreenSpaceX = p->uScreenSpaceX;
+          v15.uScreenSpaceY = p->uScreenSpaceY;
+          v15.sZValue = p->sZValue;
+          pRenderer->MakeParticleBillboardAndPush_BLV(&v15,
+                        pSprites_LOD->pHardwareSprites[p->uTextureID].pTexture,
+                        v14->uLightColor,
+                        p->_rotation);
+        }
+      }
+      else
+      {
+                    v11 = 13 * p->field_58 >> 16;
+                     if ( v11 > 30 )
+                       v11 = 30;
+                    v12 = p->uScreenSpaceY - v11;
+                    v13 = p->uScreenSpaceX - (v11 >> 1);
+                     if ( v13 + v11 < (signed int)pViewport->uViewportX
+                       || v13 >= (signed int)pViewport->uViewportZ
+                       || v12 + v11 < (signed int)pViewport->uViewportY
+                       || v12 >= (signed int)pViewport->uViewportW )
+                     {
+                      ;
+                     }
+                     else
+                     {
+                      pRenderer->MakeParticleBillboardAndPush_BLV_Software(v13, v12, p->sZValue, p->uLightColor, v11);
+                     }
+      }
+    }
+  }
+}
+
+//----- (0048BEEF) --------------------------------------------------------
+void ParticleEngine::DrawParticles_ODM()
+{
+  ParticleEngine *v1; // esi@1
+  int v2; // eax@1
+  unsigned __int8 v3; // zf@1
+  char v4; // sf@1
+  unsigned __int8 v5; // of@1
+  char *v7; // edi@2
+  int v8; // eax@6
+  signed int v9; // eax@8
+  int v10; // eax@14
+  int v11; // ecx@16
+  int v12; // edx@16
+  Particle *v13; // eax@24
+  RenderBillboardTransform_local0 v14; // [sp+Ch] [bp-58h]@1
+  int v15; // [sp+5Ch] [bp-8h]@9
+  int v16; // [sp+60h] [bp-4h]@1
+
+  v14.uParentBillboardID = -1;
+  v1 = this;
+  v2 = this->uStartParticle;
+  v5 = __OFSUB__(v2, this->uEndParticle);
+  v3 = v2 == this->uEndParticle;
+  v4 = v2 - this->uEndParticle < 0;
+  v16 = this->uStartParticle;
+  if ( (unsigned __int8)(v4 ^ v5) | v3 )
+  {
+    v7 = (char *)&this->pParticles[v2].sZValue + 2;
+    do
+    {
+      if ( *(int *)(v7 - 82) && v1->_48B5B3(v2) )
+      {
+        if ( pRenderer->pRenderD3D )
+        {
+          v8 = *(int *)(v7 - 82);
+          if ( BYTE1(v8) & 1 )
+          {
+            v13 = &v1->pParticles[v16];
+            v14.field_10 = v13->field_58 >> 2;
+            v14.field_14 = v13->field_58 >> 2;
+            v14.uScreenSpaceX = v13->uScreenSpaceX;
+            v14.uScreenSpaceY = v13->uScreenSpaceY;
+            v14.sZValue = v13->sZValue;
+            pRenderer->MakeParticleBillboardAndPush_ODM(
+              &v14,
+              0,
+              v13->uLightColor,
+              v13->_rotation);
+            return;
+          }
+          if ( BYTE1(v8) & 2 )
+          {
+            v9 = v1->pLines.uNumLines;
+            if ( v9 < 100 )
+            {
+              v1->pLines.pLineVertices[2 * v9].pos.x = (double)*(signed int *)(v7 - 18);
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].pos.y = (double)*(signed int *)(v7 - 14);
+              v15 = *(short *)v7;
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].pos.z = 1.0
+                                                                       - 1.0
+                                                                       / ((double)v15
+                                                                        * 1000.0
+                                                                        / (double)pOutdoorCamera->shading_dist_mist);
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].rhw = 1.0;
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].diffuse = *(int *)(v7 + 18);
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].specular = 0;
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].texcoord.x = 0.0;
+              *((float *)&v1->pParticles[0].uType + 16 * (v1->pLines.uNumLines + 813)) = 0.0;
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.x = (double)*(signed int *)(v7 - 10);
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.y = (double)*(signed int *)(v7 - 6);
+              v15 = *(short *)v7;
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.z = 1.0
+                                                                           - 1.0
+                                                                           / ((double)v15
+                                                                            * 1000.0
+                                                                            / (double)pOutdoorCamera->shading_dist_mist);
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].rhw = 1.0;
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].diffuse = *(int *)(v7 + 18);
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].specular = 0;
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].texcoord.x = 0.0;
+              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines++ + 1].texcoord.y = 0.0;
+            }
+          }
+          if ( *(v7 - 81) & 4 )
+          {
+            v14.field_10 = *(int *)(v7 + 6);
+            v14.field_14 = *(int *)(v7 + 6);
+            v14.uScreenSpaceX = *(int *)(v7 - 18);
+            v14.uScreenSpaceY = *(int *)(v7 - 14);
+            v14.sZValue = *(int *)(v7 - 2);
+            pRenderer->MakeParticleBillboardAndPush_ODM(
+              &v14,
+              pBitmaps_LOD->pHardwareTextures[*(int *)(v7 - 46)],
+              *(int *)(v7 + 18),
+              *(int *)(v7 - 22));
+          }
+          if ( *(v7 - 81) & 8 )
+          {
+            v14.field_10 = *(int *)(v7 + 6);
+            v14.field_14 = *(int *)(v7 + 6);
+            v14.uScreenSpaceX = *(int *)(v7 - 18);
+            v14.uScreenSpaceY = *(int *)(v7 - 14);
+            v14.sZValue = *(int *)(v7 - 2);
+            pRenderer->MakeParticleBillboardAndPush_ODM(
+              &v14,
+              pSprites_LOD->pHardwareSprites[*(int *)(v7 - 46)].pTexture,
+              *(int *)(v7 + 18),
+              *(int *)(v7 - 22));
+          }
+        }
+        else
+        {
+          v10 = 13 * *(int *)(v7 + 6) >> 16;
+          if ( v10 > 30 )
+            v10 = 30;
+          v11 = *(int *)(v7 - 18) - (v10 >> 1);
+          v12 = *(int *)(v7 - 14) - v10;
+          if ( v11 + v10 < (signed int)pViewport->uViewportX
+            || v11 >= (signed int)pViewport->uViewportZ
+            || *(int *)(v7 - 14) < (signed int)pViewport->uViewportY
+            || v12 >= (signed int)pViewport->uViewportW )
+          {
+            ;
+          }
+          else
+          {
+            pRenderer->MakeParticleBillboardAndPush_BLV_Software(v11, v12, *(int *)(v7 - 2), *(int *)(v7 + 18), v10);
+          }
+        }
+      }
+      v7 += 104;
+      v2 = v16 + 1;
+      v5 = __OFSUB__(v16 + 1, v1->uEndParticle);
+      v3 = v16 + 1 == v1->uEndParticle;
+      v4 = v16++ + 1 - v1->uEndParticle < 0;
+    }
+    while ( (unsigned __int8)(v4 ^ v5) | v3 );
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParticleEngine.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,112 @@
+#pragma once
+#include "Render.h"
+
+
+
+/*  305 */
+#pragma pack(push, 1)
+struct Particle_
+{
+  int bFree;
+  float x;
+  float y;
+  float z;
+  float flt_10;
+  float flt_14;
+  float flt_18;
+  unsigned int uDiffuse;
+  int timeToLive;
+  unsigned int uTextureID;
+  float flt_28;
+  int field_2C;
+  int field_30;
+  int field_34;
+  int field_38[12];
+};
+#pragma pack(pop)
+
+
+/*  109 */
+#pragma pack(push, 1)
+struct Particle
+{
+  int uType; // 0x0000: empty
+             // 0x0100: color plane
+             // 0x0200: line
+             // 0x0400: bitmap plane
+             // 0x0800: sprite plane
+  float x;
+  float y;
+  float z;
+  float flt_10;
+  float flt_14;
+  float flt_18;
+  union
+  {
+    struct
+    {
+      unsigned char r, g, b, a;
+    };
+    unsigned int uParticleColor;
+  };
+  int timeToLive;
+  unsigned int uTextureID;
+  float flt_28;
+  float _x;
+  float _y;
+  float _z;
+  int field_38;
+  int _rotation;
+  int uScreenSpaceX;
+  int uScreenSpaceY;
+  int uScreenSpaceZ;  // line end x
+  int uScreenSpaceW;  // line end y
+  int sZValue;
+  int sZValue2;  // line end z
+  int field_58;
+  float flt_5C;
+  float flt_60;
+  int uLightColor;
+};
+#pragma pack(pop)
+
+
+
+/*  111 */
+#pragma pack(push, 1)
+struct stru2_LineList
+{
+  unsigned int uNumLines;
+  RenderVertexD3D3 pLineVertices[48];
+  char field_604[60];
+};
+#pragma pack(pop)
+
+
+
+
+
+/*  110 */
+#pragma pack(push, 1)
+struct ParticleEngine
+{
+  ParticleEngine();
+
+  void ResetParticles();
+  void AddParticle(Particle_ *a2);
+  void Draw();
+  void   UpdateParticles();
+  bool ViewProject_TrueIfStillVisible(unsigned int uParticleID);
+  bool _48B5B3(unsigned int uID);
+  void DrawParticles_BLV();
+  void DrawParticles_ODM();
+
+  Particle pParticles[500];
+  stru2_LineList pLines;
+  char field_D160[4800];
+  float field_E420;
+  int uStartParticle;
+  int uEndParticle;
+  int uTimeElapsed;
+};
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Party.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1220 @@
+#include "Party.h"
+#include "MapInfo.h"
+#include "Time.h"
+#include "AudioPlayer.h"
+#include "IconFrameTable.h"
+#include "Mouse.h"
+#include "PlayerFrameTable.h"
+#include "TurnEngine.h"
+#include "stru279.h"
+#include "Viewport.h"
+#include "Actor.h"
+#include "GUIWindow.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+
+Party *pParty; // idb
+
+struct ActionQueue *pPartyActionQueue = new ActionQueue;
+
+
+
+
+//----- (004760C1) --------------------------------------------------------
+void ActionQueue::Add(PartyAction action)
+{
+  if (uNumActions < 30)
+    pActions[uNumActions++] = action;
+}
+
+//----- (00497FC5) --------------------------------------------------------
+bool Party::_497FC5_check_party_perception_against_level()
+{
+  int uMaxPerception; // edi@1
+  Player *v2; // esi@1
+  signed int v3; // ebx@1
+  Player *v4; // ecx@2
+  signed int v5; // eax@3
+  bool result; // eax@7
+
+  uMaxPerception = 0;
+  v2 = this->pPlayers;
+  v3 = 4;
+  do
+  {
+    if ( v2->CanAct() )
+    {
+      v5 = v2->GetPerception();
+      if ( v5 > uMaxPerception )
+        uMaxPerception = v5;
+    }
+    ++v2;
+    --v3;
+  }
+  while ( v3 );
+  if ( uLevelMapStatsID && (signed int)uLevelMapStatsID < 77 )
+    result = uMaxPerception >= 2 * pMapStats->pInfos[uLevelMapStatsID]._per;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (004936E1) --------------------------------------------------------
+void Party::SetHoldingItem(ItemGen *pItem)
+{
+  Party *v2; // esi@1
+
+  v2 = this;
+  sub_421B2C_PlaceInInventory_or_DropPickedItem();
+  memcpy(&v2->pPickedItem, pItem, sizeof(v2->pPickedItem));
+  pMouse->SetCursorBitmapFromItemID(v2->pPickedItem.uItemID);
+}
+
+//----- (0049370F) --------------------------------------------------------
+int Party::GetNextActiveCharacter()
+{
+  Party *v1; // esi@1
+  int v2; // eax@4
+  signed int v4; // ecx@6
+  char *v5; // edx@6
+  Player *v6; // eax@7
+  char *v7; // ecx@23
+  signed int v8; // esi@23
+  signed int v9; // edx@23
+  Player **v10; // edi@23
+  Player *v11; // eax@24
+  int v12; // [sp+Ch] [bp-4h]@1
+
+  v1 = this;
+  v12 = 0;
+  if ( pParty->bTurnBasedModeOn == 1 )
+  {
+    if ( pTurnEngine->field_4 != 2 || (pTurnEngine->pQueue[0].uPackedID & 7) != 4 )
+      return 0;
+    v2 = pTurnEngine->pQueue[0].uPackedID >> 3;
+    return v2 + 1;
+  }
+  v4 = 0;
+  v5 = (char *)&v1->pPlayers[0].uTimeToRecovery;
+  while ( 1 )
+  {
+    v6 = ::pPlayers[v4 + 1];
+    if ( v6->pConditions[2]
+      || v6->pConditions[12]
+      || v6->pConditions[13]
+      || v6->pConditions[14]
+      || v6->pConditions[15]
+      || v6->pConditions[16]
+      || *(short *)v5 )
+    {
+      byte_AE3368[v4] = 1;
+      goto LABEL_21;
+    }
+    if ( !byte_AE3368[v4] )
+      break;
+LABEL_21:
+    ++v4;
+    v5 += 6972;
+    if ( v4 >= 4 )
+      goto LABEL_16;
+  }
+  v12 = v4;
+  byte_AE3368[v4] = 1;
+LABEL_16:
+  if ( (unsigned __int8)(byte_AE3369 & byte_AE336A & byte_AE336B) & byte_AE3368[0] )
+    memset(byte_AE3368, 0, 4u);
+  v2 = v12;
+  if ( v12 )
+    return v2 + 1;
+  v7 = (char *)&v1->pPlayers[0].uSpeedBonus;
+  v8 = 0;
+  v9 = 1;
+  v10 = &::pPlayers[1];
+  while ( 2 )
+  {
+    v11 = *v10;
+    if ( !(*v10)->pConditions[2]
+      && !v11->pConditions[12]
+      && !v11->pConditions[13]
+      && !v11->pConditions[14]
+      && !v11->pConditions[15]
+      && !v11->pConditions[16]
+      && !*((short *)v7 + 3123) )
+    {
+      if ( v12 )
+      {
+        if ( *(short *)v7 > v8 )
+        {
+          v8 = *(short *)v7;
+          goto LABEL_35;
+        }
+      }
+      else
+      {
+        v8 = *(short *)v7;
+LABEL_35:
+        v12 = v9;
+      }
+    }
+    ++v10;
+    ++v9;
+    v7 += 6972;
+    if ( v9 - 1 < 4 )
+      continue;
+    return v12;
+  }
+}
+
+
+//----- (00493244) --------------------------------------------------------
+bool Party::HasItem(unsigned int uItemID)
+{
+  char *v2; // edx@1
+  signed int v3; // ecx@2
+  ItemGen *v4; // eax@2
+
+  v2 = (char *)pParty->pPlayers[0].pInventoryItems;
+  while ( 2 )
+  {
+    v3 = 0;
+    v4 = (ItemGen *)v2;
+    do
+    {
+      if ( v4->uItemID == uItemID )
+        return 1;
+      ++v3;
+      ++v4;
+    }
+    while ( v3 < 138 );
+    v2 += 6972;
+    if ( (signed int)v2 < (signed int)&pParty->field_777C[85] )
+      continue;
+    break;
+  }
+  return 0;
+}
+
+
+//----- (00492AD5) --------------------------------------------------------
+__int16 Party::SetFood(unsigned int uNumFood)
+{
+  __int16 result; // ax@1
+
+  pUIAnim_Food->uAnimTime = 0;
+  pParty->uNumFoodRations = uNumFood;
+  result = 8 * pIconsFrameTable->pIcons[(signed __int16)pUIAnim_Food->uIconID].uAnimLength;
+  pUIAnim_Food->uAnimLength = 8 * pIconsFrameTable->pIcons[(signed __int16)pUIAnim_Food->uIconID].uAnimLength;
+  return result;
+}
+
+//----- (00492B03) --------------------------------------------------------
+void Party::TakeFood(unsigned int uNumFood)
+{
+  if ( ((pParty->uNumFoodRations - uNumFood) & 0x80000000u) == 0 )
+    pParty->uNumFoodRations -= uNumFood;
+  else
+    pParty->uNumFoodRations = 0;
+  pUIAnim_Food->uAnimTime = 0;
+  pUIAnim_Food->uAnimLength = 8 * pIconsFrameTable->pIcons[(signed __int16)pUIAnim_Food->uIconID].uAnimLength;
+}
+
+//----- (00492B42) --------------------------------------------------------
+__int16 Party::GiveFood(unsigned int _this)
+{
+  __int16 result; // ax@1
+
+  pParty->uNumFoodRations += _this;
+  pUIAnim_Food->uAnimTime = 0;
+  result = 8 * pIconsFrameTable->pIcons[(signed __int16)pUIAnim_Food->uIconID].uAnimLength;
+  pUIAnim_Food->uAnimLength = 8 * pIconsFrameTable->pIcons[(signed __int16)pUIAnim_Food->uIconID].uAnimLength;
+  return result;
+}
+
+//----- (00492B70) --------------------------------------------------------
+void Party::SetGold(unsigned int uNumGold)
+{
+  pParty->uNumGold = uNumGold;
+  pUIAnim_Gold->uAnimTime = 0;
+  pUIAnim_Gold->uAnimLength = 8 * pIconsFrameTable->pIcons[(signed __int16)pUIAnim_Gold->uIconID].uAnimLength;
+  pAudioPlayer->PlaySound(SOUND_GoldReceived, 0, 0, -1, 0, 0, 0, 0);
+}
+
+//----- (00492BB6) --------------------------------------------------------
+void Party::TakeGold(unsigned int uNumGold)
+{
+  if ( uNumGold <= pParty->uNumGold )
+    pParty->uNumGold -= uNumGold;
+  else
+    pParty->uNumGold = 0;
+  pUIAnim_Gold->uAnimTime = 0;
+  pUIAnim_Gold->uAnimLength = 8 * pIconsFrameTable->pIcons[(signed __int16)pUIAnim_Gold->uIconID].uAnimLength;
+  pAudioPlayer->PlaySound(SOUND_GoldReceived, 0, 0, -1, 0, 0, 0, 0);
+}
+
+//----- (0049135E) --------------------------------------------------------
+unsigned int Party::GetPartyFame()
+{
+  signed int v1; // eax@1
+  char *v2; // ecx@1
+  signed int v3; // edx@1
+
+  v1 = 0;
+  v2 = (char *)&this->pPlayers[0].uExperience;
+  v3 = 4;                                       // (E exp) / 1000
+  do
+  {
+    v1 += *(int *)v2;
+    v2 += 6972;
+    --v3;
+  }
+  while ( v3 );
+  return v1 / 1000;
+}
+
+//----- (0049137D) --------------------------------------------------------
+void Party::CreateDefaultParty(char bGiveItems)
+{
+  Party *pParty; // esi@1
+  signed __int16 v3; // ax@1
+  int pResMagicBase; // ecx@1
+  Player *pCharacter; // esi@3
+  signed int uSpellBookPageCount; // edx@5
+  int pMagicSkills; // eax@5
+  int uSkillIdx; // eax@11
+  //unsigned __int8 v9; // zf@37
+  //char v10; // sf@37
+  //unsigned __int8 v11; // of@37
+  char *pAttributes; // eax@38
+  signed int v13; // ecx@38
+  int uMaxSP; // eax@42
+  unsigned int v15; // [sp-4h] [bp-44h]@14
+  unsigned int v16; // [sp-4h] [bp-44h]@26
+  int v17; // [sp+10h] [bp-30h]@1
+  int v18; // [sp+14h] [bp-2Ch]@11
+  signed int uNumPlayers; // [sp+18h] [bp-28h]@1
+  ItemGen Dst; // [sp+1Ch] [bp-24h]@10
+
+  pParty = this;
+  strcpy(this->pPlayers[0].pName, pGlobalTXT_LocalizationStrings[509]); //Zoltan
+  pParty->pPlayers[0].field_1928 = 17;
+  pParty->pPlayers[0].uFace = 17;
+  pParty->pPlayers[0].field_1924 = 17;
+  pParty->pPlayers[0].uVoiceID = 17;
+  pParty->pPlayers[0].uMight = 30;
+  pParty->pPlayers[0].uIntelligence = 5;
+  pParty->pPlayers[0].uWillpower = 5;
+  pParty->pPlayers[0].uEndurance = 13;
+  pParty->pPlayers[0].uAccuracy = 13;
+  pParty->pPlayers[0].uSpeed = 14;
+  pParty->pPlayers[0].uLuck = 7;
+  pParty->pPlayers[0].pActiveSkills[9] = 1;         // leather
+  pParty->pPlayers[0].pActiveSkills[33] = 1;        // armsmaster
+  pParty->pPlayers[0].pActiveSkills[5] = 1;         // bow
+  pParty->pPlayers[0].pActiveSkills[1] = 1;         // sword
+  pParty->pPlayers[1].field_1928 = 3;
+  pParty->pPlayers[1].uFace = 3;
+  pParty->pPlayers[1].field_1924 = 3;
+  pParty->pPlayers[1].uVoiceID = 3;
+  strcpy(pParty->pPlayers[1].pName, pGlobalTXT_LocalizationStrings[506]); //Roderic
+  pParty->pPlayers[1].uMight = 13;
+  pParty->pPlayers[1].uIntelligence = 9;
+  pParty->pPlayers[1].uWillpower = 9;
+  pParty->pPlayers[1].uEndurance = 13;
+  pParty->pPlayers[1].uAccuracy = 13;
+  pParty->pPlayers[1].uSpeed = 13;
+  pParty->pPlayers[1].uLuck = 13;
+  pParty->pPlayers[1].pActiveSkills[9] = 1;         // leather
+  pParty->pPlayers[1].pActiveSkills[34] = 1;        // stealing
+  pParty->pPlayers[1].pActiveSkills[2] = 1;         // dagger
+  pParty->pPlayers[1].pActiveSkills[29] = 1;        // disarm trap
+  pParty->pPlayers[2].field_1928 = 14;
+  pParty->pPlayers[2].uFace = 14;
+  pParty->pPlayers[2].field_1924 = 14;
+  pParty->pPlayers[2].uVoiceID = 14;
+  strcpy(pParty->pPlayers[2].pName, pGlobalTXT_LocalizationStrings[508]); // Serena
+  pParty->pPlayers[2].uMight = 12;
+  pParty->pPlayers[2].uIntelligence = 9;
+  pParty->pPlayers[2].uWillpower = 20;
+  pParty->pPlayers[2].uEndurance = 22;
+  pParty->pPlayers[2].uAccuracy = 7;
+  pParty->pPlayers[2].uSpeed = 13;
+  pParty->pPlayers[2].uLuck = 7;
+  pParty->pPlayers[2].pActiveSkills[35] = 1;        // alchemy
+  pParty->pPlayers[2].pActiveSkills[9] = 1;         // leather
+  pParty->pPlayers[2].pActiveSkills[18] = 1;        // body
+  pParty->pPlayers[2].pActiveSkills[6] = 1;         // mace
+  strcpy(pParty->pPlayers[3].pName, pGlobalTXT_LocalizationStrings[507]); // Alexis
+  v3 = 10;
+  pParty->pPlayers[3].field_1928 = 10;
+  pParty->pPlayers[3].uFace = 10;
+  pResMagicBase = (int)&pParty->pPlayers[0].sResMagicBase;
+  pParty->pPlayers[3].uEndurance = 13;
+  pParty->pPlayers[3].uAccuracy = 13;
+  pParty->pPlayers[3].uSpeed = 13;
+  pParty->pPlayers[3].field_1924 = 10;
+  pParty->pPlayers[3].uVoiceID = 10;
+  pParty->pPlayers[3].uMight = 5;
+  pParty->pPlayers[3].uIntelligence = 30;
+  pParty->pPlayers[3].uWillpower = 9;
+  pParty->pPlayers[3].uLuck = 7;
+  pParty->pPlayers[3].pActiveSkills[9] = 1;         // leather
+  pParty->pPlayers[3].pActiveSkills[13] = 1;        // air
+  pParty->pPlayers[3].pActiveSkills[12] = 1;        // fire
+  pParty->pPlayers[3].pActiveSkills[0] = 1;         // staff
+  pCharacter = &pParty->pPlayers[0];
+  //uNumPlayers = 4;
+  //while ( 1 )
+  for (uNumPlayers = 0; uNumPlayers < 4; uNumPlayers++)
+  {
+    if ( !pCharacter->uClass )
+      *(short *)pResMagicBase = v3; //player[i].pResMagicBase
+    uSpellBookPageCount = 0;
+    //pMagicSkills = pPlayers[uNumPlayers].pActiveSkills[12];// Skills
+    //while ( !*(short *)pMagicSkills )         //player[i].skillFire
+	for (int i = 0; i < 9; i++)//for Magic Book
+    {
+      //++uSpellBookPageCount;
+      //pMagicSkills++;
+      //if ( uSpellBookPageCount >= 9 )
+        //goto LABEL_10;
+	    if (pPlayers[uNumPlayers].pActiveSkills[12+i])
+			++uSpellBookPageCount;
+    }
+    pCharacter->pNumSpellBookPage = uSpellBookPageCount;
+//LABEL_10:
+    pCharacter->uExpressionTimePassed = 0;
+    Dst.Reset();
+    if ( bGiveItems )
+    {
+      pItemsTable->GenerateItem(2, 40, &Dst);
+      pCharacter->AddItem2(-1, &Dst);
+      //uSkillIdx = 0;
+      //v18 = 0;
+      //do
+	  for (uSkillIdx = 0; uSkillIdx < 36; uSkillIdx++)
+      {
+        if ( pCharacter->pActiveSkills[uSkillIdx] )
+        {
+          switch ( uSkillIdx )
+          {
+            case PLAYER_SKILL_STAFF:
+              v15 = ITEM_STAFF_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_SWORD:
+              v15 = ITEM_LONGSWORD_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_DAGGER:
+              v15 = ITEM_DAGGER_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_AXE:
+              v15 = ITEM_AXE_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_SPEAR:
+              v15 = ITEM_SPEAR_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_BOW:
+              v15 = ITEM_CROSSBOW_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_MACE:
+              v15 = ITEM_MACE_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_SHIELD:
+              v15 = ITEM_BUCKLER_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_LEATHER:
+              v15 = ITEM_LEATHER_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_CHAIN:
+              v15 = ITEM_CHAINMAIL_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_PLATE:
+              v15 = ITEM_PLATE_1;
+              pCharacter->WearItem(v15);
+              break;
+            case PLAYER_SKILL_FIRE:
+              v16 = ITEM_SPELLBOOK_FIRE_STRIKE;
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_AIR:
+              v16 = ITEM_SPELLBOOK_AIR_FEATHER_FALL;
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_WATER:
+              v16 = ITEM_SPELLBOOK_WATER_POISON_SPRAY;
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_EARTH:
+              v16 = ITEM_SPELLBOOK_EARTH_SLOW;
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_SPIRIT:
+              v16 = ITEM_SPELLBOOK_SPIRIT_BLESS;
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_MIND:
+              v16 = ITEM_SPELLBOOK_MIND_MIND_BLAST;
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_BODY:
+              v16 = ITEM_SPELLBOOK_BODY_FIRST_AID;
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_ITEM_ID:
+            case PLAYER_SKILL_REPAIR:
+            case PLAYER_SKILL_MEDITATION:
+            case PLAYER_SKILL_PERCEPTION:
+            case PLAYER_SKILL_DIPLOMACY:
+            case PLAYER_SKILL_TRAP_DISARM:
+            case PLAYER_SKILL_LEARNING:
+              pCharacter->AddItem(-1, ITEM_POTION_BOTTLE);
+              v16 = 5 * (rand() % 3 + 40);      // simple reagent
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_DODGE:
+              v16 = ITEM_BOOTS_1;
+              pCharacter->AddItem(-1, v16);
+              break;
+            case PLAYER_SKILL_UNARMED:
+              v16 = ITEM_GAUNTLETS_1;
+              pCharacter->AddItem(-1, v16);
+              break;
+            default:
+              break;
+          }
+        }
+        //uSkillIdx = v18 + 1;
+        //v11 = uSkillIdx > 36;
+        //v9 = v18 == 35;
+        //v10 = uSkillIdx - 35 < 0;
+      }
+      //while (uSkillIdx < 36);
+      pAttributes = (char *)&pCharacter->pInventoryItems[0].uAttributes;
+      //v13 = 138;
+      for (v13 = 138; v13 > 0; --v13)
+      {
+        if ( *((int *)pAttributes - 5) )
+          *(int *)pAttributes |= 1;
+        pAttributes += 36;
+        //--v13;
+      }
+      //while ( v13 );
+    }
+    pCharacter->sHealth = pCharacter->GetMaxHealth();
+    pCharacter->sMana = pCharacter->GetMaxMana();
+    pCharacter++;
+    //uNumPlayers--;
+    //if (!uNumPlayers)
+      //break;
+    pResMagicBase = (int)pCharacter;
+    v3 = 10;
+  }
+}
+
+//----- (004917CE) --------------------------------------------------------
+int Party::Reset()
+{
+  //Party *v1; // esi@1
+  //unsigned __int64 *pTimePlayed; // edi@1
+  //bool v3; // edx@1
+  //Player **v4; // eax@1
+  //Player *v5; // ecx@1
+  PLAYER_SEX pSex; // cl@3
+  PLAYER_SEX v7; // al@6
+  PLAYER_SEX v8; // al@9
+  PLAYER_SEX v9; // cl@12
+  //Player *v12; // edx@17
+  //signed int v13; // edi@18
+  SpellBuff *v14; // ebx@21
+  signed int v15; // edi@21
+
+  field_708 = 15;
+  sEyelevel = 160;
+  uFlags2 = 0;
+  uNumGold = 200;
+  uNumGoldInBank = 0;
+  uNumFoodRations = 7;
+  uAlignment = 1;
+
+  SetUserInterface(uAlignment, true);
+
+  uTimePlayed = 0x21C00u;
+  uLastRegenerationTime = 0x21C00;
+
+  bTurnBasedModeOn = false;
+
+  uActiveCharacter = 1;
+  ::pPlayers[0] = pPlayers;
+  for (uint i = 0; i < 4; ++i)
+    ::pPlayers[i + 1] = &pPlayers[i];
+
+  pPlayers[0].Reset(0);
+  pPlayers[1].Reset(4);
+  pPlayers[2].Reset(24);
+  pPlayers[3].Reset(32);
+  pPlayers[0].uFace = 17;
+  pPlayers[0].field_1924 = 17;
+  pPlayers[0].uVoiceID = 17;
+  pPlayers[0].SetInitialStats();
+ 
+  switch ( pPlayers[0].uVoiceID )
+  {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 8:
+    case 9:
+    case 12:
+    case 13:
+    case 16:
+    case 17:
+    case 20:
+    case 23:
+    default:
+      pSex = SEX_MALE;
+      break;
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 10:
+    case 11:
+    case 14:
+    case 15:
+    case 18:
+    case 19:
+    case 21:
+    case 24:
+      pSex = SEX_FEMALE;
+      break;
+  }
+  pPlayers[0].uSex = pSex;
+  pPlayers[0].RandomizeName();
+  strcpy(pPlayers[0].pName, pGlobalTXT_LocalizationStrings[509]);
+
+
+  pPlayers[1].uFace = 3;
+  pPlayers[1].field_1924 = 3;
+  pPlayers[1].uVoiceID = 3;
+  pPlayers[1].SetInitialStats();
+  v7 = SEX_MALE;
+  switch (pPlayers[1].uVoiceID)
+  {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 8:
+    case 9:
+    case 0xCu:
+    case 0xDu:
+    case 0x10u:
+    case 0x11u:
+    case 0x14u:
+    case 0x17u:
+      v7 = SEX_MALE;
+      break;
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 0xAu:
+    case 0xBu:
+    case 0xEu:
+    case 0xFu:
+    case 0x12u:
+    case 0x13u:
+    case 0x15u:
+    case 0x18u:
+      v7 = SEX_FEMALE;
+      break;
+    default:
+      break;
+  }
+  pPlayers[1].uSex = v7;
+  pPlayers[1].RandomizeName();
+  strcpy(pPlayers[1].pName, pGlobalTXT_LocalizationStrings[506]);
+  pPlayers[2].uFace = 14;
+  pPlayers[2].field_1924 = 14;
+  pPlayers[2].uVoiceID = 14;
+  pPlayers[2].SetInitialStats();
+  v8 = SEX_MALE;
+  switch (pPlayers[2].uVoiceID)
+  {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 8:
+    case 9:
+    case 0xCu:
+    case 0xDu:
+    case 0x10u:
+    case 0x11u:
+    case 0x14u:
+    case 0x17u:
+      v8 = SEX_MALE;
+      break;
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 0xAu:
+    case 0xBu:
+    case 0xEu:
+    case 0xFu:
+    case 0x12u:
+    case 0x13u:
+    case 0x15u:
+    case 0x18u:
+      v8 = SEX_FEMALE;
+      break;
+    default:
+      break;
+  }
+  pPlayers[2].uSex = v8;
+  pPlayers[2].RandomizeName();
+  strcpy(pPlayers[2].pName, pGlobalTXT_LocalizationStrings[508]);
+  pPlayers[3].uFace = 10;
+  pPlayers[3].field_1924 = 10;
+  pPlayers[3].uVoiceID = 10;
+  pPlayers[3].SetInitialStats();
+  v9 = SEX_MALE;
+  switch (pPlayers[3].uVoiceID)
+  {
+    case 0u:
+    case 1u:
+    case 2u:
+    case 3u:
+    case 8u:
+    case 9u:
+    case 0xCu:
+    case 0xDu:
+    case 0x10u:
+    case 0x11u:
+    case 0x14u:
+    case 0x17u:
+      v9 = SEX_MALE;
+      break;
+    case 4u:
+    case 5u:
+    case 6u:
+    case 7u:
+    case 0xAu:
+    case 0xBu:
+    case 0xEu:
+    case 0xFu:
+    case 0x12u:
+    case 0x13u:
+    case 0x15u:
+    case 0x18u:
+      v9 = SEX_FEMALE;
+      break;
+    default:
+      break;
+  }
+  pPlayers[3].uSex = v9;
+  pPlayers[3].RandomizeName();
+  strcpy(pPlayers[3].pName, pGlobalTXT_LocalizationStrings[507]);
+
+
+
+  for (uint i = 0; i < 4; ++i)
+  {
+    pPlayers[i].uTimeToRecovery = 0;
+    for (uint j = 0; j < 20; ++j)
+      pPlayers[i].pConditions[j] = 0;
+
+    for (uint j = 0; j < 24; ++j)
+      pPlayers[i].pPlayerBuffs[j].Reset();
+
+    pPlayers[i].uExpressionID = 1;
+    pPlayers[i].uExpressionTimePassed = 0;
+    pPlayers[i].uExpressionTimeLength = rand() % 256 + 128;
+  }
+
+  for (uint i = 1; i < 20; ++i)
+    pPartyBuffs[i].Reset();
+
+
+  pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 100;
+  uFlags = 0;
+
+  memset(_award_bits, 0, 64);
+  _449B7E_toggle_bit(_award_bits, 1, 1);
+  _449B7E_toggle_bit(_award_bits, 2, 1);
+  _449B7E_toggle_bit(_award_bits, 3, 1);
+  _449B7E_toggle_bit(_award_bits, 4, 1);
+  _449B7E_toggle_bit(_award_bits, 5, 1);
+  _449B7E_toggle_bit(_award_bits, 6, 1);
+
+
+  memcpy(pNPCStats->pNewNPCData, pNPCStats->pNPCData, 0x94BCu);
+  memcpy(pNPCStats->pGroups_copy, pNPCStats->pGroups, 0x66u);
+  pNPCStats->pNewNPCData[3].uFlags |= 0x80u;
+  _494035_timed_effects__water_walking_damage__etc();
+  pEventTimer->Pause();
+  return 0;
+}
+
+
+
+//----- (0043AD34) --------------------------------------------------------
+void Party::Yell()
+{
+  void *v0; // esi@5
+  int v1; // edi@9
+  int v2; // ebx@9
+  int v3; // eax@9
+  unsigned int v4; // [sp+8h] [bp-4h]@4
+
+  if ( (signed __int64)pParty->pPartyBuffs[11].uExpireTime > 0 )
+    pParty->pPartyBuffs[11].Reset();
+  if ( pParty->bTurnBasedModeOn != 1 )
+  {
+    v4 = 0;
+    if ( (signed int)uNumActors > 0 )
+    {
+      v0 = &pActors[0].pMonsterInfo.uMovementType;
+      do
+      {
+        if ( ((Actor *)((char *)v0 - 59))->Actor::CanAct() && *((char *)v0 + 2) != 4 && *(char *)v0 != 5 )
+        {
+          v1 = abs(*(short *)((char *)v0 + 83) - pParty->vPosition.x);
+          v2 = abs(*(short *)((char *)v0 + 85) - pParty->vPosition.y);
+          v3 = abs(*(short *)((char *)v0 + 87) - pParty->vPosition.z);
+          if ( (double)sub_4621DA(v1, v2, v3) < 512.0 )
+            Actor::_402968(v4, 4, 0, 0);
+        }
+        ++v4;
+        v0 = (char *)v0 + 836;
+      }
+      while ( (signed int)v4 < (signed int)uNumActors );
+    }
+  }
+}
+
+//----- (00491BF9) --------------------------------------------------------
+void Party::ResetPosMiscAndSpellBuffs()
+{
+  Party *v1; // esi@1
+  char *v2; // edi@1
+  SpellBuff *v3; // ebx@2
+  SpellBuff *v4; // esi@5
+  signed int v5; // edi@5
+  signed int v6; // [sp+8h] [bp-8h]@1
+  signed int v7; // [sp+Ch] [bp-4h]@2
+
+  v1 = this;
+  this->vPosition.y = 0;
+  this->vPosition.z = 0;
+  this->vPosition.x = 0;
+  this->uFallStartY = 0;
+  this->sRotationY = 0;
+  this->sRotationX = 0;
+  this->uFallSpeed = 0;
+  this->field_28 = 0;
+  this->uDefaultPartyHeight = 120;
+  this->field_14 = 37;
+  this->field_18 = 25;
+  this->uWalkSpeed = 384;
+  this->field_20_prolly_turn_speed = 90;
+  this->field_24 = 5;
+  this->field_6FC = 0;
+  this->field_708 = 15;
+  this->field_0 = 25;
+  v2 = (char *)this->pPlayers[0].pPlayerBuffs;
+  v6 = 4;
+  do
+  {
+    v3 = (SpellBuff *)v2;
+    v7 = 24;
+    do
+    {
+      v3->Reset();
+      ++v3;
+      --v7;
+    }
+    while ( v7 );
+    v2 += 6972;
+    --v6;
+  }
+  while ( v6 );
+  v4 = v1->pPartyBuffs;
+  v5 = 20;
+  do
+  {
+    v4->Reset();
+    ++v4;
+    --v5;
+  }
+  while ( v5 );
+}
+
+//----- (004909F4) --------------------------------------------------------
+void Party::_4909F4()
+{
+  char *v1; // esi@2
+  unsigned int v2; // eax@3
+  __int16 v3; // cx@5
+  int v4; // edx@27
+  signed int v5; // eax@52
+  PlayerFrame *v6; // edx@53
+  char *v7; // esi@60
+  signed int v8; // ebp@61
+  int v9; // ebx@62
+  unsigned int v10; // edi@62
+  signed int v11; // [sp+0h] [bp-4h]@2
+
+  if ( dword_A75070 != stru_51076C.field_8 )
+  {
+    dword_A75070 = stru_51076C.field_8;
+    v1 = (char *)&this->pPlayers[0].uExpressionID;
+    v11 = 4;
+    do
+    {
+      v2 = ((Player *)(v1 - 6812))->GetMajorConditionIdx();
+      if ( v2 == 18 || v2 == 17 )
+      {
+        *((short *)v1 + 1) += LOWORD(pMiscTimer->uTimeElapsed);
+        if ( *((short *)v1 + 1) >= *((short *)v1 + 2) )
+        {
+          if ( *(short *)v1 != 1 || rand() % 5 )
+          {
+            *((short *)v1 + 1) = 0;
+            *(short *)v1 = 1;
+            *((short *)v1 + 2) = rand() % 256 + 32;
+          }
+          else
+          {
+            v4 = rand() % 100;
+            if ( v4 >= 25 )
+            {
+              if ( v4 >= 31 )
+              {
+                if ( v4 >= 37 )
+                {
+                  if ( v4 >= 43 )
+                  {
+                    if ( v4 >= 46 )
+                    {
+                      if ( v4 >= 52 )
+                      {
+                        if ( v4 >= 58 )
+                        {
+                          if ( v4 >= 64 )
+                          {
+                            if ( v4 >= 70 )
+                            {
+                              if ( v4 >= 76 )
+                              {
+                                if ( v4 >= 82 )
+                                {
+                                  if ( v4 >= 88 )
+                                    *(short *)v1 = (v4 >= 94) + 29;
+                                  else
+                                    *(short *)v1 = 57;
+                                }
+                                else
+                                {
+                                  *(short *)v1 = 56;
+                                }
+                              }
+                              else
+                              {
+                                *(short *)v1 = 55;
+                              }
+                            }
+                            else
+                            {
+                              *(short *)v1 = 54;
+                            }
+                          }
+                          else
+                          {
+                            *(short *)v1 = 20;
+                          }
+                        }
+                        else
+                        {
+                          *(short *)v1 = 19;
+                        }
+                      }
+                      else
+                      {
+                        *(short *)v1 = 18;
+                      }
+                    }
+                    else
+                    {
+                      *(short *)v1 = 17;
+                    }
+                  }
+                  else
+                  {
+                    *(short *)v1 = 16;
+                  }
+                }
+                else
+                {
+                  *(short *)v1 = 15;
+                }
+              }
+              else
+              {
+                *(short *)v1 = 14;
+              }
+            }
+            else
+            {
+              *(short *)v1 = 13;
+            }
+            v5 = 0;
+            *((short *)v1 + 1) = 0;
+            if ( (signed int)pPlayerFrameTable->uNumFrames <= 0 )
+            {
+LABEL_56:
+              v5 = 0;
+            }
+            else
+            {
+              v6 = pPlayerFrameTable->pFrames;
+              while ( v6->uSequenceID != *(short *)v1 )
+              {
+                ++v5;
+                ++v6;
+                if ( v5 >= (signed int)pPlayerFrameTable->uNumFrames )
+                  goto LABEL_56;
+              }
+            }
+            *((short *)v1 + 2) = 8 * pPlayerFrameTable->pFrames[v5].uAnimLength;
+          }
+        }
+      }
+      else
+      {
+        v3 = *(short *)v1;
+        if ( *(short *)v1 != 34 && v3 != 35 && v3 != 36
+          || (signed int)(pMiscTimer->uTimeElapsed + *((short *)v1 + 1)) >= *((short *)v1 + 2) )
+        {
+          *((short *)v1 + 2) = 0;
+          *((short *)v1 + 1) = 0;
+          switch ( v2 )
+          {
+            case 0xEu:
+              *(short *)v1 = 98;
+              break;
+            case 0xFu:
+              *(short *)v1 = 12;
+              break;
+            case 0x10u:
+              *(short *)v1 = 99;
+              break;
+            case 0u:
+              *(short *)v1 = 2;
+              break;
+            case 1u:
+              *(short *)v1 = 3;
+              break;
+            case 2u:
+              *(short *)v1 = 4;
+              break;
+            case 3u:
+              *(short *)v1 = 5;
+              break;
+            case 4u:
+              *(short *)v1 = 6;
+              break;
+            case 5u:
+              *(short *)v1 = 7;
+              break;
+            case 6u:
+            case 8u:
+            case 0xAu:
+              *(short *)v1 = 8;
+              break;
+            case 7u:
+            case 9u:
+            case 0xBu:
+              *(short *)v1 = 9;
+              break;
+            case 0xCu:
+              *(short *)v1 = 10;
+              break;
+            case 0xDu:
+              *(short *)v1 = 11;
+              break;
+            default:
+              break;
+          }
+        }
+        else
+        {
+          *((short *)v1 + 1) += LOWORD(pMiscTimer->uTimeElapsed);
+        }
+      }
+      v1 += 6972;
+      --v11;
+    }
+    while ( v11 );
+    v7 = (char *)&pParty->pHirelings[0].evtb;
+    do
+    {
+      v8 = *((int *)v7 + 1);
+      if ( v8 )
+      {
+        v9 = *((int *)v7 - 1);
+        v10 = pMiscTimer->uTimeElapsed + *(int *)v7;
+        if ( (signed int)v10 >= v8 )
+        {
+          v9 = 0;
+          v8 = 0;
+          v10 = 0;
+          memset(v7 - 44, 0, 0x4Cu);
+          pParty->field_709 = 0;
+          //sub_44A56A();Ritor1: it's temporarily
+          viewparams->bRedrawGameUI = 1;
+        }
+        *(int *)v7 = v10;
+        *((int *)v7 + 1) = v8;
+        *((int *)v7 - 1) = v9;
+      }
+      v7 += 76;
+    }
+    while ( (signed int)v7 < (signed int)&pParty->field_777C[1] );
+  }
+}
+// A75070: using guessed type int dword_A75070;
+
+//----- (00490D02) --------------------------------------------------------
+void Party::RestAndHeal()
+{
+  SpellBuff *v1; // esi@1
+  Player *v2; // esi@4
+  signed int v3; // ebx@4
+  SpellBuff *v4; // edi@4
+  int v5; // eax@9
+  char v6; // zf@9
+  char *v7; // eax@10
+  signed int v8; // ecx@10
+  int v9; // eax@18
+  int v10; // eax@25
+  signed int v11; // ecx@26
+  signed int v12; // [sp-4h] [bp-1Ch]@26
+  Party *v13; // [sp+Ch] [bp-Ch]@1
+  signed int v14; // [sp+10h] [bp-8h]@10
+  signed int v15; // [sp+14h] [bp-4h]@3
+
+  v13 = this;
+  v1 = pParty->pPartyBuffs;
+  do
+  {
+    v1->Reset();
+    ++v1;
+  }
+  while ( (signed int)v1 < (signed int)pParty->pPlayers );
+  v15 = 0;
+  do
+  {
+    v2 = &pParty->pPlayers[v15];
+    v3 = 20;
+    v4 = v2->pPlayerBuffs;
+    do
+    {
+      v4->Reset();
+      ++v4;
+      --v3;
+    }
+    while ( v3 );
+    v2->Zero();
+    if ( v2->pConditions[14] || v2->pConditions[15] || v2->pConditions[16] )
+      goto LABEL_33;
+    LODWORD(v2->pConditions[13]) = 0;
+    HIDWORD(v2->pConditions[13]) = 0;
+    LODWORD(v2->pConditions[4]) = 0;
+    HIDWORD(v2->pConditions[4]) = 0;
+    LODWORD(v2->pConditions[2]) = 0;
+    HIDWORD(v2->pConditions[2]) = 0;
+    LODWORD(v2->pConditions[3]) = 0;
+    HIDWORD(v2->pConditions[3]) = 0;
+    LODWORD(v2->pConditions[1]) = 0;
+    HIDWORD(v2->pConditions[1]) = 0;
+    v2->uTimeToRecovery = 0;
+    v2->sHealth = v2->GetMaxHealth();
+    v5 = v2->GetMaxMana();
+    v6 = v2->uClass == 35;
+    v2->sMana = v5;
+    if ( v6 )
+    {
+      v14 = 0;
+      v7 = &v2->pInventoryItems[0].field_1A;
+      v8 = 138;
+      do
+      {
+        if ( *(int *)(v7 - 26) == 601 && (unsigned __int8)*v7 == v15 + 1 )
+          v14 = 1;
+        v7 += 36;
+        --v8;
+      }
+      while ( v8 );
+      if ( !v14 )
+      {
+        v2->sHealth = v2->GetMaxHealth() / 2;
+        v2->sMana = v2->GetMaxMana() / 2;
+      }
+    }
+    if ( !v2->pConditions[17] )
+    {
+      if ( v2->pConditions[10] || v2->pConditions[11] )
+      {
+        v11 = 4;
+        v12 = 4;
+      }
+      else
+      {
+        if ( !v2->pConditions[8] && !v2->pConditions[9] )
+        {
+          if ( !v2->pConditions[6] && !v2->pConditions[7] )
+            goto LABEL_30;
+          v2->sHealth /= 2;
+          v10 = v2->sMana / 2;
+          goto LABEL_29;
+        }
+        v11 = 3;
+        v12 = 3;
+      }
+      v2->sHealth /= v11;
+      v10 = v2->sMana / v12;
+LABEL_29:
+      v2->sMana = v10;
+      goto LABEL_30;
+    }
+    v9 = v2->sHealth;
+    v2->sMana = 0;
+    v2->sHealth = v9 / 2;
+LABEL_30:
+    if ( v2->pConditions[5] )
+      v2->sMana = 0;
+    _4909F4();
+LABEL_33:
+    ++v15;
+  }
+  while ( v15 < 4 );
+  pParty->field_764 = 0;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Party.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,276 @@
+#pragma once
+#include "Player.h"
+#include "NPC.h"
+#include "Spells.h"
+#include "VectorTypes.h"
+
+
+
+
+
+
+
+
+
+
+/*  355 */
+enum PARTY_FLAGS_2 : __int32
+{
+  PARTY_FLAGS_2_RUNNING = 0x2,
+};
+
+/*  347 */
+enum PARTY_BUFF_INDEX
+{
+  PARTY_BUFF_RESIST_AIR = 0x0,
+  PARTY_BUFF_RESIST_BODY = 0x1,
+  PARTY_BUFF_DAY_OF_GODS = 0x2,
+  PARTY_BUFF_DETECT_LIFE = 0x3,
+  PARTY_BUFF_RESIST_EARTH = 0x4,
+  PARTY_BUFF_FEATHER_FALL = 0x5,
+  PARTY_BUFF_RESIST_FIRE = 0x6,
+  PARTY_BUFF_FLY = 0x7,
+  PARTY_BUFF_HASTE = 0x8,
+  PARTY_BUFF_HEROISM = 0x9,
+  PARTY_BUFF_IMMOLATION = 0xA,
+  PARTY_BUFF_INVISIBILITY = 0xB,
+  PARTY_BUFF_RESIST_MIND = 0xC,
+  PARTY_BUFF_PROTECTION_FROM_MAGIC = 0xD,
+  PARTY_BUFF_SHIELD = 0xE,
+  PARTY_BUFF_STONE_SKIN = 0xF,
+  PARTY_BUFF_TORCHLIGHT = 0x10,
+  PARTY_BUFF_RESIST_WATER = 0x11,
+  PARTY_BUFF_WATER_WALK = 0x12,
+  PARTY_BUFF_WIZARD_EYE = 0x13,
+};
+
+
+
+/*  300 */
+enum PartyAction: unsigned __int32
+{
+  PARTY_INVALID = 0,
+  PARTY_TurnLeft = 0x1,
+  PARTY_TurnRight = 0x2,
+  PARTY_StrafeLeft = 0x3,
+  PARTY_StrafeRight = 0x4,
+  PARTY_WalkForward = 0x5,
+  PARTY_WalkBackward = 0x6,
+  PARTY_LookUp = 0x7,
+  PARTY_LookDown = 0x8,
+  PARTY_CenterView = 0x9,
+  PARTY_unkA = 0xA,
+  PARTY_unkB = 0xB,
+  PARTY_Jump = 0xC,
+  PARTY_FlyUp = 0xD,
+  PARTY_FlyDown = 0xE,
+  PARTY_Land = 0xF,
+  PARTY_RunForward = 0x10,
+  PARTY_RunBackward = 0x11,
+  PARTY_FastTurnLeft = 0x12,
+  PARTY_FastTurnRight = 0x13,
+
+  PARTY_dword = 0xFFFFFFFF
+};
+
+
+
+/*  135 */
+#pragma pack(push, 1)
+struct ActionQueue
+{
+  void Add(PartyAction action);
+  PartyAction Next();
+
+  unsigned int uNumActions;
+  PartyAction  pActions[30];
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+
+/*  208 */
+#pragma pack(push, 1)
+struct Party_stru0
+{
+  int field_0[20];
+  int field_50[170];
+  int _shop_ban_times[82];
+  int field_440[44];
+  int field_4F0[38];
+  char field_588[2];
+  char pIsArtifactFound[238];
+};
+#pragma pack(pop)
+
+/*  207 */
+#pragma pack(push, 1)
+struct Party
+{
+  Party():
+    uTimePlayed(0)
+  {
+    uCurrentYear = 0;
+    uCurrentMonth = 0;
+    uCurrentMonthWeek = 0;
+    uDaysPlayed = 0;
+    uCurrentHour = 0;
+    uCurrentMinute = 0;
+    uCurrentTimeSecond = 0;
+
+    field_6FC = 0;
+    field_764 = 0;
+  }
+
+  void _4909F4();
+  void RestAndHeal();
+  unsigned int GetPartyFame();
+  void CreateDefaultParty(char bGiveItems);
+  int Reset();
+  void ResetPosMiscAndSpellBuffs();
+  bool HasItem(unsigned int uItemID);
+  void SetHoldingItem(ItemGen *pItem);
+  int GetNextActiveCharacter();
+  bool _497FC5_check_party_perception_against_level();
+  bool AddItem(ItemGen *pItem);
+  void Yell();
+  
+  static void SetGold(unsigned int uNumGold);
+  static void TakeGold(unsigned int uNumGold);
+  static __int16 SetFood(unsigned int uNumFood);
+  static void TakeFood(unsigned int uNumFood);
+  static __int16 GiveFood(unsigned int _this);
+
+  inline bool WizardEyeActive()      {return pPartyBuffs[PARTY_BUFF_WIZARD_EYE].uExpireTime > 0;}
+  inline int  WizardEyeSkillLevel()  {return pPartyBuffs[PARTY_BUFF_WIZARD_EYE].uSkill;}
+  inline bool TorchlightActive()     {return pPartyBuffs[PARTY_BUFF_TORCHLIGHT].uExpireTime > 0;}
+  inline bool FlyActive()            {return pPartyBuffs[PARTY_BUFF_FLY].uExpireTime > 0;}
+  inline bool WaterWalkActive()      {return pPartyBuffs[PARTY_BUFF_WATER_WALK].uExpireTime > 0;}
+  inline bool ImmolationActive()     {return pPartyBuffs[PARTY_BUFF_IMMOLATION].uExpireTime > 0;}
+  inline bool ImmolationSkillLevel() {return pPartyBuffs[PARTY_BUFF_IMMOLATION].uSkill;}
+  inline bool FeatherFallActive()    {return pPartyBuffs[PARTY_BUFF_FEATHER_FALL].uExpireTime > 0;}
+
+
+  int field_0;
+  unsigned int uPartyHeight;
+  unsigned int uDefaultPartyHeight;
+  int sEyelevel;
+  unsigned int uDefaultEyelevel;
+  int field_14;
+  int field_18;
+  unsigned int uWalkSpeed;
+  int field_20_prolly_turn_speed;
+  int field_24;
+  int field_28;
+  unsigned __int64 uTimePlayed;
+  __int64 uLastRegenerationTime;
+  Party_stru0 field_3C;
+  Vec3_int_ vPosition;
+  int sRotationY;
+  int sRotationX;
+  Vec3_int_ vPrevPosition;
+  int sPrevRotationY;
+  int sPrevRotationX;
+  int sPrevEyelevel;
+  int field_6E0;
+  int field_6E4;
+  int uFallSpeed;
+  int field_6EC;
+  int field_6F0;
+  int field_6F4_packedid;
+  int field_6F8;
+  int field_6FC;
+  int uFallStartY;
+  unsigned int bFlying;
+  char field_708;
+  char field_709;
+  char field_70A;
+  char field_70B;
+  unsigned int uCurrentYear;
+  unsigned int uCurrentMonth;
+  unsigned int uCurrentMonthWeek;
+  unsigned int uDaysPlayed;
+  unsigned int uCurrentHour;
+  unsigned int uCurrentMinute;
+  unsigned int uCurrentTimeSecond;
+  unsigned int uNumFoodRations;
+  int field_72C;
+  int field_730;
+  unsigned int uNumGold;
+  unsigned int uNumGoldInBank;
+  unsigned int uNumDeaths;
+  int field_740;
+  int uNumPrisonTerms;
+  unsigned int uNumBountiesCollected;
+  int field_74C;
+  __int16 field_750[5];
+  __int16 field_75A[5];
+  char field_764; // num hours resting or some sort of.
+  unsigned __int8 _award_bits[64];
+  unsigned __int8 pArcomageWins[16];
+  char field_7B5_in_arena_quest;
+  char uNumArenaPageWins;
+  char uNumArenaSquireWins;
+  char uNumArenaKnightWins;
+  char uNumArenaLordWins;
+  char field_7BA[12];
+  char pArtifactsFound[56];
+  unsigned char _autonote_bits[12];
+  char field_80A[74];
+  char field_854[32];
+  int field_874;
+  int field_878;
+  unsigned int bTurnBasedModeOn;
+  int field_880;
+  int uFlags2;
+  unsigned int uAlignment;
+  SpellBuff pPartyBuffs[20];
+  Player pPlayers[4];
+  NPCData pHirelings[2];
+  ItemGen pPickedItem;
+  unsigned int uFlags;
+  int field_777C[1000];
+  int field_871C[1000];
+  int field_96BC[1000];
+  int field_A65C[1000];
+  int field_B5FC[1000];
+  int field_C59C[1000];
+  int field_D53C[1000];
+  int field_E4DC[300];
+  int field_E98C[13];
+  int dword_E9C0;
+  int dword_E9C4;
+  char field_E9C8[5000];
+  char field_FD50[5000];
+  char field_110D8[5000];
+  char field_12460[5000];
+  char field_137E8[5000];
+  char field_14B70[5000];
+  char field_15EF8[250];
+  char field_15FF2[130];
+  char pHireling1Name[100];
+  char pHireling2Name[100];
+  int field_1613C;
+  int field_16140;
+  int pTurnBasedPlayerRecoveryTimes[4];
+  char field_16154[212];
+  int uFine;
+  float flt_TorchlightColorR;
+  float flt_TorchlightColorG;
+  float flt_TorchlightColorB;
+};
+#pragma pack(pop)
+
+
+
+extern Party *pParty; // idb
+
+
+extern struct ActionQueue *pPartyActionQueue;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Player.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,9751 @@
+#include "OSAPI.h"
+
+#include "Player.h"
+#include "PlayerFrameTable.h"
+#include "Texture.h"
+#include "AudioPlayer.h"
+#include "Party.h"
+#include "GUIButton.h"
+#include "LOD.h"
+#include "Monsters.h" 
+#include "GUIWindow.h"
+#include "Viewport.h"
+#include "Actor.h"
+#include "Game.h"
+#include "Mouse.h"
+#include "TurnEngine.h"
+#include "Events.h"
+#include "Events2D.h"
+#include "Outdoor.h"
+#include "StorylineTextTable.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+/*  381 */
+#pragma pack(push, 1)
+struct PlayerCreation_AttributeProp
+{
+  unsigned __int8 uBaseValue;
+  char uMaxValue;
+  char uDroppedStep;
+  char uBaseStep;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct PlayerCreation_AttributePropsByRace
+{
+  PlayerCreation_AttributeProp attr[7];
+};
+
+struct PlayerCreation_AttributeProps
+{
+  union
+  {
+    unsigned __int8 _[4][7][4];
+    PlayerCreation_AttributePropsByRace race[4];
+  };
+};
+#pragma pack(pop)
+PlayerCreation_AttributeProps stru_4ED7B0 =
+{
+  11, 25, 1, 1,   11, 25, 1, 1,   11, 25, 1, 1,    9, 25, 1, 1,   11, 25, 1, 1,   11, 25, 1, 1,   9, 25, 1, 1,
+   7, 15, 2, 1,   14, 30, 1, 2,   11, 25, 1, 1,    7, 15, 2, 1,   14, 30, 1, 2,   11, 25, 1, 1,   9, 20, 1, 1,
+  14, 30, 1, 2,    7, 15, 2, 1,    7, 15, 2, 1,   11, 25, 1, 1,   11, 25, 1, 1,   14, 30, 1, 2,   9, 20, 1, 1,
+  14, 30, 1, 2,   11, 25, 1, 1,   11, 25, 1, 1,   14, 30, 1, 2,    7, 15, 2, 1,    7, 15, 2, 1,   9, 20, 1, 1
+};
+
+
+
+
+
+
+ // available skills per class ( 9 classes X 37 skills )
+ // 0 - not available
+ // 1 - available
+ // 2 - primary skill
+unsigned char pSkillAvailabilityPerClass[9][37] =  // byte[] @ MM7.exe::004ED820
+{
+  {0, 2, 0, 1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
+  {0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 2, 1, 0},
+  {1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 2, 1, 1, 0, 0, 0},
+  {0, 1, 1, 1, 0, 0, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
+  {0, 1, 0, 1, 1, 2, 0, 0, 0, 1, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
+  {0, 1, 1, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0},
+  {0, 0, 0, 0, 0, 0, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
+  {0, 0, 2, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
+  {2, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0} // some of these are started at 4ED94C, but needs to be here
+};
+
+
+
+
+unsigned char pBaseHealthByClass[12] = {40, 35, 35, 30, 30, 30, 25, 20, 20, 0, 0, 0};
+unsigned char pBaseManaByClass[12]   = { 0,  0,  0,  5,  5,  0, 10, 10, 15, 0, 0, 0};
+unsigned char pBaseHealthPerLevelByClass[36] = {5, 7, 9, 9, 4, 6, 8, 8, 5, 6, 8, 8, 4, 5, 6, 6, 3, 4, 6, 6, 4, 5, 6, 6, 2, 3, 4, 4, 2, 3, 4, 4, 2, 3, 3, 3};
+unsigned char pBaseManaPerLevelByClass[36]   = {0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 2, 3, 3, 1, 2, 3, 3, 0, 2, 3, 3, 3, 4, 5, 5, 3, 4, 5, 5, 3, 4, 6, 6};
+
+unsigned char pConditionStrengthMultiplier[19]     = {100, 100, 100, 120,  50, 200,  75,  60,  50,  30,  25,  10, 100, 100, 100, 100, 100, 100, 100};
+unsigned char pConditionIntelligenceMultiplier[19] = {100, 100, 100,  50,  25,  10, 100, 100,  75,  60,  50,  30, 100, 100, 100, 100, 100,   1, 100};
+unsigned char pConditionWillpowerMultiplier[19]    = {100, 100, 100,  50,  25,  10, 100, 100,  75,  60,  50,  30, 100, 100, 100, 100, 100,   1, 100};
+unsigned char pConditionEnduranceMultiplier[19]    = {100, 100, 100, 100,  50, 150,  75,  60,  50,  30,  25,  10, 100, 100, 100, 100, 100, 100, 100};
+unsigned char pConditionAccuracyMultiplier[19]     = {100, 100, 100,  50,  10, 100,  75,  60,  50,  30,  25,  10, 100, 100, 100, 100, 100,  50, 100};
+unsigned char pConditionSpeedMultiplier[19]        = {100, 100, 100, 120,  20, 120,  75,  60,  50,  30,  25,  10, 100, 100, 100, 100, 100,  50, 100};
+unsigned char pConditionLuckMultiplier[19]         = {100, 100, 100, 100, 200, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100};
+
+unsigned char pAgeingStrengthMultiplier[4]     = {100,  75,  40, 10};
+unsigned char pAgeingIntelligenceMultiplier[4] = {100, 150, 100, 10};
+unsigned char pAgeingWillpowerMultiplier[4]    = {100, 150, 100, 10};
+unsigned char pAgeingEnduranceMultiplier[4]    = {100,  75,  40, 10};
+unsigned char pAgeingAccuracyMultiplier[4]     = {100, 100,  40, 10};
+unsigned char pAgeingSpeedMultiplier[4]        = {100, 100,  40, 10};
+unsigned char pAgeingLuckMultiplier[4]         = {100, 100, 100, 100};
+
+unsigned int pAgeingTable[4] = {50, 100, 150, 65535};
+
+unsigned int pConditionImportancyTable[18] = {16, 15, 14, 17, 13, 2, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 1, 0};
+
+short word_4EDFFC[30] = {500, 500, 400, 350, 300, 275, 250, 225, 200, 175,
+                         150, 125, 100,  75,  50,  40,  35,  30,  25,  21,
+                         19,   17,  15,  13,  11,   9,   7,   5,   3,   0};
+unsigned char player_stat_bonuses[30] = {30, 25, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 255, 254, 253, 252, 251, 250, 0};
+
+
+
+
+//----- (00490913) --------------------------------------------------------
+signed int __cdecl PlayerCreation_ComputeAttributeBonus()
+{
+  signed int v0; // edi@1
+  signed int v1; // esi@1
+  int v2; // ebx@2
+  int v3; // ecx@17
+  signed int v4; // eax@17
+  int v5; // edx@18
+  signed int v6; // ecx@18
+  signed int v8; // [sp+Ch] [bp-8h]@1
+  signed int v9; // [sp+10h] [bp-4h]@2
+
+  v8 = 50;
+  v0 = 50;
+  v1 = 0;
+  do
+  {
+    v9 = 0;
+    v2 = 7 * pParty->pPlayers[v1].GetRace();
+    do
+    {
+      if ( v9 )
+      {
+        switch ( v9 )
+        {
+          case 1:
+            v0 = pParty->pPlayers[v1].uIntelligence;
+            break;
+          case 2:
+            v0 = pParty->pPlayers[v1].uWillpower;
+            break;
+          case 3:
+            v0 = pParty->pPlayers[v1].uEndurance;
+            break;
+          case 4:
+            v0 = pParty->pPlayers[v1].uAccuracy;
+            break;
+          case 5:
+            v0 = pParty->pPlayers[v1].uSpeed;
+            break;
+          case 6:
+            v0 = pParty->pPlayers[v1].uLuck;
+            break;
+        }
+      }
+      else
+      {
+        v0 = pParty->pPlayers[v1].uMight;
+      }
+      v3 = v2 + v9;
+      v4 = stru_4ED7B0.race[0].attr[v3].uBaseValue;
+      if ( v0 >= v4 )
+      {
+        v5 = stru_4ED7B0.race[0].attr[v3].uDroppedStep;
+        v6 = stru_4ED7B0.race[0].attr[v3].uBaseStep;
+      }
+      else
+      {
+        v5 = stru_4ED7B0.race[0].attr[v3].uBaseStep;
+        v6 = stru_4ED7B0.race[0].attr[v3].uDroppedStep;
+      }
+      v8 += v5 * (v4 - v0) / v6;
+      ++v9;
+    }
+    while ( v9 <= 6 );
+    ++v1;
+  }
+  while ( v1 < 4 );
+  return v8;
+}
+
+
+
+//----- (00427730) --------------------------------------------------------
+bool Player::CanCastSpell(unsigned int uRequiredMana)
+{
+  int v2; // eax@1
+  bool result; // eax@2
+
+  v2 = this->sMana;
+  if ( v2 >= (signed int)uRequiredMana )
+  {
+    this->sMana = v2 - uRequiredMana;
+    result = 1;
+  }
+  else
+  {
+    pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
+    result = 0;
+  }
+  return result;
+}
+
+
+//----- (004BE2DD) --------------------------------------------------------
+void Player::_4BE2DD(unsigned int a2, int a3, int _2devent_idx)
+{
+  Player *v4; // edi@1
+  char *v5; // esi@1
+  float v6; // ST04_4@1
+  signed int v7; // eax@1
+  signed int v8; // ebx@1
+
+  auto a4 = _2devent_idx;
+  v4 = this;
+  v5 = (char *)this + 36 * a3;
+  v6 = p2DEvents[a4 - 1].fPriceMultiplier;
+  //v6 = p2DEvents_minus1__20[13 * a4];
+  v7 = ((ItemGen *)(v5 + 532))->GetValue();
+  v8 = _4B8102(v7, v6);
+  if ( v5[552] & 2 )
+    v8 = 1;
+  if ( v8 < 1 )
+    v8 = 1;
+  RemoveItemAtInventoryIndex(a2);
+  Party::SetGold(pParty->uNumGold + v8);
+}
+
+
+
+//----- (0043EEF3) --------------------------------------------------------
+bool Player::_43EEF3()
+{
+  signed int v1; // esi@1
+  PlayerEquipment *v2; // edx@1
+  bool result; // eax@2
+
+  v1 = 0;
+  v2 = &this->pEquipment;
+  while ( 1 )
+  {
+    result = v2->uOffHand;
+    if ( v2->uOffHand )
+    {
+      result = *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
+      if ( result )
+      {
+        if ( result != 64 && result != 65 )
+          break;
+      }
+    }
+    ++v1;
+    v2 = (PlayerEquipment *)((char *)v2 + 4);
+    if ( v1 >= 16 )
+    {
+      LOBYTE(result) = 1;
+      return result;
+    }
+  }
+  LOBYTE(result) = 0;
+  return result;
+}
+
+
+
+//----- (004B8040) --------------------------------------------------------
+int Player::_4B8040_condition_time(unsigned int uCondition)
+{
+  return (unsigned int)((signed __int64)((double)this->pConditions[uCondition] * 0.234375) / 60 / 60) / 0x18 % 7 + 1;
+}
+
+//----- (004B807C) --------------------------------------------------------
+int Player::_4B807C(float a2)
+{
+  Player *v2; // edi@1
+  unsigned int v3; // eax@1
+  int v4; // esi@1
+  unsigned int v5; // ebx@7
+  int v6; // eax@8
+  signed __int64 v7; // qax@13
+  unsigned int v9; // [sp-4h] [bp-14h]@4
+  signed int v10; // [sp+8h] [bp-8h]@4
+  int v11; // [sp+Ch] [bp-4h]@6
+
+  v2 = this;
+  v3 = GetMajorConditionIdx();
+  v4 = 0;
+  if ( (signed int)v3 >= 14 )
+  {
+    if ( (signed int)v3 <= 15 )
+    {
+      v10 = 5;
+      v9 = v3;
+      goto LABEL_6;
+    }
+    if ( v3 == 16 )
+    {
+      v10 = 10;
+      v9 = 16;
+LABEL_6:
+      v11 = _4B8040_condition_time(v9);
+      goto LABEL_13;
+    }
+  }
+  v10 = 1;
+  v5 = 0;
+  do
+  {
+    v6 = _4B8040_condition_time(v5);
+    if ( v6 > v4 )
+      v4 = v6;
+    ++v5;
+  }
+  while ( (signed int)v5 <= 13 );
+  v11 = v4;
+  if ( !v4 )
+    v11 = 1;
+LABEL_13:
+  v7 = (signed __int64)((double)v11 * (double)v10 * a2);
+  if ( (signed int)v7 < 1 )
+    LODWORD(v7) = 1;
+  return v7;
+}
+
+//----- (004B8102) --------------------------------------------------------
+int Player::_4B8102(int a2, float a3)
+{
+  signed int v3; // esi@1
+  signed int result; // eax@3
+
+  v3 = (unsigned __int64)(signed __int64)((double)a2 / (a3 + 2.0)) + a2 * GetMerchant() / 100;
+  if ( v3 > a2 )
+    v3 = a2;
+  result = 1;
+  if ( v3 >= 1 )
+    result = v3;
+  return result;
+}
+
+//----- (004B8142) --------------------------------------------------------
+int Player::_4B8142(int a2, float a3)
+{
+  int result; // eax@1
+
+  result = (int)((100 - GetMerchant()) * (unsigned __int64)(signed __int64)((double)a2 * a3)) / 100;
+  if ( result < a2 )
+    result = a2;
+  if ( result < 1 )
+    result = 1;
+  return result;
+}
+
+//----- (004B8179) --------------------------------------------------------
+int Player::_4B8179(float a2)
+{
+  signed int v2; // esi@1
+  int v3; // ecx@1
+  signed int result; // eax@3
+
+  v2 = (signed __int64)(a2 * 50.0);
+  v3 = v2 * (100 - GetMerchant()) / 100;
+  if ( v3 < v2 / 3 )
+    v3 = v2 / 3;
+  result = 1;
+  if ( v3 >= 1 )
+    result = v3;
+  return result;
+}
+
+//----- (004B81C3) --------------------------------------------------------
+int Player::_4B81C3(int a2, float a3)
+{
+  signed int v3; // esi@1
+  int v4; // ecx@1
+  signed int result; // eax@3
+
+  v3 = (signed __int64)((double)a2 / (6.0 - a3));
+  v4 = v3 * (100 - GetMerchant()) / 100;
+  if ( v4 < v3 / 3 )
+    v4 = v3 / 3;
+  result = 1;
+  if ( v4 >= 1 )
+    result = v4;
+  return result;
+}
+
+//----- (004B8213) --------------------------------------------------------
+int Player::_4B8213(int a2, float a3)
+{
+  signed __int64 v3; // qax@1
+
+  v3 = (signed __int64)((double)a2 / (a3 + 2.0));
+  if ( (signed int)v3 < 1 )
+    LODWORD(v3) = 1;
+  return v3;
+}
+
+//----- (004B8233) --------------------------------------------------------
+int Player::_4B8233(int a2, float a3)
+{
+  signed __int64 v3; // qax@1
+
+  v3 = (signed __int64)((double)a2 * a3);
+  if ( (signed int)v3 < 1 )
+    LODWORD(v3) = 1;
+  return v3;
+}
+
+//----- (004B824B) --------------------------------------------------------
+int Player::_4B824B(float a2)
+{
+  signed __int64 v2; // qax@1
+
+  v2 = (signed __int64)(a2 * 50.0);
+  if ( (signed int)v2 < 1 )
+    LODWORD(v2) = 1;
+  return v2;
+}
+
+//----- (004B8265) --------------------------------------------------------
+int Player::_4B8265(int a2, float a3)
+{
+  signed __int64 v3; // qax@1
+
+  v3 = (signed __int64)((double)a2 / (6.0 - a3));
+  if ( (signed int)v3 < 1 )
+    LODWORD(v3) = 1;
+  return v3;
+}
+
+
+
+
+
+//----- (004B6FF9) --------------------------------------------------------
+int Player::_4B6FF9()
+{
+  Player *v1; // esi@1
+  signed int v2; // eax@1
+  char v3; // zf@4
+
+  v1 = this;
+  v2 = (signed int)ptr_507BC0->ptr_1C;
+  if ( v2 == 78 || v2 > 80 && v2 <= 82 )
+  {
+    if ( GetMajorConditionIdx() == 18 )
+      goto LABEL_6;
+    v3 = GetMajorConditionIdx() == 17;
+  }
+  else
+  {
+    v3 = GetMajorConditionIdx() == 18;
+  }
+  if ( !v3 )
+    return 1;
+LABEL_6:
+  if ( v1->sHealth < GetMaxHealth() || v1->sMana < GetMaxMana() )
+    return 1;
+  return 0;
+}
+
+
+
+//----- (00421E75) --------------------------------------------------------
+unsigned int Player::GetItemIDAtInventoryIndex(int *a2)
+{
+  int v2; // eax@1
+  unsigned int result; // eax@3
+
+  v2 = *a2;
+  if ( *a2 >= 126 || v2 < 0 )
+  {
+    result = 0;
+  }
+  else
+  {
+    result = this->pInventoryIndices[v2];
+    if ( (result & 0x80000000u) != 0 )
+    {
+      *a2 = -1 - result;
+      result = this->pInventoryIndices[-1 - result];
+    }
+  }
+  return result;
+}
+
+
+
+//----- (004160CA) --------------------------------------------------------
+char Player::_4160CA(int a2)
+{
+  Player *v2; // esi@1
+  signed int v3; // edx@1
+  signed int v4; // ebx@1
+  ItemGen *v5; // eax@1
+  int v6; // edi@2
+  signed int i; // edx@8
+  ItemGen **v8; // ecx@9
+  __int16 v10[137]; // [sp+Ch] [bp-118h]@1
+  __int16 v11; // [sp+11Eh] [bp-6h]@1
+  int v12; // [sp+120h] [bp-4h]@1
+
+  auto a1 = this;
+
+  v12 = a2;
+  v2 = a1;
+  v3 = 0;
+  v10[0] = 0;
+  v4 = 0;
+  memset(&v10[1], 0, 0x110u);
+  v11 = 0;
+  v5 = a1->pInventoryItems;
+  do
+  {
+    v6 = 0;
+    if ( (signed int)v5->uItemID > 0 && (signed int)v5->uItemID <= 134 )
+      v10[v4++] = v3;
+    ++v3;
+    ++v5;
+  }
+  while ( v3 < 138 );
+  if ( v4 )
+  {
+    if ( v12 )
+    {
+      if ( v12 > 0 )
+      {
+        do
+        {
+          LOWORD(v5) = 9 * v10[v6];
+          if ( !(BYTE1(v2->pInventoryItems[v10[v6]].uAttributes) & 2) )
+          {
+            v5 = (ItemGen *)((char *)&v2->pInventoryItems[v10[rand() % v4]] + 20);
+            v5->uItemID |= 2u;
+          }
+          ++v6;
+        }
+        while ( v6 < v12 );
+      }
+    }
+    else
+    {
+      for ( i = 0; i < v4; ++i )
+      {
+        v8 = (ItemGen **)&v2->pInventoryItems[v10[i]].uAttributes;
+        v5 = *v8;
+        if ( !(BYTE1(v5) & 2) )
+        {
+          LOBYTE(v5) = (unsigned __int8)v5 | 2;
+          *v8 = v5;
+        }
+      }
+    }
+  }
+  return (char)v5;
+}
+
+//----- (004948B1) --------------------------------------------------------
+__int16 Player::PlaySound(int a2, int a3)
+{
+  Player *pPlayer; // edi@1
+  int v4; // eax@4
+  signed int v5; // esi@4
+  short *v6; // ebx@4
+  signed int v7; // ecx@5
+  unsigned __int8 v8; // al@6
+  int v9; // eax@10
+  unsigned int pVoiceID; // ecx@10
+  int v11; // esi@10
+  signed int v12; // eax@11
+  signed int v13; // esi@12
+  int v14; // eax@12
+  int v15; // eax@17
+  int pExpression; // ebx@17
+  signed int v17; // ecx@19
+  char *pSoundID; // edi@20
+  int v20[5]; // [sp+Ch] [bp-1Ch]@7
+  Player *pPlayer2; // [sp+20h] [bp-8h]@1
+  int pPlayerNum; // [sp+24h] [bp-4h]@1
+  int pSoundId; // [sp+30h] [bp+8h]@4
+
+  pPlayer = this;
+  pPlayer2 = this;
+  pPlayerNum = 1;
+  do
+  {
+    if ( this == pPlayers[pPlayerNum] )
+      break;
+    ++pPlayerNum;
+  }
+  while ( pPlayerNum <= 4 );
+  v4 = a2;//102
+  v5 = 0;
+  pSoundId = 0;
+  v6 = &SoundSetAction[8 * v4];//byte_4ED280 &byte_4ED3D8[4 * v4]
+  if ( uVoicesVolumeMultiplier )
+  {
+    v7 = 0;
+    do
+    {
+      v8 = v6[v7];
+      if ( v8 )
+        v20[v5++] = v8;
+      ++v7;
+    }
+    while ( v7 < 2 );
+    if ( v5 )
+    {
+      v9 = rand();
+      pVoiceID = pPlayer->uVoiceID;
+      v11 = v20[v9 % v5];
+      if ( LOBYTE((&(&dlhu_texnames_by_face[19])[25 * v11 + 3])[pVoiceID]) )
+      {
+        pSoundId = rand() % SLOBYTE((&(&dlhu_texnames_by_face[19])[25 * v11 + 3])[pVoiceID])
+            + 2 * (v11 + 50 * pPlayer2->uVoiceID)
+            + 4998;
+        v12 = 8 * pPlayerNum + 312;
+        LOBYTE(v12) = v12 | 4;
+        pAudioPlayer->PlaySound((SoundID)pSoundId, v12, 0, -1, 0, 0, (signed __int64)(pSoundVolumeLevels[(char)uVoicesVolumeMultiplier] * 128.0), 0);
+      }
+    }
+  }
+  v13 = 0;
+  v14 = (int)(v6 + 3);
+  do
+  {
+    if ( *(char *)v14 )
+      v20[v13++] = *(char *)v14;
+    ++v14;
+  }
+  while ( -3 - (signed int)v6 + v14 < 5 );
+  if ( v13 )
+  {
+    v15 = rand();
+    pPlayerNum = 0;
+    pExpression = v20[v15 % v13];
+    if ( pExpression == 21 && pSoundId )
+    {
+      v17 = 0;
+      if ( (signed int)pSoundList->uNumSounds <= 0 )
+      {
+LABEL_23:
+        v17 = 0;
+      }
+      else
+      {
+        pSoundID = (char *)&pSoundList->pSounds->uSoundID;
+        while ( *(int *)pSoundID != pSoundId )
+        {
+          ++v17;
+          pSoundID += 120;
+          if ( v17 >= (signed int)pSoundList->uNumSounds )
+            goto LABEL_23;
+        }
+      }
+      if ( pSoundList->pSounds[v17].pSoundData[0] )
+        pPlayerNum = (sLastTrackLengthMS << 7) / 1000;
+    }
+    LOWORD(v14) = pPlayer2->PlayEmotion(pExpression, pPlayerNum);
+  }
+  return v14;
+}
+// 4948B1: using guessed type int var_1C[5];
+
+//----- (00494A25) --------------------------------------------------------
+__int16 Player::PlayEmotion(int a2, int a3)
+{
+  signed int v3; // eax@1
+  unsigned __int16 v4; // dx@1
+  signed int v5; // edi@15
+  PlayerFrame *v6; // esi@17
+  signed int v7; // eax@20
+
+  LOWORD(v3) = this->uExpressionID;
+  v4 = a2;
+  if ( (short)v3 != 4 && (short)v3 != 12 || a2 != 58 )
+  {
+    v3 = (unsigned __int16)v3;
+    if ( (signed int)(unsigned __int16)v3 >= 2 )
+    {
+      if ( v3 <= 7 )
+        goto LABEL_12;
+      if ( v3 > 8 )
+      {
+        if ( v3 > 11 )
+        {
+          if ( v3 == 12 || v3 > 97 && v3 <= 99 )
+            return v3;
+          goto LABEL_15;
+        }
+LABEL_12:
+        if ( a2 != 34 && a2 != 35 && a2 != 36 )
+          return v3;
+        goto LABEL_15;
+      }
+    }
+  }
+LABEL_15:
+  LOWORD(v3) = a3;
+  v5 = 0;
+  this->uExpressionTimeLength = a3;
+  this->uExpressionTimePassed = 0;
+  if ( !a3 )
+  {
+    if ( (signed int)pPlayerFrameTable->uNumFrames <= 0 )
+    {
+LABEL_20:
+      v7 = 0;
+    }
+    else
+    {
+      v6 = pPlayerFrameTable->pFrames;
+      while ( v6->uSequenceID != a2 )
+      {
+        ++v5;
+        ++v6;
+        if ( v5 >= (signed int)pPlayerFrameTable->uNumFrames )
+          goto LABEL_20;
+      }
+      v7 = v5;
+    }
+    v4 = a2;
+    LOWORD(v3) = 8 * pPlayerFrameTable->pFrames[v3].uAnimLength;
+    this->uExpressionTimeLength = v3;
+  }
+  this->uExpressionID = v4;
+  viewparams->bRedrawGameUI = 1;
+  return v3;
+}
+
+//----- (0049327B) --------------------------------------------------------
+int Player::_49327B(unsigned int uClass, int a3)
+{
+  Player *v3; // esi@1
+  char v4; // zf@4
+  __int16 v5; // dx@9
+  signed int result; // eax@84
+  unsigned int v7; // [sp-8h] [bp-10h]@3
+  int v8; // [sp-4h] [bp-Ch]@3
+
+  v3 = this;
+  if ( this->uClass == uClass )
+  {
+LABEL_84:
+    result = 1;
+  }
+  else
+  {
+    switch ( uClass )
+    {
+      case 0u:
+        v8 = a3;
+        v7 = 1;
+        goto LABEL_4;
+      case 1u:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, 17)
+          || _49327B(2u, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 3;
+        goto LABEL_4;
+      case 2u:
+        v5 = 19;
+        goto LABEL_82;
+      case 3u:
+        v5 = 21;
+        goto LABEL_82;
+      case 4u:
+        v8 = a3;
+        v7 = 5;
+        goto LABEL_4;
+      case 5u:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, 11)
+          || _49327B(6u, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 7;
+        goto LABEL_4;
+      case 6u:
+        if ( !a3 )
+          break;
+        v5 = 13;
+        goto LABEL_82;
+      case 7u:
+        if ( !a3 )
+          break;
+        v5 = 15;
+        goto LABEL_82;
+      case 8u:
+        v8 = a3;
+        v7 = 9;
+        goto LABEL_4;
+      case 9u:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, 23)
+          || _49327B(0xAu, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 11;
+        goto LABEL_4;
+      case 0xAu:
+        if ( !a3 )
+          break;
+        v5 = 25;
+        goto LABEL_82;
+      case 0xBu:
+        if ( !a3 )
+          break;
+        v5 = 27;
+        goto LABEL_82;
+      case 0xCu:
+        v8 = a3;
+        v7 = 13;
+        goto LABEL_4;
+      case 0xDu:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, 41)
+          || _49327B(0xEu, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 15;
+        goto LABEL_4;
+      case 0xEu:
+        if ( !a3 )
+          break;
+        v5 = 43;
+        goto LABEL_82;
+      case 0xFu:
+        if ( !a3 )
+          break;
+        v5 = 45;
+        goto LABEL_82;
+      case 0x10u:
+        v8 = a3;
+        v7 = 17;
+        goto LABEL_4;
+      case 0x11u:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, 35)
+          || _49327B(0x12u, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 19;
+        goto LABEL_4;
+      case 0x12u:
+        if ( !a3 )
+          break;
+        v5 = 37;
+        goto LABEL_82;
+      case 0x13u:
+        v5 = 39;
+        goto LABEL_82;
+      case 0x14u:
+        v8 = a3;
+        v7 = 21;
+        goto LABEL_4;
+      case 0x15u:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, 29)
+          || _49327B(0x16u, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 23;
+        goto LABEL_4;
+      case 0x16u:
+        if ( !a3 )
+          break;
+        v5 = 31;
+        goto LABEL_82;
+      case 0x17u:
+        if ( !a3 )
+          break;
+        v5 = 33;
+        goto LABEL_82;
+      case 0x18u:
+        if ( !_49327B(0x19u, a3) )
+          goto LABEL_56;
+        break;
+      case 0x19u:
+LABEL_56:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)v3->field_152, 63)
+          || _49327B(0x1Au, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 27;
+        goto LABEL_4;
+      case 0x1Au:
+        if ( !a3 )
+          break;
+        v5 = 65;
+        goto LABEL_82;
+      case 0x1Bu:
+        if ( !a3 )
+          break;
+        v5 = 67;
+        goto LABEL_82;
+      case 0x1Cu:
+        v8 = a3;
+        v7 = 29;
+        goto LABEL_4;
+      case 0x1Du:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, 69)
+          || _49327B(0x1Eu, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 31;
+        goto LABEL_4;
+      case 0x1Eu:
+        if ( !a3 )
+          break;
+        v5 = 71;
+        goto LABEL_82;
+      case 0x1Fu:
+        if ( !a3 )
+          break;
+        v5 = 73;
+        goto LABEL_82;
+      case 0x20u:
+        v8 = a3;
+        v7 = 33;
+        goto LABEL_4;
+      case 0x21u:
+        if ( a3 && (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, 73)
+          || _49327B(0x22u, a3) )
+          goto LABEL_84;
+        v8 = a3;
+        v7 = 35;
+LABEL_4:
+        v4 = _49327B(v7, v8) == 0;
+        goto LABEL_83;
+      case 0x22u:
+        if ( !a3 )
+          break;
+        v5 = 77;
+        goto LABEL_82;
+      case 0x23u:
+        if ( a3 )
+        {
+          v5 = 79;
+LABEL_82:
+          v4 = (unsigned __int16)_449B57_test_bit((unsigned __int8 *)this->field_152, v5) == 0;
+LABEL_83:
+          if ( !v4 )
+            goto LABEL_84;
+        }
+        break;
+      default:
+        break;
+    }
+    result = 0;
+  }
+  return result;
+}
+
+
+//----- (00492C0B) --------------------------------------------------------
+bool Player::CanAct()
+{
+  bool result; // eax@2
+
+  if ( this->pConditions[2] | this->pConditions[12] | this->pConditions[13] | this->pConditions[14] | this->pConditions[15] | this->pConditions[16] )
+    result = 0;
+  else
+    result = 1;
+  return result;
+}
+
+//----- (00492C40) --------------------------------------------------------
+bool Player::CanSteal()
+{
+  int v1; // eax@1
+
+  LOBYTE(v1) = GetActualSkillLevel(PLAYER_SKILL_STEALING);
+  return v1 != 0;
+}
+
+//----- (00492C4E) --------------------------------------------------------
+bool Player::CanEquip_RaceAndAlignmentCheck(unsigned int uItemID)
+{
+  char v2; // zf@9
+  __int16 v4; // dx@13
+  char v5; // zf@15
+
+  if ( (signed int)uItemID > 532 )              //  if (uItemID == 514 ||                       // item233  ®á®å âਪ                àâ¥ä ªâ, §«®
+                                                //      uItemID == 516 ||                       // item221  ‘â àë© ¨ª                 àâ¥ä ªâ, §«®
+                                                //      uItemID == 524)                         // item325  ‘ã¬à ª                    ५¨ª¢¨ï, §«®
+  {
+    if ( uItemID == 533 )
+    {
+      v2 = GetRace() == 1;
+    }
+    else
+    {
+      if ( uItemID != 534 )
+      {
+        if ( uItemID == 535 )                   // 
+                                                //  if (uItemID == 530)                         // item093  ƒ¨¡¥«ì «ìä                àâ¥ä ªâ, £®¡«¨­
+        {
+          switch ( this->uVoiceID )
+          {
+            default:
+              return 1;
+            case 4u:
+            case 5u:
+            case 6u:
+            case 7u:
+            case 0xAu:
+            case 0xBu:
+            case 0xEu:                          // 
+                                                //  if (uItemID == 535)                         // item129  ᪮àâ ‹¥¤¨                àâ¥ä ªâ, ¦¥­é¨­ 
+            case 0xFu:
+            case 0x12u:
+            case 0x13u:
+            case 0x15u:
+            case 0x18u:
+              return 0;
+          }
+          return 0;
+        }
+        if ( uItemID == 536 )                   // 
+                                                //  if (uItemID == 531)                         // item093  Žª® Œë᫨                  àâ¥ä ªâ, 祫®¢¥ª
+        {
+          switch ( this->uVoiceID )
+          {
+            case 4u:
+            case 5u:
+            case 6u:
+            case 7u:
+            case 0xAu:
+            case 0xBu:
+            case 0xEu:
+            case 0xFu:
+            case 0x12u:
+            case 0x13u:
+            case 0x15u:
+            case 0x18u:
+              return 1;
+            default:
+              return 0;
+          }
+          return 0;
+        }
+        if ( uItemID != 604 )                   // 
+                                                //  if (uItemID == 532)                         // item073  «ìä¨©áª ï Š®«ìç㣠        àâ¥ä ªâ, í«ìä
+          return 1;
+        v5 = _43EEF3() == 0;
+        goto LABEL_23;
+      }
+      v2 = GetRace() == 3;                     // 
+                                                //  if (uItemID == 533)                         // item113  Š®¢ ­ë¥ ‹ â­ë¥ 㪠¢¨æë    àâ¥ä ªâ, £­®¬
+    }
+  }
+  else
+  {
+    if ( uItemID != 532 )
+    {
+      if ( uItemID != 515 && uItemID != 517 )   // 
+                                                //  if (uItemID == 534)                         // item104  ®ïá ƒ¥à®ï                 àâ¥ä ªâ, ¬ã¦ç¨­ 
+      {
+        if ( uItemID == 521 )                   //  if (uItemID == 521 ||                       // item239  ˜«¥¬ ’ «¥¤®­               àâ¥ä ªâ, ¤®¡à®
+                                                //      uItemID == 526)                         // item230  ‘¯à ¢¥¤«¨¢®áâì            ५¨ª¢¨ï, ¤®¡à®
+        {
+LABEL_13:
+          v4 = 99;
+LABEL_15:
+          v5 = (unsigned __int16)_449B57_test_bit(pParty->_award_bits, v4) == 0;
+LABEL_23:
+          if ( !v5 )
+            return 1;
+          return 0;
+        }
+        if ( uItemID != 525 )
+        {
+          if ( uItemID != 527 )
+          {
+            if ( uItemID != 531 )
+              return 1;
+            v2 = GetRace() == 2;
+            goto LABEL_10;
+          }
+          goto LABEL_13;
+        }
+      }
+      v4 = 100;
+      goto LABEL_15;
+    }
+    v2 = GetRace() == 0;
+  }
+LABEL_10:
+  if ( v2 )
+    return 1;
+  return 0;
+}
+
+//----- (00492D65) --------------------------------------------------------
+int Player::SetCondition(unsigned int uConditionIdx, int a3)
+{
+  Player *v3; // esi@1
+  Player **v4; // ebx@2
+  Player *v5; // ecx@21
+  Player *v6; // ecx@22
+  Player *v7; // ecx@29
+  Player *v8; // ecx@30
+  Player *v9; // ecx@37
+  Player *v10; // ecx@38
+  Player *v11; // ecx@45
+  Player *v12; // ecx@46
+  char *v13; // eax@49
+  Player *v14; // ecx@58
+  Player *v15; // ecx@59
+  Player *v16; // ecx@60
+  signed int result; // eax@76
+  signed int v18; // ecx@77
+  int v19; // eax@77
+  char v20; // al@80
+  signed int v21; // ebx@82
+  signed int v22; // esi@82
+  int v23; // [sp-8h] [bp-1Ch]@7
+  int v24; // [sp-8h] [bp-1Ch]@15
+  int v25; // [sp-8h] [bp-1Ch]@53
+  int v26; // [sp-4h] [bp-18h]@7
+  signed int v27; // [sp-4h] [bp-18h]@15
+  int v28; // [sp-4h] [bp-18h]@53
+  char *v29; // [sp+Ch] [bp-8h]@1
+  int v30; // [sp+10h] [bp-4h]@2
+  int v31; // [sp+20h] [bp+Ch]@82
+
+  v3 = this;
+  v29 = (char *)this + 8 * uConditionIdx;
+  if ( *(_QWORD *)v29 )
+  {
+LABEL_76:
+    result = 0;
+  }
+  else
+  {
+    v4 = &pPlayers[1];
+    v30 = 0;
+    do
+    {
+      if ( (*v4)->CanAct() )
+        ++v30;
+      ++v4;
+    }
+    while ( (signed int)v4 <= (signed int)&pPlayers[4] );
+    switch ( uConditionIdx )
+    {
+      case 0u:
+        v26 = 0;
+        v23 = 30;
+        goto LABEL_81;
+      case 1u:
+        if ( a3 == 1 && (signed __int64)pParty->pPartyBuffs[13].uExpireTime > 0 )
+          goto LABEL_10;
+        v26 = 0;
+        v23 = 25;
+        goto LABEL_81;
+      case 2u:
+        if ( a3 != 1 )
+          goto LABEL_82;
+        if ( v3->HasEnchantedItemEquipped(22) )
+          goto LABEL_76;
+        v27 = 3;
+        v24 = 505;
+        goto LABEL_16;
+      case 3u:
+        v26 = 0;
+        v23 = 26;
+        goto LABEL_81;
+      case 4u:
+        v26 = 0;
+        v23 = 31;
+        goto LABEL_81;
+      case 5u:
+        if ( a3 == 1
+          && (v3->HasEnchantedItemEquipped(19) || v5->WearsItem(505, 3) || v6->WearsItem(530, 6)) )
+          goto LABEL_76;
+        v26 = 0;
+        v23 = 29;
+        goto LABEL_81;
+      case 6u:
+      case 8u:
+      case 0xAu:
+        if ( a3 == 1 )
+        {
+          if ( (signed __int64)pParty->pPartyBuffs[13].uExpireTime > 0 )
+          {
+            --pParty->pPartyBuffs[13].uPower;
+            if ( pParty->pPartyBuffs[13].uPower < 1u )
+              pParty->pPartyBuffs[13].Reset();
+          }
+          if ( v3->HasEnchantedItemEquipped(21)
+            || v7->WearsItem(505, 3)
+            || v8->WearsItem(530, 6) )
+            goto LABEL_76;
+        }
+        v26 = 0;
+        v23 = 27;
+        goto LABEL_81;
+      case 7u:
+      case 9u:
+      case 0xBu:
+        if ( a3 != 1 )
+          goto LABEL_40;
+        if ( SHIDWORD(pParty->pPartyBuffs[13].uExpireTime) >= 0
+          && (SHIDWORD(pParty->pPartyBuffs[13].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[13].uExpireTime) > 0) )
+          goto LABEL_10;
+        if ( v3->HasEnchantedItemEquipped(18) || v9->WearsItem(505, 3) || v10->WearsItem(530, 6) )
+          goto LABEL_76;
+LABEL_40:
+        v26 = 0;
+        v23 = 28;
+        goto LABEL_81;
+      case 0xCu:
+        if ( a3 != 1 )
+          goto LABEL_82;
+        if ( SHIDWORD(pParty->pPartyBuffs[13].uExpireTime) >= 0
+          && (SHIDWORD(pParty->pPartyBuffs[13].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[13].uExpireTime) > 0) )
+          goto LABEL_10;
+        if ( v3->HasEnchantedItemEquipped(20)
+          || v11->WearsItem(505, 3)
+          || v12->WearsItem(507, 16) )
+          goto LABEL_76;
+        v27 = 6;
+        v24 = 530;
+LABEL_16:
+        if ( v3->WearsItem(v24, v27) )
+          goto LABEL_76;
+        goto LABEL_82;
+      case 0xDu:
+        v3->PlaySound(32, 0);
+        v13 = (char *)&v3->sHealth;
+        goto LABEL_70;
+      case 0xEu:
+        if ( a3 == 1 && (signed __int64)pParty->pPartyBuffs[13].uExpireTime > 0 && pParty->pPartyBuffs[13].uSkill >= 4u )
+          goto LABEL_10;
+        v28 = 0;
+        v25 = 33;
+        goto LABEL_67;
+      case 0xFu:
+        if ( a3 == 1
+          && (SHIDWORD(pParty->pPartyBuffs[13].uExpireTime) >= 0
+           && (SHIDWORD(pParty->pPartyBuffs[13].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[13].uExpireTime) > 0)
+           || v3->HasEnchantedItemEquipped(23)
+           || v14->WearsItem(520, 16)
+           || v15->WearsItem(505, 3)
+           || v16->WearsItem(530, 6)) )
+          goto LABEL_76;
+        v26 = 0;
+        v23 = 34;
+        goto LABEL_81;
+      case 0x10u:
+        if ( a3 == 1 && (signed __int64)pParty->pPartyBuffs[13].uExpireTime > 0 && pParty->pPartyBuffs[13].uSkill >= 4u )
+        {
+LABEL_10:
+          --pParty->pPartyBuffs[13].uPower;
+          if ( pParty->pPartyBuffs[13].uPower < 1u )
+            pParty->pPartyBuffs[13].Reset();
+          goto LABEL_76;
+        }
+        v28 = 0;
+        v25 = 35;
+LABEL_67:
+        v3->PlaySound(v25, v28);
+        if ( v3->sHealth > 0 )
+          v3->sHealth = 0;
+        v13 = (char *)&v3->sMana;
+LABEL_70:
+        if ( *(int *)v13 > 0 )
+          *(int *)v13 = 0;
+LABEL_82:
+        v21 = 0;
+        *(_QWORD *)v29 = pParty->uTimePlayed;
+        v31 = 0;
+        v22 = 1;
+        do
+        {
+          if ( pPlayers[v22]->CanAct() )
+          {
+            ++v31;
+            v21 = v22;
+          }
+          ++v22;
+        }
+        while ( v22 <= 4 );
+        if ( v30 == 2 )
+        {
+          if ( v31 == 1 )
+            pPlayers[v21]->PlaySound(107, 0);
+        }
+        result = 1;
+        break;
+      case 0x11u:
+        if ( v3->uClass == 35 || v3->pConditions[16] || v3->pConditions[17] || !v3->pConditions[14] )
+          goto LABEL_76;
+        memset(v3, 0, 0xA0u);
+        v3->sHealth = v3->GetMaxHealth();
+        v18 = 0;
+        v3->field_1928 = v3->uFace;
+        v19 = v3->uVoiceID;
+        v3->sMana = 0;
+        v3->field_1924 = v19;
+        switch ( v19 )
+        {
+          case 0:
+          case 1:
+          case 2:
+          case 3:
+          case 8:
+          case 9:
+          case 12:
+          case 13:
+          case 16:
+          case 17:
+          case 20:
+          case 23:
+            v18 = 0;
+            break;
+          case 4:
+          case 5:
+          case 6:
+          case 7:
+          case 10:
+          case 11:
+          case 14:
+          case 15:
+          case 18:
+          case 19:
+          case 21:
+          case 24:
+            v18 = 1;
+            break;
+          default:
+            break;
+        }
+        v26 = 0;
+        v20 = (v18 != 0) + 23;
+        v23 = 99;
+        v3->uFace = v20;
+        v3->uVoiceID = v20;
+LABEL_81:
+        v3->PlaySound(v23, v26);
+        goto LABEL_82;
+      default:
+        goto LABEL_82;
+    }
+  }
+  return result;
+}
+
+//----- (00492528) --------------------------------------------------------
+bool Player::CanFitItem(unsigned int uSlot, unsigned int uItemID)
+{
+  unsigned int v3; // eax@1
+  Texture *v4; // esi@1
+  unsigned int v5; // ebx@1
+  signed int v6; // edi@5
+  int *v7; // ecx@6
+  signed int v8; // edx@7
+  int *v9; // eax@8
+  Player *v11; // [sp+Ch] [bp-4h]@1
+  unsigned int uItemIDa; // [sp+1Ch] [bp+Ch]@1
+
+  v11 = this;
+  v3 = pIcons_LOD->LoadTexture(pItemsTable->pItems[uItemID].pIconName, TEXTURE_16BIT_PALETTE);
+  v4 = (Texture *)(v3 != -1 ? (int)&pIcons_LOD->pTextures[v3] : 0);
+  v5 = GetSizeInInventorySlots(v3 != -1 ? pIcons_LOD->pTextures[v3].uTextureWidth : 24);
+  uItemIDa = GetSizeInInventorySlots(v4->uTextureHeight);
+  if ( !areWeLoadingTexture )
+  {
+    v4->Release();
+    pIcons_LOD->_40F9C5();
+  }
+  if ( (signed int)(v5 + (signed int)uSlot % 14) <= 14 && (signed int)(uItemIDa + (signed int)uSlot / 14) <= 9 )
+  {
+    v6 = 0;
+    if ( (signed int)uItemIDa <= 0 )
+      return 1;
+    v7 = &v11->pInventoryIndices[uSlot];
+    while ( 1 )
+    {
+      v8 = 0;
+      if ( (signed int)v5 > 0 )
+        break;
+LABEL_11:
+      ++v6;
+      v7 += 14;
+      if ( v6 >= (signed int)uItemIDa )
+        return 1;
+    }
+    v9 = v7;
+    while ( !*v9 )
+    {
+      ++v8;
+      ++v9;
+      if ( v8 >= (signed int)v5 )
+        goto LABEL_11;
+    }
+  }
+  return 0;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (004925E6) --------------------------------------------------------
+unsigned int Player::FindFreeInventorySlot()
+{
+  unsigned int result; // eax@1
+  ItemGen *v2; // ecx@1
+
+  result = 0;
+  v2 = this->pInventoryItems;
+  while ( v2->uItemID )
+  {
+    ++result;
+    ++v2;
+    if ( (signed int)result >= 126 )
+      return -1;
+  }
+  return result;
+}
+
+//----- (00492600) --------------------------------------------------------
+int Player::CreateItemInInventory(unsigned int uSlot, unsigned int uItemID)
+{
+  signed int v3; // edx@1
+  ItemGen *v4; // eax@1
+  int result; // eax@8
+  unsigned int v6; // ebx@10
+  unsigned int v7; // eax@10
+  Texture *v8; // esi@10
+  void *v9; // esi@13
+  unsigned int v10; // [sp+0h] [bp-Ch]@10
+  Player *v11; // [sp+4h] [bp-8h]@1
+  signed int v12; // [sp+8h] [bp-4h]@4
+  unsigned int uItemIDa; // [sp+18h] [bp+Ch]@10
+
+  v11 = this;
+  v3 = 0;
+  v4 = this->pInventoryItems;
+  while ( v4->uItemID )
+  {
+    ++v3;
+    ++v4;
+    if ( v3 >= 126 )
+    {
+      v12 = -1;
+      goto LABEL_5;
+    }
+  }
+  v12 = v3;
+LABEL_5:
+  if ( v12 == -1 )
+  {
+    if ( uActiveCharacter )
+      pPlayers[uActiveCharacter]->PlaySound(15, 0);
+    result = 0;
+  }
+  else
+  {
+    v6 = uItemID;
+    v7 = pIcons_LOD->LoadTexture(pItemsTable->pItems[uItemID].pIconName, TEXTURE_16BIT_PALETTE);
+    v8 = (Texture *)(v7 != -1 ? (int)&pIcons_LOD->pTextures[v7] : 0);
+    v10 = GetSizeInInventorySlots(v7 != -1 ? pIcons_LOD->pTextures[v7].uTextureWidth : 24);
+    uItemIDa = GetSizeInInventorySlots(v8->uTextureHeight);
+    if ( !areWeLoadingTexture )
+    {
+      v8->Release();
+      pIcons_LOD->_40F9C5();
+    }
+    if ( (signed int)uItemIDa > 0 )
+    {
+      v9 = &v11->pInventoryIndices[uSlot];
+      do
+      {
+        if ( (signed int)v10 > 0 )
+          memset32(v9, -1 - uSlot, v10);
+        v9 = (char *)v9 + 56;
+        --uItemIDa;
+      }
+      while ( uItemIDa );
+    }
+    result = v12 + 1;
+    v11->pInventoryIndices[uSlot] = v12 + 1;
+    v11->pInventoryItems[v12].uItemID = v6;
+  }
+  return result;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (00492700) --------------------------------------------------------
+int Player::HasSkill(unsigned int uSkillType)
+{
+  signed int result; // eax@3
+
+  if ( (signed int)uSkillType >= 37 || this->pActiveSkills[uSkillType] )
+  {
+    result = 1;
+  }
+  else
+  {
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[67], this->pName);
+    ShowStatusBarString(pTmpBuf, 2u);
+    result = 0;
+  }
+  return result;
+}
+
+//----- (00492745) --------------------------------------------------------
+int Player::WearItem(unsigned int uItemID)
+{
+  signed int v2; // eax@1
+  ItemGen *v3; // edx@1
+  int v4; // edi@6
+  char *v5; // eax@6
+  char *v6; // esi@6
+
+  v2 = 0;
+  v3 = this->pInventoryItems;
+  while ( v3->uItemID )
+  {
+    ++v2;
+    ++v3;
+    if ( v2 >= 126 )
+    {
+      v2 = -1;
+      break;
+    }
+  }
+  if ( v2 != -1 )
+  {
+    v4 = v2 + 1;
+    v5 = (char *)this + 36 * v2;
+    v6 = &byte_4E8394[pItemsTable->pItems[uItemID].uEquipType + 4];
+    *(&this->pEquipment.uOffHand + (unsigned __int8)*v6) = v4;
+    *((int *)v5 + 133) = uItemID;
+    v5[556] = *v6 + 1;
+  }
+  return 0;
+}
+
+//----- (004927A8) --------------------------------------------------------
+int Player::AddItem(unsigned int uSlot, unsigned int uItemID)
+{
+  signed int v3; // ebx@2
+  signed int v4; // edi@3
+  unsigned int v5; // esi@3
+  unsigned int v7; // [sp-8h] [bp-18h]@8
+  unsigned int v8; // [sp-4h] [bp-14h]@8
+  Player *thisa; // [sp+Ch] [bp-4h]@1
+
+  thisa = this;
+  if ( uSlot == -1 )
+  {
+    v3 = 0;
+    while ( 2 )
+    {
+      v4 = 0;
+      v5 = v3;
+      do
+      {
+        if ( CanFitItem(v5, uItemID) )
+        {
+          v8 = uItemID;
+          v7 = v5;
+          return CreateItemInInventory(v7, v8);
+        }
+        ++v4;
+        v5 += 14;
+      }
+      while ( v4 < 9 );
+      ++v3;
+      if ( v3 < 14 )
+        continue;
+      break;
+    }
+    return 0;
+  }
+  if ( !CanFitItem(uSlot, uItemID) )
+  {
+    pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+    return 0;
+  }
+  v8 = uItemID;
+  v7 = uSlot;
+  return CreateItemInInventory(v7, v8);
+}
+
+//----- (00492826) --------------------------------------------------------
+int Player::AddItem2(unsigned int uSlot, ItemGen *Src)
+{
+  unsigned int v3; // ebx@1
+  unsigned int v4; // esi@3
+  signed int v5; // edi@3
+  unsigned int v7; // [sp-8h] [bp-18h]@9
+  ItemGen *v8; // [sp-4h] [bp-14h]@9
+  Player *thisa; // [sp+Ch] [bp-4h]@1
+  signed int uSlota; // [sp+18h] [bp+8h]@2
+
+  thisa = this;
+  v3 = Src->uItemID;
+  pItemsTable->SetSpecialBonus(Src);
+  if ( uSlot == -1 )
+  {
+    uSlota = 0;
+    while ( 2 )
+    {
+      v4 = uSlota;
+      v5 = 0;
+      do
+      {
+        if ( CanFitItem(v4, v3) )
+        {
+          v8 = Src;
+          v7 = v4;
+          return CreateItemInInventory2(v7, v8);
+        }
+        ++v5;
+        v4 += 14;
+      }
+      while ( v5 < 14 );
+      ++uSlota;
+      if ( uSlota < 9 )
+        continue;
+      break;
+    }
+    return 0;
+  }
+  if ( !CanFitItem(uSlot, v3) )
+    return 0;
+  v8 = Src;
+  v7 = uSlot;
+  return CreateItemInInventory2(v7, v8);
+}
+
+//----- (0049289C) --------------------------------------------------------
+int Player::CreateItemInInventory2(unsigned int uSlot, ItemGen *Src)
+{
+  signed int v3; // ebx@1
+  ItemGen *v4; // eax@1
+  int result; // eax@6
+  unsigned int v6; // eax@7
+  Texture *v7; // esi@7
+  unsigned int v8; // edx@9
+  void *v9; // esi@10
+  unsigned int v10; // [sp+4h] [bp-Ch]@7
+  unsigned int v11; // [sp+8h] [bp-8h]@7
+  Player *v12; // [sp+Ch] [bp-4h]@1
+  unsigned int uSlota; // [sp+18h] [bp+8h]@10
+
+  v12 = this;
+  v3 = 0;
+  v4 = this->pInventoryItems;
+  while ( v4->uItemID )
+  {
+    ++v3;
+    ++v4;
+    if ( v3 >= 126 )
+    {
+      v3 = -1;
+      break;
+    }
+  }
+  if ( v3 == -1 )
+  {
+    result = 0;
+  }
+  else
+  {
+    v6 = pIcons_LOD->LoadTexture(
+           pItemsTable->pItems[Src->uItemID].pIconName,
+           TEXTURE_16BIT_PALETTE);
+    v7 = (Texture *)(v6 != -1 ? (int)&pIcons_LOD->pTextures[v6] : 0);
+    v10 = GetSizeInInventorySlots(v6 != -1 ? pIcons_LOD->pTextures[v6].uTextureWidth : 24);
+    v11 = GetSizeInInventorySlots(v7->uTextureHeight);
+    if ( !areWeLoadingTexture )
+    {
+      v7->Release();
+      pIcons_LOD->_40F9C5();
+    }
+    v8 = uSlot;
+    if ( (signed int)v11 > 0 )
+    {
+      uSlota = v11;
+      v9 = &v12->pInventoryIndices[v8];
+      do
+      {
+        if ( (signed int)v10 > 0 )
+          memset32(v9, -1 - v8, v10);
+        v9 = (char *)v9 + 56;
+        --uSlota;
+      }
+      while ( uSlota );
+    }
+    v12->pInventoryIndices[v8] = v3 + 1;
+    memcpy(&v12->pInventoryItems[v3], Src, 0x24u);
+    result = v3 + 1;
+  }
+  return result;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (0049298B) --------------------------------------------------------
+bool Player::_49298B(ItemGen *a2, int a3, int a4)
+{
+  Player *v4; // ebx@1
+  unsigned int v5; // eax@1
+  Texture *v6; // esi@1
+  void *v7; // esi@4
+  unsigned int v9; // [sp+Ch] [bp-4h]@1
+  unsigned int a2a; // [sp+18h] [bp+8h]@1
+
+  v4 = this;
+  v5 = pIcons_LOD->LoadTexture(pItemsTable->pItems[a2->uItemID].pIconName, TEXTURE_16BIT_PALETTE);
+  v6 = (Texture *)(v5 != -1 ? (int)&pIcons_LOD->pTextures[v5] : 0);
+  v9 = GetSizeInInventorySlots(v5 != -1 ? pIcons_LOD->pTextures[v5].uTextureWidth : 24);
+  a2a = GetSizeInInventorySlots(v6->uTextureHeight);
+  if ( !areWeLoadingTexture )
+  {
+    v6->Release();
+    pIcons_LOD->_40F9C5();
+  }
+  if ( (signed int)a2a > 0 )
+  {
+    v7 = &v4->pInventoryIndices[a4];
+    do
+    {
+      if ( (signed int)v9 > 0 )
+        memset32(v7, -1 - a4, v9);
+      v7 = (char *)v7 + 56;
+      --a2a;
+    }
+    while ( a2a );
+  }
+  v4->pInventoryIndices[a4] = a3 + 1;
+  return 1;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (00492A36) --------------------------------------------------------
+unsigned int Player::RemoveItemAtInventoryIndex(unsigned int uSlot)
+{
+  int *pIndices; // edi@1
+  ItemGen *v3; // ecx@1
+  unsigned int v4; // esi@1
+  unsigned int v5; // eax@1
+  Texture *v6; // esi@1
+  unsigned int result; // eax@1
+  unsigned int v8; // ebp@1
+  void *v9; // edx@4
+  unsigned int uSlota; // [sp+14h] [bp+4h]@1
+
+  pIndices = &this->pInventoryIndices[uSlot];
+  v3 = (ItemGen *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *pIndices + 5];
+  v4 = v3->uItemID;
+  v3->Reset();
+  v5 = pIcons_LOD->LoadTexture(pItemsTable->pItems[v4].pIconName, TEXTURE_16BIT_PALETTE);
+  v6 = (Texture *)(v5 != -1 ? (int)&pIcons_LOD->pTextures[v5] : 0);
+  uSlota = GetSizeInInventorySlots(v5 != -1 ? pIcons_LOD->pTextures[v5].uTextureWidth : 24);
+  result = GetSizeInInventorySlots(v6->uTextureHeight);
+  v8 = result;
+  if ( !areWeLoadingTexture )
+  {
+    v6->Release();
+    result = pIcons_LOD->_40F9C5();
+  }
+  if ( (signed int)v8 > 0 )
+  {
+    v9 = pIndices;
+    do
+    {
+      if ( (signed int)uSlota > 0 )
+      {
+        result = 0;
+        memset(v9, 0, 4 * uSlota);
+      }
+      v9 = (char *)v9 + 56;
+      --v8;
+    }
+    while ( v8 );
+  }
+  return result;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+
+//----- (00490EEE) --------------------------------------------------------
+int Player::_490EEE(ItemGen *pItem, int a3, int a4, int a5)
+{
+  int v5; // eax@1
+  int result; // eax@1
+  unsigned int v7; // edx@1
+  unsigned int v8; // ecx@1
+  signed int v9; // esi@1
+  char v10; // zf@14
+  unsigned __int8 v11; // zf@22
+  char v12; // sf@22
+  unsigned __int8 v13; // of@22
+  float *v14; // esi@26
+  float v15; // ST04_4@26
+  signed int v16; // eax@26
+  int v17; // edi@26
+  float v18; // ST04_4@30
+  signed int v19; // eax@30
+  float v20; // ST04_4@34
+  signed int v21; // eax@34
+  signed int v22; // eax@34
+  float v23; // ST04_4@37
+  signed int v24; // eax@37
+  int v26; // [sp+10h] [bp-8h]@1
+  Player *v27; // [sp+14h] [bp-4h]@1
+
+  v27 = this;
+  LOBYTE(v5) = GetActualSkillLevel(PLAYER_SKILL_MERCHANT);
+  v26 = v5;
+  result = 4;
+  v7 = pItem->uItemID;
+  v8 = pItem->uItemID;
+  v9 = pItemsTable->pItems[v8].uEquipType;
+  if ( (a3 != 4 || (signed int)v7 < 740 || (signed int)v7 > 771)
+    && ((signed int)v7 >= 600 || (signed int)v7 >= 529 && (signed int)v7 <= 599) )
+    return 5;
+  if ( a3 == 1 )
+  {
+    v13 = __OFSUB__(v9, 2);
+    v11 = v9 == 2;
+    v12 = v9 - 2 < 0;
+    goto LABEL_24;
+  }
+  if ( a3 == 2 )
+  {
+    if ( v9 < 3 )
+      return result;
+    v13 = __OFSUB__(v9, 9);
+    v11 = v9 == 9;
+    v12 = v9 - 9 < 0;
+LABEL_24:
+    if ( !((unsigned __int8)(v12 ^ v13) | v11) )
+      return result;
+    goto LABEL_16;
+  }
+  if ( a3 == 3 )
+  {
+    if ( pItemsTable->pItems[v8].uSkillType == 38 )
+      goto LABEL_16;
+    v10 = v9 == 16;
+    goto LABEL_15;
+  }
+  if ( a3 != 4 )
+    goto LABEL_26;
+  if ( v9 < 13 )
+    return result;
+  if ( v9 > 14 )
+  {
+    v10 = v9 == 17;
+LABEL_15:
+    if ( !v10 )
+      return result;
+  }
+LABEL_16:
+  if ( BYTE1(pItem->uAttributes) & 1 )
+    return 6;
+LABEL_26:
+  //v14 = &p2DEvents_minus1__20[13 * a4];
+  v14 = &p2DEvents[a4 - 1].fPriceMultiplier;
+  v15 = *v14;
+  v16 = pItem->GetValue();
+  v17 = _4B8142(v16, v15);
+  if ( a5 == 3 )
+  {
+    v23 = *v14;
+    v24 = pItem->GetValue();
+    v17 = v27->_4B8102(v24, v23);
+    if ( !(pItem->uAttributes & 2) )
+      goto LABEL_39;
+    goto LABEL_38;
+  }
+  if ( a5 == 4 )
+  {
+    v22 = v27->_4B8179(*v14);
+    goto LABEL_35;
+  }
+  if ( a5 == 5 )
+  {
+    v20 = *v14;
+    v21 = pItem->GetValue();
+    v22 = v27->_4B81C3(v21, v20);
+LABEL_35:
+    v17 = v22;
+    goto LABEL_39;
+  }
+  if ( a5 != 6 )
+    goto LABEL_39;
+  v18 = *v14;
+  v19 = pItem->GetValue();
+  v17 = v27->_4B8102(v19, v18) / 2;
+  if ( pItem->uAttributes & 2 )
+    v17 = 1;
+  if ( v17 >= 1 )
+    goto LABEL_39;
+LABEL_38:
+  v17 = 1;
+LABEL_39:
+  if ( v26 )
+    result = (v17 == pItem->GetValue()) + 2;
+  else
+    result = 1;
+  return result;
+}
+
+
+//----- (0049107D) --------------------------------------------------------
+int Player::GetBodybuilding()
+{
+  char v1; // al@1
+  int v2; // ecx@1
+  int v4; // eax@3
+  signed int v6; // [sp-4h] [bp-4h]@2
+
+  v1 = GetActualSkillLevel(PLAYER_SKILL_BODYBUILDING);
+  v2 = v1 & 0x3F;
+  if ( v1 & 0x100 )
+  {
+    v6 = 5;
+  }
+  else
+  {
+    if ( v1 >= 0 )
+    {
+      v4 = ((v1 & 0x40) != 0) + 1;
+      return v2 * v4;
+    }
+    v6 = 3;
+  }
+  v4 = v6;
+  return v2 * v4;
+}
+
+//----- (004910A8) --------------------------------------------------------
+int Player::GetMediatation()
+{
+  char v1; // al@1
+  int v2; // ecx@1
+  int v4; // eax@3
+  signed int v6; // [sp-4h] [bp-4h]@2
+
+  v1 = GetActualSkillLevel(PLAYER_SKILL_MEDITATION);
+  v2 = v1 & 0x3F;
+  if ( v1 & 0x100 )
+  {
+    v6 = 5;
+  }
+  else
+  {
+    if ( v1 >= 0 )
+    {
+      v4 = ((v1 & 0x40) != 0) + 1;
+      return v2 * v4;
+    }
+    v6 = 3;
+  }
+  v4 = v6;
+  return v2 * v4;
+}
+
+//----- (004910D3) --------------------------------------------------------
+int Player::CanIdentify(ItemGen *pItem)
+{
+  unsigned __int16 v2; // ax@1
+  unsigned __int16 v3; // bx@1
+  int uSkillMult; // eax@3
+  int v5; // edi@7
+  signed int v6; // ebp@7
+  char *v7; // esi@7
+  signed int uSkillMultiplier; // [sp-4h] [bp-14h]@2
+
+  LOBYTE(v2) = pPlayers[uActiveCharacter]->GetActualSkillLevel(PLAYER_SKILL_ITEM_ID);
+  v3 = v2;
+  if ( HIBYTE(v2) & 1 )
+  {
+    uSkillMultiplier = 5;
+  }
+  else
+  {
+    if ( (v2 & 0x80u) == 0 )
+    {
+      uSkillMult = ((v2 & 0x40) != 0) + 1;
+      goto LABEL_7;
+    }
+    uSkillMultiplier = 3;
+  }
+  uSkillMult = uSkillMultiplier;
+LABEL_7:
+  v5 = uSkillMult * (v3 & 0x3F);
+  v6 = 0;
+  v7 = (char *)&pItemsTable->pItems[pItem->uItemID].pIconName;
+  if ( CheckHiredNPCSpeciality(4u) )
+    goto LABEL_15;
+  if ( (signed int)SkillToMastery(v3) >= 4 )
+    v6 = 1;
+  if ( v5 >= (unsigned __int8)v7[46] )
+LABEL_15:
+    v6 = 1;
+  return v6;
+}
+
+//----- (00491151) --------------------------------------------------------
+int Player::CanRepair(ItemGen *a2)
+{
+  unsigned __int16 v2; // ax@1
+  unsigned __int16 v3; // bx@1
+  int v4; // eax@3
+  int v5; // edi@7
+  signed int v6; // ebp@7
+  char v8; // al@10
+  signed int v10; // [sp-4h] [bp-14h]@2
+
+  LOBYTE(v2) = GetActualSkillLevel(PLAYER_SKILL_REPAIR);
+  v3 = v2;
+  if ( HIBYTE(v2) & 1 )
+  {
+    v10 = 5;
+  }
+  else
+  {
+    if ( (v2 & 0x80u) == 0 )
+    {
+      v4 = ((v2 & 0x40) != 0) + 1;
+      goto LABEL_7;
+    }
+    v10 = 3;
+  }
+  v4 = v10;
+LABEL_7:
+  v5 = v4 * (v3 & 0x3F);
+  v6 = 0;
+  auto v7 = &pItemsTable->pItems[a2->uItemID];
+  if (CheckHiredNPCSpeciality(1) && v7->uEquipType <= 2 ||
+      CheckHiredNPCSpeciality(2) && v7->uEquipType >= 3 && v7->uEquipType <= 9 ||
+      CheckHiredNPCSpeciality(3) && v7->uEquipType >= 9 )
+    return true;
+  if ( (signed int)SkillToMastery(v3) >= 4 )
+    return true;
+  if ( v5 >= *((char *)(v7 + 1) + 2) )
+  {
+    __debugbreak(); // really odd
+    return true;
+  }
+  return false;
+}
+
+//----- (004911F3) --------------------------------------------------------
+int Player::GetMerchant()
+{
+  Player *v1; // edi@1
+  unsigned __int16 v2; // ax@1
+  unsigned __int16 v3; // bx@1
+  int v4; // esi@1
+  int v5; // edi@1
+  int v7; // eax@3
+  int v8; // ecx@7
+  signed int v9; // [sp-4h] [bp-10h]@6
+
+  v1 = this;
+  LOBYTE(v2) = GetActualSkillLevel(PLAYER_SKILL_MERCHANT);
+  v3 = v1->pActiveSkills[22];
+  v4 = v2 & 0x3F;
+  v5 = v1->pActiveSkills[22] & 0x3F;
+  if ( (signed int)SkillToMastery(v2) >= 4 )
+    return 10000;
+  v7 = GetPartyReputation();
+  if ( !v4 )
+    return -v7;
+  if ( HIBYTE(v3) & 1 )
+  {
+    v9 = 5;
+  }
+  else
+  {
+    if ( (v3 & 0x80u) == 0 )
+    {
+      v8 = ((v3 & 0x40) != 0) + 1;
+      return v5 * (v8 - 1) - v7 + v4 + 7;
+    }
+    v9 = 3;
+  }
+  v8 = v9;
+  return v5 * (v8 - 1) - v7 + v4 + 7;
+}
+
+//----- (0049125A) --------------------------------------------------------
+int Player::GetPerception()
+{
+  Player *v1; // edi@1
+  unsigned __int16 v2; // ax@1
+  unsigned __int16 v3; // bx@1
+  int v4; // esi@1
+  int v5; // edi@1
+  int v7; // eax@5
+  signed int v8; // [sp-4h] [bp-10h]@4
+
+  v1 = this;
+  LOBYTE(v2) = GetActualSkillLevel(PLAYER_SKILL_PERCEPTION);
+  v3 = v1->pActiveSkills[26];
+  v4 = v2 & 0x3F;
+  v5 = v1->pActiveSkills[26] & 0x3F;
+  if ( (signed int)SkillToMastery(v2) >= 4 )
+    return 10000;
+  if ( HIBYTE(v3) & 1 )
+  {
+    v8 = 5;
+  }
+  else
+  {
+    if ( (v3 & 0x80u) == 0 )
+    {
+      v7 = ((v3 & 0x40) != 0) + 1;
+      return v4 + v5 * (v7 - 1);
+    }
+    v8 = 3;
+  }
+  v7 = v8;
+  return v4 + v5 * (v7 - 1);
+}
+
+//----- (004912B0) --------------------------------------------------------
+int Player::GetDisarmTrap()
+{
+  Player *v1; // ebp@1
+  unsigned __int16 v2; // ax@1
+  unsigned __int16 v3; // bx@1
+  int v4; // esi@1
+  int v5; // edi@1
+  int v7; // eax@7
+  signed int v8; // [sp-4h] [bp-14h]@6
+
+  v1 = this;
+  LOBYTE(v2) = GetActualSkillLevel(PLAYER_SKILL_TRAP_DISARM);
+  v3 = v1->pActiveSkills[29];
+  v4 = v2 & 0x3F;
+  v5 = v1->pActiveSkills[29] & 0x3F;
+  if ( (signed int)SkillToMastery(v2) >= 4 )
+    return 10000;
+  if ( HasEnchantedItemEquipped(35) )
+    v4 *= 2;
+  if ( HIBYTE(v3) & 1 )
+  {
+    v8 = 5;
+  }
+  else
+  {
+    if ( (v3 & 0x80u) == 0 )
+    {
+      v7 = ((v3 & 0x40) != 0) + 1;
+      return v4 + v5 * (v7 - 1);
+    }
+    v8 = 3;
+  }
+  v7 = v8;
+  return v4 + v5 * (v7 - 1);
+}
+
+//----- (00491317) --------------------------------------------------------
+char Player::GetLearningPercent()
+{
+  Player *v1; // esi@1
+  int v2; // eax@1
+  unsigned __int16 v3; // bx@1
+  int v4; // ecx@1
+  int v5; // eax@4
+  signed int v7; // [sp-4h] [bp-Ch]@3
+
+  v1 = this;
+  LOBYTE(v2) = GetActualSkillLevel(PLAYER_SKILL_LEARNING);
+  v3 = v1->pActiveSkills[36];
+  v4 = v2 & 0x3F;
+  if ( v2 )
+  {
+    if ( HIBYTE(v3) & 1 )
+    {
+      v7 = 5;
+    }
+    else
+    {
+      if ( (v3 & 0x80u) == 0 )
+      {
+        v5 = ((v3 & 0x40) != 0) + 1;
+        goto LABEL_8;
+      }
+      v7 = 3;
+    }
+    v5 = v7;
+LABEL_8:
+    v2 = (v1->pActiveSkills[36] & 0x3F) * (v5 - 1) + v4 + 9;
+  }
+  return v2;
+}
+
+//----- (0048C6AF) --------------------------------------------------------
+Player::Player()
+{  
+  memset(&pEquipment, 0, sizeof(PlayerEquipment));
+  memset(pInventoryIndices, 0, 126 * sizeof(int));
+  for (uint i = 0; i < 126; ++i)
+    pInventoryItems[i].Reset();
+  for (uint i = 0; i < 12; ++i)
+    pEquippedItems[i].Reset();
+
+
+  for (uint i = 0; i < 24; ++i)
+  {
+    pPlayerBuffs[i].uSkill = 0;
+    pPlayerBuffs[i].uSkill = 0;
+    pPlayerBuffs[i].uPower = 0;
+    pPlayerBuffs[i].uExpireTime = 0;
+    pPlayerBuffs[i].uCaster = 0;
+    pPlayerBuffs[i].uFlags = 0;
+  }
+
+  pName[0] = 0;
+  uFace = 0;
+  uVoiceID = 0;
+  memset(pConditions, 0, 20 * sizeof(__int64));
+
+  field_BB = 0;
+
+  uMight = uMightBonus = 0;
+  uIntelligence = uIntelligenceBonus = 0;
+  uWillpower = uWillpowerBonus = 0;
+  uEndurance = uEnduranceBonus = 0;
+  uSpeed = uSpeedBonus = 0;
+  uAccuracy = uAccuracyBonus = 0;
+  uLuck = uLuckBonus = 0;
+  uLevel = sLevelModifier = 0;
+  sAgeModifier = 0;
+
+  memset(field_1F5, 0, 30);
+
+  sResFireBase = sResFireBonus = 0;
+  sResAirBase = sResAirBonus = 0;
+  sResWaterBase = sResWaterBonus = 0;
+  sResEarthBase = sResEarthBonus = 0;
+  sResMagicBase = sResMagicBonus = 0;
+  sResSpiritBase = sResSpiritBonus = 0;
+  sResMindBase = sResMindBonus = 0;
+  sResBodyBase = sResBodyBonus = 0;
+  sResLightBase = sResLightBonus = 0;
+  sResDarkBase = sResDarkBonus = 0;
+
+  uTimeToRecovery = 0;
+
+  uSkillPoints = 0;
+
+  sHealth = 0;
+  uFullHealthBonus = 0;
+  _health_related = 0;
+
+  sMana = 0;
+  uFullManaBonus = 0;
+  _mana_related = 0;
+
+  uQuickSpell = 0;
+  memset(pInstalledBeacons, 0, 5 * sizeof(LloydBeacon));
+
+  _some_attack_bonus = 0;
+  field_1A91 = 0;
+  _melee_dmg_bonus = 0;
+  field_1A93 = 0;
+  _ranged_atk_bonus = 0;
+  field_1A95 = 0;
+  _ranged_dmg_bonus = 0;
+  field_1A97 = 0;
+
+  uExpressionID = 0;
+  uExpressionTimePassed = 0;
+  uExpressionTimeLength = 0;
+
+  uNumDivineInterventionCastsThisDay = 0;
+  uNumArmageddonCasts = 0;
+  uNumFireSpikeCasts = 0;
+
+  memset(field_1988, 0, 49 * sizeof(int));
+  memset(field_1A50, 0, 64 * sizeof(char));
+
+  field_E0 = 0;
+  field_E4 = 0;
+  field_E8 = 0;
+  field_EC = 0;
+  field_F0 = 0;
+  field_F4 = 0;
+  field_F8 = 0;
+  field_FC = 0;
+  field_100 = 0;
+  field_104 = 0;
+}
+
+//----- (0048C6F6) --------------------------------------------------------
+bool Party::AddItem(ItemGen *pItem)
+{
+  unsigned int v2; // eax@1
+  unsigned int v3; // ecx@4
+  signed int v4; // edx@4
+  char *v5; // eax@8
+  unsigned int v6; // eax@10
+  Texture *v7; // ebx@10
+  signed int v8; // esi@10
+  Player *v9; // edi@11
+  int v10; // eax@11
+  bool result; // eax@15
+  std::string v12; // [sp-18h] [bp-40h]@9
+  const char *v13; // [sp-8h] [bp-30h]@9
+  int v14; // [sp-4h] [bp-2Ch]@9
+  int v15; // [sp+Ch] [bp-1Ch]@3
+  int v16; // [sp+10h] [bp-18h]@3
+  int v17; // [sp+14h] [bp-14h]@3
+  int v18; // [sp+18h] [bp-10h]@3
+  Player *v19; // [sp+1Ch] [bp-Ch]@9
+  Party *v20; // [sp+20h] [bp-8h]@1
+  int v21; // [sp+24h] [bp-4h]@10
+
+  auto thos = this;
+
+  v20 = thos;
+  v2 = pItem->uItemID;
+  if ( !BYTE2(pItemsTable->pItems[v2 + 1].uItemID) )
+    pItem->uAttributes |= 1u;
+  v15 = 0;
+  v16 = 1;
+  v18 = 3;
+  v17 = 2;
+  if ( uActiveCharacter )
+  {
+    v3 = uActiveCharacter - 1;
+    v4 = 0;
+    do
+    {
+      *(&v15 + v4++) = v3++;
+      if ( (signed int)v3 >= 4 )
+        v3 = 0;
+    }
+    while ( v4 < 4 );
+  }
+  v5 = pItemsTable->pItems[v2].pIconName;
+  if ( v5 )
+  {
+    v6 = pIcons_LOD->LoadTexture(v5, TEXTURE_16BIT_PALETTE);
+    v7 = (Texture *)(v6 != -1 ? (int)&pIcons_LOD->pTextures[v6] : 0);
+    v21 = areWeLoadingTexture;
+    v8 = 0;
+    while ( 1 )
+    {
+      v9 = &v20->pPlayers[*(&v15 + v8)];
+      v19 = &v20->pPlayers[*(&v15 + v8)];
+      v10 = v19->AddItem(0xFFFFFFFFu, pItem->uItemID);
+      if ( v10 )
+        break;
+      ++v8;
+      if ( v8 >= 4 )
+      {
+        if ( !v21 )
+        {
+          v7->Release();
+          pIcons_LOD->_40F9C5();
+        }
+        goto LABEL_15;
+      }
+    }
+    memcpy(&v9->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5], pItem, 0x24u);
+    pItem->Reset();
+    pAudioPlayer->PlaySound(SOUND_GoldReceived, 0, 0, -1, 0, 0, 0, 0);
+    v19->PlaySound(60, 0);
+    if ( !v21 )
+    {
+      v7->Release();
+      pIcons_LOD->_40F9C5();
+    }
+    result = 1;
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"Invalid picture_name detected ::addItem()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Party.cpp:795", 0);
+LABEL_15:
+    result = 0;
+  }
+  return result;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (0048C855) --------------------------------------------------------
+int Player::GetBaseStrength()
+{
+  return this->uMight + GetItemsBonus(CHARACTER_ATTRIBUTE_STRENGTH, 0);
+}
+
+//----- (0048C86C) --------------------------------------------------------
+int Player::GetBaseIntelligence()
+{
+  return this->uIntelligence + GetItemsBonus(CHARACTER_ATTRIBUTE_INTELLIGENCE, 0);
+}
+
+//----- (0048C883) --------------------------------------------------------
+int Player::GetBaseWillpower()
+{
+  return this->uWillpower + GetItemsBonus(CHARACTER_ATTRIBUTE_WILLPOWER, 0);
+}
+
+//----- (0048C89A) --------------------------------------------------------
+int Player::GetBaseEndurance()
+{
+  return this->uEndurance + GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0);
+}
+
+//----- (0048C8B1) --------------------------------------------------------
+int Player::GetBaseAccuracy()
+{
+  return this->uAccuracy + GetItemsBonus(CHARACTER_ATTRIBUTE_ACCURACY, 0);
+}
+
+//----- (0048C8C8) --------------------------------------------------------
+int Player::GetBaseSpeed()
+{
+  return this->uSpeed + GetItemsBonus(CHARACTER_ATTRIBUTE_SPEED, 0);
+}
+
+//----- (0048C8DF) --------------------------------------------------------
+int Player::GetBaseLuck()
+{
+  return this->uLuck + GetItemsBonus(CHARACTER_ATTRIBUTE_LUCK, 0);
+}
+
+//----- (0048C8F6) --------------------------------------------------------
+int Player::GetBaseLevel()
+{
+  return this->uLevel + GetItemsBonus(CHARACTER_ATTRIBUTE_LEVEL, 0);
+}
+
+//----- (0048C90D) --------------------------------------------------------
+int Player::GetActualLevel()
+{
+  return uLevel + sLevelModifier +
+         GetMagicalBonus(CHARACTER_ATTRIBUTE_LEVEL) +
+         GetItemsBonus(CHARACTER_ATTRIBUTE_LEVEL, 0);
+}
+
+//----- (0048C93C) --------------------------------------------------------
+int Player::GetActualMight()
+{
+  Player *v1; // esi@1
+  unsigned int v2; // eax@1
+  signed int v3; // ecx@1
+  signed int v4; // ebx@4
+  int v5; // edi@5
+  int v6; // ST14_4@5
+
+  v1 = this;
+  v2 = this->sAgeModifier + GetBaseAge();
+  v3 = 0;
+  while ( (signed int)v2 >= (signed int)pAgeingTable[v3] )
+  {
+    ++v3;
+    if ( v3 >= 4 )
+    {
+      v4 = 100;
+      goto LABEL_5;
+    }
+  }
+  v4 = pAgeingStrengthMultiplier[v3];
+LABEL_5:
+  v5 = pConditionStrengthMultiplier[GetMajorConditionIdx()];
+  v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_STRENGTH, 0);
+  return v5 * v4 * v1->uMight / 100 / 100 + GetMagicalBonus((CHARACTER_ATTRIBUTE_TYPE)0) + v6 + v1->uMightBonus;
+}
+
+//----- (0048C9C2) --------------------------------------------------------
+int Player::GetActualIntelligence()
+{
+  Player *v1; // esi@1
+  unsigned int sAge; // eax@1
+  signed int uAgeLevel; // ecx@1
+  signed int v4; // ebx@4
+  int v5; // edi@5
+  int v6; // ebp@5
+
+  v1 = this;
+  sAge = this->sAgeModifier + GetBaseAge();
+  uAgeLevel = 0;
+  while ( (signed int)sAge >= (signed int)pAgeingTable[uAgeLevel] )
+  {
+    ++uAgeLevel;
+    if ( uAgeLevel >= 4 )
+    {
+      v4 = 100;
+      goto LABEL_5;
+    }
+  }
+  v4 = pAgeingIntelligenceMultiplier[uAgeLevel];
+LABEL_5:
+  v5 = pConditionIntelligenceMultiplier[GetMajorConditionIdx()];
+  v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_INTELLIGENCE, 0);
+  return v5 * v4 * v1->uIntelligence / 100 / 100
+       + GetMagicalBonus(CHARACTER_ATTRIBUTE_INTELLIGENCE)
+       + v6
+       + v1->uIntelligenceBonus;
+}
+
+//----- (0048CA3F) --------------------------------------------------------
+int Player::GetActualWillpower()
+{
+  int v5; // edi@5
+  
+  uint uActualAge = GetBaseAge() + sAgeModifier;
+  uint uAgeingMultiplier = 100;
+  for (uint i = 0; i < 4; ++i)
+    if (uActualAge >= pAgeingTable[i])
+      uAgeingMultiplier = pAgeingWillpowerMultiplier[i];
+    else break;
+
+  v5 = pConditionWillpowerMultiplier[GetMajorConditionIdx()];
+  return v5 * uAgeingMultiplier * uWillpower / 100 / 100
+       + GetMagicalBonus(CHARACTER_ATTRIBUTE_WILLPOWER)
+       + GetItemsBonus(CHARACTER_ATTRIBUTE_WILLPOWER, 0)
+       + uWillpowerBonus;
+}
+
+//----- (0048CABC) --------------------------------------------------------
+int Player::GetActualEndurance()
+{
+  int v6; // ebp@5
+
+  uint uActualAge = GetBaseAge() + sAgeModifier;
+  uint uAgeingMultiplier = 100;
+  for (uint i = 0; i < 4; ++i)
+    if (uActualAge >= pAgeingTable[i])
+      uAgeingMultiplier = pAgeingEnduranceMultiplier[i];
+    else break;
+
+  auto uConditionMult = pConditionEnduranceMultiplier[GetMajorConditionIdx()];
+  auto uItemBonus = GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0);
+  return uConditionMult * uAgeingMultiplier * uEndurance / 100 / 100
+       + GetMagicalBonus(CHARACTER_ATTRIBUTE_ENDURANCE)
+       + uItemBonus
+       + uEnduranceBonus;
+}
+
+//----- (0048CB39) --------------------------------------------------------
+int Player::GetActualAccuracy()
+{
+  Player *v1; // esi@1
+  unsigned int v2; // eax@1
+  signed int v3; // ecx@1
+  signed int v4; // ebx@4
+  int v5; // edi@5
+  int v6; // ebp@5
+
+  v1 = this;
+  v2 = this->sAgeModifier + GetBaseAge();
+  v3 = 0;
+  while ( (signed int)v2 >= (signed int)pAgeingTable[v3] )
+  {
+    ++v3;
+    if ( v3 >= 4 )
+    {
+      v4 = 100;
+      goto LABEL_5;
+    }
+  }
+  v4 = pAgeingAccuracyMultiplier[v3];
+LABEL_5:
+  v5 = pConditionAccuracyMultiplier[GetMajorConditionIdx()];
+  v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_ACCURACY, 0);
+  return v5 * v4 * v1->uAccuracy / 100 / 100
+       + GetMagicalBonus(CHARACTER_ATTRIBUTE_ACCURACY)
+       + v6
+       + v1->uAccuracyBonus;
+}
+
+//----- (0048CBB6) --------------------------------------------------------
+int Player::GetActualSpeed()
+{
+  Player *v1; // esi@1
+  unsigned int v2; // eax@1
+  signed int v3; // ecx@1
+  signed int v4; // ebx@4
+  int v5; // edi@5
+  int v6; // ebp@5
+
+  v1 = this;
+  v2 = this->sAgeModifier + GetBaseAge();
+  v3 = 0;
+  while ( (signed int)v2 >= (signed int)pAgeingTable[v3] )
+  {
+    ++v3;
+    if ( v3 >= 4 )
+    {
+      v4 = 100;
+      goto LABEL_5;
+    }
+  }
+  v4 = pAgeingSpeedMultiplier[v3];
+LABEL_5:
+  v5 = pConditionSpeedMultiplier[GetMajorConditionIdx()];
+  v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_SPEED, 0);
+  return v5 * v4 * v1->uSpeed / 100 / 100
+       + GetMagicalBonus(CHARACTER_ATTRIBUTE_SPEED)
+       + v6
+       + v1->uSpeedBonus;
+}
+
+//----- (0048CC33) --------------------------------------------------------
+int Player::GetActualLuck()
+{
+  Player *v1; // esi@1
+  unsigned int v2; // eax@7
+  signed int v3; // ecx@7
+  signed int v4; // ebx@10
+  int v5; // edi@11
+  int v6; // ebp@11
+  signed int v8; // [sp+10h] [bp-4h]@1
+
+  v8 = 0;
+  v1 = this;
+  if ( CheckHiredNPCSpeciality(0x1Bu) )
+    v8 = 5;
+  if ( CheckHiredNPCSpeciality(0x1Cu) )
+    v8 += 20;
+  if ( CheckHiredNPCSpeciality(0x2Fu) )
+    v8 += 10;
+  v2 = v1->sAgeModifier + GetBaseAge();
+  v3 = 0;
+  while ( (signed int)v2 >= (signed int)pAgeingTable[v3] )
+  {
+    ++v3;
+    if ( v3 >= 4 )
+    {
+      v4 = 100;
+      goto LABEL_11;
+    }
+  }
+  v4 = pAgeingLuckMultiplier[v3];
+LABEL_11:
+  v5 = pConditionLuckMultiplier[GetMajorConditionIdx()];
+  v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_LUCK, 0);
+  return GetMagicalBonus(CHARACTER_ATTRIBUTE_LUCK)
+       + v6
+       + v8
+       + v5 * v4 * v1->uLuck / 100 / 100
+       + v1->uLuckBonus;
+}
+
+//----- (0048CCF5) --------------------------------------------------------
+int Player::GetActualAttack(int a2)
+{
+  Player *v2; // esi@1
+  int v3; // eax@1
+  int v4; // edi@1
+  int v5; // ebx@1
+  int v6; // ebp@1
+
+  v2 = this;
+  v3 = GetActualAccuracy();
+  v4 = _48EA1B_get_static_effect(v3);
+  v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_ATTACK);
+  v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_ATTACK, a2);
+  return v4 + v5 + v6 + GetMagicalBonus(CHARACTER_ATTRIBUTE_ATTACK) + v2->_some_attack_bonus;
+}
+
+//----- (0048CD45) --------------------------------------------------------
+int Player::GetMeleeDamageMinimal()
+{
+  Player *v1; // edi@1
+  int v2; // eax@1
+  int v3; // esi@1
+  int v4; // esi@1
+  int v5; // esi@1
+  int v6; // esi@1
+  signed int result; // eax@1
+
+  v1 = this;
+  v2 = GetActualMight();
+  v3 = _48EA1B_get_static_effect(v2);
+  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN, 0) + v3;
+  v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v4;
+  v6 = v1->_melee_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v5;
+  result = 1;
+  if ( v6 >= 1 )
+    result = v6;
+  return result;
+}
+
+//----- (0048CD90) --------------------------------------------------------
+int Player::GetMeleeDamageMaximal()
+{
+  Player *v1; // edi@1
+  int v2; // eax@1
+  int v3; // esi@1
+  int v4; // esi@1
+  int v5; // esi@1
+  int v6; // esi@1
+  signed int result; // eax@1
+
+  v1 = this;
+  v2 = GetActualMight();
+  v3 = _48EA1B_get_static_effect(v2);
+  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX, 0) + v3;
+  v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v4;
+  v6 = v1->_melee_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v5;
+  result = 1;
+  if ( v6 >= 1 )
+    result = v6;
+  return result;
+}
+
+//----- (0048CDDB) --------------------------------------------------------
+int Player::CalculateMeleeDamageTo(int a2, int a3, unsigned int uTargetActorID)
+{
+  int v4; // esi@1
+  Player *v5; // edi@1
+  ItemGen *v6; // ebx@4
+  unsigned int v7; // ebp@4
+  unsigned int v8; // esi@4
+  int v9; // eax@4
+  int v10; // eax@9
+  char v11; // zf@9
+  int v12; // esi@10
+  int v13; // eax@11
+  enum MONSTER_SUPERTYPE v14; // edx@24
+  ItemGen *v15; // ebx@35
+  unsigned int v16; // ebp@35
+  unsigned int v17; // esi@35
+  int v18; // edx@38
+  int v19; // eax@40
+  enum MONSTER_SUPERTYPE v20; // edx@53
+  int v21; // esi@62
+  int v22; // eax@63
+  int v23; // ebx@63
+  int v24; // ebx@63
+  signed int result; // eax@64
+  MONSTER_SUPERTYPE v26; // [sp-4h] [bp-24h]@20
+  MONSTER_SUPERTYPE v27; // [sp-4h] [bp-24h]@49
+  int v28; // [sp+10h] [bp-10h]@1
+  int v29; // [sp+10h] [bp-10h]@33
+  signed int v30; // [sp+14h] [bp-Ch]@7
+  signed int v31; // [sp+14h] [bp-Ch]@36
+  int v32; // [sp+18h] [bp-8h]@1
+  int v33; // [sp+18h] [bp-8h]@8
+  int v34; // [sp+1Ch] [bp-4h]@1
+  int v35; // [sp+28h] [bp+8h]@37
+
+  v4 = 0;
+  v5 = this;
+  v34 = 0;
+  v32 = 0;
+  v28 = 0;
+  if ( IsUnarmed() == 1 )
+  {
+    v32 = rand() % 3 + 1;
+LABEL_61:
+    v34 = v4;
+    goto LABEL_62;
+  }
+  if ( HasItemEquipped(EQUIP_TWO_HANDED) )
+  {
+    v6 = (ItemGen *)&v5->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v5->pEquipment.uMainHand + 5];
+    v7 = v6->uItemID;
+    v8 = v6->uItemID;
+    v9 = pItemsTable->pItems[v8].uDamageDice;
+    if ( pItemsTable->pItems[v8].uSkillType == PLAYER_SKILL_SPEAR && !v5->pEquipment.uOffHand )
+      ++v9;
+    v30 = pItemsTable->pItems[v8].uDamageRoll;
+    if ( v9 > 0 )
+    {
+      v33 = v9;
+      do
+      {
+        v10 = rand();
+        v11 = v33-- == 1;
+        v28 += v10 % v30 + 1;
+      }
+      while ( !v11 );
+    }
+    v12 = pItemsTable->pItems[v8].uDamageMod + v28;
+    if ( !uTargetActorID )
+      goto LABEL_28;
+    v13 = v6->uAdditionalValue;
+    if ( v13 == 64 || v7 == 507 || v7 == 508 || v7 == 527 )
+    {
+      v14 = (MONSTER_SUPERTYPE)1;
+    }
+    else
+    {
+      if ( v13 == 39 )
+      {
+        v26 = MONSTER_SUPERTYPE_KREEGAN;
+      }
+      else
+      {
+        if ( v13 == 40 )
+        {
+          v26 = MONSTER_SUPERTYPE_DRAGON;
+        }
+        else
+        {
+          if ( v13 == 63 || v7 == 517 )
+          {
+            v26 = MONSTER_SUPERTYPE_ELF;
+          }
+          else
+          {
+            if ( v13 != 65 )
+            {
+LABEL_28:
+              if ( (signed int)SkillToMastery(v5->pActiveSkills[2]) >= 3
+                && pItemsTable->pItems[v6->uItemID].uSkillType == 2
+                && rand() % 100 < 10 )
+                v12 *= 3;
+              v32 = v12;
+              goto LABEL_33;
+            }
+            v26 = MONSTER_SUPERTYPE_TITAN;
+          }
+        }
+      }
+      v14 = v26;
+    }
+    if ( MonsterStats::BelongsToSupertype(uTargetActorID, v14) )
+      v12 *= 2;
+    goto LABEL_28;
+  }
+LABEL_33:
+  v29 = 0;
+  if ( !a3 )
+  {
+    if ( v5->HasItemEquipped((ITEM_EQUIP_TYPE)0) )
+    {
+      v15 = (ItemGen *)&v5->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v5->pEquipment.uOffHand + 5];
+      v16 = v15->uItemID;
+      v17 = v15->uItemID;
+      if ( pItemsTable->pItems[v17].uEquipType != 4 )
+      {
+        v31 = pItemsTable->pItems[v17].uDamageRoll;
+        if ( (signed int)pItemsTable->pItems[v17].uDamageDice > 0 )
+        {
+          v35 = pItemsTable->pItems[v17].uDamageDice;
+          do
+          {
+            v18 = rand() % v31;
+            v11 = v35-- == 1;
+            v29 += v18 + 1;
+          }
+          while ( !v11 );
+        }
+        v4 = pItemsTable->pItems[v17].uDamageMod + v29;
+        if ( !uTargetActorID )
+          goto LABEL_57;
+        v19 = v15->uAdditionalValue;
+        if ( v19 == 64 || v16 == 507 || v16 == 508 || v16 == 527 )
+        {
+          v20 = (MONSTER_SUPERTYPE)1;
+        }
+        else
+        {
+          if ( v19 == 39 )
+          {
+            v27 = MONSTER_SUPERTYPE_KREEGAN;
+          }
+          else
+          {
+            if ( v19 == 40 )
+            {
+              v27 = MONSTER_SUPERTYPE_DRAGON;
+            }
+            else
+            {
+              if ( v19 == 63 || v16 == 517 )
+              {
+                v27 = MONSTER_SUPERTYPE_ELF;
+              }
+              else
+              {
+                if ( v19 != 65 )
+                {
+LABEL_57:
+                  if ( pItemsTable->pItems[v15->uItemID].uSkillType == PLAYER_SKILL_DAGGER
+                    && SkillToMastery(v5->pActiveSkills[2] >= 3u)
+                    && rand() % 100 < 10 )
+                    v4 *= 3;
+                  goto LABEL_61;
+                }
+                v27 = MONSTER_SUPERTYPE_TITAN;
+              }
+            }
+          }
+          v20 = v27;
+        }
+        if ( MonsterStats::BelongsToSupertype(uTargetActorID, v20) )
+          v4 *= 2;
+        goto LABEL_57;
+      }
+    }
+  }
+LABEL_62:
+  v21 = v32 + v34;
+  if ( !a2 )
+  {
+    v22 = GetActualMight();
+    v23 = _48EA1B_get_static_effect(v22);
+    v24 = GetSkillBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v23;
+    v21 += v5->_melee_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v24;
+  }
+  result = 1;
+  if ( v21 >= 1 )
+    result = v21;
+  return result;
+}
+
+//----- (0048D0B9) --------------------------------------------------------
+int Player::GetRangedAttack()
+{
+  Player *v1; // esi@1
+  int v2; // eax@1
+  int v3; // edi@3
+  int v4; // eax@4
+  int v5; // edi@4
+  int v6; // edi@4
+  int v7; // edi@4
+
+  v1 = this;
+  v2 = *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
+  if ( v2 < 64 || v2 > 65 )
+  {
+    v4 = GetActualAccuracy();
+    v5 = _48EA1B_get_static_effect(v4);
+    v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_ATTACK, 0) + v5;
+    v7 = GetSkillBonus(CHARACTER_ATTRIBUTE_RANGED_ATTACK) + v6;
+    v3 = v1->_ranged_atk_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_RANGED_ATTACK) + v7;
+  }
+  else
+  {
+    v3 = GetActualAttack(1);
+  }
+  return v3;
+}
+
+//----- (0048D124) --------------------------------------------------------
+int Player::GetRangedDamageMin()
+{
+  Player *v1; // esi@1
+  int v2; // edi@1
+  int v3; // edi@1
+  int v4; // edi@1
+  unsigned __int16 v5; // ax@1
+  int result; // eax@6
+
+  v1 = this;
+  v2 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_DAMAGE_MIN, 0);
+  v3 = GetSkillBonus(CHARACTER_ATTRIBUTE_RANGED_DAMAGE_BONUS) + v2;
+  v4 = v1->_ranged_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_RANGED_DAMAGE_BONUS) + v3;
+  v5 = v1->pActiveSkills[5];
+  if ( v5 && (signed int)SkillToMastery(v5) >= 4 && HasItemEquipped(EQUIP_BOW) )
+    v4 += v1->pActiveSkills[5] & 0x3F;
+  if ( v4 >= 1 )
+    result = v4;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0048D191) --------------------------------------------------------
+int Player::GetRangedDamageMax()
+{
+  Player *v1; // esi@1
+  int v2; // edi@1
+  int v3; // edi@1
+  int v4; // edi@1
+  unsigned __int16 v5; // ax@1
+  int result; // eax@6
+
+  v1 = this;
+  v2 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_DAMAGE_MAX, 0);
+  v3 = GetSkillBonus(CHARACTER_ATTRIBUTE_RANGED_DAMAGE_BONUS) + v2;
+  v4 = v1->_ranged_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_RANGED_DAMAGE_BONUS) + v3;
+  v5 = v1->pActiveSkills[5];
+  if ( v5 && (signed int)SkillToMastery(v5) >= 4 && HasItemEquipped(EQUIP_BOW) )
+    v4 += v1->pActiveSkills[5] & 0x3F;
+  if ( v4 >= 1 )
+    result = v4;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0048D1FE) --------------------------------------------------------
+bool Player::CalculateRangedDamageTo(int a2)
+{
+  Player *v2; // ebx@1
+  bool result; // eax@1
+  ItemGen *v4; // ebx@2
+  unsigned int v5; // edi@2
+  unsigned int v6; // esi@2
+  int v7; // edx@4
+  char v8; // zf@4
+  int v9; // esi@5
+  int v10; // ebx@6
+  enum MONSTER_SUPERTYPE v11; // edx@7
+  unsigned __int16 v12; // ax@19
+  MONSTER_SUPERTYPE v13; // [sp-Ch] [bp-20h]@13
+  Player *v14; // [sp+4h] [bp-10h]@1
+  signed int v15; // [sp+8h] [bp-Ch]@2
+  int v16; // [sp+Ch] [bp-8h]@3
+  int v17; // [sp+10h] [bp-4h]@1
+
+  v17 = 0;
+  v2 = this;
+  v14 = this;
+  result = HasItemEquipped(EQUIP_BOW);
+  if ( !result )
+    return result;
+  v4 = (ItemGen *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2->pEquipment.uBow + 5];
+  v5 = v4->uItemID;
+  v6 = v4->uItemID;
+  v15 = pItemsTable->pItems[v6].uDamageRoll;
+  if ( (signed int)pItemsTable->pItems[v6].uDamageDice > 0 )
+  {
+    v16 = pItemsTable->pItems[v6].uDamageDice;
+    do
+    {
+      v7 = rand() % v15;
+      v8 = v16-- == 1;
+      v17 += v7 + 1;
+    }
+    while ( !v8 );
+  }
+  v9 = pItemsTable->pItems[v6].uDamageMod + v17;
+  if ( a2 )
+  {
+    v10 = v4->uAdditionalValue;
+    if ( v10 == 64 )
+    {
+      v11 = (MONSTER_SUPERTYPE)1;
+      goto LABEL_17;
+    }
+    if ( v10 == 39 || v5 == 508 )
+    {
+      v13 = MONSTER_SUPERTYPE_KREEGAN;
+      goto LABEL_16;
+    }
+    if ( v10 == 40 )
+    {
+      v13 = MONSTER_SUPERTYPE_DRAGON;
+      goto LABEL_16;
+    }
+    if ( v10 == 63 || v5 == 517 )
+    {
+      v13 = MONSTER_SUPERTYPE_ELF;
+LABEL_16:
+      v11 = v13;
+LABEL_17:
+      if ( MonsterStats::BelongsToSupertype(a2, v11) )
+        v9 *= 2;
+      goto LABEL_19;
+    }
+  }
+LABEL_19:
+  v12 = v14->pActiveSkills[5];
+  if ( v12 )
+  {
+    if ( (signed int)SkillToMastery(v12) >= 4 )
+      v9 += v14->pActiveSkills[5] & 0x3F;
+  }
+  return v9;
+}
+
+//----- (0048D2EA) --------------------------------------------------------
+char *Player::GetMeleeDamageString()
+{
+  Player *v1; // esi@1
+  signed int v2; // eax@1
+  signed int v3; // edi@3
+  signed int v4; // eax@3
+  signed int v5; // ST0C_4@6
+  char *v6; // edi@6
+  signed int v7; // ST08_4@7
+  unsigned int v8; // eax@8
+  signed int v9; // esi@9
+
+  static char player__getmeleedamagestring_static_buff[40]; // idb
+
+  v1 = this;
+  v2 = *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
+  if ( v2 < 64 || v2 > 65 )
+  {
+    v3 = GetMeleeDamageMinimal();
+    v4 = GetMeleeDamageMaximal();
+  }
+  else
+  {
+    v3 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN, 0);
+    v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX, 0);
+  }
+  if ( v3 == v4 )
+  {
+    v5 = v3;
+    v6 = player__getmeleedamagestring_static_buff;
+    sprintf(player__getmeleedamagestring_static_buff, "%d", v5);
+  }
+  else
+  {
+    v7 = v3;
+    v6 = player__getmeleedamagestring_static_buff;
+    sprintf(player__getmeleedamagestring_static_buff, "%d - %d", v7, v4);
+  }
+  v8 = v1->pEquipment.uMainHand;
+  if ( v8 )
+  {
+    v9 = *(int *)&v1->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
+    if ( v9 >= 135 )
+    {
+      if ( v9 <= 159 )
+        strcpy(v6, pGlobalTXT_LocalizationStrings[595]);
+    }
+  }
+  return v6;
+}
+
+//----- (0048D396) --------------------------------------------------------
+char *Player::GetRangedDamageString()
+{
+  Player *v1; // esi@1
+  signed int v2; // eax@1
+  int v3; // edi@3
+  int v4; // eax@3
+  char *v5; // edi@6
+  int v6; // ST0C_4@8
+  int v7; // ST08_4@9
+  unsigned int v8; // eax@10
+  signed int v9; // esi@11
+  
+  static char player__getrangeddamagestring_static_buff[40]; // idb
+
+  v1 = this;
+  v2 = *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
+  if ( v2 < 64 || v2 > 65 )
+  {
+    v3 = GetRangedDamageMin();
+    v4 = GetRangedDamageMax();
+  }
+  else
+  {
+    v3 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN, 1);
+    v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX, 1);
+  }
+  if ( v4 )
+  {
+    if ( v3 == v4 )
+    {
+      v6 = v3;
+      v5 = player__getrangeddamagestring_static_buff;
+      sprintf(player__getrangeddamagestring_static_buff, "%d", v6);
+    }
+    else
+    {
+      v7 = v3;
+      v5 = player__getrangeddamagestring_static_buff;
+      sprintf(player__getrangeddamagestring_static_buff, "%d - %d", v7, v4);
+    }
+  }
+  else
+  {
+    v5 = player__getrangeddamagestring_static_buff;
+    strcpy(player__getrangeddamagestring_static_buff, "N/A");
+  }
+  v8 = v1->pEquipment.uMainHand;
+  if ( v8 )
+  {
+    v9 = *(int *)&v1->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
+    if ( v9 >= 135 )
+    {
+      if ( v9 <= 159 )
+        strcpy(v5, pGlobalTXT_LocalizationStrings[595]);
+    }
+  }
+  return v5;
+}
+
+//----- (0048D45A) --------------------------------------------------------
+bool Player::CanTrainToNextLevel()
+{
+  int v1; // edx@1
+  int v2; // eax@1
+  int i; // esi@1
+
+  v1 = this->uLevel;
+  v2 = 0;
+  for ( i = 0; i < v1; ++i )
+    v2 += i + 1;
+  return (signed __int64)this->uExperience >= 1000 * v2;
+}
+
+//----- (0048D498) --------------------------------------------------------
+unsigned int Player::GetExperienceDisplayColor()
+{
+  unsigned int result; // eax@2
+
+  if ( CanTrainToNextLevel() )
+    result = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0);
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0048D4B3) --------------------------------------------------------
+int Player::CalculateIncommingDamage(int resistance, signed int type)
+{
+  Player *v3; // esi@1
+  int v4; // edi@8
+  int v6; // eax@21
+  signed int v7; // ebx@21
+  int v8; // eax@22
+  signed int v9; // ebx@22
+  int v10; // eax@23
+  signed int v11; // ebx@23
+  int v12; // eax@24
+  signed int v13; // edi@24
+  unsigned int v14; // eax@27
+  int v15; // eax@29
+  double v16; // st7@32
+  enum CHARACTER_ATTRIBUTE_TYPE v17; // [sp-4h] [bp-10h]@9
+  signed int v18; // [sp+8h] [bp-4h]@17
+
+  v3 = this;
+  if ( !resistance )
+  {
+    v17 = (CHARACTER_ATTRIBUTE_TYPE)10;
+    goto LABEL_16;
+  }
+  if ( resistance == 1 )
+  {
+    v17 = (CHARACTER_ATTRIBUTE_TYPE)11;
+    goto LABEL_16;
+  }
+  if ( resistance == 2 )
+  {
+    v17 = (CHARACTER_ATTRIBUTE_TYPE)12;
+    goto LABEL_16;
+  }
+  if ( resistance == 3 )
+  {
+    v17 = (CHARACTER_ATTRIBUTE_TYPE)13;
+    goto LABEL_16;
+  }
+  if ( resistance == 6 )
+  {
+    v17 = (CHARACTER_ATTRIBUTE_TYPE)33;
+    goto LABEL_16;
+  }
+  if ( resistance == 7 )
+  {
+    v17 = (CHARACTER_ATTRIBUTE_TYPE)14;
+    goto LABEL_16;
+  }
+  if ( resistance == 8 )
+  {
+    v17 = (CHARACTER_ATTRIBUTE_TYPE)15;
+LABEL_16:
+    v4 = GetActualResistance(v17);
+    goto LABEL_17;
+  }
+  v4 = 0;
+LABEL_17:
+  v18 = type;
+  if ( v3->uClass == 35 && v4 >= 200 )
+    return 0;
+  if ( v4 )
+  {
+    v6 = GetActualLuck();
+    v7 = _48EA1B_get_static_effect(v6) + v4 + 30;
+    if ( rand() % v7 >= 30 )
+    {
+      v18 = type >> 1;
+      v8 = GetActualLuck();
+      v9 = _48EA1B_get_static_effect(v8) + v4 + 30;
+      if ( rand() % v9 >= 30 )
+      {
+        v18 = type >> 2;
+        v10 = GetActualLuck();
+        v11 = _48EA1B_get_static_effect(v10) + v4 + 30;
+        if ( rand() % v11 >= 30 )
+        {
+          v18 = type >> 3;
+          v12 = GetActualLuck();
+          v13 = _48EA1B_get_static_effect(v12) + v4 + 30;
+          if ( rand() % v13 >= 30 )
+            v18 = type >> 4;
+        }
+      }
+    }
+  }
+  if ( resistance == 4 )
+  {
+    v14 = v3->pEquipment.uBody;
+    if ( v14 )
+    {
+      if ( !(v3->field_1F5[36 * v14 + 15] & 2) )
+      {
+        v15 = GetEquippedItemSkillType(EQUIP_ARMOUR) - 10;
+        if ( v15 )
+        {
+          if ( v15 != 1 || (signed int)SkillToMastery(v3->pActiveSkills[11]) < 3 )
+            return v18;
+          v16 = (double)v18 * 0.5;
+          return (signed __int64)v16;
+        }
+        if ( (signed int)SkillToMastery(v3->pActiveSkills[10]) >= 4 )
+        {
+          v16 = (double)v18 * 0.66670001;
+          return (signed __int64)v16;
+        }
+      }
+    }
+  }
+  return v18;
+}
+
+//----- (0048D62C) --------------------------------------------------------
+int Player::GetEquippedItemEquipType(unsigned int uEquipSlot)
+{
+  return pItemsTable->pItems[*(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36
+                                                                             * *(&this->pEquipment.uOffHand
+                                                                               + uEquipSlot)
+                                                                             + 5]].uEquipType;
+}
+
+//----- (0048D651) --------------------------------------------------------
+int Player::GetEquippedItemSkillType(enum ITEM_EQUIP_TYPE uEquipSlot)
+{
+  return pItemsTable->pItems[*(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36
+                                                                             * *(&this->pEquipment.uOffHand
+                                                                               + uEquipSlot)
+                                                                             + 5]].uSkillType;
+}
+
+//----- (0048D676) --------------------------------------------------------
+bool Player::IsUnarmed()
+{
+  return HasItemEquipped(EQUIP_TWO_HANDED) != 1
+      && (HasItemEquipped(EQUIP_ONE_OR_TWO_HANDS) != 1
+       || GetEquippedItemEquipType(0) == EQUIP_SHIELD);
+}
+
+//----- (0048D6AA) --------------------------------------------------------
+bool Player::HasItemEquipped(ITEM_EQUIP_TYPE uEquipIndex)
+{
+  auto i = pEquipment.pIndices[uEquipIndex];
+  if (i)
+    return ~pInventoryItems[i - 1].uAttributes & 0x02;
+  else return false;
+}
+
+//----- (0048D6D0) --------------------------------------------------------
+bool Player::HasEnchantedItemEquipped(int uEnchantment)
+{
+  for (uint i = 0; i < 16; ++i)
+  {
+    if (HasItemEquipped((ITEM_EQUIP_TYPE)i) &&
+      pInventoryItems[i].uAdditionalValue == uEnchantment)
+      //  *(int *)&this->field_1F6[36 * pEquipment[i] + 6] != uEnchantment)
+      return true;
+  }
+  return false;
+}
+
+//----- (0048D709) --------------------------------------------------------
+bool Player::WearsItem(int a1, signed int a2)
+{
+  int v3; // edx@2
+  Player *v4; // ecx@2
+  int v6; // esi@5
+  int v7; // edx@6
+
+  if ( a2 >= 16 )
+  {
+    v6 = 0;
+    while ( !HasItemEquipped((ITEM_EQUIP_TYPE)v6)
+         || *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v7 + 5] != a1 )
+    {
+      ++v6;
+      if ( (signed int)v6 >= 16 )
+        return 0;
+    }
+    return 1;
+  }
+  if ( HasItemEquipped((ITEM_EQUIP_TYPE)a2)
+    && *(int *)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(&v4->pEquipment.uOffHand + v3) + 5] == a1 )
+    return 1;
+  return 0;
+}
+
+//----- (0048D76C) --------------------------------------------------------
+bool Player::StealFromShop(ItemGen *a2, int a3, int a4, int a5, int *a6)
+{
+  unsigned __int16 v6; // cx@8
+  int v7; // edi@8
+  unsigned int v8; // ebx@8
+  unsigned int v9; // esi@8
+  int v10; // eax@8
+  int v11; // edi@12
+  bool result; // eax@13
+
+  if ( !a2
+    || this->pConditions[16]
+    || this->pConditions[14]
+    || this->pConditions[15]
+    || this->pConditions[4]
+    || this->pConditions[13]
+    || this->pConditions[2] )
+  {
+    result = 0;
+  }
+  else
+  {
+    v6 = this->pActiveSkills[34];
+    v7 = v6 & 0x3F;
+    v8 = SkillToMastery(v6);
+    v9 = a2->GetValue();
+    v10 = pItemsTable->pItems[a2->uItemID].uEquipType;
+    if ( !pItemsTable->pItems[a2->uItemID].uEquipType || v10 == 1 || v10 == 2 )
+      v9 *= 3;
+    v11 = dword_4EDEB4[rand() % 100 / 20] + v7 * dword_4EDEA0[v8];
+    *a6 = 100 * (a4 + a3) + v9 + (a5 != 0 ? 0x1F4 : 0);
+    if ( rand() % 100 >= 5 )
+    {
+      if ( *a6 > v11 )
+        result = *a6 - v11 < 500;
+      else
+        result = 2;
+    }
+    else
+    {
+      result = 0;
+    }
+  }
+  return result;
+}
+// 4EDEA0: using guessed type int dword_4EDEA0[];
+// 4EDEB4: using guessed type int dword_4EDEB4[];
+
+//----- (0048D88B) --------------------------------------------------------
+int Player::StealFromActor(unsigned int uActorID, int _steal_perm, int reputation)
+{
+  Player *v4; // esi@1
+  Actor *v5; // edi@1
+  unsigned __int16 v6; // cx@10
+  int v7; // ebx@10
+  unsigned int v8; // esi@10
+  int v9; // eax@10
+  int v10; // esi@10
+  int v11; // eax@13
+  signed int v12; // ebx@15
+  signed int v13; // edx@15
+  int v14; // ecx@15
+  unsigned __int16 v15; // si@21
+  unsigned int v16; // ebx@24
+  int v17; // esi@24
+  const void *v18; // eax@29
+  unsigned int v19; // esi@31
+  int v20; // eax@34
+  char v21; // zf@36
+  unsigned int v22; // ST0C_4@39
+  char *v23; // esi@39
+  const char *v25; // [sp-Ch] [bp-48h]@40
+  int v26; // [sp-8h] [bp-44h]@40
+  ItemGen v27; // [sp+8h] [bp-34h]@15
+  unsigned int v28; // [sp+2Ch] [bp-10h]@10
+  int v29; // [sp+30h] [bp-Ch]@10
+  int v30; // [sp+34h] [bp-8h]@10
+  Player *v31; // [sp+38h] [bp-4h]@1
+  signed int _steal_perma; // [sp+48h] [bp+Ch]@12
+
+  v4 = this;
+  v5 = &pActors[uActorID];
+  v31 = this;
+  if ( &pActors[uActorID]
+    && !this->pConditions[16]
+    && !this->pConditions[14]
+    && !this->pConditions[15]
+    && !this->pConditions[4]
+    && !this->pConditions[13]
+    && !this->pConditions[2] )
+  {
+    if ( !(BYTE2(v5->uAttributes) & 0x80) )
+      pActors[uActorID].SetRandomGoldIfTheresNoItem();
+    v6 = v4->pActiveSkills[34];
+    v7 = v6 & 0x3F;
+    v8 = SkillToMastery(v6);
+    v9 = rand();
+    v28 = 4 * v8;
+    v30 = dword_4EDEA0[v8];
+    v29 = dword_4EDEB4[v9 % 100 / 20];
+    v10 = v5->pMonsterInfo.uLevel + 100 * (_steal_perm + reputation);
+    if ( rand() % 100 < 5 || v10 > v29 + v7 * v30 || (_steal_perma = 2, BYTE2(v5->uAttributes) & 8) )
+    {
+      Actor::_43AC45(uActorID, 1);
+      _steal_perma = 0;
+      v26 = (int)v31->pName;
+      v25 = pGlobalTXT_LocalizationStrings[376];
+    }
+    else
+    {
+      v11 = rand();
+      if ( v11 % 100 >= 40 )
+      {
+        if ( v11 % 100 >= 70 )
+        {
+          v19 = 0;
+          if ( v7 > 0 )
+          {
+            do
+            {
+              --v7;
+              v19 += rand() % dword_4EDEC4[v28 / 4] + 1;
+            }
+            while ( v7 );
+          }
+          if ( pItemsTable->pItems[v5->array_000234[3].uItemID].uEquipType != 18 )
+            return _steal_perma;
+          v20 = (int)&v5->array_000234[3].uAdditionalValue;
+          if ( (signed int)v19 > v5->array_000234[3].uAdditionalValue )
+            v19 = v5->array_000234[3].uAdditionalValue;
+          v21 = *(int *)v20 == v19;
+          *(int *)v20 -= v19;
+          if ( v21 )
+            v5->array_000234[3].uItemID = 0;
+          if ( v19 )
+          {
+            party_finds_gold(v19, 2);
+            v22 = v19;
+            v23 = pTmpBuf2;
+            sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[302], v31->pName, v22);
+LABEL_43:
+            ShowStatusBarString(v23, 2u);
+            return _steal_perma;
+          }
+        }
+        else
+        {
+          v27.Reset();
+          v12 = 0;
+          v13 = 0;
+          v14 = (int)v5->array_000234;
+          while ( !*(int *)v14 || pItemsTable->pItems[*(int *)v14].uEquipType == 18 )
+          {
+            ++v13;
+            v14 += 36;
+            if ( v13 >= 4 )
+              goto LABEL_21;
+          }
+          v12 = 1;
+LABEL_21:
+          v15 = v5->uCarriedItemID;
+          if ( v15 || v12 )
+          {
+            v27.Reset();
+            if ( v15 )
+            {
+              v16 = (signed __int16)v15;
+              v5->uCarriedItemID = 0;
+              v27.uItemID = (signed __int16)v15;
+              v17 = (signed __int16)v15;
+              if ( pItemsTable->pItems[v17].uEquipType == 12 )
+                v27.uNumCharges = rand() % 6 + pItemsTable->pItems[v17].uDamageMod + 1;
+              if ( pItemsTable->pItems[v17].uEquipType == 14 )
+              {
+                if ( v16 != 220 )
+                  v27._bonus_type = 2 * rand() % 4 + 2;
+              }
+            }
+            else
+            {
+              v18 = &v5->array_000234[rand() % 4];
+              memcpy(&v27, v18, sizeof(v27));
+              ((ItemGen *)v18)->Reset();
+              v16 = v27.uItemID;
+            }
+            sub_421B2C_PlaceInInventory_or_DropPickedItem();
+            sprintf(
+              pTmpBuf2,
+              pGlobalTXT_LocalizationStrings[304],
+              v31->pName,
+              pItemsTable->pItems[v16].pUnidentifiedName);
+            ShowStatusBarString(pTmpBuf2, 2u);
+            sub_421B2C_PlaceInInventory_or_DropPickedItem();
+            memcpy(&pParty->pPickedItem, &v27, sizeof(pParty->pPickedItem));
+            pMouse->SetCursorBitmapFromItemID(v16);
+            return _steal_perma;
+          }
+        }
+      }
+      v26 = (int)v31->pName;
+      v25 = pGlobalTXT_LocalizationStrings[377];
+    }
+    v23 = pTmpBuf2;
+    sprintf(pTmpBuf2, v25, v26);
+    goto LABEL_43;
+  }
+  return 0;
+}
+// 4EDEA0: using guessed type int dword_4EDEA0[];
+// 4EDEB4: using guessed type int dword_4EDEB4[];
+// 4EDEC4: using guessed type int dword_4EDEC4[];
+
+//----- (0048DBB9) --------------------------------------------------------
+void Player::Heal(int amount)
+{
+  Player *v2; // esi@1
+  signed int v3; // eax@3
+
+  v2 = this;
+  if ( !this->pConditions[16] && !this->pConditions[14] )
+  {
+    v3 = GetMaxHealth();
+    if ( v2->pConditions[17] )
+      v3 /= 2;
+    v2->sHealth += amount;
+    if ( v2->sHealth > v3 )
+      v2->sHealth = v3;
+    if ( v2->pConditions[13] )
+    {
+      if ( v2->sHealth > 0 )
+      {
+        LODWORD(v2->pConditions[13]) = 0;
+        HIDWORD(v2->pConditions[13]) = 0;
+      }
+    }
+  }
+}
+
+//----- (0048DC1E) --------------------------------------------------------
+int Player::ReceiveDamage(signed int type, int resistance)
+{
+  Player *v3; // esi@1
+  signed int v4; // eax@1
+  int v5; // eax@1
+  bool v6; // ebx@1
+  unsigned int v7; // eax@8
+  char *v8; // ecx@9
+  int v9; // eax@9
+  signed int typea; // [sp+14h] [bp+8h]@1
+
+  v3 = this;
+  this->pConditions[2] = 0i64;
+  v4 = CalculateIncommingDamage(resistance, type);
+  v3->sHealth -= v4;
+  typea = v4;
+  v5 = v3->sHealth;
+  v6 = v5 < -10;
+  LOBYTE(v6) = v5 <= -10;
+  if ( v5 < 1 )
+  {
+    if ( v3->sHealth + v3->uEndurance + GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0) >= 1
+      || (signed __int64)v3->pPlayerBuffs[11].uExpireTime > 0 )
+    {
+      SetCondition(0xDu, 0);
+    }
+    else
+    {
+      SetCondition(0xEu, 0);
+      v6 = LODWORD(pParty->uTimePlayed);
+      if ( v3->sHealth > 0 )
+        v3->sHealth = 0;
+    }
+    if ( v6 )
+    {
+      v7 = v3->pEquipment.uBody;
+      if ( v7 )
+      {
+        v8 = &v3->field_1F5[36 * v7 + 15];
+        v9 = *(int *)v8;
+        if ( !(BYTE1(v9) & 2) )
+        {
+          LOBYTE(v9) = v9 | 2;
+          *(int *)v8 = v9;
+        }
+      }
+    }
+  }
+  if ( typea && CanAct() )
+    PlaySound(24, 0);
+  return typea;
+}
+
+//----- (0048DCF6) --------------------------------------------------------
+int Player::_48DCF6(int a2, Actor *pActor)
+{
+  signed int v3; // edi@1
+  signed int v4; // ebx@1
+  Player *v5; // esi@1
+  int v6; // eax@2
+  int v7; // eax@5
+  int v8; // eax@8
+  int v9; // ebx@8
+  int v10; // eax@8
+  int v11; // ebx@8
+  signed int v12; // edx@9
+  ItemGen *v13; // eax@9
+  int v14; // edx@16
+  unsigned int v15; // edx@17
+  int v16; // edx@26
+  unsigned int v17; // edx@27
+  Player *v18; // ecx@32
+  signed int v19; // edx@38
+  int *v20; // ecx@38
+  signed int v21; // eax@40
+  int v22; // eax@49
+  signed int v23; // ebx@49
+  unsigned int v24; // eax@60
+  int v25; // ecx@61
+  int v26; // ebx@74
+  void *v27; // ecx@76
+  unsigned int v28; // ebx@78
+  signed int result; // eax@86
+  SoundID v30; // [sp-20h] [bp-C0h]@56
+  signed int v31; // [sp-1Ch] [bp-BCh]@56
+  unsigned int v32; // [sp-18h] [bp-B8h]@56
+  signed int v33; // [sp-14h] [bp-B4h]@56
+  signed int v34; // [sp-10h] [bp-B0h]@56
+  int v35; // [sp-Ch] [bp-ACh]@56
+  unsigned int v36; // [sp-8h] [bp-A8h]@51
+  unsigned int v37; // [sp-8h] [bp-A8h]@56
+  unsigned int v38; // [sp-8h] [bp-A8h]@57
+  unsigned int v39; // [sp-8h] [bp-A8h]@68
+  enum CHARACTER_ATTRIBUTE_TYPE v40; // [sp-4h] [bp-A4h]@4
+  int v41; // [sp-4h] [bp-A4h]@51
+  int v42; // [sp-4h] [bp-A4h]@56
+  int v43; // [sp-4h] [bp-A4h]@57
+  signed int v44; // [sp-4h] [bp-A4h]@59
+  int v45; // [sp-4h] [bp-A4h]@68
+  char v46[140]; // [sp+Ch] [bp-94h]@13
+  unsigned int v47; // [sp+98h] [bp-8h]@1
+  int v48; // [sp+9Ch] [bp-4h]@1
+
+  v3 = 0;
+  v4 = 0;
+  v5 = this;
+  v47 = 0;
+  v48 = 0;
+  switch ( a2 )
+  {
+    case 1:
+      v6 = GetActualWillpower();
+      goto LABEL_46;
+    case 2:
+    case 3:
+    case 4:
+    case 9:
+    case 10:
+    case 11:
+    case 13:
+    case 21:
+      v6 = GetActualEndurance();
+      goto LABEL_46;
+    case 5:
+    case 12:
+    case 23:
+      v40 = (CHARACTER_ATTRIBUTE_TYPE)14;
+      goto LABEL_5;
+    case 15:
+      v40 = (CHARACTER_ATTRIBUTE_TYPE)13;
+      goto LABEL_5;
+    case 6:
+    case 7:
+    case 8:
+    case 14:
+    case 16:
+      v40 = (CHARACTER_ATTRIBUTE_TYPE)15;
+LABEL_5:
+      v7 = GetActualResistance(v40);
+      goto LABEL_47;
+    case 22:
+      v8 = GetActualWillpower();
+      v9 = _48EA1B_get_static_effect(v8);
+      v10 = GetActualIntelligence();
+      v11 = (_48EA1B_get_static_effect(v10) + v9) >> 1;
+      break;
+    case 17:
+      v12 = 0;
+      v13 = this->pInventoryItems;
+      do
+      {
+        if ( (signed int)v13->uItemID > 0 && (signed int)v13->uItemID <= 134 && !(v13->uAttributes & 2) )
+          v46[v4++] = v12;
+        ++v12;
+        ++v13;
+      }
+      while ( v12 < 138 );
+      goto LABEL_36;
+    case 18:
+      v14 = 0;
+      do
+      {
+        if ( HasItemEquipped((ITEM_EQUIP_TYPE)v14) )
+        {
+          if ( v15 == 3 )
+            v46[v4++] = LOBYTE(v5->pEquipment.uBody) - 1;
+          if ( (!v15 || v15 == 1) && GetEquippedItemEquipType(v15) == 4 )
+            v46[v4++] = *((char *)&v5->pEquipment.uOffHand + 4 * v15) - 1;
+        }
+        v14 = v15 + 1;
+      }
+      while ( v14 < 16 );
+      goto LABEL_36;
+    case 19:
+      v16 = 0;
+      do
+      {
+        if ( HasItemEquipped((ITEM_EQUIP_TYPE)v16) )
+        {
+          if ( v17 == 2 )
+            v46[v4++] = LOBYTE(v5->pEquipment.uBow) - 1;
+          if ( (!v17 || v17 == 1)
+            && (!GetEquippedItemEquipType(v17) || GetEquippedItemEquipType(v17) == 1) )
+            v46[v4++] = *((char *)&v5->pEquipment.uOffHand + 4 * v17) - 1;
+        }
+        v16 = v17 + 1;
+      }
+      while ( v16 < 16 );
+LABEL_36:
+      if ( !v4 )
+        goto LABEL_87;
+      v48 = (int)&v5->pInventoryItems[(unsigned __int8)v46[rand() % v4]];
+      v11 = 3 * (pItemsTable->pItems[*(int *)v48].uMaterial + pItemsTable->pItems[*(int *)v48].uDamageMod);
+      break;
+    case 20:
+      v19 = 0;
+      v20 = this->pInventoryIndices;
+      do
+      {
+        if ( *v20 > 0 )
+        {
+          v21 = *(int *)&v5->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *v20 + 5];
+          if ( v21 > 0 )
+          {
+            if ( v21 <= 134 )
+              v46[v4++] = v19;
+          }
+        }
+        ++v19;
+        ++v20;
+      }
+      while ( v19 < 126 );
+      if ( !v4 )
+        goto LABEL_87;
+      v47 = (unsigned __int8)v46[rand() % v4];
+      v6 = GetActualAccuracy();
+LABEL_46:
+      v7 = _48EA1B_get_static_effect(v6);
+LABEL_47:
+      v11 = v7;
+      break;
+    default:
+      v11 = 0;
+      break;
+  }
+  v22 = GetActualLuck();
+  v23 = _48EA1B_get_static_effect(v22) + v11 + 30;
+  if ( rand() % v23 >= 30 )
+  {
+LABEL_87:
+    result = 0;
+  }
+  else
+  {
+    switch ( a2 )
+    {
+      case 1:
+        v41 = 1;
+        v36 = 0;
+        goto LABEL_56;
+      case 2:
+        v41 = 1;
+        v36 = 1;
+        goto LABEL_56;
+      case 3:
+        v41 = 1;
+        v36 = 2;
+        goto LABEL_56;
+      case 23:
+        v41 = 1;
+        v36 = 3;
+        goto LABEL_56;
+      case 4:
+        v41 = 1;
+        v36 = 4;
+LABEL_56:
+        SetCondition(v36, v41);
+        v42 = 0;
+        v37 = 0;
+        v35 = 0;
+        v34 = 0;
+        v33 = -1;
+        v32 = 0;
+        v31 = 0;
+        v30 = (SoundID)221;
+        goto LABEL_83;
+      case 5:
+        v43 = 1;
+        v38 = 5;
+        goto LABEL_70;
+      case 6:
+      case 7:
+      case 8:
+        if ( a2 == 6 )
+        {
+          v44 = 6;
+          goto LABEL_60;
+        }
+        v25 = 2 * (a2 != 8) + 8;
+        goto LABEL_65;
+      case 9:
+        if ( a2 == 6 )
+        {
+          v44 = 7;
+LABEL_60:
+          v24 = v44;
+        }
+        else
+        {
+          v25 = 2 * (a2 != 8) + 9;
+LABEL_65:
+          v24 = v25;
+        }
+        SetCondition(v24, 1);
+        v42 = 0;
+        v37 = 0;
+        v35 = 0;
+        v34 = 0;
+        v33 = -1;
+        v32 = 0;
+        v31 = 0;
+        v30 = (SoundID)222;
+LABEL_83:
+        pAudioPlayer->PlaySound(v30, v31, v32, v33, v34, v35, v37, v42);
+        do
+        {
+LABEL_84:
+          if ( v5 == pPlayers[v3 + 1] )
+            break;
+          ++v3;
+        }
+        while ( v3 < 4 );
+        pGame->pStru6Instance->SetPlayerBuffAnim(0x99u, v3);
+        result = 1;
+        break;
+      case 12:
+        v43 = 1;
+        v38 = 12;
+        goto LABEL_70;
+      case 15:
+        v45 = 1;
+        v39 = 15;
+        goto LABEL_73;
+      case 13:
+        v43 = 1;
+        v38 = 13;
+LABEL_70:
+        SetCondition(v38, v43);
+        v42 = 0;
+        v37 = 0;
+        v35 = 0;
+        v34 = 0;
+        v33 = -1;
+        v32 = 0;
+        v31 = 0;
+        v30 = (SoundID)224;
+        goto LABEL_83;
+      case 14:
+        v45 = 1;
+        v39 = 14;
+        goto LABEL_73;
+      case 16:
+        v45 = 1;
+        v39 = 16;
+LABEL_73:
+        SetCondition(v39, v45);
+        v42 = 0;
+        v37 = 0;
+        v35 = 0;
+        v34 = 0;
+        v33 = -1;
+        v32 = 0;
+        v31 = 0;
+        v30 = (SoundID)225;
+        goto LABEL_83;
+      case 17:
+      case 18:
+      case 19:
+        v26 = v48;
+        if ( *(char *)(v48 + 21) & 2 )
+          goto LABEL_84;
+        PlaySound(40, 0);
+        *(int *)(v26 + 20) |= 2u;
+        goto LABEL_79;
+      case 20:
+        PlaySound(40, 0);
+        v27 = pActor->array_000234;
+        if ( pActor->array_000234[0].uItemID )
+        {
+          v27 = &pActor->array_000234[1];
+          if ( pActor->array_000234[1].uItemID )
+            goto LABEL_84;
+        }
+        v28 = v47;
+        memcpy(v27, &v5->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v5->pInventoryIndices[v47] + 5], 0x24u);
+        RemoveItemAtInventoryIndex(v28);
+LABEL_79:
+        v42 = 0;
+        v37 = 0;
+        v35 = 0;
+        v34 = 0;
+        v33 = -1;
+        v32 = 0;
+        v31 = 0;
+        v30 = (SoundID)47;
+        goto LABEL_83;
+      case 21:
+        PlaySound(42, 0);
+        ++v5->sAgeModifier;
+        goto LABEL_82;
+      case 22:
+        PlaySound(41, 0);
+        v5->sMana = 0;
+LABEL_82:
+        v42 = 0;
+        v37 = 0;
+        v35 = 0;
+        v34 = 0;
+        v33 = -1;
+        v32 = 0;
+        v31 = 0;
+        v30 = (SoundID)226;
+        goto LABEL_83;
+      default:
+        goto LABEL_87;
+    }
+  }
+  return result;
+}
+// 48DCF6: using guessed type char var_94[140];
+
+//----- (0048E1A3) --------------------------------------------------------
+unsigned int Player::GetSpellSchool(unsigned int uSpellID)
+{
+  return LOBYTE(pSpellStats->pInfos[uSpellID].uSchool);
+}
+
+//----- (0048E1B5) --------------------------------------------------------
+int Player::GetAttackRecoveryTime(int a2)
+{
+  unsigned int v2; // ebx@1
+  char *v3; // edi@1
+  Player *v4; // esi@1
+  int v5; // eax@3
+  int v6; // eax@3
+  int v7; // eax@6
+  int v8; // eax@9
+  int v9; // eax@9
+  int v10; // eax@10
+  int v11; // edx@13
+  int v12; // ecx@14
+  int v13; // eax@15
+  int v14; // ebx@18
+  int v15; // eax@18
+  double v16; // st7@21
+  double v17; // st7@22
+  unsigned __int16 v18; // cx@27
+  Player *v19; // ecx@28
+  int v20; // eax@30
+  int v21; // eax@30
+  int v22; // eax@30
+  int v23; // ecx@30
+  unsigned int v24; // eax@30
+  int v25; // eax@31
+  int v26; // ebx@32
+  int v27; // eax@32
+  unsigned __int16 *v28; // ebx@36
+  int v29; // eax@42
+  int v30; // edi@43
+  signed int v31; // eax@49
+  int v32; // ecx@50
+  int result; // eax@54
+  float v34; // [sp+8h] [bp-38h]@27
+  float v35; // [sp+Ch] [bp-34h]@18
+  float v36; // [sp+10h] [bp-30h]@21
+  float v37; // [sp+14h] [bp-2Ch]@21
+  float v38; // [sp+18h] [bp-28h]@27
+  int v39; // [sp+1Ch] [bp-24h]@31
+  int v40; // [sp+20h] [bp-20h]@1
+  int v41; // [sp+24h] [bp-1Ch]@1
+  unsigned int v42; // [sp+28h] [bp-18h]@14
+  int v43; // [sp+2Ch] [bp-14h]@1
+  int v44; // [sp+30h] [bp-10h]@1
+  int v45; // [sp+34h] [bp-Ch]@1
+  int v46; // [sp+38h] [bp-8h]@1
+  int v47; // [sp+3Ch] [bp-4h]@1
+
+  v2 = 0;
+  v3 = 0;
+  v4 = this;
+  v47 = (unsigned __int16)word_4EDED8[0];
+  v43 = 0;
+  v45 = 0;
+  v40 = 0;
+  v41 = 0;
+  v44 = 0;
+  v46 = 0;
+  if ( a2 )
+  {
+    if ( !HasItemEquipped(EQUIP_BOW) )
+      goto LABEL_17;
+    v5 = (int)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uBow + 5];
+    v46 = v5;
+    v3 = (char *)&pItemsTable->pItems[*(int *)v5].pIconName;
+    v6 = (unsigned __int16)word_4EDED8[(unsigned __int8)v3[29]];
+    goto LABEL_4;
+  }
+  if ( IsUnarmed() == 1 )
+  {
+    LOBYTE(v7) = GetActualSkillLevel(PLAYER_SKILL_UNARMED);
+    if ( v7 )
+    {
+      v6 = (unsigned __int16)word_4EDED8[1];
+LABEL_4:
+      v47 = v6;
+      goto LABEL_17;
+    }
+  }
+  if ( HasItemEquipped(EQUIP_TWO_HANDED) )
+  {
+    v8 = (int)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uMainHand + 5];
+    v46 = v8;
+    v9 = *(int *)v8;
+    v3 = (char *)&pItemsTable->pItems[v9].pIconName;
+    if ( v3[28] == 12 )
+      v10 = *(&pSpellDatas[0].field_A + 10 * *((int *)&pSpellDatas[66].field_8 + v9));
+    else
+      v10 = (unsigned __int16)word_4EDED8[(unsigned __int8)v3[29]];
+    v47 = v10;
+  }
+  if ( HasItemEquipped((ITEM_EQUIP_TYPE)0) )
+  {
+    v12 = (int)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uOffHand + 5];
+    v42 = (unsigned __int16)word_4EDED8[pItemsTable->pItems[*(int *)v12].uSkillType];
+    if ( (signed int)v42 > v47 )
+    {
+      v13 = *(int *)v12;
+      v46 = v12;
+      v3 = (char *)(v11 + 48 * v13);
+      v47 = v42;
+    }
+    v2 = 0;
+  }
+LABEL_17:
+  if ( HasItemEquipped(EQUIP_ARMOUR) )
+  {
+    v14 = pItemsTable->pItems[*(int *)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uBody + 5]].uSkillType;
+    SkillToMastery(v4->pActiveSkills[9]);
+    v15 = (unsigned __int16)word_4EDED8[v14];
+    v35 = 1.0;
+    v43 = v15;
+    if ( v14 == 9 )
+    {
+      v36 = 0.0;
+    }
+    else
+    {
+      if ( v14 != 10 )
+      {
+        if ( v14 != 11 )
+        {
+          v36 = 1.0;
+          v37 = 1.0;
+          v16 = 1.0;
+LABEL_27:
+          v18 = v4->pActiveSkills[v14];
+          v38 = v16;
+          v43 = (signed __int64)((double)v43 * *(&v34 + SkillToMastery(v18)));
+          v2 = 0;
+          goto LABEL_28;
+        }
+        v17 = 0.5;
+        v36 = 0.5;
+LABEL_26:
+        v37 = v17;
+        v16 = 0.0;
+        goto LABEL_27;
+      }
+      v36 = 0.5;
+    }
+    v17 = 0.0;
+    goto LABEL_26;
+  }
+LABEL_28:
+  if ( HasItemEquipped((ITEM_EQUIP_TYPE)v2) && v19->GetEquippedItemEquipType(v2) == 4 )
+  {
+    v20 = 9 * v4->pEquipment.uOffHand;
+    v35 = 1.0;
+    v21 = 3 * *(int *)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * v20 + 5];
+    v36 = 0.0;
+    v22 = pItemsTable->pItems[16 * v21 / 0x30u].uSkillType;
+    v37 = 0.0;
+    v23 = (unsigned __int16)word_4EDED8[v22];
+    v38 = 0.0;
+    v45 = v23;
+    v24 = SkillToMastery(v4->pActiveSkills[v22]);
+    v45 = (signed __int64)((double)v45 * *(&v34 + v24));
+  }
+  v25 = GetActualSpeed();
+  v39 = _48EA1B_get_static_effect(v25);
+  v42 = v2;
+  if ( v3 != (char *)v2 )
+  {
+    v26 = (unsigned __int8)v3[29];
+    LOBYTE(v27) = GetActualSkillLevel((enum PLAYER_SKILL_TYPE)(unsigned __int8)v3[29]);
+    if ( v27 && (v26 == 1 || v26 == 3 || v26 == 5) )
+    {
+      v28 = &v4->pActiveSkills[v26];
+      if ( (signed int)SkillToMastery(*v28) >= 2 )
+        v40 = *(char *)v28 & 0x3F;
+    }
+    v2 = 0;
+    if ( v3[29] == 7 )
+      v42 = 1;
+  }
+  if ( a2 == v2 )
+  {
+    if ( v42 == v2 )
+    {
+      LOBYTE(v29) = GetActualSkillLevel(PLAYER_SKILL_ARMSMASTER);
+      if ( v29 != v2 )
+      {
+        v30 = v29 & 0x3F;
+        v44 = v29 & 0x3F;
+        if ( (signed int)SkillToMastery(v29) >= 4 )
+          v44 += v30;
+      }
+    }
+  }
+  if ( SHIDWORD(v4->pPlayerBuffs[7].uExpireTime) >= (signed int)v2
+    && (SHIDWORD(v4->pPlayerBuffs[7].uExpireTime) > (signed int)v2 || LODWORD(v4->pPlayerBuffs[7].uExpireTime) > v2) )
+    v41 = 25;
+  v31 = 0;
+  if ( v46 != v2 )
+  {
+    v32 = *(int *)(v46 + 12);
+    if ( v32 == 59 || v32 == 41 || *(int *)v46 == 500 )
+      v31 = 20;
+  }
+  result = v47 + v43 + v45 - v44 - v31 - v41 - v40 - v39;
+  if ( result < 0 )
+    result = 0;
+  return result;
+}
+
+//----- (0048E4F8) --------------------------------------------------------
+int Player::GetMaxHealth()
+{
+  int v3; // esi@1
+  int v4; // esi@1
+  int v6; // esi@1
+
+  v3 = _48EA1B_get_static_effect(GetActualEndurance());
+  v4 = pBaseHealthPerLevelByClass[uClass] * (GetActualLevel() + v3);
+  v6 = uFullHealthBonus
+     + pBaseHealthByClass[uClass / 4]
+     + GetSkillBonus(CHARACTER_ATTRIBUTE_HEALTH)
+     + GetItemsBonus(CHARACTER_ATTRIBUTE_HEALTH, 0) + v4;
+  if (v6 <= 0)
+    return 1;
+  return v6;
+}
+
+//----- (0048E565) --------------------------------------------------------
+int Player::GetMaxMana()
+{
+  int v2; // eax@2
+  int v3; // esi@4
+  int v4; // eax@5
+  int v5; // esi@5
+  int v6; // eax@5
+  int v7; // esi@6
+  int v8; // esi@6
+  int v9; // esi@6
+  int result; // eax@7
+
+  switch (uClass)
+  {
+    case 5u:
+    case 6u:
+    case 7u:
+    case 0x10u:
+    case 0x11u:
+    case 0x12u:
+    case 0x13u:
+    case 0x20u:
+    case 0x21u:
+    case 0x22u:
+    case 0x23u:
+      v2 = GetActualIntelligence();
+      v3 = _48EA1B_get_static_effect(v2);
+      goto LABEL_6;
+    case 9u:
+    case 0xAu:
+    case 0xBu:
+    case 0xCu:
+    case 0xDu:
+    case 0xEu:
+    case 0xFu:
+    case 0x18u:
+    case 0x19u:
+    case 0x1Au:
+    case 0x1Bu:
+      v2 = GetActualWillpower();
+      v3 = _48EA1B_get_static_effect(v2);
+      goto LABEL_6;
+    case 0x15u:
+    case 0x16u:
+    case 0x17u:
+    case 0x1Cu:
+    case 0x1Du:
+    case 0x1Eu:
+    case 0x1Fu:
+      v4 = GetActualWillpower();
+      v5 = _48EA1B_get_static_effect(v4);
+      v6 = GetActualIntelligence();
+      v3 = _48EA1B_get_static_effect(v6) + v5;
+LABEL_6:
+      v7 = pBaseManaPerLevelByClass[uClass] * (GetActualLevel() + v3);
+      v8 = GetItemsBonus(CHARACTER_ATTRIBUTE_MANA, 0) + v7;
+      v9 = uFullManaBonus
+         + pBaseManaByClass[uClass / 4]
+         + GetSkillBonus(CHARACTER_ATTRIBUTE_MANA)
+         + v8;
+      if ( v9 < 1 )
+        goto LABEL_7;
+      result = v9;
+      break;
+    default:
+LABEL_7:
+      result = 0;
+      break;
+  }
+  return result;
+}
+
+//----- (0048E656) --------------------------------------------------------
+int Player::GetBaseAC()
+{
+  Player *v1; // edi@1
+  int v2; // eax@1
+  int v3; // esi@1
+  int v4; // esi@1
+  int v5; // esi@1
+  int result; // eax@2
+
+  v1 = this;
+  v2 = GetActualSpeed();
+  v3 = _48EA1B_get_static_effect(v2);
+  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_AC_BONUS, 0) + v3;
+  v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v4;
+  if ( v5 >= 1 )
+    result = v5;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0048E68F) --------------------------------------------------------
+int Player::GetActualAC()
+{
+  Player *v1; // edi@1
+  int v2; // eax@1
+  int v3; // esi@1
+  int v4; // esi@1
+  int v5; // esi@1
+  int v6; // esi@1
+  int result; // eax@2
+
+  v1 = this;
+  v2 = GetActualSpeed();
+  v3 = _48EA1B_get_static_effect(v2);
+  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_AC_BONUS, 0) + v3;
+  v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v4;
+  v6 = v1->sACModifier + GetMagicalBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v5;
+  if ( v6 >= 1 )
+    result = v6;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0048E6DC) --------------------------------------------------------
+unsigned int Player::GetBaseAge()
+{
+  return ((__int64)(pParty->uTimePlayed * 0.234375) / 60 / 60 / 24) / 7 / 4 / 12
+       - uBirthYear + 1168;
+}
+
+//----- (0048E72C) --------------------------------------------------------
+unsigned int Player::GetActualAge()
+{
+  return this->sAgeModifier + GetBaseAge();
+}
+
+//----- (0048E73F) --------------------------------------------------------
+int Player::GetBaseResistance(enum CHARACTER_ATTRIBUTE_TYPE a2)
+{
+  Player *v2; // ebx@1
+  signed int v3; // esi@1
+  enum CHARACTER_RACE v4; // eax@1
+  signed int v5; // edi@8
+  char v6; // zf@9
+  int v7; // esi@20
+  int result; // eax@21
+  signed int v9; // [sp-4h] [bp-10h]@11
+
+  v2 = this;
+  v3 = 0;
+  v4 = GetRace();
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_FIRE )
+  {
+    v5 = 0;
+    goto LABEL_16;
+  }
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_AIR )
+  {
+    v5 = 1;
+LABEL_16:
+    v6 = v4 == 2;
+    goto LABEL_17;
+  }
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_WATER )
+  {
+    v6 = v4 == 3;
+    v5 = 2;
+    goto LABEL_17;
+  }
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_EARTH )
+  {
+    v5 = 3;
+    v6 = v4 == 3;
+    goto LABEL_17;
+  }
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_MIND )
+  {
+    v5 = 7;
+    if ( v4 != 1 )
+      goto LABEL_20;
+    v9 = 10;
+LABEL_19:
+    v3 = v9;
+    goto LABEL_20;
+  }
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_BODY || a2 == 33 )
+  {
+    v5 = 8;
+    v6 = v4 == 0;
+LABEL_17:
+    if ( !v6 )
+      goto LABEL_20;
+    v9 = 5;
+    goto LABEL_19;
+  }
+  v5 = 0;
+LABEL_20:
+  v7 = GetItemsBonus(a2, 0) + v3;
+  if ( v2->uClass != 35 || (result = 200, v7 + *(&v2->sResFireBase + v5) <= 200) )
+    result = v7 + *(&v2->sResFireBase + v5);
+  return result;
+}
+
+//----- (0048E7D0) --------------------------------------------------------
+int Player::GetActualResistance(enum CHARACTER_ATTRIBUTE_TYPE a2)
+{
+  signed int v2; // edi@1
+  Player *v3; // esi@1
+  enum CHARACTER_RACE v4; // ebx@1
+  Player *v5; // ecx@8
+  char v6; // zf@18
+  int v7; // ebx@28
+  int result; // eax@28
+  signed int v9; // [sp+10h] [bp-8h]@1
+  signed int v10; // [sp+14h] [bp-4h]@1
+
+  v2 = 0;
+  v3 = this;
+  v10 = 0;
+  v9 = 0;
+  v4 = GetRace();
+  if ( CheckHiredNPCSpeciality(0x25u) )
+    v10 = 20;
+  if ( (a2 == CHARACTER_ATTRIBUTE_RESIST_FIRE
+     || a2 == CHARACTER_ATTRIBUTE_RESIST_AIR
+     || a2 == CHARACTER_ATTRIBUTE_RESIST_WATER
+     || a2 == CHARACTER_ATTRIBUTE_RESIST_EARTH)
+    && SkillToMastery(v3->pActiveSkills[9]) == 4
+    && HasItemEquipped(EQUIP_ARMOUR)
+    && GetEquippedItemSkillType(EQUIP_ARMOUR) == PLAYER_SKILL_LEATHER )
+    v10 += v3->pActiveSkills[9] & 0x3F;
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_FIRE )
+    goto LABEL_25;
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_AIR )
+  {
+    v2 = 1;
+LABEL_25:
+    v6 = v4 == 2;
+LABEL_26:
+    if ( v6 )
+      v9 = 5;
+    goto LABEL_28;
+  }
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_WATER )
+  {
+    v6 = v4 == 3;
+    v2 = 2;
+    goto LABEL_26;
+  }
+  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_EARTH )
+  {
+    v2 = 3;
+    if ( v4 == 3 )
+      v10 += 5;
+  }
+  else
+  {
+    if ( a2 != CHARACTER_ATTRIBUTE_RESIST_MIND )
+    {
+      if ( a2 != CHARACTER_ATTRIBUTE_RESIST_BODY && a2 != 33 )
+        goto LABEL_28;
+      v2 = 8;
+      v6 = v4 == 0;
+      goto LABEL_26;
+    }
+    v2 = 7;
+    if ( v4 == 1 )
+      v9 = 10;
+  }
+LABEL_28:
+  v7 = GetItemsBonus(a2, 0);
+  result = v10 + GetMagicalBonus(a2) + v7 + v9 + *(&v3->sResFireBonus + v2) + *(&v3->sResFireBase + v2);
+  if ( v3->uClass == 35 )
+  {
+    if ( result > 200 )
+      result = 200;
+  }
+  return result;
+}
+
+//----- (0048E8F5) --------------------------------------------------------
+bool Player::Recover(signed int a2)
+{
+  Player *v2; // esi@1
+  signed __int64 v3; // qax@1
+  bool result; // eax@4
+
+  v2 = this;
+  v3 = (signed __int64)((double)(a2 * _48EA46_calc_special_bonus_by_items(17)) * 0.01 + (double)a2);
+  if ( v2->uTimeToRecovery - (signed int)v3 > 0 )
+  {
+    v2->uTimeToRecovery -= v3;
+    result = 1;
+  }
+  else
+  {
+    v2->uTimeToRecovery = 0;
+    viewparams->bRedrawGameUI = 1;
+    if ( !uActiveCharacter )
+      uActiveCharacter = pParty->GetNextActiveCharacter();
+    result = 0;
+  }
+  return result;
+}
+
+//----- (0048E96A) --------------------------------------------------------
+void Player::SetRecoveryTime(signed int sRecoveryTime)
+{
+  signed int v2; // edx@1
+
+  v2 = sRecoveryTime;
+  if ( sRecoveryTime < 0 )
+    v2 = 0;
+  if ( v2 > this->uTimeToRecovery )
+    this->uTimeToRecovery = v2;
+  if ( pPlayers[uActiveCharacter] == this && !some_active_character )
+    uActiveCharacter = pParty->GetNextActiveCharacter();
+  viewparams->bRedrawGameUI = 1;
+}
+// 50C0C4: using guessed type int some_active_character;
+
+//----- (0048E9B7) --------------------------------------------------------
+void Player::RandomizeName()
+{
+  if (!uExpressionTimePassed)
+    strcpy(pName, pNPCStats->pNPCNames[rand() % pNPCStats->uNumNPCNames[uSex]][uSex]);
+}
+
+//----- (0048E9F4) --------------------------------------------------------
+unsigned int Player::GetMajorConditionIdx()
+{
+  for (uint i = 0; i < 18; ++i)
+    if (pConditions[pConditionImportancyTable[i]] != 0)
+      return pConditionImportancyTable[i];
+
+  return 18;
+}
+
+//----- (0048EA1B) --------------------------------------------------------
+int Player::_48EA1B_get_static_effect(int a2)
+{
+  __int16 v2; // cx@1
+  int v3; // eax@1
+
+  v2 = word_4EDFFC[0];
+  v3 = 0;
+  while ( a2 < v2 && v2 )
+    v2 = word_4EDFFC[v3++ + 1];
+  return player_stat_bonuses[v3];
+}
+
+//----- (0048EA46) --------------------------------------------------------
+int Player::_48EA46_calc_special_bonus_by_items(int a2)
+{
+  int v2; // edi@1
+  int v3; // esi@1
+  int v4; // edx@2
+  int v5; // eax@3
+  char *v6; // eax@4
+
+  v2 = 0;
+  v3 = 0;
+  while ( 1 )
+  {
+    if ( !HasItemEquipped((ITEM_EQUIP_TYPE)v3) )
+      goto LABEL_11;
+    v5 = pEquipment.uOffHand  - 1;            // BUG
+                                                // v5 = _this->cEquippedItems.uOffHand - 1;
+    if ( a2 != 17 )
+      break;
+    v6 = (char *)this + 36 * v5;
+    if ( *((int *)v6 + 133) == 533 || *((int *)v6 + 136) == 17 )
+      return 50;
+LABEL_11:
+    ++v3;
+    if ( (signed int)v3 >= 16 )
+      return v2;
+  }
+  if ( a2 != 24 || this->pInventoryItems[v5].uAdditionalValue != 24 )
+    goto LABEL_11;
+  return 5;
+}
+
+//----- (0048EAAE) --------------------------------------------------------
+int Player::GetItemsBonus(CHARACTER_ATTRIBUTE_TYPE attr, int a3)
+{
+  CHARACTER_ATTRIBUTE_TYPE v3; // esi@1
+  signed int v4; // eax@1
+  int v5; // edi@1
+  Player *v6; // ebx@1
+  Player *v8; // ecx@48
+  int v9; // eax@49
+  int v10; // edx@49
+  Player *v11; // ecx@55
+  int v12; // eax@56
+  int v13; // edx@56
+  int v14; // ecx@58
+  int v15; // eax@58
+  Player *v16; // ecx@61
+  int v17; // eax@62
+  Player *v18; // ecx@66
+  int v19; // eax@67
+  int v20; // eax@69
+  Player *v21; // ecx@75
+  int v22; // eax@76
+  int v23; // edx@76
+  int v24; // eax@79
+  int v25; // ecx@80
+  int v26; // edi@80
+  Player *v27; // ecx@84
+  int v28; // eax@85
+  int v29; // edx@85
+  Player *v30; // ecx@96
+  int v31; // ebp@97
+  int v32; // eax@98
+  unsigned int v33; // eax@100
+  int v34; // eax@103
+  char v35; // zf@104
+  char v36; // zf@107
+  unsigned __int8 v37; // zf@119
+  char v38; // sf@119
+  unsigned __int8 v39; // of@119
+  char v40; // zf@122
+  char v41; // zf@145
+  char v42; // zf@164
+  char v43; // zf@173
+  char v44; // zf@189
+  char v45; // zf@198
+  char v46; // zf@239
+  int v47; // eax@268
+  int v48; // eax@269
+  int v49; // eax@291
+  char v50; // zf@295
+  int v51; // eax@306
+  int v52; // eax@307
+  char v53; // zf@312
+  char v54; // zf@336
+  char v55; // zf@348
+  int v56; // eax@365
+  int v57; // ebx@368
+  signed int v58; // [sp-4h] [bp-20h]@10
+  signed int v59; // [sp-4h] [bp-20h]@71
+  signed int v60; // [sp-4h] [bp-20h]@347
+  int v61; // [sp+10h] [bp-Ch]@1
+  int v62; // [sp+14h] [bp-8h]@1
+  int v63; // [sp+18h] [bp-4h]@101
+  ItemGen *attra; // [sp+20h] [bp+4h]@101
+  unsigned int v65; // [sp+24h] [bp+8h]@95
+
+  v3 = attr;
+  v4 = 36;
+  v5 = 0;
+  v6 = this;
+  v62 = 0;
+  v61 = 0;
+
+  switch (attr)
+  {
+    case CHARACTER_ATTRIBUTE_LEVEL:
+      if (HasEnchantedItemEquipped(25))
+        return 5;
+      return 0;
+  };
+
+  if ( (signed int)attr > 36 )
+  {
+    switch ( attr )
+    {
+      case 37:
+        v58 = 15;
+        goto LABEL_35;
+      case 38:
+        v58 = 16;
+        goto LABEL_35;
+      case 39:
+        v58 = 17;
+        goto LABEL_35;
+      case 40:
+        v58 = 18;
+        goto LABEL_35;
+      case 41:
+        v58 = 19;
+        goto LABEL_35;
+      case 42:
+        v58 = 20;
+        goto LABEL_35;
+      case 43:
+        v58 = 25;
+        goto LABEL_35;
+      case 44:
+        v58 = 5;
+        goto LABEL_35;
+      case 45:
+        v58 = 8;
+        goto LABEL_35;
+      case 46:
+        goto LABEL_36;
+      default:
+        break;
+    }
+  }
+  else
+  {
+    if ( attr == 36 )
+    {
+      v58 = 14;
+    }
+    else
+    {
+      if ( (signed int)attr > 21 )
+      {
+        switch ( attr )
+        {
+          case 22:
+            v58 = 30;
+            break;
+          case 23:
+            v58 = 31;
+            break;
+          case 34:
+            v58 = 12;
+            break;
+          default:
+            if ( attr != 35 )
+              goto LABEL_38;
+            v58 = 13;
+            break;
+        }
+      }
+      else
+      {
+        switch ( attr )
+        {
+          case 21:
+            v58 = 33;
+            break;
+          case 16:
+            v58 = 35;
+            break;
+          case 17:
+            v58 = 34;
+            break;
+          case 18:
+            v58 = 29;
+            break;
+          case 19:
+            v58 = 21;
+            break;
+          default:
+            if ( attr != 20 )
+              goto LABEL_38;
+            v58 = 32;
+            break;
+        }
+      }
+    }
+LABEL_35:
+    v4 = v58;
+LABEL_36:
+    if ( !this->pActiveSkills[v4] )
+      return 0;
+  }
+LABEL_38:
+  if ( (signed int)attr > 28 )
+  {
+    if ( (signed int)attr < 29 )
+      return v5 + v62 + v61;
+    if ( (signed int)attr <= 30 )
+    {
+      if ( HasItemEquipped(EQUIP_BOW) )
+        v5 = pItemsTable->pItems[*(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5]].uDamageMod;
+      return v5 + v62 + v61;
+    }
+    if ( attr == 31 )
+    {
+      if ( !HasItemEquipped(EQUIP_BOW) )
+        return v5 + v62 + v61;
+      v57 = *(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5];
+      v5 = pItemsTable->pItems[v57].uDamageMod;
+      v56 = pItemsTable->pItems[v57].uDamageDice;
+      goto LABEL_366;
+    }
+    if ( attr == 32 )
+    {
+      if ( !HasItemEquipped(EQUIP_BOW) )
+        return v5 + v62 + v61;
+      v20 = *(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5];
+      v5 = pItemsTable->pItems[v20].uDamageDice * pItemsTable->pItems[v20].uDamageRoll;
+LABEL_365:
+      v56 = pItemsTable->pItems[v20].uDamageMod;
+LABEL_366:
+      v5 += v56;
+      return v5 + v62 + v61;
+    }
+    if ( (signed int)attr <= 33 || (signed int)attr > 46 )
+      return v5 + v62 + v61;
+LABEL_95:
+    v65 = 0;
+    while ( 1 )
+    {
+      if ( !HasItemEquipped((ITEM_EQUIP_TYPE)v65) )
+        goto LABEL_361;
+      v31 = *(&v6->pEquipment.uOffHand + v65) - 1;
+      if ( v3 == 9 )
+      {
+        v32 = GetEquippedItemEquipType(v65);
+        if ( v32 >= 3 )
+        {
+          if ( v32 <= 11 )
+          {
+            v33 = v6->pInventoryItems[v31].uItemID;
+            v5 += pItemsTable->pItems[v33].uDamageDice + pItemsTable->pItems[v33].uDamageMod;
+          }
+        }
+      }
+      v63 = (int)((char *)v6 + 36 * v31);
+      attra = (ItemGen *)(v63 + 532);
+      if ( pItemsTable->_456D5E_is_some_material((ItemGen *)(v63 + 532)) == 1
+        && !pItemsTable->_456D43_is_material_equals_3(attra) )
+      {
+        v34 = attra->uItemID;
+        switch ( attra->uItemID )
+        {
+          case 0x1F4u:
+            v35 = v3 == 5;
+            goto LABEL_105;
+          case 0x1F5u:
+            v36 = v3 == 0;
+            goto LABEL_108;
+          case 0x1F6u:
+            if ( v3 == 21 )
+              v61 += 10;
+            v36 = v3 == 2;
+            goto LABEL_108;
+          case 0x1F7u:
+            if ( v3 == 17 )
+              v61 += 5;
+            if ( v3 == 18 )
+              v61 += 5;
+            v36 = v3 == 6;
+            goto LABEL_108;
+          case 0x1F8u:
+            goto LABEL_118;
+          case 0x1F9u:
+            v40 = v3 == 3;
+            goto LABEL_123;
+          case 0x1FAu:
+            v35 = v3 == 10;
+            goto LABEL_105;
+          case 0x1FEu:
+            v35 = v3 == 4;
+            goto LABEL_105;
+          case 0x1FFu:
+            if ( v3 == 23 )
+              v61 += 10;
+            if ( v3 == 22 )
+              v61 += 10;
+            goto LABEL_361;
+          case 0x200u:
+            if ( v3 == 36 )
+            {
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[14]);
+              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+            }
+            v36 = v3 == 5;
+LABEL_108:
+            if ( v36 )
+              v5 += 40;
+            goto LABEL_361;
+          case 0x201u:
+            if ( v3 == 39 )
+            {
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[17]);
+              v34 = ((unsigned int)v34 >> 1) & 0x1F;
+              v62 = v34;
+            }
+            goto LABEL_136;
+          case 0x202u:
+            if ( !v3 )
+              v5 += 150;
+            if ( v3 == 1 )
+              v5 -= 40;
+            if ( v3 == 2 )
+              v5 -= 40;
+            goto LABEL_145;
+          case 0x203u:
+            if ( v3 == 42 )
+            {
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[20]);
+              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+            }
+            if ( v3 == 43 )
+              v61 += 15;
+            goto LABEL_361;
+          case 0x204u:
+            if ( v3 == 17 )
+              v61 += 5;
+            if ( v3 == 18 )
+              v61 += 5;
+            if ( v3 == 6 )
+              v5 += 50;
+            if ( v3 == 11 || v3 == 10 || v3 == 12 || v3 == 13 || v3 == 33 || v3 == 14 )
+              goto LABEL_166;
+            v42 = v3 == 15;
+            goto LABEL_165;
+          case 0x205u:
+            if ( v3 == 18 )
+              v61 += 5;
+            goto LABEL_361;
+          case 0x206u:
+            if ( !v3 )
+              v5 += 100;
+            if ( v3 == 3 )
+              v5 += 100;
+            v43 = v3 == 9;
+            goto LABEL_174;
+          case 0x207u:
+            if ( v3 == 45 )
+              v61 += 5;
+            if ( v3 == 15 )
+              v5 -= 10;
+            v42 = v3 == 14;
+LABEL_165:
+            if ( v42 )
+LABEL_166:
+              v5 -= 10;
+            goto LABEL_361;
+          case 0x208u:
+            v35 = v3 == 3;
+            goto LABEL_105;
+          case 0x209u:
+            if ( v3 == 2 )
+              v5 += 15;
+            if ( !v3 )
+              v5 += 15;
+            v41 = v3 == 6;
+            goto LABEL_146;
+          case 0x20Au:
+            if ( v3 == 46 )
+              v61 += 15;
+            v44 = v3 == 3;
+            goto LABEL_190;
+          case 0x20Bu:
+            if ( v3 == 34 )
+            {
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[12]);
+              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+            }
+            if ( v3 == 12 )
+              v5 += 50;
+            if ( v3 == 2 )
+              v5 += 30;
+            v45 = v3 == 9;
+            goto LABEL_199;
+          case 0x20Cu:
+            if ( !v3 )
+              v5 += 75;
+            goto LABEL_145;
+          case 0x20Du:
+            if ( v3 == 5 )
+              v5 += 50;
+            if ( v3 == 6 )
+              v5 += 50;
+            if ( v3 == 11 || v3 == 10 || v3 == 12 || v3 == 13 || v3 == 33 || v3 == 14 )
+              goto LABEL_374;
+            v43 = v3 == 15;
+LABEL_174:
+            if ( v43 )
+LABEL_374:
+              v5 -= 15;
+            goto LABEL_361;
+          case 0x20Eu:
+            if ( v3 == 4 )
+              v5 += 150;
+            if ( v3 == 44 )
+              v61 += 5;
+            if ( v3 == 9 )
+              v5 -= 25;
+            goto LABEL_361;
+          case 0x20Fu:
+            if ( v3 == 39 )
+            {
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[17]);
+              v34 = ((unsigned int)v34 >> 1) & 0x1F;
+              v62 = v34;
+            }
+            if ( v3 == 40 )
+            {
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[18]);
+              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+            }
+LABEL_145:
+            v41 = v3 == 5;
+LABEL_146:
+            if ( v41 )
+              v5 -= 40;
+            goto LABEL_361;
+          case 0x210u:
+            if ( v3 == 38 )
+            {
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[16]);
+              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+            }
+            if ( !v3 )
+              v5 += 75;
+            v44 = v3 == 11;
+LABEL_190:
+            if ( v44 )
+              v5 -= 50;
+            goto LABEL_361;
+          case 0x211u:
+            if ( v3 == 5 )
+              v5 += 100;
+            if ( v3 == 4 )
+              v5 += 50;
+            v35 = v3 == 11;
+LABEL_105:
+            if ( v35 )
+              v5 += 50;
+            goto LABEL_361;
+          case 0x212u:
+            if ( v3 == 1 )
+              v5 -= 20;
+            v45 = v3 == 2;
+LABEL_199:
+            if ( v45 )
+              v5 -= 20;
+            goto LABEL_361;
+          case 0x214u:
+            if ( v3 == 1 )
+              v5 += 15;
+            v46 = v3 == 2;
+            goto LABEL_240;
+          case 0x215u:
+            if ( v3 == 5 )
+              v5 += 15;
+            v46 = v3 == 4;
+            goto LABEL_240;
+          case 0x216u:
+            if ( v3 == 10 )
+              v5 += 30;
+            if ( !v3 )
+              v5 += 15;
+            goto LABEL_315;
+          case 0x217u:
+            if ( v3 == 21 )
+              v61 += 5;
+            if ( !v3 )
+              v5 += 15;
+            goto LABEL_253;
+          case 0x218u:
+            goto LABEL_253;
+          default:
+            goto LABEL_361;
+        }
+        goto LABEL_361;
+      }
+      if ( *(int *)(v63 + 536) == v3 + 1 )
+      {
+        if ( (signed int)v3 >= 0 )
+        {
+          if ( (signed int)v3 <= 15 )
+          {
+            v5 += *((int *)v6->pConditions + 9 * v31 + 135);
+          }
+          else
+          {
+            if ( (signed int)v3 <= 23 && v5 < *((int *)v6->pConditions + 9 * v31 + 135) )
+              v5 = *((int *)v6->pConditions + 9 * v31 + 135);
+          }
+        }
+        goto LABEL_361;
+      }
+      v34 = *(int *)(v63 + 544);
+      if ( v34 > 48 )
+      {
+        switch ( v34 )
+        {
+          case 54:
+            goto LABEL_315;
+          case 49:
+            if ( v3 == 6 )
+              goto LABEL_121;
+            v50 = v3 == 1;
+            goto LABEL_296;
+          case 51:
+            if ( v3 != 5 && v3 != 1 )
+              goto LABEL_309;
+            goto LABEL_121;
+          case 52:
+            if ( v3 == 3 )
+              goto LABEL_121;
+            v50 = v3 == 4;
+            goto LABEL_296;
+          case 53:
+            if ( !v3 )
+              goto LABEL_121;
+            v50 = v3 == 2;
+            goto LABEL_296;
+          case 55:
+            v46 = v3 == 6;
+            goto LABEL_240;
+          case 56:
+            if ( !v3 )
+              goto LABEL_351;
+            v53 = v3 == 3;
+            goto LABEL_350;
+          case 57:
+            if ( v3 == 1 )
+              goto LABEL_351;
+            v53 = v3 == 2;
+            goto LABEL_350;
+          case 50:
+            if ( v3 == 10 )
+              v5 += 30;
+            goto LABEL_361;
+          case 60:
+            if ( v3 != 23 )
+              goto LABEL_336;
+            if ( v5 >= 3 )
+              goto LABEL_361;
+            v5 = 3;
+LABEL_336:
+            v54 = v3 == 22;
+            goto LABEL_345;
+          case 61:
+            if ( v3 != 17 )
+              goto LABEL_340;
+            if ( v5 >= 3 )
+              goto LABEL_361;
+            v5 = 3;
+LABEL_340:
+            v54 = v3 == 18;
+            goto LABEL_345;
+          case 62:
+            if ( v3 != 19 )
+              goto LABEL_344;
+            if ( v5 >= 3 )
+              goto LABEL_361;
+            v5 = 3;
+LABEL_344:
+            v54 = v3 == 20;
+LABEL_345:
+            if ( !v54 )
+              goto LABEL_361;
+            if ( v5 >= 3 )
+              goto LABEL_361;
+            v60 = 3;
+            goto LABEL_360;
+          case 67:
+            v55 = v3 == 18;
+            goto LABEL_357;
+          case 68:
+            v53 = v3 == 9;
+            goto LABEL_350;
+          case 69:
+            if ( v3 == 11 )
+              v5 += 20;
+            break;
+          case 70:
+            if ( v3 == 12 )
+              v5 += 10;
+            v55 = v3 == 16;
+LABEL_357:
+            if ( v55 && v5 < 2 )
+            {
+              v60 = 2;
+LABEL_360:
+              v5 = v60;
+            }
+            break;
+          default:
+            goto LABEL_361;
+        }
+        goto LABEL_361;
+      }
+      if ( v34 == 48 )
+      {
+        if ( v3 == 9 )
+          v5 += 5;
+LABEL_315:
+        v46 = v3 == 3;
+LABEL_240:
+        if ( v46 )
+          v5 += 15;
+        goto LABEL_361;
+      }
+      if ( v34 > 32 )
+      {
+        if ( v34 > 44 )
+        {
+          v51 = v34 - 45;
+          if ( !v51 )
+          {
+            if ( v3 == 5 )
+              goto LABEL_351;
+            v53 = v3 == 4;
+LABEL_350:
+            if ( v53 )
+LABEL_351:
+              v5 += 5;
+            goto LABEL_361;
+          }
+          v52 = v51 - 1;
+          if ( !v52 )
+          {
+            v40 = v3 == 0;
+LABEL_123:
+            if ( v40 )
+              v5 += 25;
+            goto LABEL_361;
+          }
+          if ( v52 == 1 )
+          {
+LABEL_309:
+            v50 = v3 == 8;
+            goto LABEL_296;
+          }
+        }
+        else
+        {
+          if ( v34 == 44 )
+          {
+            v50 = v3 == 7;
+            goto LABEL_296;
+          }
+          v34 -= 33;
+          if ( !v34 )
+          {
+            if ( v3 != 38 )
+              goto LABEL_361;
+            LOBYTE(v34) = LOBYTE(v6->pActiveSkills[16]);
+            goto LABEL_138;
+          }
+          --v34;
+          if ( !v34 )
+          {
+            if ( v3 != 36 )
+              goto LABEL_361;
+            LOBYTE(v34) = LOBYTE(v6->pActiveSkills[14]);
+            goto LABEL_138;
+          }
+          v49 = v34 - 8;
+          if ( !v49 )
+          {
+            if ( (signed int)v3 >= 0 && (signed int)v3 <= 15 )
+              ++v5;
+            goto LABEL_361;
+          }
+          if ( v49 == 1 )
+          {
+            if ( v3 != 3 && v3 != 7 )
+            {
+              v50 = v3 == 9;
+LABEL_296:
+              if ( !v50 )
+                goto LABEL_361;
+            }
+LABEL_121:
+            v5 += 10;
+            goto LABEL_361;
+          }
+        }
+      }
+      else
+      {
+        if ( v34 == 32 )
+        {
+          if ( v3 != 39 )
+            goto LABEL_361;
+          LOBYTE(v34) = LOBYTE(v6->pActiveSkills[17]);
+          goto LABEL_138;
+        }
+        if ( v34 > 28 )
+        {
+          v34 -= 29;
+          if ( v34 )
+          {
+            --v34;
+            if ( v34 )
+            {
+              --v34;
+              if ( v34 || v3 != 41 )
+                goto LABEL_361;
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[19]);
+            }
+            else
+            {
+              if ( v3 != 34 )
+                goto LABEL_361;
+              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[12]);
+            }
+          }
+          else
+          {
+            if ( v3 != 37 )
+              goto LABEL_361;
+            LOBYTE(v34) = LOBYTE(v6->pActiveSkills[15]);
+          }
+          goto LABEL_138;
+        }
+        if ( v34 == 28 )
+        {
+LABEL_136:
+          if ( v3 == 42 )
+          {
+            LOBYTE(v34) = LOBYTE(v6->pActiveSkills[20]);
+LABEL_138:
+            v62 = ((unsigned int)v34 >> 1) & 0x1F;
+            goto LABEL_361;
+          }
+        }
+        else
+        {
+          v47 = v34 - 1;
+          if ( v47 )
+          {
+            v48 = v47 - 1;
+            if ( v48 )
+            {
+              v34 = v48 - 24;
+              if ( v34 )
+              {
+                --v34;
+                if ( v34 || v3 != 40 )
+                  goto LABEL_361;
+                LOBYTE(v34) = LOBYTE(v6->pActiveSkills[18]);
+              }
+              else
+              {
+                if ( v3 != 35 )
+                  goto LABEL_361;
+                LOBYTE(v34) = LOBYTE(v6->pActiveSkills[13]);
+              }
+              goto LABEL_138;
+            }
+LABEL_118:
+            if ( (signed int)v3 < 0 )
+              goto LABEL_361;
+            v39 = __OFSUB__((int)v3, 6);
+            v37 = v3 == 6;
+            v38 = v3 - 6 < 0;
+          }
+          else
+          {
+LABEL_253:
+            if ( (signed int)v3 < 10 )
+              goto LABEL_361;
+            v39 = __OFSUB__((int)v3, 15);
+            v37 = v3 == 15;
+            v38 = v3 - 15 < 0;
+          }
+          if ( (unsigned __int8)(v38 ^ v39) | v37 )
+            goto LABEL_121;
+        }
+      }
+LABEL_361:
+      ++v65;
+      if ( (signed int)v65 >= 16 )
+        return v5 + v62 + v61;
+    }
+  }
+  if ( attr == 28 )
+  {
+    if ( IsUnarmed() != 1 )
+    {
+      if ( v6->HasItemEquipped(EQUIP_TWO_HANDED) )
+      {
+        v22 = v21->GetEquippedItemEquipType(1u);
+        if ( v22 >= 0 )
+        {
+          if ( v22 <= 2 )
+          {
+            if ( v6->pEquipment.uOffHand || (v24 = v23, pItemsTable->pItems[v23].uSkillType != 4) )
+            {
+              v24 = v23;
+              v26 = pItemsTable->pItems[v23].uDamageRoll;
+              v25 = pItemsTable->pItems[v23].uDamageDice;
+            }
+            else
+            {
+              v25 = pItemsTable->pItems[v24].uDamageRoll;
+              v26 = pItemsTable->pItems[v24].uDamageDice + 1;
+            }
+            v5 = pItemsTable->pItems[v24].uDamageMod + v25 * v26;
+          }
+        }
+      }
+      if ( a3 || !v6->HasItemEquipped((ITEM_EQUIP_TYPE)0) || (v28 = v27->GetEquippedItemEquipType(0), v28 < 0) || v28 > 2 )
+        return v5 + v62 + v61;
+      v15 = pItemsTable->pItems[v29].uDamageMod;
+      v14 = pItemsTable->pItems[v29].uDamageDice * pItemsTable->pItems[v29].uDamageRoll;
+      goto LABEL_88;
+    }
+    v59 = 3;
+LABEL_74:
+    v5 = v59;
+    return v5 + v62 + v61;
+  }
+  if ( (signed int)attr < 0 )
+    return v5 + v62 + v61;
+  if ( (signed int)attr <= 23 )
+    goto LABEL_95;
+  if ( (signed int)attr <= 24 )
+    return v5 + v62 + v61;
+  if ( (signed int)attr <= 26 )
+  {
+    if ( IsUnarmed() == 1 )
+    {
+      v5 = 0;
+      return v5 + v62 + v61;
+    }
+    if ( v6->HasItemEquipped(EQUIP_TWO_HANDED) )
+    {
+      v17 = v16->GetEquippedItemEquipType(1u);
+      if ( v17 >= 0 )
+      {
+        if ( v17 <= 2 )
+          v5 = pItemsTable->pItems[*(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uMainHand + 5]].uDamageMod;
+      }
+    }
+    if ( a3 || !v6->HasItemEquipped((ITEM_EQUIP_TYPE)0) || (v19 = v18->GetEquippedItemEquipType(0), v19 < 0) || v19 > 2 )
+      return v5 + v62 + v61;
+    v20 = *(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uOffHand + 5];
+    goto LABEL_365;
+  }
+  if ( attr == 27 )
+  {
+    if ( IsUnarmed() == 1 )
+    {
+      v5 = 1;
+      return v5 + v62 + v61;
+    }
+    if ( v6->HasItemEquipped(EQUIP_TWO_HANDED) )
+    {
+      v9 = v8->GetEquippedItemEquipType(1u);
+      if ( v9 >= 0 )
+      {
+        if ( v9 <= 2 )
+        {
+          v5 = pItemsTable->pItems[v10].uDamageDice + pItemsTable->pItems[v10].uDamageMod;
+          if ( !v6->pEquipment.uOffHand )
+          {
+            if ( pItemsTable->pItems[v10].uSkillType == 4 )
+              ++v5;
+          }
+        }
+      }
+    }
+    if ( a3 || !v6->HasItemEquipped((ITEM_EQUIP_TYPE)0) || (v12 = v11->GetEquippedItemEquipType(0), v12 < 0) || v12 > 2 )
+      return v5 + v62 + v61;
+    v14 = pItemsTable->pItems[v13].uDamageMod;
+    v15 = pItemsTable->pItems[v13].uDamageDice;
+LABEL_88:
+    v5 += v15 + v14;
+  }
+  return v5 + v62 + v61;
+}
+
+//----- (0048F73C) --------------------------------------------------------
+int Player::GetMagicalBonus(enum CHARACTER_ATTRIBUTE_TYPE a2)
+{
+  int result; // eax@1
+  int v3; // eax@4
+  int v4; // ecx@5
+
+  switch (a2)
+  {
+    case CHARACTER_ATTRIBUTE_LEVEL: return 0;
+  }
+
+  result = 0;
+  if ( (signed int)a2 > 10 )
+  {
+    if ( (signed int)a2 <= 15 )
+    {
+      switch ( a2 )
+      {
+        case CHARACTER_ATTRIBUTE_RESIST_BODY:
+          v3 = this->pPlayerBuffs[2].uPower;
+          v4 = pParty->pPartyBuffs[1].uPower;
+          break;
+        case CHARACTER_ATTRIBUTE_RESIST_AIR:
+          v3 = this->pPlayerBuffs[0].uPower;
+          v4 = pParty->pPartyBuffs[0].uPower;
+          break;
+        case CHARACTER_ATTRIBUTE_RESIST_WATER:
+          v3 = this->pPlayerBuffs[22].uPower;
+          v4 = pParty->pPartyBuffs[17].uPower;
+          break;
+        case CHARACTER_ATTRIBUTE_RESIST_EARTH:
+          v3 = this->pPlayerBuffs[3].uPower;
+          v4 = pParty->pPartyBuffs[4].uPower;
+          break;
+        default:
+          if ( a2 != 14 )
+            return result;
+          v3 = this->pPlayerBuffs[9].uPower;
+          v4 = pParty->pPartyBuffs[12].uPower;
+          break;
+      }
+      return v4 + v3;
+    }
+    if ( a2 != CHARACTER_ATTRIBUTE_ATTACK )
+    {
+      if ( a2 == CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS )
+      {
+        v3 = this->pPlayerBuffs[8].uPower;
+        v4 = pParty->pPartyBuffs[9].uPower;
+        return v4 + v3;
+      }
+      if ( a2 != CHARACTER_ATTRIBUTE_RANGED_ATTACK )
+        return result;
+    }
+    return this->pPlayerBuffs[1].uPower;
+  }
+  if ( a2 == 10 )
+  {
+    v3 = this->pPlayerBuffs[5].uPower;
+    v4 = pParty->pPartyBuffs[6].uPower;
+    return v4 + v3;
+  }
+  switch ( a2 )
+  {
+    case CHARACTER_ATTRIBUTE_STRENGTH:
+      v3 = pPlayerBuffs[19].uPower;
+      goto LABEL_5;
+    case CHARACTER_ATTRIBUTE_INTELLIGENCE:
+      v3 = pPlayerBuffs[17].uPower;
+      goto LABEL_5;
+    case CHARACTER_ATTRIBUTE_WILLPOWER:
+      v3 = pPlayerBuffs[20].uPower;
+      goto LABEL_5;
+    case CHARACTER_ATTRIBUTE_ENDURANCE:
+      v3 = pPlayerBuffs[16].uPower;
+      goto LABEL_5;
+    case CHARACTER_ATTRIBUTE_ACCURACY:
+      v3 = pPlayerBuffs[15].uPower;
+      goto LABEL_5;
+    case CHARACTER_ATTRIBUTE_SPEED:
+      v3 = pPlayerBuffs[21].uPower;
+      goto LABEL_5;
+    case CHARACTER_ATTRIBUTE_LUCK:
+      v3 = pPlayerBuffs[18].uPower;
+LABEL_5:
+      v4 = pParty->pPartyBuffs[2].uPower;
+      return v4 + v3;
+    case CHARACTER_ATTRIBUTE_AC_BONUS:
+      v3 = this->pPlayerBuffs[14].uPower;
+      v4 = pParty->pPartyBuffs[15].uPower;
+      return v4 + v3;
+    default:
+      return result;
+  }
+  return result;
+}
+
+//----- (0048F882) --------------------------------------------------------
+char Player::GetActualSkillLevel(enum PLAYER_SKILL_TYPE uSkillType)
+{
+  signed int v2; // esi@1
+  unsigned __int16 v3; // ax@126
+  char result; // al@127
+  unsigned int v5; // [sp-4h] [bp-14h]@13
+  signed int v6; // [sp-4h] [bp-14h]@27
+  unsigned int v7; // [sp-4h] [bp-14h]@35
+  CHARACTER_ATTRIBUTE_TYPE v8; // [sp-4h] [bp-14h]@68
+  Player *v9; // [sp+Ch] [bp-4h]@1
+
+  v2 = 0;
+  v9 = this;
+  if ( uSkillType > PLAYER_SKILL_DODGE )
+  {
+    if ( uSkillType != PLAYER_SKILL_UNARMED )
+    {
+      if ( uSkillType == PLAYER_SKILL_MONSTER_ID )
+      {
+        if ( CheckHiredNPCSpeciality(0x3Au) )
+          v2 = 6;
+        if ( CheckHiredNPCSpeciality(0x39u) )
+          v2 += 6;
+        goto LABEL_83;
+      }
+      if ( uSkillType == PLAYER_SKILL_ARMSMASTER )
+      {
+        if ( CheckHiredNPCSpeciality(0xFu) )
+          v2 = 2;
+        if ( CheckHiredNPCSpeciality(0x10u) )
+          v2 += 3;
+        goto LABEL_64;
+      }
+      if ( uSkillType == PLAYER_SKILL_STEALING )
+      {
+        if ( CheckHiredNPCSpeciality(0x33u) )
+          v2 = 8;
+        goto LABEL_64;
+      }
+      if ( uSkillType == PLAYER_SKILL_ALCHEMY )
+      {
+        if ( CheckHiredNPCSpeciality(0x17u) )
+          v2 = 4;
+        if ( CheckHiredNPCSpeciality(0x18u) )
+          v2 += 8;
+        goto LABEL_64;
+      }
+      if ( uSkillType == 36 )                   // learning
+      {
+        if ( CheckHiredNPCSpeciality(0xDu) )
+          v2 = 10;
+        if ( CheckHiredNPCSpeciality(0xEu) )
+          v2 += 15;
+        if ( CheckHiredNPCSpeciality(4u) )
+          v2 += 5;
+        goto LABEL_64;
+      }
+      goto LABEL_86;
+    }
+    if ( !CheckHiredNPCSpeciality(0x38u) )
+      goto LABEL_112;
+LABEL_85:
+    v2 = 2;
+    goto LABEL_86;
+  }
+  if ( uSkillType == PLAYER_SKILL_DODGE )
+  {
+    if ( !CheckHiredNPCSpeciality(0x38u) )
+      goto LABEL_112;
+    v6 = 2;
+    goto LABEL_51;
+  }
+  if ( uSkillType <= PLAYER_SKILL_ITEM_ID )
+  {
+    if ( uSkillType != PLAYER_SKILL_ITEM_ID )
+    {
+      if ( (signed int)uSkillType < 0 )
+        goto LABEL_86;
+      if ( uSkillType > PLAYER_SKILL_PLATE )
+      {
+        if ( uSkillType <= PLAYER_SKILL_EARTH )
+        {
+          if ( CheckHiredNPCSpeciality(0x11u) )
+            v2 = 2;
+          if ( CheckHiredNPCSpeciality(0x12u) )
+            v2 += 3;
+          v5 = 19;
+        }
+        else
+        {
+          if ( uSkillType > PLAYER_SKILL_BODY )
+            goto LABEL_86;
+          if ( CheckHiredNPCSpeciality(0x35u) )
+            v2 = 2;
+          if ( CheckHiredNPCSpeciality(0x36u) )
+            v2 += 3;
+          v5 = 55;
+        }
+        if ( CheckHiredNPCSpeciality(v5) )
+          v2 += 4;
+        if ( v9->uClass == 31 && sub_476387() )
+          v2 += 3;
+LABEL_86:
+        if ( uSkillType <= PLAYER_SKILL_DARK )
+        {
+          if ( uSkillType == PLAYER_SKILL_DARK )
+          {
+            v8 = (CHARACTER_ATTRIBUTE_TYPE)42;
+          }
+          else
+          {
+            if ( uSkillType > PLAYER_SKILL_EARTH )
+            {
+              switch ( uSkillType )
+              {
+                case 16:
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)38;
+                  break;
+                case 17:
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)39;
+                  break;
+                case 18:
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)40;
+                  break;
+                default:
+                  if ( uSkillType != 19 )
+                    goto LABEL_126;
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)41;
+                  break;
+              }
+            }
+            else
+            {
+              switch ( uSkillType )
+              {
+                case PLAYER_SKILL_EARTH:
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)37;
+                  break;
+                case PLAYER_SKILL_BOW:
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)44;
+                  break;
+                case PLAYER_SKILL_SHIELD:
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)45;
+                  break;
+                case PLAYER_SKILL_FIRE:
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)34;
+                  break;
+                case PLAYER_SKILL_AIR:
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)35;
+                  break;
+                default:
+                  if ( uSkillType != 14 )
+                    goto LABEL_126;
+                  v8 = (CHARACTER_ATTRIBUTE_TYPE)36;
+                  break;
+              }
+            }
+          }
+          goto LABEL_125;
+        }
+        if ( uSkillType <= PLAYER_SKILL_MONSTER_ID )
+        {
+          if ( uSkillType != PLAYER_SKILL_MONSTER_ID )
+            goto LABEL_112;
+LABEL_83:
+          v8 = (CHARACTER_ATTRIBUTE_TYPE)20;
+          goto LABEL_125;
+        }
+LABEL_64:
+        switch ( uSkillType )
+        {
+          case PLAYER_SKILL_ARMSMASTER:
+            v8 = (CHARACTER_ATTRIBUTE_TYPE)21;
+            break;
+          case PLAYER_SKILL_STEALING:
+            v8 = (CHARACTER_ATTRIBUTE_TYPE)17;
+            break;
+          case PLAYER_SKILL_ALCHEMY:
+            v8 = (CHARACTER_ATTRIBUTE_TYPE)16;
+            break;
+          default:
+            if ( uSkillType != 36 )
+              goto LABEL_126;
+            v8 = (CHARACTER_ATTRIBUTE_TYPE)46;
+            break;
+        }
+        goto LABEL_125;
+      }
+      if ( !CheckHiredNPCSpeciality(0x2Eu) )
+        goto LABEL_86;
+      goto LABEL_85;
+    }
+    if ( !CheckHiredNPCSpeciality(0x39u) )
+      goto LABEL_112;
+    v6 = 6;
+LABEL_51:
+    v2 = v6;
+    goto LABEL_112;
+  }
+  if ( uSkillType == PLAYER_SKILL_MERCHANT )
+  {
+    if ( CheckHiredNPCSpeciality(0x14u) )
+      v2 = 4;
+    if ( CheckHiredNPCSpeciality(0x15u) )
+      v2 += 6;
+    if ( CheckHiredNPCSpeciality(0x30u) )
+      v2 += 3;
+    v7 = 50;
+LABEL_47:
+    if ( CheckHiredNPCSpeciality(v7) )
+      v2 += 8;
+    goto LABEL_112;
+  }
+  if ( uSkillType != PLAYER_SKILL_PERCEPTION )
+  {
+    if ( uSkillType != PLAYER_SKILL_TRAP_DISARM )
+      goto LABEL_86;
+    if ( CheckHiredNPCSpeciality(0x19u) )
+      v2 = 4;
+    if ( CheckHiredNPCSpeciality(0x1Au) )
+      v2 += 6;
+    v7 = 51;
+    goto LABEL_47;
+  }
+  if ( CheckHiredNPCSpeciality(0x16u) )
+    v2 = 6;
+  if ( CheckHiredNPCSpeciality(0x2Fu) )
+    v2 += 5;
+LABEL_112:
+  switch ( uSkillType )
+  {
+    case PLAYER_SKILL_ITEM_ID:
+      v8 = (CHARACTER_ATTRIBUTE_TYPE)19;
+      break;
+    case PLAYER_SKILL_MEDITATION:
+      v8 = (CHARACTER_ATTRIBUTE_TYPE)43;
+      break;
+    case PLAYER_SKILL_TRAP_DISARM:
+      v8 = (CHARACTER_ATTRIBUTE_TYPE)18;
+      break;
+    case PLAYER_SKILL_DODGE:
+      v8 = (CHARACTER_ATTRIBUTE_TYPE)22;
+      break;
+    default:
+      if ( uSkillType != 31 )
+        goto LABEL_126;
+      v8 = (CHARACTER_ATTRIBUTE_TYPE)23;
+      break;
+  }
+LABEL_125:
+  v2 += v9->GetItemsBonus(v8, 0);
+LABEL_126:
+  v3 = v9->pActiveSkills[uSkillType];
+  if ( v2 + (v9->pActiveSkills[uSkillType] & 0x3F) < 60 )
+    result = v2 + v3;
+  else
+    result = v3 & 0xFC | 0x3C;
+  return result;
+}
+
+//----- (0048FC00) --------------------------------------------------------
+int Player::GetSkillBonus(enum CHARACTER_ATTRIBUTE_TYPE a2)
+{
+  Player *v2; // esi@1
+  int v3; // eax@1
+  char v4; // di@1
+  signed int v5; // ebx@1
+  unsigned int v6; // eax@2
+  unsigned __int8 v7; // sf@5
+  unsigned __int8 v8; // of@5
+  PlayerEquipment *v9; // ebx@19
+  Player *v10; // ecx@20
+  enum PLAYER_SKILL_TYPE v11; // edi@21
+  int v12; // eax@21
+  int v13; // edi@21
+  char v14; // di@25
+  signed int v15; // esi@25
+  char v16; // al@32
+  int v18; // eax@36
+  unsigned int v19; // eax@37
+  ITEM_EQUIP_TYPE v20; // edi@40
+  int v21; // edx@41
+  int v22; // eax@42
+  enum PLAYER_SKILL_TYPE v23; // edi@45
+  unsigned __int16 v24; // ax@45
+  unsigned __int16 v25; // bx@45
+  unsigned int v26; // eax@45
+  unsigned __int8 v27; // sf@50
+  unsigned __int8 v28; // of@50
+  unsigned int v29; // eax@52
+  int v30; // eax@55
+  int v31; // eax@58
+  unsigned int v32; // eax@59
+  int v33; // eax@65
+  char v34; // si@65
+  ITEM_EQUIP_TYPE v35; // edi@69
+  int v36; // edx@70
+  int v37; // eax@71
+  enum PLAYER_SKILL_TYPE v38; // edi@74
+  int v39; // eax@74
+  int v40; // eax@89
+  char v41; // si@89
+  int v42; // eax@96
+  enum PLAYER_SKILL_TYPE v43; // edx@97
+  int v44; // eax@97
+  int v45; // eax@98
+  int v46; // eax@99
+  int v47; // eax@100
+  int v48; // eax@101
+  int v49; // eax@102
+  unsigned __int16 v50; // ax@113
+  char v51; // di@113
+  unsigned int v52; // eax@113
+  int v53; // edi@113
+  signed int i; // ecx@113
+  unsigned __int16 v55; // ax@118
+  char v56; // si@118
+  unsigned int v57; // eax@118
+  int v58; // esi@121
+  signed int j; // ecx@121
+  int v60; // edi@126
+  int v61; // eax@126
+  signed int v62; // [sp-4h] [bp-30h]@26
+  signed int v63; // [sp-4h] [bp-30h]@80
+  int v64; // [sp+Ch] [bp-20h]@104
+  int v65; // [sp+10h] [bp-1Ch]@104
+  int v66; // [sp+14h] [bp-18h]@104
+  int v67; // [sp+18h] [bp-14h]@104
+  int v68; // [sp+1Ch] [bp-10h]@69
+  PlayerEquipment *v69; // [sp+20h] [bp-Ch]@1
+  int v70; // [sp+24h] [bp-8h]@1
+  ITEM_EQUIP_TYPE v71; // [sp+28h] [bp-4h]@1
+  int a1; // [sp+34h] [bp+8h]@21
+  int a1a; // [sp+34h] [bp+8h]@74
+  signed int a1b; // [sp+34h] [bp+8h]@94
+
+  v2 = this;
+  v70 = 0;
+  v69 = 0;
+  v71 = (ITEM_EQUIP_TYPE)0;
+  LOBYTE(v3) = GetActualSkillLevel(PLAYER_SKILL_ARMSMASTER);
+  v4 = v3;
+  v5 = 1;
+  if ( v3 )
+  {
+    v6 = SkillToMastery(v3);
+    if ( a2 == CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS )
+    {
+      if ( (signed int)v6 >= 4 )
+        goto LABEL_4;
+      v8 = __OFSUB__(v6, 3);
+      v7 = ((v6 - 3) & 0x80000000u) != 0;
+    }
+    else
+    {
+      if ( a2 != CHARACTER_ATTRIBUTE_ATTACK )
+        goto LABEL_11;
+      if ( (signed int)v6 >= 4 )
+      {
+LABEL_4:
+        v71 = (ITEM_EQUIP_TYPE)2;
+LABEL_11:
+        v69 = (PlayerEquipment *)(v71 * (v4 & 0x3F));
+        goto LABEL_12;
+      }
+      v8 = __OFSUB__(v6, 2);
+      v7 = ((v6 - 2) & 0x80000000u) != 0;
+    }
+    if ( !(v7 ^ v8) )
+      v71 = (ITEM_EQUIP_TYPE)1;
+    goto LABEL_11;
+  }
+LABEL_12:
+  if ( a2 == CHARACTER_ATTRIBUTE_HEALTH )
+  {
+    v60 = pBaseHealthPerLevelByClass[v2->uClass];
+    v61 = v2->GetBodybuilding();
+    return v60 * v61;
+  }
+  if ( a2 == CHARACTER_ATTRIBUTE_MANA )
+  {
+    v60 = pBaseManaPerLevelByClass[v2->uClass];
+    v61 = v2->GetMediatation();
+    return v60 * v61;
+  }
+  if ( a2 != 9 )
+  {
+    if ( a2 != CHARACTER_ATTRIBUTE_ATTACK )
+    {
+      if ( a2 <= CHARACTER_ATTRIBUTE_ATTACK )
+        return v70;
+      if ( a2 > CHARACTER_ATTRIBUTE_MELEE_DMG_MAX )
+      {
+        if ( a2 != CHARACTER_ATTRIBUTE_RANGED_ATTACK )
+          return v70;
+        v71 = (ITEM_EQUIP_TYPE)0;
+        v9 = &v2->pEquipment;
+        while ( 1 )
+        {
+          if ( v2->HasItemEquipped(v71) )
+          {
+            v11 = (PLAYER_SKILL_TYPE)pItemsTable->pItems[*(int *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v9->uOffHand + 5]].uSkillType;
+            LOBYTE(v12) = v10->GetActualSkillLevel(v11);
+            a1 = v12;
+            SkillToMastery(v12);
+            v13 = v11 - 5;
+            if ( !v13 )
+              return a1 & 0x3F;
+            if ( v13 == 2 )
+              break;
+          }
+          v71 = (ITEM_EQUIP_TYPE)((int)v71 + 1);
+          v9 = (PlayerEquipment *)((char *)v9 + 4);
+          if ( (signed int)v71 >= 16 )
+            return v70;
+        }
+        v14 = a1;
+        v15 = 1;
+        if ( (signed int)SkillToMastery(a1) >= 4 )
+        {
+          v62 = 5;
+          goto LABEL_31;
+        }
+        if ( (signed int)SkillToMastery(a1) >= 3 )
+        {
+          v62 = 3;
+          goto LABEL_31;
+        }
+        if ( (signed int)SkillToMastery(a1) < 2 )
+          goto LABEL_32;
+        goto LABEL_30;
+      }
+      if ( v2->IsUnarmed() )
+      {
+        LOBYTE(v18) = v2->GetActualSkillLevel(PLAYER_SKILL_UNARMED);
+        v14 = v18;
+        if ( !v18 )
+          return v70;
+        v15 = 0;
+        v19 = SkillToMastery(v18);
+        if ( (signed int)v19 < 3 )
+        {
+          if ( (signed int)v19 >= 2 )
+            v15 = 1;
+LABEL_32:
+          v16 = v14;
+          return v15 * (v16 & 0x3F);
+        }
+LABEL_30:
+        v62 = 2;
+LABEL_31:
+        v15 = v62;
+        goto LABEL_32;
+      }
+      v20 = (ITEM_EQUIP_TYPE)0;
+      while ( 1 )
+      {
+        if ( v2->HasItemEquipped(v20) )
+        {
+          v22 = *(int *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v21 + 5];
+          if ( pItemsTable->pItems[v22].uEquipType <= 1u )
+            break;
+        }
+        v20 = (ITEM_EQUIP_TYPE)((int)v20 + 1);
+        if ( (signed int)v20 >= 16 )
+          return v70;
+      }
+      v71 = (ITEM_EQUIP_TYPE)0;
+      v23 = (PLAYER_SKILL_TYPE)pItemsTable->pItems[v22].uSkillType;
+      LOBYTE(v24) = v2->GetActualSkillLevel(v23);
+      v25 = v24;
+      v26 = SkillToMastery(v24);
+      if ( !v23 )
+      {
+        if ( (signed int)SkillToMastery(v25) >= 4 )
+        {
+          LOBYTE(v31) = v2->GetActualSkillLevel(PLAYER_SKILL_UNARMED);
+          LOBYTE(v25) = v31;
+          if ( v31 )
+          {
+            v15 = 0;
+            v32 = SkillToMastery(v31);
+            if ( (signed int)v32 < 3 )
+            {
+              if ( (signed int)v32 >= 2 )
+                v15 = 1;
+            }
+            else
+            {
+              v15 = 2;
+            }
+            v16 = v25;
+            return v15 * (v16 & 0x3F);
+          }
+        }
+        goto LABEL_55;
+      }
+      if ( v23 == PLAYER_SKILL_DAGGER )
+      {
+        v29 = SkillToMastery(v25);
+        v28 = __OFSUB__(v29, 4);
+        v27 = ((v29 - 4) & 0x80000000u) != 0;
+      }
+      else
+      {
+        if ( v23 <= PLAYER_SKILL_DAGGER )
+          goto LABEL_55;
+        if ( v23 > PLAYER_SKILL_SPEAR )
+        {
+          if ( v23 == PLAYER_SKILL_MACE )
+          {
+            v28 = __OFSUB__(v26, 2);
+            v27 = ((v26 - 2) & 0x80000000u) != 0;
+            goto LABEL_53;
+          }
+LABEL_55:
+          v30 = v71 * (v25 & 0x3F);
+          return (int)((char *)v69 + v30);
+        }
+        v28 = __OFSUB__(v26, 3);
+        v27 = ((v26 - 3) & 0x80000000u) != 0;
+      }
+LABEL_53:
+      if ( !(v27 ^ v28) )
+        v71 = (ITEM_EQUIP_TYPE)1;
+      goto LABEL_55;
+    }
+    if ( v2->IsUnarmed() == 1 )
+    {
+      LOBYTE(v33) = v2->GetActualSkillLevel(PLAYER_SKILL_UNARMED);
+      v34 = v33;
+      if ( !v33 )
+        return v70;
+      if ( (signed int)SkillToMastery(v33) >= 3 )
+        v5 = 2;
+      v30 = v5 * (v34 & 0x3F);
+      return (int)((char *)v69 + v30);
+    }
+    v35 = (ITEM_EQUIP_TYPE)0;
+    v68 = 0;
+    while ( 1 )
+    {
+      if ( v2->HasItemEquipped(v35) )
+      {
+        v37 = *(int *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v36 + 5];
+        if ( pItemsTable->pItems[v37].uEquipType <= 1u )
+          break;
+      }
+      v35 = (ITEM_EQUIP_TYPE)((int)v35 + 1);
+      if ( (signed int)v35 >= 16 )
+        return v70;
+    }
+    v38 = (PLAYER_SKILL_TYPE)pItemsTable->pItems[v37].uSkillType;
+    LOBYTE(v39) = v2->GetActualSkillLevel(v38);
+    a1a = v39;
+    SkillToMastery(v39);
+    v71 = (ITEM_EQUIP_TYPE)0;
+    if ( v38 )
+    {
+      if ( (signed int)v38 > 0 )
+      {
+        if ( (signed int)v38 <= 4 || v38 == 6 )
+        {
+          v71 = (ITEM_EQUIP_TYPE)1;
+        }
+        else
+        {
+          if ( v38 == 7 )
+          {
+            if ( (signed int)SkillToMastery(a1a) < 4 )
+            {
+              if ( (signed int)SkillToMastery(a1a) < 3 )
+              {
+                if ( (signed int)SkillToMastery(a1a) < 2 )
+                  return v5 * (a1a & 0x3F);
+                v63 = 2;
+              }
+              else
+              {
+                v63 = 3;
+              }
+            }
+            else
+            {
+              v63 = 5;
+            }
+            v5 = v63;
+            return v5 * (a1a & 0x3F);
+          }
+        }
+      }
+    }
+    else
+    {
+      v71 = (ITEM_EQUIP_TYPE)1;
+      if ( (signed int)SkillToMastery(a1a) >= 4 )
+      {
+        LOBYTE(v40) = v2->GetActualSkillLevel(PLAYER_SKILL_UNARMED);
+        v41 = v40;
+        if ( v40 )
+        {
+          if ( (signed int)SkillToMastery(v40) >= 3 )
+            v5 = 2;
+          v68 = v5 * (v41 & 0x3F);
+        }
+      }
+    }
+    v30 = v68 + v71 * (a1a & 0x3F);
+    return (int)((char *)v69 + v30);
+  }
+  a1b = 0;
+  v71 = (ITEM_EQUIP_TYPE)0;
+  v68 = 16;
+  v69 = &v2->pEquipment;
+  do
+  {
+    if ( !v69->uOffHand || (v42 = (int)((char *)v2 + 36 * v69->uOffHand), *(char *)(v42 + 516) & 2) )
+      goto LABEL_117;
+    v43 = (PLAYER_SKILL_TYPE)pItemsTable->pItems[*(int *)(v42 + 496)].uSkillType;
+    v44 = pItemsTable->pItems[*(int *)(v42 + 496)].uSkillType;
+    if ( !v44 )
+    {
+      v64 = 0;
+      v65 = 1;
+LABEL_111:
+      v66 = 0;
+      goto LABEL_112;
+    }
+    v45 = v44 - 1;
+    if ( !v45 || (v46 = v45 - 3) == 0 )
+    {
+      v64 = 0;
+      v65 = 0;
+      v66 = 0;
+      v67 = 1;
+      goto LABEL_113;
+    }
+    v47 = v46 - 4;
+    if ( v47 )
+    {
+      v48 = v47 - 1;
+      if ( v48 )
+      {
+        v49 = v48 - 1;
+        if ( v49 )
+        {
+          if ( v49 != 1 )
+            goto LABEL_117;
+          a1b = 1;
+          v64 = 1;
+          v65 = 0;
+          v66 = 0;
+          v67 = 0;
+          goto LABEL_113;
+        }
+        a1b = 1;
+        v64 = 1;
+        v65 = 0;
+        goto LABEL_111;
+      }
+      v71 = (ITEM_EQUIP_TYPE)1;
+    }
+    else
+    {
+      a1b = 1;
+    }
+    v64 = 1;
+    v65 = 0;
+    v66 = 1;
+LABEL_112:
+    v67 = 0;
+LABEL_113:
+    LOBYTE(v50) = v2->GetActualSkillLevel(v43);
+    v51 = v50;
+    v52 = SkillToMastery(v50);
+    v53 = v51 & 0x3F;
+    for ( i = 0; i < (signed int)v52; ++i )
+    {
+      if ( *(&v64 + i) )
+        v70 += v53;
+    }
+LABEL_117:
+    v69 = (PlayerEquipment *)((char *)v69 + 4);
+    --v68;
+  }
+  while ( v68 );
+  v64 = 1;
+  v65 = 1;
+  v66 = 1;
+  v67 = 0;
+  LOBYTE(v55) = v2->GetActualSkillLevel(PLAYER_SKILL_DODGE);
+  v56 = v55;
+  v57 = SkillToMastery(v55);
+  if ( !a1b && (!v71 || v57 == 4) )
+  {
+    v58 = v56 & 0x3F;
+    for ( j = 0; j < (signed int)v57; ++j )
+    {
+      if ( *(&v64 + j) )
+        v70 += v58;
+    }
+  }
+  return v70;
+}
+
+//----- (00490109) --------------------------------------------------------
+// faces are:  0  1  2  3   human males
+//             4  5  6  7   human females
+//                   8  9   elf males
+//                  10 11   elf females
+//                  12 13   dwarf males
+//                  14 15   dwarf females
+//                  16 17   goblin males
+//                  18 19   goblin females
+//                     20   lich male
+//                     21   lich female
+//                     22   underwater suits (unused)
+//                     23   zombie male
+//                     24   zombie female
+enum CHARACTER_RACE Player::GetRace()
+{
+  if ( uFace > 15 )
+  {
+    if ( uFace >= 16 && uFace <= 19 )
+      return CHARACTER_RACE_GOBLIN;
+  }
+  else
+  {
+    if ( uFace >= 12 )
+    {
+      return CHARACTER_RACE_DWARF;
+    }
+    else
+    {
+      if ( uFace >= 0 )
+      {
+        if ( uFace <= 7 )
+        {
+          return CHARACTER_RACE_HUMAN;
+        }
+        else
+        {
+          if ( uFace <= 11 )
+            return CHARACTER_RACE_ELF;
+        }
+      }
+    }
+  }
+  return CHARACTER_RACE_HUMAN;
+}
+
+//----- (00490141) --------------------------------------------------------
+int Player::GetSexByVoice()
+{
+  signed int result; // eax@1
+
+  result = 0;
+  switch ( this->uVoiceID )
+  {
+    case 0u:
+    case 1u:
+    case 2u:
+    case 3u:
+    case 8u:
+    case 9u:
+    case 0xCu:
+    case 0xDu:
+    case 0x10u:
+    case 0x11u:
+    case 0x14u:
+    case 0x17u:
+      result = 0;
+      break;
+    case 4u:
+    case 5u:
+    case 6u:
+    case 7u:
+    case 0xAu:
+    case 0xBu:
+    case 0xEu:
+    case 0xFu:
+    case 0x12u:
+    case 0x13u:
+    case 0x15u:
+    case 0x18u:
+      result = 1;
+      break;
+    default:
+      return result;
+  }
+  return result;
+}
+
+//----- (00490188) --------------------------------------------------------
+void Player::SetInitialStats()
+{
+  auto v1 = GetRace();
+  uMight = stru_4ED7B0.race[v1].attr[0].uBaseValue;
+  uIntelligence = stru_4ED7B0.race[v1].attr[1].uBaseValue;
+  uWillpower = stru_4ED7B0.race[v1].attr[2].uBaseValue;
+  uEndurance = stru_4ED7B0.race[v1].attr[3].uBaseValue;
+  uAccuracy = stru_4ED7B0.race[v1].attr[4].uBaseValue;
+  uSpeed = stru_4ED7B0.race[v1].attr[5].uBaseValue;
+  uLuck = stru_4ED7B0.race[v1].attr[6].uBaseValue;
+}
+
+//----- (004901FC) --------------------------------------------------------
+int Player::SetSexByVoice()
+{
+  __int64 v1; // qax@1
+
+  v1 = this->uVoiceID;
+  switch ( (int)v1 )
+  {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 8:
+    case 9:
+    case 0xC:
+    case 0xD:
+    case 0x10:
+    case 0x11:
+    case 0x14:
+    case 0x17:
+      BYTE4(v1) = 0;
+      break;
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 0xA:
+    case 0xB:
+    case 0xE:
+    case 0xF:
+    case 0x12:
+    case 0x13:
+    case 0x15:
+    case 0x18:
+      BYTE4(v1) = 1;
+      break;
+    default:
+      break;
+  }
+  this->uSex = (PLAYER_SEX)BYTE4(v1);
+  return v1;
+}
+
+//----- (0049024A) --------------------------------------------------------
+void Player::Reset(unsigned __int8 classID)
+{
+  sLevelModifier = 0;
+  sAgeModifier = 0;
+
+  uClass = classID;
+  uLuckBonus = 0;
+  uSpeedBonus = 0;
+  uAccuracyBonus = 0;
+  uEnduranceBonus = 0;
+  uWillpowerBonus = 0;
+  uIntelligenceBonus = 0;
+  uMightBonus = 0;
+  uLevel = 1;
+  uExperience = 251 + rand() % 100;
+  uBirthYear = 1147 - rand() % 6;
+  memset(pActiveSkills, 0, sizeof(pActiveSkills));
+  memset(field_152, 0, 64);
+  memset(&spellbook, 0, sizeof(PlayerSpells));
+
+  for (uint i = 0; i < 37; ++i)
+  {
+    if (pSkillAvailabilityPerClass[uClass / 4][i] != 2)
+      continue;
+
+    pActiveSkills[i] = 1;
+
+    switch (i)
+    {
+      case PLAYER_SKILL_FIRE:   spellbook.pFireSpellbook.bIsSpellbookAvailable = true;   break;
+      case PLAYER_SKILL_AIR:    spellbook.pAirSpellbook.bIsSpellbookAvailable = true;    break;
+      case PLAYER_SKILL_WATER:  spellbook.pWaterSpellbook.bIsSpellbookAvailable = true;  break;
+      case PLAYER_SKILL_EARTH:  spellbook.pEarthSpellbook.bIsSpellbookAvailable = true;  break;
+      case PLAYER_SKILL_SPIRIT: spellbook.pSpiritSpellbook.bIsSpellbookAvailable = true; break;
+      case PLAYER_SKILL_MIND:   spellbook.pMindSpellbook.bIsSpellbookAvailable = 1; break;
+      case PLAYER_SKILL_BODY:   spellbook.pBodySpellbook.bIsSpellbookAvailable = 1; break;
+      case PLAYER_SKILL_LIGHT:  spellbook.pLightSpellbook.bIsSpellbookAvailable = 1; break;
+      case PLAYER_SKILL_DARK:   spellbook.pDarkSpellbook.bIsSpellbookAvailable = 1; break;
+    }
+  }
+
+  sHealth = GetMaxHealth();
+  sMana = GetMaxMana();
+}
+
+//----- (004903C9) --------------------------------------------------------
+enum PLAYER_SKILL_TYPE Player::GetSkillIdxByOrder(signed int order)
+{
+  enum PLAYER_SKILL_TYPE result; // eax@5
+  int v3; // edx@5
+  char *v4; // ecx@5
+  int v5; // esi@11
+  unsigned __int16 *v6; // edx@11
+  int v7; // esi@18
+  unsigned __int16 *pActiveSkill; // edx@18
+
+  if ( order >= 0 )
+  {
+    if ( order <= 1 )
+    {
+      result = (PLAYER_SKILL_TYPE)0;
+      v7 = 0;
+      pActiveSkill = this->pActiveSkills;
+      do
+      {
+        if ( *pActiveSkill && pSkillAvailabilityPerClass[uClass / 4][result] == 2 )
+        {
+          if ( v7 == order )
+            return result;
+          ++v7;
+        }
+        result = (PLAYER_SKILL_TYPE)((int)result + 1);
+        ++pActiveSkill;
+      }
+      while ( (signed int)result < 37 );
+    }
+    else
+    {
+      if ( order <= 3 )
+      {
+        result = (PLAYER_SKILL_TYPE)0;
+        v5 = 0;
+        pActiveSkill = this->pActiveSkills;
+        do
+        {
+          if ( *pActiveSkill && pSkillAvailabilityPerClass[uClass / 4][result] == 1 )
+          {
+            if ( v5 == order - 2 )
+              return result;
+            ++v5;
+          }
+          result = (PLAYER_SKILL_TYPE)((int)result + 1);
+          ++pActiveSkill;
+        }
+        while ( (signed int)result < 37 );
+      }
+      else
+      {
+        if ( order <= 12 )
+        {
+          result = (PLAYER_SKILL_TYPE)0;
+          v3 = 0;
+          v4 = (char *)pSkillAvailabilityPerClass[uClass / 4];
+          do
+          {
+            if ( *v4 == 1 )
+            {
+              if ( v3 == order - 4 )
+                return result;
+              ++v3;
+            }
+            result = (PLAYER_SKILL_TYPE)((int)result + 1);
+            ++v4;
+          }
+          while ( (signed int)result < 37 );
+        }
+      }
+    }
+  }
+  return (PLAYER_SKILL_TYPE)37;
+}
+
+
+
+//----- (0049048D) --------------------------------------------------------
+//unsigned __int16 PartyCreation_BtnMinusClick(Player *_this, int eAttribute)
+void Player::DecreaseAttribute(int eAttribute)
+{
+  int v2; // eax@1
+  int pBaseValue; // ecx@1
+  int pDroppedStep; // ebx@1
+  int pStep; // esi@1
+  unsigned __int16 result; // ax@7
+  int uMinValue; // [sp+Ch] [bp-4h]@1
+
+  v2 = eAttribute + 7 * GetRace();
+  pBaseValue = stru_4ED7B0.race[0].attr[v2].uBaseValue;
+  pDroppedStep = stru_4ED7B0.race[0].attr[v2].uDroppedStep;
+  uMinValue = pBaseValue - 2;
+  pStep = stru_4ED7B0.race[0].attr[v2].uBaseStep;
+    switch ( eAttribute )
+    {
+      case CHARACTER_MIGHT:
+        if ( this->uMight <= pBaseValue )
+          pStep = pDroppedStep;
+        if ( this->uMight - pStep >= uMinValue )
+         this->uMight -= pStep;
+        break;
+	  case CHARACTER_INTELLIGANCE:
+        if ( this->uIntelligence <= pBaseValue )
+          pStep = pDroppedStep;
+        if ( this->uIntelligence - pStep >= uMinValue )
+          this->uIntelligence -= pStep;
+        break;
+      case CHARACTER_WILLPOWER:
+        if ( this->uWillpower <= pBaseValue )
+          pStep = pDroppedStep;
+        if ( this->uWillpower - pStep >= uMinValue )
+          this->uWillpower -= pStep;
+        break;
+      case CHARACTER_ENDURANCE:
+        if ( this->uEndurance <= pBaseValue )
+          pStep = pDroppedStep;
+        if ( this->uEndurance - pStep >= uMinValue )
+          this->uEndurance -= pStep;
+        break;
+      case CHARACTER_ACCURACY:
+        if ( this->uAccuracy <= pBaseValue )
+          pStep = pDroppedStep;
+        if ( this->uAccuracy - pStep >= uMinValue )
+          this->uAccuracy -= pStep;
+        break;
+      case CHARACTER_SPEED:
+        if ( this->uSpeed <= pBaseValue )
+          pStep = pDroppedStep;
+        if ( this->uSpeed - pStep >= uMinValue )
+          this->uSpeed -= pStep;
+        break;
+      case CHARACTER_LUCK:
+		if ( this->uLuck <= pBaseValue )
+          pStep = pDroppedStep;
+        if ( this->uLuck - pStep >= uMinValue )
+          this->uLuck -= pStep;
+        break;
+    }
+}
+
+//----- (004905F5) --------------------------------------------------------
+//signed int __thiscall PartyCreation_BtnPlusClick(Player *this, int eAttribute)
+int Player::IncreaseAttribute(int eAttribute)
+{
+  Player *v2; // esi@1
+  int v3; // eax@1
+  int v4; // ebx@1
+  signed int v5; // edi@1
+  int v6; // eax@8
+  signed int v7; // eax@17
+  signed int result; // eax@18
+  int v9; // [sp+Ch] [bp-8h]@1
+  signed int v10; // [sp+10h] [bp-4h]@1
+
+  v2 = this;
+  v3 = eAttribute + 7 * GetRace();
+  v4 = stru_4ED7B0.race[0].attr[v3].uMaxValue;
+  v5 = stru_4ED7B0.race[0].attr[v3].uBaseStep;
+  v9 = stru_4ED7B0.race[0].attr[v3].uBaseValue;
+  v10 = stru_4ED7B0.race[0].attr[v3].uDroppedStep;
+  PlayerCreation_ComputeAttributeBonus();
+  if ( eAttribute )
+  {
+    switch ( eAttribute )
+    {
+      case 1:
+        v6 = v2->uIntelligence;
+        break;
+      case 2:
+        v6 = v2->uWillpower;
+        break;
+      case 3:
+        v6 = v2->uEndurance;
+        break;
+      case 4:
+        v6 = v2->uAccuracy;
+        break;
+      case 5:
+        v6 = v2->uSpeed;
+        break;
+      case 6:
+        v6 = v2->uLuck;
+        break;
+      default:
+        v6 = eAttribute;
+        break;
+    }
+  }
+  else
+  {
+    v6 = v2->uMight;
+  }
+  if ( v6 < v9 )
+  {
+    v7 = v5;
+    v5 = v10;
+    v10 = v7;
+  }
+  result = PlayerCreation_ComputeAttributeBonus();
+  if ( result >= v10 )
+  {
+    if ( eAttribute )
+    {
+      switch ( eAttribute )
+      {
+        case 1:
+          result = (signed int)&v2->uIntelligence;
+          break;
+        case 2:
+          result = (signed int)&v2->uWillpower;
+          break;
+        case 3:
+          result = (signed int)&v2->uEndurance;
+          break;
+        case 4:
+          result = (signed int)&v2->uAccuracy;
+          break;
+        case 5:
+          result = (signed int)&v2->uSpeed;
+          break;
+        default:
+          result = eAttribute - 6;
+          if ( eAttribute != 6 )
+            return result;
+          result = (signed int)&v2->uLuck;
+          break;
+      }
+    }
+    else
+    {
+      result = (signed int)&v2->uMight;
+    }
+    if ( v5 + *(short *)result <= v4 )
+      *(short *)result += v5;
+  }
+  return result;
+}
+
+//----- (0049070F) --------------------------------------------------------
+void Player::Zero()
+{
+  Player *v1; // esi@1
+  void *result; // eax@1
+
+  v1 = this;
+  this->sLevelModifier = 0;
+  this->sACModifier = 0;
+  this->uLuckBonus = 0;
+  this->uAccuracyBonus = 0;
+  this->uSpeedBonus = 0;
+  this->uEnduranceBonus = 0;
+  this->uWillpowerBonus = 0;
+  this->uIntelligenceBonus = 0;
+  this->uMightBonus = 0;
+  this->field_100 = 0;
+  this->field_FC = 0;
+  this->field_F8 = 0;
+  this->field_F4 = 0;
+  this->field_F0 = 0;
+  this->field_EC = 0;
+  this->field_E8 = 0;
+  this->field_E4 = 0;
+  this->field_E0 = 0;
+  result = memset(&this->sResFireBonus, 0, 0x16u);
+  v1->field_1A97 = 0;
+  v1->_ranged_dmg_bonus = 0;
+  v1->field_1A95 = 0;
+  v1->_ranged_atk_bonus = 0;
+  v1->field_1A93 = 0;
+  v1->_melee_dmg_bonus = 0;
+  v1->field_1A91 = 0;
+  v1->_some_attack_bonus = 0;
+  v1->_mana_related = 0;
+  v1->uFullManaBonus = 0;
+  v1->_health_related = 0;
+  v1->uFullHealthBonus = 0;
+}
+
+//----- (004907E7) --------------------------------------------------------
+__int16 Player::GetStatColor(unsigned int uStat)
+{
+  Player *v2; // edi@1
+  __int16 uWhite; // si@1
+//  int uStartingHP; // eax@1
+  int v5; // edx@1
+ // unsigned __int8 v6; // zf@1
+ // char v7; // sf@1
+  unsigned __int8 v8; // of@1
+  __int16 result; // ax@2
+  __int16 uGreen; // [sp+8h] [bp-8h]@1
+  __int16 uRed; // [sp+Ch] [bp-4h]@1
+
+  v2 = this;
+  uRed = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0x23u, 0);
+  uGreen = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0);
+  uWhite = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v8 = stru_4ED7B0.race[GetRace()].attr[uStat].uBaseValue;
+
+  int attribute_value = 0;
+  switch (uStat)
+  {
+    case 0:  attribute_value = uMight;        break;
+    case 1:  attribute_value = uIntelligence; break;
+    case 2:  attribute_value = uWillpower;    break;
+    case 3:  attribute_value = uEndurance;    break;
+    case 4:  attribute_value = uSpeed;        break;
+    case 5:  attribute_value = uAccuracy;     break;
+    case 6:  attribute_value = uLuck;         break;
+  };
+
+  v5 = attribute_value;
+  if ( v5 >= v8 )
+  {
+    result = uGreen;
+    if ( v5 == v8 )
+      result = uWhite;
+  }
+  else
+  {
+    result = uRed;
+  }
+  return result;
+}
+
+//----- (004908A8) --------------------------------------------------------
+bool Player::DiscardConditionIfLastsLongerThan(unsigned int uCondition, unsigned __int64 uTime)
+{
+  unsigned __int64 *result; // eax@1
+
+  result = (unsigned __int64 *)((char *)this + 8 * uCondition);
+  if ( *result && (signed __int64)uTime < (signed __int64)*result )
+  {
+    *(int *)result = 0;
+    *((int *)result + 1) = 0;
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+    LOBYTE(result) = 0;
+  }
+  return (bool)result;
+}
+
+//----- (004680ED) --------------------------------------------------------
+void Player::UseItem_DrinkPotion_etc(signed int a2, int a3)
+{
+  Player *v3; // esi@1
+  unsigned int v4; // ebx@4
+  signed int v5; // eax@17
+  unsigned int v6; // eax@26
+  unsigned __int8 v7; // cf@37
+  int v8; // edx@39
+  int v9; // edx@40
+  int v10; // edx@41
+  int v11; // edx@42
+  int v12; // edx@43
+  char *v13; // eax@45
+  AudioPlayer *v14; // ecx@62
+  signed int v15; // edi@68
+  int v16; // edx@73
+  unsigned __int16 *v17; // edi@73
+  unsigned int v18; // eax@73
+  int v19; // eax@74
+  int v20; // eax@75
+  signed int v21; // eax@81
+  const char *v22; // eax@84
+  char *v23; // ecx@90
+  int v24; // esi@96
+  int v25; // eax@109
+  int v26; // eax@113
+  char *v27; // edi@114
+  signed __int64 v28; // qax@120
+  char *v29; // ecx@120
+  int v30; // edi@137
+  int v31; // ST30_4@137
+  int v32; // ST3C_4@137
+  int v33; // ST40_4@137
+  int v34; // ST34_4@137
+  int v35; // ST38_4@137
+  unsigned __int8 v36; // al@173
+  SoundID v37; // [sp-20h] [bp-4Ch]@18
+  SoundID v38; // [sp-20h] [bp-4Ch]@174
+  signed int v39; // [sp-1Ch] [bp-48h]@18
+  signed int v40; // [sp-1Ch] [bp-48h]@174
+  unsigned int v41; // [sp-18h] [bp-44h]@18
+  unsigned int v42; // [sp-18h] [bp-44h]@174
+  signed int v43; // [sp-14h] [bp-40h]@18
+  signed int v44; // [sp-14h] [bp-40h]@174
+  signed int v45; // [sp-10h] [bp-3Ch]@18
+  unsigned __int16 v46; // [sp-10h] [bp-3Ch]@120
+  signed int v47; // [sp-10h] [bp-3Ch]@174
+  int v48; // [sp-Ch] [bp-38h]@18
+  unsigned int v49; // [sp-Ch] [bp-38h]@33
+  unsigned __int16 v50; // [sp-Ch] [bp-38h]@120
+  int v51; // [sp-Ch] [bp-38h]@174
+  unsigned int v52; // [sp-8h] [bp-34h]@18
+  char *v53; // [sp-8h] [bp-34h]@33
+  int v54; // [sp-8h] [bp-34h]@34
+  unsigned int v55; // [sp-8h] [bp-34h]@60
+  int v56; // [sp-8h] [bp-34h]@66
+  const char *v57; // [sp-8h] [bp-34h]@69
+  const char *v58; // [sp-8h] [bp-34h]@89
+  int v59; // [sp-8h] [bp-34h]@120
+  unsigned int v60; // [sp-8h] [bp-34h]@174
+  int v61; // [sp-4h] [bp-30h]@18
+  char *v62; // [sp-4h] [bp-30h]@33
+  char *v63; // [sp-4h] [bp-30h]@34
+  int v64; // [sp-4h] [bp-30h]@60
+  int v65; // [sp-4h] [bp-30h]@66
+  const char *v66; // [sp-4h] [bp-30h]@69
+  signed int v67; // [sp-4h] [bp-30h]@77
+  const char *v68; // [sp-4h] [bp-30h]@89
+  int v69; // [sp-4h] [bp-30h]@110
+  unsigned __int8 v70; // [sp-4h] [bp-30h]@120
+  int v71; // [sp-4h] [bp-30h]@174
+  char *v72; // [sp+20h] [bp-Ch]@68
+  signed int v73; // [sp+24h] [bp-8h]@1
+  char *v74; // [sp+24h] [bp-8h]@23
+  int v75; // [sp+24h] [bp-8h]@73
+  Player *thisb; // [sp+28h] [bp-4h]@1
+  unsigned int thisa; // [sp+28h] [bp-4h]@22
+
+  thisb = this;
+  v3 = (Player *)&stru_AA1058[3].pSounds[6972 * a2 + 40552];
+  v73 = 1;
+  if ( pParty->bTurnBasedModeOn == 1 && (pTurnEngine->field_4 == 1 || pTurnEngine->field_4 == 3) )
+    return;
+  v4 = 0;
+  if ( pItemsTable->pItems[pParty->pPickedItem.uItemID].uEquipType == 13 )
+  {
+    if ( pParty->pPickedItem.uItemID != 160 )
+    {
+      if ( pParty->pPickedItem.uItemID == 161 )
+      {
+        v27 = (char *)&v3->sMana;
+        *(int *)v27 += 2;
+LABEL_170:
+        if ( *(int *)v27 > v3->GetMaxMana() )
+          *(int *)v27 = v3->GetMaxMana();
+      }
+      else
+      {
+        if ( pParty->pPickedItem.uItemID != 162 )
+        {
+LABEL_167:
+          v68 = pParty->pPickedItem.GetDisplayName();
+          v58 = pGlobalTXT_LocalizationStrings[36];
+          goto LABEL_90;
+        }
+        v69 = 2;
+LABEL_111:
+        ((Player *)&stru_AA1058[3].pSounds[6972 * a2 + 40552])->Heal(v69);
+      }
+LABEL_112:
+      v3->PlaySound(36, 0);
+      goto LABEL_173;
+    }
+LABEL_172:
+    ((Player *)&stru_AA1058[3].pSounds[6972 * a2 + 40552])->SetCondition(6u, 1);
+    goto LABEL_173;
+  }
+  if ( pItemsTable->pItems[pParty->pPickedItem.uItemID].uEquipType == 14 )
+  {
+    switch ( pParty->pPickedItem.uItemID )
+    {
+      case 0xDEu:
+        v25 = pParty->pPickedItem._bonus_type + 10;
+        goto LABEL_110;
+      case 0xDFu:
+        v26 = pParty->pPickedItem._bonus_type + 10;
+        goto LABEL_114;
+      case 0xE0u:
+        LODWORD(v3->pConditions[1]) = 0;
+        HIDWORD(v3->pConditions[1]) = 0;
+        goto LABEL_112;
+      case 0xE1u:
+        LODWORD(v3->pConditions[11]) = 0;
+        HIDWORD(v3->pConditions[11]) = 0;
+        LODWORD(v3->pConditions[9]) = 0;
+        HIDWORD(v3->pConditions[9]) = 0;
+        LODWORD(v3->pConditions[7]) = 0;
+        HIDWORD(v3->pConditions[7]) = 0;
+        goto LABEL_112;
+      case 0xE2u:
+        LODWORD(v3->pConditions[10]) = 0;
+        HIDWORD(v3->pConditions[10]) = 0;
+        LODWORD(v3->pConditions[8]) = 0;
+        HIDWORD(v3->pConditions[8]) = 0;
+        LODWORD(v3->pConditions[6]) = 0;
+        HIDWORD(v3->pConditions[6]) = 0;
+        goto LABEL_112;
+      case 0xE3u:
+        LODWORD(v3->pConditions[2]) = 0;
+        HIDWORD(v3->pConditions[2]) = 0;
+        goto LABEL_112;
+      case 0xE4u:
+        if ( v3->pConditions[1] )
+          goto LABEL_173;
+        v70 = 0;
+        v59 = 0;
+        v50 = 5;
+        v46 = 3;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[7];
+        goto LABEL_147;
+      case 0xE5u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 5;
+        v46 = 3;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[8];
+        goto LABEL_147;
+      case 0xE6u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 5;
+        v46 = 3;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[1];
+        goto LABEL_147;
+      case 0xE7u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[11];
+        goto LABEL_147;
+      case 0xE8u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[13];
+        goto LABEL_147;
+      case 0xEAu:
+        v70 = 0;
+        v59 = 0;
+        v50 = 5;
+        v46 = 3;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[14];
+        goto LABEL_147;
+      case 0xEBu:
+        v3->pPlayerBuffs[23].Apply(
+          pParty->uTimePlayed + (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335),
+          3u,
+          5u,
+          0,
+          0);
+        goto LABEL_173;
+      case 0xEDu:
+        LODWORD(v3->pConditions[3]) = 0;
+        HIDWORD(v3->pConditions[3]) = 0;
+        goto LABEL_112;
+      case 0xEEu:
+        LODWORD(v3->pConditions[0]) = 0;
+        HIDWORD(v3->pConditions[0]) = 0;
+        goto LABEL_112;
+      case 0xEFu:
+        LODWORD(v3->pConditions[5]) = 0;
+        HIDWORD(v3->pConditions[5]) = 0;
+        goto LABEL_112;
+      case 0xF0u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[19];
+        goto LABEL_147;
+      case 0xF1u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[17];
+        goto LABEL_147;
+      case 0xF2u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[20];
+        goto LABEL_147;
+      case 0xF3u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[16];
+        goto LABEL_147;
+      case 0xF4u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[21];
+        goto LABEL_147;
+      case 0xF5u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[15];
+        goto LABEL_147;
+      case 0xFBu:
+        LODWORD(v3->pConditions[12]) = 0;
+        HIDWORD(v3->pConditions[12]) = 0;
+        goto LABEL_112;
+      case 0xFCu:
+        v30 = LODWORD(v3->pConditions[14]);
+        v31 = HIDWORD(v3->pConditions[14]);
+        v32 = LODWORD(v3->pConditions[15]);
+        v33 = HIDWORD(v3->pConditions[15]);
+        v34 = LODWORD(v3->pConditions[16]);
+        v35 = HIDWORD(v3->pConditions[16]);
+        memset(&stru_AA1058[3].pSounds[6972 * a2 + 40552], 0, 0xA0u);
+        HIDWORD(v3->pConditions[14]) = v31;
+        LODWORD(v3->pConditions[15]) = v32;
+        HIDWORD(v3->pConditions[15]) = v33;
+        LODWORD(v3->pConditions[16]) = v34;
+        LODWORD(v3->pConditions[14]) = v30;
+        HIDWORD(v3->pConditions[16]) = v35;
+        goto LABEL_112;
+      case 0xFDu:
+        v25 = 5 * pParty->pPickedItem._bonus_type;
+LABEL_110:
+        v69 = v25;
+        goto LABEL_111;
+      case 0xFEu:
+        v26 = 5 * pParty->pPickedItem._bonus_type;
+LABEL_114:
+        v27 = (char *)&v3->sMana;
+        *(int *)v27 += v26;
+        goto LABEL_170;
+      case 0xFFu:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[18];
+        goto LABEL_147;
+      case 0x100u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[5];
+        goto LABEL_147;
+      case 0x101u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)v3->pPlayerBuffs;
+        goto LABEL_147;
+      case 0x102u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[22];
+        goto LABEL_147;
+      case 0x103u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[3];
+        goto LABEL_147;
+      case 0x104u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[9];
+        goto LABEL_147;
+      case 0x105u:
+        v70 = 0;
+        v59 = 0;
+        v50 = 3 * LOWORD(pParty->pPickedItem._bonus_type);
+        v46 = 0;
+        v28 = (signed __int64)((double)(230400 * pParty->pPickedItem._bonus_type) * 0.033333335);
+        v29 = (char *)&v3->pPlayerBuffs[2];
+LABEL_147:
+        ((SpellBuff *)v29)->Apply(pParty->uTimePlayed + v28, v46, v50, v59, v70);
+        goto LABEL_112;
+      case 0x106u:
+        LODWORD(v3->pConditions[15]) = 0;
+        HIDWORD(v3->pConditions[15]) = 0;
+        goto LABEL_112;
+      case 0x108u:
+        if ( !*(int *)&v3->field_1F5[3] )
+        {
+          v3->uLuck += 50;
+          *(int *)&v3->field_1F5[3] = 1;
+        }
+        goto LABEL_112;
+      case 0x109u:
+        if ( !*(int *)&v3->field_1F5[7] )
+        {
+          v3->uSpeed += 50;
+          *(int *)&v3->field_1F5[7] = 1;
+        }
+        goto LABEL_112;
+      case 0x10Au:
+        if ( !*(int *)&v3->field_1F5[11] )
+        {
+          v3->uIntelligence += 50;
+          *(int *)&v3->field_1F5[11] = 1;
+        }
+        goto LABEL_112;
+      case 0x10Bu:
+        if ( !*(int *)&v3->field_1F5[15] )
+        {
+          v3->uEndurance += 50;
+          *(int *)&v3->field_1F5[15] = 1;
+        }
+        goto LABEL_112;
+      case 0x10Cu:
+        if ( !*(int *)&v3->field_1F5[19] )
+        {
+          v3->uWillpower += 50;
+          *(int *)&v3->field_1F5[19] = 1;
+        }
+        goto LABEL_112;
+      case 0x10Du:
+        if ( !*(int *)&v3->field_1F5[23] )
+        {
+          v3->uAccuracy += 50;
+          *(int *)&v3->field_1F5[23] = 1;
+        }
+        goto LABEL_112;
+      case 0x10Eu:
+        if ( !*(int *)&v3->field_1F5[27] )
+        {
+          v3->uMight += 50;
+          *(int *)&v3->field_1F5[27] = 1;
+        }
+        goto LABEL_112;
+      case 0x10Fu:
+        v3->sAgeModifier = 0;
+        goto LABEL_112;
+      default:
+        goto LABEL_167;
+      case 0xDDu:
+        goto LABEL_172;
+    }
+    goto LABEL_172;
+  }
+  if ( pItemsTable->pItems[pParty->pPickedItem.uItemID].uEquipType != 15 )
+  {
+    if ( pItemsTable->pItems[pParty->pPickedItem.uItemID].uEquipType != 16 )
+    {
+      if ( pItemsTable->pItems[pParty->pPickedItem.uItemID].uEquipType != 17 )
+      {
+        if ( pParty->pPickedItem.uItemID == 616 )
+        {
+          thisa = pParty->uCurrentMonthWeek + 1;
+          if ( pParty->uCurrentMonth >= 7 )
+            v74 = 0;
+          else
+            v74 = aAttributeNames[pParty->uCurrentMonth];
+          switch ( pParty->uCurrentMonth )
+          {
+            case 0u:
+              v6 = pParty->uCurrentMonthWeek + 1;
+              v3->uMight += thisa;
+              goto LABEL_33;
+            case 1u:
+              v6 = pParty->uCurrentMonthWeek + 1;
+              v3->uIntelligence += thisa;
+              goto LABEL_33;
+            case 2u:
+              v6 = pParty->uCurrentMonthWeek + 1;
+              v3->uWillpower += thisa;
+              goto LABEL_33;
+            case 3u:
+              v6 = pParty->uCurrentMonthWeek + 1;
+              v3->uEndurance += thisa;
+              goto LABEL_33;
+            case 4u:
+              v6 = pParty->uCurrentMonthWeek + 1;
+              v3->uAccuracy += thisa;
+              goto LABEL_33;
+            case 5u:
+              v6 = pParty->uCurrentMonthWeek + 1;
+              v3->uSpeed += thisa;
+              goto LABEL_33;
+            case 6u:
+              v6 = pParty->uCurrentMonthWeek + 1;
+              v3->uLuck += thisa;
+LABEL_33:
+              v62 = pGlobalTXT_LocalizationStrings[121];
+              v53 = v74;
+              v49 = v6;
+              goto LABEL_53;
+            case 7u:
+              party_finds_gold(1000 * thisa, 0);
+              v63 = pGlobalTXT_LocalizationStrings[97];
+              v54 = 1000 * thisa;
+              goto LABEL_38;
+            case 8u:
+              Party::GiveFood(5 * thisa);
+              v63 = pGlobalTXT_LocalizationStrings[653];
+              v54 = 5 * thisa;
+              goto LABEL_38;
+            case 9u:
+              v63 = pGlobalTXT_LocalizationStrings[207];
+              v3->uSkillPoints += 2 * thisa;
+              v54 = 2 * thisa;
+              goto LABEL_38;
+            case 0xAu:
+              v63 = pGlobalTXT_LocalizationStrings[83];
+              v54 = 2500 * thisa;
+              v7 = __CFADD__(2500 * thisa, LODWORD(v3->uExperience));
+              LODWORD(v3->uExperience) += 2500 * thisa;
+              HIDWORD(v3->uExperience) += ((unsigned __int64)(signed int)(2500 * thisa) >> 32) + v7;
+LABEL_38:
+              sprintf(pTmpBuf, "+%u %s", v54, v63);
+              goto LABEL_54;
+            case 0xBu:
+              v8 = rand() % 6;
+              if ( v8 )
+              {
+                v9 = v8 - 1;
+                if ( v9 )
+                {
+                  v10 = v9 - 1;
+                  if ( v10 )
+                  {
+                    v11 = v10 - 1;
+                    if ( v11 )
+                    {
+                      v12 = v11 - 1;
+                      if ( v12 )
+                      {
+                        if ( v12 != 1 )
+                          goto LABEL_52;
+                        v3->sResBodyBase += thisa;
+                        v13 = pGlobalTXT_LocalizationStrings[29];
+                      }
+                      else
+                      {
+                        v3->sResMindBase += thisa;
+                        v13 = pGlobalTXT_LocalizationStrings[142];
+                      }
+                    }
+                    else
+                    {
+                      v3->sResEarthBase += thisa;
+                      v13 = pGlobalTXT_LocalizationStrings[70];
+                    }
+                  }
+                  else
+                  {
+                    v3->sResWaterBase += thisa;
+                    v13 = pGlobalTXT_LocalizationStrings[240];
+                  }
+                }
+                else
+                {
+                  v3->sResAirBase += thisa;
+                  v13 = pGlobalTXT_LocalizationStrings[6];
+                }
+              }
+              else
+              {
+                v3->sResFireBase += thisa;
+                v13 = pGlobalTXT_LocalizationStrings[87];
+              }
+              v74 = v13;
+LABEL_52:
+              v62 = pGlobalTXT_LocalizationStrings[121];
+              v53 = v74;
+              v49 = thisa;
+LABEL_53:
+              sprintf(pTmpBuf, "+%u %s %s", v49, v53, v62);
+LABEL_54:
+              ShowStatusBarString(pTmpBuf, 2u);
+              pMouse->RemoveHoldingItem();
+              pGame->pStru6Instance->SetPlayerBuffAnim(0x97u, a2 - 1);
+              v3->PlaySound(93, 0);
+              pAudioPlayer->PlaySound((SoundID)(SOUND_Bell|0x2), 0, 0, -1, 0, 0, 0, 0);
+              if ( pParty->uDaysPlayed == 6 || pParty->uDaysPlayed == 20 )
+              {
+                v64 = 0;
+                v55 = 16;
+              }
+              else
+              {
+                if ( pParty->uDaysPlayed == 12 || pParty->uDaysPlayed == 26 )
+                {
+                  v64 = 0;
+                  v55 = 14;
+                }
+                else
+                {
+                  if ( pParty->uDaysPlayed != 4 && pParty->uDaysPlayed != 25 )
+                    return;
+                  v64 = 0;
+                  v55 = 15;
+                }
+              }
+              v3->SetCondition(v55, v64);
+              v61 = 0;
+              v52 = 0;
+              v48 = 0;
+              v45 = 0;
+              v43 = -1;
+              v41 = 0;
+              v39 = 0;
+              v37 = (SoundID)215;
+              v14 = pAudioPlayer;
+              goto LABEL_63;
+            default:
+              goto LABEL_54;
+          }
+        }
+        if ( pParty->pPickedItem.uItemID == 630 )
+        {
+          Party::GiveFood(1u);
+          pAudioPlayer->PlaySound((SoundID)(SOUND_PlayerCantCastSpell|0x2), 0, 0, -1, 0, 0, 0, 0);
+        }
+        else
+        {
+          if ( pParty->pPickedItem.uItemID == 632 )
+          {
+            v61 = 0;
+            v52 = 0;
+            v48 = 0;
+            v45 = 0;
+            v43 = -1;
+            v41 = 0;
+            v39 = 0;
+            v37 = (SoundID)133;
+            goto LABEL_93;
+          }
+          if ( pParty->pPickedItem.uItemID == 633 )
+          {
+            v61 = 0;
+            v52 = 0;
+            v48 = 0;
+            v45 = 0;
+            v43 = -1;
+            v41 = 0;
+            v39 = 0;
+            v37 = (SoundID)134;
+            goto LABEL_93;
+          }
+          if ( pParty->pPickedItem.uItemID == 634 )
+          {
+            v61 = 0;
+            v52 = 0;
+            v48 = 0;
+            v45 = 0;
+            v43 = -1;
+            v41 = 0;
+            v39 = 0;
+            v37 = (SoundID)135;
+            goto LABEL_93;
+          }
+          if ( pParty->pPickedItem.uItemID != 646 )
+          {
+            if ( pParty->pPickedItem.uItemID == 650 )
+            {
+              sub_44C28F_open_nwc_dungeon();
+              return;
+            }
+            goto LABEL_167;
+          }
+          pGame->pStru6Instance->SetPlayerBuffAnim(0x97u, a2 - 1);
+          v5 = 8 * a2 + 392;
+          LOBYTE(v5) = (8 * a2 - 120) | 4;
+          pAudioPlayer->PlaySound(SOUND_20001, v5, 0, -1, 0, 0, 0, 0);
+          v3->AddVariable(VAR_NumSkillPoints, 2);
+        }
+LABEL_187:
+        pMouse->RemoveHoldingItem();
+        return;
+      }
+      if ( ((Player *)&stru_AA1058[3].pSounds[6972 * a2 + 40552])->CanAct() )
+      {
+        sub_467F48(pParty->pPickedItem.uItemID);
+        v65 = 0;
+        v56 = 37;
+LABEL_67:
+        v3->PlaySound(v56, v65);
+        return;
+      }
+LABEL_89:
+      v68 = aCharacterConditionNames[v3->GetMajorConditionIdx()];
+      v58 = pGlobalTXT_LocalizationStrings[382];
+LABEL_90:
+      sprintf(pTmpBuf, v58, v68);
+      v23 = pTmpBuf;
+LABEL_91:
+      ShowStatusBarString(v23, 2u);
+      v4 = 0;
+      goto LABEL_92;
+    }
+    v15 = pParty->pPickedItem.uItemID - 400;
+    v72 = (char *)&v3->pConditions[0] + pParty->pPickedItem.uItemID + 2;
+    if ( *v72 )
+    {
+      v66 = pParty->pPickedItem.GetDisplayName();
+      v57 = pGlobalTXT_LocalizationStrings[380];
+LABEL_72:
+      sprintf(pTmpBuf, v57, v66);
+      ShowStatusBarString(pTmpBuf, 2u);
+LABEL_92:
+      v61 = v4;
+      v52 = v4;
+      v48 = v4;
+      v45 = v4;
+      v43 = -1;
+      v41 = v4;
+      v39 = v4;
+      v37 = (SoundID)27;
+LABEL_93:
+      v14 = pAudioPlayer;
+LABEL_63:
+      pAudioPlayer->PlaySound(v37, v39, v41, v43, v45, v48, v52, v61);
+      return;
+    }
+    if ( !((Player *)&stru_AA1058[3].pSounds[6972 * a2 + 40552])->CanAct() )
+    {
+      v66 = aCharacterConditionNames[v3->GetMajorConditionIdx()];
+      v57 = pGlobalTXT_LocalizationStrings[382];
+      goto LABEL_72;
+    }
+    v16 = v15 % 11 + 1;
+    v17 = &v3->pActiveSkills[v15 / 11 + 12];
+    v75 = v16;
+    v18 = SkillToMastery(*v17) - 1;
+    if ( v18 )
+    {
+      v19 = v18 - 1;
+      if ( v19 )
+      {
+        v20 = v19 - 1;
+        if ( v20 )
+        {
+          if ( v20 != 1 )
+          {
+            v21 = a2;
+LABEL_83:
+            if ( v75 > v21 || !*v17 )
+            {
+              v22 = pParty->pPickedItem.GetDisplayName();
+              sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[381], v22);
+              ShowStatusBarString(pTmpBuf, 2u);
+              v65 = 0;
+              v56 = 20;
+              goto LABEL_67;
+            }
+            *v72 = 1;
+            v3->PlaySound(21, 0);
+            v73 = 0;
+LABEL_173:
+            v36 = pItemsTable->pItems[pParty->pPickedItem.uItemID].uEquipType;
+            if ( v36 == 14 )
+            {
+              v71 = 0;
+              v60 = 0;
+              v51 = 0;
+              v47 = 0;
+              v44 = -1;
+              v42 = 0;
+              v40 = 0;
+              v38 = (SoundID)210;
+            }
+            else
+            {
+              if ( v36 != 13 )
+              {
+LABEL_178:
+                if ( pGUIWindow_CurrentMenu && pGUIWindow_CurrentMenu->eWindowType != WINDOW_null)
+                {
+                  if ( !v73 )
+                    goto LABEL_187;
+                  if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+                  {
+                    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+                    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+                    *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+                    ++pMessageQueue_50CBD0->uNumMessages;
+                  }
+                }
+                if ( v73 )
+                {
+                  if ( pParty->bTurnBasedModeOn )
+                  {
+                    *(&pParty->field_16140 + a2) = 100;
+                    thisb->SetRecoveryTime(100);
+                    pTurnEngine->_40471C();
+                  }
+                  else
+                  {
+                    thisb->SetRecoveryTime((signed __int64)(flt_6BE3A4_debug_recmod1 * 213.3333333333333));
+                  }
+                }
+                goto LABEL_187;
+              }
+              v71 = 0;
+              v60 = 0;
+              v51 = 0;
+              v47 = 0;
+              v44 = -1;
+              v42 = 0;
+              v40 = 0;
+              v38 = (SoundID)211;
+            }
+            pAudioPlayer->PlaySound(v38, v40, v42, v44, v47, v51, v60, v71);
+            goto LABEL_178;
+          }
+          v67 = 11;
+        }
+        else
+        {
+          v67 = 10;
+        }
+      }
+      else
+      {
+        v67 = 7;
+      }
+    }
+    else
+    {
+      v67 = 4;
+    }
+    v21 = v67;
+    goto LABEL_83;
+  }
+  if ( pCurrentScreen == 23 )
+    return;
+  if ( !((Player *)&stru_AA1058[3].pSounds[6972 * a2 + 40552])->CanAct() )
+    goto LABEL_89;
+  if ( bUnderwater == 1 )
+  {
+    v23 = pGlobalTXT_LocalizationStrings[652];
+    goto LABEL_91;
+  }
+  dword_50C9AC = 1;
+  v24 = pParty->pPickedItem.uItemID - 299;
+  if ( pParty->pPickedItem.uItemID == 329 || v24 == 4 || v24 == 91 || v24 == 28 )
+  {
+    pMouse->RemoveHoldingItem();
+    pGUIWindow_CurrentMenu->Release();
+    pIcons_LOD->_4114F2();
+    pCurrentScreen = 0;
+    viewparams->bRedrawGameUI = 1;
+    _42777D_CastSpell_UseWand_ShootArrow(v24, a2 - 1, 0x85u, 1, 0);
+  }
+  else
+  {
+    _720984_unused = pParty->pPickedItem.uItemID;
+    pMouse->RemoveHoldingItem();
+    if ( dword_50C9E8 < 40 )
+    {
+      dword_50C9EC[3 * dword_50C9E8] = 146;
+      dword_50C9F0[3 * dword_50C9E8] = v24;
+      *(&dword_50C9E8 + 3 * dword_50C9E8 + 3) = a2 - 1;
+      ++dword_50C9E8;
+    }
+    if ( pCurrentScreen
+      && pGUIWindow_CurrentMenu
+      && pGUIWindow_CurrentMenu->eWindowType != WINDOW_null
+      && (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+      *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+  }
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+// 50C9AC: using guessed type int dword_50C9AC;
+// 50C9EC: using guessed type int dword_50C9EC[];
+// 6BE3C4: using guessed type char bUnderwater;
+// 720984: using guessed type int 720984_unused;
+
+
+
+//----- (00449BB4) --------------------------------------------------------
+char Player::CompareVariable(enum VariableType var, signed int a1)
+{
+  Player *v3; // esi@1
+  signed int v4; // edi@1
+  unsigned int v5; // eax@8
+  int v6; // eax@9
+  enum CHARACTER_RACE v7; // eax@11
+  signed int v8; // eax@17
+  unsigned __int8 v9; // sf@17
+  unsigned __int8 v10; // of@17
+  int v11; // eax@19
+  unsigned int v12; // eax@20
+  unsigned int v13; // eax@25
+  unsigned __int8 v14; // cl@25
+  signed int v15; // ecx@28
+  ItemGen *v16; // eax@28
+  char v17; // zf@31
+  int v18; // edi@90
+  DDM_DLV_Header *v19; // eax@122
+  char v20; // cl@124
+  DDM_DLV_Header *v21; // eax@126
+  unsigned int v22; // edi@129
+  ItemGen *v23; // esi@134
+  ItemGen *v24; // ecx@135
+  signed int v25; // edx@135
+  ITEM_EQUIP_TYPE v26; // ebx@155
+  char *v27; // edi@155
+  int v28; // ebx@161
+  int v29; // eax@161
+
+  v3 = this;
+  v4 = -1;
+  if ( var > VAR_AutoNotes )
+  {
+    switch ( var )
+    {
+      case VAR_Invisible:
+        if ( SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) >= 0
+          && (SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[11].uExpireTime) > 0) )
+          goto _return_true;
+        goto _cmp_against_arg;
+      case VAR_NumDeaths:
+        v4 = pParty->uNumDeaths;
+        goto _cmp_against_arg;
+      case VAR_NumBounties:
+        v4 = pParty->uNumBountiesCollected;
+        goto _cmp_against_arg;
+      case VAR_PrisonTerms:
+        v4 = pParty->uNumPrisonTerms;
+        goto _cmp_against_arg;
+      case VAR_ArenaWinsPage:
+        v4 = (unsigned __int8)pParty->uNumArenaPageWins;
+        goto _cmp_against_arg;
+      case VAR_ArenaWinsSquire:
+        v4 = (unsigned __int8)pParty->uNumArenaSquireWins;
+        goto _cmp_against_arg;
+      case VAR_ArenaWinsKnight:
+        v4 = (unsigned __int8)pParty->uNumArenaKnightWins;
+        goto _cmp_against_arg;
+      case VAR_ArenaWinsLord:
+        v4 = (unsigned __int8)pParty->uNumArenaLordWins;
+        goto _cmp_against_arg;
+      case VAR_ReputationInCurrentLocation:
+        v19 = &pOutdoor->ddm;
+        if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+          v19 = &pIndoor->dlv;
+        v20 = v19->uReputation >= a1;
+        goto _return;
+      case VAR_History_28|VAR_Sex:
+        v21 = &pOutdoor->ddm;
+        if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+          v21 = &pIndoor->dlv;
+        v20 = v21->field_C_alert == a1;
+_return:
+        LOBYTE(v6) = v20;
+        return v6;
+      case VAR_MonthEquals2|VAR_Sex:
+      case VAR_MonthEquals2|VAR_Class:
+      case VAR_Counter1:
+      case VAR_Counter2:
+      case VAR_Counter3:
+      case VAR_Counter4:
+      case VAR_Counter5:
+      case VAR_Counter6:
+      case VAR_Counter7:
+      case VAR_Counter8:
+        v22 = *(int *)&stru_AA1058[3].pSounds[8 * var + 44304];
+        if ( v22 | *(int *)&stru_AA1058[3].pSounds[8 * var + 44300]
+          && (signed __int64)(__PAIR__(v22, *(int *)&stru_AA1058[3].pSounds[8 * var + 44300])
+                            + (signed __int64)((double)(460800 * a1) * 0.033333335)) <= (signed __int64)pParty->uTimePlayed )
+          goto _return_true;
+        goto _return_false;
+      case VAR_NumSkillPoints:
+        v4 = this->uSkillPoints;
+        goto _cmp_against_arg;
+      case VAR_CircusPrises:
+        v4 = 0;
+        v23 = pParty->pPlayers[0].pInventoryItems;
+        do
+        {
+          v24 = v23;
+          v25 = 138;
+          do
+          {
+            switch ( v24->uItemID )
+            {
+              case 0x1D6u:
+                ++v4;
+                break;
+              case 0x1D7u:
+                v4 += 3;
+                break;
+              case 0x1DDu:
+                v4 += 5;
+                break;
+            }
+            ++v24;
+            --v25;
+          }
+          while ( v25 );
+          v23 = (ItemGen *)((char *)v23 + 6972);
+        }
+        while ( (signed int)v23 < (signed int)&pParty->field_777C[85] );
+        goto _cmp_against_arg;
+      case VAR_MonthEquals2:
+        v17 = pParty->uCurrentMonth == a1;
+        goto _return2;
+      case VAR_IsFlying:
+        if ( pParty->bFlying
+          && SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) >= 0
+          && (SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[7].uExpireTime) > 0) )
+          goto _return_true;
+        goto _return_false;
+      case VAR_HiredNPCHasSpeciality:
+        LOBYTE(v6) = CheckHiredNPCSpeciality(a1);
+        return v6;
+      case VAR_NPCs2:
+        return pNPCStats->pNewNPCData[a1].uFlags & 0x80;
+      case VAR_MonthEquals|VAR_CurrentSP:
+        v13 = 0x80u >> ((signed __int16)a1 - 1) % 8;
+        v14 = this->field_1A50[((signed __int16)a1 - 1) >> 3];
+        goto LABEL_108;
+      case VAR_ItemEquipped:
+        v26 = (ITEM_EQUIP_TYPE)0;
+        v27 = (char *)&this->pEquipment;
+        break;
+      case VAR_GoldInBank:
+        v4 = pParty->uNumGoldInBank;
+        goto _cmp_against_arg;
+      case VAR_ThieverySkill|0x80:
+        v28 = GetActualMight();
+        v29 = v3->GetBaseStrength();
+        goto LABEL_168;
+      case VAR_DisarmTrapSkill|0x80:
+        v28 = GetActualIntelligence();
+        v29 = v3->GetBaseIntelligence();
+        goto LABEL_168;
+      case VAR_MonthEquals:
+        v28 = GetActualWillpower();
+        v29 = v3->GetBaseWillpower();
+        goto LABEL_168;
+      case VAR_MonthEquals|VAR_Sex:
+        v28 = GetActualEndurance();
+        v29 = v3->GetBaseEndurance();
+        goto LABEL_168;
+      case VAR_IdentifyMonsterSkill|0x80:
+        v28 = GetActualSpeed();
+        v29 = v3->GetBaseSpeed();
+        goto LABEL_168;
+      case VAR_ArmsmasterSkill|0x80:
+        v28 = GetActualAccuracy();
+        v29 = v3->GetBaseAccuracy();
+        goto LABEL_168;
+      case VAR_MonthEquals|VAR_MaxHP:
+        v28 = GetActualLuck();
+        v29 = v3->GetBaseLuck();
+LABEL_168:
+        v10 = __OFSUB__(v28, v29);
+        v9 = v28 - v29 < 0;
+LABEL_169:
+        if ( v9 ^ v10 )
+          goto _cmp_against_arg;
+        goto _return_true;
+      default:
+        goto _cmp_against_arg;
+    }
+    while ( !v3->HasItemEquipped(v26)
+         || *(int *)&v3->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v27 + 5] != a1 )
+    {
+      v26 = (ITEM_EQUIP_TYPE)((int)v26 + 1);
+      v27 += 4;
+      if ( (signed int)v26 >= 16 )
+      {
+_return_false:
+        LOBYTE(v6) = 0;
+        return v6;
+      }
+    }
+    goto _return_true;
+  }
+  if ( var == VAR_AutoNotes )
+  {
+    v13 = 0x80u >> ((signed __int16)(a1 - 1) - 1) % 8;
+    v14 = pParty->_autonote_bits[((signed __int16)(a1 - 1) - 1) >> 3];
+LABEL_108:
+    if ( !((unsigned __int8)v13 & v14) )
+      goto _cmp_against_arg;
+    goto LABEL_109;
+  }
+  if ( var <= VAR_BaseLuck )
+  {
+    if ( var != VAR_BaseLuck )
+    {
+      switch ( var )
+      {
+        case VAR_Hour:
+          if ( (signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 60 / 60 % 24 == a1 )
+            goto _return_true;
+          goto _return_false;
+        case VAR_DayOfYear:
+          v5 = (unsigned int)((signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 60 / 60) / 0x18
+             % 0x150
+             + 1;
+          goto LABEL_9;
+        case VAR_DayOfWeek:
+          v5 = (unsigned int)((signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 60 / 60) / 0x18
+             % 7;
+LABEL_9:
+          LOBYTE(v6) = v5 == a1;
+          return v6;
+        case VAR_Sex:
+          v7 = (CHARACTER_RACE)this->uSex;
+          goto _cmp_against_arg2;
+        case VAR_Class:
+          v7 = (CHARACTER_RACE)this->uClass;
+          goto _cmp_against_arg2;
+        case VAR_Race:
+          v7 = GetRace();
+_cmp_against_arg2:
+          if ( a1 == v7 )
+            goto _return_true;
+          goto _cmp_against_arg;
+        case VAR_CurrentHP:
+          v4 = this->sHealth;
+          goto _cmp_against_arg;
+        case VAR_MaxHP:
+          v8 = GetMaxHealth();
+          v10 = __OFSUB__(v3->sHealth, v8);
+          v9 = v3->sHealth - v8 < 0;
+          goto LABEL_169;
+        case VAR_CurrentSP:
+          v4 = this->sMana;
+          goto _cmp_against_arg;
+        case VAR_MaxSP:
+          v11 = GetMaxMana();
+          v10 = __OFSUB__(v3->sMana, v11);
+          v9 = v3->sMana - v11 < 0;
+          goto LABEL_169;
+        case VAR_ActualAC:
+          v12 = GetActualAC();
+          goto _j_cmp_against_arg;
+        case VAR_ACModifier:
+          v4 = this->sACModifier;
+          goto _cmp_against_arg;
+        case VAR_BaseLevel:
+          v4 = this->uLevel;
+          goto _cmp_against_arg;
+        case VAR_LevelModifier:
+          v4 = this->sLevelModifier;
+          goto _cmp_against_arg;
+        case VAR_Age:
+          v12 = GetActualAge();
+          goto _j_cmp_against_arg;
+        case VAR_Award:
+          v13 = 0x80u >> ((signed __int16)a1 - 1) % 8;
+          v14 = this->field_152[((signed __int16)a1 - 1) >> 3];
+          goto LABEL_108;
+        case VAR_Experience:
+          v4 = LODWORD(this->uExperience);
+          goto _cmp_against_arg;
+        case VAR_QBits_QuestsDone:
+          v13 = 0x80u >> ((signed __int16)a1 - 1) % 8;
+          v14 = pParty->_award_bits[((signed __int16)a1 - 1) >> 3];
+          goto LABEL_108;
+        case VAR_PlayerItemInHands:
+          v15 = 0;
+          v16 = v3->pInventoryItems;
+          break;
+        case VAR_FixedGold:
+          v4 = pParty->uNumGold;
+          goto _cmp_against_arg;
+        case VAR_MightBonus:
+          v4 = this->uMightBonus;
+          goto _cmp_against_arg;
+        case VAR_IntellectBonus:
+          v4 = this->uIntelligenceBonus;
+          goto _cmp_against_arg;
+        case VAR_PersonalityBonus:
+          v4 = this->uWillpowerBonus;
+          goto _cmp_against_arg;
+        case VAR_EnduranceBonus:
+          v4 = this->uEnduranceBonus;
+          goto _cmp_against_arg;
+        case VAR_SpeedBonus:
+          v4 = this->uSpeedBonus;
+          goto _cmp_against_arg;
+        case VAR_AccuracyBonus:
+          v4 = this->uAccuracyBonus;
+          goto _cmp_against_arg;
+        case VAR_LuckBonus:
+          v4 = this->uLuckBonus;
+          goto _cmp_against_arg;
+        case VAR_BaseMight:
+          v4 = this->uMight;
+          goto _cmp_against_arg;
+        case VAR_BaseIntellect:
+          v4 = this->uIntelligence;
+          goto _cmp_against_arg;
+        case VAR_BasePersonality:
+          v4 = this->uWillpower;
+          goto _cmp_against_arg;
+        case VAR_BaseEndurance:
+          v4 = this->uEndurance;
+          goto _cmp_against_arg;
+        case VAR_BaseSpeed:
+          v4 = this->uSpeed;
+          goto _cmp_against_arg;
+        case VAR_BaseAccuracy:
+          v4 = this->uAccuracy;
+          goto _cmp_against_arg;
+        case VAR_FixedFood:
+          v4 = pParty->uNumFoodRations;
+          goto _cmp_against_arg;
+        default:
+          goto _cmp_against_arg;
+      }
+      while ( v16->uItemID != a1 )
+      {
+        ++v15;
+        ++v16;
+        if ( v15 >= 138 )
+        {
+          v17 = pParty->pPickedItem.uItemID == a1;
+_return2:
+          LOBYTE(v6) = v17;
+          return v6;
+        }
+      }
+_return_true:
+      LOBYTE(v6) = 1;
+      return v6;
+    }
+    v4 = this->uLuck;
+    goto _cmp_against_arg;
+  }
+  if ( var <= VAR_MagicResistance )
+  {
+    if ( var == VAR_MagicResistance )
+    {
+      v4 = this->sResMagicBase;
+    }
+    else
+    {
+      switch ( var )
+      {
+        case VAR_FireResistance:
+          v4 = this->sResFireBase;
+          goto _cmp_against_arg;
+        case VAR_AirResistance:
+          v4 = this->sResAirBase;
+          goto _cmp_against_arg;
+        case VAR_WaterResistance:
+          v4 = this->sResWaterBase;
+          goto _cmp_against_arg;
+        case VAR_EarthResistance:
+          v4 = this->sResEarthBase;
+          goto _cmp_against_arg;
+        case VAR_SpiritResistance:
+          v4 = this->sResSpiritBase;
+          goto _cmp_against_arg;
+        case VAR_MindResistance:
+          v4 = this->sResMindBase;
+          goto _cmp_against_arg;
+        case VAR_BodyResistance:
+          v4 = this->sResBodyBase;
+          goto _cmp_against_arg;
+        case VAR_LightResistance:
+          v4 = this->sResLightBase;
+          goto _cmp_against_arg;
+        case VAR_DarkResistance:
+          v4 = this->sResDarkBase;
+          goto _cmp_against_arg;
+        case VAR_ActualMight:
+          v12 = GetActualMight();
+          goto _j_cmp_against_arg;
+        case VAR_ActualIntellect:
+          v12 = GetActualIntelligence();
+          goto _j_cmp_against_arg;
+        case VAR_ActualPersonality:
+          v12 = GetActualWillpower();
+          goto _j_cmp_against_arg;
+        case VAR_ActualEndurance:
+          v12 = GetActualEndurance();
+          goto _j_cmp_against_arg;
+        case VAR_ActualSpeed:
+          v12 = GetActualSpeed();
+          goto _j_cmp_against_arg;
+        case VAR_ActualAccuracy:
+          v12 = GetActualAccuracy();
+          goto _j_cmp_against_arg;
+        case VAR_ActualLuck:
+          v12 = GetActualLuck();
+_j_cmp_against_arg:
+          v4 = v12;
+          break;
+        default:
+          goto _cmp_against_arg;
+      }
+    }
+    goto _cmp_against_arg;
+  }
+  if ( var <= VAR_DisarmTrapSkill )
+  {
+    if ( var != VAR_DisarmTrapSkill )
+    {
+      if ( var <= VAR_MindResistanceBonus )
+      {
+        switch ( var )
+        {
+          case VAR_MindResistanceBonus:
+            v4 = this->sResMindBonus;
+            break;
+          case VAR_FireResistanceBonus:
+            v4 = this->sResFireBonus;
+            break;
+          case VAR_AirResistanceBonus:
+            v4 = this->sResAirBonus;
+            break;
+          case VAR_WaterResistanceBonus:
+            v4 = this->sResWaterBonus;
+            break;
+          case VAR_EarthResistanceBonus:
+            v4 = this->sResEarthBonus;
+            break;
+          case VAR_SpiritResistanceBonus:
+            v4 = this->sResSpiritBonus;
+            break;
+        }
+        goto _cmp_against_arg;
+      }
+      if ( var == VAR_BodyResistanceBonus )
+      {
+        v4 = this->sResBodyBonus;
+        goto _cmp_against_arg;
+      }
+      if ( var == VAR_LightResistanceBonus )
+      {
+        v4 = this->sResLightBonus;
+        goto _cmp_against_arg;
+      }
+      if ( var == VAR_DarkResistanceBonus )
+      {
+        v4 = this->sResDarkBonus;
+        goto _cmp_against_arg;
+      }
+      if ( var == VAR_MagicResistanceBonus )
+      {
+        v4 = this->sResMagicBonus;
+        goto _cmp_against_arg;
+      }
+      if ( var <= VAR_MagicResistanceBonus || var > VAR_DiplomacySkill )
+        goto _cmp_against_arg;
+    }
+LABEL_90:
+    v18 = *((short *)&this->pConditions[16] + var);
+    if ( a1 <= 63 )
+      v4 = v18 & 0x3F;
+    else
+      v4 = a1 & v18;
+    goto _cmp_against_arg;
+  }
+  if ( var == 104 )
+    goto LABEL_90;
+  if ( (signed int)var <= 104 )
+    goto _cmp_against_arg;
+  if ( (signed int)var > 0x79 )
+  {
+    if ( var != 122 )
+    {
+      if ( (signed int)var > 122 && var <= VAR_ActiveSpells )
+        v4 = (unsigned __int8)byte_5E4C15[var];
+      goto _cmp_against_arg;
+    }
+    v4 = GetMajorConditionIdx();
+    if ( v4 != 18 )
+    {
+_cmp_against_arg:
+      LOBYTE(v6) = v4 >= a1;
+      return v6;
+    }
+LABEL_109:
+    v4 = a1;
+    goto _cmp_against_arg;
+  }
+  return *((int *)this + 2 * var - 210);
+}
+
+
+//----- (0044A5CB) --------------------------------------------------------
+void Player::SetVariable(enum VariableType var, signed int a3)
+{
+  signed int v3; // ebx@1
+  Player *v4; // esi@1
+  unsigned int v5; // edi@1
+  unsigned int v6; // esi@13
+  unsigned int v7; // esi@14
+  signed int v8; // eax@17
+  ItemGen *v9; // ecx@17
+  int v10; // eax@21
+  signed int v11; // eax@30
+  Player *v12; // ecx@44
+  char *v13; // ecx@45
+  Player *v14; // ecx@49
+  int v15; // ecx@86
+  int v16; // esi@106
+  char v17; // al@106
+  int v18; // eax@107
+  Player *v19; // ecx@112
+  Player *v20; // ecx@127
+  int v21; // eax@127
+  int v22; // eax@145
+  char v23; // zf@146
+  DDM_DLV_Header *v24; // ecx@148
+  signed int v25; // eax@172
+  int v26; // [sp-8h] [bp-3Ch]@84
+  signed int v27; // [sp-4h] [bp-38h]@4
+  int v28; // [sp-4h] [bp-38h]@84
+  ItemGen item; // [sp+Ch] [bp-28h]@52
+  char v30; // [sp+32h] [bp-2h]@1
+  char v31; // [sp+33h] [bp-1h]@1
+
+  v3 = 0;
+  v30 = 0;
+  v31 = 0;
+  v4 = this;
+  v5 = 0;
+  if ( this == pPlayers[2] )
+  {
+    v3 = 1;
+    goto LABEL_8;
+  }
+  if ( this == pPlayers[3] )
+  {
+    v27 = 2;
+  }
+  else
+  {
+    if ( this != pPlayers[4] )
+      goto LABEL_8;
+    v27 = 3;
+  }
+  v3 = v27;
+LABEL_8:
+  if ( var > VAR_AutoNotes )
+  {
+    if ( var <= VAR_GoldInBank )
+    {
+      if ( var == VAR_GoldInBank )
+      {
+        pParty->uNumGoldInBank = a3;
+        return;
+      }
+      if ( var <= VAR_Counter8 )
+      {
+        if ( (signed int)var >= 245 )
+        {
+          *(int *)&stru_AA1058[3].pSounds[8 * var + 44300] = LODWORD(pParty->uTimePlayed);
+          *(int *)&stru_AA1058[3].pSounds[8 * var + 44304] = HIDWORD(pParty->uTimePlayed);
+        }
+        else
+        {
+          switch ( var )
+          {
+            case VAR_MonthEquals|VAR_CurrentSP:
+              _449B7E_toggle_bit((unsigned char *)field_1A50, a3, 1u);
+              break;
+            case VAR_NPCs2:
+              pParty->field_709 = 0;
+              LOBYTE(pNPCStats->pNewNPCData[a3].uFlags) |= 0x80u;
+              sub_44A56A();
+              viewparams->bRedrawGameUI = 1;
+              break;
+            case VAR_NumSkillPoints:
+              this->uSkillPoints = a3;
+              break;
+          }
+        }
+        return;
+      }
+      if ( var < VAR_Counter9 )
+        return;
+      if ( (signed int)var <= 274 )
+      {
+        *(int *)&stru_AA1058[3].pSounds[8 * var + 44532] = LODWORD(pParty->uTimePlayed);
+        *(int *)&stru_AA1058[3].pSounds[8 * var + 44536] = HIDWORD(pParty->uTimePlayed);
+      }
+      else
+      {
+        if ( var == VAR_ReputationInCurrentLocation )
+        {
+          v24 = &pOutdoor->ddm;
+          if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+            v24 = &pIndoor->dlv;
+          v24->uReputation = a3;
+          if ( a3 > 10000 )
+            v24->uReputation = 10000;
+          return;
+        }
+        if ( var <= VAR_ReputationInCurrentLocation
+          || var > VAR_History_28
+          || (v22 = var - 276, pParty->field_3C.field_4F0[2 * v22 + 1] | pParty->field_3C.field_4F0[2 * v22])
+          || (pParty->field_3C.field_4F0[2 * (var - 276)] = LODWORD(pParty->uTimePlayed),
+              v23 = *(&pStorylineText->field_0 + 3 * v22) == 0,
+              pParty->field_3C.field_4F0[2 * (var - 276) + 1] = HIDWORD(pParty->uTimePlayed),
+              v23) )
+          return;
+        bFlashHistoryBook = 1;
+      }
+LABEL_172:
+      v25 = 8 * v3 + 400;
+      LOBYTE(v25) = (8 * v3 - 112) | 4;
+      pAudioPlayer->PlaySound(SOUND_20001, v25, v5, -1, v5, v5, v5, v5);
+      return;
+    }
+    if ( var != 307 )
+    {
+      switch ( var )
+      {
+        case 308:
+          pParty->uNumBountiesCollected = a3;
+          break;
+        case 309:
+          pParty->uNumPrisonTerms = a3;
+          break;
+        case 310:
+          pParty->uNumArenaPageWins = a3;
+          break;
+        case 311:
+          pParty->uNumArenaSquireWins = a3;
+          break;
+        case 312:
+          pParty->uNumArenaKnightWins = a3;
+          break;
+        case 313:
+          pParty->uNumArenaLordWins = a3;
+          break;
+      }
+      return;
+    }
+    pParty->uNumDeaths = a3;
+LABEL_168:
+    if ( v30 != 1 )
+    {
+LABEL_170:
+      if ( v31 != 1 )
+        return;
+      v5 = 0;
+      goto LABEL_172;
+    }
+LABEL_169:
+    pGame->pStru6Instance->SetPlayerBuffAnim(0x96u, v3);
+    goto LABEL_170;
+  }
+  if ( var == VAR_AutoNotes )
+  {
+    if ( !((unsigned __int8)(0x80u >> ((signed __int16)a3 - 1) % 8) & pParty->_autonote_bits[((signed __int16)a3 - 1) >> 3])
+      && (&dword_723718_autonote_related)[8 * a3] )
+    {
+      v20 = pPlayers[v3 + 1];
+      v30 = 1;
+      v20->PlaySound(96, 0);
+      v21 = dword_72371C[2 * a3];
+      bFlashAutonotesBook = 1;
+      dword_506568 = v21;
+    }
+    _449B7E_toggle_bit(pParty->_autonote_bits, a3, 1u);
+    v31 = 1;
+    goto LABEL_168;
+  }
+  if ( var <= VAR_ActualMight )
+  {
+    if ( var != VAR_ActualMight )
+    {
+      switch ( var )
+      {
+        case VAR_RandomGold:
+          v6 = rand() % a3 + 1;
+          Party::SetGold(v6);
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[500], v6);// You have %lu gold
+          ShowStatusBarString(pTmpBuf, 2u);
+          GameUI_DrawFoodAndGold();
+          return;
+        case VAR_RandomFood:
+          v7 = rand() % a3 + 1;
+          Party::SetFood(v7);
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[501], v7);// You have %lu food
+          ShowStatusBarString(pTmpBuf, 2u);
+          GameUI_DrawFoodAndGold();
+          goto LABEL_124;
+        case VAR_Sex:
+          this->uSex = (PLAYER_SEX)a3;
+          goto LABEL_124;
+        case VAR_Class:
+          this->uClass = a3;
+          if ( (char)a3 != 35 )
+            goto LABEL_124;
+          v8 = 0;
+          v9 = this->pInventoryItems;
+          break;
+        case VAR_CurrentHP:
+          this->sHealth = a3;
+          goto LABEL_124;
+        case VAR_MaxHP:
+          this->sHealth = GetMaxHealth();
+          return;
+        case VAR_CurrentSP:
+          this->sMana = a3;
+          goto LABEL_124;
+        case VAR_MaxSP:
+          this->sMana = GetMaxMana();
+          return;
+        case VAR_ACModifier:
+          this->sACModifier = (unsigned __int8)a3;
+          goto LABEL_124;
+        case VAR_BaseLevel:
+          this->uLevel = (unsigned __int8)a3;
+          goto LABEL_124;
+        case VAR_LevelModifier:
+          this->sLevelModifier = (unsigned __int8)a3;
+          goto LABEL_124;
+        case VAR_Age:
+          this->sAgeModifier = a3;
+          return;
+        case VAR_Award:
+          if ( !((unsigned __int8)(0x80u >> ((signed __int16)a3 - 1) % 8) & pPlayers[v3 + 1]->field_152[((signed __int16)a3 - 1) >> 3])
+            && dword_723E80_award_related[2 * a3] )
+          {
+            v12 = pPlayers[v3 + 1];
+            v30 = 1;
+            v31 = 1;
+            v12->PlaySound(96, 0);
+          }
+          v13 = v4->field_152;
+          goto LABEL_51;
+        case VAR_Experience:
+          this->uExperience = a3;
+          goto LABEL_124;
+        case VAR_QBits_QuestsDone:
+          if ( !((unsigned __int8)(0x80u >> ((signed __int16)a3 - 1) % 8) & pParty->_award_bits[((signed __int16)a3 - 1) >> 3])
+            && (&dword_722F10)[4 * a3] )
+          {
+            v14 = pPlayers[v3 + 1];
+            bFlashQuestBook = 1;
+            v30 = 1;
+            v31 = 1;
+            v14->PlaySound(93, 0);
+          }
+          v13 = (char *)pParty->_award_bits;
+LABEL_51:
+          _449B7E_toggle_bit((unsigned char *)v13, a3, 1u);
+          goto LABEL_168;
+        case VAR_PlayerItemInHands:
+          item.Reset();
+          item.Reset();
+          item.uItemID = a3;
+          item.uAttributes = 1;
+          pParty->SetHoldingItem(&item);
+          if ( a3 >= ITEM_ARTIFACT_PUCK && a3 <= ITEM_RELIC_MEKORIGS_HAMMER )
+            pParty->field_3C.pIsArtifactFound[a3] = 1;
+          return;
+        case VAR_FixedGold:
+          Party::SetGold(a3);
+          return;
+        case VAR_BaseMight:
+          this->uMight = (unsigned __int8)a3;
+          goto LABEL_84;
+        case VAR_BaseIntellect:
+          this->uIntelligence = (unsigned __int8)a3;
+          goto LABEL_84;
+        case VAR_BasePersonality:
+          this->uWillpower = (unsigned __int8)a3;
+          goto LABEL_84;
+        case VAR_BaseEndurance:
+          this->uEndurance = (unsigned __int8)a3;
+          goto LABEL_84;
+        case VAR_BaseSpeed:
+          this->uSpeed = (unsigned __int8)a3;
+          goto LABEL_84;
+        case VAR_BaseAccuracy:
+          this->uAccuracy = (unsigned __int8)a3;
+          goto LABEL_84;
+        case VAR_BaseLuck:
+          this->uLuck = (unsigned __int8)a3;
+          goto LABEL_84;
+        case VAR_FixedFood:
+          Party::SetFood(a3);
+          goto LABEL_124;
+        case VAR_MightBonus:
+          goto LABEL_64;
+        case VAR_IntellectBonus:
+          goto LABEL_68;
+        case VAR_PersonalityBonus:
+          goto LABEL_69;
+        case VAR_EnduranceBonus:
+          goto LABEL_70;
+        case VAR_SpeedBonus:
+          goto LABEL_71;
+        case VAR_AccuracyBonus:
+          goto LABEL_72;
+        case VAR_LuckBonus:
+          goto LABEL_73;
+        default:
+          return;
+      }
+      while ( v9->uItemID != 615 )
+      {
+        ++v8;
+        ++v9;
+        if ( v8 >= 138 )
+          goto LABEL_22;
+      }
+      v10 = (int)((char *)v4 + 36 * v8);
+      *(int *)(v10 + 532) = 601;
+      *(char *)(v10 + 558) = v3 + 1;
+LABEL_22:
+      if ( v4->sResFireBase < 20 )
+        v4->sResFireBase = 20;
+      if ( v4->sResAirBase < 20 )
+        v4->sResAirBase = 20;
+      if ( v4->sResWaterBase < 20 )
+        v4->sResWaterBase = 20;
+      if ( v4->sResEarthBase < 20 )
+        v4->sResEarthBase = 20;
+      v4->sResMindBase = 200;
+      v4->sResBodyBase = 200;
+      v11 = v4->GetSexByVoice();
+      v4->field_1924 = v4->uVoiceID;
+      v4->field_1928 = v4->uFace;
+      if ( v11 )
+      {
+        v4->uFace = 21;
+        v4->uVoiceID = 21;
+      }
+      else
+      {
+        v4->uFace = 20;
+        v4->uVoiceID = 20;
+      }
+      ReloadPlayerPortraits(v3, v4->uFace);
+      goto LABEL_124;
+    }
+LABEL_64:
+    this->uMightBonus = (unsigned __int8)a3;
+LABEL_111:
+    v28 = 0;
+    v26 = 91;
+LABEL_112:
+    v19 = pPlayers[v3 + 1];
+    v31 = 1;
+    v19->PlaySound(v26, v28);
+    goto LABEL_169;
+  }
+  if ( var <= VAR_FireResistanceBonus )
+  {
+    if ( var == VAR_FireResistanceBonus )
+    {
+      this->sResFireBonus = (unsigned __int8)a3;
+      goto LABEL_111;
+    }
+    switch ( var )
+    {
+      case VAR_ActualIntellect:
+LABEL_68:
+        this->uIntelligenceBonus = (unsigned __int8)a3;
+        goto LABEL_111;
+      case VAR_ActualPersonality:
+LABEL_69:
+        this->uWillpowerBonus = (unsigned __int8)a3;
+        goto LABEL_111;
+      case VAR_ActualEndurance:
+LABEL_70:
+        this->uEnduranceBonus = (unsigned __int8)a3;
+        goto LABEL_111;
+      case VAR_ActualSpeed:
+LABEL_71:
+        this->uSpeedBonus = (unsigned __int8)a3;
+        goto LABEL_111;
+      case VAR_ActualAccuracy:
+LABEL_72:
+        this->uAccuracyBonus = (unsigned __int8)a3;
+        goto LABEL_111;
+      case VAR_ActualLuck:
+LABEL_73:
+        this->uLuckBonus = (unsigned __int8)a3;
+        goto LABEL_111;
+      case VAR_FireResistance:
+        this->sResFireBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_AirResistance:
+        this->sResAirBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_WaterResistance:
+        this->sResWaterBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_EarthResistance:
+        this->sResEarthBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_SpiritResistance:
+        this->sResSpiritBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_MindResistance:
+        this->sResMindBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_BodyResistance:
+        this->sResBodyBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_LightResistance:
+        this->sResLightBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_DarkResistance:
+        this->sResDarkBase = (unsigned __int8)a3;
+        goto LABEL_84;
+      case VAR_MagicResistance:
+        this->sResMagicBase = (unsigned __int8)a3;
+LABEL_84:
+        v28 = 0;
+        v26 = 92;
+        goto LABEL_112;
+      default:
+        return;
+    }
+    return;
+  }
+  HIWORD(v15) = 0;
+  if ( var > VAR_DisarmTrapSkill )
+  {
+    if ( var != VAR_LearningSkill )
+    {
+      if ( var <= VAR_LearningSkill )
+        return;
+      if ( var <= VAR_Eradicated )
+      {
+        v4->SetCondition(var - 105, 1);
+      }
+      else
+      {
+        if ( var != VAR_MajorCondition )
+        {
+          if ( var > VAR_MajorCondition && var <= VAR_ActiveSpells )
+            byte_5E4C15[var] = a3;
+          return;
+        }
+        memset(v4, 0, 0xA0u);
+      }
+LABEL_124:
+      v31 = 1;
+      goto LABEL_169;
+    }
+LABEL_106:
+    v16 = (int)((char *)&v4->pConditions[16] + 2 * var);
+    v17 = *(char *)v16;
+    if ( a3 <= VAR_BodyResistanceBonus )
+    {
+      LOWORD(v15) = (unsigned __int8)a3;
+      v18 = v15 | v17 & VAR_BodyResistanceBonus;
+    }
+    else
+    {
+      LOWORD(v18) = (unsigned __int8)(a3 | v17 & 0xC0);
+    }
+    *(short *)v16 = v18;
+    goto LABEL_124;
+  }
+  if ( var == VAR_DisarmTrapSkill )
+    goto LABEL_106;
+  if ( var <= VAR_BodyResistanceBonus )
+  {
+    switch ( var )
+    {
+      case VAR_BodyResistanceBonus:
+        v4->sResBodyBonus = (unsigned __int8)a3;
+        break;
+      case VAR_AirResistanceBonus:
+        v4->sResAirBonus = (unsigned __int8)a3;
+        break;
+      case VAR_WaterResistanceBonus:
+        v4->sResWaterBonus = (unsigned __int8)a3;
+        break;
+      case VAR_EarthResistanceBonus:
+        v4->sResEarthBonus = (unsigned __int8)a3;
+        break;
+      case VAR_SpiritResistanceBonus:
+        v4->sResSpiritBonus = (unsigned __int8)a3;
+        break;
+      default:
+        if ( var != 62 )
+          return;
+        v4->sResMindBonus = (unsigned __int8)a3;
+        break;
+    }
+    goto LABEL_111;
+  }
+  if ( var == VAR_LightResistanceBonus )
+  {
+    v4->sResLightBonus = (unsigned __int8)a3;
+    goto LABEL_111;
+  }
+  if ( var == VAR_DarkResistanceBonus )
+  {
+    v4->sResDarkBonus = (unsigned __int8)a3;
+    goto LABEL_111;
+  }
+  if ( var == VAR_MagicResistanceBonus )
+  {
+    v4->sResMagicBonus = (unsigned __int8)a3;
+    goto LABEL_111;
+  }
+  if ( var > VAR_MagicResistanceBonus && var <= VAR_DiplomacySkill )
+    goto LABEL_106;
+}
+
+
+
+//----- (0044AFFB) --------------------------------------------------------
+void Player::AddVariable(enum VariableType var, signed int val)
+{
+  char v3; // bl@1
+  Player *v4; // esi@1
+  signed int uPlayerIdx; // edi@1
+  int v6; // eax@15
+  unsigned int v7; // esi@18
+  int *v8; // ebx@21
+  int v9; // eax@22
+  signed int v10; // eax@24
+  int v11; // eax@27
+  __int16 *v12; // esi@28
+  Player *v13; // ecx@34
+  Player *v14; // ecx@36
+  char *v15; // ecx@37
+  unsigned __int8 v16; // cf@38
+  Player *v17; // ecx@42
+  __int16 *v18; // esi@53
+  __int16 *v19; // esi@62
+  char *v20; // esi@107
+  __int16 v21; // dx@107
+  int v22; // ecx@107
+  Player *v23; // ecx@132
+  int v24; // eax@132
+  int v25; // eax@150
+  char v26; // zf@151
+  DDM_DLV_Header *v27; // eax@153
+  signed int v28; // eax@176
+  int v29; // [sp-8h] [bp-40h]@84
+  signed int v30; // [sp-4h] [bp-3Ch]@4
+  int v31; // [sp-4h] [bp-3Ch]@84
+  ItemGen item; // [sp+Ch] [bp-2Ch]@45
+  unsigned int v33; // [sp+30h] [bp-8h]@34
+  char v34; // [sp+37h] [bp-1h]@1
+
+  auto Dst = this;
+  v3 = 0;
+  v34 = 0;
+  v4 = Dst;
+  uPlayerIdx = 0;
+  if ( Dst == pPlayers[2] )
+  {
+    uPlayerIdx = 1;
+    goto LABEL_8;
+  }
+  if ( Dst == pPlayers[3] )
+  {
+    v30 = 2;
+  }
+  else
+  {
+    if ( Dst != pPlayers[4] )
+      goto LABEL_8;
+    v30 = 3;
+  }
+  uPlayerIdx = v30;
+LABEL_8:
+  if ( var <= VAR_AutoNotes )
+  {
+    if ( var != VAR_AutoNotes )
+    {
+      if ( var <= VAR_ActualMight )
+      {
+        if ( var != VAR_ActualMight )
+        {
+          switch ( var )
+          {
+            case VAR_RandomGold:
+              if ( !val )
+                val = 1;
+              v6 = rand();
+              party_finds_gold(v6 % val + 1, 1);
+              GameUI_DrawFoodAndGold();
+              return;
+            case VAR_RandomFood:
+              if ( !val )
+                val = 1;
+              v7 = rand() % val + 1;
+              Party::GiveFood(v7);
+              sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[502], v7);// You find %lu food
+              ShowStatusBarString(pTmpBuf, 2u);
+              GameUI_DrawFoodAndGold();
+              goto _play_sound;
+            case VAR_Sex:
+              Dst->uSex = (PLAYER_SEX)val;
+              goto _play_anim_and_exit;
+            case VAR_Class:
+              Dst->uClass = val;
+              goto _play_anim_and_exit;
+            case VAR_CurrentHP:
+              v8 = &Dst->sHealth;
+              *v8 += val;
+              if ( Dst->sHealth <= Dst->GetMaxHealth() )
+                goto _play_anim_and_exit;
+              v9 = v4->GetMaxHealth();
+              goto LABEL_23;
+            case VAR_MaxHP:
+              v10 = Dst->GetMaxHealth();
+              v4->_health_related = 0;
+              v4->uFullHealthBonus = 0;
+              v4->sHealth = v10;
+              return;
+            case VAR_CurrentSP:
+              v8 = &Dst->sMana;
+              *v8 += val;
+              if ( Dst->sMana > GetMaxMana() )
+              {
+                v9 = v4->GetMaxMana();
+LABEL_23:
+                *v8 = v9;
+              }
+              goto _play_anim_and_exit;
+            case VAR_MaxSP:
+              v11 = GetMaxMana();
+              v4->_mana_related = 0;
+              v4->uFullManaBonus = 0;
+              v4->sMana = v11;
+              return;
+            case VAR_ACModifier:
+              v12 = &Dst->sACModifier;
+              goto LABEL_29;
+            case VAR_BaseLevel:
+              v12 = (__int16 *)&Dst->uLevel;
+              goto LABEL_29;
+            case VAR_LevelModifier:
+              v12 = &Dst->sLevelModifier;
+LABEL_29:
+              *v12 += val;
+              if ( *v12 > 255 )
+                *v12 = 255;
+              goto _play_anim_and_exit;
+            case VAR_Age:
+              Dst->sAgeModifier += val;
+              return;
+            case VAR_Award:
+              v13 = pPlayers[uPlayerIdx + 1];
+              v33 = 0x80u >> ((signed __int16)val - 1) % 8;
+              if ( !((unsigned __int8)(0x80u >> ((signed __int16)val - 1) % 8) & v13->field_152[((signed __int16)val - 1) >> 3])
+                && dword_723E80_award_related[2 * val] )
+              {
+                v14 = pPlayers[uPlayerIdx + 1];
+                v34 = 1;
+                v3 = 1;
+                v14->PlaySound(96, 0);
+              }
+              v15 = v4->field_152;
+              goto LABEL_44;
+            case VAR_Experience:
+              v16 = __CFADD__(val, LODWORD(Dst->uExperience));
+              LODWORD(Dst->uExperience) += val;
+              HIDWORD(Dst->uExperience) += ((unsigned __int64)val >> 32) + v16;
+              if ( (signed __int64)Dst->uExperience > 4000000000i64 )
+                Dst->uExperience = 4000000000i64;
+              goto _play_anim_and_exit;
+            case VAR_QBits_QuestsDone:
+              if ( !((unsigned __int8)(0x80u >> ((signed __int16)val - 1) % 8) & pParty->_award_bits[((signed __int16)val - 1) >> 3])
+                && (&dword_722F10)[4 * val] )
+              {
+                v17 = pPlayers[uPlayerIdx + 1];
+                bFlashQuestBook = 1;
+                v34 = 1;
+                v3 = 1;
+                v17->PlaySound(93, 0);
+              }
+              v15 = (char *)pParty->_award_bits;
+LABEL_44:
+              _449B7E_toggle_bit((unsigned char *)v15, val, 1u);
+              goto LABEL_173;
+            case VAR_PlayerItemInHands:
+              item.Reset();
+              item.Reset();
+              item.uAttributes = 1;
+              item.uItemID = val;
+              if ( val >= ITEM_ARTIFACT_PUCK && val <= ITEM_RELIC_MEKORIGS_HAMMER )
+                pParty->field_3C.pIsArtifactFound[val] = 1;
+              if ( val >= ITEM_WAND_FIRE && val <= ITEM_WAND_INCENERATION )
+              {
+                item.uNumCharges = rand() % 6 + pItemsTable->pItems[item.uItemID].uDamageMod + 1;
+                item.uMaxCharges = LOBYTE(item.uNumCharges);
+              }
+              pParty->SetHoldingItem(&item);
+              return;
+            case VAR_FixedGold:
+              party_finds_gold(val, 1);
+              return;
+            case VAR_BaseMight:
+              v18 = (__int16 *)&Dst->uMight;
+              goto LABEL_82;
+            case VAR_BaseIntellect:
+              v18 = (__int16 *)&Dst->uIntelligence;
+              goto LABEL_82;
+            case VAR_BasePersonality:
+              v18 = (__int16 *)&Dst->uWillpower;
+              goto LABEL_82;
+            case VAR_BaseEndurance:
+              v18 = (__int16 *)&Dst->uEndurance;
+              goto LABEL_82;
+            case VAR_BaseSpeed:
+              v18 = (__int16 *)&Dst->uSpeed;
+              goto LABEL_82;
+            case VAR_BaseAccuracy:
+              v18 = (__int16 *)&Dst->uAccuracy;
+              goto LABEL_82;
+            case VAR_BaseLuck:
+              v18 = (__int16 *)&Dst->uLuck;
+              goto LABEL_82;
+            case VAR_FixedFood:
+              Party::GiveFood(val);
+              sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[502], val);
+              ShowStatusBarString(pTmpBuf, 2u);
+              if ( pParty->uNumFoodRations > 0xFFFF )
+                Party::SetFood(0xFFFFu);
+              goto _play_sound;
+            case VAR_MightBonus:
+              goto LABEL_62;
+            case VAR_IntellectBonus:
+              goto LABEL_66;
+            case VAR_PersonalityBonus:
+              goto LABEL_67;
+            case VAR_EnduranceBonus:
+              goto LABEL_68;
+            case VAR_SpeedBonus:
+              goto LABEL_69;
+            case VAR_AccuracyBonus:
+              goto LABEL_70;
+            case VAR_LuckBonus:
+              goto LABEL_71;
+            default:
+              return;
+          }
+          return;
+        }
+LABEL_62:
+        v19 = (__int16 *)&Dst->uMightBonus;
+        goto LABEL_113;
+      }
+      if ( var <= VAR_FireResistanceBonus )
+      {
+        if ( var != VAR_FireResistanceBonus )
+        {
+          switch ( var )
+          {
+            case VAR_ActualIntellect:
+LABEL_66:
+              v19 = (__int16 *)&Dst->uIntelligenceBonus;
+              goto LABEL_113;
+            case VAR_ActualPersonality:
+LABEL_67:
+              v19 = (__int16 *)&Dst->uWillpowerBonus;
+              goto LABEL_113;
+            case VAR_ActualEndurance:
+LABEL_68:
+              v19 = (__int16 *)&Dst->uEnduranceBonus;
+              goto LABEL_113;
+            case VAR_ActualSpeed:
+LABEL_69:
+              v19 = (__int16 *)&Dst->uSpeedBonus;
+              goto LABEL_113;
+            case VAR_ActualAccuracy:
+LABEL_70:
+              v19 = (__int16 *)&Dst->uAccuracyBonus;
+              goto LABEL_113;
+            case VAR_ActualLuck:
+LABEL_71:
+              v19 = (__int16 *)&Dst->uLuckBonus;
+              goto LABEL_113;
+            case VAR_FireResistance:
+              v18 = &Dst->sResFireBase;
+              goto LABEL_82;
+            case VAR_AirResistance:
+              v18 = &Dst->sResAirBase;
+              goto LABEL_82;
+            case VAR_WaterResistance:
+              v18 = &Dst->sResWaterBase;
+              goto LABEL_82;
+            case VAR_EarthResistance:
+              v18 = &Dst->sResEarthBase;
+              goto LABEL_82;
+            case VAR_SpiritResistance:
+              v18 = &Dst->sResSpiritBase;
+              goto LABEL_82;
+            case VAR_MindResistance:
+              v18 = &Dst->sResMindBase;
+              goto LABEL_82;
+            case VAR_BodyResistance:
+              v18 = &Dst->sResBodyBase;
+              goto LABEL_82;
+            case VAR_LightResistance:
+              v18 = &Dst->sResLightBase;
+              goto LABEL_82;
+            case VAR_DarkResistance:
+              v18 = &Dst->sResDarkBase;
+              goto LABEL_82;
+            case VAR_MagicResistance:
+              v18 = &Dst->sResMagicBase;
+LABEL_82:
+              *v18 += val;
+              if ( *v18 > 255 )
+                *v18 = 255;
+              v31 = 0;
+              v29 = 92;
+              goto LABEL_116;
+            default:
+              return;
+          }
+          return;
+        }
+        v19 = &Dst->sResFireBonus;
+LABEL_113:
+        *v19 += val;
+        if ( *v19 > 255 )
+          *v19 = 255;
+        v31 = 0;
+        v29 = 91;
+LABEL_116:
+        v3 = 1;
+        pPlayers[uPlayerIdx + 1]->PlaySound(v29, v31);
+        goto _play_anim_and_maybe_sound;
+      }
+      if ( var <= VAR_DisarmTrapSkill )
+      {
+        if ( var != VAR_DisarmTrapSkill )
+        {
+          if ( var <= VAR_BodyResistanceBonus )
+          {
+            switch ( var )
+            {
+              case VAR_BodyResistanceBonus:
+                v19 = &Dst->sResBodyBonus;
+                break;
+              case VAR_AirResistanceBonus:
+                v19 = &Dst->sResAirBonus;
+                break;
+              case VAR_WaterResistanceBonus:
+                v19 = &Dst->sResWaterBonus;
+                break;
+              case VAR_EarthResistanceBonus:
+                v19 = &Dst->sResEarthBonus;
+                break;
+              case VAR_SpiritResistanceBonus:
+                v19 = &Dst->sResSpiritBonus;
+                break;
+              default:
+                if ( var != 62 )
+                  return;
+                v19 = &Dst->sResMindBonus;
+                break;
+            }
+            goto LABEL_113;
+          }
+          if ( var == VAR_LightResistanceBonus )
+          {
+            v19 = &Dst->sResLightBonus;
+            goto LABEL_113;
+          }
+          if ( var == VAR_DarkResistanceBonus )
+          {
+            v19 = &Dst->sResDarkBonus;
+            goto LABEL_113;
+          }
+          if ( var == VAR_MagicResistanceBonus )
+          {
+            v19 = &Dst->sResMagicBonus;
+            goto LABEL_113;
+          }
+          if ( var <= VAR_MagicResistanceBonus || var > VAR_DiplomacySkill )
+            return;
+        }
+        goto LABEL_106;
+      }
+      if ( var == VAR_LearningSkill )
+      {
+LABEL_106:
+        if ( val <= VAR_BodyResistanceBonus )
+        {
+          *((short *)&Dst->pConditions[16] + var) = (unsigned __int8)val | *((char *)&Dst->pConditions[16] + 2 * var) & VAR_BodyResistanceBonus;
+        }
+        else
+        {
+          v20 = (char *)&Dst->pConditions[16] + 2 * var;
+          v21 = *(short *)v20;
+          v22 = (unsigned __int8)val + (v21 & VAR_BodyResistanceBonus);
+          if ( v22 > 60 )
+            LOWORD(v22) = 60;
+          LOBYTE(v21) = v21 & 0xC0;
+          *(short *)v20 = v22 | v21;
+        }
+        goto _play_anim_and_exit;
+      }
+      if ( var <= VAR_LearningSkill )
+        return;
+      if ( var <= VAR_Eradicated )
+      {
+        Dst->SetCondition(var - 105, 0);
+      }
+      else
+      {
+        if ( var != VAR_MajorCondition )
+        {
+          if ( var > VAR_MajorCondition && var <= VAR_ActiveSpells )
+          {
+            if ( (unsigned __int8)val + (unsigned __int8)byte_5E4C15[var] <= 255 )
+              byte_5E4C15[var] += val;
+            else
+              byte_5E4C15[var] = -1;
+          }
+          return;
+        }
+        memset(Dst, 0, 0xA0u);
+      }
+_play_anim_and_exit:
+      v3 = 1;
+_play_anim_and_maybe_sound:
+      pGame->pStru6Instance->SetPlayerBuffAnim(0x97u, uPlayerIdx);
+_maybe_play_sound:
+      if ( v3 != 1 )
+        return;
+      goto _play_sound;
+    }
+    if ( !((unsigned __int8)(0x80u >> ((signed __int16)val - 1) % 8) & pParty->_autonote_bits[((signed __int16)val - 1) >> 3])
+      && (&dword_723718_autonote_related)[8 * val] )
+    {
+      v23 = pPlayers[uPlayerIdx + 1];
+      v34 = 1;
+      v23->PlaySound(96, 0);
+      v24 = dword_72371C[2 * val];
+      bFlashAutonotesBook = 1;
+      dword_506568 = v24;
+    }
+    _449B7E_toggle_bit(pParty->_autonote_bits, val, 1u);
+    v3 = 1;
+LABEL_173:
+    if ( v34 != 1 )
+      goto _maybe_play_sound;
+    goto _play_anim_and_maybe_sound;
+  }
+  if ( var > VAR_GoldInBank )
+  {
+    if ( var == 307 )
+    {
+      pParty->uNumDeaths += val;
+      goto LABEL_173;
+    }
+    switch ( var )
+    {
+      case 308:
+        pParty->uNumBountiesCollected += val;
+        break;
+      case 309:
+        pParty->uNumPrisonTerms += val;
+        break;
+      case 310:
+        pParty->uNumArenaPageWins += val;
+        break;
+      case 311:
+        pParty->uNumArenaSquireWins += val;
+        break;
+      case 312:
+        pParty->uNumArenaKnightWins += val;
+        break;
+      case 313:
+        pParty->uNumArenaLordWins += val;
+        break;
+    }
+  }
+  else
+  {
+    if ( var == VAR_GoldInBank )
+    {
+      pParty->uNumGoldInBank += val;
+      return;
+    }
+    if ( var <= VAR_Counter8 )
+    {
+      if ( (signed int)var >= 245 )
+      {
+        *(int *)&stru_AA1058[3].pSounds[8 * var + 44300] = LODWORD(pParty->uTimePlayed);
+        *(int *)&stru_AA1058[3].pSounds[8 * var + 44304] = HIDWORD(pParty->uTimePlayed);
+      }
+      else
+      {
+        switch ( var )
+        {
+          case VAR_MonthEquals|VAR_CurrentSP:
+            _449B7E_toggle_bit((unsigned char *)Dst->field_1A50, val, 1u);
+            break;
+          case VAR_NPCs2:
+            pParty->field_709 = 0;
+            LOBYTE(pNPCStats->pNewNPCData[val].uFlags) |= 0x80u;
+            sub_44A56A();
+            viewparams->bRedrawGameUI = 1;
+            break;
+          case VAR_NumSkillPoints:
+            Dst->uSkillPoints += val;
+            break;
+        }
+      }
+      return;
+    }
+    if ( var < VAR_Counter9 )
+      return;
+    if ( (signed int)var <= 274 )
+    {
+      *(int *)&stru_AA1058[3].pSounds[8 * var + 44532] = LODWORD(pParty->uTimePlayed);
+      *(int *)&stru_AA1058[3].pSounds[8 * var + 44536] = HIDWORD(pParty->uTimePlayed);
+      goto _play_sound;
+    }
+    if ( var != VAR_ReputationInCurrentLocation )
+    {
+      if ( var <= VAR_ReputationInCurrentLocation
+        || var > VAR_History_28
+        || (v25 = var - 276, pParty->field_3C.field_4F0[2 * v25 + 1] | pParty->field_3C.field_4F0[2 * v25])
+        || (pParty->field_3C.field_4F0[2 * (var - 276)] = LODWORD(pParty->uTimePlayed),
+            v26 = *(&pStorylineText->field_0 + 3 * v25) == 0,
+            pParty->field_3C.field_4F0[2 * (var - 276) + 1] = HIDWORD(pParty->uTimePlayed),
+            v26) )
+        return;
+      bFlashHistoryBook = 1;
+_play_sound:
+      v28 = 8 * uPlayerIdx + 400;
+      LOBYTE(v28) = (8 * uPlayerIdx - 112) | 4;
+      pAudioPlayer->PlaySound(SOUND_20001, v28, 0, -1, 0, 0, 0, 0);
+      return;
+    }
+    v27 = &pOutdoor->ddm;
+    if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+      v27 = &pIndoor->dlv;
+    v27->uReputation += val;
+    if ( v27->uReputation > 10000 )
+      v27->uReputation = 10000;
+  }
+}
+// 506568: using guessed type int dword_506568;
+// 507948: using guessed type char bFlashHistoryBook;
+// 507949: using guessed type char bFlashAutonotesBook;
+// 50794A: using guessed type char bFlashQuestBook;
+// 72371C: using guessed type int dword_72371C[];
+// 723E80: using guessed type int dword_723E80_award_related[];
+
+
+
+
+//----- (0044B9C4) --------------------------------------------------------
+void Player::SubtractVariable(enum VariableType var, void *a3)
+{
+  unsigned int v3; // ebx@1
+  signed int v4; // esi@1
+  enum VariableType v5; // eax@8
+  int v6; // esi@11
+  int v7; // edi@14
+  signed int v8; // eax@17
+  char *v9; // eax@20
+  char v10; // sf@20
+  char *v11; // ecx@26
+  char *v12; // ecx@27
+  __int64 v13; // qax@27
+  unsigned __int8 v14; // cf@27
+  char *v15; // edx@29
+  char *v16; // eax@90
+  char *v17; // ecx@94
+  void *v18; // esi@97
+  signed int v19; // edx@97
+  char *v20; // ecx@98
+  int v21; // eax@100
+  __int16 v22; // dx@112
+  int v23; // [sp-8h] [bp-14h]@45
+  signed int v24; // [sp-4h] [bp-10h]@4
+  int v25; // [sp-4h] [bp-10h]@45
+
+  v3 = 0;
+  v4 = 0;
+  if ( this == pPlayers[2] )
+  {
+    v4 = 1;
+    goto LABEL_8;
+  }
+  if ( this == pPlayers[3] )
+  {
+    v24 = 2;
+  }
+  else
+  {
+    if ( this != pPlayers[4] )
+      goto LABEL_8;
+    v24 = 3;
+  }
+  v4 = v24;
+LABEL_8:
+  v5 = var;
+  if ( (signed int)var > 222 )
+  {
+    if ( (signed int)var <= 307 )
+    {
+      if ( var == 307 )
+      {
+        pParty->uNumDeaths -= (unsigned int)a3;
+        return;
+      }
+      if ( var == 223 )
+      {
+        v11 = (char *)pParty->_autonote_bits;
+        v22 = (short)a3 - 1;
+      }
+      else
+      {
+        if ( var != 231 )
+        {
+          switch ( var )
+          {
+            case 232:
+              var = (VariableType)0;
+              GetNewNPCData(uDialogue_SpeakingActorNPC_ID, (int)&var);
+              dword_5B65CC = 0;
+              if ( (void *)var == a3 )
+              {
+                dword_5B65CC = (int)a3;
+              }
+              else
+              {
+                pParty->field_709 = 0;
+                LOBYTE(pNPCStats->pNewNPCData[(int)a3].uFlags) &= 0x7Fu;
+                sub_44A56A();
+                viewparams->bRedrawGameUI = 1;
+              }
+              break;
+            case 241:
+              v18 = a3;
+              v19 = 0;
+              if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+              {
+                v20 = (char *)&pNPCStats->pNewNPCData[0].uFlags;
+                do
+                {
+                  if ( *((void **)v20 + 4) == v18 )
+                  {
+                    v21 = *(int *)v20;
+                    if ( (char)*(int *)v20 < 0 )
+                    {
+                      LOBYTE(v21) = v21 & 0x7F;
+                      *(int *)v20 = v21;
+                    }
+                  }
+                  ++v19;
+                  v20 += 76;
+                }
+                while ( v19 < (signed int)pNPCStats->uNumNewNPCs );
+              }
+              if ( (void *)pParty->pHirelings[0].uProfession == v18 )
+                memset(pParty->pHirelings, 0, 0x4Cu);
+              if ( (void *)pParty->pHirelings[1].uProfession == v18 )
+                memset(&pParty->pHirelings[1], 0, 0x4Cu);
+              pParty->field_709 = 0;
+              sub_44A56A();
+              break;
+            case 243:
+              v17 = (char *)&this->uSkillPoints;
+              if ( (unsigned int)a3 <= *(int *)v17 )
+                *(int *)v17 -= (int)a3;
+              else
+                *(int *)v17 = 0;
+              break;
+            case 275:
+              v16 = (char *)&pOutdoor->ddm;
+              if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+                v16 = (char *)&pIndoor->dlv;
+              *((int *)v16 + 2) -= (int)a3;
+              if ( *((int *)v16 + 2) < -10000 )
+                *((int *)v16 + 2) = -10000;
+              break;
+            case 306:
+              if ( (unsigned int)a3 <= pParty->uNumGoldInBank )
+                pParty->uNumGoldInBank -= (unsigned int)a3;
+              else
+LABEL_88:
+                dword_5B65C4 = 1;
+              break;
+          }
+          return;
+        }
+        v11 = this->field_1A50;
+LABEL_112:
+        v22 = (signed __int16)a3;
+      }
+      _449B7E_toggle_bit((unsigned char *)v11, v22, 0);
+      return;
+    }
+    switch ( var )
+    {
+      case 308:
+        pParty->uNumBountiesCollected -= (unsigned int)a3;
+        break;
+      case 309:
+        pParty->uNumPrisonTerms -= (int)a3;
+        break;
+      case 310:
+        pParty->uNumArenaPageWins -= (char)a3;
+        break;
+      case 311:
+        pParty->uNumArenaSquireWins -= (char)a3;
+        break;
+      case 312:
+        pParty->uNumArenaKnightWins -= (char)a3;
+        break;
+      case 313:
+        pParty->uNumArenaLordWins -= (char)a3;
+        break;
+    }
+  }
+  else
+  {
+    if ( (signed int)var >= 123 )
+    {
+      byte_5E4C15[var] -= (char)a3;
+    }
+    else
+    {
+      switch ( var )
+      {
+        case VAR_RandomGold:
+          v6 = rand() % (signed int)a3 + 1;
+          if ( v6 > pParty->uNumGold )
+            v6 = pParty->uNumGold;
+          Party::TakeGold(v6);
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[503], v6);
+          ShowStatusBarString(pTmpBuf, 2u);
+          GameUI_DrawFoodAndGold();
+          return;
+        case VAR_RandomFood:
+          v7 = rand() % (signed int)a3 + 1;
+          if ( v7 > pParty->uNumFoodRations )
+            v7 = pParty->uNumFoodRations;
+          Party::TakeFood(v7);
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[504], v7);
+          ShowStatusBarString(pTmpBuf, 2u);
+          GameUI_DrawFoodAndGold();
+          goto LABEL_17;
+        default:
+          return;
+        case VAR_CurrentHP:
+          ReceiveDamage((signed int)a3, 4);
+          goto LABEL_17;
+        case VAR_CurrentSP:
+          v9 = (char *)&this->sMana;
+          v10 = this->sMana - (signed int)a3 < 0;
+          *(int *)v9 -= (int)a3;
+          if ( v10 )
+            *(int *)v9 = 0;
+          goto LABEL_17;
+        case VAR_ACModifier:
+          this->sACModifier -= (unsigned __int8)a3;
+          goto LABEL_17;
+        case VAR_BaseLevel:
+          this->uLevel -= (unsigned __int8)a3;
+          goto LABEL_17;
+        case VAR_LevelModifier:
+          this->sLevelModifier -= (unsigned __int8)a3;
+          goto LABEL_17;
+        case VAR_Age:
+          this->sAgeModifier -= (signed __int16)a3;
+          return;
+        case VAR_Award:
+          v11 = this->field_152;
+          goto LABEL_112;
+        case VAR_Experience:
+          v12 = (char *)&this->uExperience;
+          v13 = (signed int)a3;
+          v14 = *(int *)v12 < (unsigned int)a3;
+          *(int *)v12 -= (int)a3;
+          *((int *)v12 + 1) -= v14 + HIDWORD(v13);
+          goto LABEL_17;
+        case VAR_QBits_QuestsDone:
+          _449B7E_toggle_bit(pParty->_award_bits, (__int16)a3, 0);
+          pPlayers[v4 + 1]->PlaySound(96, 0);
+          return;
+        case VAR_PlayerItemInHands:
+          v15 = (char *)this->pInventoryIndices;
+          break;
+        case VAR_FixedGold:
+          if ( (unsigned int)a3 > pParty->uNumGold )
+            goto LABEL_88;
+          Party::TakeGold((unsigned int)a3);
+          return;
+        case VAR_MightBonus:
+        case VAR_ActualMight:
+          this->uMightBonus -= (unsigned __int16)a3;
+          goto LABEL_72;
+        case VAR_IntellectBonus:
+        case VAR_ActualIntellect:
+          this->uIntelligenceBonus -= (unsigned __int16)a3;
+          goto LABEL_72;
+        case VAR_PersonalityBonus:
+        case VAR_ActualPersonality:
+          this->uWillpowerBonus -= (unsigned __int16)a3;
+          goto LABEL_72;
+        case VAR_EnduranceBonus:
+        case VAR_ActualEndurance:
+          this->uEnduranceBonus -= (unsigned __int16)a3;
+          goto LABEL_72;
+        case VAR_SpeedBonus:
+        case VAR_ActualSpeed:
+          this->uSpeedBonus -= (unsigned __int16)a3;
+          goto LABEL_72;
+        case VAR_AccuracyBonus:
+        case VAR_ActualAccuracy:
+          this->uAccuracyBonus -= (unsigned __int16)a3;
+          goto LABEL_72;
+        case VAR_LuckBonus:
+        case VAR_ActualLuck:
+          this->uLuckBonus -= (unsigned __int16)a3;
+          goto LABEL_72;
+        case VAR_BaseMight:
+          this->uMight -= (unsigned __int16)a3;
+          goto LABEL_45;
+        case VAR_BaseIntellect:
+          this->uIntelligence -= (unsigned __int16)a3;
+          goto LABEL_45;
+        case VAR_BasePersonality:
+          this->uWillpower -= (unsigned __int16)a3;
+          goto LABEL_45;
+        case VAR_BaseEndurance:
+          this->uEndurance -= (unsigned __int16)a3;
+          goto LABEL_45;
+        case VAR_BaseSpeed:
+          this->uSpeed -= (unsigned __int16)a3;
+          goto LABEL_45;
+        case VAR_BaseAccuracy:
+          this->uAccuracy -= (unsigned __int16)a3;
+          goto LABEL_45;
+        case VAR_BaseLuck:
+          this->uLuck -= (unsigned __int16)a3;
+          goto LABEL_45;
+        case VAR_FireResistance:
+          this->sResFireBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_AirResistance:
+          this->sResAirBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_WaterResistance:
+          this->sResWaterBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_EarthResistance:
+          this->sResEarthBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_SpiritResistance:
+          this->sResSpiritBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_MindResistance:
+          this->sResMindBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_BodyResistance:
+          this->sResBodyBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_LightResistance:
+          this->sResLightBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_DarkResistance:
+          this->sResDarkBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_MagicResistance:
+          this->sResMagicBase -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_FireResistanceBonus:
+          this->sResFireBonus -= (signed __int16)a3;
+          goto LABEL_45;
+        case VAR_AirResistanceBonus:
+          this->sResAirBonus -= (signed __int16)a3;
+LABEL_45:
+          v25 = 0;
+          v23 = 92;
+          goto LABEL_73;
+        case VAR_WaterResistanceBonus:
+          this->sResWaterBonus -= (signed __int16)a3;
+          goto LABEL_72;
+        case VAR_EarthResistanceBonus:
+          this->sResEarthBonus -= (signed __int16)a3;
+          goto LABEL_72;
+        case VAR_SpiritResistanceBonus:
+          this->sResSpiritBonus -= (signed __int16)a3;
+          goto LABEL_72;
+        case VAR_MindResistanceBonus:
+          this->sResMindBonus -= (signed __int16)a3;
+          goto LABEL_72;
+        case VAR_BodyResistanceBonus:
+          this->sResBodyBonus -= (signed __int16)a3;
+          goto LABEL_72;
+        case VAR_LightResistanceBonus:
+          this->sResLightBonus -= (signed __int16)a3;
+          goto LABEL_72;
+        case VAR_DarkResistanceBonus:
+          this->sResDarkBonus -= (signed __int16)a3;
+          goto LABEL_72;
+        case VAR_MagicResistanceBonus:
+          this->sResMagicBonus -= (signed __int16)a3;
+LABEL_72:
+          v25 = 0;
+          v23 = 91;
+LABEL_73:
+          pPlayers[v4 + 1]->PlaySound(v23, v25);
+          goto LABEL_17;
+        case VAR_FixedFood:
+          Party::TakeFood((unsigned int)a3);
+          goto LABEL_17;
+        case VAR_StaffSkill:
+        case VAR_SwordSkill:
+        case VAR_DaggerSkill:
+        case VAR_AxeSkill:
+        case VAR_SpearSkill:
+        case VAR_BowSkill:
+        case VAR_MaceSkill:
+        case VAR_BlasterSkill:
+        case VAR_ShieldSkill:
+        case VAR_LeatherSkill:
+        case VAR_SkillChain:
+        case VAR_PlateSkill:
+        case VAR_FireSkill:
+        case VAR_AirSkill:
+        case VAR_WaterSkill:
+        case VAR_EarthSkill:
+        case VAR_SpiritSkill:
+        case VAR_MindSkill:
+        case VAR_BodySkill:
+        case VAR_LightSkill:
+        case VAR_DarkSkill:
+        case VAR_IdentifyItemSkill:
+        case VAR_MerchantSkill:
+        case VAR_RepairSkill:
+        case VAR_BodybuildingSkill:
+        case VAR_MeditationSkill:
+        case VAR_PerceptionSkill:
+        case VAR_DiplomacySkill:
+        case VAR_DisarmTrapSkill:
+        case VAR_LearningSkill:
+          *((short *)&this->pConditions[16] + var) -= (unsigned __int8)a3;
+          goto LABEL_17;
+        case VAR_Cursed:
+        case VAR_Weak:
+        case VAR_Asleep:
+        case VAR_Afraid:
+        case VAR_Drunk:
+        case VAR_Insane:
+        case VAR_PoisonedGreen:
+        case VAR_DiseasedGreen:
+        case VAR_PoisonedYellow:
+        case VAR_DiseasedYellow:
+        case VAR_PoisonedRed:
+        case VAR_DiseasedRed:
+        case VAR_Paralyzed:
+        case VAR_Unconsious:
+        case VAR_Dead:
+        case VAR_Stoned:
+        case VAR_Eradicated:
+          *((int *)this + 2 * var - 210) = 0;
+          *((int *)this + 2 * v5 - 209) = 0;
+LABEL_17:
+          pGame->pStru6Instance->SetPlayerBuffAnim(0x98u, v4);
+          v8 = 8 * v4 + 400;
+          LOBYTE(v8) = (8 * v4 - 112) | 4;
+          pAudioPlayer->PlaySound(SOUND_20001, v8, 0, -1, 0, 0, 0, 0);
+          return;
+      }
+      do
+      {
+        if ( *(void **)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v15 + 5] == a3 )
+        {
+          RemoveItemAtInventoryIndex(v3);
+          return;
+        }
+        ++v3;
+        v15 += 4;
+      }
+      while ( (signed int)v3 < 126 );
+      if ( (void *)pParty->pPickedItem.uItemID == a3 )
+        pMouse->RemoveHoldingItem();
+    }
+  }
+}
+// 5B65C4: using guessed type int dword_5B65C4;
+// 5B65CC: using guessed type int dword_5B65CC;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Player.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,514 @@
+#pragma once
+#include "Items.h"
+#include "Spells.h"
+
+
+
+
+
+/*  339 */
+enum CHARACTER_RACE
+{
+  CHARACTER_RACE_HUMAN = 0x0,
+  CHARACTER_RACE_ELF = 0x1,
+  CHARACTER_RACE_GOBLIN = 0x2,
+  CHARACTER_RACE_DWARF = 0x3,
+};
+enum CHARACTER_ATTRIBUTE
+{
+  CHARACTER_MIGHT = 0x0,
+  CHARACTER_INTELLIGANCE = 0x1,
+  CHARACTER_WILLPOWER = 0x2,
+  CHARACTER_ENDURANCE = 0x3,
+  CHARACTER_ACCURACY = 0x4,
+  CHARACTER_SPEED = 0x5,
+  CHARACTER_LUCK = 0x6,
+};
+
+/*  332 */
+enum CHARACTER_ATTRIBUTE_TYPE
+{
+  CHARACTER_ATTRIBUTE_STRENGTH = 0x0,
+  CHARACTER_ATTRIBUTE_INTELLIGENCE = 0x1,
+  CHARACTER_ATTRIBUTE_WILLPOWER = 0x2,
+  CHARACTER_ATTRIBUTE_ENDURANCE = 0x3,
+  CHARACTER_ATTRIBUTE_ACCURACY = 0x4,
+  CHARACTER_ATTRIBUTE_SPEED = 0x5,
+  CHARACTER_ATTRIBUTE_LUCK = 0x6,
+  CHARACTER_ATTRIBUTE_HEALTH = 0x7,
+  CHARACTER_ATTRIBUTE_MANA = 0x8,
+  CHARACTER_ATTRIBUTE_AC_BONUS = 0x9,
+  CHARACTER_ATTRIBUTE_RESIST_FIRE = 0xA,
+  CHARACTER_ATTRIBUTE_RESIST_AIR = 0xB,
+  CHARACTER_ATTRIBUTE_RESIST_WATER = 0xC,
+  CHARACTER_ATTRIBUTE_RESIST_EARTH = 0xD,
+  CHARACTER_ATTRIBUTE_RESIST_MIND = 0xE,
+  CHARACTER_ATTRIBUTE_RESIST_BODY = 0xF,
+  CHARACTER_ATTRIBUTE_LEVEL = 0x18,
+  CHARACTER_ATTRIBUTE_ATTACK = 0x19,
+  CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS = 0x1A,
+  CHARACTER_ATTRIBUTE_MELEE_DMG_MIN = 0x1B,
+  CHARACTER_ATTRIBUTE_MELEE_DMG_MAX = 0x1C,
+  CHARACTER_ATTRIBUTE_RANGED_ATTACK = 0x1D,
+  CHARACTER_ATTRIBUTE_RANGED_DAMAGE_BONUS = 0x1E,
+  CHARACTER_ATTRIBUTE_RANGED_DAMAGE_MIN = 0x1F,
+  CHARACTER_ATTRIBUTE_RANGED_DAMAGE_MAX = 0x20,
+};
+
+/*  328 */
+enum PLAYER_SKILL_TYPE
+{
+  PLAYER_SKILL_STAFF = 0x0,
+  PLAYER_SKILL_SWORD = 0x1,
+  PLAYER_SKILL_DAGGER = 0x2,
+  PLAYER_SKILL_AXE = 0x3,
+  PLAYER_SKILL_SPEAR = 0x4,
+  PLAYER_SKILL_BOW = 0x5,
+  PLAYER_SKILL_MACE = 0x6,
+  PLAYER_SKILL_BLASTER = 0x7,
+  PLAYER_SKILL_SHIELD = 0x8,
+  PLAYER_SKILL_LEATHER = 0x9,
+  PLAYER_SKILL_CHAIN = 0xA,
+  PLAYER_SKILL_PLATE = 0xB,
+  PLAYER_SKILL_FIRE = 0xC,
+  PLAYER_SKILL_AIR = 0xD,
+  PLAYER_SKILL_WATER = 0xE,
+  PLAYER_SKILL_EARTH = 0xF,
+  PLAYER_SKILL_SPIRIT = 0x10,
+  PLAYER_SKILL_MIND = 0x11,
+  PLAYER_SKILL_BODY = 0x12,
+  PLAYER_SKILL_LIGHT = 0x13,
+  PLAYER_SKILL_DARK = 0x14,
+  PLAYER_SKILL_ITEM_ID = 0x15,
+  PLAYER_SKILL_MERCHANT = 0x16,
+  PLAYER_SKILL_REPAIR = 0x17,
+  PLAYER_SKILL_BODYBUILDING = 0x18,
+  PLAYER_SKILL_MEDITATION = 0x19,
+  PLAYER_SKILL_PERCEPTION = 0x1A,
+  PLAYER_SKILL_DIPLOMACY = 0x1B,
+  PLAYER_SKILL_TIEVERY = 0x1C,
+  PLAYER_SKILL_TRAP_DISARM = 0x1D,
+  PLAYER_SKILL_DODGE = 0x1E,
+  PLAYER_SKILL_UNARMED = 0x1F,
+  PLAYER_SKILL_MONSTER_ID = 0x20,
+  PLAYER_SKILL_ARMSMASTER = 0x21,
+  PLAYER_SKILL_STEALING = 0x22,
+  PLAYER_SKILL_ALCHEMY = 0x23,
+  PLAYER_SKILL_LEARNING = 0x24,
+};
+
+/*  329 */
+enum PLAYER_CLASS_TYPE
+{
+  PLAYER_CLASS_KNIGHT = 0x0,
+  PLAYER_CLASS_THEIF = 0x4,
+  PLAYER_CLASS_BOUNTY_HUNTER = 0x7,
+  PLAYER_CLASS_MONK = 0x8,
+  PLAYER_CLASS_PALADIN = 0xC,
+  PLAYER_CLASS_SHOOTER = 0x10,
+  PLAYER_CLASS_RANGER = 0x14,
+  PLAYER_CLASS_CLERIC = 0x18,
+  PLAYER_CLASS_PRIEST_OF_MOON = 0x1B,
+  PLAYER_CLASS_DRUID = 0x1C,
+  PLAYER_CLASS_SORCERER = 0x20,
+  PLAYER_CLASS_LICH = 0x23,
+};
+
+
+
+
+#pragma pack(push, 1)
+struct LloydBeacon
+{
+  unsigned __int64 uBeaconTime;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct PlayerSpellbookChapter
+{
+  unsigned __int8 bIsSpellbookAvailable;
+  char bIsSpellAvailable[10];
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct PlayerSpells
+{
+  union
+  {
+    struct
+    {
+      PlayerSpellbookChapter pFireSpellbook;
+      PlayerSpellbookChapter pAirSpellbook;
+      PlayerSpellbookChapter pWaterSpellbook;
+      PlayerSpellbookChapter pEarthSpellbook;
+      PlayerSpellbookChapter pSpiritSpellbook;
+      PlayerSpellbookChapter pMindSpellbook;
+      PlayerSpellbookChapter pBodySpellbook;
+      PlayerSpellbookChapter pLightSpellbook;
+      PlayerSpellbookChapter pDarkSpellbook;
+      char _pad_0;
+    };
+    struct
+    {
+      PlayerSpellbookChapter pChapters[9];
+      char _pad_1;
+    };
+  };
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+union PlayerEquipment
+{
+  union
+  {
+    struct
+    {
+      unsigned int uOffHand;
+      unsigned int uMainHand;
+      unsigned int uBow;
+      unsigned int uBody;
+      unsigned int uHelm;
+      unsigned int uBelt;
+      unsigned int uCloak;
+      unsigned int field_1C;
+      unsigned int field_20;
+      unsigned int field_24;
+      unsigned int field_28;
+      unsigned int field_2C;
+      unsigned int field_30;
+      unsigned int field_34;
+      unsigned int field_38;
+      unsigned int field_3C;
+    };
+    unsigned int pIndices[16];
+  };
+};
+#pragma pack(pop)
+
+
+
+
+
+enum PLAYER_SEX: unsigned __int8
+{
+  SEX_MALE = 0,
+  SEX_FEMALE = 1
+};
+
+#pragma pack(push, 1)
+struct Player
+{
+  enum Condition: unsigned __int32
+  {
+    Condition_Cursed = 0,
+    Condition_Weak = 1,
+    Condition_Sleep = 2,
+    Condition_Fear = 3,
+    Condition_Drunk = 4,
+    Condition_Insane = 5,
+    Condition_Poison1 = 6,
+    Condition_Disease1 = 7,
+    Condition_Posion2 = 8,
+    Condition_Disease2 = 9,
+    Condition_Poison3 = 10,
+    Condition_Disease3 = 11,
+    Condition_Paralyzed = 12,
+    Condition_Unconcious = 13,
+    Condition_Dead = 14,
+    Condition_Pertified = 15,
+    Condition_Eradicated = 16,
+    Condition_Zombie = 17,
+    Condition_Good = 18
+  };
+
+  Player();
+
+  void SetVariable(enum VariableType var, signed int a3);
+  void AddVariable(enum VariableType var, signed int val);
+  void SubtractVariable(enum VariableType var, void *a3);
+  char CompareVariable(enum VariableType var, signed int a1);
+  void UseItem_DrinkPotion_etc(signed int a2, int a3);
+  bool AddItem(struct ItemGen *pItem);
+  int GetBaseStrength();
+  int GetBaseIntelligence();
+  int GetBaseWillpower();
+  int GetBaseEndurance();
+  int GetBaseAccuracy();
+  int GetBaseSpeed();
+  int GetBaseLuck();
+  int GetBaseLevel();
+  int GetActualLevel();
+  int GetActualMight();
+  int GetActualIntelligence();
+  int GetActualWillpower();
+  int GetActualEndurance();
+  int GetActualAccuracy();
+  int GetActualSpeed();
+  int GetActualLuck();
+  int GetActualAttack(int a2);
+  int GetMeleeDamageMinimal();
+  int GetMeleeDamageMaximal();
+  int CalculateMeleeDamageTo(int a2, int a3, unsigned int uTargetActorID);
+  int GetRangedAttack();
+  int GetRangedDamageMin();
+  int GetRangedDamageMax();
+  bool CalculateRangedDamageTo(int a2);
+  char *GetMeleeDamageString();
+  char *GetRangedDamageString();
+  bool CanTrainToNextLevel();
+  unsigned int GetExperienceDisplayColor();
+  int CalculateIncommingDamage(int resistance, signed int type);
+  int GetEquippedItemEquipType(unsigned int uEquipSlot);
+  int GetEquippedItemSkillType(enum ITEM_EQUIP_TYPE uEquipSlot);
+  bool IsUnarmed();
+  bool HasItemEquipped(enum ITEM_EQUIP_TYPE uEquipIndex);
+  bool HasEnchantedItemEquipped(int uEnchantment);
+  bool WearsItem(int a1, signed int a2);
+  bool StealFromShop(struct ItemGen *a2, int a3, int a4, int a5, int *a6);
+  int StealFromActor(unsigned int uActorID, int _steal_perm, int reputation);
+  void Heal(int amount);
+  int ReceiveDamage(signed int type, int resistance);
+  int _48DCF6(int a2, struct Actor *pActor);
+  unsigned int GetSpellSchool(unsigned int uSpellID);
+  int GetAttackRecoveryTime(int a2);
+  int GetMaxHealth();
+  int GetMaxMana();
+  int GetBaseAC();
+  int GetActualAC();
+  unsigned int GetBaseAge();
+  unsigned int GetActualAge();
+  int GetBaseResistance(enum CHARACTER_ATTRIBUTE_TYPE a2);
+  int GetActualResistance(enum CHARACTER_ATTRIBUTE_TYPE a2);
+  void SetRecoveryTime(signed int sRecoveryTime);
+  void RandomizeName();
+  unsigned int GetMajorConditionIdx();
+  int _48EA1B_get_static_effect(int a2);
+  int _48EA46_calc_special_bonus_by_items(int a2);
+  int GetItemsBonus(enum CHARACTER_ATTRIBUTE_TYPE attr, int a3);
+  int GetMagicalBonus(enum CHARACTER_ATTRIBUTE_TYPE a2);
+  char GetActualSkillLevel(enum PLAYER_SKILL_TYPE uSkillType);
+  int GetSkillBonus(enum CHARACTER_ATTRIBUTE_TYPE a2);
+  enum CHARACTER_RACE GetRace();
+  int GetSexByVoice();
+  void SetInitialStats();
+  int SetSexByVoice();
+  void Reset(unsigned __int8 uClass);
+  enum PLAYER_SKILL_TYPE GetSkillIdxByOrder(signed int order);
+  void DecreaseAttribute(int eAttribute);
+  int IncreaseAttribute(int eAttribute);
+  void Player::Zero();
+  __int16 GetStatColor(unsigned int uStat);
+  bool DiscardConditionIfLastsLongerThan(unsigned int uCondition, unsigned __int64 uTime);
+  int _490EEE(ItemGen *pItem, int a3, int a4, int a5);
+  int GetBodybuilding();
+  int GetMediatation();
+  int CanIdentify(ItemGen *pItem);
+  int CanRepair(ItemGen *);
+  int GetMerchant();
+  int GetPerception();
+  int GetDisarmTrap();
+  char GetLearningPercent();
+  bool CanFitItem(unsigned int uSlot, unsigned int uItemID);
+  unsigned int FindFreeInventorySlot();
+  int CreateItemInInventory(unsigned int uSlot, unsigned int uItemID);
+  int HasSkill(unsigned int uSkillType);
+  int WearItem(unsigned int uItemID);
+  int AddItem(unsigned int uSlot, unsigned int uItemID);
+  int AddItem2(unsigned int uSlot, ItemGen *Src);
+  int CreateItemInInventory2(unsigned int uSlot, ItemGen *Src);
+  bool _49298B(ItemGen *a2, int a3, int a4);
+  unsigned int RemoveItemAtInventoryIndex(unsigned int uSlot);
+  bool CanAct();
+  bool CanSteal();
+  bool CanEquip_RaceAndAlignmentCheck(unsigned int uItemID);
+  int SetCondition(unsigned int uConditionIdx, int a3);
+  int _49327B(unsigned int uClass, int a3);
+  __int16 PlaySound(int a2, int a3);
+  __int16 PlayEmotion(int a2, int a3);
+  char _4160CA(int a2);
+  unsigned int GetItemIDAtInventoryIndex(int *a2);
+  int _4B6FF9();
+  int _4B824B(float a2);
+  int _4B8265(int a2, float a3);
+  int _4B8233(int a2, float a3);
+  int _4B8213(int a2, float a3);
+  int _4B81C3(int a2, float a3);
+  int _4B8179(float a2);
+  int _4B8142(int a2, float a3);
+  int _4B8102(int a2, float a3);
+  int _4B807C(float a2);
+  int _4B8040_condition_time(unsigned int uCondition);
+  bool _43EEF3();
+  void _4BE2DD(unsigned int a2, int a3, int _2devent_idx);
+  bool Recover(signed int a2);
+  bool CanCastSpell(unsigned int uRequiredMana);
+
+  inline bool Dead()       {return pConditions[Condition::Condition_Dead] != 0;}
+  inline bool Eradicated() {return pConditions[Condition::Condition_Eradicated] != 0;}
+
+
+
+  __int64 pConditions[20];
+  unsigned __int64 uExperience;
+  char pName[16];
+  PLAYER_SEX uSex;
+  unsigned __int8 uClass;
+  unsigned __int8 uFace;
+  char field_BB;
+  unsigned __int16 uMight;
+  unsigned __int16 uMightBonus;
+  unsigned __int16 uIntelligence;
+  unsigned __int16 uIntelligenceBonus;
+  unsigned __int16 uWillpower;
+  unsigned __int16 uWillpowerBonus;
+  unsigned __int16 uEndurance;
+  unsigned __int16 uEnduranceBonus;
+  unsigned __int16 uSpeed;
+  unsigned __int16 uSpeedBonus;
+  unsigned __int16 uAccuracy;
+  unsigned __int16 uAccuracyBonus;
+  unsigned __int16 uLuck;
+  unsigned __int16 uLuckBonus;
+  __int16 sACModifier;
+  unsigned __int16 uLevel;
+  __int16 sLevelModifier;
+  __int16 sAgeModifier;
+  int field_E0;
+  int field_E4;
+  int field_E8;
+  int field_EC;
+  int field_F0;
+  int field_F4;
+  int field_F8;
+  int field_FC;
+  int field_100;
+  int field_104;
+  union
+  {
+    struct
+    {
+      unsigned __int16 skillStaff;
+      unsigned __int16 skillSword;
+      unsigned __int16 skillDagger;
+      unsigned __int16 skillAxe;
+      unsigned __int16 skillSpear;
+      unsigned __int16 skillBow;
+      unsigned __int16 skillMace;
+      unsigned __int16 skillBlaster;
+      unsigned __int16 skillShield;
+      unsigned __int16 skillLeather;
+      unsigned __int16 skillChain;
+      unsigned __int16 skillPlate;
+      unsigned __int16 skillFire;
+      unsigned __int16 skillAir;
+      unsigned __int16 skillWater;
+      unsigned __int16 skillEarth;
+      unsigned __int16 skillSpirit;
+      unsigned __int16 skillMind;
+      unsigned __int16 skillBody;
+      unsigned __int16 skillLight;
+      unsigned __int16 skillDark;
+      unsigned __int16 skillItemId;
+      unsigned __int16 skillMerchant;
+      unsigned __int16 skillRepair;
+      unsigned __int16 skillBodybuilding;
+      unsigned __int16 skillMeditation;
+      unsigned __int16 skillPerception;
+      unsigned __int16 skillDiplomacy;
+      unsigned __int16 skillThievery;
+      unsigned __int16 skillDisarmTrap;
+      unsigned __int16 skillDodge;
+      unsigned __int16 skillUnarmed;
+      unsigned __int16 skillMonsterId;
+      unsigned __int16 skillArmsmaster;
+      unsigned __int16 skillStealing;
+      unsigned __int16 skillAlchemy;
+      unsigned __int16 skillLearning;
+    };
+    unsigned __int16 pActiveSkills[37];
+  };
+  char field_152[64];
+  PlayerSpells spellbook;
+  char field_1F5[30]; // used to be [31]
+  ItemGen pInventoryItems[126];
+  ItemGen pEquippedItems[12];
+  int pInventoryIndices[126];
+  __int16 sResFireBase;
+  __int16 sResAirBase;
+  __int16 sResWaterBase;
+  __int16 sResEarthBase;
+  __int16 field_177C;
+  __int16 sResMagicBase;
+  __int16 sResSpiritBase;
+  __int16 sResMindBase;
+  __int16 sResBodyBase;
+  __int16 sResLightBase;
+  __int16 sResDarkBase;
+  __int16 sResFireBonus;
+  __int16 sResAirBonus;
+  __int16 sResWaterBonus;
+  __int16 sResEarthBonus;
+  __int16 field_1792;
+  __int16 sResMagicBonus;
+  __int16 sResSpiritBonus;
+  __int16 sResMindBonus;
+  __int16 sResBodyBonus;
+  __int16 sResLightBonus;
+  __int16 sResDarkBonus;
+  SpellBuff pPlayerBuffs[24];
+  unsigned int uVoiceID;
+  int field_1924;
+  int field_1928;
+  int field_192C;
+  int field_1930;
+  unsigned __int16 uTimeToRecovery;
+  char field_1936;
+  char field_1937;
+  unsigned int uSkillPoints;
+  int sHealth;
+  int sMana;
+  unsigned int uBirthYear;
+  PlayerEquipment pEquipment;
+  int field_1988[49];
+  char field_1A4C;
+  char field_1A4D;
+  char pNumSpellBookPage;
+  unsigned __int8 uQuickSpell;
+  char field_1A50[64];
+  char _some_attack_bonus;
+  char field_1A91;
+  char _melee_dmg_bonus;
+  char field_1A93;
+  char _ranged_atk_bonus;
+  char field_1A95;
+  char _ranged_dmg_bonus;
+  char field_1A97;
+  char uFullHealthBonus;
+  char _health_related;
+  char uFullManaBonus;
+  char _mana_related;
+  unsigned __int16 uExpressionID;
+  unsigned __int16 uExpressionTimePassed;
+  unsigned __int16 uExpressionTimeLength;
+  __int16 field_1AA2;
+  int field_1AA4;
+  int field_1AA8;
+  LloydBeacon pInstalledBeacons[5];
+  char uNumDivineInterventionCastsThisDay;
+  char uNumArmageddonCasts;
+  char uNumFireSpikeCasts;
+  char field_1B3B;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PlayerFrameTable.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,40 @@
+#pragma once
+
+
+
+/*   46 */
+#pragma pack(push, 1)
+struct PlayerFrame
+{
+  __int16 uSequenceID;
+  unsigned __int16 uTextureID;
+  __int16 uAnimTime;
+  __int16 uAnimLength;
+  __int16 uFlags;
+};
+#pragma pack(pop)
+
+
+/*   47 */
+#pragma pack(push, 1)
+struct PlayerFrameTable
+{
+  inline PlayerFrameTable():
+    uNumFrames(0), pFrames(nullptr)
+  {}
+
+  unsigned int GetFrameIdBy_field0(int uField0);
+  PlayerFrame *GetFrameBy_x(unsigned int uFramesetID, unsigned int uFrameID);
+  PlayerFrame *GetFrameBy_y(int *a2, int *a3, int a4);
+  void ToFile();
+  void FromFile(void *pSerialized);
+  int FromFileTxt(const char *Args);
+
+  unsigned int uNumFrames;
+  struct PlayerFrame *pFrames;
+};
+#pragma pack(pop)
+
+
+
+extern struct PlayerFrameTable *pPlayerFrameTable; // idb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Random.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,91 @@
+#include <math.h>
+
+#include "Random.h"
+
+#include "mm7_data.h"
+
+
+
+
+struct Random *pRnd; // idb
+
+
+
+
+
+//----- (004BE59E) --------------------------------------------------------
+void Random::SetRange(int min, int max)
+{
+  this->min = min;
+  this->range = max - min;
+}
+
+//----- (004BE5B1) --------------------------------------------------------
+double Random::GetRandom()
+{
+  Random *v1; // esi@1
+  double v2; // st7@1
+  double v3; // st7@1
+
+  v1 = this;
+  this->field_0[3] = this->field_0[2];
+  this->field_0[2] = this->field_0[1];
+  v2 = this->field_0[0];
+  this->field_0[1] = v2;
+  v3 = this->field_0[3] * 1492.0
+     + this->field_0[2] * 1776.0
+     + this->field_0[3] * 2111111111.0
+     + v2 * 5115.0
+     + this->field_0[4];
+  v1->field_0[0] = v3 - floor(v3);
+  v1->field_0[4] = v3 * 2.328306436538696e-10;
+  return v3 - v3;
+}
+
+//----- (004BE623) --------------------------------------------------------
+int Random::GetInRange()
+{
+  Random *v1; // esi@1
+  float v2; // ST10_4@1
+  double v3; // ST04_8@1
+  int floored_random; // ecx@1
+
+  v1 = this;
+  v2 = GetRandom() * (double)this->range;
+  v3 = v2 + 6.7553994e15;
+  floored_random = LODWORD(v3);
+  if ( SLODWORD(v3) >= v1->range )
+    floored_random = v1->range;
+  return floored_random + v1->min;
+}
+
+//----- (004BE65D) --------------------------------------------------------
+void Random::Initialize(int seed)
+{
+  int v2; // eax@1
+  Random *this_; // esi@1
+  signed int v4; // ecx@3
+  unsigned int v5; // eax@4
+  signed int v6; // edi@5
+
+  v2 = seed;
+  this_ = this;
+  if ( !seed )
+    v2 = -1;
+  v4 = 0;
+  do
+  {
+    v5 = (((v2 << 13) ^ (unsigned int)v2) >> 17) ^ (v2 << 13) ^ v2;
+    v2 = 32 * v5 ^ v5;
+    this_->field_0[v4++] = (double)(unsigned int)v2 * 2.328306436538696e-10;
+  }
+  while ( v4 < 5 );
+  v6 = 19;
+  do
+  {
+    GetRandom();
+    --v6;
+  }
+  while ( v6 );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Random.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,31 @@
+#pragma once
+
+
+/*  304 */
+#pragma pack(push, 1)
+struct Random
+{
+  //----- (004BE365) --------------------------------------------------------
+  inline Random()
+  {
+    Initialize(0x5CCE1E47u);
+    min = 0;
+    range = 99;
+  }
+
+
+  void SetRange(int min, int max);
+  double GetRandom();
+  int GetInRange();
+  void Initialize(int seed);
+
+  double field_0[5];
+  int min;
+  int range;
+};
+#pragma pack(pop)
+
+
+
+
+extern struct Random *pRnd; // idb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Render.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,11160 @@
+#include "Render.h"
+#include "OutdoorCamera.h"
+#include "IndoorCamera.h"
+#include "Outdoor.h"
+#include "Party.h"
+#include "LOD.h"
+#include "Viewport.h"
+#include "Math.h"
+#include "PaletteManager.h"
+#include "Time.h"
+#include "Game.h"
+#include "LightmapBuilder.h"
+#include "stru220.h"
+#include "ObjectList.h"
+#include "LayingItem.h"
+#include "DecorationList.h"
+#include "Allocator.h"
+#include "OSInfo.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+#pragma comment(lib, "lib\\legacy_dx\\lib\\ddraw.lib")
+#pragma comment(lib, "lib\\legacy_dx\\lib\\dxguid.lib")
+
+
+
+
+
+
+
+struct IDirectDrawClipper *pDDrawClipper;
+struct Render *pRenderer; // idb
+
+
+int uNumDecorationsDrawnThisFrame; // weak
+RenderBillboard pBillboardRenderList[500];
+unsigned int uNumBillboardsToDraw;
+int uNumSpritesDrawnThisFrame; // weak
+
+
+RenderVertexSoft array_507D30[50];
+RenderVertexSoft array_508690[50];
+RenderVertexSoft array_508FF0[50];
+RenderVertexSoft array_509950[50];
+RenderVertexSoft array_50A2B0[50];
+RenderVertexSoft array_50AC10[50];
+
+RenderVertexSoft array_73D150[20];
+
+RenderVertexD3D3 arary_77E5C8[50];
+
+RenderVertexSoft *ptr_801A04;
+RenderVertexSoft *ptr_801A08;
+
+RenderVertexSoft pVerticesSR_801A10[384];
+RenderVertexSoft pVerticesSR_806210[384];
+
+
+
+
+
+
+
+void SetBillboardBlendOptions(RenderBillboardD3D::OpacityType a1);
+
+
+/*  384 */
+#pragma pack(push, 1)
+struct PCXHeader_1
+{
+  char manufacturer;
+  char version;
+  char encoding;
+  char bpp;
+  __int16 left;
+  __int16 up;
+  __int16 right;
+  __int16 bottom;
+  __int16 hdpi;
+  __int16 vdpi;
+};
+#pragma pack(pop)
+
+/*  385 */
+#pragma pack(push, 1)
+struct PCXHeader_2
+{
+  char reserved;
+  char planes;
+  __int16 pitch;
+  __int16 palette_info;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+HRESULT __stdcall D3DZBufferFormatEnumerator(DDPIXELFORMAT *Src, DDPIXELFORMAT *Dst);
+HRESULT __stdcall DDrawDisplayModesEnumerator(DDSURFACEDESC2 *pSurfaceDesc, __int16 *a2);
+HRESULT __stdcall D3DDeviceEnumerator(const GUID *lpGUID, const char *lpDeviceDesc, const char *lpDeviceName, D3DDEVICEDESC *pHWDesc, D3DDEVICEDESC *pSWDesc, struct RenderD3D_aux *a6);
+signed int __stdcall RenderD3D__DeviceEnumerator(GUID *lpGUID, const char *lpDevDesc, const char *lpDriverName, RenderD3D__DevInfo *pOut); // idb
+
+
+
+
+
+
+
+
+
+
+
+
+//----- (0049E79F) --------------------------------------------------------
+bool __cdecl CheckTextureStages()
+{
+  bool v0; // edi@1
+  IDirectDrawSurface4 *pSurface2; // [sp+Ch] [bp-14h]@1
+  IDirectDrawSurface4 *pSurface1; // [sp+10h] [bp-10h]@1
+  DWORD v4; // [sp+14h] [bp-Ch]@1
+  IDirect3DTexture2 *pTexture2; // [sp+18h] [bp-8h]@1
+  IDirect3DTexture2 *pTexture1; // [sp+1Ch] [bp-4h]@1
+
+  v0 = false;
+  pRenderer->pRenderD3D->CreateTexture(64u, 64u, &pSurface1, &pTexture1, true, false, 32u);
+  pRenderer->pRenderD3D->CreateTexture(64u, 64u, &pSurface2, &pTexture2, true, false, 32u);
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, pTexture1));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLOROP, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MINFILTER, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, 1u));
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, pTexture2));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_ADDRESS, 3u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_COLOROP, 7u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_COLORARG1, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_COLORARG2, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_MINFILTER, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_MIPFILTER, 1u));
+
+  if ( !pRenderer->pRenderD3D->pDevice->ValidateDevice(&v4) && v4 == 1 )
+    v0 = true;
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(1, D3DTSS_COLOROP, 1u));
+  pTexture1->Release();
+  pTexture2->Release();
+  pSurface1->Release();
+  pSurface2->Release();
+  return v0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+//----- (00440CB8) --------------------------------------------------------
+void Render::DrawBillboardList_BLV()
+{
+  __int16 v2; // ax@3
+  int v5; // eax@11
+  RenderBillboardTransform_local0 soft_billboard; // [sp+4h] [bp-50h]@1
+
+  soft_billboard.uParentBillboardID = -1;
+  soft_billboard.pTarget = pBLVRenderParams->pRenderTarget;
+  soft_billboard.pTargetZ = pBLVRenderParams->pTargetZBuffer;
+  soft_billboard.uTargetPitch = pRenderer->uTargetSurfacePitch;
+  soft_billboard.uViewportX = pBLVRenderParams->uViewportX;
+  soft_billboard.uViewportY = pBLVRenderParams->uViewportY;
+  soft_billboard.uViewportZ = pBLVRenderParams->uViewportZ - 1;
+  soft_billboard.uViewportW = pBLVRenderParams->uViewportW;
+
+  pOutdoorCamera->uNumBillboards = uNumBillboardsToDraw;
+
+  for (uint i = 0; i < uNumBillboardsToDraw; ++i)
+  {
+    auto p = pBillboardRenderList + i;
+
+      soft_billboard.uScreenSpaceX = p->uScreenSpaceX;
+      soft_billboard.uParentBillboardID = i;
+      soft_billboard.uScreenSpaceY = p->uScreenSpaceY;
+      soft_billboard.field_10 = p->field_0;
+      soft_billboard.field_14 = p->field_4;
+      soft_billboard.sZValue = p->sZValue;
+      soft_billboard.uFlags = p->field_1E;
+      soft_billboard.uTintColor = p->uTintColor;
+      v2 = p->uHwSpriteID;
+      if ( v2 != -1 )
+      {
+        if ( pRenderer->pRenderD3D )
+          pRenderer->DrawBillboard_Indoor(&soft_billboard, &pSprites_LOD->pHardwareSprites[v2], p->uPaletteSubindex);
+        else
+        {
+          soft_billboard.pPalette = PaletteManager::Get_Dark_or_Red_LUT(p->uPalette, p->uPaletteSubindex, 1);
+          if (p->field_1E & 0x0100)
+            soft_billboard.pPalette = pPaletteManager->field_261600[p->uPalette];
+          if ( !(soft_billboard.uFlags & 0x40) && soft_billboard.uFlags & 0x80 )
+            soft_billboard.pPalette2 = PaletteManager::Get_Dark_or_Red_LUT(p->uPalette, 0, 1);
+          v5 = p->uHwSpriteID;
+          if ( v5 >= 0 )
+            pSprites_LOD->pSpriteHeaders[v5]._4ACC38(&soft_billboard, 1);
+        }
+      }
+  }
+}
+
+
+
+
+
+//----- (004A16A5) --------------------------------------------------------
+bool __cdecl AreRenderSurfacesOk()
+{
+  char v0; // zf@4
+  bool result; // eax@8
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    if ( !pRenderer->pBackBuffer4 )
+      goto LABEL_9;
+    v0 = pRenderer->pFrontBuffer4 == 0;
+  }
+  else
+  {
+    if ( !pRenderer->pBackBuffer2 )
+      goto LABEL_9;
+    v0 = pRenderer->pFrontBuffer2 == 0;
+  }
+  if ( !v0 )
+  {
+    LOBYTE(result) = 1;
+    return result;
+  }
+LABEL_9:
+  LOBYTE(result) = 0;
+  return result;
+}
+
+
+
+//----- (00487389) --------------------------------------------------------
+__int16 Render::ExecOutdoorDrawSW()
+{
+  unsigned __int16 *v0; // ebx@1
+  unsigned int v1; // esi@1
+  stru148 *v2; // eax@1
+  Span *v3; // edi@6
+  stru148 *v4; // esi@9
+  Texture *v5; // ebp@10
+  int v6; // esi@16
+  unsigned int v7; // edx@16
+  char *v8; // ecx@17
+  unsigned int v9; // edi@22
+  int v10; // eax@26
+  int v11; // eax@27
+  unsigned int v12; // ebp@32
+  Span *v13; // esi@33
+  int v14; // ecx@37
+  int v15; // eax@40
+  Texture *v16; // ebp@51
+  unsigned int v17; // eax@51
+  int v18; // eax@54
+  char v19; // al@56
+  unsigned int v20; // eax@57
+  int v21; // ecx@57
+  unsigned int v22; // eax@57
+  stru149 *v23; // eax@65
+  int v24; // eax@67
+  ODMFace *v25; // eax@78
+  signed int v26; // edx@79
+  signed int v27; // ecx@79
+  unsigned int v28; // eax@106
+  unsigned int v29; // ebp@117
+  Span *v30; // esi@118
+  unsigned int v31; // ST04_4@124
+  int v33; // [sp+18h] [bp-44h]@80
+  signed int v34; // [sp+1Ch] [bp-40h]@3
+  signed int v35; // [sp+20h] [bp-3Ch]@79
+  Span **v36; // [sp+24h] [bp-38h]@4
+  unsigned int v37; // [sp+28h] [bp-34h]@1
+  unsigned __int16 *a1; // [sp+2Ch] [bp-30h]@1
+  int a1a; // [sp+2Ch] [bp-30h]@26
+  unsigned int a1b; // [sp+2Ch] [bp-30h]@116
+  char v41; // [sp+30h] [bp-2Ch]@57
+
+  v0 = pRenderer->pTargetSurface;
+  v1 = pOutdoorCamera->numStru148s;
+  a1 = pRenderer->pTargetSurface;
+  v2 = array_77EC08;
+  v37 = pOutdoorCamera->numStru148s;
+  if ( !(pParty->uFlags & 2) )
+  {
+    v1 = uNumElementsIn80AA28;
+    v2 = ptr_80AA28[0];
+    v37 = uNumElementsIn80AA28;
+  }
+  v34 = 0;
+  if ( (signed int)v1 > 0 )
+  {
+    v36 = &v2->prolly_head;
+    do
+    {
+      if ( pParty->uFlags & 2 )
+        v3 = *v36;
+      else
+        v3 = ptr_80AA28[v34]->prolly_head;
+      if ( v3 )
+      {
+        v4 = v3->pParent;
+        if ( v4 )
+        {
+          v5 = v4->pTexture;
+          if ( v5 )
+          {
+            if ( v3->field_8 >= (signed int)pViewport->uViewportX || v3->field_C != pViewport->uViewportX )
+            {
+              LOBYTE(v4->field_32) |= 2u;
+              v14 = *(int *)&v4->flags;
+              if ( v14 & 0x10 && v4->field_59 != 5 )
+              {
+                dword_80AA20 = (v4->field_5C - 64) << 25;
+                dword_80AA1C = dword_80AA20 + 0x1FF0000;
+                dword_80AA14 = (v4->field_5D << 25) + 0x7FFF0000;
+                dword_80AA18 = dword_80AA14 - 0x1FF0000;
+                byte_80AA10 = ((unsigned int)pOutdoor->ActuallyGetSomeOtherTileInfo(
+                                               v4->field_5C,
+                                               v4->field_5D - 1) >> 9) & 1;
+                if ( *(int *)&v4->flags & 2 || (v15 = *(int *)&v4->flags, BYTE1(v15) & 1) )
+                {
+                  if ( *(int *)&v4->flags & 2 )
+                  {
+                    while ( 1 )
+                    {
+                      if ( pOutdoorCamera->outdoor_no_wavy_water )
+                        sr_sub_48408A_prolly_odm_water_no_waves(v3);
+                      else
+                        sr_sub_485407_prolly_odm_water_wavy(v3);
+                      v3->field_E = LOWORD(unnamed_6BE060[1]);
+                      if ( v4->prolly_tail == v3 )
+                        break;
+                      v3 = v3->pNext;
+                    }
+                  }
+                  else
+                  {
+                    while ( 1 )
+                    {
+                      v16 = v4->pTexture;
+                      v17 = pBitmaps_LOD->LoadTexture("wtrtyl");
+                      v4->pTexture = (Texture *)(v17 != -1 ? (int)&pBitmaps_LOD->pTextures[v17] : 0);
+                      if ( pOutdoorCamera->outdoor_no_wavy_water )
+                        sr_sub_48408A_prolly_odm_water_no_waves(v3);
+                      else
+                        sr_sub_485407_prolly_odm_water_wavy(v3);
+                      v18 = v4->field_5C - 64;
+                      v4->pTexture = v16;
+                      dword_80AA20 = v18 << 25;
+                      dword_80AA1C = (v18 << 25) + 0x1FF0000;
+                      dword_80AA14 = (v4->field_5D << 25) + 0x7FFF0000;
+                      dword_80AA18 = dword_80AA14 - 0x1FF0000;
+                      byte_80AA10 = ((unsigned int)pOutdoor->ActuallyGetSomeOtherTileInfo(
+                                                     v4->field_5C,
+                                                     v4->field_5D - 1) >> 9) & 1;
+                      sr_sub_484442(v3);
+                      v3->field_E = LOWORD(unnamed_6BE060[1]);
+                      if ( v4->prolly_tail == v3 )
+                        break;
+                      v3 = v3->pNext;
+                    }
+                  }
+                }
+                else
+                {
+                  while ( sr_sub_48408A_prolly_odm_water_no_waves(v3) )
+                  {
+                    v3->field_E = LOWORD(unnamed_6BE060[1]);
+                    if ( v4->prolly_tail == v3 )
+                      break;
+                    v3 = v3->pNext;
+                  }
+                }
+              }
+              else
+              {
+                v19 = v4->field_59;
+                if ( v19 != 5 )
+                {
+                  if ( v14 & 2 )
+                  {
+                    while ( 1 )
+                    {
+                      v28 = pBitmaps_LOD->LoadTexture("wtrtyla");
+                      v4->pTexture = (Texture *)(v28 != -1 ? &pBitmaps_LOD->pTextures[v28] : 0);
+                      if ( !sr_sub_4847EB(v3) )
+                        break;
+                      v4->pTexture = v5;
+                      if ( !sr_sub_484442(v3) )
+                        break;
+                      v3->field_E = LOWORD(unnamed_6BE060[1]);
+                      if ( v4->prolly_tail == v3 )
+                        break;
+                      v3 = v3->pNext;
+                      v5 = v4->pTexture;
+                    }
+                  }
+                  else
+                  {
+                    if ( v19 == 1 )
+                    {
+                      dword_80AA20 = (v4->field_5C - 64) << 25;
+                      dword_80AA1C = dword_80AA20 + 33488896;
+                      dword_80AA14 = (v4->field_5D << 25) + 0x7FFF0000;
+                      dword_80AA18 = dword_80AA14 - 33488896;
+                      byte_80AA10 = ((unsigned int)pOutdoor->ActuallyGetSomeOtherTileInfo(
+                                                     v4->field_5C,
+                                                     v4->field_5D - 1) >> 9) & 1;
+                      while ( 1 )
+                      {
+                        if ( !sr_sub_4847EB(v3) )
+                          sr_sub_48585C_mb_DrawSpan(v3, &pRenderer->pTargetSurface[v3->field_8 + 640 * v3->field_A], 0);
+                        v3->field_E = LOWORD(unnamed_6BE060[1]);
+                        if ( v4->prolly_tail == v3 )
+                          break;
+                        v3 = v3->pNext;
+                      }
+                    }
+                  }
+                  goto LABEL_14;
+                }
+                v4->ptr_38 = (stru149 *)&v41;
+                v4->_479295();
+                v20 = GetTickCount();
+                v21 = *(int *)&v4->flags;
+                v22 = v20 >> 3;
+                if ( BYTE1(v21) & 4 )
+                {
+                  v4->sTextureDeltaV -= v22 & v4->pTexture->uHeightMinus1;
+                }
+                else
+                {
+                  if ( BYTE1(v21) & 8 )
+                    v4->sTextureDeltaV += v22 & v4->pTexture->uHeightMinus1;
+                }
+                if ( BYTE1(v21) & 0x10 )
+                {
+                  v4->sTextureDeltaU -= v22 & v4->pTexture->uWidthMinus1;
+                }
+                else
+                {
+                  if ( BYTE1(v21) & 0x20 )
+                    v4->sTextureDeltaU += v22 & v4->pTexture->uWidthMinus1;
+                }
+                v23 = v4->ptr_38;
+                v4->field_52 = 32;
+                v4->field_5A = 5;
+                if ( (double)abs(v23->field_C) > 52428.8 )
+                {
+                  v4->field_52 = 8;
+                  v4->field_5A = 3;
+                }
+                v24 = *(int *)&v4->flags;
+                if ( !(v24 & 0x10000) )
+                {
+                  if ( !(v24 & 2) )
+                  {
+                    v25 = v4->pODMFace;
+                    if ( v25->uPolygonType == 1 )
+                    {
+                      v26 = v25->pTextureUIDs[0];
+                      dword_80AA1C = v26;
+                      dword_80AA20 = v26;
+                      v27 = v25->pTextureVIDs[0];
+                      dword_80AA14 = v27;
+                      dword_80AA18 = v27;
+                      v35 = 1;
+                      if ( v25->uNumVertices > 1u )
+                      {
+                        v33 = (int)&v25->pTextureVIDs[1];
+                        do
+                        {
+                          if ( dword_80AA20 > *(short *)(v33 - 40) )
+                            dword_80AA20 = *(short *)(v33 - 40);
+                          if ( v26 < *(short *)(v33 - 40) )
+                          {
+                            v26 = *(short *)(v33 - 40);
+                            dword_80AA1C = *(short *)(v33 - 40);
+                          }
+                          if ( dword_80AA18 > *(short *)v33 )
+                            dword_80AA18 = *(short *)v33;
+                          if ( v27 < *(short *)v33 )
+                          {
+                            v27 = *(short *)v33;
+                            dword_80AA14 = *(short *)v33;
+                          }
+                          ++v35;
+                          v33 += 2;
+                        }
+                        while ( v35 < v25->uNumVertices );
+                        v0 = a1;
+                      }
+                      dword_80AA20 = (dword_80AA20 + v4->sTextureDeltaU) << 16;
+                      dword_80AA1C = ((v26 + v4->sTextureDeltaU) << 16) - 65536;
+                      dword_80AA18 = (dword_80AA18 + v4->sTextureDeltaV) << 16;
+                      dword_80AA14 = ((v27 + v4->sTextureDeltaV) << 16) - 65536;
+                    }
+                    while ( 1 )
+                    {
+                      if ( !sr_sub_482E07(v3, v0) )
+                        sr_sub_48585C_mb_DrawSpan(v3, &v0[v3->field_8 + 640 * v3->field_A], 0);
+                      v3->field_E = LOWORD(unnamed_6BE060[1]);
+                      if ( v4->prolly_tail == v3 )
+                        break;
+                      v3 = v3->pNext;
+                    }
+                    goto LABEL_14;
+                  }
+                  while ( 1 )
+                  {
+LABEL_74:
+                    if ( !sr_sub_4839BD(v3, v0) )
+                      sr_sub_48585C_mb_DrawSpan(v3, &v0[v3->field_8 + 640 * v3->field_A], 0);
+                    v3->field_E = LOWORD(unnamed_6BE060[1]);
+                    if ( v4->prolly_tail == v3 )
+                      break;
+                    v3 = v3->pNext;
+                  }
+                  goto LABEL_14;
+                }
+                if ( v24 & 2 )
+                  goto LABEL_74;
+                while ( 1 )
+                {
+                  if ( !sr_sub_482A94(v3) )
+                    sr_sub_48585C_mb_DrawSpan(v3, &v0[v3->field_8 + 640 * v3->field_A], 0);
+                  v3->field_E = LOWORD(unnamed_6BE060[1]);
+                  if ( v4->prolly_tail == v3 )
+                    break;
+                  v3 = v3->pNext;
+                }
+              }
+            }
+            else
+            {
+              v3->field_E = LOWORD(unnamed_6BE060[1]);
+            }
+          }
+        }
+      }
+LABEL_14:
+      ++v34;
+      LOWORD(v2) = v34;
+      v36 += 67;
+    }
+    while ( v34 < (signed int)v37 );
+  }
+  if ( pParty->uFlags & 2 )
+  {
+    v6 = pOutdoorCamera->numStru148s;
+    v7 = 0;
+    uNumElementsIn80AA28 = 0;
+    if ( pOutdoorCamera->numStru148s > 0 )
+    {
+      v8 = (char *)&array_77EC08[0].flags;
+      do
+      {
+        v2 = *(stru148 **)v8;
+        if ( (unsigned int)v2 & 0x20000 )
+        {
+          ++v7;
+          *(int *)v8 = (unsigned int)v2 & 0xFFFDFFFF;
+          LOWORD(v2) = (short)v8 - 48;
+          *(&uNumElementsIn80AA28 + v7) = (unsigned int)(v8 - 48);
+        }
+        v8 += 268;
+        --v6;
+      }
+      while ( v6 );
+      uNumElementsIn80AA28 = v7;
+    }
+  }
+  v9 = pOutdoorCamera->uNumSpans;
+  unnamed_6BE060[0] = pOutdoorCamera->uNumSpans;
+  if ( pOutdoorCamera->numStru148s >= 1999
+    || (array_77EC08[1999]._48607B(&stru_8019C8),
+        array_77EC08[1999].ptr_38->_48694B(),
+        v2 = (stru148 *)&pBitmaps_LOD->pTextures[pOutdoor->uMainTile_BitmapID],
+        (array_77EC08[1999].pTexture = (Texture *)(pOutdoor->uMainTile_BitmapID != -1 ? (int)v2 : 0)) == 0) )
+    return (signed __int16)v2;
+  array_77EC08[1999].field_58 = 23 - (-20 * pOutdoor->vSunlight.z >> 16);
+  if ( array_77EC08[1999].field_58 > 20 )
+    array_77EC08[1999].field_58 = 20;
+  v10 = stru_5C6E00->SinCos(pIndoorCamera->sRotationX - stru_5C6E00->uIntegerHalfPi);
+  array_77EC08[1999].v_18.y = 0;
+  array_77EC08[1999].v_18.x = v10;
+  array_77EC08[1999].v_18.z = stru_5C6E00->SinCos(pIndoorCamera->sRotationX);
+  array_77EC08[1999].field_24 = 2048 - (pIndoorCamera->pos.z << 16);
+  a1a = (signed __int64)((double)(pIndoorCamera->pos.z * pOutdoorCamera->int_fov_rad)
+                       / ((double)pOutdoorCamera->int_fov_rad + 8192.0)
+                       + (double)pViewport->uScreenCenterY);
+  cos((double)pIndoorCamera->sRotationX * 0.0030664064);
+  sin((double)pIndoorCamera->sRotationX * 0.0030664064);
+  array_77EC08[1999]._48607B(&stru_8019C8);
+  array_77EC08[1999].ptr_38->_48694B();
+  v2 = (stru148 *)&pBitmaps_LOD->pTextures[pOutdoor->uSky_TextureID];
+  array_77EC08[1999].pTexture = (Texture *)(pOutdoor->uSky_TextureID != -1 ? (int)v2 : 0);
+  if ( !(pOutdoor->uSky_TextureID != -1 ? (int)v2 : 0) )
+    return (signed __int16)v2;
+  array_77EC08[1999].field_58 = 0;
+  v11 = stru_5C6E00->SinCos(pIndoorCamera->sRotationX + 16 - stru_5C6E00->uIntegerHalfPi);
+  array_77EC08[1999].v_18.y = 0;
+  array_77EC08[1999].v_18.x = -v11;
+  array_77EC08[1999].v_18.z = -stru_5C6E00->SinCos(pIndoorCamera->sRotationX + 16);
+  LOWORD(v2) = 224 * LOWORD(pMiscTimer->uTotalGameTimeElapsed);
+  array_77EC08[1999].field_24 = 0x2000000u;
+  array_77EC08[1999].sTextureDeltaU = 224 * pMiscTimer->uTotalGameTimeElapsed;
+  array_77EC08[1999].sTextureDeltaV = 224 * pMiscTimer->uTotalGameTimeElapsed;
+  if ( day_attrib & 1
+    && (LOWORD(v2) = LOWORD(pParty->uCurrentHour), pParty->uCurrentHour >= 5)
+    && pParty->uCurrentHour < 0x15
+    || bUnderwater )
+  {
+    v2 = (stru148 *)*(short *)PaletteManager::Get_Mist_or_Red_LUT(array_77EC08[1999].pTexture->palette_id2, 31, 1);
+    a1b = (unsigned int)v2;
+    if ( (signed int)v9 <= 0 )
+      return (signed __int16)v2;
+    v29 = v9;
+    while ( 1 )
+    {
+      v30 = &pSpans[v29 - 1];
+      v2 = (stru148 *)v30->field_E;
+      if ( v2 != (stru148 *)unnamed_6BE060[1] )
+      {
+        LOWORD(v2) = LOWORD(pViewport->uViewportX);
+        if ( v30->field_8 >= (signed int)pViewport->uViewportX )
+          goto LABEL_124;
+        if ( v30->field_C == pViewport->uViewportX )
+        {
+          v30->field_E = LOWORD(unnamed_6BE060[1]);
+        }
+        else
+        {
+          v30->field_8 = LOWORD(pViewport->uViewportX);
+          v30->field_C -= LOWORD(pViewport->uViewportX);
+          if ( v30->field_C >= 0 )
+          {
+LABEL_124:
+            v31 = v30->field_C;
+            v30->pParent = &array_77EC08[1999];
+            fill_pixels_fast(
+              a1b,
+              &pRenderer->pTargetSurface[v30->field_8 + pRenderer->uTargetSurfacePitch * v30->field_A],
+              v31);
+            j_memset32(-65536, &pRenderer->pActiveZBuffer[v30->field_8 + 640 * v30->field_A], v30->field_C);
+            goto LABEL_125;
+          }
+          LOWORD(v2) = LOWORD(unnamed_6BE060[1]);
+          v30->field_E = LOWORD(unnamed_6BE060[1]);
+        }
+      }
+LABEL_125:
+      --v29;
+      --v9;
+      if ( !v9 )
+        return (signed __int16)v2;
+    }
+  }
+  if ( (signed int)v9 > 0 )
+  {
+    v12 = v9;
+    do
+    {
+      v13 = &pSpans[v12 - 1];
+      v2 = (stru148 *)v13->field_E;
+      if ( v2 != (stru148 *)unnamed_6BE060[1] )
+      {
+        LOWORD(v2) = LOWORD(pViewport->uViewportX);
+        if ( v13->field_8 >= (signed int)pViewport->uViewportX )
+          goto LABEL_109;
+        if ( v13->field_C != pViewport->uViewportX )
+        {
+          v13->field_8 = LOWORD(pViewport->uViewportX);
+          v13->field_C -= LOWORD(pViewport->uViewportX);
+          if ( v13->field_C >= 0 )
+          {
+LABEL_109:
+            if ( pOutdoorCamera->bNoSky )
+            {
+              const_1_0();
+            }
+            else
+            {
+              v13->pParent = &array_77EC08[1999];
+              if ( !Render::DrawSkySW(v13, &array_77EC08[1999], a1a) )
+                j_memset32(-65536, &pRenderer->pActiveZBuffer[v13->field_8 + 640 * v13->field_A], v13->field_C);
+            }
+          }
+          LOWORD(v2) = LOWORD(unnamed_6BE060[1]);
+          v13->field_E = LOWORD(unnamed_6BE060[1]);
+          goto LABEL_114;
+        }
+        v13->field_E = LOWORD(unnamed_6BE060[1]);
+      }
+LABEL_114:
+      --v12;
+      --v9;
+    }
+    while ( v9 );
+  }
+  return (signed __int16)v2;
+}
+// 6BE030: using guessed type int day_attrib;
+// 6BE3C4: using guessed type char bUnderwater;
+// 80AA10: using guessed type char byte_80AA10;
+// 80AA14: using guessed type int dword_80AA14;
+// 80AA18: using guessed type int dword_80AA18;
+// 80AA1C: using guessed type int dword_80AA1C;
+// 80AA20: using guessed type int dword_80AA20;
+
+//----- (00485044) --------------------------------------------------------
+int Render::DrawSkySW(Span *a1, stru148 *a2, int a3)
+{
+  stru148 *v3; // esi@1
+  Span *v4; // edi@1
+  float v5; // ST2C_4@1
+  signed int result; // eax@2
+  int v7; // ST40_4@3
+  stru149 *v8; // eax@3
+  int v9; // ebx@3
+  int v10; // ecx@3
+  int v11; // edx@3
+  int v12; // eax@3
+  int v13; // ST28_4@5
+  int v14; // eax@5
+  signed __int64 v15; // qtt@11
+  int v16; // ST28_4@11
+  int v17; // eax@11
+  signed int v18; // ecx@11
+  int v19; // ST40_4@11
+  int v20; // ST3C_4@11
+  int v21; // ST30_4@11
+  void *v22; // eax@11
+  Texture *v23; // esi@11
+  int v24; // ecx@11
+  unsigned int v25; // esi@11
+  int v26; // edi@11
+  unsigned __int16 *v27; // eax@11
+  int *v28; // ebx@12
+  int v29; // edx@13
+  unsigned __int16 v30; // cx@13
+  int v31; // edx@14
+  unsigned __int16 v32; // cx@14
+  unsigned __int8 v33; // sf@15
+  unsigned __int8 v34; // of@15
+  double v35; // [sp+14h] [bp-38h]@1
+  int v36; // [sp+18h] [bp-34h]@3
+  signed int v37; // [sp+18h] [bp-34h]@11
+  int v38; // [sp+1Ch] [bp-30h]@3
+  signed int v39; // [sp+1Ch] [bp-30h]@11
+  int v40; // [sp+20h] [bp-2Ch]@3
+  void *v41; // [sp+20h] [bp-2Ch]@11
+  int v42; // [sp+24h] [bp-28h]@3
+  unsigned __int8 *v43; // [sp+24h] [bp-28h]@11
+  int v44; // [sp+28h] [bp-24h]@11
+  int v45; // [sp+2Ch] [bp-20h]@3
+  signed int v46; // [sp+30h] [bp-1Ch]@3
+  __int16 v47; // [sp+30h] [bp-1Ch]@11
+  signed int v48; // [sp+34h] [bp-18h]@3
+  int v49; // [sp+34h] [bp-18h]@11
+  int v50; // [sp+38h] [bp-14h]@3
+  unsigned __int16 *v51; // [sp+38h] [bp-14h]@11
+  int v52; // [sp+3Ch] [bp-10h]@4
+  int a1a; // [sp+40h] [bp-Ch]@3
+  int v54; // [sp+44h] [bp-8h]@3
+  int v55; // [sp+48h] [bp-4h]@3
+  int v56; // [sp+54h] [bp+8h]@11
+  int *v57; // [sp+54h] [bp+8h]@11
+
+  v3 = a2;
+  v4 = a1;
+  v5 = (double)(pViewport->uViewportZ - pViewport->uViewportX) * 0.5 / tan(0.6457717418670654) + 0.5;
+  v35 = v5 + 6.7553994e15;
+  if ( LODWORD(v35) )
+  {
+    v55 = 65536 / SLODWORD(v35);
+    v7 = 65536 / SLODWORD(v35) * (a3 - v4->field_A);
+    v8 = v3->ptr_38;
+    v42 = ((unsigned __int64)(v3->ptr_38->field_14 * (signed __int64)v7) >> 16) + v8->field_C;
+    v40 = ((unsigned __int64)(v8->field_20 * (signed __int64)v7) >> 16) + v3->ptr_38->field_18;
+    v38 = pOutdoorCamera->camera_rotation_y_int_sine;
+    HIDWORD(v35) = pOutdoorCamera->camera_rotation_y_int_cosine;
+    v45 = v4->field_C;
+    v9 = ((unsigned __int64)(v3->v_18.z * (signed __int64)v7) >> 16) + v3->v_18.x;
+    v10 = 65536 / SLODWORD(v35) * (pViewport->uScreenCenterX - v4->field_8);
+    v48 = 0;
+    v50 = 65536 / SLODWORD(v35) * (pViewport->uScreenCenterX - v4->field_8);
+    v46 = -v3->field_24;
+    v11 = v4->field_A - 1;
+    v54 = v11;
+    v12 = 65536 / SLODWORD(v35) * (a3 - v11);
+    a1a = 65536 / SLODWORD(v35) * (a3 - v11);
+    while ( 1 )
+    {
+      v52 = v9;
+      if ( v9 )
+      {
+        v13 = abs(v46 >> 14);
+        v14 = abs(v9);
+        v11 = v54;
+        v10 = v50;
+        if ( v13 <= v14 )
+          break;
+        v12 = a1a;
+      }
+      if ( v11 <= (signed int)pViewport->uViewportY )
+        break;
+      v9 = ((unsigned __int64)(v3->v_18.z * (signed __int64)v12) >> 16) + v3->v_18.x;
+      --v54;
+      a1a += v55;
+      v12 = a1a;
+      v11 = v54;
+      v48 = 1;
+    }
+    if ( v48 )
+      v52 = ((unsigned __int64)(v3->v_18.z * (signed __int64)(v55 * (a3 + (signed int)v4->field_A - 2 * v11))) >> 16)
+          + v3->v_18.x;
+    LODWORD(v15) = v46 << 16;
+    HIDWORD(v15) = v46 >> 16;
+    v16 = v42 + ((unsigned __int64)(v3->ptr_38->field_10 * (signed __int64)v10) >> 16);
+    v17 = v40 + ((unsigned __int64)(v3->ptr_38->field_1C * (signed __int64)v10) >> 16);
+    v18 = v15 / v52;
+    v43 = v3->pTexture->pLevelOfDetail0;
+    v19 = v3->sTextureDeltaU + ((signed int)((unsigned __int64)(v16 * v15 / v52) >> 16) >> 3);
+    v56 = v15 / v52;
+    v20 = v3->sTextureDeltaV + ((signed int)((unsigned __int64)(v17 * v15 / v52) >> 16) >> 3);
+    v21 = (unsigned __int64)(v55 * (signed __int64)v56) >> 16;
+    v39 = (signed int)((unsigned __int64)(v21 * (signed __int64)v38) >> 16) >> 3;
+    v37 = (signed int)((unsigned __int64)(v21 * (signed __int64)v36) >> 16) >> 3;
+    v22 = sr_sub_47C178(v18, v3, 0, 1);
+    v23 = v3->pTexture;
+    v41 = v22;
+    v47 = 16 - v23->uWidthLn2;
+    v44 = v23->uTextureWidth - 1;
+    v49 = (v23->uTextureHeight << 16) - 65536;
+    v24 = v4->field_8;
+    v51 = &pRenderer->pTargetSurface[v24 + pRenderer->uTargetSurfacePitch * v4->field_A];
+    v57 = &pRenderer->pActiveZBuffer[v24 + 640 * v4->field_A];
+    v25 = v19;
+    v26 = v20;
+    v27 = v51;
+    if ( !(v45 & 1) )
+      goto LABEL_15;
+    --v45;
+    v27 = v51 - 1;
+    v28 = v57;
+    ++v57;
+    while ( 1 )
+    {
+      *v28 = -65536;
+      v31 = v44 & (v25 >> 16);
+      v27 += 2;
+      v25 += v39;
+      v32 = *((short *)v41 + *(&v43[v31] + ((v49 & (unsigned int)v26) >> v47)));
+      v26 += v37;
+      *(v27 - 1) = v32;
+LABEL_15:
+      v34 = __OFSUB__(v45, 2);
+      v33 = v45 - 2 < 0;
+      v45 -= 2;
+      if ( v33 ^ v34 )
+        break;
+      v29 = v44 & (v25 >> 16);
+      v25 += v39;
+      v30 = *((short *)v41 + *(&v43[v29] + ((v49 & (unsigned int)v26) >> v47)));
+      v26 += v37;
+      v28 = v57;
+      *v27 = v30;
+      v57 += 2;
+      v28[1] = -65536;
+    }
+    result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+//----- (0047F5C6) --------------------------------------------------------
+float Render::DrawBezierTerrain()
+{
+ //__debugbreak();Ritor1: it's temporarily
+  //return 0;
+  
+  unsigned int v0; // ebx@1
+  unsigned int v1; // edi@1
+  unsigned int v2; // eax@1
+  int v3; // eax@3
+  int v4; // edi@3
+  int v5; // ebx@3
+  int v6; // esi@3
+  unsigned int v7; // eax@3
+  int v8; // eax@4
+  unsigned int v9; // eax@6
+  int v10; // eax@7
+  int v11; // ebx@9
+  int v12; // edi@9
+  int v13; // eax@21
+  int v14; // eax@31
+  int v15; // edi@33
+  float v16; // eax@34
+  int v17; // edx@34
+  int v18; // ebx@34
+  int v19; // eax@36
+  int v20; // eax@39
+  int v21; // ecx@43
+  char v22; // zf@44
+  int v23; // ecx@47
+  int v24; // edi@52
+  float v25; // eax@54
+  int v26; // ecx@54
+  int v27; // eax@56
+  int v28; // edx@60
+  int v29; // ecx@61
+  int v30; // ecx@64
+  int v31; // ecx@68
+  int v32; // eax@70
+  int v33; // ecx@71
+  int v34; // eax@73
+  int v35; // ecx@77
+  int v36; // ecx@81
+  int v37; // ecx@86
+  float v38; // eax@88
+  IndoorCameraD3D *v39; // ecx@88
+  int v40; // eax@90
+  int v41; // edx@94
+  int v42; // ecx@95
+  int v43; // ecx@98
+  int v44; // ecx@102
+  int v45; // eax@104
+  int v46; // eax@107
+  int v47; // ecx@111
+  int v48; // ecx@115
+  int v49; // edi@120
+  float v50; // eax@122
+  int v51; // ecx@122
+  int v52; // eax@124
+  int v53; // edx@128
+  int v54; // ecx@129
+  int v55; // ecx@132
+  int v56; // eax@139
+  int v57; // ecx@140
+  int v58; // eax@142
+  int v59; // ecx@146
+  int v60; // ecx@147
+  int v61; // ecx@150
+  int v62; // ecx@155
+  float v63; // eax@157
+  IndoorCameraD3D *v64; // ecx@157
+  int v65; // eax@159
+  int v66; // edx@163
+  int v67; // ecx@164
+  int v68; // ecx@167
+  int v69; // eax@173
+  int v70; // edi@178
+  int v71; // eax@178
+  int v72; // ecx@178
+  int v73; // ebx@180
+  int v74; // eax@182
+  int v75; // eax@184
+  IndoorCameraD3D *v76; // ecx@184
+  int v77; // ecx@184
+  int v79; // ebx@185
+  int v127; // esi@185
+  int v86; // edi@196
+  int v87; // eax@196
+  int v88; // ecx@196
+  int v89; // eax@198
+  int v90; // ecx@200
+  int v92; // ebx@203
+  int v93; // ST08_4@204
+  int v97; // ST08_4@204
+  float result; // eax@212
+  char v102; // [sp+Ch] [bp-68h]@191
+  __int16 v103; // [sp+10h] [bp-64h]@190
+  __int16 v104; // [sp+12h] [bp-62h]@190
+  int v105; // [sp+1Ch] [bp-58h]@1
+  int v106; // [sp+20h] [bp-54h]@3
+  int v107; // [sp+24h] [bp-50h]@3
+  int v108; // [sp+28h] [bp-4Ch]@9
+  int v109; // [sp+2Ch] [bp-48h]@9
+  int v110; // [sp+30h] [bp-44h]@9
+  int v111; // [sp+34h] [bp-40h]@3
+  int v112; // [sp+38h] [bp-3Ch]@6
+  IndoorCameraD3D *a1; // [sp+3Ch] [bp-38h]@9
+  int v114; // [sp+40h] [bp-34h]@9
+  int v115; // [sp+44h] [bp-30h]@9
+  int v116; // [sp+48h] [bp-2Ch]@9
+  int v117; // [sp+4Ch] [bp-28h]@9
+  int v118; // [sp+50h] [bp-24h]@9
+  int v119; // [sp+54h] [bp-20h]@1
+  int v120; // [sp+58h] [bp-1Ch]@1
+  int i; // [sp+5Ch] [bp-18h]@1
+  int v122; // [sp+60h] [bp-14h]@1
+  int v123; // [sp+64h] [bp-10h]@1
+  float v124; // [sp+68h] [bp-Ch]@1
+  int v125; // [sp+6Ch] [bp-8h]@9
+  float v126; // [sp+70h] [bp-4h]@9
+
+  memset(&v102, 0, sizeof(v102));
+  v105 = pIndoorCamera->sRotationY / ((signed int)stru_5C6E00->uIntegerHalfPi / 2);
+  v0 = stru_5C6E00->uDoublePiMask & (stru_5C6E00->uIntegerDoublePi - pIndoorCamera->sRotationY);
+  v1 = stru_5C6E00->uDoublePiMask & (stru_5C6E00->uIntegerPi + v0);
+  LODWORD(v124) = (signed int)((pIndoorCamera->uMapGridCellX << 16)
+                             + 3
+                             * stru_5C6E00->SinCos(
+                                 stru_5C6E00->uDoublePiMask & (stru_5C6E00->uIntegerPi + v0))) >> 16;
+  v123 = (signed int)((pIndoorCamera->uMapGridCellZ << 16)
+                    + 3 * stru_5C6E00->SinCos(v1 - stru_5C6E00->uIntegerHalfPi)) >> 16;
+  v120 = pOutdoorCamera->outdoor_grid_band_3 + LODWORD(v124);
+  v119 = pOutdoorCamera->outdoor_grid_band_3 + v123;
+  v2 = pOutdoorCamera->uCameraFovInDegrees + 15;
+  i = LODWORD(v124) - pOutdoorCamera->outdoor_grid_band_3;
+  v122 = v123 - pOutdoorCamera->outdoor_grid_band_3;
+  if ( (signed int)(pOutdoorCamera->uCameraFovInDegrees + 15) > 90 )
+    v2 = 90;
+  v3 = (signed int)(v2 << 11) / 720;
+  v4 = stru_5C6E00->uDoublePiMask & (v0 - v3);
+  v5 = stru_5C6E00->uDoublePiMask & (v3 + v0);
+  v106 = stru_5C6E00->SinCos(v4);
+  v107 = stru_5C6E00->SinCos(v4 - stru_5C6E00->uIntegerHalfPi);
+  v111 = stru_5C6E00->SinCos(v5);
+  v6 = stru_5C6E00->SinCos(v5 - stru_5C6E00->uIntegerHalfPi);
+  v7 = v4 & stru_5C6E00->uPiMask;
+  if ( (signed int)(v4 & stru_5C6E00->uPiMask) >= (signed int)stru_5C6E00->uIntegerHalfPi )
+    v8 = -stru_5C6E00->pTanTable[stru_5C6E00->uIntegerPi - v7];
+  else
+    v8 = stru_5C6E00->pTanTable[v7];
+  v112 = abs(v8);
+  v9 = v5 & stru_5C6E00->uPiMask;
+  if ( (signed int)(v5 & stru_5C6E00->uPiMask) >= (signed int)stru_5C6E00->uIntegerHalfPi )
+    v10 = -stru_5C6E00->pTanTable[stru_5C6E00->uIntegerPi - v9];
+  else
+    v10 = stru_5C6E00->pTanTable[v9];
+  v108 = abs(v10);
+  v11 = LODWORD(v124);
+  v12 = v123;
+  v114 = 0;
+  v115 = 0;
+  a1 = 0;
+  v125 = 0;
+  v110 = 2 * (v106 >= 0) - 1;
+  v126 = v124;
+  v118 = v123;
+  v109 = 2 * (v107 >= 0) - 1;
+  v107 = 2 * (v111 >= 0) - 1;
+  terrain_76E1C8[0] = 65535;
+  v116 = 1;
+  v106 = 2 * (v6 >= 0) - 1;
+  v117 = 1;
+  terrain_76E3C8[0] = 65535;
+  terrain_76DDC8[0] = 65535;
+  terrain_76DFC8[0] = 65535;
+  while ( 1 )
+  {
+    if ( v112 >= 65536 )
+    {
+      v111 = 4294967296i64 / v112;
+      v114 += v111;
+      if ( v114 >= 65536 )
+      {
+        v11 += v110;
+        v114 = (unsigned __int16)v114;
+      }
+      v12 += v109;
+    }
+    else
+    {
+      v11 += v110;
+      v115 += v112;
+      if ( v115 >= 65536 )
+      {
+        v12 += v109;
+        v115 = (unsigned __int16)v115;
+      }
+    }
+    if ( v116 > 128 || v11 < i || v11 > v120 || v12 < v122 || v12 > v119 )
+      break;
+    v13 = v116++;
+    terrain_76E3C8[v13] = v11;
+    terrain_76E1C8[v13] = v12;
+  }
+  while ( 1 )
+  {
+    if ( v108 >= 65536 )
+    {
+      v111 = 4294967296i64 / v108;
+      a1 = (IndoorCameraD3D *)((char *)a1 + v111);
+      if ( (signed int)a1 >= 65536 )
+      {
+        LODWORD(v126) += v107;
+        a1 = (IndoorCameraD3D *)(unsigned __int16)a1;
+      }
+      v118 += v106;
+    }
+    else
+    {
+      v125 += v108;
+      LODWORD(v126) += v107;
+      if ( v125 >= 65536 )
+      {
+        v118 += v106;
+        v125 = (unsigned __int16)v125;
+      }
+    }
+    if ( v117 >= 128 )
+      break;
+    if ( SLODWORD(v126) < i )
+      break;
+    if ( SLODWORD(v126) > v120 )
+      break;
+    v14 = v118;
+    if ( v118 < v122 )
+      break;
+    if ( v118 > v119 )
+      break;
+    v15 = v117++;
+    terrain_76DFC8[v15] = LODWORD(v126);
+    terrain_76DDC8[v15] = v14;
+  }
+  LODWORD(v16) = 0;
+  LODWORD(v126) = 0;
+  v17 = v117 - 1;
+  v18 = v116 - 1;
+  switch ( v105 )
+  {
+    case 0:
+    case 7:
+      v116 = terrain_76DFC8[v17];
+      if ( v120 > v116 )
+      {
+        v125 = v120;
+        memset32(terrain_76D9C8, v119 + 1, v120 - v116 + 1);
+        v19 = v120;
+        do
+          terrain_76DBC8[LODWORD(v126)++] = v19--;
+        while ( v19 >= v116 );
+        if ( terrain_76DFC8[v17] == terrain_76DDC8[v17 + 127] )
+        {
+          do
+            v20 = terrain_76DDC8[v17-- + 127];
+          while ( v20 == terrain_76DDC8[v17 + 127] );
+        }
+        v16 = v126;
+        --v17;
+      }
+      if ( v17 < 0 )
+        v17 = 0;
+      v21 = terrain_76DFC8[v17];
+      while ( 1 )
+      {
+        v125 = v21;
+        if ( v21 < SLODWORD(v124) )
+          break;
+        terrain_76DBC8[LODWORD(v16)] = v21;
+        v22 = terrain_76DDC8[v17] == 65535;
+        terrain_76D9C8[LODWORD(v16)] = terrain_76DDC8[v17] + 1;
+        if ( v22 )
+        {
+          terrain_76D9C8[LODWORD(v16)] = v123 + 1;
+          break;
+        }
+        if ( !v17 )
+          break;
+        if ( terrain_76DFC8[v17] == terrain_76DDC8[v17 + 127] )
+        {
+          do
+            v23 = terrain_76DDC8[v17-- + 127];
+          while ( v23 == terrain_76DDC8[v17 + 127] );
+        }
+        --v17;
+        v21 = v125 - 1;
+        ++LODWORD(v16);
+      }
+      LODWORD(v16) = 0;
+      v24 = terrain_76E3C8[v18];
+      LODWORD(v126) = 0;
+      if ( v120 > v24 )
+      {
+        v125 = v120;
+        memset32(terrain_76D5C8, v122, v120 - v24 + 1);
+        do
+        {
+          v25 = v126;
+          v26 = v125--;
+          ++LODWORD(v126);
+          terrain_76D7C8[LODWORD(v25)] = v26;
+        }
+        while ( v125 >= terrain_76E3C8[v18] );
+        if ( terrain_76E3C8[v18] == terrain_76E1C8[v18 + 127] )
+        {
+          do
+            v27 = terrain_76E1C8[v18-- + 127];
+          while ( v27 == terrain_76E1C8[v18 + 127] );
+        }
+        v16 = v126;
+        --v18;
+      }
+      if ( v18 < 0 )
+        v18 = 0;
+      v28 = terrain_76E3C8[v18];
+      while ( v28 >= SLODWORD(v124) )
+      {
+        v29 = terrain_76E1C8[v18];
+        terrain_76D7C8[LODWORD(v16)] = v28;
+        terrain_76D5C8[LODWORD(v16)] = v29;
+        if ( v29 == 65535 )
+        {
+          v31 = v123;
+          goto LABEL_172;
+        }
+        if ( !v18 )
+          break;
+        if ( terrain_76E3C8[v18] == terrain_76E1C8[v18 + 127] )
+        {
+          do
+            v30 = terrain_76E1C8[v18-- + 127];
+          while ( v30 == terrain_76E1C8[v18 + 127] );
+        }
+        --v18;
+        --v28;
+        ++LODWORD(v16);
+      }
+      break;
+    case 1:
+    case 2:
+      v116 = terrain_76DDC8[v17];
+      if ( v122 < v116 )
+      {
+        v106 = v122;
+        memset32(terrain_76DBC8, v120 + 1, v116 - v122 + 1);
+        v32 = v122;
+        do
+        {
+          v33 = LODWORD(v126)++;
+          terrain_76D9C8[v33] = v32++;
+        }
+        while ( v32 <= v116 );
+        if ( terrain_76DDC8[v17] == terrain_76DBC8[v17 + 127] )
+        {
+          do
+            v34 = terrain_76DBC8[v17-- + 127];
+          while ( v34 == terrain_76DBC8[v17 + 127] );
+        }
+        v16 = v126;
+        --v17;
+      }
+      if ( v17 < 0 )
+        v17 = 0;
+      v35 = terrain_76DDC8[v17];
+      v125 = terrain_76DDC8[v17];
+      while ( v35 <= v123 )
+      {
+        v22 = terrain_76DFC8[v17] == 65535;
+        terrain_76DBC8[LODWORD(v16)] = terrain_76DFC8[v17] + 1;
+        terrain_76D9C8[LODWORD(v16)] = v125;
+        if ( v22 )
+        {
+          terrain_76DBC8[LODWORD(v16)] = LODWORD(v124) + 1;
+          break;
+        }
+        if ( !v17 )
+          break;
+        if ( terrain_76DDC8[v17] == terrain_76DBC8[v17 + 127] )
+        {
+          do
+            v36 = terrain_76DBC8[v17-- + 127];
+          while ( v36 == terrain_76DBC8[v17 + 127] );
+        }
+        --v17;
+        ++v125;
+        v35 = v125;
+        ++LODWORD(v16);
+      }
+      LODWORD(v16) = 0;
+      LODWORD(v126) = 0;
+      v37 = terrain_76E1C8[v18];
+      if ( v122 < v37 )
+      {
+        a1 = (IndoorCameraD3D *)v122;
+        memset32(terrain_76D7C8, i, v37 - v122 + 1);
+        do
+        {
+          v38 = v126;
+          v39 = a1;
+          ++LODWORD(v126);
+          a1 = (IndoorCameraD3D *)((char *)a1 + 1);
+          terrain_76D5C8[LODWORD(v38)] = (int)v39;
+        }
+        while ( (signed int)a1 <= terrain_76E1C8[v18] );
+        if ( terrain_76E1C8[v18] == terrain_76DFC8[v18 + 127] )
+        {
+          do
+            v40 = terrain_76DFC8[v18-- + 127];
+          while ( v40 == terrain_76DFC8[v18 + 127] );
+        }
+        v16 = v126;
+        --v18;
+      }
+      if ( v18 < 0 )
+        v18 = 0;
+      v41 = terrain_76E1C8[v18];
+      while ( v41 <= v123 )
+      {
+        v42 = terrain_76E3C8[v18];
+        terrain_76D5C8[LODWORD(v16)] = v41;
+        terrain_76D7C8[LODWORD(v16)] = v42;
+        if ( v42 == 65535 )
+        {
+          v44 = LODWORD(v124);
+          goto LABEL_137;
+        }
+        if ( !v18 )
+          break;
+        if ( terrain_76E1C8[v18] == terrain_76DFC8[v18 + 127] )
+        {
+          do
+            v43 = terrain_76DFC8[v18-- + 127];
+          while ( v43 == terrain_76DFC8[v18 + 127] );
+        }
+        --v18;
+        ++v41;
+        ++LODWORD(v16);
+      }
+      break;
+    case 5:
+    case 6:
+      v116 = terrain_76DDC8[v17];
+      if ( v119 > v116 )
+      {
+        v106 = v119;
+        memset32(terrain_76DBC8, i, v119 - v116 + 1);
+        v45 = v119;
+        do
+          terrain_76D9C8[LODWORD(v126)++] = v45--;
+        while ( v45 >= v116 );
+        if ( terrain_76DDC8[v17] == terrain_76DBC8[v17 + 127] )
+        {
+          do
+            v46 = terrain_76DBC8[v17-- + 127];
+          while ( v46 == terrain_76DBC8[v17 + 127] );
+        }
+        v16 = v126;
+        --v17;
+      }
+      if ( v17 < 0 )
+        v17 = 0;
+      v47 = terrain_76DDC8[v17];
+      v125 = terrain_76DDC8[v17];
+      while ( v47 >= v123 )
+      {
+        v22 = terrain_76DFC8[v17] == 65535;
+        terrain_76DBC8[LODWORD(v16)] = terrain_76DFC8[v17];
+        terrain_76D9C8[LODWORD(v16)] = v125;
+        if ( v22 )
+        {
+          terrain_76DBC8[LODWORD(v16)] = LODWORD(v124);
+          break;
+        }
+        if ( !v17 )
+          break;
+        if ( terrain_76DDC8[v17] == terrain_76DBC8[v17 + 127] )
+        {
+          do
+            v48 = terrain_76DBC8[v17-- + 127];
+          while ( v48 == terrain_76DBC8[v17 + 127] );
+        }
+        --v17;
+        --v125;
+        v47 = v125;
+        ++LODWORD(v16);
+      }
+      LODWORD(v16) = 0;
+      v49 = terrain_76E1C8[v18];
+      LODWORD(v126) = 0;
+      if ( v119 > v49 )
+      {
+        v125 = v119;
+        memset32(terrain_76D7C8, v120 + 1, v119 - v49 + 1);
+        do
+        {
+          v50 = v126;
+          v51 = v125--;
+          ++LODWORD(v126);
+          terrain_76D5C8[LODWORD(v50)] = v51;
+        }
+        while ( v125 >= terrain_76E1C8[v18] );
+        if ( terrain_76E1C8[v18] == terrain_76DFC8[v18 + 127] )
+        {
+          do
+            v52 = terrain_76DFC8[v18-- + 127];
+          while ( v52 == terrain_76DFC8[v18 + 127] );
+        }
+        v16 = v126;
+        --v18;
+      }
+      if ( v18 < 0 )
+        v18 = 0;
+      v53 = terrain_76E1C8[v18];
+      while ( v53 >= v123 )
+      {
+        v54 = terrain_76E3C8[v18];
+        terrain_76D5C8[LODWORD(v16)] = v53;
+        terrain_76D7C8[LODWORD(v16)] = v54 + 1;
+        if ( v54 == 65535 )
+        {
+          v44 = LODWORD(v124) + 1;
+LABEL_137:
+          terrain_76D7C8[LODWORD(v16)] = v44;
+          goto LABEL_173;
+        }
+        if ( !v18 )
+          goto LABEL_173;
+        if ( terrain_76E1C8[v18] == terrain_76DFC8[v18 + 127] )
+        {
+          do
+            v55 = terrain_76DFC8[v18-- + 127];
+          while ( v55 == terrain_76DFC8[v18 + 127] );
+        }
+        --v18;
+        --v53;
+        ++LODWORD(v16);
+      }
+      break;
+    case 3:
+    case 4:
+      v116 = terrain_76DFC8[v17];
+      if ( i < v116 )
+      {
+        v106 = i;
+        memset32(terrain_76D9C8, v122, v116 - i + 1);
+        v56 = i;
+        do
+        {
+          v57 = LODWORD(v126)++;
+          terrain_76DBC8[v57] = v56++;
+        }
+        while ( v56 <= v116 );
+        if ( terrain_76DFC8[v17] == terrain_76DDC8[v17 + 127] )
+        {
+          do
+            v58 = terrain_76DDC8[v17-- + 127];
+          while ( v58 == terrain_76DDC8[v17 + 127] );
+        }
+        v16 = v126;
+        --v17;
+      }
+      if ( v17 < 0 )
+        v17 = 0;
+      v59 = terrain_76DFC8[v17];
+      while ( 1 )
+      {
+        v125 = v59;
+        if ( v59 > SLODWORD(v124) )
+          break;
+        terrain_76DBC8[LODWORD(v16)] = v59;
+        v60 = terrain_76DDC8[v17];
+        terrain_76D9C8[LODWORD(v16)] = v60;
+        if ( v60 == 65535 )
+        {
+          terrain_76D9C8[LODWORD(v16)] = v123;
+          break;
+        }
+        if ( !v17 )
+          break;
+        if ( terrain_76DFC8[v17] == terrain_76DDC8[v17 + 127] )
+        {
+          do
+            v61 = terrain_76DDC8[v17-- + 127];
+          while ( v61 == terrain_76DDC8[v17 + 127] );
+        }
+        --v17;
+        v59 = v125 + 1;
+        ++LODWORD(v16);
+      }
+      LODWORD(v16) = 0;
+      LODWORD(v126) = 0;
+      v62 = terrain_76E3C8[v18];
+      if ( i < v62 )
+      {
+        a1 = (IndoorCameraD3D *)i;
+        memset32(terrain_76D5C8, v119 + 1, v62 - i + 1);
+        do
+        {
+          v63 = v126;
+          v64 = a1;
+          ++LODWORD(v126);
+          a1 = (IndoorCameraD3D *)((char *)a1 + 1);
+          terrain_76D7C8[LODWORD(v63)] = (int)v64;
+        }
+        while ( (signed int)a1 <= terrain_76E3C8[v18] );
+        if ( terrain_76E3C8[v18] == terrain_76E1C8[v18 + 127] )
+        {
+          do
+            v65 = terrain_76E1C8[v18-- + 127];
+          while ( v65 == terrain_76E1C8[v18 + 127] );
+        }
+        v16 = v126;
+        --v18;
+      }
+      if ( v18 < 0 )
+        v18 = 0;
+      v66 = terrain_76E3C8[v18];
+      while ( v66 <= SLODWORD(v124) )
+      {
+        v67 = terrain_76E1C8[v18];
+        terrain_76D7C8[LODWORD(v16)] = v66;
+        terrain_76D5C8[LODWORD(v16)] = v67 + 1;
+        if ( v67 == 65535 )
+        {
+          v31 = v123 + 1;
+LABEL_172:
+          terrain_76D5C8[LODWORD(v16)] = v31;
+          goto LABEL_173;
+        }
+        if ( !v18 )
+          goto LABEL_173;
+        if ( terrain_76E3C8[v18] == terrain_76E1C8[v18 + 127] )
+        {
+          do
+            v68 = terrain_76E1C8[v18-- + 127];
+          while ( v68 == terrain_76E1C8[v18 + 127] );
+        }
+        --v18;
+        ++v66;
+        ++LODWORD(v16);
+      }
+      break;
+    default:
+      break;
+  }
+LABEL_173:
+  v69 = LODWORD(v16) - 1;
+  ptr_801A08 = pVerticesSR_806210;
+  ptr_801A04 = pVerticesSR_801A10;
+  LODWORD(v126) = v69;
+  if ( v105 && v105 != 7 && v105 != 3 && v105 != 4 )
+  {
+    for ( i = v69; i >= 1; --i )
+    {
+      v70 = i;
+      v71 = terrain_76D7C8[i];
+      v72 = terrain_76DBC8[i];
+      if ( v71 < v72 )
+      {
+        terrain_76DBC8[v70] = v71;
+        terrain_76D7C8[v70] = v72;
+      }
+      v73 = terrain_76DBC8[v70];
+      v111 = 0;
+      if ( v73 <= 0 )
+        v73 = -v73;
+      v74 = terrain_76D7C8[v70];
+      if ( v74 <= 0 )
+        v74 = -v74;
+      v75 = v74 + 2;
+      v76 = pGame->pIndoorCameraD3D;
+      v107 = v75;
+      a1 = v76;
+      v77 = v73 - 2;
+      if ( v73 - 2 < v75 )
+      {
+        v127 = 0;
+        v79 = (v73 - 66) << 9;
+        v116 = v77;
+        v105 = v79;
+        v111 = v75 - v77;
+        do
+        {
+		  *(float *)&v106 = (double)v105;
+          *(float *)((char *)&ptr_801A08->vWorldPosition.x + v127) = *(float *)&v106;
+          v105 = (64 - *(int *)((char *)terrain_76D9C8 + v70)) << 9;
+          *(float *)((char *)&ptr_801A08->vWorldPosition.y + v127) = (double)v105;
+          v105 = pOutdoor->GetHeightOnTerrain(v112, *(int *)((char *)terrain_76D9C8 + v70));
+          *(float *)((char *)&ptr_801A08->vWorldPosition.z + v127) = (double)v105;
+          *(float *)((char *)&ptr_801A04->vWorldPosition.x + v127) = *(float *)&v106;
+          v105 = (63 - *(int *)((char *)terrain_76D9C8 + v70)) << 9;
+          *(float *)((char *)&ptr_801A04->vWorldPosition.y + v127) = (double)v105;
+          v105 = pOutdoor->GetHeightOnTerrain(v112, *(int *)((char *)terrain_76D9C8 + v70) + 1);
+          *(float *)((char *)&ptr_801A04->vWorldPosition.z + v127) = (double)v105;
+          if ( !byte_4D864C || !(pGame->uFlags & 0x80) )
+          {
+            a1->ViewTransform((RenderVertexSoft *)(char *)ptr_801A08 + v127, 1);
+            a1->ViewTransform((RenderVertexSoft *)(char *)ptr_801A04 + v127, 1);
+            a1->Project((RenderVertexSoft *)(char *)ptr_801A08 + v127, 1, 0);
+            a1->Project((RenderVertexSoft *)(char *)ptr_801A04 + v127, 1, 0);
+          }
+          v79 += 512;
+          v127 += 48;
+          ++v116;
+          v105 = v79;
+		}
+        while ( v116 < v107 );
+      }
+	  v103 = abs((int)pIndoorCamera->uMapGridCellZ - terrain_76D9C8[v70]);
+      v104 = abs((int)pIndoorCamera->uMapGridCellX - terrain_76DBC8[v70]);
+	  if ( pRenderer->pRenderD3D )
+        Render::DrawTerrainD3D(v111, 0, (int)&v102);
+      else
+        Render::DrawTerrainSW(v111, 0, (int)&v102);
+    }
+  }
+  else
+  {
+    for ( i = v69; i >= 1; --i )
+    {
+      v86 = i;
+      v87 = terrain_76D5C8[i];
+      v88 = terrain_76D9C8[i];
+      if ( v87 < v88 )
+      {
+        terrain_76D9C8[v86] = v87;
+        terrain_76D5C8[v86] = v88;
+      }
+      v89 = terrain_76D9C8[v86];
+      v111 = 0;
+      if ( v89 <= 0 )
+        v89 = -v89;
+      v90 = terrain_76D5C8[v86];
+      if ( v90 <= 0 )
+        v90 = -v90;
+      a1 = pGame->pIndoorCameraD3D;
+      v107 = v90 + 2;
+      if ( v89 - 2 < v90 + 2 )
+      {
+        v86 = 0;
+        v116 = v89 - 2;
+        v92 = (66 - v89) << 9;
+        v105 = (66 - v89) << 9;
+        v111 = v90 + 2 - (v89 - 2);
+        do
+        {
+          v93 = v116;
+          v106 = (*(int *)((char *)terrain_76DBC8 + v86) - 64) << 9;
+          *(float *)((char *)&ptr_801A08->vWorldPosition.x + v86) = (double)v106;
+          *(float *)&v105 = (double)v105;
+          *(float *)((char *)&ptr_801A08->vWorldPosition.y + v86) = *(float *)&v105;
+          v106 = pOutdoor->GetHeightOnTerrain(*(int *)((char *)terrain_76DBC8 + v86), v93);
+          v97 = v116;
+          *(float *)((char *)&ptr_801A08->vWorldPosition.z + v86) = (double)v106;
+          v106 = (*(int *)((char *)terrain_76DBC8 + v86) - 63) << 9;
+          *(float *)((char *)&ptr_801A04->vWorldPosition.x + v86) = (double)v106;
+          *(float *)((char *)&ptr_801A04->vWorldPosition.y + v86) = *(float *)&v105;
+          v105 = pOutdoor->GetHeightOnTerrain(*(int *)((char *)terrain_76DBC8 + v86) + 1, v97);
+          *(float *)((char *)&ptr_801A04->vWorldPosition.z + v86) = (double)v105;
+          if ( !byte_4D864C || !(pGame->uFlags & 0x80) )
+          {
+           a1->ViewTransform((RenderVertexSoft *)(char *)ptr_801A08 + v86, 1);
+           a1->ViewTransform((RenderVertexSoft *)(char *)ptr_801A04 + v86, 1);
+           a1->Project((RenderVertexSoft *)(char *)ptr_801A08 + v86, 1, 0);
+           a1->Project((RenderVertexSoft *)(char *)ptr_801A04 + v86, 1, 0);
+          }
+          v92 -= 512;
+          v86 += 48;
+          ++v116;
+          v105 = v92;
+		}
+        while ( v116 < v107 );
+      }
+      v103 = abs((int)pIndoorCamera->uMapGridCellX - terrain_76DBC8[v86]);
+	  v104 = abs((int)pIndoorCamera->uMapGridCellZ - terrain_76D9C8[v86]);
+	  if ( pRenderer->pRenderD3D )
+        Render::DrawTerrainD3D(v111, 1, (int)&v102);
+      else
+        Render::DrawTerrainSW(v111, 1, (int)&v102);
+    }
+  }
+  result = v126;
+  pOutdoorCamera->field_40 = v126;
+  return result;
+}
+// 47FFC4: inconsistent fpu stack
+// 4D864C: using guessed type char byte_4D864C;
+
+
+
+//----- (0048034E) --------------------------------------------------------
+void Render::DrawTerrainD3D(int a1, int edx0, int a3)
+{
+  int v3; // esi@1
+  int v4; // edi@1
+  int v5; // ebx@2
+  int v6; // eax@2
+  int v7; // eax@3
+  RenderVertexSoft *v8; // edi@3
+  RenderVertexSoft *v9; // ebx@4
+  RenderVertexSoft *v10; // ecx@4
+  float v11; // eax@6
+  double v12; // ST5C_8@6
+  double v13; // ST2C_8@6
+  int v14; // eax@6
+  double v15; // st7@6
+  stru148 *v16; // ebx@12
+  unsigned __int16 v17; // ax@12
+  int v18; // eax@13
+  LightmapBuilder *v19; // ecx@13
+  stru220 *v20; // eax@13
+  int v21; // eax@13
+  signed int v22; // eax@13
+  Vec3_float_ *v23; // eax@15
+  double v24; // st6@17
+  double v25; // ST54_8@17
+  unsigned __int8 v26; // sf@17
+  unsigned __int8 v27; // of@17
+  double v28; // st5@19
+  double v29; // st5@19
+  double v30; // st5@19
+  double v31; // st5@19
+  double v32; // st7@32
+  int v33; // edi@38
+  unsigned int v34; // ecx@47
+  char v35; // zf@47
+  unsigned int v36; // eax@50
+  int v37; // eax@54
+  stru148 *v38; // ecx@55
+  unsigned int v39; // eax@59
+  stru148 *v40; // ebx@62
+  unsigned __int16 v41; // ax@62
+  int v42; // eax@63
+  LightmapBuilder *v43; // ecx@63
+  stru220 *v44; // eax@63
+  int v45; // eax@63
+  int v46; // eax@63
+  signed int v47; // eax@63
+  Vec3_float_ *v48; // eax@65
+  double v49; // st6@67
+  double v50; // ST4C_8@67
+  double v51; // st5@71
+  double v52; // st5@71
+  double v53; // st5@71
+  double v54; // st7@84
+  unsigned int v55; // ecx@98
+  unsigned int v56; // eax@101
+  int v57; // eax@105
+  unsigned int v58; // eax@109
+  stru148 *v59; // esi@112
+  unsigned __int16 v60; // ax@112
+  stru220 *v61; // eax@113
+  signed int v62; // eax@113
+  Vec3_float_ *v63; // eax@114
+  double v64; // st6@116
+  double v65; // ST3C_8@116
+  double v66; // st5@120
+  double v67; // st5@120
+  double v68; // st5@120
+  double v69; // st7@133
+  int v70; // edi@138
+  RenderVertexSoft *v71; // esi@147
+  unsigned int v72; // ecx@147
+  unsigned int v73; // eax@150
+  float v74; // eax@154
+  unsigned int v75; // eax@158
+  unsigned int v76; // [sp-10h] [bp-E0h]@61
+  stru148 *v77; // [sp-Ch] [bp-DCh]@61
+  IDirect3DTexture2 *v78; // [sp-8h] [bp-D8h]@61
+  int v79; // [sp-4h] [bp-D4h]@61
+  int v80; // [sp+0h] [bp-D0h]@59
+  int v81; // [sp+0h] [bp-D0h]@109
+  int v82; // [sp+54h] [bp-7Ch]@1
+  int v83; // [sp+60h] [bp-70h]@1
+  int v84; // [sp+6Ch] [bp-64h]@1
+  int v85; // [sp+70h] [bp-60h]@63
+  int a4; // [sp+74h] [bp-5Ch]@73
+  float v87; // [sp+78h] [bp-58h]@122
+  int v88; // [sp+7Ch] [bp-54h]@1
+  int v89; // [sp+80h] [bp-50h]@6
+  float v90; // [sp+84h] [bp-4Ch]@1
+  float v91; // [sp+88h] [bp-48h]@1
+  float v92; // [sp+8Ch] [bp-44h]@1
+  stru220 *v93; // [sp+90h] [bp-40h]@2
+  int X; // [sp+94h] [bp-3Ch]@1
+  float v95; // [sp+98h] [bp-38h]@21
+  LightmapBuilder *v96; // [sp+9Ch] [bp-34h]@73
+  LightmapBuilder *_this; // [sp+A0h] [bp-30h]@6
+  int sX; // [sp+A4h] [bp-2Ch]@6
+  unsigned int uNumVertices; // [sp+A8h] [bp-28h]@73
+  int v100; // [sp+ACh] [bp-24h]@122
+  int sY; // [sp+B0h] [bp-20h]@6
+  RenderVertexSoft *a2; // [sp+B4h] [bp-1Ch]@3
+  unsigned int a5; // [sp+B8h] [bp-18h]@21
+  RenderVertexSoft *v101; // [sp+BCh] [bp-14h]@6
+  Vec3_float_ *v99; // [sp+C0h] [bp-10h]@17
+  RenderVertexSoft *pVertices; // [sp+C4h] [bp-Ch]@6
+  RenderVertexSoft *a8; // [sp+C8h] [bp-8h]@6
+  char v108; // [sp+CFh] [bp-1h]@36
+  float thisd; // [sp+D8h] [bp+8h]@6
+  float thise; // [sp+D8h] [bp+8h]@6
+  float thisf; // [sp+D8h] [bp+8h]@17
+  IndoorCameraD3D *thisa; // [sp+D8h] [bp+8h]@23
+  float thisg; // [sp+D8h] [bp+8h]@67
+  IndoorCameraD3D *thisb; // [sp+D8h] [bp+8h]@75
+  float thish; // [sp+D8h] [bp+8h]@116
+  IndoorCameraD3D *thisc; // [sp+D8h] [bp+8h]@124
+  char this_3; // [sp+DBh] [bp+Bh]@30
+  char this_3a; // [sp+DBh] [bp+Bh]@82
+  char this_3b; // [sp+DBh] [bp+Bh]@131
+
+  v3 = a1;
+  v82 = edx0;
+  v83 = *(/*short **/_WORD *)(a3 + 4);
+  X = abs(*(/*short **/_WORD *)(a3 + 6));
+  v4 = 0;
+  v88 = 0;
+  v84 = v3 - 1;
+  v90 = (double)pOutdoor->vSunlight.x * 0.000015258789;
+  v91 = (double)pOutdoor->vSunlight.y * 0.000015258789;
+  v92 = (double)pOutdoor->vSunlight.z * 0.000015258789;
+  if ( v3 - 1 > 0 )
+  {
+    while ( 1 )
+    {
+      v5 = abs(X);//v5 = 13108
+      v6 = abs(v83);//v6 = 13108
+      --X;
+      v93 = &stru_76E5C8[(v5 << 7) + v6];
+ 	  if ( !v93->field_0 || ((v7 = 48 * v4, v8 = &pVerticesSR_806210[v4], a2 = v8, !v82) ? (v9 = (RenderVertexSoft *)((char *)&pVerticesSR_801A10 + v7),
+                                                                       v10 = &pVerticesSR_806210[1] + v7) : (v9 = &pVerticesSR_806210[1] + v7, v10 = (RenderVertexSoft *)((char *)&pVerticesSR_801A10 + v7)),
+             ((a8 = v9,
+               pVertices = &pVerticesSR_801A10[1] + v7,
+               v11 = v8->vWorldPosition.x,
+               v101 = v10,
+               v12 = v11 + 6.755399441055744e15,
+               sX = LODWORD(v12),
+               v13 = v8->vWorldPosition.y + 6.755399441055744e15,
+               sY = LODWORD(v13),
+               thisd = (v10->vWorldPosition.x + v8->vWorldPosition.x) * 0.5,
+               v14 = WorldPosToGridCellX(floorf(thisd + 0.5f)),
+               v15 = v9->vWorldPosition.y + v8->vWorldPosition.y,
+               v89 = v14,
+               thise = v15 * 0.5,
+               _this = (LightmapBuilder *)WorldPosToGridCellZ(floorf(thisd + 0.5f)),
+               WorldPosToGridCellX(sX),
+               WorldPosToGridCellZ(sY),
+               !byte_4D864C)
+           || !(pGame->uFlags & 0x80))
+          && !sub_481EFA(v8, v9, v101, pVertices, 1)) )
+        goto LABEL_162;
+      if ( v8->vWorldPosition.z != v9->vWorldPosition.z || v9->vWorldPosition.z != pVertices->vWorldPosition.z || pVertices->vWorldPosition.z != v101->vWorldPosition.z )
+        break;
+      v16 = &array_77EC08[pOutdoorCamera->numStru148s];
+      v17 = pOutdoor->GetTileTexture(sX, sY);
+      v16->uTileBitmapID = v17;
+      if ( v17 != -1 )
+      {
+        v18 = pOutdoor->GetSomeOtherTileInfo(sX, sY);
+        LOWORD(v18) = v18 | 0x8010;
+        v19 = _this;
+        *(int *)&v16->flags = v18;
+        v20 = v93;
+        v16->field_59 = 1;
+        v16->field_5D = (char)v19;
+        v16->field_34 = v20->distance;
+        v21 = v89;
+        v16->field_5C = v89;
+        v22 = pTerrainNormalIndices[2 * (signed int)((char *)v19 + 128 * v21) + 1];
+        if ( v22 < 0 || v22 > (signed int)(uNumTerrainNormals - 1) )
+          v23 = 0;
+        else
+          v23 = &pTerrainNormals[v22];
+        v24 = v92 * v23->z;
+        v99 = v23;
+        thisf = 20.0 - (-v24 - v91 * v23->y - v90 * v23->x) * 20.0;
+        v25 = thisf + 6.7553994e15;
+        v27 = pOutdoorCamera->numStru148s > 1999;
+        v26 = pOutdoorCamera->numStru148s - 1999 < 0;
+        v16->field_58 = LOBYTE(v25);
+        if ( !(v26 ^ v27) )
+          return;
+        ++pOutdoorCamera->numStru148s;
+        if ( !sub_481FC9(v8, a8, v101, v16) )
+          goto LABEL_126;
+        v28 = 1.0 / (a2->vWorldViewPosition.x + 0.0000001);
+        memcpy(array_50AC10, a2, 0x30u);
+        array_50AC10[0].flt_20 = v28;
+        array_50AC10[0].u = 0.0;
+        array_50AC10[0].v = 0.0;
+        v29 = a8->vWorldViewPosition.x + 0.0000001;
+        memcpy(&array_50AC10[1], a8, sizeof(array_50AC10[1]));
+        array_50AC10[1].flt_20 = 1.0 / v29;
+        array_50AC10[1].u = 0.0;
+        array_50AC10[1].v = 1.0;
+        v30 = pVertices->vWorldViewPosition.x + 0.0000001;
+        memcpy(&array_50AC10[2], pVertices, sizeof(array_50AC10[2]));
+        array_50AC10[2].flt_20 = 1.0 / v30;
+        array_50AC10[2].u = 1.0;
+        array_50AC10[2].v = 1.0;
+        v31 = v101->vWorldViewPosition.x + 0.0000001;
+        memcpy(&array_50AC10[3], v101, sizeof(array_50AC10[3]));
+        array_50AC10[3].flt_20 = 1.0 / v31;
+        array_50AC10[3].u = 1.0;
+        array_50AC10[3].v = 0.0;
+
+        static stru154 static_sub_0048034E_stru_154;
+        /*static bool __init_flag3 = false;
+        if (!__init_flag3)
+        {
+          __init_flag3 = true;
+
+          stru154::stru154(&static_sub_0048034E_stru_154);
+        }*/
+
+        _this = pGame->pLightmapBuilder;
+        pGame->pLightmapBuilder->StackLights_TerrainFace(v99, &v95, array_50AC10, 4u, 1);
+        pDecalBuilder->_49BE8A(v16, *(float *)&v99, (int)&v95, array_50AC10, 4u, 1);
+        a5 = 4;
+        if ( byte_4D864C && pGame->uFlags & 0x80 )
+        {
+          thisa = pGame->pIndoorCameraD3D;
+          if ( pGame->pIndoorCameraD3D->_4371C3(array_50AC10, &a5, 0) == 1 && !a5 )
+            goto LABEL_162;
+          thisa->ViewTransform(array_50AC10, a5);
+          thisa->Project(array_50AC10, a5, 0);
+        }
+        this_3 = a2->vWorldViewPosition.x < 8.0
+              || a8->vWorldViewPosition.x < 8.0
+              || v101->vWorldViewPosition.x < 8.0
+              || pVertices->vWorldViewPosition.x < 8.0;
+        v32 = (double)pOutdoorCamera->shading_dist_mist;
+        v108 = v32 < a2->vWorldViewPosition.x
+            || v32 < a8->vWorldViewPosition.x
+            || v32 < v101->vWorldViewPosition.x
+            || v32 < pVertices->vWorldViewPosition.x;
+        LOBYTE(v33) = 0;
+        pGame->pLightmapBuilder->std__vector_000004_size = 0;
+        if ( stru_F8AD28.uNumLightsApplied > 0 || pDecalBuilder->uNumDecals > 0 )
+        {
+          if ( this_3 )
+            LOBYTE(v33) = 3;
+          else
+            v33 = v108 != 0 ? 5 : 0;
+          static_sub_0048034E_stru_154._49B0C9(v99, v95);
+          if ( pDecalBuilder->uNumDecals > 0 )
+            pDecalBuilder->ApplyDecals(
+              31 - v16->field_58,
+              4,
+              &static_sub_0048034E_stru_154,
+              a5,
+              array_50AC10,
+              0,
+              v33,
+              -1);
+        }
+        if ( stru_F8AD28.uNumLightsApplied > 0 )
+          pGame->pLightmapBuilder->ApplyLights(&stru_F8AD28, &static_sub_0048034E_stru_154, a5, array_50AC10, 0, v33);
+        v34 = a5;
+        v35 = byte_4D864C == 0;
+        v16->uNumVertices = a5;
+        if ( v35 || !(pGame->uFlags & 0x80) )
+        {
+          if ( this_3 )
+          {
+            v36 = sr_424CD7(v34);
+            goto LABEL_53;
+          }
+          if ( v108 )
+          {
+            v36 = sr_424EE0_MakeFanFromTriangle(v34);
+LABEL_53:
+            v16->uNumVertices = v36;
+            OutdoorCamera::Project(v36);
+          }
+        }
+        v37 = *(int *)&v16->flags;
+        if ( !(BYTE1(v37) & 1) )
+        {
+          if ( v37 & 2 && v16->uTileBitmapID == pRenderer->field_1036AC_bitmapid )
+          {
+            v80 = 0;
+            v39 = pRenderer->pHDWaterBitmapIDs[pRenderer->field_1036A8_bitmapid];
+          }
+          else
+          {
+            v39 = v16->uTileBitmapID;
+            v80 = 1;
+          }
+          v79 = 0;
+          v78 = pBitmaps_LOD->pHardwareTextures[v39];
+          v77 = v16;
+          v76 = v16->uNumVertices;
+LABEL_161:
+          pRenderer->DrawTerrainPolygon(v76, v77, v78, v79, v80);
+          goto LABEL_162;
+        }
+        v38 = v16;
+LABEL_56:
+        v38->_4811A3();
+      }
+LABEL_162:
+      v4 = v88++ + 1;
+      if ( v88 >= v84 )
+        return;
+    }
+    v40 = &array_77EC08[pOutdoorCamera->numStru148s];
+    v41 = pOutdoor->GetTileTexture(sX, sY);
+    v40->uTileBitmapID = v41;
+    if ( v41 == -1 )
+      goto LABEL_162;
+    v42 = pOutdoor->GetSomeOtherTileInfo(sX, sY);
+    BYTE1(v42) |= 0x80u;
+    v43 = pGame->pLightmapBuilder;
+    *(int *)&v40->flags = v42;
+    v44 = v93;
+    v40->field_59 = 1;
+    v40->field_5D = (char)v43;
+    v40->field_34 = v44->distance;
+    v45 = v89;
+    v40->field_5C = v89;
+    v46 = 2 * (int)((char *)v43 + 128 * v45);
+    v85 = v46 * 2;
+    v47 = pTerrainNormalIndices[v46 + 1];
+    if ( v47 < 0 || v47 > (signed int)(uNumTerrainNormals - 1) )
+      v48 = 0;
+    else
+      v48 = &pTerrainNormals[v47];
+    v49 = v92 * v48->z;
+    v99 = v48;
+    thisg = 20.0 - (-v49 - v91 * v48->y - v90 * v48->x) * 20.0;
+    v50 = thisg + 6.7553994e15;
+    v40->field_58 = LOBYTE(v50);
+    if ( SLOBYTE(v50) < 0 )
+      v40->field_58 = 0;
+    if ( pOutdoorCamera->numStru148s >= 1999 )
+      return;
+    ++pOutdoorCamera->numStru148s;
+    if ( !sub_481FC9(a8, pVertices, v8, v40) )
+      goto LABEL_77;
+    v51 = 1.0 / (a2->vWorldViewPosition.x + 0.0000001);
+    memcpy(array_50AC10, a2, 0x30u);
+    array_50AC10[0].flt_20 = v51;
+    array_50AC10[0].u = 0.0;
+    array_50AC10[0].v = 0.0;
+    v52 = a8->vWorldViewPosition.x + 0.0000001;
+    memcpy(&array_50AC10[1], a8, sizeof(array_50AC10[1]));
+    array_50AC10[1].flt_20 = 1.0 / v52;
+    array_50AC10[1].u = 0.0;
+    array_50AC10[1].v = 1.0;
+    v53 = pVertices->vWorldViewPosition.x + 0.0000001;
+    memcpy(&array_50AC10[2], pVertices, sizeof(array_50AC10[2]));
+    array_50AC10[2].flt_20 = 1.0 / v53;
+    array_50AC10[2].u = 1.0;
+    array_50AC10[2].v = 1.0;
+
+    static stru154 static_sub_0048034E_stru_76D590;
+    /*static bool __init_flag2 = false;
+    if (!__init_flag2)
+    {
+      __init_flag2 = true;
+
+      stru154::stru154(&static_sub_0048034E_stru_76D590);
+    }*/
+
+    v96 = pGame->pLightmapBuilder;
+    pGame->pLightmapBuilder->StackLights_TerrainFace(v99, (float *)&a4, array_50AC10, 3u, 0);
+    pDecalBuilder->_49BE8A(v40, *(float *)&v99, (int)&a4, array_50AC10, 3u, 0);
+    uNumVertices = 3;
+    if ( byte_4D864C && pGame->uFlags & 0x80 )
+    {
+      thisb = pGame->pIndoorCameraD3D;
+      if ( pGame->pIndoorCameraD3D->_4371C3(array_50AC10, &uNumVertices, 0) == 1 && !uNumVertices )
+      {
+LABEL_77:
+        --pOutdoorCamera->numStru148s;
+        goto LABEL_112;
+      }
+      thisb->ViewTransform(array_50AC10, uNumVertices);
+      thisb->Project(array_50AC10, uNumVertices, 0);
+    }
+    this_3a = a2->vWorldViewPosition.x < 8.0 || a8->vWorldViewPosition.x < 8.0 || pVertices->vWorldViewPosition.x < 8.0;
+    v54 = (double)pOutdoorCamera->shading_dist_mist;
+    v108 = v54 < a2->vWorldViewPosition.x || v54 < a8->vWorldViewPosition.x || v54 < pVertices->vWorldViewPosition.x;
+    a8 = 0;
+    v96->std__vector_000004_size = 0;
+    if ( stru_F8AD28.uNumLightsApplied > 0 || pDecalBuilder->uNumDecals > 0 )
+    {
+      a8 = (RenderVertexSoft *)(this_3a ? 3 : v108 != 0 ? 5 : 0);
+      static_sub_0048034E_stru_76D590._49B0C9(v99, *(float *)&a4);
+      if ( pDecalBuilder->uNumDecals > 0 )
+        pDecalBuilder->ApplyDecals(
+          31 - v40->field_58,
+          4,
+          &static_sub_0048034E_stru_76D590,
+          uNumVertices,
+          array_50AC10,
+          0,
+          (char)a8,
+          -1);
+    }
+    if ( stru_F8AD28.uNumLightsApplied > 0 )
+      v96->ApplyLights(
+        &stru_F8AD28,
+        &static_sub_0048034E_stru_76D590,
+        uNumVertices,
+        array_50AC10,
+        0,
+        (char)a8);
+    v55 = uNumVertices;
+    v35 = byte_4D864C == 0;
+    v40->uNumVertices = uNumVertices;
+    if ( v35 || !(pGame->uFlags & 0x80) )
+    {
+      if ( this_3a )
+      {
+        v56 = sr_424CD7(v55);
+      }
+      else
+      {
+        if ( !v108 )
+          goto LABEL_105;
+        v56 = sr_424EE0_MakeFanFromTriangle(v55);
+      }
+      v40->uNumVertices = v56;
+      OutdoorCamera::Project(v56);
+    }
+LABEL_105:
+    v57 = *(int *)&v40->flags;
+    if ( BYTE1(v57) & 1 )
+    {
+      v40->_4811A3();
+    }
+    else
+    {
+      if ( v57 & 2 && v40->uTileBitmapID == pRenderer->field_1036AC_bitmapid )
+      {
+        v81 = 0;
+        v58 = pRenderer->pHDWaterBitmapIDs[pRenderer->field_1036A8_bitmapid];
+      }
+      else
+      {
+        v58 = v40->uTileBitmapID;
+        v81 = 1;
+      }
+      pRenderer->DrawTerrainPolygon(v40->uNumVertices, v40, pBitmaps_LOD->pHardwareTextures[v58], 0, v81);
+    }
+LABEL_112:
+    v59 = &array_77EC08[pOutdoorCamera->numStru148s];
+    a8 = (RenderVertexSoft *)&array_77EC08[pOutdoorCamera->numStru148s];
+    v60 = pOutdoor->GetTileTexture(sX, sY);
+    v59->uTileBitmapID = v60;
+    if ( v60 == -1 )
+      goto LABEL_162;
+    *(int *)&v59->flags = pOutdoor->GetSomeOtherTileInfo(sX, sY);
+    v61 = v93;
+    v59->field_59 = 1;
+    v59->field_34 = v61->distance;
+    v59->field_5C = v89;
+    v59->field_5D = (char)_this;
+    v62 = *(unsigned __int16 *)((char *)pTerrainNormalIndices + v85);
+    if ( v62 > (signed int)(uNumTerrainNormals - 1) )
+      v63 = 0;
+    else
+      v63 = &pTerrainNormals[v62];
+    v64 = v92 * v63->z;
+    v99 = v63;
+    thish = 20.0 - (-v64 - v91 * v63->y - v90 * v63->x) * 20.0;
+    v65 = thish + 6.7553994e15;
+    v59->field_58 = LOBYTE(v65);
+    if ( SLOBYTE(v65) < 0 )
+      v59->field_58 = 0;
+    if ( pOutdoorCamera->numStru148s >= 1999 )
+      return;
+    ++pOutdoorCamera->numStru148s;
+    if ( !sub_481FC9(v101, a2, pVertices, v59) )
+    {
+LABEL_126:
+      --pOutdoorCamera->numStru148s;
+      goto LABEL_162;
+    }
+    v66 = 1.0 / (a2->vWorldViewPosition.x + 0.0000001);
+    memcpy(array_50AC10, a2, 0x30u);
+    array_50AC10[0].flt_20 = v66;
+    array_50AC10[0].u = 0.0;
+    array_50AC10[0].v = 0.0;
+    v67 = pVertices->vWorldViewPosition.x + 0.0000001;
+    memcpy(&array_50AC10[1], pVertices, sizeof(array_50AC10[1]));
+    array_50AC10[1].flt_20 = 1.0 / v67;
+    array_50AC10[1].u = 1.0;
+    array_50AC10[1].v = 1.0;
+    v68 = v101->vWorldViewPosition.x + 0.0000001;
+    memcpy(&array_50AC10[2], v101, sizeof(array_50AC10[2]));
+    array_50AC10[2].flt_20 = 1.0 / v68;
+    array_50AC10[2].u = 1.0;
+    array_50AC10[2].v = 0.0;
+
+    static stru154 static_sub_0048034E_stru_76D578;
+    /*static bool __init_flag1 = false;
+    if (!__init_flag1)
+    {
+      __init_flag1 = true;
+
+      stru154::stru154(&static_sub_0048034E_stru_76D578);
+    }*/
+
+    v96 = pGame->pLightmapBuilder;
+    pGame->pLightmapBuilder->StackLights_TerrainFace(v99, &v87, array_50AC10, 3u, 1);
+    pDecalBuilder->_49BE8A(v40, *(float *)&v99, (int)&v87, array_50AC10, 3u, 1);
+    v100 = 3;
+    if ( byte_4D864C && pGame->uFlags & 0x80 )
+    {
+      thisc = pGame->pIndoorCameraD3D;
+      if ( pGame->pIndoorCameraD3D->_4371C3(array_50AC10, (unsigned int *)&v100, 0) == 1 && !v100 )
+        goto LABEL_126;
+      thisc->ViewTransform(array_50AC10, v100);
+      thisc->Project(array_50AC10, v100, 0);
+    }
+    this_3b = a2->vWorldViewPosition.x < 8.0
+           || pVertices->vWorldViewPosition.x < 8.0
+           || v101->vWorldViewPosition.x < 8.0;
+    v69 = (double)pOutdoorCamera->shading_dist_mist;
+    v108 = v69 < a2->vWorldViewPosition.x || v69 < pVertices->vWorldViewPosition.x || v69 < v101->vWorldViewPosition.x;
+    LOBYTE(v70) = 0;
+    v96->std__vector_000004_size = 0;
+    if ( stru_F8AD28.uNumLightsApplied > 0 || pDecalBuilder->uNumDecals > 0 )
+    {
+      if ( this_3b )
+        LOBYTE(v70) = 3;
+      else
+        v70 = v108 != 0 ? 5 : 0;
+      static_sub_0048034E_stru_76D578._49B0C9(v99, v87);
+      if ( pDecalBuilder->uNumDecals > 0 )
+        pDecalBuilder->ApplyDecals(
+          31 - v40->field_58,
+          4,
+          &static_sub_0048034E_stru_76D578,
+          v100,
+          array_50AC10,
+          0,
+          v70,
+          -1);
+    }
+    if ( stru_F8AD28.uNumLightsApplied > 0 )
+      v96->ApplyLights(&stru_F8AD28, &static_sub_0048034E_stru_76D578, v100, array_50AC10, 0, v70);
+    v71 = a8;
+    v72 = v100;
+    v35 = byte_4D864C == 0;
+    LODWORD(a8->vWorldViewPosition.z) = v100;
+    if ( !v35 && pGame->uFlags & 0x80 )
+      goto LABEL_154;
+    if ( this_3b )
+    {
+      v73 = sr_424CD7(v72);
+    }
+    else
+    {
+      if ( !v108 )
+      {
+LABEL_154:
+        v74 = v71[1].vWorldPosition.x;
+        if ( !(BYTE1(v74) & 1) )
+        {
+          if ( LOBYTE(v74) & 2 && LOWORD(v71[1].vWorldViewProjY) == pRenderer->field_1036AC_bitmapid )
+          {
+            v80 = 0;
+            v75 = pRenderer->pHDWaterBitmapIDs[pRenderer->field_1036A8_bitmapid];
+          }
+          else
+          {
+            v75 = LOWORD(v71[1].vWorldViewProjY);
+            v80 = 1;
+          }
+          v79 = 0;
+          v78 = pBitmaps_LOD->pHardwareTextures[v75];
+          v77 = (stru148 *)v71;
+          v76 = LODWORD(v71->vWorldViewPosition.z);
+          goto LABEL_161;
+        }
+        v38 = (stru148 *)v71;
+        goto LABEL_56;
+      }
+      v73 = sr_424EE0_MakeFanFromTriangle(v72);
+    }
+    LODWORD(v71->vWorldViewPosition.z) = v73;
+    OutdoorCamera::Project(v73);
+    goto LABEL_154;
+  }
+}
+// 47F44B: using guessed type int __stdcall WorldPosToGridCellX(int);
+// 47F458: using guessed type int __stdcall WorldPosToGridCellZ(int);
+// 4D864C: using guessed type char byte_4D864C;
+// 76D5C0: using guessed type char static_sub_0048034E_byte_76D5C0__init_flag;
+
+
+
+//----- (00481212) --------------------------------------------------------
+void Render::DrawTerrainSW(int a1, int a2, int a3)
+{
+  int v3; // esi@1
+  int v4; // ecx@1
+  int v5; // ST10_4@1
+  int v6; // edi@1
+  int v7; // ebx@2
+  int v8; // eax@2
+  int v9; // eax@3
+  RenderVertexSoft *v10; // edi@3
+  RenderVertexSoft *v11; // ebx@4
+  RenderVertexSoft *v12; // ecx@4
+  float v13; // eax@6
+  int v14; // eax@6
+  double v15; // st7@6
+  double v16; // st7@6
+  stru148 *v17; // ebx@12
+  unsigned __int16 v18; // ax@12
+  int v19; // eax@13
+  float v20; // ecx@13
+  stru220 *v21; // eax@13
+  int v22; // eax@13
+  signed int v23; // eax@13
+  Vec3_float_ *v24; // eax@15
+  double v25; // st7@18
+  double v26; // st5@24
+  double v27; // st5@24
+  double v28; // st5@24
+  double v29; // st5@24
+  Game *v30; // eax@25
+  RenderVertexSoft *v31; // edi@29
+  double v32; // st7@31
+  int v33; // esi@35
+  RenderVertexSoft *v34; // edx@36
+  RenderVertexSoft *v35; // ecx@36
+  signed int v36; // eax@39
+  signed int v37; // esi@40
+  stru148 *v38; // ebx@43
+  unsigned __int16 v39; // ax@43
+  int v40; // eax@44
+  float v41; // ecx@44
+  stru220 *v42; // eax@44
+  int v43; // eax@44
+  int v44; // eax@44
+  signed int v45; // eax@44
+  Vec3_float_ *v46; // eax@46
+  double v47; // st7@49
+  double v48; // st5@57
+  double v49; // st5@57
+  double v50; // st5@57
+  Game *v51; // eax@58
+  RenderVertexSoft *v52; // edi@62
+  double v53; // st7@63
+  int v54; // esi@66
+  signed int v55; // eax@69
+  signed int v56; // esi@71
+  unsigned __int16 v57; // ax@75
+  stru220 *v58; // eax@76
+  signed int v59; // eax@76
+  Vec3_float_ *v60; // eax@77
+  double v61; // st7@80
+  double v62; // st5@88
+  double v63; // st5@88
+  double v64; // st5@88
+  Game *v65; // eax@89
+  double v66; // st7@94
+  RenderVertexSoft *v67; // [sp-Ch] [bp-C4h]@36
+  stru148 *v68; // [sp-8h] [bp-C0h]@36
+  int v69; // [sp-4h] [bp-BCh]@36
+  float v70; // [sp+Ch] [bp-ACh]@88
+  double v71; // [sp+10h] [bp-A8h]@6
+  double v72; // [sp+18h] [bp-A0h]@82
+  double v73; // [sp+20h] [bp-98h]@6
+  double v74; // [sp+28h] [bp-90h]@51
+  double v75; // [sp+30h] [bp-88h]@6
+  double v76; // [sp+38h] [bp-80h]@20
+  double v77; // [sp+40h] [bp-78h]@6
+  float v78; // [sp+48h] [bp-70h]@57
+  float v79; // [sp+4Ch] [bp-6Ch]@6
+  float v80; // [sp+50h] [bp-68h]@6
+  int v81; // [sp+54h] [bp-64h]@1
+  int v82; // [sp+58h] [bp-60h]@6
+  int v83; // [sp+5Ch] [bp-5Ch]@82
+  int v84; // [sp+60h] [bp-58h]@20
+  int v85; // [sp+64h] [bp-54h]@1
+  int v86; // [sp+68h] [bp-50h]@1
+  int v87; // [sp+6Ch] [bp-4Ch]@51
+  float v88; // [sp+70h] [bp-48h]@51
+  int v89; // [sp+74h] [bp-44h]@6
+  int v90; // [sp+78h] [bp-40h]@1
+  float a3a; // [sp+7Ch] [bp-3Ch]@24
+  stru220 *v92; // [sp+80h] [bp-38h]@2
+  float v93; // [sp+84h] [bp-34h]@44
+  int v94; // [sp+88h] [bp-30h]@6
+  float v95; // [sp+8Ch] [bp-2Ch]@1
+  float v96; // [sp+90h] [bp-28h]@1
+  float v97; // [sp+94h] [bp-24h]@1
+  int X; // [sp+98h] [bp-20h]@1
+  float v99; // [sp+9Ch] [bp-1Ch]@6
+  int v100; // [sp+A0h] [bp-18h]@6
+  unsigned __int64 v101; // [sp+A4h] [bp-14h]@6
+  RenderVertexSoft *v102; // [sp+ACh] [bp-Ch]@6
+  RenderVertexSoft *v103; // [sp+B0h] [bp-8h]@6
+  RenderVertexSoft *v104; // [sp+B4h] [bp-4h]@3
+  float pNormalc; // [sp+C0h] [bp+8h]@6
+  float pNormald; // [sp+C0h] [bp+8h]@6
+  Vec3_float_ *pNormal; // [sp+C0h] [bp+8h]@17
+  Vec3_float_ *pNormala; // [sp+C0h] [bp+8h]@48
+  Vec3_float_ *pNormalb; // [sp+C0h] [bp+8h]@77
+
+  v3 = a1;
+  //v4 = *(short *)(a3 + 4);
+  //v5 = *(short *)(a3 + 6);
+  v85 = a2;
+  v86 = *(_WORD *)(a3 + 4); //v4;
+  X = abs(*(_WORD *)(a3 + 6)); //v5
+  v6 = 0;
+  v90 = 0;
+  v81 = v3 - 1;
+  v95 = (double)pOutdoor->vSunlight.x * 0.000015258789;
+  v96 = (double)pOutdoor->vSunlight.y * 0.000015258789;
+  v97 = (double)pOutdoor->vSunlight.z * 0.000015258789;
+  if ( v3 - 1 > 0 )
+  {
+    while ( 1 )
+    {
+      v7 = abs(X);
+      v8 = abs(v86);
+      --X;
+      v92 = &stru_76E5C8[(v7 << 7) + v8];
+      if ( !v92->field_0
+        || ((v9 = v6, v10 = &pVerticesSR_806210[v6], v104 = v10, !v85) ? (v11 = &pVerticesSR_801A10[v9],
+                                                                          v12 = &pVerticesSR_806210[v9 + 1]) : (v11 = &pVerticesSR_806210[v9 + 1], v12 = &pVerticesSR_801A10[v9]),
+            ((v103 = &pVerticesSR_801A10[v9 + 1],
+              v13 = v10->vWorldPosition.x,
+              v102 = v12,
+              v80 = v13,
+              v73 = v13 + 6.7553994e15,
+              v101 = __PAIR__((unsigned int)v11, LODWORD(v73)),
+              v79 = v10->vWorldPosition.y,
+              v75 = v79 + 6.7553994e15,
+              v100 = LODWORD(v75),
+              pNormalc = (v12->vWorldPosition.x + v10->vWorldPosition.x) * 0.5,
+              v71 = pNormalc + 6.7553994e15,
+              v89 = LODWORD(v71),
+              v14 = WorldPosToGridCellX(COERCE_UNSIGNED_INT64(pNormalc + 6.7553994e15)),
+              v15 = v11->vWorldPosition.y + v10->vWorldPosition.y,
+              v94 = v14,
+              pNormald = v15 * 0.5,
+              v16 = pNormald + 6.7553994e15,
+              v77 = v16,
+              v82 = LODWORD(v77),
+              LODWORD(v99) = WorldPosToGridCellZ(LODWORD(v16)),
+              WorldPosToGridCellX(v101),
+              WorldPosToGridCellZ(v100),
+              !byte_4D864C)
+          || !(pGame->uFlags & 0x80))
+         && !sub_481EFA(v10, v11, v102, v103, 1)) )
+        goto LABEL_105;
+      if ( v10->vWorldPosition.z != v11->vWorldPosition.z
+        || v11->vWorldPosition.z != v103->vWorldPosition.z
+        || v103->vWorldPosition.z != v102->vWorldPosition.z )
+        break;
+      v17 = &array_77EC08[pOutdoorCamera->numStru148s];
+      v18 = pOutdoor->GetTileTexture(v101, v100);
+      v17->uTileBitmapID = v18;
+      if ( v18 != -1 )
+      {
+        v19 = pOutdoor->GetSomeOtherTileInfo(v101, v100);
+        LOWORD(v19) = v19 | 0x8010;
+        v20 = v99;
+        *(int *)&v17->flags = v19;
+        v21 = v92;
+        v17->field_59 = 1;
+        v17->field_5D = LOBYTE(v20);
+        v17->field_34 = v21->distance;
+        v22 = v94;
+        v17->field_5C = v94;
+        v23 = pTerrainNormalIndices[2 * (LODWORD(v20) + (v22 << 7)) + 1];
+        if ( v23 < 0 || v23 > (signed int)(uNumTerrainNormals - 1) )
+          v24 = 0;
+        else
+          v24 = &pTerrainNormals[v23];
+        pNormal = v24;
+        if ( v24 )
+        {
+          v25 = -(v97 * v24->z + v96 * v24->y + v95 * v24->x);
+          if ( v25 < 0.0 )
+            v25 = 0.0;
+          v99 = v25 * 31.0;
+          v76 = v99 + 6.7553994e15;
+          v84 = LODWORD(v76);
+          v17->field_58 = 31 - LOBYTE(v76);
+        }
+        else
+        {
+          v17->field_58 = 0;
+        }
+        if ( pOutdoorCamera->numStru148s >= 1999 )
+          return;
+        ++pOutdoorCamera->numStru148s;
+        if ( !sub_481FC9(v10, (RenderVertexSoft *)HIDWORD(v101), v102, v17) )
+          goto LABEL_104;
+        v26 = 1.0 / (v104->vWorldViewPosition.x + 0.0000001);
+        memcpy(array_50AC10, v104, 0x30u);
+        array_50AC10[0].flt_20 = v26;
+        array_50AC10[0].u = 0.0;
+        array_50AC10[0].v = 0.0;
+        v27 = *(float *)(HIDWORD(v101) + 12) + 0.0000001;
+        memcpy(&array_50AC10[1], (void *)HIDWORD(v101), sizeof(array_50AC10[1]));
+        array_50AC10[1].flt_20 = 1.0 / v27;
+        array_50AC10[1].u = 0.0;
+        array_50AC10[1].v = 1.0;
+        v28 = v103->vWorldViewPosition.x + 0.0000001;
+        memcpy(&array_50AC10[2], v103, sizeof(array_50AC10[2]));
+        array_50AC10[2].flt_20 = 1.0 / v28;
+        array_50AC10[2].u = 1.0;
+        array_50AC10[2].v = 1.0;
+        v29 = v102->vWorldViewPosition.x + 0.0000001;
+        memcpy(&array_50AC10[3], v102, sizeof(array_50AC10[3]));
+        array_50AC10[3].flt_20 = 1.0 / v29;
+        array_50AC10[3].u = 1.0;
+        array_50AC10[3].v = 0.0;
+        pGame->pLightmapBuilder->StackLights_TerrainFace(pNormal, &a3a, array_50AC10, 4u, 1);
+        if ( stru_F8AD28.uNumLightsApplied <= 0 )
+        {
+          v17->field_108 = 0;
+        }
+        else
+        {
+          v30 = pGame;
+          v17->field_108 = 1;
+          pGame->pLightmapBuilder->_45CA88(&stru_F8AD28, array_50AC10, 4, pNormal);
+        }
+        if ( v104->vWorldViewPosition.x < 8.0
+          || *(float *)(HIDWORD(v101) + 12) < 8.0
+          || (v31 = v102, v102->vWorldViewPosition.x < 8.0)
+          || v103->vWorldViewPosition.x < 8.0 )
+        {
+          v36 = sr_4250FE(4u);
+        }
+        else
+        {
+          v32 = (double)pOutdoorCamera->shading_dist_mist;
+          if ( v32 >= v104->vWorldViewPosition.x
+            && v32 >= *(float *)(HIDWORD(v101) + 12)
+            && v32 >= v102->vWorldViewPosition.x
+            && v32 >= v103->vWorldViewPosition.x )
+          {
+            v33 = sr_4254D2(4);
+            v17->uNumVertices = v33;
+            if ( !v33 )
+              goto LABEL_104;
+            v34 = (RenderVertexSoft *)HIDWORD(v101);
+            v35 = v104;
+            v69 = 0;
+            v68 = v17;
+            v67 = v31;
+            goto LABEL_37;
+          }
+          v36 = sr_4252E8(4u);
+        }
+        v37 = v36;
+        if ( !v36 )
+          goto LABEL_104;
+LABEL_41:
+        OutdoorCamera::Project(v37);
+LABEL_102:
+        v33 = sr_4254D2(v37);
+        v17->uNumVertices = v33;
+        if ( !v33 )
+          goto LABEL_104;
+        v17->_48276F_sr();
+        goto LABEL_38;
+      }
+LABEL_105:
+      v6 = v90++ + 1;
+      if ( v90 >= v81 )
+        return;
+    }
+    v38 = &array_77EC08[pOutdoorCamera->numStru148s];
+    v39 = pOutdoor->GetTileTexture(v101, v100);
+    v38->uTileBitmapID = v39;
+    if ( v39 == -1 )
+      goto LABEL_105;
+    v40 = pOutdoor->GetSomeOtherTileInfo(v101, v100);
+    BYTE1(v40) |= 0x80u;
+    v41 = v99;
+    *(int *)&v38->flags = v40;
+    v42 = v92;
+    v38->field_59 = 1;
+    v38->field_5D = LOBYTE(v41);
+    v38->field_34 = v42->distance;
+    v43 = v94;
+    v38->field_5C = v94;
+    v44 = 2 * (LODWORD(v41) + (v43 << 7));
+    LODWORD(v93) = v44 * 2;
+    v45 = pTerrainNormalIndices[v44 + 1];
+    if ( v45 < 0 || v45 > (signed int)(uNumTerrainNormals - 1) )
+      v46 = 0;
+    else
+      v46 = &pTerrainNormals[v45];
+    pNormala = v46;
+    if ( v46 )
+    {
+      v47 = -(v97 * v46->z + v96 * v46->y + v95 * v46->x);
+      if ( v47 < 0.0 )
+        v47 = 0.0;
+      v88 = v47 * 31.0;
+      v74 = v88 + 6.7553994e15;
+      v87 = LODWORD(v74);
+      v38->field_58 = 31 - LOBYTE(v74);
+    }
+    else
+    {
+      v38->field_58 = 0;
+    }
+    if ( v38->field_58 < 0 )
+      v38->field_58 = 0;
+    if ( pOutdoorCamera->numStru148s >= 1999 )
+      return;
+    ++pOutdoorCamera->numStru148s;
+    if ( !sub_481FC9((RenderVertexSoft *)HIDWORD(v101), v103, v104, v38) )
+      goto LABEL_74;
+    v48 = 1.0 / (v104->vWorldViewPosition.x + 0.0000001);
+    memcpy(array_50AC10, v104, 0x30u);
+    array_50AC10[0].flt_20 = v48;
+    array_50AC10[0].u = 0.0;
+    array_50AC10[0].v = 0.0;
+    v49 = *(float *)(HIDWORD(v101) + 12) + 0.0000001;
+    memcpy(&array_50AC10[1], (void *)HIDWORD(v101), sizeof(array_50AC10[1]));
+    array_50AC10[1].flt_20 = 1.0 / v49;
+    array_50AC10[1].u = 0.0;
+    array_50AC10[1].v = 1.0;
+    v50 = v103->vWorldViewPosition.x + 0.0000001;
+    memcpy(&array_50AC10[2], v103, sizeof(array_50AC10[2]));
+    array_50AC10[2].flt_20 = 1.0 / v50;
+    array_50AC10[2].u = 1.0;
+    array_50AC10[2].v = 1.0;
+    pGame->pLightmapBuilder->StackLights_TerrainFace(pNormala, &v78, array_50AC10, 3u, 0);
+    if ( stru_F8AD28.uNumLightsApplied <= 0 )
+    {
+      v38->field_108 = 0;
+    }
+    else
+    {
+      v51 = pGame;
+      v38->field_108 = 1;
+      pGame->pLightmapBuilder->_45CA88(&stru_F8AD28, array_50AC10, 3, pNormala);
+    }
+    if ( v104->vWorldViewPosition.x < 8.0
+      || *(float *)(HIDWORD(v101) + 12) < 8.0
+      || (v52 = v103, v103->vWorldViewPosition.x < 8.0) )
+    {
+      v55 = sr_4250FE(3u);
+    }
+    else
+    {
+      v53 = (double)pOutdoorCamera->shading_dist_mist;
+      if ( v53 >= v104->vWorldViewPosition.x
+        && v53 >= *(float *)(HIDWORD(v101) + 12)
+        && v53 >= v103->vWorldViewPosition.x )
+      {
+        v54 = sr_4254D2(3);
+        v38->uNumVertices = v54;
+        if ( v54 )
+        {
+          sr_sub_4829B9((RenderVertexSoft *)HIDWORD(v101), v52, v104, v38, 0);
+LABEL_68:
+          sr_sub_481DB2(array_508690, v54, v38);
+LABEL_75:
+          v17 = &array_77EC08[pOutdoorCamera->numStru148s];
+          v57 = pOutdoor->GetTileTexture(v101, v100);
+          v17->uTileBitmapID = v57;
+          if ( v57 == -1 )
+            goto LABEL_105;
+          *(int *)&v17->flags = pOutdoor->GetSomeOtherTileInfo(v101, v100);
+          v58 = v92;
+          v17->field_59 = 1;
+          v17->field_34 = v58->distance;
+          v17->field_5C = v94;
+          v17->field_5D = LOBYTE(v99);
+          v59 = *(unsigned __int16 *)((char *)pTerrainNormalIndices + LODWORD(v93));
+          if ( v59 > (signed int)(uNumTerrainNormals - 1) )
+          {
+            pNormalb = 0;
+            v60 = 0;
+          }
+          else
+          {
+            v60 = &pTerrainNormals[v59];
+            pNormalb = v60;
+          }
+          if ( v60 )
+          {
+            v61 = -(v97 * v60->z + v96 * v60->y + v95 * v60->x);
+            if ( v61 < 0.0 )
+              v61 = 0.0;
+            v93 = v61 * 31.0;
+            v72 = v93 + 6.7553994e15;
+            v83 = LODWORD(v72);
+            v17->field_58 = 31 - LOBYTE(v72);
+          }
+          else
+          {
+            v17->field_58 = 0;
+          }
+          if ( v17->field_58 < 0 )
+            v17->field_58 = 0;
+          if ( pOutdoorCamera->numStru148s >= 1999 )
+            return;
+          ++pOutdoorCamera->numStru148s;
+          if ( !sub_481FC9(v102, v104, v103, v17) )
+          {
+LABEL_104:
+            --pOutdoorCamera->numStru148s;
+            goto LABEL_105;
+          }
+          v62 = 1.0 / (v104->vWorldViewPosition.x + 0.0000001);
+          memcpy(array_50AC10, v104, 0x30u);
+          array_50AC10[0].flt_20 = v62;
+          array_50AC10[0].u = 0.0;
+          array_50AC10[0].v = 0.0;
+          v63 = v103->vWorldViewPosition.x + 0.0000001;
+          memcpy(&array_50AC10[1], v103, sizeof(array_50AC10[1]));
+          array_50AC10[1].flt_20 = 1.0 / v63;
+          array_50AC10[1].u = 1.0;
+          array_50AC10[1].v = 1.0;
+          v64 = v102->vWorldViewPosition.x + 0.0000001;
+          memcpy(&array_50AC10[2], v102, sizeof(array_50AC10[2]));
+          array_50AC10[2].flt_20 = 1.0 / v64;
+          array_50AC10[2].u = 1.0;
+          array_50AC10[2].v = 0.0;
+          pGame->pLightmapBuilder->StackLights_TerrainFace(pNormalb, &v70, array_50AC10, 3u, 1);
+          if ( stru_F8AD28.uNumLightsApplied <= 0 )
+          {
+            v17->field_108 = 0;
+          }
+          else
+          {
+            v65 = pGame;
+            v17->field_108 = 1;
+            pGame->pLightmapBuilder->_45CA88(&stru_F8AD28, array_50AC10, 3, pNormalb);
+          }
+          if ( v104->vWorldViewPosition.x < 8.0 || v103->vWorldViewPosition.x < 8.0 || v102->vWorldViewPosition.x < 8.0 )
+          {
+            v37 = sr_4250FE(3u);
+            OutdoorCamera::Project(v37);
+            if ( !v37 )
+              goto LABEL_104;
+            goto LABEL_102;
+          }
+          v66 = (double)pOutdoorCamera->shading_dist_mist;
+          if ( v66 < v104->vWorldViewPosition.x || v66 < v103->vWorldViewPosition.x || v66 < v102->vWorldViewPosition.x )
+          {
+            v37 = sr_4252E8(3u);
+            if ( !v37 )
+              goto LABEL_105;
+            goto LABEL_41;
+          }
+          v33 = sr_4254D2(3);
+          v17->uNumVertices = v33;
+          if ( !v33 )
+            goto LABEL_104;
+          v34 = v104;
+          v35 = v102;
+          v69 = 0;
+          v68 = v17;
+          v67 = v103;
+LABEL_37:
+          sr_sub_4829B9(v35, v34, v67, v68, v69);
+LABEL_38:
+          sr_sub_481DB2(array_508690, v33, v17);
+          goto LABEL_105;
+        }
+        goto LABEL_74;
+      }
+      v55 = sr_4252E8(3u);
+    }
+    v56 = v55;
+    if ( v55 )
+    {
+      OutdoorCamera::Project(v55);
+      v54 = sr_4254D2(v56);
+      v38->uNumVertices = v54;
+      if ( v54 )
+      {
+        v38->_48276F_sr();
+        goto LABEL_68;
+      }
+    }
+LABEL_74:
+    --pOutdoorCamera->numStru148s;
+    goto LABEL_75;
+  }
+}
+// 47F44B: using guessed type int __stdcall WorldPosToGridCellX(int);
+// 47F458: using guessed type int __stdcall WorldPosToGridCellZ(int);
+// 4D864C: using guessed type char byte_4D864C;
+
+
+//----- (0047BACF) --------------------------------------------------------
+void Render::TransformBillboardsAndSetPalettesODM()
+{
+  int v0; // edi@1
+  char *v1; // esi@2
+  unsigned int v2; // edx@3
+  int v3; // eax@3
+  int v4; // edi@3
+  int v5; // eax@3
+  __int16 v6; // di@3
+  int v7; // eax@3
+  int v8; // ebx@4
+  unsigned __int16 *v9; // eax@7
+  char v10; // zf@9
+  DWORD v11; // eax@13
+  int v12; // eax@13
+  int v13; // eax@14
+  RenderBillboardTransform_local0 billboard; // [sp+4h] [bp-60h]@1
+  int v15; // [sp+54h] [bp-10h]@13
+  int v16; // [sp+58h] [bp-Ch]@1
+  int v17; // [sp+5Ch] [bp-8h]@2
+  int v18; // [sp+60h] [bp-4h]@13
+
+  billboard.uParentBillboardID = -1;
+  billboard.pTarget = pRenderer->pTargetSurface;
+  billboard.pTargetZ = pRenderer->pActiveZBuffer;
+  billboard.uTargetPitch = pRenderer->uTargetSurfacePitch;
+  billboard.uViewportX = pViewport->uViewportX;
+  billboard.uViewportY = pViewport->uViewportY;
+  billboard.uViewportZ = pViewport->uViewportZ - 1;
+  billboard.uViewportW = pViewport->uViewportW;
+  v0 = 0;
+  pOutdoorCamera->uNumBillboards = uNumBillboardsToDraw;
+  v16 = 0;
+  if ( (signed int)uNumBillboardsToDraw > 0 )
+  {
+    v17 = 0;
+    v1 = (char *)&pBillboardRenderList[0].uScreenSpaceY;
+    do
+    {
+      billboard.uScreenSpaceX = *((short *)v1 - 1);
+      v2 = *((short *)v1 - 5);
+      billboard.uScreenSpaceY = *(short *)v1;
+      v3 = *((int *)v1 - 10);
+      billboard.uParentBillboardID = v0;
+      v4 = *((int *)v1 + 1);
+      billboard.field_10 = v3;
+      v5 = *((int *)v1 - 9);
+      billboard.uTintColor = v4;
+      v6 = *((short *)v1 - 8);
+      billboard.field_14 = v5;
+      v7 = *((int *)v1 - 6);
+      billboard.sZValue = *((int *)v1 - 6);
+      billboard.uFlags = v2;
+      if ( v6 != -1 )
+      {
+        v8 = *((short *)v1 + 1);
+        if ( pRenderer->pRenderD3D )
+        {
+          billboard.sZValue = v7;
+          billboard.uFlags = v2;
+          pRenderer->TransformBillboard(
+            &billboard,
+            &pSprites_LOD->pHardwareSprites[v6],
+            v8,
+            (RenderBillboard *)(v1 - 40));
+        }
+        else
+        {
+          if ( *(v1 - 10) & 2 )
+            v9 = PaletteManager::Get_Dark_or_Red_LUT(*((short *)v1 - 7), 0, 1);
+          else
+            v9 = GetBillboardPalette((RenderBillboard *)(v1 - 40), *((short *)v1 - 7), v7, *((short *)v1 + 1));
+          v10 = (*(v1 - 9) & 1) == 0;
+          billboard.pPalette = v9;
+          if ( !v10 )
+            billboard.pPalette = pPaletteManager->field_261600[*((short *)v1 - 7)];
+          if ( !(billboard.uFlags & 0x40) && billboard.uFlags & 0x80 )
+          {
+            v11 = GetTickCount();
+            v12 = stru_5C6E00->SinCos(v17 + v11);
+            v15 = abs(v12);
+            v18 = (unsigned __int64)(15i64 * v15) >> 16;
+            billboard.pPalette2 = PaletteManager::Get_Dark_or_Red_LUT(*((short *)v1 - 7), 15 - v18, 1);
+          }
+          v13 = *((short *)v1 - 8);
+          if ( v13 >= 0 )
+            pSprites_LOD->pSpriteHeaders[v13]._4ACC38(&billboard, 1);
+        }
+      }
+      v17 += 5;
+      v0 = v16 + 1;
+      v1 += 52;
+      ++v16;
+    }
+    while ( v16 < (signed int)uNumBillboardsToDraw );
+  }
+}
+
+
+//----- (0047AF11) --------------------------------------------------------
+void Render::DrawLayingItems_Shooting_Magic_ODM()
+{
+  char *v0; // edi@2
+  ObjectDesc *v1; // ebx@4
+  __int16 v2; // cx@5
+  RenderBillboard *v3; // esi@10
+  SpriteFrame *v4; // eax@10
+  SpriteFrame *v5; // ebx@10
+  unsigned int v6; // eax@10
+  int v7; // ecx@10
+  int v8; // edx@10
+  int v9; // ecx@10
+  unsigned __int16 v10; // ax@10
+  int *v11; // eax@14
+  int v12; // eax@22
+  int v13; // ST3C_4@23
+  int v14; // eax@23
+  int v15; // ecx@23
+  int v16; // ebx@23
+  int v17; // ecx@25
+  int v18; // eax@25
+  int v19; // ST40_4@26
+  int v20; // ecx@26
+  int v21; // ST44_4@28
+  int v22; // ST3C_4@29
+  signed __int64 v23; // qtt@30
+  int v24; // ebx@30
+  int v25; // ST3C_4@30
+  int v26; // eax@31
+  char v27; // zf@31
+  SpriteFrame *v28; // [sp+Ch] [bp-34h]@10
+  __int16 a5; // [sp+10h] [bp-30h]@10
+  int v30; // [sp+14h] [bp-2Ch]@23
+  int v31; // [sp+14h] [bp-2Ch]@29
+  __int16 v32; // [sp+14h] [bp-2Ch]@30
+  int v33; // [sp+18h] [bp-28h]@23
+  int v34; // [sp+18h] [bp-28h]@26
+  int v35; // [sp+18h] [bp-28h]@30
+  int v36; // [sp+1Ch] [bp-24h]@10
+  int v37; // [sp+1Ch] [bp-24h]@23
+  int a6; // [sp+20h] [bp-20h]@10
+  int a6a; // [sp+20h] [bp-20h]@23
+  int v40; // [sp+24h] [bp-1Ch]@25
+  signed int v41; // [sp+28h] [bp-18h]@1
+  int v42; // [sp+2Ch] [bp-14h]@23
+  int y; // [sp+30h] [bp-10h]@10
+  int x; // [sp+34h] [bp-Ch]@10
+  int z; // [sp+38h] [bp-8h]@10
+  signed __int16 v46; // [sp+3Ch] [bp-4h]@12
+
+  v41 = 0;
+  if ( (signed int)uNumLayingItems > 0 )
+  {
+    v0 = (char *)&pLayingItems[0].uSectorID;
+    do
+    {
+      if ( *((short *)v0 - 13) )
+      {
+        v1 = &pObjectList->pObjects[*((short *)v0 - 13)];
+        if ( !(v1->uFlags & 1) )
+        {
+          if ( ((v2 = *((short *)v0 - 14), v2 < 1000) || v2 >= 10000) && (v2 < 500 || v2 >= 600)
+            || pGame->pStru6Instance->_4A81CA((LayingItem *)(v0 - 28)) )
+          {
+            a5 = *(short *)v0;
+            x = *((int *)v0 - 6);
+            y = *((int *)v0 - 5);
+            z = *((int *)v0 - 4);
+            v3 = &pBillboardRenderList[uNumBillboardsToDraw];
+            v4 = pSpriteFrameTable->GetFrame(v1->uSpriteID, *((short *)v0 + 1));
+            v5 = v4;
+            v28 = v4;
+            v36 = v4->uFlags;
+            a6 = v4->uGlowRadius * *((short *)v0 + 3);
+            v6 = stru_5C6E00->Atan2(
+                   *((int *)v0 - 6) - pIndoorCamera->pos.x,
+                   *((int *)v0 - 5) - pIndoorCamera->pos.y);
+            LOWORD(v7) = *((short *)v0 - 3);
+            v8 = v36;
+            v9 = ((signed int)(stru_5C6E00->uIntegerPi + ((signed int)stru_5C6E00->uIntegerPi >> 3) + v7 - v6) >> 8) & 7;
+            v10 = v5->pHwSpriteIDs[v9];
+            v3->uHwSpriteID = v10;
+            if ( v36 & 0x20 )
+            {
+              v8 = v36;
+              z -= (signed int)((unsigned __int64)(v5->scale
+                                                 * (signed __int64)pSprites_LOD->pSpriteHeaders[(signed __int16)v10].uHeight) >> 16) >> 1;
+            }
+            v46 = 0;
+            if ( v8 & 2 )
+              v46 = 2;
+            v11 = (int *)(256 << v9);
+            if ( (256 << v9) & v8 )
+              v46 |= 4u;
+            if ( v8 & 0x40000 )
+              v46 |= 0x40u;
+            if ( v8 & 0x20000 )
+              LOBYTE(v46) = v46 | 0x80;
+            if ( a6 )
+            {
+              LOBYTE(v11) = byte_4E94D3;
+              pMobileLightsStack->AddLight(x, y, z, a5, a6, 0xFFu, 0xFFu, 0xFFu, byte_4E94D3);
+            }
+            v12 = (x - pIndoorCamera->pos.x) << 16;
+            if ( pIndoorCamera->sRotationX )
+            {
+              v13 = (y - pIndoorCamera->pos.y) << 16;
+              v30 = ((unsigned __int64)(v12 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16)
+                  + ((unsigned __int64)(v13 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
+              v37 = (unsigned __int64)(v12 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+              a6a = (unsigned __int64)(v13 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
+              v33 = (z - pIndoorCamera->pos.z) << 16;
+              v14 = (unsigned __int64)(v30 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16;
+              v15 = (unsigned __int64)(v33 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16;
+              v16 = v15 + v14;
+              v42 = v15 + v14;
+              if ( v15 + v14 >= 262144 && v16 <= pOutdoorCamera->shading_dist_mist << 16 )
+              {
+                v17 = a6a - v37;
+                v40 = a6a - v37;
+                v18 = ((unsigned __int64)(v33 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16)
+                    - ((unsigned __int64)(v30 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
+                goto LABEL_29;
+              }
+            }
+            else
+            {
+              v34 = (y - pIndoorCamera->pos.y) << 16;
+              v19 = (unsigned __int64)(v12 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
+              v20 = (unsigned __int64)(v34 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+              v16 = v20 + v19;
+              v42 = v20 + v19;
+              if ( v20 + v19 >= 262144 && v16 <= pOutdoorCamera->shading_dist_mist << 16 )
+              {
+                v21 = (unsigned __int64)(((x - pIndoorCamera->pos.x) << 16)
+                                       * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+                v17 = ((unsigned __int64)(v34 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16)
+                    - v21;
+                v40 = ((unsigned __int64)(v34 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16)
+                    - v21;
+                v18 = (z - pIndoorCamera->pos.z) << 16;
+LABEL_29:
+                v31 = v18;
+                v22 = abs(v17);
+                if ( abs(v16) >= v22 )
+                {
+                  LODWORD(v23) = 0;
+                  HIDWORD(v23) = SLOWORD(pOutdoorCamera->int_fov_rad);
+                  v24 = v23 / v42;
+                  v25 = v23 / v42;
+                  LODWORD(v23) = 0;
+                  HIDWORD(v23) = SLOWORD(pOutdoorCamera->int_fov_rad);
+                  v35 = pViewport->uScreenCenterX
+                      - ((signed int)(((unsigned __int64)(v25 * (signed __int64)v40) >> 16) + 32768) >> 16);
+                  v32 = LOWORD(pViewport->uScreenCenterY)
+                      - (((unsigned int)((unsigned __int64)(v23 / v42 * v31) >> 16) + 32768) >> 16);
+                  if ( (signed int)uNumBillboardsToDraw >= 500 )
+                    return;
+                  ++uNumBillboardsToDraw;
+                  ++uNumSpritesDrawnThisFrame;
+                  *(v0 - 2) |= 1u;
+                  v3->uPalette = v28->uPaletteIndex;
+                  v3->uIndoorSectorID = a5;
+                  v3->field_0 = (unsigned __int64)(v28->scale * (signed __int64)v24) >> 16;
+                  v26 = (unsigned __int64)(v28->scale * (signed __int64)v24) >> 16;
+                  v3->pSpriteFrame = v28;
+                  v3->field_4 = v26;
+                  v3->field_1E = v46;
+                  v3->some_x = x;
+                  v3->some_y = y;
+                  v3->some_z = z;
+                  v3->uScreenSpaceX = v35;
+                  v3->uScreenSpaceY = v32;
+                  HIWORD(v26) = HIWORD(v42);
+                  LOWORD(v26) = 0;
+                  v27 = (*(v0 - 2) & 0x20) == 0;
+                  v3->sZValue = v26 + (8 * v41 | 2);
+                  v3->uPaletteSubindex = 0;
+                  v3->uTintColor = 0;
+                  if ( !v27 )
+                  {
+                    if ( !pRenderer->pRenderD3D )
+                      v3->sZValue = 0;
+                  }
+                }
+                goto LABEL_34;
+              }
+            }
+          }
+        }
+      }
+LABEL_34:
+      ++v41;
+      v0 += 112;
+    }
+    while ( v41 < (signed int)uNumLayingItems );
+  }
+}
+// 4E94D3: using guessed type char byte_4E94D3;
+// 5187E4: using guessed type int uNumSpritesDrawnThisFrame;
+
+
+//----- (0049D9BC) --------------------------------------------------------
+signed int __stdcall RenderD3D__DeviceEnumerator(GUID *lpGUID, const char *lpDevDesc, const char *lpDriverName, RenderD3D__DevInfo *pOut)
+{
+  size_t v4; // eax@1
+  size_t v5; // eax@1
+  IUnknown *v6; // eax@10
+  size_t v7; // eax@13
+  DDDEVICEIDENTIFIER ddDevId; // [sp+4h] [bp-4F8h]@11
+  DDSURFACEDESC2 v10;/*int v10; // [sp+42Ch] [bp-D0h]@16
+  int v11; // [sp+430h] [bp-CCh]@16
+  int v12; // [sp+434h] [bp-C8h]@16
+  int v13; // [sp+438h] [bp-C4h]@16
+  int v14; // [sp+474h] [bp-88h]@16*/
+  DDSCAPS2 ddsCaps; // [sp+4A8h] [bp-54h]@14
+  unsigned int uFreeVideoMem; // [sp+4B8h] [bp-44h]@14
+  RenderD3D_aux aux; // [sp+4BCh] [bp-40h]@19
+  IDirect3D3 *pDirect3D3; // [sp+4C4h] [bp-38h]@18
+  int v19; // [sp+4C8h] [bp-34h]@16
+  RenderD3D_D3DDevDesc v20; // [sp+4CCh] [bp-30h]@1
+  LPDIRECTDRAW pDirectDraw; // [sp+4F4h] [bp-8h]@4
+  IDirectDraw4 *pDirectDraw4; // [sp+4F8h] [bp-4h]@7
+
+  v4 = strlen(lpDriverName);
+  v20.pDriverName = new char[v4 + 1];
+  v5 = strlen(lpDevDesc);
+  v20.pDeviceDesc = new char[v5 + 1];
+  strcpy(v20.pDriverName, lpDriverName);
+  strcpy(v20.pDeviceDesc, lpDevDesc);
+  if ( lpGUID )
+  {
+    v20.pGUID = new GUID;
+    memcpy(v20.pGUID, lpGUID, 0x10u);
+  }
+  else
+  {
+    v20.pGUID = 0;
+  }
+
+  if (FAILED(DirectDrawCreate(v20.pGUID, &pDirectDraw, 0)))
+  {
+    delete [] v20.pDriverName;
+    delete [] v20.pDeviceDesc;
+    if ( v20.pGUID )
+      delete v20.pGUID;
+  }
+  else
+  {
+    if (FAILED(pDirectDraw->QueryInterface(IID_IDirectDraw4, (LPVOID *)&pDirectDraw4)))
+    {
+      delete [] v20.pDriverName;
+      delete [] v20.pDeviceDesc;
+      if ( v20.pGUID )
+        delete v20.pGUID;
+      v6 = (IUnknown *)pDirectDraw;
+    }
+    else
+    {
+      pDirectDraw->Release();
+      if (FAILED( pDirectDraw4->GetDeviceIdentifier(&ddDevId, 1u)))
+      {
+        v20.pDDraw4DevDesc = 0;
+      }
+      else
+      {
+        v7 = strlen(ddDevId.szDescription);
+        v20.pDDraw4DevDesc = new char[v7 + 1];
+        strcpy(v20.pDDraw4DevDesc, ddDevId.szDescription);
+      }
+      memset(&ddsCaps, 0, 0x10u);
+      if (FAILED(pDirectDraw4->GetAvailableVidMem(
+             &ddsCaps,
+             (LPDWORD)&v20.uVideoMem,
+             (LPDWORD)&uFreeVideoMem)))
+        v20.uVideoMem = 0;
+      memset(&v10, 0, 0x7Cu);
+      v10.dwSize = 124;
+      v10.dwFlags = 6;
+      v10.dwHeight = 640;
+      v10.dwWidth = 480;
+      v10.ddpfPixelFormat.dwSize = 32;
+
+      v19 = 0;
+      if ( FAILED(pDirectDraw4->EnumDisplayModes(
+             0,
+             0,
+             &v19,
+             (LPDDENUMMODESCALLBACK2)DDrawDisplayModesEnumerator))
+        || !v19
+        || FAILED(pDirectDraw4->QueryInterface(IID_IDirect3D3, (LPVOID *)&pDirect3D3)))
+      {
+        delete [] v20.pDriverName;
+        delete [] v20.pDeviceDesc;
+        if ( v20.pDDraw4DevDesc )
+          free(v20.pDDraw4DevDesc);
+        if ( v20.pGUID )
+          delete v20.pGUID;
+        v6 = (IUnknown *)pDirectDraw4;
+      }
+      else
+      {
+        aux.pInfo = pOut;
+        aux.ptr_4 = &v20;
+        pDirect3D3->EnumDevices((LPD3DENUMDEVICESCALLBACK)D3DDeviceEnumerator, &aux);
+        delete [] v20.pDriverName;
+        delete [] v20.pDeviceDesc;
+        if ( v20.pDDraw4DevDesc )
+          free(v20.pDDraw4DevDesc);
+        if ( v20.pGUID )
+          delete v20.pGUID;
+        pDirectDraw4->Release();
+        v6 = (IUnknown *)pDirect3D3;
+        pDirectDraw4 = 0;
+      }
+    }
+    v6->Release();
+  }
+  return 1;
+}
+
+
+//----- (0049D784) --------------------------------------------------------
+HRESULT __stdcall D3DDeviceEnumerator(const GUID *lpGUID, const char *lpDeviceDesc, const char *lpDeviceName, D3DDEVICEDESC *pHWDesc, D3DDEVICEDESC *pSWDesc, RenderD3D_aux *a6)
+{
+  int v6; // eax@1
+  signed int v7; // edi@1
+  signed int v8; // edi@14
+  size_t v9; // eax@30
+  size_t v10; // eax@30
+  size_t v11; // eax@30
+  size_t v12; // eax@30
+  size_t v13; // eax@30
+
+  v6 = pHWDesc->dwFlags;
+  v7 = -1;
+  if ( v6 )
+  {
+    if ( !a6->ptr_4->pGUID )
+      v7 = 0;
+    if ( v6 && a6->ptr_4->pGUID )
+      v7 = 1;
+  }
+  if ( !strcmp(lpDeviceName, "RGB Emulation") && !a6->ptr_4->pGUID )
+    v7 = 2;
+  if ( !strcmp(lpDeviceName, "Reference Rasterizer") && !a6->ptr_4->pGUID )
+    v7 = 3;
+  if ( v7 != -1 )
+  {
+    v8 = v7;
+    a6->pInfo[v8].bIsDeviceCompatible = 1;
+    a6->pInfo[v8].uCaps = 0;
+    if ( !(pHWDesc->dpcTriCaps.dwSrcBlendCaps & 0x10) )
+      a6->pInfo[v8].uCaps |= 2u;
+    if ( !(pHWDesc->dpcTriCaps.dwSrcBlendCaps & 2) )
+      a6->pInfo[v8].uCaps |= 4u;
+    if ( !(pHWDesc->dpcTriCaps.dwSrcBlendCaps & 1) )
+      a6->pInfo[v8].uCaps |= 8u;
+    if ( !(pHWDesc->dpcTriCaps.dwDestBlendCaps & 0x20) )
+      a6->pInfo[v8].uCaps |= 0x10u;
+    if ( !(pHWDesc->dpcTriCaps.dwDestBlendCaps & 2) )
+      a6->pInfo[v8].uCaps |= 0x20u;
+    if ( !(pHWDesc->dpcTriCaps.dwDestBlendCaps & 4) )
+      a6->pInfo[v8].uCaps |= 0x40u;
+    if ( !(BYTE1(pHWDesc->dwDevCaps) & 0x10) )
+      BYTE1(a6->pInfo[v8].uCaps) |= 1u;
+    if ( pHWDesc->dpcTriCaps.dwTextureCaps & 0x20 )
+      LOBYTE(a6->pInfo[v8].uCaps) |= 0x80u;
+    v9 = strlen(lpDeviceName);
+    a6->pInfo[v8].pName = new char[v9 + 1];
+    strcpy(a6->pInfo[v8].pName, lpDeviceName);
+    v10 = strlen(lpDeviceDesc);
+    a6->pInfo[v8].pDescription = new char[v10 + 1];
+    strcpy(a6->pInfo[v8].pDescription, lpDeviceDesc);
+    a6->pInfo[v8].pGUID = (GUID *)operator new(0x10u);
+    memcpy(a6->pInfo[v8].pGUID, lpGUID, 0x10u);
+    v11 = strlen(a6->ptr_4->pDriverName);
+    a6->pInfo[v8].pDriverName = new char[v11 + 1];
+    strcpy(a6->pInfo[v8].pDriverName, a6->ptr_4->pDriverName);
+    v12 = strlen(a6->ptr_4->pDeviceDesc);
+    a6->pInfo[v8].pDeviceDesc = new char[v12 + 1];
+    strcpy(a6->pInfo[v8].pDeviceDesc, a6->ptr_4->pDeviceDesc);
+    v13 = strlen(a6->ptr_4->pDDraw4DevDesc);
+    a6->pInfo[v8].pDDraw4DevDesc = new char[v13 + 1];
+    strcpy(a6->pInfo[v8].pDDraw4DevDesc, a6->ptr_4->pDDraw4DevDesc);
+    if ( a6->ptr_4->pGUID )
+    {
+      a6->pInfo[v8].pDirectDrawGUID = new GUID;
+      memcpy(a6->pInfo[v8].pDirectDrawGUID, a6->ptr_4->pGUID, 0x10u);
+    }
+    else
+    {
+      a6->pInfo[v8].pDirectDrawGUID = 0;
+    }
+    a6->pInfo[v8].uVideoMem = a6->ptr_4->uVideoMem;
+  }
+  return 1;
+}
+
+
+//----- (0049D75C) --------------------------------------------------------
+HRESULT __stdcall DDrawDisplayModesEnumerator(DDSURFACEDESC2 *pSurfaceDesc, __int16 *a2)
+{
+  HRESULT result; // eax@3
+
+  if ( pSurfaceDesc->ddsCaps.dwCaps | 0x2000 && pSurfaceDesc->ddpfPixelFormat.dwRGBBitCount == 16 )
+  {
+    *a2 = 1;
+    result = 0;
+  }
+  else
+  {
+    result = 1;
+  }
+  return result;
+}
+
+
+
+//----- (0047A95E) --------------------------------------------------------
+void Render::DrawDecorations()
+{
+  char *v0; // esi@2
+  DecorationDesc *v1; // ebx@6
+  __int16 v2; // ax@6
+  double v3; // st7@7
+  int v4; // eax@9
+  int v5; // edx@9
+  unsigned int v6; // edi@9
+  int v7; // eax@9
+  SpriteFrame *v8; // eax@9
+  SpriteFrame *v9; // edi@9
+  unsigned __int16 *v10; // eax@9
+  int v11; // ecx@9
+  int v12; // eax@9
+  int v13; // ecx@9
+  int v14; // ecx@20
+  char v15; // dl@20
+  signed int v16; // eax@20
+  int v17; // eax@23
+  int v18; // ecx@24
+  int v19; // eax@24
+  int v20; // ecx@24
+  int v21; // ebx@26
+  int v22; // eax@26
+  int v23; // eax@30
+  signed __int64 v24; // qtt@31
+  int v25; // ebx@31
+  int v26; // ecx@32
+  RenderBillboard *v27; // eax@37
+  __int16 v28; // dx@37
+  __int16 v29; // cx@37
+  int v30; // ecx@37
+  int v31; // ebx@37
+  Particle_ local_0; // [sp+Ch] [bp-98h]@7
+  int x; // [sp+74h] [bp-30h]@9
+  int y; // [sp+78h] [bp-2Ch]@9
+  int v35; // [sp+7Ch] [bp-28h]@1
+  int v36; // [sp+80h] [bp-24h]@9
+  unsigned __int16 *v37; // [sp+84h] [bp-20h]@9
+  int v38; // [sp+88h] [bp-1Ch]@9
+  int v39; // [sp+8Ch] [bp-18h]@24
+  int v40; // [sp+90h] [bp-14h]@24
+  int v41; // [sp+94h] [bp-10h]@24
+  int v42; // [sp+98h] [bp-Ch]@9
+  int a5; // [sp+9Ch] [bp-8h]@9
+  int b; // [sp+A0h] [bp-4h]@22
+
+  v35 = 0;
+  if ( (signed int)uNumLevelDecorations > 0 )
+  {
+    v0 = (char *)&pLevelDecorations[0].vPosition.y;
+    do
+    {
+      if ( (!(*(v0 - 6) & 0x40) || ((LevelDecoration *)(v0 - 8))->_47A825()) && !(*(v0 - 6) & 0x20) )
+      {
+        v1 = &pDecorationList->pDecorations[*((short *)v0 - 4)];
+        v2 = v1->uFlags;
+        if ( (char)v2 >= 0 )
+        {
+          if ( !(v2 & 0x22) )
+          {
+            v4 = *((int *)v0 - 1);
+            v5 = *((int *)v0 + 1);
+            v6 = pMiscTimer->uTotalGameTimeElapsed;
+            y = *(int *)v0;
+            x = v4;
+            v36 = v5;
+            v7 = abs(v4 + y);
+            v8 = pSpriteFrameTable->GetFrame(v1->uSpriteID, v6 + v7);
+            v9 = v8;
+            v42 = v8->uFlags;
+            a5 = v8->uGlowRadius;
+            v10 = (unsigned __int16 *)stru_5C6E00->Atan2(
+                                        *((int *)v0 - 1) - pIndoorCamera->pos.x,
+                                        *(int *)v0 - pIndoorCamera->pos.y);
+            v11 = *((int *)v0 + 2);
+            v37 = v10;
+            v12 = v42;
+            v38 = 0;
+            v13 = ((signed int)(stru_5C6E00->uIntegerPi
+                              + ((signed int)stru_5C6E00->uIntegerPi >> 3)
+                              + v11
+                              - (signed int)v37) >> 8) & 7;
+            v37 = (unsigned __int16 *)v13;
+            if ( v42 & 2 )
+              v38 = 2;
+            if ( (256 << v13) & v42 )
+              v38 |= 4u;
+            if ( v12 & 0x40000 )
+              v38 |= 0x40u;
+            if ( v12 & 0x20000 )
+              LOBYTE(v38) = v38 | 0x80;
+            if ( a5 )
+            {
+              if ( pRenderer->pRenderD3D && pRenderer->bUseColoredLights )
+              {
+                v14 = v1->uColoredLightRed;
+                v15 = v1->uColoredLightGreen;
+                v16 = v1->uColoredLightBlue;
+              }
+              else
+              {
+                v16 = 255;
+                v14 = 255;
+                v15 = 255;
+              }
+              b = v16;
+              pStationaryLightsStack->AddLight(
+                x,
+                y,
+                v36 + v1->uDecorationHeight / 2,
+                a5,
+                v14,
+                v15,
+                v16,
+                byte_4E94D0);
+            }
+            v17 = (x - pIndoorCamera->pos.x) << 16;
+            if ( pIndoorCamera->sRotationX )
+            {
+              v40 = (y - pIndoorCamera->pos.y) << 16;
+              v18 = ((unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16)
+                  + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
+              v42 = v18;
+              b = (unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+              a5 = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
+              v40 = (v36 - pIndoorCamera->pos.z) << 16;
+              v41 = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16;
+              v19 = (unsigned __int64)(v18 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16;
+              v20 = v19 + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
+              v39 = v19 + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
+              if ( v20 >= 262144 && v20 <= pOutdoorCamera->shading_dist_mist << 16 )
+              {
+                v21 = a5 - b;
+                v41 = a5 - b;
+                a5 = (unsigned __int64)(v42 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16;
+                b = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16;
+                v22 = ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16) - a5;
+LABEL_30:
+                v42 = v22;
+                v40 = 2 * abs(v20);
+                v23 = abs(v21);
+                if ( v40 >= v23 )
+                {
+                  LODWORD(v24) = 0;
+                  HIDWORD(v24) = SLOWORD(pOutdoorCamera->int_fov_rad);
+                  a5 = v24 / v39;
+                  v25 = pViewport->uScreenCenterX
+                      - ((signed int)(((unsigned __int64)(v24 / v39 * v41) >> 16) + 32768) >> 16);
+                  b = (unsigned __int64)(a5 * (signed __int64)v42) >> 16;
+                  v41 = v24 / v39;
+                  v40 = pViewport->uScreenCenterY
+                      - ((signed int)(((unsigned __int64)(a5 * (signed __int64)v42) >> 16) + 32768) >> 16);
+                  v42 = v9->scale;
+                  v41 = (unsigned __int64)(v42 * v24 / v39) >> 16;
+                  v37 = (unsigned __int16 *)&v9->pHwSpriteIDs[(int)v37];
+                  if ( pRenderer->pRenderD3D )
+                  {
+                    v26 = v41;
+                    v42 = pSprites_LOD->pHardwareSprites[(signed __int16)*v37].uBufferWidth >> 1;
+                    b = (unsigned __int64)(v42 * (signed __int64)v41) >> 16;
+                  }
+                  else
+                  {
+                    v26 = v41;
+                    v42 = pSprites_LOD->pSpriteHeaders[(signed __int16)*v37].uWidth >> 1;
+                    b = (unsigned __int64)(v42 * (signed __int64)v41) >> 16;
+                  }
+                  if ( b + v25 >= (signed int)pViewport->uViewportX && v25 - b <= (signed int)pViewport->uViewportZ )
+                  {
+                    if ( (signed int)uNumBillboardsToDraw >= 500 )
+                      return;
+                    v27 = &pBillboardRenderList[uNumBillboardsToDraw++];
+                    ++uNumDecorationsDrawnThisFrame;
+                    v27->uHwSpriteID = *v37;
+                    v28 = v9->uPaletteIndex;
+                    v27->field_0 = v26;
+                    v27->field_4 = v26;
+                    v29 = v38;
+                    v27->uScreenSpaceX = v25;
+                    HIBYTE(v29) |= 2u;
+                    v27->uPalette = v28;
+                    v27->field_1E = v29;
+                    v27->some_x = x;
+                    v27->some_y = y;
+                    v27->some_z = v36;
+                    v27->uScreenSpaceY = v40;
+                    HIWORD(v30) = HIWORD(v39);
+                    v31 = 8 * v35 | 5;
+                    LOWORD(v30) = 0;
+                    v27->uIndoorSectorID = 0;
+                    v27->sZValue = v30 + v31;
+                    v27->uPaletteSubindex = 0;
+                    v27->pSpriteFrame = v9;
+                    v27->uTintColor = 0;
+                  }
+                }
+                goto LABEL_38;
+              }
+            }
+            else
+            {
+              v42 = (x - pIndoorCamera->pos.x) << 16;
+              v40 = (y - pIndoorCamera->pos.y) << 16;
+              b = (unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
+              a5 = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+              v20 = b + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
+              v39 = b + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
+              if ( v20 >= 262144 && v20 <= pOutdoorCamera->shading_dist_mist << 16 )
+              {
+                a5 = (unsigned __int64)(v42 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+                b = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
+                v21 = ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - a5;
+                v41 = ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - a5;
+                v22 = (v36 - pIndoorCamera->pos.z) << 16;
+                goto LABEL_30;
+              }
+            }
+          }
+        }
+        else
+        {
+          memset(&local_0, 0, 0x68u);
+          v3 = (double)*((signed int *)v0 - 1);
+          local_0.bFree = 1036;
+          local_0.uDiffuse = 0xFF3C1Eu;
+          local_0.x = v3;
+          local_0.y = (double)*(signed int *)v0;
+          local_0.z = (double)*((signed int *)v0 + 1);
+          local_0.flt_10 = 0.0;
+          local_0.flt_14 = 0.0;
+          local_0.flt_18 = 0.0;
+          local_0.flt_28 = 1.0;
+          local_0.timeToLive = (rand() & 0x80) + 128;
+          local_0.uTextureID = pBitmaps_LOD->LoadTexture("effpar01");
+          pGame->pParticleEngine->AddParticle(&local_0);
+        }
+      }
+LABEL_38:
+      ++v35;
+      v0 += 32;
+    }
+    while ( v35 < (signed int)uNumLevelDecorations );
+  }
+}
+// 4E94D0: using guessed type char byte_4E94D0;
+// 5187EC: using guessed type int uNumDecorationsDrawnThisFrame;
+
+
+//----- (0049D717) --------------------------------------------------------
+HRESULT __stdcall D3DZBufferFormatEnumerator(DDPIXELFORMAT *Src, DDPIXELFORMAT *Dst)
+{
+  HRESULT v2; // esi@2
+
+  if ( Src->dwFlags & 0x400 | 0x2000 )
+  {
+    v2 = 0;
+    if ( Src->dwRGBBitCount == 16 && !Src->dwRBitMask )
+      goto LABEL_6;
+    if ( !Dst->dwSize )
+    {
+      v2 = 1;
+LABEL_6:
+      memcpy(Dst, Src, 0x20u);
+      return v2;
+    }
+  }
+  return 1;
+}
+
+//----- (0049DC28) --------------------------------------------------------
+void RenderD3D::GetAvailableDevices(RenderD3D__DevInfo **pOutDevices)
+{
+  RenderD3D__DevInfo *v2; // eax@1
+
+  v2 = new RenderD3D__DevInfo[4];// 4 items
+  *pOutDevices = v2;
+  memset(v2, 0, 0xA0u);
+  DirectDrawEnumerateA((LPDDENUMCALLBACKA)RenderD3D__DeviceEnumerator, *pOutDevices);
+}
+
+
+//----- (0049DC58) --------------------------------------------------------
+RenderD3D::RenderD3D()
+{
+  RenderD3D *v1; // esi@1
+
+  v1 = this;
+  this->pHost = 0;
+  this->pDirect3D = 0;
+  this->pUnk = 0;
+  this->pBackBuffer = 0;
+  this->pFrontBuffer = 0;
+  this->pZBuffer = 0;
+  this->pDevice = 0;
+  this->pViewport = 0;
+  this->field_40 = 1;
+  this->field_44 = 10;
+  GetAvailableDevices(&this->pAvailableDevices);
+}
+
+//----- (0049DC90) --------------------------------------------------------
+void RenderD3D::Release()
+{
+  RenderD3D *v1; // esi@1
+  IDirectDraw4 *v2; // eax@2
+  signed int v3; // edi@4
+  IDirect3DViewport3 *v4; // eax@22
+  IUnknown *v5; // eax@24
+  IDirectDrawSurface4 *v6; // eax@26
+  IDirect3DDevice3 *v7; // eax@28
+  IDirect3D3 *v8; // eax@30
+  IDirectDrawSurface4 *v9; // eax@32
+  IDirectDrawSurface4 *v10; // eax@34
+  IDirectDraw4 *v11; // eax@36
+
+  v1 = this;
+  if ( !this->bWindowed )
+  {
+    v2 = this->pHost;
+    if ( v2 )
+    {
+      v2->RestoreDisplayMode();
+      v1->pHost->SetCooperativeLevel(v1->hWindow, 8u);
+      v1->pHost->FlipToGDISurface();
+    }
+  }
+  v3 = 0;
+  do
+  {
+    if ( v1->pAvailableDevices[v3].pDriverName )
+    {
+      free(v1->pAvailableDevices[v3].pDriverName);
+      v1->pAvailableDevices[v3].pDriverName = 0;
+    }
+    if ( v1->pAvailableDevices[v3].pDeviceDesc )
+    {
+      free(v1->pAvailableDevices[v3].pDeviceDesc);
+      v1->pAvailableDevices[v3].pDeviceDesc = 0;
+    }
+    if ( v1->pAvailableDevices[v3].pDDraw4DevDesc )
+    {
+      free(v1->pAvailableDevices[v3].pDDraw4DevDesc);
+      v1->pAvailableDevices[v3].pDDraw4DevDesc = 0;
+    }
+    if ( v1->pAvailableDevices[v3].pDirectDrawGUID )
+    {
+      free(v1->pAvailableDevices[v3].pDirectDrawGUID);
+      v1->pAvailableDevices[v3].pDirectDrawGUID = 0;
+    }
+    if ( v1->pAvailableDevices[v3].pName )
+    {
+      free(v1->pAvailableDevices[v3].pName);
+      v1->pAvailableDevices[v3].pName = 0;
+    }
+    if ( v1->pAvailableDevices[v3].pDescription )
+    {
+      free(v1->pAvailableDevices[v3].pDescription);
+      v1->pAvailableDevices[v3].pDescription = 0;
+    }
+    if ( v1->pAvailableDevices[v3].pGUID )
+    {
+      free(v1->pAvailableDevices[v3].pGUID);
+      v1->pAvailableDevices[v3].pGUID = 0;
+    }
+    ++v3;
+  }
+  while ( v3 < 4 );
+  if ( v1->pAvailableDevices )
+  {
+    free(v1->pAvailableDevices);
+    v1->pAvailableDevices = 0;
+  }
+  v4 = v1->pViewport;
+  if ( v4 )
+  {
+    v4->Release();
+    v1->pViewport = 0;
+  }
+  v5 = v1->pUnk;
+  if ( v5 )
+  {
+    v5->Release();
+    v1->pUnk = 0;
+  }
+  v6 = v1->pZBuffer;
+  if ( v6 )
+  {
+    v6->Release();
+    v1->pZBuffer = 0;
+  }
+  v7 = v1->pDevice;
+  if ( v7 )
+  {
+    v7->Release();
+    v1->pDevice = 0;
+  }
+  v8 = v1->pDirect3D;
+  if ( v8 )
+  {
+    v8->Release();
+    v1->pDirect3D = 0;
+  }
+  v9 = v1->pBackBuffer;
+  if ( v9 )
+  {
+    v9->Release();
+    v1->pBackBuffer = 0;
+  }
+  v10 = v1->pFrontBuffer;
+  if ( v10 )
+  {
+    v10->Release();
+    v1->pFrontBuffer = 0;
+  }
+  v11 = v1->pHost;
+  if ( v11 )
+  {
+    v11->Release();
+    v1->pHost = 0;
+  }
+}
+
+
+//----- (0049DE14) --------------------------------------------------------
+bool RenderD3D::CreateDevice(unsigned int uDeviceID, int bWindowed, HWND hWnd)
+{
+  //IDirectDraw4 *v8; // eax@12
+  //IDirectDraw4 *v9; // eax@16
+  //IDirectDraw4 *v10; // eax@20
+  //IDirectDraw4 *v13; // eax@35
+  const char *v23; // [sp-4h] [bp-DCh]@9
+  const char *v24; // [sp-4h] [bp-DCh]@13
+  const char *v25; // [sp-4h] [bp-DCh]@19
+  DWORD v26; // [sp-4h] [bp-DCh]@30
+  DDSCAPS2 v27; // [sp+Ch] [bp-CCh]@37
+  DDSURFACEDESC2 ddsd2; // [sp+1Ch] [bp-BCh]@11
+  D3DVIEWPORT2 d3dvp2; // [sp+98h] [bp-40h]@28
+  IDirectDrawClipper *v30; // [sp+C4h] [bp-14h]@18
+  LPDIRECTDRAW lpDD; // [sp+C8h] [bp-10h]@1
+
+  this->bWindowed = bWindowed;
+  this->hWindow = hWnd;
+
+  if (FAILED(DirectDrawCreate(pAvailableDevices[uDeviceID].pDirectDrawGUID, &lpDD, 0)))
+  {
+    sprintf(pErrorMessage, "Init - Failed to create DirectDraw interface.\n");
+    return 0;
+  }
+
+  if (FAILED(lpDD->QueryInterface(IID_IDirectDraw4, (LPVOID *)&pHost)))
+  {
+    sprintf(pErrorMessage, "Init - Failed to create DirectDraw4 interface.\n");
+    if (lpDD)
+      lpDD->Release();
+    return 0;
+  }
+  lpDD->Release();
+  lpDD = 0;
+
+  if (bWindowed && !pAvailableDevices[uDeviceID].pDirectDrawGUID)
+  {
+    if (FAILED(pHost->SetCooperativeLevel(hWnd, DDSCL_MULTITHREADED | DDSCL_NORMAL)))
+    {
+      v23 = "Init - Failed to set cooperative level.\n";
+      sprintf(pErrorMessage, v23);
+LABEL_65:
+      if (pHost)
+      {
+        pHost->Release();
+        pHost = 0;
+      }
+      return 0;
+    }
+    memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
+    ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+    ddsd2.dwFlags = DDSD_CAPS;
+    ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    if ( !pHost->CreateSurface(&ddsd2, &pFrontBuffer, 0) )
+    {
+      ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+      pHost->GetDisplayMode(&ddsd2);
+      if ( ddsd2.ddpfPixelFormat.dwRGBBitCount != 16 )
+      {
+        v24 = "Init - Desktop isn't in 16 bit mode.\n";
+        goto LABEL_14;
+      }
+
+      ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+      ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+      ddsd2.dwWidth = 640;
+      ddsd2.dwHeight = 480;
+      if (pHost->CreateSurface(&ddsd2, &pBackBuffer, 0) )
+      {
+        v24 = "Init - Failed to create back buffer.\n";
+LABEL_14:
+        sprintf(pErrorMessage, v24);
+        if (pFrontBuffer)
+        {
+          pFrontBuffer->Release();
+          pFrontBuffer = 0;
+        }
+        goto LABEL_65;
+      }
+      if ( pHost->CreateClipper(0, &v30, 0) )
+      {
+        v25 = "Init - Failed to create clipper.\n";
+        goto LABEL_45;
+      }
+      v30->SetHWnd(0, hWnd);
+      pFrontBuffer->SetClipper(v30);
+
+      v30->Release();
+      v30 = 0;
+
+      pHost->QueryInterface(IID_IDirect3D3, (LPVOID *)&pDirect3D);
+
+      ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+      ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
+      ddsd2.dwWidth = 640;
+      ddsd2.dwHeight = 480;
+
+      if ( pDirect3D->EnumZBufferFormats(*pAvailableDevices[uDeviceID].pGUID,
+             (HRESULT (__stdcall *)(DDPIXELFORMAT *, void *))D3DZBufferFormatEnumerator,
+             &ddsd2.ddpfPixelFormat) )
+        goto LABEL_21;
+      if ( uDeviceID == 2 || uDeviceID == 3 )
+        ddsd2.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+
+      if ( !pHost->CreateSurface(&ddsd2, &pZBuffer, 0) )
+      {
+        if ( !pBackBuffer->AddAttachedSurface(pZBuffer) )
+        {
+          if ( !pDirect3D->CreateDevice(*pAvailableDevices[uDeviceID].pGUID,
+                  pBackBuffer,
+                  &pDevice,
+                  0) )
+          {
+            memset(&d3dvp2, 0, sizeof(D3DVIEWPORT2));
+            d3dvp2.dvClipWidth = 2.0;
+            d3dvp2.dvClipY = 1.0;
+            d3dvp2.dvClipHeight = 2.0;
+            d3dvp2.dvMaxZ = 1.0;
+            d3dvp2.dvMinZ = 0.0;
+            goto LABEL_54;
+          }
+LABEL_51:
+          sprintf(pErrorMessage, "Init - Failed to create D3D device.\n");
+          if (pDirect3D)
+          {
+            pDirect3D->Release();
+            pDirect3D = 0;
+          }
+          goto LABEL_59;
+        }
+LABEL_48:
+        sprintf(pErrorMessage, "Init - Failed to attach z-buffer to back buffer.\n");
+        if (pZBuffer)
+        {
+          pZBuffer->Release();
+          pZBuffer = 0;
+        }
+        goto LABEL_61;
+      }
+      goto LABEL_44;
+    }
+LABEL_36:
+    v23 = "Init - Failed to create front buffer.\n";
+    sprintf(pErrorMessage, v23);
+    goto LABEL_65;
+  }
+  if ( uDeviceID == 1 )
+    v26 = 1045;
+  else
+    v26 = 1041;
+  if (pHost->SetCooperativeLevel(hWnd, v26) )
+  {
+    v23 = "Init - Failed to set cooperative level.\n";
+    sprintf(pErrorMessage, v23);
+    goto LABEL_65;
+  }
+  if (pHost->SetDisplayMode(640u, 480u, 16u, 0, 0) )
+  {
+    v23 = "Init - Failed to set display mode.\n";
+    sprintf(pErrorMessage, v23);
+    goto LABEL_65;
+  }
+
+  memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
+  ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+  ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+  ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+  ddsd2.dwBackBufferCount = 1;
+  if ( pHost->CreateSurface(&ddsd2, &pFrontBuffer, 0) )
+    goto LABEL_36;
+  //a3a = &pBackBuffer;
+  //v14 = *v34;
+  memset(&v27, 0, sizeof(DDSCAPS2));
+  v27.dwCaps = DDSCAPS_BACKBUFFER;
+  //v33 = (IDirect3DDevice3 **)v14->GetAttachedSurface(&v27, &pBackBuffer);
+  //hWnda = &pDirect3D;
+  pHost->QueryInterface(IID_IDirect3D3, (LPVOID *)&pDirect3D);
+  if (FAILED(pFrontBuffer->GetAttachedSurface(&v27, &pBackBuffer)))
+  {
+    v25 = "Init - Failed to get D3D interface.\n";
+    goto LABEL_45;
+  }
+
+  ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+  ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
+  ddsd2.dwWidth = 640;
+  ddsd2.dwHeight = 480;
+  if ( pDirect3D->EnumZBufferFormats(*pAvailableDevices[uDeviceID].pGUID,
+         (HRESULT (__stdcall *)(DDPIXELFORMAT *, void *))D3DZBufferFormatEnumerator,
+         &ddsd2.ddpfPixelFormat) )
+  {
+LABEL_21:
+    v25 = "Init - Failed to enumerate Z buffer formats.\n";
+    goto LABEL_45;
+  }
+  if ( uDeviceID == 2 || uDeviceID == 3 )
+    BYTE1(ddsd2.ddsCaps.dwCaps) |= 8u;
+  //uDeviceIDa = &pZBuffer;
+  if (pHost->CreateSurface(&ddsd2, &pZBuffer, 0) )
+  {
+LABEL_44:
+    v25 = "Init - Failed to create z-buffer.\n";
+LABEL_45:
+    sprintf(pErrorMessage, v25);
+    if (pBackBuffer)
+    {
+      pBackBuffer->Release();
+      pBackBuffer = 0;
+    }
+LABEL_63:
+    //v19 = &pFrontBuffer;
+    if (pFrontBuffer)
+    {
+      pFrontBuffer->Release();
+      pFrontBuffer= 0;
+    }
+    goto LABEL_65;
+  }
+  if (pBackBuffer->AddAttachedSurface(pZBuffer))
+    goto LABEL_48;
+  //v33 = &pDevice;
+  if (pDirect3D->CreateDevice(*pAvailableDevices[uDeviceID].pGUID,
+         pBackBuffer,
+         &pDevice,
+         0) )
+    goto LABEL_51;
+  memset(&d3dvp2, 0, sizeof(D3DVIEWPORT2));
+  d3dvp2.dvClipWidth = 2.0;
+  d3dvp2.dvClipY = 1.0;
+  d3dvp2.dvClipHeight = 2.0;
+  d3dvp2.dvMaxZ = 1.0;
+
+LABEL_54:
+  d3dvp2.dwSize = sizeof(D3DVIEWPORT2);
+  //v17 = *hWnda;
+  d3dvp2.dwWidth = 640;
+  d3dvp2.dwHeight = 480;
+  d3dvp2.dvClipX = -1.0;
+  //v18 = v17->lpVtbl;
+  //v32 = &v4->pViewport;
+  if (pDirect3D->CreateViewport(&pViewport, 0))
+  {
+    sprintf(pErrorMessage, "Init - Failed to create viewport.\n");
+    if (pDevice)
+    {
+      pDevice->Release();
+      pDevice = 0;
+    }
+    if (pDirect3D)
+    {
+      pDirect3D->Release();
+      pDirect3D = 0;
+    }
+LABEL_59:
+    if (pZBuffer)
+    {
+      pZBuffer->Release();
+      pZBuffer = 0;
+    }
+LABEL_61:
+    if (pBackBuffer)
+    {
+      pBackBuffer->Release();
+      pBackBuffer = 0;
+    }
+    goto LABEL_63;
+  }
+
+  pDevice->AddViewport(pViewport);
+  pViewport->SetViewport2(&d3dvp2);
+  pDevice->SetCurrentViewport(pViewport);
+  return 1;
+}
+
+
+//----- (0049E444) --------------------------------------------------------
+unsigned int RenderD3D::GetDeviceCaps()
+{
+  unsigned int v1; // ebx@1
+  RenderD3D *v2; // edi@1
+  IDirect3DDevice3 *v3; // eax@1
+  unsigned int result; // eax@2
+  D3DDEVICEDESC refCaps; // [sp+Ch] [bp-1F8h]@1
+  D3DDEVICEDESC halCaps; // [sp+108h] [bp-FCh]@1
+
+  v1 = 0;
+  v2 = this;
+  memset(&halCaps, 0, 0xFCu);
+  halCaps.dwSize = 252;
+  memset(&refCaps, 0, 0xFCu);
+  v3 = v2->pDevice;
+  refCaps.dwSize = 252;
+  if ( v3->GetCaps(&halCaps, &refCaps) )
+  {
+    result = 1;
+  }
+  else
+  {
+    if ( !(halCaps.dpcTriCaps.dwSrcBlendCaps & 0x10) )
+      v1 = 2;
+    if ( !(halCaps.dpcTriCaps.dwSrcBlendCaps & 2) )
+      v1 |= 4u;
+    if ( !(halCaps.dpcTriCaps.dwSrcBlendCaps & 1) )
+      v1 |= 8u;
+    if ( !(halCaps.dpcTriCaps.dwDestBlendCaps & 0x20) )
+      v1 |= 0x10u;
+    if ( !(halCaps.dpcTriCaps.dwDestBlendCaps & 2) )
+      v1 |= 0x20u;
+    if ( !(halCaps.dpcTriCaps.dwDestBlendCaps & 4) )
+      v1 |= 0x40u;
+    if ( halCaps.dpcTriCaps.dwTextureCaps & 0x20 )
+      LOBYTE(v1) = v1 | 0x80;
+    result = v1;
+  }
+  return result;
+}
+
+
+//----- (0049E4FC) --------------------------------------------------------
+void RenderD3D::ClearTarget(unsigned int bClearColor, unsigned int uClearColor, unsigned int bClearDepth, float z_clear)
+{
+  uint uClearFlags = 0;
+
+  if (bClearColor)
+    uClearFlags |= D3DCLEAR_TARGET;
+  if (bClearDepth)
+    uClearFlags |= D3DCLEAR_ZBUFFER;
+  
+  D3DRECT rects[] = {{0, 0, 640, 480}};
+  if (uClearFlags)
+    pViewport->Clear2(1, rects, uClearFlags, uClearColor, z_clear, 0);
+}
+
+
+//----- (0049E54D) --------------------------------------------------------
+void RenderD3D::Present(bool bForceBlit)
+{
+  RECT v5; // [sp+18h] [bp-18h]@1
+  struct tagPOINT Point; // [sp+28h] [bp-8h]@4
+
+  v5.left = 0;
+  v5.top = 0;
+  v5.bottom = 480;
+  v5.right = 640;
+
+  if (bWindowed || bForceBlit)
+  {
+    RECT rc;
+    GetClientRect(hWindow, &rc);
+    Point.y = 0;
+    Point.x = 0;
+    ClientToScreen(hWindow, &Point);
+    OffsetRect(&rc, Point.x, Point.y);
+    pFrontBuffer->Blt(&rc, pBackBuffer, &v5, DDBLT_WAIT, 0);
+  }
+  else
+    pFrontBuffer->Flip(0, 1);
+}
+
+
+//----- (0049E5D4) --------------------------------------------------------
+bool RenderD3D::CreateTexture(unsigned int uTextureWidth, unsigned int uTextureHeight, IDirectDrawSurface4 **pOutSurface, IDirect3DTexture2 **pOutTexture, bool bAlphaChannel, bool bMipmaps, unsigned int uMinDeviceTexDim)
+{
+  unsigned int v8; // edx@4
+  unsigned int v9; // ebx@5
+  unsigned int v10; // eax@5
+  DWORD v11; // edx@5
+  //int v12; // edx@7
+  DDSURFACEDESC2 ddsd2; // [sp+Ch] [bp-80h]@1
+  //RenderD3D *v15; // [sp+88h] [bp-4h]@1
+
+  //v15 = this;
+  memset(&ddsd2, 0, 0x7Cu);
+  ddsd2.dwSize = 0x7Cu;
+  ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+  ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+  ddsd2.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
+  ddsd2.dwHeight = uTextureHeight;
+  ddsd2.dwWidth = uTextureWidth;
+  if ( bMipmaps )
+  {
+    if ( (signed int)uTextureHeight <= (signed int)uTextureWidth )
+    {
+      v8 = GetMaxMipLevels(uTextureHeight) - GetMaxMipLevels(uMinDeviceTexDim);
+LABEL_8:
+      ddsd2.dwMipMapCount = v8;
+      if ( !v8 )
+        goto LABEL_12;
+      goto LABEL_11;
+    }
+    if ( (signed int)uTextureWidth < (signed int)uMinDeviceTexDim )
+    {
+      v8 = GetMaxMipLevels(uMinDeviceTexDim);
+      goto LABEL_8;
+    }
+    v9 = GetMaxMipLevels(uTextureWidth);
+    v10 = GetMaxMipLevels(uMinDeviceTexDim);
+    ddsd2.dwMipMapCount = v9 - v10;
+    if ( v9 == v10 )
+    {
+      ddsd2.dwFlags = 0x1007u;
+      ddsd2.ddsCaps.dwCaps = v11;
+      goto LABEL_12;
+    }
+  }
+  else
+  {
+    ddsd2.dwMipMapCount = 1;
+  }
+LABEL_11:
+  ddsd2.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
+  ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
+LABEL_12:
+  ddsd2.ddpfPixelFormat.dwRGBBitCount = 16;
+  ddsd2.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+  if (bAlphaChannel)
+  {
+    ddsd2.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
+    ddsd2.ddpfPixelFormat.dwRBitMask = 0x7C00;
+    ddsd2.ddpfPixelFormat.dwGBitMask = 0x03E0;
+    ddsd2.ddpfPixelFormat.dwBBitMask = 0x001F;
+    ddsd2.ddpfPixelFormat.dwRGBAlphaBitMask = 0x8000u;
+  }
+  else
+  {
+    ddsd2.ddpfPixelFormat.dwFlags = DDPF_RGB;
+    ddsd2.ddpfPixelFormat.dwRBitMask = 0xF800;
+    ddsd2.ddpfPixelFormat.dwGBitMask = 0x07E0;
+    ddsd2.ddpfPixelFormat.dwBBitMask = 0x001F;
+    ddsd2.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
+  }
+  if (FAILED(pHost->CreateSurface(&ddsd2, pOutSurface, 0)))
+    return false;
+  if (FAILED((*pOutSurface)->QueryInterface(IID_IDirect3DTexture2, (void **)pOutTexture)))
+  {
+    (*pOutSurface)->Release();
+    *pOutSurface = 0;
+    return false;
+  }
+  return true;
+}
+
+//----- (004A5190) --------------------------------------------------------
+void RenderD3D::HandleLostResources()
+{
+  pBitmaps_LOD->ReleaseLostHardwareTextures();
+  pBitmaps_LOD->_410423_move_textures_to_device();
+  pSprites_LOD->ReleaseLostHardwareSprites();
+}
+
+
+
+//----- (004A2050) --------------------------------------------------------
+void Render::DrawPolygon(unsigned int uNumVertices, stru148 *a3, ODMFace *a4, IDirect3DTexture2 *pTexture)
+{
+  Render *v5; // edi@1
+  unsigned int v6; // ebx@1
+  LightmapBuilder *v7; // esi@3
+  int v8; // eax@7
+  ODMFace *v9; // eax@12
+  char *v10; // esi@12
+  double v11; // st7@14
+  double v12; // st7@14
+  int v13; // eax@14
+  ODMFace *v14; // ecx@14
+  double v15; // st7@14
+  float v16; // ST48_4@15
+  int v17; // eax@15
+  char v18; // zf@17
+  HRESULT v19; // eax@18
+  HRESULT v20; // eax@18
+  HRESULT v21; // eax@20
+  HRESULT v22; // eax@20
+  unsigned int v23; // ecx@20
+  char *v24; // eax@21
+  HRESULT v25; // eax@23
+  HRESULT v26; // eax@23
+  HRESULT v27; // eax@24
+  HRESULT v28; // eax@25
+  HRESULT v29; // eax@25
+  HRESULT v30; // eax@25
+  HRESULT v31; // eax@25
+  HRESULT v32; // eax@26
+  unsigned int v33; // ecx@26
+  char *v34; // eax@27
+  int v35; // edx@28
+  HRESULT v36; // eax@29
+  HRESULT v37; // eax@29
+  HRESULT v38; // eax@29
+  HRESULT v39; // eax@29
+  //IDirect3DDevice3Vtbl *v40; // ebx@29
+  unsigned int v41; // eax@29
+  HRESULT v42; // eax@30
+  HRESULT v43; // eax@30
+  HRESULT v44; // eax@30
+  char *v45; // esi@34
+  int v46; // ecx@35
+  double v47; // st6@35
+  int v48; // eax@36
+  const char *v49; // [sp+4Ch] [bp-1Ch]@0
+  const char *v50; // [sp+4Ch] [bp-1Ch]@20
+  int v51; // [sp+50h] [bp-18h]@0
+  unsigned int v52; // [sp+54h] [bp-14h]@0
+  LightmapBuilder *v53; // [sp+58h] [bp-10h]@3
+  unsigned int v54; // [sp+5Ch] [bp-Ch]@3
+  unsigned int v55; // [sp+5Ch] [bp-Ch]@34
+  unsigned int v56; // [sp+60h] [bp-8h]@12
+  int v57; // [sp+60h] [bp-8h]@34
+  HRESULT a2; // [sp+64h] [bp-4h]@4
+
+  v5 = this;
+  v6 = 0;
+  if ( this->uNumD3DSceneBegins && (signed int)uNumVertices >= 3 )
+  {
+    v7 = pGame->pLightmapBuilder;
+    v53 = v7;
+    v54 = v7->std__vector_000004_size;
+    if ( v7->std__vector_000004_size)
+      a2 = -1;
+    pGame->_44EE30(a4, (int)&a2);
+    if ( byte_4D864C && pGame->uFlags & 1 )
+    {
+      v8 = GetActorTintColor(a3->field_58, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
+      v7->_45D74F_MessWithLight(v8, 0);
+    }
+    else
+    {
+      if ( !v54 || byte_4D864C && pGame->uFlags & 2 )
+      {
+        ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1u));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW));
+        if (bUsingSpecular)
+        {
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1));
+        }
+        if ( (signed int)uNumVertices > 0 )
+        {
+          v45 = (char *)&array_50AC10[0].vWorldViewPosition;
+          v57 = (int)&arary_77E5C8[0].pos.y;
+          v55 = uNumVertices;
+          do
+          {
+            a2 = GetActorTintColor(a3->field_58, 0, *(float *)v45, 0, 0);
+            pGame->_44EE30(a4, (int)&a2);
+            v46 = v57;
+            v47 = *(float *)v45 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist;
+            *(int *)(v57 - 4) = *((int *)v45 + 3);
+            *(int *)v57 = *((int *)v45 + 4);
+            *(int *)(v57 + 12) = a2;
+            *(float *)(v57 + 4) = 1.0 - 1.0 / v47;
+            *(float *)(v57 + 8) = 1.0 / (*(float *)v45 + 0.0000001);
+            if ( v5->bUsingSpecular )
+            {
+              v48 = sub_47C3D7_get_fog_related_stuff(0, 0, *(float *)v45);
+              v46 = v57;
+            }
+            else
+            {
+              v48 = 0;
+            }
+            *(int *)(v46 + 16) = v48;
+            *(int *)(v46 + 20) = *((int *)v45 + 6);
+            *(int *)(v46 + 24) = *((int *)v45 + 7);
+            v45 += 48;
+            v18 = v55-- == 1;
+            v57 = v46 + 32;
+          }
+          while ( !v18 );
+        }
+        pRenderD3D->pDevice->SetTexture(0, pTexture);
+        pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+                                           D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                                           arary_77E5C8,
+                                           uNumVertices,
+                                           D3DDP_DONOTLIGHT);
+      }
+      else
+      {
+        if ( (signed int)uNumVertices > 0 )
+        {
+          v9 = (ODMFace *)&arary_77E5C8[0].pos.y;
+          v10 = (char *)&array_50AC10[0].vWorldViewPosition;
+          a4 = (ODMFace *)&arary_77E5C8[0].pos.y;
+          v56 = uNumVertices;
+          while ( 1 )
+          {
+            v11 = *(float *)v10 * 1000.0;
+            *((int *)v9 - 1) = *((int *)v10 + 3);
+            v12 = v11 / (double)pOutdoorCamera->shading_dist_mist;
+            v9->pFacePlane.vNormal.x = *((int *)v10 + 4);
+            *(float *)&v9->pFacePlane.vNormal.y = 1.0 - 1.0 / v12;
+            *(float *)&v9->pFacePlane.vNormal.z = 1.0 / (*(float *)v10 + 0.0000001);
+            v13 = GetActorTintColor(a3->field_58, 0, *(float *)v10, 0, 0);
+            v14 = a4;
+            v15 = *(float *)v10;
+            a4->pFacePlane.dist = v13;
+            if ( v5->bUsingSpecular )
+            {
+              v16 = v15;
+              v17 = sub_47C3D7_get_fog_related_stuff(0, 0, v16);
+              v14 = a4;
+            }
+            else
+            {
+              v17 = 0;
+            }
+            v14->zCalc1 = v17;
+            v14->zCalc2 = *((int *)v10 + 6);
+            v14->zCalc3 = *((int *)v10 + 7);
+            v10 += 48;
+            v18 = v56-- == 1;
+            a4 = (ODMFace *)((char *)v14 + 32);
+            if ( v18 )
+              break;
+            v9 = a4;
+          }
+        }
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false));
+        ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1u));
+        if (bUsingSpecular)
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0));
+
+        ErrD3D(pRenderD3D->pDevice->SetTexture(0, nullptr));
+        ErrD3D(pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+                                                  D3DFVF_XYZRHW | D3DFVF_TEX1 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
+                                                  arary_77E5C8,
+                                                  uNumVertices,
+                                                  D3DDP_DONOTLIGHT));
+        //v50 = (const char *)v5->pRenderD3D->pDevice;
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE));
+        //(*(void (**)(void))(*(int *)v50 + 88))();
+        v53->_45D74F_MessWithLight(-1, 0);
+        v23 = uNumVertices;
+        if ( (signed int)uNumVertices > 0 )
+        {
+          v24 = (char *)&arary_77E5C8[0].diffuse;
+          do
+          {
+            *(int *)v24 = a2;
+            v24 += 32;
+            --v23;
+          }
+          while ( v23 );
+        }
+        ErrD3D(pRenderD3D->pDevice->SetTexture(0, pTexture));
+        ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1u));
+        if ( !pRenderer->bUsingSpecular )
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true));
+
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 1));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 3));
+        ErrD3D(pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+                                                  D3DFVF_XYZRHW | D3DFVF_TEX1 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
+                                                  arary_77E5C8,
+                                                  uNumVertices,
+                                                  D3DDP_DONOTLIGHT));
+        if (bUsingSpecular)
+        {
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true));
+
+          v33 = uNumVertices;
+          if ( (signed int)uNumVertices > 0 )
+          {
+            v34 = (char *)&arary_77E5C8[0].specular;
+            do
+            {
+              v35 = *(int *)v34;
+              *(int *)v34 = 0;
+              v34 += 32;
+              --v33;
+              *((int *)v34 - 9) = pRenderer->uFogColor | v35 & 0xFF000000;
+            }
+            while ( v33 );
+          }
+          ErrD3D(pRenderD3D->pDevice->SetTexture(0, nullptr));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 6));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 5));
+          ErrD3D(pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+                                                    D3DFVF_XYZRHW | D3DFVF_TEX1 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
+                                                    arary_77E5C8,
+                                                    uNumVertices,
+                                                    D3DDP_DONOTLIGHT));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true));
+          //v40 = pRenderer->pRenderD3D->pDevice->lpVtbl;
+          v41 = GetLevelFogColor();
+          pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, GetLevelFogColor() & 0xFFFFFF);
+          v6 = 0;
+          pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0);
+        }
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, v6));
+      }
+    }
+  }
+}
+// 4D864C: using guessed type char byte_4D864C;
+
+
+//----- (0049EB79) --------------------------------------------------------
+Render::~Render()
+{
+  Render *v1; // esi@1
+
+  v1 = this;
+  pAllocator->FreeChunk(this->pDefaultZBuffer);
+  v1->pD3DBitmaps.Release();
+  v1->pD3DSprites.Release();
+  Release();
+  v1->bWindowMode = 1;
+  //nullsub_1();
+  //nullsub_1();
+}
+
+
+
+//----- (0049E756) --------------------------------------------------------
+bool Render::IsColorKeySupported(IDirectDraw4 *this_)
+{
+  DDCAPS refCaps; // [sp+0h] [bp-2F8h]@1
+  DDCAPS halCaps; // [sp+17Ch] [bp-17Ch]@1
+
+  halCaps.dwSize = 380;
+  refCaps.dwSize = 380;
+  this_->GetCaps(&halCaps, &refCaps);
+  return halCaps.dwSVBCaps & 0x40 && BYTE1(halCaps.dwSVBCKeyCaps) & 2;
+}
+
+//----- (0049E992) --------------------------------------------------------
+Render::Render()
+{
+  Render *v1; // esi@1
+  int v2; // eax@1
+  char v3; // zf@1
+
+  v1 = this;
+  this->pDirectDraw4 = 0;
+  this->pFrontBuffer4 = 0;
+  this->pBackBuffer4 = 0;
+  this->pColorKeySurface4 = 0;
+  this->pDirectDraw2 = 0;
+  this->pFrontBuffer2 = 0;
+  this->pBackBuffer2 = 0;
+  this->pSomeSurface2 = 0;
+  //RenderHWLContainer::RenderHWLContainer(&this->pD3DBitmaps);
+  //RenderHWLContainer::RenderHWLContainer(&v1->pD3DSprites);
+  v1->bWindowMode = 1;
+  v1->field_40054 = 0;
+  v1->field_10 = 640;
+  v1->field_14 = 480;
+  v1->field_40030 = 0;
+  v1->field_4002C = 0;
+  v1->pActiveZBuffer = 0;
+  v1->pDefaultZBuffer = 0;
+  v1->field_20_clipy = 0;
+  v1->field_1C_clipx = 0;
+  v1->field_24_clipz = 639;
+  v1->field_28_clipw = 479;
+  v1->field_4003C = (int)&unk_4EED80;
+  v1->field_40040 = dword_4EED78;
+  v1->uClipZ = 640;
+  v1->field_40044 = 2;
+  v1->field_40048 = 6;
+  v1->pFrontBuffer4 = 0;
+  v1->pBackBuffer4 = 0;
+  v1->pColorKeySurface4 = 0;
+  v1->pDirectDraw4 = 0;
+  v1->pRenderD3D = 0;
+  v1->uNumSceneBegins = 0;
+  v1->uNumD3DSceneBegins = 0;
+  v1->field_40110 = 0;
+  v1->pTargetSurface = 0;
+  v1->uTargetSurfacePitch = 0;
+  v1->uClipY = 0;
+  v1->uClipX = 0;
+  v1->uClipW = 480;
+  v1->bClip = 1;
+  v1->bColorKeySupported = 0;
+  v1->bRequiredTextureStagesAvailable = 0;
+  v1->bTinting = 1;
+  LOBYTE(v1->field_103668) = 0;
+  v1->field_1036B8 = 0;
+  v1->_gpu_memory_used = 0;
+  uNumBillboardsToDraw = 0;
+  bFogEnabled = false;
+}
+
+bool Render::Initialize(bool bWindowed, uint uDefaultDevice,
+                        bool bColoredLights, uint uDetailLevel, uint bTinting)
+{
+  bUserDirect3D = true;//ReadWindowsRegistryInt("Use D3D", 0);
+  bStartInWindow = bWindowed;
+
+  uDesiredDirect3DDevice = uDefaultDevice;//ReadWindowsRegistryInt("D3D Device", 1);
+
+  bUseColoredLights = bColoredLights;//ReadWindowsRegistryInt("Colored Lights", 0);
+  uLevelOfDetail = uDetailLevel;//ReadWindowsRegistryInt("Detail Level", 1);
+
+  this->bTinting = bTinting;
+
+  auto r1 = pD3DBitmaps.Load(L"data\\d3dbitmap.hwl");
+  auto r2 = pD3DSprites.Load(L"data\\d3dsprite.hwl");
+
+  return r1 && r2;
+}
+
+
+
+//----- (0049EBF1) --------------------------------------------------------
+void Render::_49EBF1()
+{
+  signed int uNumRedBits; // edx@1
+  signed int uNuGreenBits; // edi@1
+  signed int uNumBlueBits; // esi@1
+  unsigned int v4; // edx@4
+  unsigned int v5; // edi@4
+  int v6; // ebx@4
+  int v7; // edx@4
+  signed int v8; // [sp+8h] [bp-24h]@1
+  signed int v9; // [sp+Ch] [bp-20h]@1
+  signed int v10; // [sp+20h] [bp-Ch]@1
+  signed int i; // [sp+24h] [bp-8h]@2
+  signed int v12; // [sp+28h] [bp-4h]@3
+
+  v10 = 0;
+  uNumRedBits = 1 << this->uTargetRBits;
+  uNuGreenBits = 1 << this->uTargetGBits;
+  uNumBlueBits = 1 << this->uTargetBBits;
+  v9 = 1 << this->uTargetRBits;
+  v8 = 1 << this->uTargetGBits;
+  if ( uNumRedBits > 0 )
+  {
+    do
+    {
+      for ( i = 0; i < uNuGreenBits; ++i )
+      {
+        v12 = 0;
+        if ( uNumBlueBits > 0 )
+        {
+          do
+          {
+            v4 = this->uTargetBBits;
+            v5 = v4 + this->uTargetGBits;
+            v6 = (v12 >> 1) + (v10 >> 1 << v5) + (i >> 1 << this->uTargetBBits);
+            v7 = (v10 << v5) + v12++ + (i << v4);
+            this->field_2C[v7] = v6;
+          }
+          while ( v12 < uNumBlueBits );
+          uNumRedBits = v9;
+          uNuGreenBits = v8;
+        }
+      }
+      ++v10;
+    }
+    while ( v10 < uNumRedBits );
+  }
+}
+
+
+//----- (0049ECC4) --------------------------------------------------------
+void Render::ClearBlack()
+{
+  if (pRenderD3D)
+  {
+    if (field_40110)
+      pRenderD3D->ClearTarget(true, 0, false, 0.0);
+  }
+  else
+    memset(pRenderer->pTargetSurface, 0, 4 * (field_10 * field_14 / 2));
+}
+
+
+//----- (0049ED18) --------------------------------------------------------
+void Render::PresentBlackScreen()
+{
+  LONG w; // edx@3
+  IDirectDrawSurface *v2; // eax@3
+  DDBLTFX v3; // [sp+4h] [bp-74h]@5
+  RECT x; // [sp+68h] [bp-10h]@3
+
+  memset(&v3, 0, sizeof(DDBLTFX));
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion >= 5)
+  {
+    x.left = uWindowX;
+    x.right = uWindowX + uWindowHeight;
+    x.top = uWindowY;
+    w = uWindowY + uWindowWidth;
+    v2 = (IDirectDrawSurface *)this->pBackBuffer4;
+  }
+  else
+  {
+    x.left = uWindowX;
+    x.right = uWindowX + uWindowHeight;
+    x.top = uWindowY;
+    w = uWindowY + uWindowWidth;
+    v2 = (IDirectDrawSurface *)this->pBackBuffer2;
+  }
+  x.bottom = w;
+  v3.dwFillColor = 0;
+  v3.dwSize = 100;
+  v2->Blt(&x, 0, 0, DDBLT_COLORFILL, &v3);
+  pRenderer->Present();
+}
+
+
+//----- (0049EDB6) --------------------------------------------------------
+void Render::SavePCXScreenshot()
+{
+  Render *v1; // esi@1
+  __int16 v2; // di@1
+  int v3; // eax@4
+  int v4; // ecx@4
+  int v5; // eax@8
+  FILE *v6; // edi@10
+  int v7; // ecx@11
+  int v8; // eax@11
+  int v9; // eax@13
+  int v10; // ecx@15
+  unsigned __int8 v11; // dl@15
+  signed int v12; // eax@18
+  char v13; // zf@27
+  HRESULT v14; // eax@29
+  char v15[56]; // [sp+Ch] [bp-158h]@10
+  __int16 v16; // [sp+44h] [bp-120h]@10
+  DDSURFACEDESC2 Dst; // [sp+48h] [bp-11Ch]@7
+  char color_map[48]; // [sp+C4h] [bp-A0h]@10
+  char Filename[40]; // [sp+F4h] [bp-70h]@3
+  char *v20; // [sp+11Ch] [bp-48h]@14
+  char *v21; // [sp+120h] [bp-44h]@14
+  int v24; // [sp+124h] [bp-40h]@11
+  FILE *File; // [sp+128h] [bp-3Ch]@3
+  int var38; // [sp+12Ch] [bp-38h]@4
+  PCXHeader_1 header1; // [sp+130h] [bp-34h]@10
+  PCXHeader_2 header2; // [sp+140h] [bp-24h]@10
+  void *ptr; // [sp+148h] [bp-1Ch]@10
+  void *v28; // [sp+14Ch] [bp-18h]@8
+  int v29; // [sp+150h] [bp-14h]@4
+  int v30; // [sp+154h] [bp-10h]@4
+  char v31; // [sp+15Ah] [bp-Ah]@25
+  unsigned __int8 v32; // [sp+15Bh] [bp-9h]@17
+  int i; // [sp+15Ch] [bp-8h]@10
+  unsigned __int8 v34; // [sp+163h] [bp-1h]@17
+
+  v1 = this;
+  v2 = 0;
+  if ( !this->pRenderD3D || this->field_40110 )
+  {
+    sprintf(Filename, "screen%0.2i.pcx", dword_4EFA80++ % 100);
+    File = fopen(Filename, "wb");
+    if ( File )
+    {
+      v3 = v1->field_10;
+      v4 = v1->field_14;
+      var38 = v3;
+      v29 = v4;
+      v30 = v3;
+      if ( v3 & 1 )
+        v30 = v3 + 1;
+      if ( v1->pRenderD3D )
+      {
+        memset(&Dst, 0, 0x7Cu);
+        Dst.dwSize = 124;
+        if ( !pRenderer->LockSurface_DDraw4(pRenderer->pBackBuffer4, &Dst, 1u) )
+          return;
+        v28 = Dst.lpSurface;
+        v5 = Dst.lPitch >> 1;
+        v2 = 0;
+      }
+      else
+      {
+        pRenderer->BeginScene();
+        v28 = pRenderer->pTargetSurface;
+        v5 = pRenderer->uTargetSurfacePitch;
+      }
+      i = v5;
+      header1.right = var38 - 1;
+      header1.left = v2;
+      header1.bottom = v29 - 1;
+      header1.up = v2;
+      header2.pitch = v30;
+      memset(color_map, 0, sizeof(color_map));
+      memset(v15, 0, sizeof(v15));
+      header2.reserved = 0;
+      header1.manufacturer = 10;
+      v16 = 0;
+      v6 = File;
+      header1.version = 5;
+      header1.encoding = 1;
+      header1.bpp = 8;
+      header1.hdpi = 75;
+      header1.vdpi = 75;
+      header2.planes = 3;
+      header2.palette_info = 1;
+      fwrite(&header1, 1u, 1u, File);
+      fwrite(&header1.version, 1u, 1u, v6);
+      fwrite(&header1.encoding, 1u, 1u, v6);
+      fwrite(&header1.bpp, 1u, 1u, v6);
+      fwrite(&header1.left, 2u, 1u, v6);
+      fwrite(&header1.up, 2u, 1u, v6);
+      fwrite(&header1.right, 2u, 1u, v6);
+      fwrite(&header1.bottom, 2u, 1u, v6);
+      fwrite(&header1.hdpi, 2u, 1u, v6);
+      fwrite(&header1.vdpi, 2u, 1u, v6);
+      fwrite(color_map, 0x30u, 1u, v6);
+      fwrite(&header2, 1u, 1u, v6);
+      fwrite(&header2.planes, 1u, 1u, v6);
+      fwrite(&header2.pitch, 2u, 1u, v6);
+      fwrite(&header2.palette_info, 2u, 1u, v6);
+      fwrite(v15, 0x3Au, 1u, v6);
+      ptr = pAllocator->AllocNamedChunk(0, 3 * var38 + 6, 0);
+      if ( v29 > 0 )
+      {
+        v7 = v30;
+        File = (FILE *)v29;
+        v29 = 3 * v30;
+        v24 = 2 * i;
+        v8 = (int)v28;
+        while ( 1 )
+        {
+          i = v8;
+          v9 = 0;
+          if ( var38 > 0 )
+          {
+            v21 = (char *)ptr + v7;
+            v20 = (char *)ptr + 2 * v30;
+            do
+            {
+              *((char *)ptr + v9) = (signed int)(v1->uTargetRMask & *(short *)i) >> (LOBYTE(v1->uTargetGBits)
+                                                                                    + LOBYTE(v1->uTargetBBits)
+                                                                                    + v1->uTargetRBits
+                                                                                    - 8);
+              v21[v9] = (signed int)(v1->uTargetGMask & *(short *)i) >> (LOBYTE(v1->uTargetBBits)
+                                                                       + LOBYTE(v1->uTargetGBits)
+                                                                       - 8);
+              v10 = i;
+              v11 = LOBYTE(v1->uTargetBMask);
+              i += 2;
+              v20[v9++] = (*(char *)v10 & v11) << (8 - LOBYTE(v1->uTargetBBits));
+            }
+            while ( v9 < var38 );
+          }
+          for ( i = 0; i < v29; i += v34 )
+          {
+            v34 = 1;
+            v32 = *((char *)ptr + i);
+            do
+            {
+              v12 = i + v34;
+              if ( *((char *)ptr + v12) != v32 )
+                break;
+              if ( !(v12 % v30) )
+                break;
+              ++v34;
+            }
+            while ( v34 < 0x3Fu );
+            if ( i + v34 > v29 )
+              v34 = 3 * v30 - i;
+            if ( v34 > 1u || v32 >= 0xC0u )
+            {
+              v31 = v34 | 0xC0;
+              fwrite(&v31, 1u, 1u, v6);
+            }
+            fwrite(&v32, 1u, 1u, v6);
+          }
+          v8 = (int)((char *)v28 + v24);
+          v13 = File == (FILE *)1;
+          File = (FILE *)((char *)File - 1);
+          v28 = (char *)v28 + v24;
+          if ( v13 )
+            break;
+          v7 = v30;
+        }
+      }
+      if ( v1->pRenderD3D )
+      {
+        ErrD3D(pRenderer->pBackBuffer4->Unlock(0));
+      }
+      else
+      {
+        pRenderer->EndScene();
+      }
+
+      pAllocator->FreeChunk(ptr);
+      fclose(v6);
+    }
+  }
+}
+// 4EFA80: using guessed type int dword_4EFA80;
+
+
+//----- (0049F1BC) --------------------------------------------------------
+void Render::_49F1BC(const char *a1)
+{
+  Render *v2; // esi@1
+  __int16 v3; // di@1
+  int v4; // eax@4
+  char *v5; // ecx@4
+  unsigned int v6; // eax@8
+  FILE *v7; // edi@10
+  int v8; // ecx@11
+  int v9; // eax@11
+  int v10; // eax@13
+  const char *v11; // ecx@15
+  unsigned __int8 v12; // dl@15
+  signed int v13; // eax@18
+  char v14; // zf@27
+  HRESULT v15; // eax@29
+  char v16; // [sp+Ch] [bp-12Ch]@10
+  __int16 v17; // [sp+44h] [bp-F4h]@10
+  int Dst; // [sp+48h] [bp-F0h]@7
+  int v19; // [sp+58h] [bp-E0h]@8
+  unsigned __int16 *v20; // [sp+6Ch] [bp-CCh]@8
+  char v21; // [sp+C4h] [bp-74h]@10
+  unsigned int v22; // [sp+F4h] [bp-44h]@11
+  char *v23; // [sp+F8h] [bp-40h]@14
+  int v24; // [sp+FCh] [bp-3Ch]@11
+  int v25; // [sp+100h] [bp-38h]@4
+  FILE *File; // [sp+104h] [bp-34h]@3
+  char Str; // [sp+108h] [bp-30h]@10
+  char v28; // [sp+109h] [bp-2Fh]@10
+  char v29; // [sp+10Ah] [bp-2Eh]@10
+  char v30; // [sp+10Bh] [bp-2Dh]@10
+  __int16 v31; // [sp+10Ch] [bp-2Ch]@10
+  __int16 v32; // [sp+10Eh] [bp-2Ah]@10
+  __int16 v33; // [sp+110h] [bp-28h]@10
+  __int16 v34; // [sp+112h] [bp-26h]@10
+  __int16 v35; // [sp+114h] [bp-24h]@10
+  __int16 v36; // [sp+116h] [bp-22h]@10
+  char v37; // [sp+118h] [bp-20h]@10
+  char v38; // [sp+119h] [bp-1Fh]@10
+  __int16 v39; // [sp+11Ah] [bp-1Eh]@10
+  __int16 v40; // [sp+11Ch] [bp-1Ch]@10
+  void *ptr; // [sp+120h] [bp-18h]@10
+  unsigned __int16 *v42; // [sp+124h] [bp-14h]@8
+  int v43; // [sp+128h] [bp-10h]@4
+  char v44; // [sp+12Fh] [bp-9h]@25
+  char *i; // [sp+130h] [bp-8h]@10
+  unsigned __int8 v46; // [sp+137h] [bp-1h]@17
+
+  v2 = this;
+  v3 = 0;
+  if ( !this->pRenderD3D || this->field_40110 )
+  {
+    ++dword_4EFA84;
+    File = fopen(a1, "wb");
+    if ( File )
+    {
+      v4 = v2->field_10;
+      v5 = (char *)v2->field_14;
+      v25 = v4;
+      a1 = v5;
+      v43 = v4;
+      if ( v4 & 1 )
+        v43 = v4 + 1;
+      if ( v2->pRenderD3D )
+      {
+        memset(&Dst, 0, 0x7Cu);
+        Dst = 124;
+        if ( !pRenderer->LockSurface_DDraw4(pRenderer->pBackBuffer4, (DDSURFACEDESC2 *)&Dst, 1u) )
+          return;
+        v42 = v20;
+        v6 = v19 >> 1;
+        v3 = 0;
+      }
+      else
+      {
+        pRenderer->BeginScene();
+        v42 = pRenderer->pTargetSurface;
+        v6 = pRenderer->uTargetSurfacePitch;
+      }
+      i = (char *)v6;
+      v33 = v25 - 1;
+      v31 = v3;
+      v34 = (short)a1 - 1;
+      v32 = v3;
+      v39 = v43;
+      memset(&v21, 0, 0x30u);
+      memset(&v16, 0, 0x38u);
+      v37 = 0;
+      Str = 10;
+      v17 = 0;
+      v7 = File;
+      v28 = 5;
+      v29 = 1;
+      v30 = 8;
+      v35 = 75;
+      v36 = 75;
+      v38 = 3;
+      v40 = 1;
+      fwrite(&Str, 1u, 1u, File);
+      fwrite(&v28, 1u, 1u, v7);
+      fwrite(&v29, 1u, 1u, v7);
+      fwrite(&v30, 1u, 1u, v7);
+      fwrite(&v31, 2u, 1u, v7);
+      fwrite(&v32, 2u, 1u, v7);
+      fwrite(&v33, 2u, 1u, v7);
+      fwrite(&v34, 2u, 1u, v7);
+      fwrite(&v35, 2u, 1u, v7);
+      fwrite(&v36, 2u, 1u, v7);
+      fwrite(&v21, 0x30u, 1u, v7);
+      fwrite(&v37, 1u, 1u, v7);
+      fwrite(&v38, 1u, 1u, v7);
+      fwrite(&v39, 2u, 1u, v7);
+      fwrite(&v40, 2u, 1u, v7);
+      fwrite(&v16, 0x3Au, 1u, v7);
+      ptr = pAllocator->AllocNamedChunk(0, 3 * v25 + 6, 0);
+      if ( (signed int)a1 > 0 )
+      {
+        v8 = v43;
+        File = (FILE *)a1;
+        v24 = 3 * v43;
+        v22 = 2 * (int)i;
+        v9 = (int)v42;
+        while ( 1 )
+        {
+          a1 = (const char *)v9;
+          v10 = 0;
+          if ( v25 > 0 )
+          {
+            i = (char *)ptr + v8;
+            v23 = (char *)ptr + 2 * v43;
+            do
+            {
+              *((char *)ptr + v10) = (signed int)(v2->uTargetRMask & *(short *)a1) >> (LOBYTE(v2->uTargetGBits)
+                                                                                      + LOBYTE(v2->uTargetBBits)
+                                                                                      + v2->uTargetRBits
+                                                                                      - 8);
+              i[v10] = (signed int)(v2->uTargetGMask & *(short *)a1) >> (LOBYTE(v2->uTargetBBits)
+                                                                       + LOBYTE(v2->uTargetGBits)
+                                                                       - 8);
+              v11 = a1;
+              v12 = LOBYTE(v2->uTargetBMask);
+              a1 += 2;
+              v23[v10++] = ((unsigned __int8)*v11 & v12) << (8 - LOBYTE(v2->uTargetBBits));
+            }
+            while ( v10 < v25 );
+          }
+          for ( i = 0; (signed int)i < v24; i += BYTE3(a1) )
+          {
+            BYTE3(a1) = 1;
+            v46 = *((char *)ptr + (int)i);
+            do
+            {
+              v13 = (signed int)&i[BYTE3(a1)];
+              if ( *((char *)ptr + v13) != v46 )
+                break;
+              if ( !(v13 % v43) )
+                break;
+              ++BYTE3(a1);
+            }
+            while ( BYTE3(a1) < 0x3Fu );
+            if ( (signed int)&i[BYTE3(a1)] > v24 )
+              BYTE3(a1) = 3 * v43 - (char)i;
+            if ( BYTE3(a1) > 1u || v46 >= 0xC0u )
+            {
+              v44 = BYTE3(a1) | 0xC0;
+              fwrite(&v44, 1u, 1u, v7);
+            }
+            fwrite(&v46, 1u, 1u, v7);
+          }
+          v9 = (int)&v42[v22 / 2];
+          v14 = File == (FILE *)1;
+          File = (FILE *)((char *)File - 1);
+          v42 = (unsigned __int16 *)((char *)v42 + v22);
+          if ( v14 )
+            break;
+          v8 = v43;
+        }
+      }
+      if ( v2->pRenderD3D )
+      {
+        ErrD3D(pRenderer->pBackBuffer4->Unlock(0));
+      }
+      else
+      {
+        pRenderer->EndScene();
+      }
+      pAllocator->FreeChunk(ptr);
+      fclose(v7);
+    }
+  }
+}
+// 4EFA84: using guessed type int dword_4EFA84;
+
+
+
+//----- (0049F5A2) --------------------------------------------------------
+int Render::_49F5A2(int a2, int a3, int a4, void *Dst, int a6, int a7)
+{
+  Render *v7; // ebx@1
+  void *v8; // esi@3
+  void *v9; // esi@3
+  int v10; // ecx@4
+  int v11; // eax@4
+  int v12; // eax@6
+  int v13; // eax@8
+  int v14; // ecx@8
+  signed int v15; // eax@11
+  char v16; // zf@20
+  int result; // eax@21
+  char v18[58]; // [sp+Ch] [bp-ACh]@3
+ // __int16 v19; // [sp+44h] [bp-74h]@3
+  char v20[48]; // [sp+48h] [bp-70h]@3
+  char *v21; // [sp+78h] [bp-40h]@7
+  char *v22; // [sp+7Ch] [bp-3Ch]@7
+  int v23; // [sp+80h] [bp-38h]@4
+  int v24; // [sp+84h] [bp-34h]@4
+  int v25; // [sp+88h] [bp-30h]@4
+  int v26; // [sp+8Ch] [bp-2Ch]@4
+  char Src; // [sp+90h] [bp-28h]@3
+  char v28; // [sp+91h] [bp-27h]@3
+  char v29; // [sp+92h] [bp-26h]@3
+  char v30; // [sp+93h] [bp-25h]@3
+  __int16 v31; // [sp+94h] [bp-24h]@3
+  __int16 v32; // [sp+96h] [bp-22h]@3
+  __int16 v33; // [sp+98h] [bp-20h]@3
+  __int16 v34; // [sp+9Ah] [bp-1Eh]@3
+  __int16 v35; // [sp+9Ch] [bp-1Ch]@3
+  __int16 v36; // [sp+9Eh] [bp-1Ah]@3
+  char v37; // [sp+A0h] [bp-18h]@3
+  char v38; // [sp+A1h] [bp-17h]@3
+  __int16 v39; // [sp+A2h] [bp-16h]@3
+  __int16 v40; // [sp+A4h] [bp-14h]@3
+  void *ptr; // [sp+A8h] [bp-10h]@3
+  int v42; // [sp+ACh] [bp-Ch]@1
+  char v43; // [sp+B3h] [bp-5h]@18
+  int i; // [sp+B4h] [bp-4h]@6
+
+  v7 = this;
+  v42 = a3;
+  if ( a3 & 1 )
+    v42 = a3 + 1;
+  v31 = 0;
+  v32 = 0;
+  v33 = a3 - 1;
+  v34 = a4 - 1;
+  v39 = v42;
+  memset(&v20, 0, 0x30u);
+  memset(&v18, 0, 0x38u);
+  v8 = Dst;
+  v37 = 0;
+  *(_WORD *)&v18[56] = 0;
+  Src = 10;
+  v28 = 5;
+  v29 = 1;
+  v30 = 8;
+  v35 = 75;
+  v36 = 75;
+  v38 = 3;
+  v40 = 1;
+  memcpy(Dst, &Src, 1u);
+  v8 = (char *)v8 + 1;
+  memcpy(v8, &v28, 1u);
+  v8 = (char *)v8 + 1;
+  memcpy(v8, &v29, 1u);
+  v8 = (char *)v8 + 1;
+  memcpy(v8, &v30, 1u);
+  v8 = (char *)v8 + 1;
+  memcpy(v8, &v31, 2u);
+  v8 = (char *)v8 + 2;
+  memcpy(v8, &v32, 2u);
+  v8 = (char *)v8 + 2;
+  memcpy(v8, &v33, 2u);
+  v8 = (char *)v8 + 2;
+  memcpy(v8, &v34, 2u);
+  v8 = (char *)v8 + 2;
+  memcpy(v8, &v35, 2u);
+  v8 = (char *)v8 + 2;
+  memcpy(v8, &v36, 2u);
+  v8 = (char *)v8 + 2;
+  memcpy(v8, &v20, 0x30u);
+  v8 = (char *)v8 + 48;
+  memcpy(v8, &v37, 1u);
+  v8 = (char *)v8 + 1;
+  memcpy(v8, &v38, 1u);
+  v8 = (char *)v8 + 1;
+  memcpy(v8, &v39, 2u);
+  v8 = (char *)v8 + 2;
+  memcpy(v8, &v40, 2u);
+  v8 = (char *)v8 + 2;
+  memcpy(v8, &v18, 0x3Au);
+  v9 = (char *)v8 + 58;
+  ptr = pAllocator->AllocNamedChunk(0, 3 * a3 + 6, 0);
+  if ( a4 > 0 )
+  {
+    v10 = v42;
+    v25 = a4;
+    v26 = 3 * v42;
+    v23 = 2 * a3;
+    v11 = a2;
+    v24 = a2;
+    while ( 1 )
+    {
+      a4 = v11;
+      v12 = 0;
+      i = 0;
+      if ( a3 > 0 )
+      {
+        v21 = (char *)ptr + v10;
+        v22 = (char *)ptr + 2 * v42;
+        do
+        {
+          *((char *)ptr + v12) = (signed int)(v7->uTargetRMask & *(short *)a4) >> (LOBYTE(v7->uTargetGBits)
+                                                                                  + LOBYTE(v7->uTargetBBits)
+                                                                                  + v7->uTargetRBits
+                                                                                  - 8);
+          v13 = i;
+          v21[i] = (signed int)(v7->uTargetGMask & *(short *)a4) >> (LOBYTE(v7->uTargetBBits)
+                                                                   + LOBYTE(v7->uTargetGBits)
+                                                                   - 8);
+          v14 = a4;
+          a4 += 2;
+          v22[v13] = (v7->uTargetBMask & *(char *)v14) << (8 - LOBYTE(v7->uTargetBBits));
+          v12 = v13 + 1;
+          i = v12;
+        }
+        while ( v12 < a3 );
+      }
+      for ( i = 0; i < v26; v9 = (char *)v9 + 1 )
+      {
+        BYTE3(a4) = 1;
+        BYTE3(a2) = *((char *)ptr + i);
+        do
+        {
+          v15 = i + BYTE3(a4);
+          if ( *((char *)ptr + v15) != BYTE3(a2) )
+            break;
+          if ( !(v15 % v42) )
+            break;
+          ++BYTE3(a4);
+        }
+        while ( BYTE3(a4) < 0x3Fu );
+        if ( i + BYTE3(a4) > v26 )
+          BYTE3(a4) = 3 * v42 - i;
+        if ( BYTE3(a4) > 1u || BYTE3(a2) >= 0xC0u )
+        {
+          v43 = BYTE3(a4) | 0xC0;
+          memcpy(v9, &v43, 1u);
+          v9 = (char *)v9 + 1;
+        }
+        memcpy(v9, (char *)&a2 + 3, 1u);
+        i += BYTE3(a4);
+      }
+      v11 = v23 + v24;
+      v16 = v25-- == 1;
+      v24 += v23;
+      if ( v16 )
+        break;
+      v10 = v42;
+    }
+  }
+  pAllocator->FreeChunk(ptr);
+  result = a7;
+  *(int *)a7 = (char *)v9 - Dst;
+  return result;
+}
+
+
+//----- (0049F8B5) --------------------------------------------------------
+FILE *Render::SavePCXImage(const char *Filename, char *a3, int a4, int a5)
+{
+  Render *v5; // esi@1
+  FILE *result; // eax@1
+  FILE *v7; // edi@4
+  int v8; // ecx@5
+  int v9; // eax@5
+  int v10; // eax@7
+  int v11; // ecx@9
+  signed int v12; // eax@12
+  char v13; // zf@21
+  char v14[56]; // [sp+4h] [bp-A0h]@4
+  __int16 v15; // [sp+3Ch] [bp-68h]@4
+  char color_map[48]; // [sp+40h] [bp-64h]@4
+  int v17; // [sp+70h] [bp-34h]@5
+  int v18; // [sp+74h] [bp-30h]@5
+  char *v19; // [sp+78h] [bp-2Ch]@5
+  int v20; // [sp+7Ch] [bp-28h]@5
+  PCXHeader_1 header1; // [sp+80h] [bp-24h]@4
+  PCXHeader_2 header2; // [sp+90h] [bp-14h]@4
+  void *ptr; // [sp+98h] [bp-Ch]@4
+  int v24; // [sp+9Ch] [bp-8h]@2
+  char *i; // [sp+A0h] [bp-4h]@8
+
+  v5 = this;
+  result = fopen(Filename, "wb");
+  Filename = (const char *)result;
+  if ( result )
+  {
+    v24 = a4;
+    if ( a4 & 1 )
+      v24 = a4 + 1;
+    header1.left = 0;
+    header1.up = 0;
+    header1.right = a4 - 1;
+    header1.bottom = a5 - 1;
+    header2.pitch = v24;
+    memset(color_map, 0, sizeof(color_map));
+    header2.reserved = 0;
+    memset(v14, 0, sizeof(v14));
+    v15 = 0;
+    header1.manufacturer = 10;
+    header1.version = 5;
+    header1.encoding = 1;
+    header1.bpp = 8;
+    header1.hdpi = 75;
+    header1.vdpi = 75;
+    header2.planes = 3;
+    header2.palette_info = 1;
+    fwrite(&header1, 1u, 1u, (FILE *)Filename);
+    v7 = (FILE *)Filename;
+    fwrite(&header1.version, 1u, 1u, (FILE *)Filename);
+    fwrite(&header1.encoding, 1u, 1u, v7);
+    fwrite(&header1.bpp, 1u, 1u, v7);
+    fwrite(&header1.left, 2u, 1u, v7);
+    fwrite(&header1.up, 2u, 1u, v7);
+    fwrite(&header1.right, 2u, 1u, v7);
+    fwrite(&header1.bottom, 2u, 1u, v7);
+    fwrite(&header1.hdpi, 2u, 1u, v7);
+    fwrite(&header1.vdpi, 2u, 1u, v7);
+    fwrite(color_map, 0x30u, 1u, v7);
+    fwrite(&header2, 1u, 1u, v7);
+    fwrite(&header2.planes, 1u, 1u, v7);
+    fwrite(&header2.pitch, 2u, 1u, v7);
+    fwrite(&header2.palette_info, 2u, 1u, v7);
+    fwrite(v14, 0x3Au, 1u, v7);
+    ptr = pAllocator->AllocNamedChunk(0, 3 * a4 + 6, 0);
+    if ( a5 > 0 )
+    {
+      v8 = v24;
+      v18 = a5;
+      v20 = 3 * v24;
+      v17 = 2 * a4;
+      v9 = (int)a3;
+      v19 = a3;
+      while ( 1 )
+      {
+        a5 = v9;
+        v10 = 0;
+        if ( a4 > 0 )
+        {
+          a3 = (char *)ptr + v8;
+          i = (char *)ptr + 2 * v24;
+          do
+          {
+            *((char *)ptr + v10) = (signed int)(v5->uTargetRMask & *(short *)a5) >> (LOBYTE(v5->uTargetGBits)
+                                                                                    + LOBYTE(v5->uTargetBBits)
+                                                                                    + v5->uTargetRBits
+                                                                                    - 8);
+            a3[v10] = (signed int)(v5->uTargetGMask & *(short *)a5) >> (LOBYTE(v5->uTargetBBits)
+                                                                      + LOBYTE(v5->uTargetGBits)
+                                                                      - 8);
+            v11 = a5;
+            a5 += 2;
+            i[v10++] = (v5->uTargetBMask & *(char *)v11) << (8 - LOBYTE(v5->uTargetBBits));
+          }
+          while ( v10 < a4 );
+        }
+        for ( i = 0; (signed int)i < v20; i += BYTE3(a5) )
+        {
+          BYTE3(a5) = 1;
+          BYTE3(Filename) = *((char *)ptr + (int)i);
+          do
+          {
+            v12 = (signed int)&i[BYTE3(a5)];
+            if ( *((char *)ptr + v12) != BYTE3(Filename) )
+              break;
+            if ( !(v12 % v24) )
+              break;
+            ++BYTE3(a5);
+          }
+          while ( BYTE3(a5) < 0x3Fu );
+          if ( (signed int)&i[BYTE3(a5)] > v20 )
+            BYTE3(a5) = 3 * v24 - (char)i;
+          if ( BYTE3(a5) > 1u || BYTE3(Filename) >= 0xC0u )
+          {
+            BYTE3(a3) = BYTE3(a5) | 0xC0;
+            fwrite((char *)&a3 + 3, 1u, 1u, v7);
+          }
+          fwrite((char *)&Filename + 3, 1u, 1u, v7);
+        }
+        v9 = (int)&v19[v17];
+        v13 = v18-- == 1;
+        v19 += v17;
+        if ( v13 )
+          break;
+        v8 = v24;
+      }
+    }
+    pAllocator->FreeChunk(ptr);
+    result = (FILE *)fclose(v7);
+  }
+  return result;
+}
+
+
+//----- (0049FBCD) --------------------------------------------------------
+void Render::ClearTarget(unsigned int uColor)
+{
+  if (pRenderD3D)
+  {
+    if (field_40110)
+      pRenderD3D->ClearTarget(true, uColor, false, 0.0);
+  }
+  else
+    memset32(pTargetSurface, uColor, field_10 * field_14 / 2);
+}
+
+
+
+//----- (0049FC23) --------------------------------------------------------
+void Render::Release2()
+{
+  Release();
+  bWindowMode = 1;
+}
+
+
+//----- (0049FC37) --------------------------------------------------------
+void Render::Present()
+{
+  Render *v1; // esi@1
+  struct tagRECT Rect; // [sp+8h] [bp-28h]@11
+  RECT a4; // [sp+18h] [bp-18h]@11
+  struct tagPOINT Point; // [sp+28h] [bp-8h]@11
+
+  v1 = this;
+  if ( !pRenderer->pRenderD3D || this->field_40110 )
+  {
+    this->pBeforePresentFunction();
+    if ( v1->pRenderD3D )
+    {
+      if ( v1->field_40110 )
+      {
+        if (pAsyncMouse)
+          pAsyncMouse->_46BAEC();
+        pRenderD3D->Present(false);
+        if (pAsyncMouse)
+          pAsyncMouse->_46BB0A();
+      }
+    }
+    else
+    {
+      if ( v1->bWindowMode )
+      {
+        RestoreFrontBuffer();
+        GetClientRect(v1->hWnd, &Rect);
+        Point.y = 0;
+        Point.x = 0;
+        ClientToScreen(v1->hWnd, &Point);
+        OffsetRect(&Rect, Point.x, Point.y);
+        a4.top = 0;
+        a4.bottom = 480;
+        a4.left = 0;
+        a4.right = 640;
+        PresentRect(&Rect, &a4);
+      }
+      else
+      {
+        RestoreFrontBuffer();
+        a4.top = 0;
+        a4.bottom = 480;
+        a4.left = 0;
+        a4.right = 640;
+        BltBackToFontFast(0, 0, &a4);
+      }
+    }
+  }
+}
+
+//----- (0049FD3A) --------------------------------------------------------
+void Render::_49FD3A()
+{
+  Render *v2; // esi@1
+  IDirectDrawSurface4 *v3; // eax@6
+  IDirectDrawSurface4 *v4; // ST0C_4@6
+  RECT v5; // [sp+8h] [bp-10h]@6
+
+  auto a1 = this;
+  v2 = a1;
+  if ( a1->pRenderD3D )
+  {
+    if (pFrontBuffer4->IsLost() == DDERR_SURFACELOST)
+      pFrontBuffer4->Restore();
+    if (pBackBuffer4->IsLost() == DDERR_SURFACELOST)
+      pBackBuffer4->Restore();
+    v3 = v2->pBackBuffer4;
+    v4 = v2->pFrontBuffer4;
+    v5.top = 0;
+    v5.bottom = 480;
+    v5.left = 0;
+    v5.right = 640;
+    v3->BltFast(0, 0, v4, &v5, 16u);
+  }
+}
+
+
+//----- (0049FDBF) --------------------------------------------------------
+void Render::CreateZBuffer()
+{
+  if (!pDefaultZBuffer)
+  {
+    pDefaultZBuffer = pActiveZBuffer = nullptr;
+    pDefaultZBuffer = pActiveZBuffer = (int *)pAllocator->AllocNamedChunk(0, 0x12C000, "Z Buf.");
+    memset32(pActiveZBuffer, 0xFFFF0000u, 0x4B000u);
+  }
+}
+
+
+//----- (0049FE05) --------------------------------------------------------
+void Render::Release()
+{
+  Render *v1; // esi@1
+  RenderD3D *v2; // ecx@1
+  char v3; // zf@4
+  void *v4; // ebx@6
+  IDirectDraw *v5; // eax@10
+  IDirectDrawSurface2 *v6; // eax@11
+  IDirectDrawSurface2 *v7; // eax@13
+  IDirectDrawSurface2 *v8; // eax@15
+  IDirectDraw2 *v9; // eax@17
+  IDirectDraw4 *v10; // eax@19
+  IDirectDrawSurface4 *v11; // eax@20
+  IDirectDrawSurface4 *v12; // eax@22
+  IDirectDrawSurface4 *v13; // eax@24
+  IDirectDraw4 *v14; // eax@26
+  unsigned __int16 **v15; // ebx@28
+  void **v16; // esi@29
+
+  v1 = this;
+  v2 = this->pRenderD3D;
+  if ( v2 )
+  {
+    if ( v1->field_40110 )
+    {
+      pRenderD3D->ClearTarget(1u, 0, 0, 1.0);
+      pRenderD3D->Present(0);
+      pRenderD3D->ClearTarget(1u, 0, 0, 1.0);
+    }
+    v1->pColorKeySurface4 = 0;
+    v1->pBackBuffer4 = 0;
+    v3 = v1->pTargetSurface == 0;
+    v1->pFrontBuffer4 = 0;
+    v1->pDirectDraw4 = 0;
+    if ( !v3 )
+    {
+      free(v1->ptr_400E8);
+      v1->pTargetSurface = 0;
+      v1->ptr_400E8 = 0;
+    }
+    v4 = v1->pRenderD3D;
+    if ( v4 )
+    {
+      pRenderD3D->Release();
+      free(v4);
+    }
+    v1->pRenderD3D = 0;
+  }
+  else
+  {
+    if ( bWinNT4_0 == 1 )
+    {
+      v5 = (IDirectDraw *)v1->pDirectDraw2;
+      if ( !v5 )
+        return;
+      v5->SetCooperativeLevel(v1->hWnd, 8u);
+      v1->pDirectDraw2->FlipToGDISurface();
+      v6 = v1->pSomeSurface2;
+      if ( v6 )
+      {
+        v6->Release();
+        v1->pSomeSurface2 = 0;
+      }
+      v7 = v1->pBackBuffer2;
+      if ( v7 )
+      {
+        v7->Release();
+        v1->pBackBuffer2 = 0;
+      }
+      v8 = v1->pFrontBuffer2;
+      if ( v8 )
+      {
+        v8->Release();
+        v1->pFrontBuffer2 = 0;
+      }
+      v9 = v1->pDirectDraw2;
+      if ( v9 )
+      {
+        v9->Release();
+        v1->pDirectDraw2 = 0;
+      }
+    }
+    else
+    {
+      v10 = v1->pDirectDraw4;
+      if ( !v10 )
+        return;
+      v10->SetCooperativeLevel(v1->hWnd, 1032u);
+      v1->pDirectDraw4->FlipToGDISurface();
+      v11 = v1->pColorKeySurface4;
+      if ( v11 )
+      {
+        v11->Release();
+        v1->pColorKeySurface4 = 0;
+      }
+      v12 = v1->pBackBuffer4;
+      if ( v12 )
+      {
+        v12->Release();
+        v1->pBackBuffer4 = 0;
+      }
+      v13 = v1->pFrontBuffer4;
+      if ( v13 )
+      {
+        v13->Release();
+        v1->pFrontBuffer4 = 0;
+      }
+      v14 = v1->pDirectDraw4;
+      if ( v14 )
+      {
+        v14->Release();
+        v1->pDirectDraw4 = 0;
+      }
+    }
+    v15 = &v1->pTargetSurface;
+    if ( v1->pTargetSurface )
+    {
+      v16 = (void **)&v1->ptr_400E8;
+      free(*v16);
+      *v15 = 0;
+      *v16 = 0;
+    }
+  }
+}
+
+//----- (0049FFD7) --------------------------------------------------------
+void Render::CreateSomeTexture()
+{
+  pRenderD3D->CreateTexture(64, 64, &pSurface, &pTexture, true, false, 32);
+}
+
+//----- (0049FFFB) --------------------------------------------------------
+bool Render::InitializeFullscreen(HWND hWnd)
+{
+  //Render *v2; // esi@1
+  //HWND v3; // ebx@1
+  //void *v4; // eax@2
+  //RenderD3D *v5; // eax@3
+  unsigned int v6; // edx@5
+  RenderD3D__DevInfo *v7; // ecx@5
+  bool v8; // eax@6
+  RenderD3D *v9; // ecx@13
+  unsigned int v10; // eax@13
+  RenderD3D *v11; // eax@25
+  HRESULT v12; // eax@25
+  int v13; // ecx@25
+  int v14; // eax@27
+  signed int v15; // ebx@31
+  bool v16; // eax@35
+  char v17; // zf@35
+  IDirectDraw4 *v18; // eax@38
+  HRESULT v19; // eax@38
+  int *v20; // eax@39
+  int *v22; // eax@42
+  int v23; // ecx@42
+  D3DDEVICEDESC refCaps; // [sp+Ch] [bp-300h]@25
+  DDSURFACEDESC2 pDesc; // [sp+108h] [bp-204h]@40
+  D3DDEVICEDESC halCaps; // [sp+184h] [bp-188h]@25
+  DDSURFACEDESC2 ddsd2; // [sp+280h] [bp-8Ch]@38
+  void *v28; // [sp+2FCh] [bp-10h]@2
+  int v29; // [sp+308h] [bp-4h]@2
+
+  //v2 = this;
+  this->field_40110 = 0;
+  this->pColorKeySurface4 = 0;
+  this->pBackBuffer4 = 0;
+  this->pFrontBuffer4 = 0;
+  this->pDirectDraw4 = 0;
+  this->bColorKeySupported = 0;
+  Release();
+  //v3 = hWnd;
+  this->hWnd = hWnd;
+  CreateZBuffer();
+  if ( bUserDirect3D )
+  {
+    pRenderD3D = new RenderD3D;
+    v28 = pRenderD3D;
+    v6 = uDesiredDirect3DDevice;
+    v29 = -1;
+    v7 = pRenderD3D->pAvailableDevices;
+    if ( v7[v6].bIsDeviceCompatible )
+    {
+      v8 = pRenderD3D->CreateDevice(v6, 0, hWnd);
+      uAcquiredDirect3DDevice = uDesiredDirect3DDevice;
+    }
+    else
+    {
+      if ( v7[1].bIsDeviceCompatible )
+      {
+        v8 = pRenderD3D->CreateDevice(1u, 0, hWnd);
+        uAcquiredDirect3DDevice = 1;
+      }
+      else
+      {
+        if ( !v7->bIsDeviceCompatible )
+          Abortf("There aren't any D3D devices to create.");
+        v8 = pRenderD3D->CreateDevice(0, 0, hWnd);
+        uAcquiredDirect3DDevice = 0;
+      }
+    }
+    if ( !v8 )
+      Abortf("D3Drend->Init failed.");
+    v9 = pRenderD3D;
+    pBackBuffer4 = v9->pBackBuffer;
+    pFrontBuffer4 = v9->pFrontBuffer;
+    pDirectDraw4 = v9->pHost;
+    v10 = pRenderD3D->GetDeviceCaps();
+    if ( v10 & 1 )
+    {
+      if ( pRenderD3D )
+      {
+        pRenderD3D->Release();
+        delete pRenderD3D;
+      }
+      pRenderD3D = 0;
+      pBackBuffer4 = 0;
+      pFrontBuffer4 = 0;
+      pDirectDraw4 = 0;
+      Abortf("Direct3D renderer:  The device failed to return capabilities.");
+    }
+    if ( v10 & 0x3E )
+    {
+      if ( pRenderD3D )
+      {
+        pRenderD3D->Release();
+        delete pRenderD3D;
+      }
+      pColorKeySurface4 = 0;
+      pRenderD3D = 0;
+      pBackBuffer4 = 0;
+      pFrontBuffer4 = 0;
+      pDirectDraw4 = 0;
+      Abortf("Direct3D renderer:  The device doesn't support the necessary alpha blending modes.");
+    }
+    if ( (v10 & 0x80u) != 0 )
+    {
+      if ( pRenderD3D )
+      {
+        pRenderD3D->Release();
+        delete pRenderD3D;
+      }
+      pRenderD3D = 0;
+      pBackBuffer4 = 0;
+      pFrontBuffer4 = 0;
+      pDirectDraw4 = 0;
+      Abortf("Direct3D renderer:  The device doesn't support non-square textures.");
+    }
+    LOBYTE(field_10365C) = ~(unsigned __int8)(v10 >> 6) & 1;
+    bRequiredTextureStagesAvailable = CheckTextureStages();
+    memset(&halCaps, 0, 0xFCu);
+    halCaps.dwSize = 252;
+    memset(&refCaps, 0, 0xFCu);
+    v11 = pRenderD3D;
+    refCaps.dwSize = 252;
+    ErrD3D(v11->pDevice->GetCaps(&halCaps, &refCaps));
+    v13 = halCaps.dwMinTextureWidth;
+    if ( (unsigned int)halCaps.dwMinTextureWidth >= halCaps.dwMinTextureHeight )
+      v13 = halCaps.dwMinTextureHeight;
+    v14 = halCaps.dwMaxTextureWidth;
+    uMinDeviceTextureDim = v13;
+    if ( (unsigned int)v14 < halCaps.dwMaxTextureHeight )
+      v14 = halCaps.dwMaxTextureHeight;
+    uMaxDeviceTextureDim = v14;
+    if ( (unsigned int)v13 < 4 )
+      uMinDeviceTextureDim = 4;
+    CreateSomeTexture();
+    v15 = 1;
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, false));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, false));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MINFILTER, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, 3u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, 0));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, 0));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLOROP, 4u));
+  }
+  else
+  {
+    CreateDirectDraw();
+    SetDirectDrawCooperationMode(hWnd, 1);
+    SetDirectDrawDisplayMode(640u, 480u, 16u);
+    CreateDirectDrawPrimarySurface();
+    v15 = 1;
+  }
+  ddpfPrimareSuface.dwSize = 32;
+  GetTargetPixelFormat(&ddpfPrimareSuface);
+  ParseTargetPixelFormat();
+  _49EBF1();
+  if ( pRenderD3D )
+  {
+    v16 = IsColorKeySupported(pDirectDraw4);
+    v17 = uAcquiredDirect3DDevice == v15;
+    bColorKeySupported = v16;
+    if ( !v17 )
+      bColorKeySupported = 0;
+    if ( bColorKeySupported )
+    {
+      memset(&ddsd2, 0, 0x7Cu);
+      ddsd2.ddckCKSrcBlt.dwColorSpaceLowValue = uTargetGMask | uTargetBMask;
+      ddsd2.ddckCKSrcBlt.dwColorSpaceHighValue = ddsd2.ddckCKSrcBlt.dwColorSpaceLowValue;
+      v18 = pDirectDraw4;
+      ddsd2.dwSize = 124;
+      ddsd2.dwFlags = 65543;
+      ddsd2.ddsCaps.dwCaps = 2112;
+      ddsd2.dwWidth = 640;
+      ddsd2.dwHeight = 480;
+      ErrD3D(v18->CreateSurface(&ddsd2, &pColorKeySurface4, 0));
+      pBeforePresentFunction = Present_ColorKey;
+    }
+    else
+    {
+      pTargetSurface = 0;
+      ptr_400E8 = 0;
+      v20 = (int *)operator new(0x96020u);
+      ptr_400E8 = v20;
+      if ( !v20
+        || (memset(&pDesc, 0, 0x7Cu),
+            pDesc.dwSize = 124,
+            !pRenderer->LockSurface_DDraw4(pRenderer->pBackBuffer4, &pDesc, v15)) )
+        return 0;
+      pBackBuffer4->Unlock(0);
+      v22 = ptr_400E8 + 4;
+      v23 = (unsigned int)pDesc.lpSurface & 7;
+      LOBYTE(v22) = (unsigned __int8)v22 & 0xF8;
+      uTargetSurfacePitch = 640;
+      pBeforePresentFunction = Present_NoColorKey;
+      v15 = 1;
+      pTargetSurface = (unsigned __int16 *)((char *)v22 + 2 * v23);
+    }
+    field_40110 = v15;
+  }
+  else
+  {
+    pBeforePresentFunction = 0;//nullsub_1;
+  }
+  bWindowMode = 0;
+  pParty->uFlags |= 2u;
+  LODWORD(flt_6BE3A0) = 0x3F0CCCCDu;
+  pViewport->_4C02F8(36044);
+  return v15;
+}
+// 6BE3A0: using guessed type float flt_6BE3A0;
+
+
+//----- (004A05F3) --------------------------------------------------------
+bool Render::SwitchToWindow(HWND hWnd)
+{
+  //Render *v2; // esi@1
+  //void *v3; // eax@2
+  //RenderD3D *v4; // eax@3
+  //unsigned int v5; // edx@5
+  //RenderD3D__DevInfo *v6; // ecx@5
+  bool v7; // eax@7
+  //RenderD3D *v8; // ecx@12
+  unsigned int v9; // eax@12
+  RenderD3D *v10; // eax@24
+  HRESULT v11; // eax@24
+  int v12; // eax@24
+  int v13; // eax@26
+  bool v14; // eax@32
+  char v15; // zf@32
+  IDirectDraw4 *v16; // eax@35
+  HRESULT v17; // eax@35
+  int *v18; // eax@36
+  int *v19; // edx@38
+  int v20; // eax@38
+  unsigned int v21; // ecx@38
+  int v22; // eax@41
+  D3DDEVICEDESC refCaps; // [sp+Ch] [bp-300h]@24
+  DDSURFACEDESC2 pDesc; // [sp+108h] [bp-204h]@37
+  D3DDEVICEDESC halCaps; // [sp+184h] [bp-188h]@24
+  DDSURFACEDESC2 ddsd2; // [sp+280h] [bp-8Ch]@35
+  //RenderD3D *thisa; // [sp+2FCh] [bp-10h]@2
+  int v29; // [sp+308h] [bp-4h]@2
+
+  pParty->uFlags |= 2u;
+  //v2 = this;
+  flt_6BE3A0 = 0.55000001f;
+  pViewport->_4C02F8(36044);
+  field_40110 = 0;
+  Release();
+  pColorKeySurface4 = 0;
+  pBackBuffer4 = 0;
+  pFrontBuffer4 = 0;
+  pDirectDraw4 = 0;
+  bColorKeySupported = 0;
+  CreateZBuffer();
+  if ( bUserDirect3D )
+  {
+    /*v3 = operator new(0x148u);
+    thisa = (RenderD3D *)v3;
+    v29 = 0;
+    if ( v3 )
+      v4 = RenderD3D::RenderD3D((RenderD3D *)v3);
+    else
+      v4 = 0;*/
+    pRenderD3D = new RenderD3D;
+    //v4 = pRenderD3D;
+    //v5 = uDesiredDirect3DDevice;
+    v29 = -1;
+    //v6 = pRenderD3D->pAvailableDevices;
+    if (pRenderD3D->pAvailableDevices[uDesiredDirect3DDevice].bIsDeviceCompatible &&
+        uDesiredDirect3DDevice != 1 )
+    {
+      v7 = pRenderD3D->CreateDevice(uDesiredDirect3DDevice, 1, hWnd);
+      uAcquiredDirect3DDevice = uDesiredDirect3DDevice;
+    }
+    else
+    {
+      if ( !pRenderD3D->pAvailableDevices[0].bIsDeviceCompatible )
+        Abortf("There aren't any D3D devices to init.");
+      v7 = pRenderD3D->CreateDevice(0, 1, hWnd);
+      uAcquiredDirect3DDevice = 0;
+    }
+    if ( !v7 )
+      Abortf("D3Drend->Init failed.");
+
+    //v8 = pRenderD3D;
+    pColorKeySurface4 = 0;
+    pBackBuffer4 = pRenderD3D->pBackBuffer;
+    pFrontBuffer4 = pRenderD3D->pFrontBuffer;
+    pDirectDraw4 = pRenderD3D->pHost;
+    v9 = pRenderD3D->GetDeviceCaps();
+    if ( v9 & 1 )
+    {
+      if (pRenderD3D)
+      {
+        pRenderD3D->Release();
+        delete pRenderD3D;
+      }
+      pRenderD3D = 0;
+      pBackBuffer4 = 0;
+      pFrontBuffer4 = 0;
+      pDirectDraw4 = 0;
+      Abortf("Direct3D renderer:  The device failed to return capabilities.");
+    }
+    if ( v9 & 0x3E )
+    {
+      if (pRenderD3D)
+      {
+        pRenderD3D->Release();
+        delete pRenderD3D;
+      }
+      pColorKeySurface4 = 0;
+      pRenderD3D = 0;
+      pBackBuffer4 = 0;
+      pFrontBuffer4 = 0;
+      pDirectDraw4 = 0;
+      Abortf("Direct3D renderer:  The device doesn't support the necessary alpha blending modes.");
+    }
+    if ( (v9 & 0x80u) != 0 )
+    {
+      if (pRenderD3D)
+      {
+        pRenderD3D->Release();
+        delete pRenderD3D;
+      }
+      pRenderD3D = 0;
+      pBackBuffer4 = 0;
+      pFrontBuffer4 = 0;
+      pDirectDraw4 = 0;
+      Abortf("Direct3D renderer:  The device doesn't support non-square textures.");
+    }
+    LOBYTE(field_10365C) = ~(unsigned __int8)(v9 >> 6) & 1;
+    bRequiredTextureStagesAvailable = CheckTextureStages();
+    memset(&halCaps, 0, 0xFCu);
+    halCaps.dwSize = 252;
+    memset(&refCaps, 0, 0xFCu);
+    //v10 = v2->pRenderD3D;
+    refCaps.dwSize = 252;
+    ErrD3D(pRenderD3D->pDevice->GetCaps(&halCaps, &refCaps));
+    v12 = halCaps.dwMinTextureWidth;
+    if ( (unsigned int)halCaps.dwMinTextureWidth >= halCaps.dwMinTextureHeight )
+      v12 = halCaps.dwMinTextureHeight;
+    uMinDeviceTextureDim = v12;
+    v13 = halCaps.dwMaxTextureWidth;
+    if ( (unsigned int)halCaps.dwMaxTextureWidth < halCaps.dwMaxTextureHeight )
+      v13 = halCaps.dwMaxTextureHeight;
+    uMaxDeviceTextureDim = v13;
+    CreateSomeTexture();
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, 1u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, 0));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, 0));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MINFILTER, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, 3u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, 0));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, 2u));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, 0));
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLOROP, 4u));
+  }
+  else
+  {
+    CreateDirectDraw();
+    SetDirectDrawCooperationMode(hWnd, 0);
+    field_4004C = 1;
+    CreateFrontBuffer();
+    CreateClipper(hWnd);
+    CreateBackBuffer();
+    field_40030 = 0;
+    field_18_locked_pitch = 0;
+  }
+  ddpfPrimareSuface.dwSize = 32;
+  GetTargetPixelFormat(&ddpfPrimareSuface);
+  ParseTargetPixelFormat();
+  _49EBF1();
+  if ( !pRenderD3D )
+  {
+    pBeforePresentFunction = 0;//nullsub_1;
+    goto LABEL_47;
+  }
+  v14 = IsColorKeySupported(pDirectDraw4);
+  v15 = uAcquiredDirect3DDevice == 1;
+  bColorKeySupported = v14;
+  if ( !v15 )
+    bColorKeySupported = 0;
+  if ( bColorKeySupported )
+  {
+    memset(&ddsd2, 0, 0x7Cu);
+    ddsd2.ddckCKSrcBlt.dwColorSpaceLowValue = uTargetGMask | uTargetBMask;
+    ddsd2.ddckCKSrcBlt.dwColorSpaceHighValue = ddsd2.ddckCKSrcBlt.dwColorSpaceLowValue;
+    v16 = pDirectDraw4;
+    ddsd2.dwSize = 124;
+    ddsd2.dwFlags = 65543;
+    ddsd2.ddsCaps.dwCaps = 2112;
+    ddsd2.dwWidth = 640;
+    ddsd2.dwHeight = 480;
+    ErrD3D(v16->CreateSurface(&ddsd2, &pColorKeySurface4, 0));
+    pBeforePresentFunction = Present_ColorKey;
+LABEL_45:
+    field_40110 = 1;
+LABEL_47:
+    bWindowMode = 1;
+    hWnd = hWnd;
+    return 0;
+  }
+  pTargetSurface = 0;
+  ptr_400E8 = 0;
+  v18 = (int *)new char[0x96020];
+  memset(v18, -1, 0x96020);
+  ptr_400E8 = v18;
+  if ( v18 )
+  {
+    memset(&pDesc, 0, 0x7Cu);
+    pDesc.dwSize = 124;
+    if ( pRenderer->LockSurface_DDraw4(pRenderer->pBackBuffer4, &pDesc, 1u) )
+    {
+      pRenderer->pBackBuffer4->Unlock(0);
+      v19 = ptr_400E8;
+      v20 = (unsigned int)pDesc.lpSurface & 7;
+      v21 = (unsigned int)ptr_400E8 & 7;
+      if ( v21 == v20 )
+      {
+        pTargetSurface = (unsigned __int16 *)v19;
+      }
+      else
+      {
+        if ( (signed int)v21 >= v20 )
+          v22 = (int)((char *)v19 + 2 * (v21 - v20) + 16);
+        else
+          v22 = (int)((char *)v19 + 2 * (v20 - v21) + 16);
+        pTargetSurface = (unsigned __int16 *)v22;
+      }
+      uTargetSurfacePitch = 640;
+      pBeforePresentFunction = Present_NoColorKey;
+      goto LABEL_45;
+    }
+  }
+  return 0;
+}
+
+
+//----- (004A0BEE) --------------------------------------------------------
+char Render::Line2D(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW, unsigned __int16 uColor)
+{
+  int v6; // edi@1
+  int v7; // edx@5
+  unsigned int v8; // ebx@5
+  int v9; // eax@7
+  unsigned int v10; // ecx@9
+  unsigned int v11; // esi@13
+  int v12; // eax@17
+  int v13; // eax@21
+  Render *v14; // edi@21
+  int v15; // eax@25
+  int v16; // eax@27
+  signed int v17; // eax@28
+  signed int v18; // edi@30
+  signed __int64 v19; // qax@41
+  int v20; // edi@41
+  unsigned int v21; // edi@46
+  int v22; // esi@47
+  int v23; // ebx@47
+  signed int v24; // edx@50
+  signed int v25; // esi@52
+  unsigned __int16 *v26; // ecx@52
+  int v27; // ebx@54
+  int v28; // edi@55
+  int v29; // edx@55
+  int v30; // ebx@60
+  int v31; // edx@61
+  int v32; // edi@61
+  int v34; // [sp+Ch] [bp-10h]@3
+  Render *v35; // [sp+10h] [bp-Ch]@1
+  __int64 v36; // [sp+14h] [bp-8h]@1
+  signed int v37; // [sp+18h] [bp-4h]@28
+  unsigned int uXa; // [sp+24h] [bp+8h]@49
+  unsigned int uYa; // [sp+28h] [bp+Ch]@28
+  int uYb; // [sp+28h] [bp+Ch]@47
+  int uZa; // [sp+2Ch] [bp+10h]@38
+
+  v36 = 0i64;
+  v6 = this->field_1C_clipx;
+  v35 = this;
+  if ( (signed int)uX < v6 )
+    HIDWORD(v36) = 8;
+  v34 = this->field_24_clipz;
+  if ( (signed int)uX > this->field_24_clipz )
+    HIDWORD(v36) |= 4u;
+  v7 = this->field_20_clipy;
+  v8 = uY;
+  if ( (signed int)uY < v7 )
+    HIDWORD(v36) |= 2u;
+  v9 = this->field_28_clipw;
+  if ( (signed int)uY > v9 )
+    HIDWORD(v36) |= 1u;
+  v10 = uZ;
+  if ( (signed int)uZ < v6 )
+    LODWORD(v36) = 8;
+  if ( (signed int)uZ > v34 )
+    LODWORD(v36) = v36 | 4;
+  v11 = uW;
+  if ( (signed int)uW < v7 )
+    LODWORD(v36) = v36 | 2;
+  if ( (signed int)uW > v9 )
+    LODWORD(v36) = v36 | 1;
+  LOBYTE(v12) = v36;
+  if ( (unsigned int)v36 & HIDWORD(v36) )
+    return v12;
+  if ( !v36 )
+  {
+LABEL_46:
+    v21 = pRenderer->uTargetSurfacePitch;
+    if ( pRenderer->uTargetSurfacePitch )
+    {
+      v12 = uX + v8 * pRenderer->uTargetSurfacePitch;
+      v22 = v11 - v8;
+      v23 = v22;
+      uYb = v22;
+      if ( v22 < 0 )
+      {
+        v23 = -v22;
+        uYb = -v22;
+        v21 = -pRenderer->uTargetSurfacePitch;
+      }
+      uXa = v10 - uX;
+      if ( (uXa & 0x80000000u) == 0 )
+      {
+        v24 = 1;
+      }
+      else
+      {
+        uXa = -uXa;
+        v24 = -1;
+      }
+      v25 = 0;
+      v26 = v35->pTargetSurface;
+      if ( v26 )
+      {
+        if ( (signed int)uXa <= v23 )
+        {
+          v30 = v23 + 1;
+          if ( v30 > 0 )
+          {
+            v31 = 2 * v24;
+            v32 = 2 * v21;
+            v12 = (int)&v26[v12];
+            do
+            {
+              v25 += uXa;
+              *(short *)v12 = uColor;
+              v12 += v32;
+              if ( v25 > 0 )
+              {
+                v25 -= uYb;
+                v12 += v31;
+              }
+              --v30;
+            }
+            while ( v30 );
+          }
+        }
+        else
+        {
+          v27 = uXa + 1;
+          if ( (signed int)(uXa + 1) > 0 )
+          {
+            v28 = 2 * v21;
+            v29 = 2 * v24;
+            v12 = (int)&v26[v12];
+            do
+            {
+              v25 += uYb;
+              *(short *)v12 = uColor;
+              v12 += v29;
+              if ( v25 > (signed int)uXa )
+              {
+                v25 -= uXa;
+                v12 += v28;
+              }
+              --v27;
+            }
+            while ( v27 );
+          }
+        }
+      }
+    }
+    return v12;
+  }
+  if ( (BYTE4(v36) ^ (unsigned __int8)v36) & 8 )
+  {
+    if ( BYTE4(v36) & 8 )
+    {
+      v13 = (signed int)((uW - uY) * (v6 - uX)) / (signed int)(uZ - uX);
+      v14 = v35;
+      v8 = v13 + uY;
+      uX = v35->field_1C_clipx;
+      goto LABEL_24;
+    }
+    v10 = v6;
+    v11 = (signed int)((uY - uW) * (v6 - uZ)) / (signed int)(uX - uZ) + uW;
+  }
+  v14 = v35;
+LABEL_24:
+  if ( (BYTE4(v36) ^ (unsigned __int8)v36) & 4 )
+  {
+    v15 = v14->field_24_clipz;
+    if ( BYTE4(v36) & 4 )
+    {
+      v14 = v35;
+      v8 += (signed int)((v11 - v8) * (v15 - uX)) / (signed int)(v10 - uX);
+      uX = v35->field_24_clipz;
+    }
+    else
+    {
+      v16 = (signed int)((v8 - v11) * (v15 - v10)) / (signed int)(uX - v10);
+      v10 = v14->field_24_clipz;
+      v11 += v16;
+    }
+  }
+  v17 = v14->field_20_clipy;
+  v37 = 0;
+  uYa = v14->field_20_clipy;
+  if ( (signed int)v8 < v17 )
+    v37 = 2;
+  v18 = v14->field_28_clipw;
+  if ( (signed int)v8 > v18 )
+    v37 |= 1u;
+  if ( (signed int)v11 >= v17 )
+    v12 = 0;
+  else
+    v12 = 2;
+  if ( (signed int)v11 > v18 )
+    LOBYTE(v12) = v12 | 1;
+  if ( !(v12 & v37) )
+  {
+    v12 ^= v37;
+    uZa = v12;
+    if ( v12 & 2 )
+    {
+      if ( v37 & 2 )
+      {
+        uX += (signed int)((v10 - uX) * (uYa - v8)) / (signed int)(v11 - v8);
+        LOBYTE(v12) = (char)v35;
+        v8 = v35->field_20_clipy;
+      }
+      else
+      {
+        v19 = (signed int)((uX - v10) * (uYa - v11));
+        v20 = v8 - v11;
+        v11 = uYa;
+        v12 = v19 / v20;
+        v10 += v12;
+      }
+    }
+    if ( uZa & 1 )
+    {
+      if ( v37 & 1 )
+      {
+        uX += (signed int)((v10 - uX) * (v35->field_28_clipw - v8)) / (signed int)(v11 - v8);
+        LOBYTE(v12) = (char)v35;
+        v8 = v35->field_28_clipw;
+      }
+      else
+      {
+        v12 = (signed int)((uX - v10) * (v35->field_28_clipw - v11)) / (signed int)(v8 - v11);
+        v11 = v35->field_28_clipw;
+        v10 += v12;
+      }
+    }
+    goto LABEL_46;
+  }
+  return v12;
+}
+
+
+
+//----- (004A0E80) --------------------------------------------------------
+void Render::ClearZBuffer(int a2, int a3)
+{
+  memset32(this->pActiveZBuffer, -65536, 0x4B000u);
+}
+
+
+
+//----- (004A0E97) --------------------------------------------------------
+void Render::Clip_v2(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW)
+{
+  this->field_1C_clipx = uX;
+  this->field_20_clipy = uY;
+  this->field_24_clipz = uZ;
+  this->field_28_clipw = uW;
+}
+
+
+//----- (004A0EB6) --------------------------------------------------------
+void Render::ParseTargetPixelFormat()
+{
+  Render *v1; // eax@1
+  signed int v2; // ecx@1
+  DWORD uRedMask; // edx@1
+  unsigned int uGreenMask; // esi@5
+  signed int v5; // ecx@5
+  unsigned int uBlueMask; // edx@9
+  signed int v7; // ecx@9
+  unsigned int v8; // ecx@13
+
+  v1 = this;
+  v2 = 0;
+  uRedMask = v1->ddpfPrimareSuface.dwRBitMask;
+  v1->uTargetBBits = 0;
+  v1->uTargetGBits = 0;
+  v1->uTargetRBits = 0;
+  do
+  {
+    if ( (1 << v2) & uRedMask )
+      ++v1->uTargetRBits;
+    ++v2;
+  }
+  while ( v2 < 16 );
+  uGreenMask = v1->ddpfPrimareSuface.dwGBitMask;
+  v5 = 0;
+  do
+  {
+    if ( (1 << v5) & uGreenMask )
+      ++v1->uTargetGBits;
+    ++v5;
+  }
+  while ( v5 < 16 );
+  uBlueMask = v1->ddpfPrimareSuface.dwBBitMask;
+  v7 = 0;
+  do
+  {
+    if ( (1 << v7) & uBlueMask )
+      ++v1->uTargetBBits;
+    ++v7;
+  }
+  while ( v7 < 16 );
+  v8 = v1->ddpfPrimareSuface.dwRBitMask;
+  v1->uTargetGMask = uGreenMask;
+  v1->uTargetRMask = v8;
+  v1->uTargetBMask = uBlueMask;
+}
+
+//----- (004A0F40) --------------------------------------------------------
+bool Render::LockSurface_DDraw4(IDirectDrawSurface4 *pSurface, DDSURFACEDESC2 *pDesc, unsigned int uLockFlags)
+{
+  IDirectDrawSurface4 *v4; // esi@1
+  bool result; // eax@1
+  HRESULT v6; // eax@4
+  int v7; // [sp-8h] [bp-14h]@10
+  unsigned int v8; // [sp-4h] [bp-10h]@10
+  char v9; // [sp+Bh] [bp-1h]@1
+
+  v4 = pSurface;
+  v9 = 1;
+  result = pSurface->Lock(0, pDesc, uLockFlags, 0);
+  if ( result == DDERR_SURFACELOST )
+  {
+    if (pAsyncMouse)
+      pAsyncMouse->Suspend();
+    v6 = v4->Restore();
+    if ( v6 )
+    {
+      if ( v6 != DDERR_IMPLICITLYCREATED )
+      {
+LABEL_20:
+        v9 = 0;
+        result = (bool)memset(pDesc, 0, 4u);
+        goto LABEL_21;
+      }
+      pRenderer->pFrontBuffer4->Restore();
+      v4->Restore();
+    }
+    result = v4->Lock(0, pDesc, DDLOCK_WAIT, 0);
+    if ( result == DDERR_INVALIDRECT || result == DDERR_SURFACEBUSY )
+      goto LABEL_20;
+    ErrD3D(result);
+    if ( result )
+    {
+      //v8 = 0;
+      //v7 = 2161;
+LABEL_19:
+      //CheckHRESULT((CheckHRESULT_stru0 *)&pSurface, result, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Screen16.cpp", v7, v8);
+      goto LABEL_20;
+    }
+    if ( pRenderer->pRenderD3D )
+      pRenderD3D->HandleLostResources();
+    result = pRenderer->pDirectDraw4->RestoreAllSurfaces();
+    if (pAsyncMouse)
+      pAsyncMouse->Resume();
+  }
+  else
+  {
+    if ( result )
+    {
+      if ( result == DDERR_INVALIDRECT || result == DDERR_SURFACEBUSY )
+        goto LABEL_20;
+      ErrD3D(result);
+      //v8 = 0;
+      //v7 = 2199;
+      //goto LABEL_19;
+    }
+  }
+LABEL_21:
+  LOBYTE(result) = v9;
+  return result;
+}
+
+
+//----- (004A1032) --------------------------------------------------------
+bool Render::LockSurface_DDraw2(IDirectDrawSurface2 *pSurface, DDSURFACEDESC *pDesc, unsigned int uLockFlags)
+{
+  IDirectDrawSurface2 *v4; // esi@1
+  bool v5; // eax@1
+  HRESULT v6; // eax@2
+  int v7; // [sp-8h] [bp-10h]@8
+  unsigned int v8; // [sp-4h] [bp-Ch]@8
+
+  v4 = pSurface;
+  v5 = pSurface->Lock(
+         0,
+         pDesc,
+         uLockFlags,
+         0);
+  BYTE3(pSurface) = 1;
+  if ( v5 == DDERR_SURFACELOST )
+  {
+    v6 = v4->Restore();
+    if ( !v6 )
+      goto LABEL_5;
+    if ( v6 == DDERR_IMPLICITLYCREATED )
+    {
+      pRenderer->pFrontBuffer2->Restore();
+      v4->Restore();
+LABEL_5:
+      v5 = v4->Lock(0, pDesc, 1u, 0) != 0;
+      if ( v5 == DDERR_INVALIDRECT || v5 == DDERR_SURFACEBUSY )
+        goto LABEL_14;
+      if ( !v5 )
+        return true;
+      ErrD3D(v5);
+      //v8 = 0;
+      //v7 = 2247;
+      goto LABEL_13;
+    }
+    else
+    {
+      pDesc->dwSize = 0;
+      return false;
+    }
+  }
+  else
+  {
+    if ( !v5 )
+      return true;
+    if ( v5 != DDERR_INVALIDRECT && v5 != DDERR_SURFACEBUSY )
+    {
+      //v8 = 0;
+      //v7 = 2269;
+      ErrD3D(v5);
+      pDesc->dwSize = 0;
+      return false;
+LABEL_13:
+      //CheckHRESULT((CheckHRESULT_stru0 *)&pSurface, v5, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Screen16.cpp", v7, v8);
+      goto LABEL_14;
+    }
+  }
+LABEL_14:
+  return true;
+}
+
+//----- (004A10E4) --------------------------------------------------------
+void Render::CreateDirectDraw()
+{
+  Render *v1; // edi@1
+  HRESULT v2; // eax@1
+  HRESULT v3; // eax@5
+  int v6; // [sp-Ch] [bp-20h]@3
+  unsigned int v9; // [sp+0h] [bp-14h]@0
+  IDirectDraw *lpDD; // [sp+10h] [bp-4h]@1
+
+  v1 = this;
+  ErrD3D(DirectDrawCreate(0, &lpDD, 0));
+
+  pDirectDraw2 = nullptr;
+  pDirectDraw4 = nullptr;
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+    ErrD3D(lpDD->QueryInterface(IID_IDirectDraw4, (void **)&pDirectDraw4));
+  else
+    ErrD3D(lpDD->QueryInterface(IID_IDirectDraw2, (void **)&pDirectDraw2));
+
+  lpDD->Release();
+  lpDD = nullptr;
+}
+
+//----- (004A1169) --------------------------------------------------------
+void Render::SetDirectDrawCooperationMode(HWND hWnd, bool bFullscreen)
+{
+  DWORD flags; // eax@1
+  IDirectDraw *v4; // ecx@3
+  HRESULT v5; // eax@5
+  int v6; // [sp-8h] [bp-8h]@3
+  unsigned int v7; // [sp-4h] [bp-4h]@3
+
+  flags = bFullscreen ? DDSCL_NORMAL | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN :
+                        DDSCL_NORMAL;
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+    ErrD3D(pDirectDraw4->SetCooperativeLevel(hWnd, flags | DDSCL_MULTITHREADED));
+  else
+    ErrD3D(pDirectDraw2->SetCooperativeLevel(hWnd, flags));
+}
+
+//----- (004A11C6) --------------------------------------------------------
+void Render::SetDirectDrawDisplayMode(unsigned int uWidth, unsigned int uHeight, unsigned int uBPP)
+{
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+    ErrD3D(pDirectDraw4->SetDisplayMode(uWidth, uHeight, uBPP, 0, 0));
+  else
+    ErrD3D(pDirectDraw2->SetDisplayMode(uWidth, uHeight, uBPP, 0, 0));
+}
+
+//----- (004A121C) --------------------------------------------------------
+void Render::CreateFrontBuffer()
+{
+  Render *v1; // esi@1
+  IDirectDraw *pDD; // eax@3
+  IDirectDrawSurface **pOutSurf; // esi@3
+  struct _DDSURFACEDESC *v4; // edx@3
+  HRESULT v5; // eax@5
+  int v6; // [sp-8h] [bp-8Ch]@3
+  unsigned int v7; // [sp-4h] [bp-88h]@3
+  DDSURFACEDESC2 a2; // [sp+4h] [bp-80h]@3
+
+  v1 = this;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    memset(&a2, 0, 0x7Cu);
+    pDD = (IDirectDraw *)v1->pDirectDraw4;
+    a2.dwSize = 124;
+    a2.dwFlags = 1;
+    v7 = 0;
+    a2.ddsCaps.dwCaps = 512;
+    v6 = 2357;
+    pOutSurf = (IDirectDrawSurface **)&v1->pFrontBuffer4;
+    v4 = (struct _DDSURFACEDESC *)&a2;
+  }
+  else
+  {
+    memset(&a2.lPitch, 0, 0x6Cu);               // DDSURFACEDESC here
+    pDD = (IDirectDraw *)v1->pDirectDraw2;
+    a2.lPitch = 108;
+    a2.dwBackBufferCount = 1;
+    v7 = 0;
+    a2.dwTextureStage = 512;
+    v6 = 2346;
+    pOutSurf = (IDirectDrawSurface **)&v1->pFrontBuffer2;
+    v4 = (struct _DDSURFACEDESC *)&a2.lPitch;
+  }
+  ErrD3D(pDD->CreateSurface(v4, pOutSurf, 0));
+}
+
+//----- (004A12CD) --------------------------------------------------------
+void Render::CreateBackBuffer()
+{
+  Render *v1; // esi@1
+  IDirectDraw *v2; // eax@3
+  IDirectDrawSurface **ppBackBuffer; // esi@3
+  struct _DDSURFACEDESC *v4; // edx@3
+  HRESULT v5; // eax@5
+  int v6; // [sp-8h] [bp-8Ch]@3
+  unsigned int v7; // [sp-4h] [bp-88h]@3
+  DDSURFACEDESC2 a2; // [sp+4h] [bp-80h]@3
+
+  v1 = this;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    memset(&a2, 0, 0x7Cu);
+    v2 = (IDirectDraw *)v1->pDirectDraw4;
+    a2.dwSize = 124;
+    a2.dwFlags = 7;
+    v7 = 0;
+    a2.ddsCaps.dwCaps = 2112;
+    a2.dwWidth = 640;
+    a2.dwHeight = 480;
+    v6 = 2387;
+    ppBackBuffer = (IDirectDrawSurface **)&v1->pBackBuffer4;
+    v4 = (struct _DDSURFACEDESC *)&a2;
+  }
+  else
+  {
+    memset(&a2.lPitch, 0, 0x6Cu);
+    v2 = (IDirectDraw *)v1->pDirectDraw2;
+    a2.lPitch = 108;
+    a2.dwBackBufferCount = 7;
+    v7 = 0;
+    a2.dwTextureStage = 2112;
+    a2.dwAlphaBitDepth = 640;
+    a2.dwMipMapCount = 480;
+    v6 = 2374;
+    ppBackBuffer = (IDirectDrawSurface **)&v1->pBackBuffer2;
+    v4 = (struct _DDSURFACEDESC *)&a2.lPitch;   // //DDSURFACEDESC here fo ddraw2
+  }
+  ErrD3D(v2->CreateSurface(v4, ppBackBuffer, 0));
+}
+
+//----- (004A139A) --------------------------------------------------------
+void Render::CreateDirectDrawPrimarySurface()
+{
+  Render *v1; // esi@1
+  int v2; // ebx@3
+  IDirectDraw2 *v3; // eax@3
+  HRESULT v4; // eax@3
+  IDirectDrawSurface *pFrontBuffer; // eax@3
+  DDSCAPS2 *v6; // edx@3
+  IDirectDraw4 *v7; // eax@4
+  HRESULT v8; // eax@4
+  int v9; // ST14_4@5
+  IDirectDrawSurface *v10; // ST10_4@5
+  HRESULT v11; // eax@5
+  IDirectDrawSurface **ppBackBuffer; // [sp-4h] [bp-A4h]@3
+  const char *v13; // [sp+0h] [bp-A0h]@0
+  int v14; // [sp+4h] [bp-9Ch]@0
+  unsigned int v15; // [sp+8h] [bp-98h]@0
+  DDSURFACEDESC2 ddsd2; // [sp+Ch] [bp-94h]@3
+  DDSCAPS2 v17; // [sp+88h] [bp-18h]@4
+  int a4; // [sp+98h] [bp-8h]@3
+
+  v1 = this;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    v2 = 0;
+    this->field_4004C = 1;
+    memset(&ddsd2, 0, 0x7Cu);
+    v7 = v1->pDirectDraw4;
+    ddsd2.dwBackBufferCount = 1;
+    ddsd2.dwSize = 0x7Cu;
+    ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+    ddsd2.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_3DDEVICE | DDSCAPS_PRIMARYSURFACE;
+    ErrD3D(v7->CreateSurface(
+           &ddsd2,
+           &pFrontBuffer4,
+           0));
+    pFrontBuffer = (IDirectDrawSurface *)v1->pFrontBuffer4;
+    ppBackBuffer = (IDirectDrawSurface **)&v1->pBackBuffer4;
+  }
+  else
+  {
+    v2 = 0;
+    this->field_4004C = 1;
+
+    DDSURFACEDESC ddsd;
+    memset(&ddsd, 0, sizeof(DDSURFACEDESC));
+
+    ddsd.lpSurface = (LPVOID)1;
+    ddsd.lPitch = 108;
+    ddsd.dwBackBufferCount = 33;
+    ddsd.ddsCaps.dwCaps = 8728;
+    ErrD3D(pDirectDraw2->CreateSurface(
+           &ddsd,
+           (IDirectDrawSurface **)&pFrontBuffer2,
+           0));
+
+    pFrontBuffer = (IDirectDrawSurface *)v1->pFrontBuffer2;
+    ppBackBuffer = (IDirectDrawSurface **)&v1->pBackBuffer2;
+  }
+  v9 = (int)v6;
+  v10 = pFrontBuffer;                           // BUG
+
+    v17.dwCaps = 4;
+  ErrD3D(pFrontBuffer->GetAttachedSurface((DDSCAPS *)&v17, ppBackBuffer));//  hr = this->pFrontBuffer->GetAttachedSurface(&ddsCaps2, ppBackBuffer);
+  //CheckHRESULT(&thisa, v11, (const char *)v10, v9, (unsigned int)ppBackBuffer);
+  v1->field_40030 = v2;
+  v1->field_18_locked_pitch = v2;
+}
+
+//----- (004A14F4) --------------------------------------------------------
+void Render::CreateClipper(HWND a2)
+{
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    ErrD3D(pDirectDraw4->CreateClipper(0, &pDDrawClipper, 0));
+    ErrD3D(pDDrawClipper->SetHWnd(0, a2));
+    ErrD3D(pFrontBuffer4->SetClipper(pDDrawClipper));
+  }
+  else
+  {
+    ErrD3D(pDirectDraw2->CreateClipper(0, &pDDrawClipper, 0));
+    ErrD3D(pDDrawClipper->SetHWnd(0, a2));
+  }
+}
+
+//----- (004A15D8) --------------------------------------------------------
+void Render::GetTargetPixelFormat(DDPIXELFORMAT *pOut)
+{
+  IDirectDrawSurface *v2; // eax@3
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+    v2 = (IDirectDrawSurface *)this->pFrontBuffer4;
+  else
+    v2 = (IDirectDrawSurface *)this->pFrontBuffer2;
+  v2->GetPixelFormat(pOut);
+}
+
+//----- (004A1605) --------------------------------------------------------
+void Render::LockRenderSurface(void **pOutSurfacePtr, unsigned int *pOutPixelsPerRow)
+{
+  Render *v3; // esi@1
+  signed int v4; // eax@3
+
+  v3 = this;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+  DDSURFACEDESC2 pDesc; // [sp+4h] [bp-7Ch]@3
+    memset(&pDesc, 0, 0x7Cu);
+    pDesc.dwSize = 124;
+    LockSurface_DDraw4(v3->pBackBuffer4, &pDesc, 1u);
+    *pOutSurfacePtr = pDesc.lpSurface;
+    v4 = pDesc.lPitch;
+  }
+  else
+  {
+  DDSURFACEDESC pDesc; // [sp+4h] [bp-7Ch]@3
+    memset(&pDesc.lPitch, 0, 0x6Cu);
+    pDesc.lPitch = 108;
+    LockSurface_DDraw2(v3->pBackBuffer2, &pDesc, 1u);
+    *pOutSurfacePtr = (void *)pDesc.lpSurface;
+    v4 = pDesc.dwReserved;
+  }
+  *pOutPixelsPerRow = v4 >> 1;
+}
+
+//----- (004A169E) --------------------------------------------------------
+bool Render::UsingDirect3D()
+{
+  return bUserDirect3D == 0;
+}
+
+
+//----- (004A16E1) --------------------------------------------------------
+void Render::UnlockBackBuffer()
+{
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+    ErrD3D(pBackBuffer4->Unlock(0));
+  else
+    ErrD3D(pBackBuffer2->Unlock(0));
+}
+
+
+//----- (004A172E) --------------------------------------------------------
+void Render::LockFrontBuffer(void **pOutSurface, unsigned int *pOutPixelsPerRow)
+{
+  Render *v3; // esi@1
+  signed int v4; // eax@3
+
+  v3 = this;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+  DDSURFACEDESC2 pDesc; // [sp+4h] [bp-7Ch]@3
+    memset(&pDesc, 0, 0x7Cu);
+    pDesc.dwSize = 124;
+    LockSurface_DDraw4(v3->pFrontBuffer4, &pDesc, 1u);
+    *pOutSurface = pDesc.lpSurface;
+    v4 = pDesc.lPitch;
+  }
+  else
+  {
+  DDSURFACEDESC pDesc; // [sp+4h] [bp-7Ch]@3
+    memset(&pDesc.lPitch, 0, 0x6Cu);
+    pDesc.lPitch = 108;
+    LockSurface_DDraw2(v3->pFrontBuffer2, &pDesc, 1u);
+    *pOutSurface = (void *)pDesc.lpSurface;
+    v4 = pDesc.dwReserved;
+  }
+  *pOutPixelsPerRow = v4 >> 1;
+}
+
+//----- (004A17C7) --------------------------------------------------------
+void Render::UnlockFrontBuffer()
+{
+  IDirectDrawSurface *pFront; // eax@3
+  HRESULT v2; // eax@5
+  signed int v3; // [sp-8h] [bp-Ch]@3
+  int v4; // [sp-4h] [bp-8h]@3
+
+  auto a5 = this;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    pFront = (IDirectDrawSurface *)a5->pFrontBuffer4;
+    v4 = 0;
+    v3 = 2615;
+  }
+  else
+  {
+    pFront = (IDirectDrawSurface *)a5->pFrontBuffer2;
+    v4 = 0;
+    v3 = 2611;
+  }
+  ErrD3D(pFront->Unlock(0));
+}
+
+
+//----- (004A1814) --------------------------------------------------------
+void Render::RestoreFrontBuffer()
+{
+  IDirectDrawSurface **v1; // esi@2
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT
+    || (v1 = (IDirectDrawSurface **)&this->pFrontBuffer2, pVersion->pVersionInfo.dwMajorVersion >= 5u) )
+    v1 = (IDirectDrawSurface **)&this->pFrontBuffer4;
+  if ( (*v1)->IsLost() == DDERR_SURFACELOST )
+    (*v1)->Restore();
+}
+
+
+//----- (004A184C) --------------------------------------------------------
+HRESULT Render::_4A184C()
+{
+  IDirectDrawSurface **pBack; // esi@2
+  HRESULT result; // eax@4
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT
+    || (pBack = (IDirectDrawSurface **)&this->pBackBuffer2, pVersion->pVersionInfo.dwMajorVersion != 4) )
+    pBack = (IDirectDrawSurface **)&this->pBackBuffer4;
+  result = (*pBack)->IsLost();
+  if ( result == DDERR_SURFACELOST )
+    result = (*pBack)->Restore();
+  return result;
+}
+
+//----- (004A1884) --------------------------------------------------------
+void Render::PresentRect(RECT *a2, RECT *a3)
+{
+  IDirectDrawSurface *pFront; // eax@3
+  HRESULT v4; // eax@5
+  IDirectDrawSurface *pBack; // [sp-1Ch] [bp-1Ch]@3
+  struct tagRECT *v6; // [sp-18h] [bp-18h]@3
+  DWORD v7; // [sp-14h] [bp-14h]@3
+  DDBLTFX *v8; // [sp-10h] [bp-10h]@3
+  const char *v9; // [sp-Ch] [bp-Ch]@3
+  int v10; // [sp-8h] [bp-8h]@3
+  unsigned int v11; // [sp-4h] [bp-4h]@3
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    v11 = 0;
+    pFront = (IDirectDrawSurface *)this->pFrontBuffer4;
+    v10 = 2657;
+    v9 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Screen16.cpp";
+    v8 = 0;
+    v7 = DDBLT_WAIT;
+    v6 = a3;
+    pBack = (IDirectDrawSurface *)this->pBackBuffer4;
+  }
+  else
+  {
+    v11 = 0;
+    pFront = (IDirectDrawSurface *)this->pFrontBuffer2;
+    v10 = 2653;
+    v9 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Screen16.cpp";
+    v8 = 0;
+    v7 = DDBLT_WAIT;
+    v6 = a3;
+    pBack = (IDirectDrawSurface *)this->pBackBuffer2;
+  }
+  ErrD3D(pFront->Blt(a2, pBack, v6, v7, v8));
+}
+
+
+//----- (004A18F5) --------------------------------------------------------
+void Render::BltToFront(RECT *pDstRect, IDirectDrawSurface *pSrcSurface, RECT *pSrcRect, unsigned int uBltFlags)
+{
+  IDirectDrawSurface *pFront; // eax@3
+  HRESULT v6; // eax@5
+  int v7; // [sp-8h] [bp-8h]@3
+  unsigned int v8; // [sp-4h] [bp-4h]@3
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion >= 5u )
+    ErrD3D(pFrontBuffer4->Blt(pDstRect, (IDirectDrawSurface4 *)pSrcSurface, pSrcRect, uBltFlags, nullptr));
+  else
+    ErrD3D(pFrontBuffer2->Blt(pDstRect, (IDirectDrawSurface2 *)pSrcSurface, pSrcRect, uBltFlags, nullptr));
+}
+
+//----- (004A194A) --------------------------------------------------------
+void Render::BltBackToFontFast(int a2, int a3, RECT *a4)
+{
+  IDirectDrawSurface *pFront; // eax@3
+  IDirectDrawSurface *pBack; // [sp-Ch] [bp-Ch]@3
+  RECT *v6; // [sp-8h] [bp-8h]@3
+  DWORD v7; // [sp-4h] [bp-4h]@3
+
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  {
+    pFront = (IDirectDrawSurface *)this->pFrontBuffer4;
+    v7 = DDBLTFAST_WAIT;
+    v6 = a4;
+    pBack = (IDirectDrawSurface *)this->pBackBuffer4;
+  }
+  else
+  {
+    pFront = (IDirectDrawSurface *)this->pFrontBuffer2;
+    v7 = DDBLTFAST_WAIT;
+    v6 = a4;
+    pBack = (IDirectDrawSurface *)this->pBackBuffer2;
+  }
+  pFront->BltFast(0, 0, pBack, v6, v7);
+}
+
+//----- (004A1B22) --------------------------------------------------------
+unsigned int Render::Billboard_ProbablyAddToListAndSortByZOrder(unsigned int a1)
+{
+  unsigned int v2; // ebx@1
+  double v4; // st7@5
+  unsigned int v5; // esi@5
+  int v6; // ecx@5
+  unsigned int v7; // edx@6
+  char *v8; // ecx@12
+  void *v9; // edi@16
+  unsigned int v10; // eax@16
+  void *v11; // edi@21
+  unsigned int v12; // eax@21
+
+  v2 = pRenderer->uNumBillboardsToDraw;
+  if ( (signed int)pRenderer->uNumBillboardsToDraw >= 999 )
+    return 0;
+  if ( !pRenderer->uNumBillboardsToDraw )
+  {
+    pRenderer->uNumBillboardsToDraw = 1;
+    return 0;
+  }
+  v4 = *(float *)&a1;
+  v5 = pRenderer->uNumBillboardsToDraw;
+  v6 = 0;
+  if ( (signed int)pRenderer->uNumBillboardsToDraw <= 0 )
+  {
+    v7 = a1;
+  }
+  else
+  {
+    do
+    {
+      v7 = v6 + (signed int)(v5 - v6) / 2;
+      if ( v4 <= pRenderer->pBillboardRenderListD3D[v6 + (signed int)(v5 - v6) / 2].flt_88 )
+        v5 = v6 + (signed int)(v5 - v6) / 2;
+      else
+        v6 = v7 + 1;
+    }
+    while ( v6 < (signed int)v5 );
+  }
+  v8 = (char *)&pRenderer->pBillboardRenderListD3D[v7].flt_88;
+  if ( v4 > *(float *)v8 )
+  {
+    if ( v7 == pRenderer->uNumBillboardsToDraw - 1 )
+    {
+      v7 = pRenderer->uNumBillboardsToDraw;
+    }
+    else
+    {
+      if ( (signed int)pRenderer->uNumBillboardsToDraw > (signed int)v7 )
+      {
+        v9 = &pRenderer->pBillboardRenderListD3D[pRenderer->uNumBillboardsToDraw];
+        v10 = pRenderer->uNumBillboardsToDraw - v7;
+        do
+        {
+          memcpy(v9, (char *)v9 - 156, 0x9Cu);
+          v9 = (char *)v9 - 156;
+          --v10;
+        }
+        while ( v10 );
+      }
+      ++v7;
+    }
+LABEL_23:
+    pRenderer->uNumBillboardsToDraw = v2 + 1;
+    return v7;
+  }
+  if ( v4 <= *(float *)v8 )
+  {
+    if ( (signed int)pRenderer->uNumBillboardsToDraw > (signed int)v7 )
+    {
+      v11 = &pRenderer->pBillboardRenderListD3D[pRenderer->uNumBillboardsToDraw];
+      v12 = pRenderer->uNumBillboardsToDraw - v7;
+      do
+      {
+        memcpy(v11, (char *)v11 - 156, 0x9Cu);
+        v11 = (char *)v11 - 156;
+        --v12;
+      }
+      while ( v12 );
+    }
+    goto LABEL_23;
+  }
+  return v7;
+}
+
+
+//----- (004A1E9D) --------------------------------------------------------
+unsigned int Render::GetBillboardDrawListSize()
+{
+  return pRenderer->uNumBillboardsToDraw;
+}
+
+//----- (004A1EA3) --------------------------------------------------------
+unsigned int Render::GetParentBillboardID(unsigned int uBillboardID)
+{
+  return pRenderer->pBillboardRenderListD3D[uBillboardID].uParentBillboardID;
+}
+
+//----- (004A1EB6) --------------------------------------------------------
+void Render::BeginSceneD3D()
+{
+  if (!uNumD3DSceneBegins++)
+  {
+    if (pRenderD3D)
+    {
+      pRenderD3D->ClearTarget(true, 0x00F08020, true, 1.0);
+      pRenderer->uNumBillboardsToDraw = 0;
+      pRenderD3D->pDevice->BeginScene();
+      if (!pRenderD3D->DoesRaiseExceptions())
+      {
+        MessageBoxW(nullptr, L"Error executing scratch 3D operations", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\screen16_3d.cpp:360", 0);
+      }
+      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+        uFogColor = GetLevelFogColor();
+      else
+        uFogColor = 0;
+
+      if ( uFogColor & 0xFF000000 )
+      {
+        pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1);
+        pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, uFogColor & 0xFFFFFF);
+        pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0);
+        bUsingSpecular = true;
+      }
+      else
+      {
+        pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0);
+        bUsingSpecular = 0;
+      }
+    }
+    else
+    {
+      LockRenderSurface((void **)&pTargetSurface, &uTargetSurfacePitch);
+      if (pTargetSurface)
+        field_18_locked_pitch = uTargetSurfacePitch;
+      else
+        --uNumD3DSceneBegins;
+    }
+  }
+}
+
+//----- (004A1FE1) --------------------------------------------------------
+void Render::DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene()
+{
+  --uNumD3DSceneBegins;
+  if (uNumD3DSceneBegins)
+    return;
+
+  if (pRenderD3D)
+  {
+    pGame->draw_debug_outlines();
+    //DoRenderBillboards_D3D(); Ritor1: it's temporarily
+    pGame->pStru6Instance->RenderSpecialEffects();
+    pRenderD3D->pDevice->EndScene();
+  }
+  else
+    pGame->pStru6Instance->RenderSpecialEffects();
+}
+
+
+
+//----- (004A2031) --------------------------------------------------------
+unsigned int Render::GetActorTintColor(float a2, int a3, int a4, int a5, RenderBillboard *a6)
+{
+  return ::GetActorTintColor(a3, a4, a2, a5, a6);
+}
+
+
+//----- (004A26BC) --------------------------------------------------------
+void Render::DrawTerrainPolygon(unsigned int uNumVertices, stru148 *a4, IDirect3DTexture2 *a5, int a6, int a7)
+{
+  RenderVertexSoft *pVertices; // esi@0
+  Render *v7; // edi@1
+  unsigned int v8; // ebx@1
+  LightmapBuilder *v9; // esi@3
+  unsigned int v10; // edx@3
+  int v11; // eax@5
+  int v12; // eax@11
+  char *v13; // esi@11
+  double v14; // st7@13
+  double v15; // st7@13
+  signed int v16; // eax@13
+  int v17; // ecx@13
+  double v18; // st7@13
+  float v19; // ST78_4@14
+  int v20; // eax@14
+  char v21; // zf@16
+  HRESULT v22; // eax@17
+  HRESULT v23; // eax@17
+  HRESULT v24; // eax@19
+  HRESULT v25; // eax@19
+  unsigned int v26; // ecx@19
+  char *v27; // eax@20
+  HRESULT v28; // eax@22
+  HRESULT v29; // eax@22
+  HRESULT v30; // eax@23
+  HRESULT v31; // eax@24
+  HRESULT v32; // eax@24
+  HRESULT v33; // eax@24
+  HRESULT v34; // eax@24
+  HRESULT v35; // eax@25
+  HRESULT v36; // eax@25
+  unsigned int v37; // ecx@25
+  char *v38; // eax@26
+  int v39; // edx@27
+  HRESULT v40; // eax@28
+  HRESULT v41; // eax@28
+  HRESULT v42; // eax@28
+  HRESULT v43; // eax@28
+  //IDirect3DDevice3Vtbl *v44; // ebx@28
+  unsigned int v45; // eax@28
+  HRESULT v46; // eax@29
+  HRESULT v47; // eax@29
+  HRESULT v48; // eax@29
+  IDirect3DDevice3 *v49; // eax@35
+  //IDirect3DDevice3Vtbl *v50; // ecx@35
+  int v51; // eax@40
+  char *v52; // esi@40
+  double v53; // st7@42
+  double v54; // st7@42
+  signed int v55; // eax@42
+  int v56; // ecx@42
+  double v57; // st7@42
+  float v58; // ST7C_4@43
+  int v59; // eax@43
+  signed int v60; // [sp+78h] [bp-14h]@31
+  RenderVertexSoft *v61; // [sp+7Ch] [bp-10h]@3
+  const char *v62; // [sp+80h] [bp-Ch]@0
+  const char *v63; // [sp+80h] [bp-Ch]@19
+  int v64; // [sp+84h] [bp-8h]@0
+  LightmapBuilder *v65; // [sp+88h] [bp-4h]@3
+  unsigned int v66; // [sp+88h] [bp-4h]@40
+  unsigned int a6a; // [sp+A0h] [bp+14h]@11
+
+  v7 = this;
+  v8 = 0;
+  if ( this->uNumD3DSceneBegins && (signed int)uNumVertices >= 3 )
+  {
+    v61 = pVertices;
+    v9 = pGame->pLightmapBuilder;
+    v65 = v9;
+    v10 = v9->std__vector_000004_size;
+    if ( byte_4D864C && pGame->uFlags & 1 )
+    {
+      v11 = GetActorTintColor(a4->field_58, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
+      v9->_45D74F_MessWithLight(v11, 0);
+    }
+    else
+    {
+      if ( a6 || !v10 || byte_4D864C && pGame->uFlags & 2 )
+      {
+        if ( (char)a7 )
+          v60 = 3;
+        else
+          v60 = 1;
+        ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, v60));
+        if ( a6 || v7->bUsingSpecular )
+        {
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+          //v49 = v7->pRenderD3D->pDevice;
+          //v50 = v49->lpVtbl;
+          if ( a6 )
+          {
+            ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 5));
+            ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 6));
+          }
+          else
+          {
+            ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2));
+            ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1));
+          }
+
+        }
+        if ( (signed int)uNumVertices > 0 )
+        {
+          v51 = (int)&arary_77E5C8[0].pos.y;
+          v52 = (char *)&array_50AC10[0].vWorldViewPosition;
+          a7 = (int)&arary_77E5C8[0].pos.y;
+          v66 = uNumVertices;
+          while ( 1 )
+          {
+            v53 = *(float *)v52 * 1000.0;
+            *(int *)(v51 - 4) = *((int *)v52 + 3);
+            v54 = v53 / (double)pOutdoorCamera->shading_dist_mist;
+            *(int *)v51 = *((int *)v52 + 4);
+            *(float *)(v51 + 4) = 1.0 - 1.0 / v54;
+            *(float *)(v51 + 8) = 1.0 / (*(float *)v52 + 0.0000001);
+            v55 = GetActorTintColor(a4->field_58, 0, *(float *)v52, 0, 0);
+            v56 = a7;
+            v57 = *(float *)v52;
+            *(int *)(a7 + 12) = v55;
+            if ( v7->bUsingSpecular )
+            {
+              v58 = v57;
+              v59 = sub_47C3D7_get_fog_related_stuff(0, 0, v58);
+              v56 = a7;
+            }
+            else
+            {
+              v59 = 0;
+            }
+            *(int *)(v56 + 16) = v59;
+            *(int *)(v56 + 20) = *((int *)v52 + 6);
+            *(int *)(v56 + 24) = *((int *)v52 + 7);
+            v52 += 48;
+            v21 = v66-- == 1;
+            a7 = v56 + 32;
+            if ( v21 )
+              break;
+            v51 = a7;
+          }
+        }
+        ErrD3D(pRenderD3D->pDevice->SetTexture(0, a5));
+        ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+          D3DPT_TRIANGLEFAN,
+          D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+          arary_77E5C8,
+          uNumVertices,
+          16));
+        if ( a6 )
+        {
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+        }
+      }
+      else
+      {
+        if ( (signed int)uNumVertices > 0 )
+        {
+          v12 = (int)&arary_77E5C8[0].pos.y;
+          v13 = (char *)&array_50AC10[0].vWorldViewPosition;
+          a7 = (int)&arary_77E5C8[0].pos.y;
+          a6a = uNumVertices;
+          while ( 1 )
+          {
+            v14 = *(float *)v13 * 1000.0;
+            *(int *)(v12 - 4) = *((int *)v13 + 3);
+            v15 = v14 / (double)pOutdoorCamera->shading_dist_mist;
+            *(int *)v12 = *((int *)v13 + 4);
+            *(float *)(v12 + 4) = 1.0 - 1.0 / v15;
+            *(float *)(v12 + 8) = 1.0 / (*(float *)v13 + 0.0000001);
+            v16 = GetActorTintColor(a4->field_58, 0, *(float *)v13, 0, 0);
+            v17 = a7;
+            v18 = *(float *)v13;
+            *(int *)(a7 + 12) = v16;
+            if ( v7->bUsingSpecular )
+            {
+              v19 = v18;
+              v20 = sub_47C3D7_get_fog_related_stuff(0, 0, v19);
+              v17 = a7;
+            }
+            else
+            {
+              v20 = 0;
+            }
+            *(int *)(v17 + 16) = v20;
+            *(int *)(v17 + 20) = *((int *)v13 + 6);
+            *(int *)(v17 + 24) = *((int *)v13 + 7);
+            v13 += 48;
+            v21 = a6a-- == 1;
+            a7 = v17 + 32;
+            if ( v21 )
+              break;
+            v12 = a7;
+          }
+        }
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false));
+        ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1u));
+        if ( pRenderer->bUsingSpecular )
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0));
+
+        ErrD3D(pRenderD3D->pDevice->SetTexture(0, 0));
+        ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+                D3DPT_TRIANGLEFAN,
+                D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                arary_77E5C8,
+                uNumVertices,
+                16));
+        //v63 = (const char *)v7->pRenderD3D->pDevice;
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1));
+        //(*(void (**)(void))(*(int *)v63 + 88))();
+        pGame->pLightmapBuilder->_45D74F_MessWithLight(-1, 0);
+        v26 = uNumVertices;
+        if ( (signed int)uNumVertices > 0 )
+        {
+          v27 = (char *)&arary_77E5C8[0].diffuse;
+          do
+          {
+            *(int *)v27 = -1;
+            v27 += 32;
+            --v26;
+          }
+          while ( v26 );
+        }
+        ErrD3D(pRenderD3D->pDevice->SetTexture(0, a5));
+        ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1u));
+        if ( !pRenderer->bUsingSpecular )
+        {
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1u));
+        }
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 1u));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 3u));
+        ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+                D3DPT_TRIANGLEFAN,
+                D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                arary_77E5C8,
+                uNumVertices,
+                16));
+        if ( pRenderer->bUsingSpecular )
+        {
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1u));
+          ErrD3D(pRenderD3D->pDevice->SetTexture(0, 0));
+          v37 = uNumVertices;
+          if ( (signed int)uNumVertices > 0 )
+          {
+            v38 = (char *)&arary_77E5C8[0].specular;
+            do
+            {
+              v39 = *(int *)v38;
+              *(int *)v38 = 0;
+              v38 += 32;
+              --v37;
+              *((int *)v38 - 9) = pRenderer->uFogColor | v39 & 0xFF000000;
+            }
+            while ( v37 );
+          }
+          ErrD3D(pRenderD3D->pDevice->SetTexture(0, 0));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 6u));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 5u));
+          ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+                  D3DPT_TRIANGLEFAN,
+                  D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                  arary_77E5C8,
+                  uNumVertices,
+                  16));
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1));
+          //v44 = pRenderer->pRenderD3D->pDevice;
+          v45 = GetLevelFogColor();
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, v45 & 0xFFFFFF));
+          v8 = 0;
+          ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0));
+        }
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, v8));
+      }
+    }
+    if ( pIndoorCamera->field_4C & 2 || pBLVRenderParams->uFlags & 2 )
+      pGame->pIndoorCameraD3D->debug_outline_d3d(arary_77E5C8, uNumVertices, 0xFFFFFFu, 0.0);
+  }
+}
+// 4A26BC: could not find valid save-restore pair for esi
+// 4D864C: using guessed type char byte_4D864C;
+
+
+//----- (004A2DA3) --------------------------------------------------------
+void Render::DrawFan(unsigned int uNumVertices, stru148 *a3, IDirect3DTexture2 *a4)
+{
+  Render *v4; // ebx@1
+  char *v5; // esi@6
+  char *v6; // edi@6
+  double v7; // st7@7
+  float v8; // ST34_4@7
+  int v9; // eax@7
+  signed int v10; // eax@7
+  double v11; // st7@7
+  int v12; // eax@7
+  float v13; // ST3C_4@8
+  unsigned int v14; // [sp+4Ch] [bp-4h]@6
+
+  v4 = this;
+  if ( this->uNumD3DSceneBegins && (signed int)uNumVertices >= 3 )
+  {
+    ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1u));
+    if ( v4->bUsingSpecular )
+    {
+      ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+      ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+      ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+    }
+    if ( (signed int)uNumVertices > 0 )
+    {
+      v5 = (char *)&arary_77E5C8[0].pos.y;
+      v6 = (char *)&array_50AC10[0].vWorldViewProjY;
+      v14 = uNumVertices;
+      do
+      {
+        v7 = *((float *)v6 - 4);
+        *((int *)v5 - 1) = *((int *)v6 - 1);
+        v8 = v7;
+        *(int *)v5 = *(int *)v6;
+        v9 = *((int *)v6 + 1);
+        *((int *)v5 + 1) = 0x3F7FF972u;
+        *((int *)v5 + 2) = v9;
+        v10 = GetActorTintColor(31, 0, v8, 1, 0);
+        v11 = *((float *)v6 - 4);
+        *((int *)v5 + 3) = v10;
+        v12 = 0;
+        if ( v4->bUsingSpecular )
+        {
+          v13 = v11;
+          v12 = sub_47C3D7_get_fog_related_stuff(0, 1, v13);
+        }
+        *((int *)v5 + 4) = v12;
+        *((int *)v5 + 5) = *((int *)v6 + 2);
+        *((int *)v5 + 6) = *((int *)v6 + 3);
+        v6 += 48;
+        v5 += 32;
+        --v14;
+      }
+      while ( v14 );
+    }
+    ErrD3D(pRenderD3D->pDevice->SetTexture(0, a4));
+    ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+      D3DPT_TRIANGLEFAN,
+      D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+      arary_77E5C8,
+      uNumVertices,
+      24));
+  }
+}
+
+
+//----- (004A2ED5) --------------------------------------------------------
+void Render::_4A2ED5(signed int a2, stru148 *a3, IDirect3DTexture2 *pHwTex)
+{
+  signed int v4; // edi@2
+  int v5; // eax@3
+  int v6; // edx@5
+  char *v7; // eax@6
+  char *v8; // ecx@6
+  double v9; // st6@7
+  int v10; // ebx@7
+  int v11; // ebx@7
+
+  if ( this->uNumD3DSceneBegins )
+  {
+    v4 = a2;
+    if ( a2 >= 3 )
+    {
+      ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1u));
+      v5 = 31 - (a3->field_58 & 0x1F);
+      if ( v5 < pOutdoor->field_CBC_terrain_triangles_shade_type )
+        v5 = pOutdoor->field_CBC_terrain_triangles_shade_type;
+      v6 = 8 * v5 | ((8 * v5 | (v5 << 11)) << 8);
+      if ( a2 > 0 )
+      {
+        v7 = (char *)&arary_77E5C8[0].pos.y;
+        v8 = (char *)&array_507D30[0].vWorldViewProjY;
+        do
+        {
+          v9 = *((float *)v8 - 4) * 0.061758894;
+          v10 = *((int *)v8 - 1);
+          *((int *)v7 + 4) = 0;
+          *((int *)v7 - 1) = v10;
+          *(int *)v7 = *(int *)v8;
+          *((int *)v7 + 2) = *((int *)v8 + 1);
+          *((int *)v7 + 5) = *((int *)v8 + 2);
+          v11 = *((int *)v8 + 3);
+          *((int *)v7 + 3) = v6;
+          *((int *)v7 + 6) = v11;
+          v8 += 48;
+          v7 += 32;
+          --v4;
+          *((float *)v7 - 7) = 1.0 - 1.0 / v9;
+        }
+        while ( v4 );
+      }
+      ErrD3D(pRenderD3D->pDevice->SetTexture(0, pHwTex));
+      ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+        D3DPT_TRIANGLEFAN,
+        D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+        arary_77E5C8,
+        a2,
+        28));
+    }
+  }
+}
+
+
+
+//----- (004A2FC0) --------------------------------------------------------
+void Render::DrawIndoorPolygon(unsigned int uNumVertices, BLVFace *pFace, IDirect3DTexture2 *pHwTex, Texture *pTex, int uPackedID, unsigned int uColor, int a8)
+{
+  //Render *v8; // edi@1
+  //unsigned int v9; // esi@3
+  char *v12; // ecx@9
+  char *v13; // eax@9
+  double v14; // st6@10
+  int v15; // edx@10
+  Texture *v16; // edx@10
+  double v17; // st6@10
+  //char v18; // zf@10
+  Texture *v19; // edx@10
+  Texture *v23; // edx@16
+  char *v24; // ecx@16
+  char *v25; // eax@16
+  double v26; // st6@17
+  int v27; // esi@17
+  double v28; // st6@17
+  unsigned int v33; // ecx@18
+  char *v34; // eax@19
+  //Texture *v45; // edx@23
+  //char *v46; // ecx@23
+  //char *v47; // eax@23
+  //double v48; // st6@24
+  //int v49; // esi@24
+  //double v50; // st6@24
+  const char *v53; // [sp-Ch] [bp-20h]@21
+  //int v54; // [sp-8h] [bp-1Ch]@21
+  //unsigned int v55; // [sp-4h] [bp-18h]@21
+  const char *v56; // [sp+0h] [bp-14h]@0
+  int v57; // [sp+4h] [bp-10h]@0
+  unsigned int v58; // [sp+8h] [bp-Ch]@0
+  //LightmapBuilder *v59; // [sp+Ch] [bp-8h]@3
+  //int a3a; // [sp+10h] [bp-4h]@4
+
+  //v8 = this;
+  if (!uNumD3DSceneBegins || uNumVertices < 3)
+    return;
+
+  //auto a3 = pFace;
+  //auto a6 = uPackedID;
+    //v59 = pGame->pLightmapBuilder;
+    //v9 = v59->std__vector_000004_size;
+
+  auto uCorrectedColor = uColor;
+  if (pGame->pLightmapBuilder->std__vector_000004_size)
+    uCorrectedColor = 0xFFFFFFFF;
+  pGame->AlterGamma(pFace, &uCorrectedColor);
+
+  if (byte_4D864C && pGame->uFlags & 1)
+  {
+      __debugbreak();
+      ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false));
+      ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1));
+      if ( (signed int)uNumVertices > 0 )
+      {
+        v12 = (char *)&array_507D30[0].vWorldViewPosition;
+        v13 = (char *)&arary_77E5C8[0].pos.y;
+        auto a7 = uNumVertices;
+        uint v18;
+        do
+        {
+          v14 = *(float *)v12 * 0.061758894;
+          v15 = *((int *)v12 + 3);
+          *((int *)v13 + 4) = 0;
+          *((int *)v13 - 1) = v15;
+          *(int *)v13 = *((int *)v12 + 4);
+          *((int *)v13 + 3) = uCorrectedColor;
+          v16 = pTex;
+          v13 += 32;
+          *((float *)v13 - 7) = 1.0 - 1.0 / v14;
+          v17 = 1.0 / *(float *)v12;
+          v12 += 48;
+          v18 = a7-- == 1;
+          *((float *)v13 - 6) = v17;
+          pHwTex = (IDirect3DTexture2 *)v16->uTextureWidth;
+          v19 = pTex;
+          *((float *)v13 - 3) = *((float *)v12 - 6) / (double)(signed int)pHwTex;
+          pHwTex = (IDirect3DTexture2 *)v19->uTextureHeight;
+          *((float *)v13 - 2) = *((float *)v12 - 5) / (double)(signed int)pHwTex;
+        }
+        while ( !v18 );
+      }
+      ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1));
+      ErrD3D(pRenderD3D->pDevice->SetTexture(0, nullptr));
+      ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+              D3DPT_TRIANGLEFAN,
+              D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+              arary_77E5C8,
+              uNumVertices,
+              28));
+      pGame->pLightmapBuilder->_45D74F_MessWithLight(-1, 0);
+  }
+  else
+  {
+    if (!pGame->pLightmapBuilder->std__vector_000004_size ||
+        byte_4D864C && pGame->uFlags & 2)
+    {
+      for (uint i = 0; i < uNumVertices; ++i)
+      {
+        arary_77E5C8[i].pos.x = array_507D30[i].vWorldViewProjX;
+        arary_77E5C8[i].pos.y = array_507D30[i].vWorldViewProjY;
+        arary_77E5C8[i].pos.z = 1.0 - 1.0 / (array_507D30[i].vWorldViewPosition.x * 0.061758894);
+        arary_77E5C8[i].rhw = 1.0 / array_507D30[i].vWorldViewPosition.x;
+        arary_77E5C8[i].diffuse = uCorrectedColor;
+        arary_77E5C8[i].specular = 0;
+        arary_77E5C8[i].texcoord.x = array_507D30[i].u / (double)pTex->uTextureWidth;
+        arary_77E5C8[i].texcoord.y = array_507D30[i].v / (double)pTex->uTextureHeight;
+      }
+
+      ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1));
+      ErrD3D(pRenderD3D->pDevice->SetTexture(0, pHwTex));
+      ErrD3D(pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+                D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                arary_77E5C8,
+                uNumVertices,
+                28));
+    }
+    else
+    {
+      __debugbreak();
+        if ( (signed int)uNumVertices > 0 )
+        {
+          v23 = pTex;
+          v24 = (char *)&array_507D30[0].vWorldViewPosition;
+          v25 = (char *)&arary_77E5C8[0].pos.y;
+          pTex = (Texture *)uNumVertices;
+          uint v18;
+          do
+          {
+            v26 = *(float *)v24 * 0.061758894;
+            v27 = *((int *)v24 + 3);
+            *((int *)v25 + 4) = 0;
+            *((int *)v25 - 1) = v27;
+            *(int *)v25 = *((int *)v24 + 4);
+            *((int *)v25 + 3) = uColor;
+            v25 += 32;
+            *((float *)v25 - 7) = 1.0 - 1.0 / v26;
+            v28 = 1.0 / *(float *)v24;
+            v24 += 48;
+            v18 = pTex == (Texture *)1;
+            pTex = (Texture *)((char *)pTex - 1);
+            *((float *)v25 - 6) = v28;
+            //a3 = (BLVFace *)v23->uTextureWidth;
+            *((float *)v25 - 3) = *((float *)v24 - 6) / (double)(signed int)v23->uTextureWidth;
+            //a3 = (BLVFace *)v23->uTextureHeight;
+            *((float *)v25 - 2) = *((float *)v24 - 5) / (double)(signed int)v23->uTextureHeight;
+          }
+          while ( !v18 );
+        }
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false));
+        ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1));
+        ErrD3D(pRenderD3D->pDevice->SetTexture(0, nullptr));
+        ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+                D3DPT_TRIANGLEFAN,
+                D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                arary_77E5C8,
+                uNumVertices,
+                28));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1));
+        pGame->pLightmapBuilder->_45D74F_MessWithLight(-1, 0);
+        v33 = uNumVertices;
+        if ( (signed int)uNumVertices > 0 )
+        {
+          v34 = (char *)&arary_77E5C8[0].diffuse;
+          do
+          {
+            *(int *)v34 = uCorrectedColor;
+            v34 += 32;
+            --v33;
+          }
+          while ( v33 );
+        }
+        ErrD3D(pRenderD3D->pDevice->SetTexture(0, pHwTex));
+        ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 1));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1u));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 1));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 3));
+        ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+                D3DPT_TRIANGLEFAN,
+                D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                arary_77E5C8,
+                uNumVertices,
+                28));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1));
+        ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false));
+    }
+  }
+}
+// 4D864C: using guessed type char byte_4D864C;
+
+
+//----- (004A43B1) --------------------------------------------------------
+void Render::DrawBillboard_Indoor(RenderBillboardTransform_local0 *pSoftBillboard, Sprite *a3, int uPaletteSubindex)
+{
+  RenderBillboardTransform_local0 *v4; // ebx@2
+  double v5; // st7@2
+  float v6; // ST08_4@2
+  unsigned int v7; // eax@2
+  int v8; // ecx@2
+  unsigned int v9; // esi@2
+  Sprite *v10; // edi@5
+  signed int v11; // eax@9
+  signed int v12; // eax@9
+  double v13; // st7@12
+  double v14; // st6@12
+  double v15; // st5@12
+  double v16; // st4@12
+  double v17; // st3@12
+  double v18; // st2@12
+  int v19; // ecx@14
+  double v20; // st3@14
+  int v21; // ecx@16
+  double v22; // st3@16
+  IDirect3DTexture2 *v23; // eax@18
+  signed int v24; // [sp+18h] [bp-18h]@5
+  signed int v25; // [sp+1Ch] [bp-14h]@5
+  Render *v26; // [sp+20h] [bp-10h]@1
+  float v27; // [sp+24h] [bp-Ch]@5
+  int v28; // [sp+28h] [bp-8h]@2
+  float v29; // [sp+2Ch] [bp-4h]@5
+  float pSoftBillboarda; // [sp+38h] [bp+8h]@2
+  float v31; // [sp+3Ch] [bp+Ch]@5
+  float v32; // [sp+3Ch] [bp+Ch]@12
+  float a1; // [sp+40h] [bp+10h]@5
+
+  v26 = this;
+  if ( this->uNumD3DSceneBegins )
+  {
+    v4 = pSoftBillboard;
+    v5 = (double)HIWORD(pSoftBillboard->sZValue);
+    pSoftBillboarda = v5;
+    v6 = v5;
+    v7 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v6));
+    v8 = uPaletteSubindex;
+    v9 = v7;
+    v28 = uPaletteSubindex & 0xFF000000;
+    if ( uPaletteSubindex & 0xFF000000 )
+      pBillboardRenderListD3D[v9].uOpacity = RenderBillboardD3D::Opaque_3;
+    else
+      pBillboardRenderListD3D[v9].uOpacity = RenderBillboardD3D::Transparent;
+    v10 = a3;
+    pBillboardRenderListD3D[v9].field_90 = v4->field_44;
+    pBillboardRenderListD3D[v9].sZValue = v4->sZValue;
+    pBillboardRenderListD3D[v9].uParentBillboardID = v4->uParentBillboardID;
+    v25 = v4->uScreenSpaceX;
+    v24 = v4->uScreenSpaceY;
+    a1 = (double)(v4->field_10 & 0xFFFF) * 0.000015260186 + (double)HIWORD(v4->field_10);
+    v29 = (double)(v4->field_14 & 0xFFFF) * 0.000015260186 + (double)HIWORD(v4->field_14);
+    v31 = (double)((v10->uBufferWidth >> 1) - v10->uAreaX);
+    v27 = (double)(v10->uBufferHeight - v10->uAreaY);
+    if ( v4->uFlags & 4 )
+      v31 = v31 * -1.0;
+    if ( v4->uTintColor && v26->bTinting )
+    {
+      v11 = GetActorTintColor(v8, 0, pSoftBillboarda, 0, 0);
+      v12 = sub_4A19D8(v4->uTintColor, v11);
+      if ( v28 )
+        v12 = (unsigned int)((char *)&array_77EC08[1852].pEdgeList1[17] + 3) & ((unsigned int)v12 >> 1);
+    }
+    else
+    {
+      v12 = GetActorTintColor(v8, 0, pSoftBillboarda, 0, 0);
+    }
+    v13 = (double)v25;
+    pBillboardRenderListD3D[v9].pQuards[0].specular = 0;
+    pBillboardRenderListD3D[v9].pQuards[0].diffuse = v12;
+    pBillboardRenderListD3D[v9].pQuards[0].pos.x = v13 - v31 * a1;
+    v14 = (double)v24;
+    v32 = v14;
+    pBillboardRenderListD3D[v9].pQuards[0].pos.y = v14 - v27 * v29;
+    v15 = 1.0 - 1.0 / (pSoftBillboarda * 0.061758894);
+    pBillboardRenderListD3D[v9].pQuards[0].pos.z = v15;
+    v16 = 1.0 / pSoftBillboarda;
+    pBillboardRenderListD3D[v9].pQuards[0].rhw = 1.0 / pSoftBillboarda;
+    pBillboardRenderListD3D[v9].pQuards[0].texcoord.x = 0.0;
+    pBillboardRenderListD3D[v9].pQuards[0].texcoord.y = 0.0;
+    v17 = (double)((v10->uBufferWidth >> 1) - v10->uAreaX);
+    v18 = (double)(v10->uBufferHeight - v10->uAreaY - v10->uAreaHeight);
+    if ( v4->uFlags & 4 )
+      v17 = v17 * -1.0;
+    pBillboardRenderListD3D[v9].pQuards[1].specular = 0;
+    pBillboardRenderListD3D[v9].pQuards[1].diffuse = v12;
+    pBillboardRenderListD3D[v9].pQuards[1].pos.x = v13 - v17 * a1;
+    pBillboardRenderListD3D[v9].pQuards[1].pos.y = v32 - v18 * v29;
+    pBillboardRenderListD3D[v9].pQuards[1].pos.z = v15;
+    pBillboardRenderListD3D[v9].pQuards[1].rhw = v16;
+    pBillboardRenderListD3D[v9].pQuards[1].texcoord.x = 0.0;
+    pBillboardRenderListD3D[v9].pQuards[1].texcoord.y = 1.0;
+    v19 = v10->uBufferHeight - v10->uAreaY - v10->uAreaHeight;
+    v20 = (double)(v10->uAreaX + v10->uAreaWidth + (v10->uBufferWidth >> 1) - v10->uBufferWidth);
+    if ( v4->uFlags & 4 )
+      v20 = v20 * -1.0;
+    pBillboardRenderListD3D[v9].pQuards[2].specular = 0;
+    pBillboardRenderListD3D[v9].pQuards[2].diffuse = v12;
+    pBillboardRenderListD3D[v9].pQuards[2].pos.x = v20 * a1 + v13;
+    pBillboardRenderListD3D[v9].pQuards[2].pos.y = v32 - (double)v19 * v29;
+    pBillboardRenderListD3D[v9].pQuards[2].pos.z = v15;
+    pBillboardRenderListD3D[v9].pQuards[2].rhw = v16;
+    pBillboardRenderListD3D[v9].pQuards[2].texcoord.x = 1.0;
+    pBillboardRenderListD3D[v9].pQuards[2].texcoord.y = 1.0;
+    v21 = v10->uBufferHeight - v10->uAreaY;
+    v22 = (double)(v10->uAreaX + v10->uAreaWidth + (v10->uBufferWidth >> 1) - v10->uBufferWidth);
+    if ( v4->uFlags & 4 )
+      v22 = v22 * -1.0;
+    pBillboardRenderListD3D[v9].pQuards[3].specular = 0;
+    pBillboardRenderListD3D[v9].pQuards[3].diffuse = v12;
+    pBillboardRenderListD3D[v9].pQuards[3].pos.x = v22 * a1 + v13;
+    pBillboardRenderListD3D[v9].pQuards[3].pos.y = v32 - (double)v21 * v29;
+    pBillboardRenderListD3D[v9].pQuards[3].pos.z = v15;
+    pBillboardRenderListD3D[v9].pQuards[3].rhw = v16;
+    pBillboardRenderListD3D[v9].pQuards[3].texcoord.x = 1.0;
+    pBillboardRenderListD3D[v9].pQuards[3].texcoord.y = 0.0;
+    v23 = v10->pTexture;
+    pBillboardRenderListD3D[v9].uNumVertices = 4;
+    pBillboardRenderListD3D[v9].flt_88 = pSoftBillboarda;
+    pBillboardRenderListD3D[v9].pTexture = v23;
+  }
+}
+
+
+
+//----- (004A354F) --------------------------------------------------------
+void Render::MakeParticleBillboardAndPush_BLV(RenderBillboardTransform_local0 *a2, IDirect3DTexture2 *a3, unsigned int uDiffuse, int angle)
+{
+  double v5; // st7@3
+  float v6; // ST20_4@3
+  float v7; // ST00_4@3
+  unsigned int v8; // esi@3
+  int v9; // eax@3
+  int v10; // ebx@3
+  float v11; // ST28_4@3
+  double v12; // st7@3
+  float v13; // ST24_4@3
+  double v14; // st6@3
+  float v15; // ST1C_4@3
+  float v16; // ST2C_4@3
+  float v17; // ST30_4@3
+  signed int v18; // ST18_4@3
+  signed int v19; // ST14_4@3
+  signed int v20; // ST10_4@3
+  signed int v21; // eax@3
+  double v22; // st6@3
+  float v23; // ST2C_4@3
+  float v24; // ST30_4@3
+  signed int v25; // ST10_4@3
+  signed int v26; // ST14_4@3
+  signed int v27; // ST18_4@3
+  signed int v28; // eax@3
+  double v29; // st6@3
+  float v30; // ecx@3
+  float v31; // ST2C_4@3
+  float v32; // ST30_4@3
+  signed int v33; // ST10_4@3
+  signed int v34; // ST14_4@3
+  signed int v35; // ST18_4@3
+  signed int v36; // eax@3
+  float v37; // ecx@3
+  double v38; // st6@3
+  float v39; // ST2C_4@3
+  float v40; // ST30_4@3
+  signed int v41; // ST10_4@3
+  signed int v42; // ST14_4@3
+  signed int v43; // ST18_4@3
+  signed int v44; // eax@3
+  double v45; // st6@3
+  float v46; // eax@3
+
+  if ( this->uNumD3DSceneBegins )
+  {
+    if ( HIWORD(a2->sZValue) )
+    {
+      v5 = (double)HIWORD(a2->sZValue);
+      v6 = v5;
+      v7 = v5;
+      v8 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v7));
+      pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_1;
+      pBillboardRenderListD3D[v8].field_90 = a2->field_44;
+      pBillboardRenderListD3D[v8].sZValue = a2->sZValue;
+      pBillboardRenderListD3D[v8].uParentBillboardID = a2->uParentBillboardID;
+      v9 = a2->uScreenSpaceX;
+      v10 = a2->uScreenSpaceY;
+      v11 = (double)(a2->field_10 & 0xFFFF) * 0.000015260186 + (double)HIWORD(a2->field_10);
+      v12 = (double)v9;
+      v13 = v12;
+      v14 = (double)(v10 - 12);
+      v15 = v14;
+      v16 = (double)(v9 - 12) - v12;
+      v17 = (double)(v10 - 25) - v14;
+      v18 = stru_5C6E00->SinCos(angle);
+      v19 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+      v20 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+      v21 = stru_5C6E00->SinCos(angle);
+      pBillboardRenderListD3D[v8].pQuards[0].pos.x = (((double)(unsigned __int16)v18 * 0.000015259022
+                                                       + (double)(v18 >> 16))
+                                                       * v16
+                                                       - ((double)(unsigned __int16)v19 * 0.000015259022
+                                                       + (double)(v19 >> 16))
+                                                       * v17)
+                                                       * v11 + v13;
+      v22 = (((double)(unsigned __int16)v21 * 0.000015259022 + (double)(v21 >> 16)) * v17
+           + ((double)(unsigned __int16)v20 * 0.000015259022 + (double)(v20 >> 16)) * v16
+           - 12.0)
+          * v11
+          + (double)a2->uScreenSpaceY;
+      pBillboardRenderListD3D[v8].pQuards[0].specular = 0;
+      pBillboardRenderListD3D[v8].pQuards[0].diffuse = uDiffuse;
+      pBillboardRenderListD3D[v8].pQuards[0].pos.y = v22;
+      pBillboardRenderListD3D[v8].pQuards[0].pos.z = 1.0 - 1.0 / (v6 * 0.061758894);
+      pBillboardRenderListD3D[v8].pQuards[0].rhw = 1.0 / v6;
+      pBillboardRenderListD3D[v8].pQuards[0].texcoord.x = 0.0;
+      pBillboardRenderListD3D[v8].pQuards[0].texcoord.y = 0.0;
+      v31 = (double)(a2->uScreenSpaceX + 12) - v13;
+      v32 = (double)a2->uScreenSpaceY - v15;
+      v25 = stru_5C6E00->SinCos(angle);
+      v26 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+      v27 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+      v28 = stru_5C6E00->SinCos(angle);
+      pBillboardRenderListD3D[v8].pQuards[1].pos.x = (((double)(unsigned __int16)v25 * 0.000015259022
+                                                       + (double)(v25 >> 16))
+                                                       * v23
+                                                       - ((double)(unsigned __int16)v26 * 0.000015259022
+                                                       + (double)(v26 >> 16))
+                                                       * v24)
+                                                       * v11 + v13;
+      v29 = (((double)(unsigned __int16)v28 * 0.000015259022 + (double)(v28 >> 16)) * v24
+           + ((double)(unsigned __int16)v27 * 0.000015259022 + (double)(v27 >> 16)) * v23
+           - 12.0)
+          * v11
+          + (double)a2->uScreenSpaceY;
+      pBillboardRenderListD3D[v8].pQuards[1].pos.z = pRenderer->pBillboardRenderListD3D[v8].pQuards[0].pos.z;
+      v30 = pBillboardRenderListD3D[v8].pQuards[0].rhw;
+      pBillboardRenderListD3D[v8].pQuards[1].pos.y = v29;
+      pBillboardRenderListD3D[v8].pQuards[1].specular = 0;
+      pBillboardRenderListD3D[v8].pQuards[1].rhw = v30;
+      pBillboardRenderListD3D[v8].pQuards[1].diffuse = uDiffuse;
+      pBillboardRenderListD3D[v8].pQuards[1].texcoord.x = 0.0;
+      pBillboardRenderListD3D[v8].pQuards[1].texcoord.y = 1.0;
+      v23 = (double)(a2->uScreenSpaceX - 12) - v13;
+      v24 = (double)a2->uScreenSpaceY - v15;
+      v33 = stru_5C6E00->SinCos(angle);
+      v34 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+      v35 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+      v36 = stru_5C6E00->SinCos(angle);
+      pBillboardRenderListD3D[v8].pQuards[2].pos.x = (((double)(unsigned __int16)v33 * 0.000015259022
+                                                        + (double)(v33 >> 16))
+                                                        * v31
+                                                        - ((double)(unsigned __int16)v34 * 0.000015259022
+                                                        + (double)(v34 >> 16))
+                                                        * v32)
+                                                        * v11 + v13;
+      v37 = pBillboardRenderListD3D[v8].pQuards[0].pos.z;
+      v38 = (((double)(unsigned __int16)v36 * 0.000015259022 + (double)(v36 >> 16)) * v32
+           + ((double)(unsigned __int16)v35 * 0.000015259022 + (double)(v35 >> 16)) * v31
+           - 12.0)
+          * v11
+          + (double)a2->uScreenSpaceY;
+      pBillboardRenderListD3D[v8].pQuards[2].specular = 0;
+      pBillboardRenderListD3D[v8].pQuards[2].pos.z = v37;
+      pBillboardRenderListD3D[v8].pQuards[2].rhw = pBillboardRenderListD3D[v8].pQuards[0].rhw;
+      pBillboardRenderListD3D[v8].pQuards[2].diffuse = uDiffuse;
+      pBillboardRenderListD3D[v8].pQuards[2].pos.y = v38;
+      pBillboardRenderListD3D[v8].pQuards[2].texcoord.x = 1.0;
+      pBillboardRenderListD3D[v8].pQuards[2].texcoord.y = 1.0;
+      v39 = (double)(a2->uScreenSpaceX + 12) - v13;
+      v40 = (double)(a2->uScreenSpaceY - 25) - v15;
+      v41 = stru_5C6E00->SinCos(angle);
+      v42 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+      v43 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+      v44 = stru_5C6E00->SinCos(angle);
+      pBillboardRenderListD3D[v8].pQuards[3].pos.x = (((double)(unsigned __int16)v41 * 0.000015259022
+                                                        + (double)(v41 >> 16))
+                                                        * v39
+                                                        - ((double)(unsigned __int16)v42 * 0.000015259022
+                                                        + (double)(v42 >> 16))
+                                                        * v40)
+                                                        * v11 + v13;
+      v45 = (((double)(unsigned __int16)v44 * 0.000015259022 + (double)(v44 >> 16)) * v40
+           + ((double)(unsigned __int16)v43 * 0.000015259022 + (double)(v43 >> 16)) * v39
+           - 12.0)
+          * v11
+          + (double)a2->uScreenSpaceY;
+      v46 = pBillboardRenderListD3D[v8].pQuards[0].pos.z;
+      pBillboardRenderListD3D[v8].pQuards[3].specular = 0;
+      pBillboardRenderListD3D[v8].pQuards[3].pos.z = v46;
+      pBillboardRenderListD3D[v8].pQuards[3].rhw = pBillboardRenderListD3D[v8].pQuards[0].rhw;
+      pBillboardRenderListD3D[v8].pQuards[3].diffuse = uDiffuse;
+      pBillboardRenderListD3D[v8].pTexture = a3;
+      pBillboardRenderListD3D[v8].flt_88 = v6;
+      pBillboardRenderListD3D[v8].uNumVertices = 4;
+      pBillboardRenderListD3D[v8].pQuards[3].pos.y = v45;
+      pBillboardRenderListD3D[v8].pQuards[3].texcoord.x = 1.0;
+      pBillboardRenderListD3D[v8].pQuards[3].texcoord.y = 0.0;
+    }
+  }
+}
+
+
+//----- (004A3AD9) --------------------------------------------------------
+void Render::MakeParticleBillboardAndPush_ODM(RenderBillboardTransform_local0 *a2, IDirect3DTexture2 *a3, unsigned int uDiffuse, int angle)
+{
+  double v5; // st7@2
+  float v6; // ST28_4@2
+  float v7; // ST00_4@2
+  unsigned int v8; // esi@2
+  int v9; // eax@2
+  int v10; // ebx@2
+  float v11; // ST34_4@2
+  double v12; // st7@2
+  float v13; // ST2C_4@2
+  double v14; // st6@2
+  float v15; // ST24_4@2
+  float v16; // ST38_4@2
+  float v17; // ST3C_4@2
+  signed int v18; // ST1C_4@2
+  int v19; // ST30_4@2
+  signed int v20; // ST20_4@2
+  signed int v21; // ST18_4@2
+  signed int v22; // eax@2
+  double v23; // st6@2
+  float v24; // ST20_4@2
+  float v25; // ST1C_4@2
+  float v26; // ST38_4@2
+  float v27; // ST3C_4@2
+  signed int v28; // ST18_4@2
+  signed int v29; // ST14_4@2
+  signed int v30; // ST10_4@2
+  signed int v31; // eax@2
+  double v32; // st6@2
+  float v33; // ST38_4@2
+  float v34; // ST3C_4@2
+  signed int v35; // ST10_4@2
+  signed int v36; // ST14_4@2
+  signed int v37; // ST18_4@2
+  signed int v38; // eax@2
+  double v39; // st6@2
+  float v40; // ST38_4@2
+  float v41; // ST3C_4@2
+  signed int v42; // ST10_4@2
+  signed int v43; // ST14_4@2
+  signed int v44; // ST18_4@2
+  signed int v45; // eax@2
+  double v46; // st6@2
+
+  if ( this->uNumD3DSceneBegins )
+  {
+    v5 = (double)HIWORD(a2->sZValue);
+    v6 = v5;
+    v7 = v5;
+    v8 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v7));
+    pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_1;
+    pBillboardRenderListD3D[v8].field_90 = a2->field_44;
+    pBillboardRenderListD3D[v8].sZValue = a2->sZValue;
+    pBillboardRenderListD3D[v8].uParentBillboardID = a2->uParentBillboardID;
+    v9 = a2->uScreenSpaceX;
+    v10 = a2->uScreenSpaceY;
+    v11 = (double)(a2->field_10 & 0xFFFF) * 0.000015260186 + (double)HIWORD(a2->field_10);
+    v12 = (double)v9;
+    v13 = v12;
+    v14 = (double)(v10 - 12);
+    v15 = v14;
+    v16 = (double)(v9 - 12) - v12;
+    v17 = (double)(v10 - 25) - v14;
+    v18 = stru_5C6E00->SinCos(angle);
+    v19 = angle - stru_5C6E00->uIntegerHalfPi;
+    v20 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+    v21 = stru_5C6E00->SinCos(v19);
+    v22 = stru_5C6E00->SinCos(angle);
+    pBillboardRenderListD3D[v8].pQuards[0].pos.x = (((double)(unsigned __int16)v18 * 0.000015259022
+                                                    + (double)(v18 >> 16))
+                                                    * v16
+                                                    - ((double)(unsigned __int16)v20 * 0.000015259022
+                                                    + (double)(v20 >> 16))
+                                                    * v17)
+                                                    * v11 + v13;
+    v23 = (((double)(unsigned __int16)v22 * 0.000015259022 + (double)(v22 >> 16)) * v17
+         + ((double)(unsigned __int16)v21 * 0.000015259022 + (double)(v21 >> 16)) * v16
+         - 12.0)
+        * v11
+        + (double)a2->uScreenSpaceY;
+    pBillboardRenderListD3D[v8].pQuards[0].specular = 0;
+    pBillboardRenderListD3D[v8].pQuards[0].diffuse = uDiffuse;
+    pBillboardRenderListD3D[v8].pQuards[0].pos.y = v23;
+    v24 = 1.0 - 1.0 / (v6 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+    pBillboardRenderListD3D[v8].pQuards[0].pos.z = v24;
+    v25 = 1.0 / v6;
+    pBillboardRenderListD3D[v8].pQuards[0].rhw = v25;
+    pBillboardRenderListD3D[v8].pQuards[0].texcoord.x = 0.0;
+    pBillboardRenderListD3D[v8].pQuards[0].texcoord.y = 0.0;
+    v26 = (double)(a2->uScreenSpaceX - 12) - v13;
+    v27 = (double)a2->uScreenSpaceY - v15;
+    v28 = stru_5C6E00->SinCos(angle);
+    v29 = stru_5C6E00->SinCos(v19);
+    v30 = stru_5C6E00->SinCos(v19);
+    v31 = stru_5C6E00->SinCos(angle);
+    pBillboardRenderListD3D[v8].pQuards[1].pos.x = (((double)(unsigned __int16)v28 * 0.000015259022
+                                                     + (double)(v28 >> 16))
+                                                     * v26
+                                                     - ((double)(unsigned __int16)v29 * 0.000015259022
+                                                     + (double)(v29 >> 16))
+                                                     * v27)
+                                                     * v11 + v13;
+    v32 = (((double)(unsigned __int16)v31 * 0.000015259022 + (double)(v31 >> 16)) * v27
+         + ((double)(unsigned __int16)v30 * 0.000015259022 + (double)(v30 >> 16)) * v26
+         - 12.0)
+        * v11
+        + (double)a2->uScreenSpaceY;
+    pBillboardRenderListD3D[v8].pQuards[1].pos.z = v24;
+    pBillboardRenderListD3D[v8].pQuards[1].pos.y = v32;
+    pBillboardRenderListD3D[v8].pQuards[1].specular = 0;
+    pBillboardRenderListD3D[v8].pQuards[1].rhw = v25;
+    pBillboardRenderListD3D[v8].pQuards[1].diffuse = uDiffuse;
+    pBillboardRenderListD3D[v8].pQuards[1].texcoord.x = 0.0;
+    pBillboardRenderListD3D[v8].pQuards[1].texcoord.y = 1.0;
+    v33 = (double)(a2->uScreenSpaceX + 12) - v13;
+    v34 = (double)a2->uScreenSpaceY - v15;
+    v35 = stru_5C6E00->SinCos(angle);
+    v36 = stru_5C6E00->SinCos(v19);
+    v37 = stru_5C6E00->SinCos(v19);
+    v38 = stru_5C6E00->SinCos(angle);
+    pBillboardRenderListD3D[v8].pQuards[2].pos.x = (((double)(unsigned __int16)v35 * 0.000015259022
+                                                     + (double)(v35 >> 16))
+                                                     * v33
+                                                     - ((double)(unsigned __int16)v36 * 0.000015259022
+                                                     + (double)(v36 >> 16))
+                                                     * v34)
+                                                     * v11 + v13;
+    v39 = (((double)(unsigned __int16)v38 * 0.000015259022 + (double)(v38 >> 16)) * v34
+         + ((double)(unsigned __int16)v37 * 0.000015259022 + (double)(v37 >> 16)) * v33
+         - 12.0)
+        * v11
+        + (double)a2->uScreenSpaceY;
+    pBillboardRenderListD3D[v8].pQuards[2].specular = 0;
+    pBillboardRenderListD3D[v8].pQuards[2].pos.z = v24;
+    pBillboardRenderListD3D[v8].pQuards[2].rhw = v25;
+    pBillboardRenderListD3D[v8].pQuards[2].diffuse = uDiffuse;
+    pBillboardRenderListD3D[v8].pQuards[2].pos.y = v39;
+    pBillboardRenderListD3D[v8].pQuards[2].texcoord.x = 1.0;
+    pBillboardRenderListD3D[v8].pQuards[2].texcoord.y = 1.0;
+    v40 = (double)(a2->uScreenSpaceX + 12) - v13;
+    v41 = (double)(a2->uScreenSpaceY - 25) - v15;
+    v42 = stru_5C6E00->SinCos(angle);
+    v43 = stru_5C6E00->SinCos(v19);
+    v44 = stru_5C6E00->SinCos(v19);
+    v45 = stru_5C6E00->SinCos(angle);
+    pBillboardRenderListD3D[v8].pQuards[3].pos.x = (((double)(unsigned __int16)v42 * 0.000015259022
+                                                     + (double)(v42 >> 16))
+                                                     * v40
+                                                     - ((double)(unsigned __int16)v43 * 0.000015259022
+                                                     + (double)(v43 >> 16))
+                                                     * v41)
+                                                     * v11 + v13;
+    v46 = (((double)(unsigned __int16)v45 * 0.000015259022 + (double)(v45 >> 16)) * v41
+         + ((double)(unsigned __int16)v44 * 0.000015259022 + (double)(v44 >> 16)) * v40
+         - 12.0)
+        * v11
+        + (double)a2->uScreenSpaceY;
+    pBillboardRenderListD3D[v8].pQuards[3].specular = 0;
+    pBillboardRenderListD3D[v8].pQuards[3].pos.z = v24;
+    pBillboardRenderListD3D[v8].pQuards[3].rhw = v25;
+    pBillboardRenderListD3D[v8].pQuards[3].diffuse = uDiffuse;
+    pBillboardRenderListD3D[v8].pTexture = a3;
+    pBillboardRenderListD3D[v8].flt_88 = v6;
+    pBillboardRenderListD3D[v8].uNumVertices = 4;
+    pBillboardRenderListD3D[v8].pQuards[3].pos.y = v46;
+    pBillboardRenderListD3D[v8].pQuards[3].texcoord.x = 1.0;
+    pBillboardRenderListD3D[v8].pQuards[3].texcoord.y = 0.0;
+  }
+}
+
+
+//----- (004A4023) --------------------------------------------------------
+void Render::TransformBillboard(RenderBillboardTransform_local0 *a2, Sprite *pSprite, int a1a, RenderBillboard *pBillboard)
+{
+  RenderBillboardTransform_local0 *v5; // ebx@2
+  double v6; // st7@2
+  float v7; // ST08_4@2
+  unsigned int v8; // esi@2
+  Sprite *v9; // edi@5
+  signed int v10; // eax@9
+  signed int v11; // eax@9
+  int v12; // eax@12
+  double v13; // st7@12
+  double v14; // st6@14
+  double v15; // st5@14
+  unsigned int v16; // ecx@16
+  double v17; // st7@16
+  double v18; // st5@16
+  double v19; // st4@16
+  double v20; // st5@18
+  double v21; // st4@18
+  IDirect3DTexture2 *v22; // eax@20
+  signed int v23; // [sp+18h] [bp-18h]@5
+  signed int v24; // [sp+1Ch] [bp-14h]@5
+  float v25; // [sp+1Ch] [bp-14h]@12
+  float v26; // [sp+20h] [bp-10h]@5
+  float v27; // [sp+20h] [bp-10h]@12
+  Render *a3; // [sp+24h] [bp-Ch]@1
+  float v29; // [sp+28h] [bp-8h]@5
+  float v30; // [sp+2Ch] [bp-4h]@5
+  float v31; // [sp+38h] [bp+8h]@2
+  float pSpritea; // [sp+3Ch] [bp+Ch]@5
+  float a1b; // [sp+40h] [bp+10h]@12
+  float pBillboarda; // [sp+44h] [bp+14h]@12
+
+  auto a1 = this;
+  a3 = a1;
+  if ( a1->uNumD3DSceneBegins )
+  {
+    v5 = a2;
+    v6 = (double)HIWORD(a2->sZValue);
+    v31 = v6;
+    v7 = v6;
+    v8 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v7));
+    if ( BYTE3(v5->uTintColor) )
+      pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_3;
+    else
+      pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Transparent;
+    v9 = pSprite;
+    pBillboardRenderListD3D[v8].field_90 = v5->field_44;
+    pBillboardRenderListD3D[v8].sZValue = v5->sZValue;
+    pBillboardRenderListD3D[v8].uParentBillboardID = v5->uParentBillboardID;
+    v24 = v5->uScreenSpaceX;
+    v23 = v5->uScreenSpaceY;
+    v30 = (double)(v5->field_10 & 0xFFFF) * 0.000015260186 + (double)HIWORD(v5->field_10);
+    v29 = (double)(v5->field_14 & 0xFFFF) * 0.000015260186 + (double)HIWORD(v5->field_14);
+    pSpritea = (double)((v9->uBufferWidth >> 1) - v9->uAreaX);
+    v26 = (double)(v9->uBufferHeight - v9->uAreaY);
+    if ( v5->uFlags & 4 )
+      pSpritea = pSpritea * -1.0;
+    if ( v5->uTintColor & 0xFFFFFF && a3->bTinting )
+    {
+      v10 = GetActorTintColor(a1a, 0, v31, 0, pBillboard);
+      v11 = sub_4A19D8(v5->uTintColor, v10);
+      if ( BYTE3(v5->uTintColor) )
+        v11 = (unsigned int)((char *)&array_77EC08[1852].pEdgeList1[17] + 3) & ((unsigned int)v11 >> 1);
+    }
+    else
+    {
+      v11 = GetActorTintColor(a1a, 0, v31, 0, pBillboard);
+    }
+    pBillboardRenderListD3D[v8].pQuards[0].diffuse = v11;
+    v12 = 0;
+    pBillboarda = (double)v24;
+    pBillboardRenderListD3D[v8].pQuards[0].pos.x = pBillboarda - pSpritea * v30;
+    a1b = (double)v23;
+    pBillboardRenderListD3D[v8].pQuards[0].pos.y = a1b - v26 * v29;
+    v27 = v31 * 1000.0;
+    v13 = 1.0;
+    pBillboardRenderListD3D[v8].pQuards[0].pos.z = 1.0
+                                                    - 1.0 / (v27 / (double)pOutdoorCamera->shading_dist_mist);
+    v25 = 1.0 / v31;
+    pBillboardRenderListD3D[v8].pQuards[0].rhw = v25;
+    if ( a3->bUsingSpecular )
+    {
+      v12 = sub_47C3D7_get_fog_related_stuff(0, 0, v31);
+      v13 = 1.0;
+    }
+    pBillboardRenderListD3D[v8].pQuards[0].specular = v12;
+    pBillboardRenderListD3D[v8].pQuards[0].texcoord.x = 0.0;
+    pBillboardRenderListD3D[v8].pQuards[0].texcoord.y = 0.0;
+    v14 = (double)((v9->uBufferWidth >> 1) - v9->uAreaX);
+    v15 = (double)(v9->uBufferHeight - v9->uAreaHeight - v9->uAreaY);
+    if ( v5->uFlags & 4 )
+      v14 = v14 * -1.0;
+    v16 = pBillboardRenderListD3D[v8].pQuards[0].diffuse;
+    pBillboardRenderListD3D[v8].pQuards[1].specular = v12;
+    pBillboardRenderListD3D[v8].pQuards[1].diffuse = v16;
+    pBillboardRenderListD3D[v8].pQuards[1].pos.x = pBillboarda - v14 * v30;
+    pBillboardRenderListD3D[v8].pQuards[1].pos.y = a1b - v15 * v29;
+    v17 = v13 - v13 / (v27 / (double)pOutdoorCamera->shading_dist_mist);
+    pBillboardRenderListD3D[v8].pQuards[1].pos.z = v17;
+    pBillboardRenderListD3D[v8].pQuards[1].rhw = v25;
+    pBillboardRenderListD3D[v8].pQuards[1].texcoord.x = 0.0;
+    pBillboardRenderListD3D[v8].pQuards[1].texcoord.y = 1.0;
+    v18 = (double)(v9->uAreaWidth + v9->uAreaX + (v9->uBufferWidth >> 1) - v9->uBufferWidth);
+    v19 = (double)(v9->uBufferHeight - v9->uAreaHeight - v9->uAreaY);
+    if ( v5->uFlags & 4 )
+      v18 = v18 * -1.0;
+    pBillboardRenderListD3D[v8].pQuards[2].diffuse = v16;
+    pBillboardRenderListD3D[v8].pQuards[2].specular = v12;
+    pBillboardRenderListD3D[v8].pQuards[2].pos.x = v18 * v30 + pBillboarda;
+    pBillboardRenderListD3D[v8].pQuards[2].pos.y = a1b - v19 * v29;
+    pBillboardRenderListD3D[v8].pQuards[2].pos.z = v17;
+    pBillboardRenderListD3D[v8].pQuards[2].rhw = v25;
+    pBillboardRenderListD3D[v8].pQuards[2].texcoord.x = 1.0;
+    pBillboardRenderListD3D[v8].pQuards[2].texcoord.y = 1.0;
+    v20 = (double)(v9->uAreaWidth + v9->uAreaX + (v9->uBufferWidth >> 1) - v9->uBufferWidth);
+    v21 = (double)(v9->uBufferHeight - v9->uAreaY);
+    if ( v5->uFlags & 4 )
+      v20 = v20 * -1.0;
+    pBillboardRenderListD3D[v8].pQuards[3].diffuse = v16;
+    pBillboardRenderListD3D[v8].pQuards[3].specular = v12;
+    pBillboardRenderListD3D[v8].pQuards[3].pos.x = v20 * v30 + pBillboarda;
+    pBillboardRenderListD3D[v8].pQuards[3].pos.y = a1b - v21 * v29;
+    pBillboardRenderListD3D[v8].pQuards[3].pos.z = v17;
+    pBillboardRenderListD3D[v8].pQuards[3].rhw = v25;
+    pBillboardRenderListD3D[v8].pQuards[3].texcoord.x = 1.0;
+    pBillboardRenderListD3D[v8].pQuards[3].texcoord.y = 0.0;
+    v22 = v9->pTexture;
+    pBillboardRenderListD3D[v8].uNumVertices = 4;
+    pBillboardRenderListD3D[v8].pTexture = v22;
+    pBillboardRenderListD3D[v8].flt_88 = v31;
+  }
+}
+
+
+//----- (004A48E4) --------------------------------------------------------
+int Render::MakeParticleBillboardAndPush_BLV_Software(int screenSpaceX, int screenSpaceY, int z, int lightColor, int a6)
+{
+  int v6; // ecx@1
+  int v7; // ebx@1
+  int v8; // ecx@1
+  int v9; // edx@1
+  int v10; // edi@1
+  unsigned int x; // esi@1
+  int result; // eax@8
+  int v13; // [sp+Ch] [bp-10h]@1
+  int v14; // [sp+10h] [bp-Ch]@1
+  int v15; // [sp+14h] [bp-8h]@1
+  int v16; // [sp+18h] [bp-4h]@1
+  int v17; // [sp+24h] [bp+8h]@1
+  unsigned int v18; // [sp+28h] [bp+Ch]@1
+  int v19; // [sp+34h] [bp+18h]@1
+
+  v6 = screenSpaceX;
+  v7 = (a6 >> 1) + screenSpaceY;
+  v17 = 0;
+  v15 = 0;
+  v8 = (a6 >> 1) + v6;
+  v14 = (a6 >> 1) * (a6 >> 1);
+  v9 = 2 * (a6 >> 1);
+  v10 = (a6 >> 1) * ((a6 >> 1) - 1);
+  x = v8 - (a6 >> 1);
+  v16 = (a6 >> 1) + screenSpaceY - v8;
+  v19 = a6 >> 1;
+  v13 = v9;
+  v18 = v8;
+  do
+  {
+    sr_4A46E6_draw_particle_segment(x, v16 + v18, z, 2 * v19, lightColor);
+    if ( v15 )
+      sr_4A46E6_draw_particle_segment(x, v17 + v7, z, 2 * v19, lightColor);
+    v14 -= v15;
+    if ( v14 <= v10 )
+    {
+      if ( v19 != v17 )
+      {
+        sr_4A46E6_draw_particle_segment(v18, v16 + x, z, 2 * v17, lightColor);
+        sr_4A46E6_draw_particle_segment(v18, v19 + v7, z, 2 * v17, lightColor);
+      }
+      --v19;
+      v13 -= 2;
+      ++x;
+      v10 -= v13;
+    }
+    result = v17++;
+    v15 += 2;
+    --v18;
+  }
+  while ( result < v19 );
+  return result;
+}
+
+//----- (004A49D0) --------------------------------------------------------
+void Render::DrawProjectile(float srcX, float srcY, float a3, float a4, float dstX, float dstY, float a7, float a8, IDirect3DTexture2 *a9)
+{
+  int v10; // eax@1
+  unsigned int v11; // ebx@1
+  unsigned int v12; // ecx@1
+  int v13; // edx@2
+  int v14; // edx@4
+  unsigned int v15; // edx@6
+  double v16; // st7@7
+  double v17; // st7@7
+  double v18; // st6@7
+  double v19; // st4@7
+  double v20; // st4@8
+  double v21; // st4@10
+  double v22; // st4@10
+  double v23; // st4@10
+  double v24; // st4@10
+  double v25; // st4@11
+  double v26; // st4@13
+  double v27; // st5@13
+  double v28; // st4@13
+  RenderVertexD3D3 v29[4]; // [sp+0h] [bp-94h]@7
+  double v30; // [sp+80h] [bp-14h]@1
+  int v31; // [sp+88h] [bp-Ch]@1
+  signed int v32; // [sp+8Ch] [bp-8h]@1
+  int X; // [sp+90h] [bp-4h]@1
+  float a3a; // [sp+A4h] [bp+10h]@10
+  float a4a; // [sp+A8h] [bp+14h]@10
+
+  *(float *)&X = dstX - srcX;
+  v30 = *(float *)&X + 6.7553994e15;
+  v31 = LODWORD(v30);
+  *(float *)&v32 = dstY - srcY;
+  v30 = *(float *)&v32 + 6.7553994e15;
+  X = LODWORD(v30);
+  HIDWORD(v30) = abs(COERCE_UNSIGNED_INT64(*(float *)&v32 + 6.7553994e15));
+  v10 = abs(v31);
+  v32 = v10;
+  v11 = HIDWORD(v30);
+  v12 = 0;
+  if ( v10 < SHIDWORD(v30) )
+  {
+    v13 = v10;
+    v10 = HIDWORD(v30);
+    v11 = v13;
+  }
+  if ( v10 < 0 )
+  {
+    v14 = v10;
+    v10 = 0;
+    v12 = v14;
+  }
+  if ( (signed int)v11 < (signed int)v12 )
+  {
+    v15 = v12;
+    v12 = v11;
+    v11 = v15;
+  }
+  v32 = (11 * v11 >> 5) + (v12 >> 2) + v10;
+  v16 = 1.0 / (double)v32;
+  *(float *)&v31 = (double)v31 * v16;
+  *(float *)&X = (double)X * v16;
+  v17 = *(float *)&X * a4;
+  v29[0].pos.x = srcX + v17;
+  v18 = *(float *)&v31 * a4;
+  v29[0].pos.y = srcY - v18;
+  v19 = a3;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+    v20 = v19 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist;
+  else
+    v20 = v19 * 0.061758894;
+  v29[0].diffuse = -1;
+  v29[0].specular = 0;
+  v29[0].pos.z = 1.0 - 1.0 / v20;
+  v21 = 1.0 / a3;
+  *((float *)&v30 + 1) = v21;
+  v29[0].rhw = v21;
+  v29[0].texcoord.x = 1.0;
+  v29[0].texcoord.y = 0.0;
+  v22 = *(float *)&X * a8;
+  a3a = v22;
+  v29[1].pos.x = v22 + dstX;
+  v23 = *(float *)&v31 * a8;
+  a4a = v23;
+  v29[1].pos.y = dstY - v23;
+  v24 = a7;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+    v25 = v24 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist;
+  else
+    v25 = v24 * 0.061758894;
+  v29[2].diffuse = -1;
+  v29[3].diffuse = -1;
+  *(_QWORD *)&v29[3].pos.z = __PAIR__(HIDWORD(v30), LODWORD(v29[0].pos.z));
+  v29[1].diffuse = -16711936;
+  v29[1].specular = 0;
+  v29[2].specular = 0;
+  v29[3].specular = 0;
+  v26 = 1.0 - 1.0 / v25;
+  v29[1].pos.z = v26;
+  v27 = v26;
+  v28 = 1.0 / a7;
+  v29[1].rhw = v28;
+  v29[1].texcoord.x = 1.0;
+  v29[1].texcoord.y = 1.0;
+  v29[2].pos.x = dstX - a3a;
+  v29[2].pos.y = a4a + dstY;
+  v29[2].pos.z = v27;
+  v29[2].rhw = v28;
+  v29[2].texcoord.x = 0.0;
+  v29[2].texcoord.y = 1.0;
+  v29[3].pos.x = srcX - v17;
+  v29[3].pos.y = v18 + srcY;
+  v29[3].texcoord.x = 0.0;
+  v29[3].texcoord.y = 0.0;
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, a9));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(
+    D3DPT_TRIANGLEFAN,
+    D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+    v29,
+    4,
+    24));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 2u));
+}
+
+
+//----- (004A4CC9) --------------------------------------------------------
+void Render::_4A4CC9(stru6_stru1_indoor_sw_billboard *a1, int a2)
+{
+  int v3; // eax@1
+  int v4; // edx@3
+  unsigned int v5; // eax@7
+  int v6; // edi@7
+  char *v7; // edx@8
+  char *v8; // ecx@8
+  char v9; // zf@9
+  double v10; // st6@9
+  double v11; // st6@10
+  int v12; // ebx@13
+  int v13; // ecx@16
+  unsigned int v14; // [sp+Ch] [bp-4h]@1
+
+  auto _this = this;
+
+  *(float *)&v14 = 1000000.0;
+  v3 = a1->field_10;
+  if ( v3 >= 3 )
+  {
+    if ( v3 > 0 )
+    {
+      _this = (Render *)&a1->field_14[62];
+      v4 = a1->field_10;
+      do
+      {
+        if ( *(float *)&this->bUserDirect3D < (double)*(float *)&v14 )
+          v14 = this->bUserDirect3D;
+        _this = (Render *)((char *)_this + 16);
+        --v4;
+      }
+      while ( v4 );
+    }
+    v5 = Billboard_ProbablyAddToListAndSortByZOrder(v14);
+    v6 = 0;
+    pBillboardRenderListD3D[v5].field_90 = 0;
+    pBillboardRenderListD3D[v5].uParentBillboardID = -1;
+    pBillboardRenderListD3D[v5].uOpacity = RenderBillboardD3D::Opaque_2;
+    if ( a1->field_10 > 0 )
+    {
+      v7 = (char *)&a1->field_14[62];
+      v8 = (char *)&pBillboardRenderListD3D[v5].pQuards[0].pos.z;
+      do
+      {
+        v9 = uCurrentlyLoadedLevelType == LEVEL_Indoor;
+        *((int *)v8 - 2) = *((int *)v7 - 2);
+        *((int *)v8 - 1) = *((int *)v7 - 1);
+        v10 = *(float *)v7;
+        if ( v9 )
+          v11 = v10 * 0.061758894;
+        else
+          v11 = v10 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist;
+        *(float *)v8 = 1.0 - 1.0 / v11;
+        *((float *)v8 + 1) = 1.0 / *(float *)v7;
+        if ( a2 & 0xFF000000 )
+          v12 = *((int *)v7 + 1);
+        else
+          v12 = a2;
+        *((int *)v8 + 3) = 0;
+        *((int *)v8 + 2) = v12;
+        ++v6;
+        v7 += 16;
+        *((float *)v8 + 4) = 0.0;
+        *((float *)v8 + 5) = 0.0;
+        v8 += 32;
+      }
+      while ( v6 < a1->field_10 );
+    }
+    v13 = a1->field_10;
+    pBillboardRenderListD3D[v5].pTexture = 0;
+    pBillboardRenderListD3D[v5].uNumVertices = v13;
+    LODWORD(pBillboardRenderListD3D[v5].flt_88) = v14;
+  }
+}
+
+
+//----- (004A4DE1) --------------------------------------------------------
+bool Render::LoadTexture(const char *pName, unsigned int bMipMaps, IDirectDrawSurface4 **pOutSurface, IDirect3DTexture2 **pOutTexture)
+{
+  HRESULT v12; // eax@14
+  unsigned __int16 *v13; // ecx@19
+  unsigned __int16 *v14; // eax@19
+  DWORD v15; // edx@20
+  HRESULT v16; // eax@23
+  stru350 Dst; // [sp+Ch] [bp-F8h]@12
+
+  auto pHWLTexture = pD3DBitmaps.LoadTexture(pName, bMipMaps);
+  if ( pHWLTexture )
+  {
+    bMipMaps = !strncmp(pName, "HDWTR", 5);
+    if ( !pRenderD3D->CreateTexture(
+            pHWLTexture->uWidth,
+            pHWLTexture->uHeight,
+            pOutSurface,
+            pOutTexture,
+            true,
+            bMipMaps,
+            uMinDeviceTextureDim) )
+      Abortf("HiScreen16::LoadTexture - D3Drend->CreateTexture() failed: %x", 0);
+    //v10 = *pOutSurface;
+    //v11 = 0;
+    if ( bMipMaps )
+    {
+      Dst._450DDE();
+      //v20 = 0;
+      Dst._450DF1(&stru_4EFCBC, &stru_4EFCBC);
+
+      IDirectDrawSurface4 *pNextSurf = *pOutSurface;
+      while ( 1 )
+      {
+        DDSCAPS2 v19;
+        memset(&v19, 0, sizeof(DDSCAPS2));
+        v19.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
+
+        DDSURFACEDESC2 desc;
+        memset(&desc, 0, sizeof(DDSURFACEDESC2));
+        desc.dwSize = sizeof(DDSURFACEDESC2);
+
+        if ( LockSurface_DDraw4(pNextSurf, &desc, 0x21u) )
+        {
+          Dst.sub_451007_scale_image_bicubic(
+            pHWLTexture->pPixels,
+            pHWLTexture->uWidth,
+            pHWLTexture->uHeight,
+            pHWLTexture->uWidth,
+            (unsigned short *)desc.lpSurface,
+            desc.dwWidth,
+            desc.dwHeight,
+            desc.lPitch >> 1,
+            0,
+            0);
+          ErrD3D(pNextSurf->Unlock(0));
+          //bMipMaps = 0x4D86ACu;
+        }
+        if (FAILED(pNextSurf->GetAttachedSurface(&v19, &pNextSurf)))
+          break;
+        //v10 = (IDirectDrawSurface4 *)pName;
+        //v11 = 0;
+      }
+      //v20 = -1;
+      //nullsub_1();
+    }
+    else
+    {
+        DDSCAPS2 v19;
+        memset(&v19, 0, sizeof(DDSCAPS2));
+        v19.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
+
+        DDSURFACEDESC2 desc;
+        memset(&desc, 0, sizeof(DDSURFACEDESC2));
+        desc.dwSize = sizeof(DDSURFACEDESC2);
+
+      if ( LockSurface_DDraw4(*pOutSurface, &desc, 0x21u) )
+      {
+        bMipMaps = 0;
+        v13 = pHWLTexture->pPixels;
+        v14 = (unsigned __int16 *)desc.lpSurface;
+        if ( desc.dwHeight )
+        {
+          do
+          {
+            v15 = 0;
+            if ( desc.dwWidth )
+            {
+              do
+              {
+                ++v15;
+                *v14 = *v13;
+                ++v14;
+                ++v13;
+              }
+              while ( v15 < desc.dwWidth );
+            }
+            ++bMipMaps;
+            v14 += (desc.lPitch >> 1) - desc.dwWidth;
+          }
+          while ( bMipMaps < desc.dwHeight );
+        }
+        ErrD3D((*pOutSurface)->Unlock(0));
+      }
+    }
+    delete [] pHWLTexture->pPixels;
+    delete pHWLTexture;
+    return true;
+  }
+  return false;
+}
+
+//----- (004A5048) --------------------------------------------------------
+HWLTexture *Render::MoveSpriteToDevice(Sprite *pSprite)
+{
+  Sprite *v2; // edi@1
+  Render *v3; // ebx@1
+  HWLTexture *result; // eax@1
+  HWLTexture *v5; // esi@1
+  unsigned int v6; // ST18_4@2
+  RenderD3D *v7; // ecx@2
+  Sprite *v8; // ebx@4
+  unsigned __int16 *v9; // edx@5
+  LPVOID v10; // eax@5
+  signed int v11; // ebx@5
+  signed int v12; // ecx@6
+  signed int v13; // edi@7
+  HRESULT v14; // eax@10
+  DDSURFACEDESC2 Dst; // [sp+Ch] [bp-7Ch]@4
+
+  v2 = pSprite;
+  v3 = this;
+  result = pD3DSprites.LoadTexture(pSprite->pName, pSprite->uPaletteID);
+  v5 = result;
+  if ( result )
+  {
+    v3->_gpu_memory_used += 2 * result->uWidth * result->uHeight;
+    v2->uAreaX = result->field_30;
+    v2->uAreaY = result->field_34;
+    v2->uBufferWidth = result->field_18;
+    v2->uBufferHeight = result->field_1C;
+    v2->uAreaWidth = result->field_20;
+    v2->uAreaHeight = result->field_24;
+    v6 = v3->uMinDeviceTextureDim;
+    v7 = v3->pRenderD3D;
+    if ( !v7->CreateTexture(result->uWidth, result->uHeight, &v2->pTextureSurface, &v2->pTexture, 1u, 0, v6) )
+      Abortf("HiScreen16::LoadTexture - D3Drend->CreateTexture() failed: %x", 0);
+    //pSprite = v2->pTextureSurface;
+    //pSprite = (Sprite *)pSprite->pName;
+    //v8 = pSprite;
+    memset(&Dst, 0, 0x7Cu);
+    Dst.dwSize = 124;
+    if ( LockSurface_DDraw4((IDirectDrawSurface4 *)v2->pTextureSurface, &Dst, 0x21u) )
+    {
+      v9 = v5->pPixels;
+      v10 = Dst.lpSurface;
+      v11 = 0;
+      if ( (signed int)v5->uHeight > 0 )
+      {
+        v12 = (signed int)v5->uWidth >> 1;
+        do
+        {
+          v13 = 0;
+          if ( v12 > 0 )
+          {
+            do
+            {
+              ++v13;
+              *(int *)v10 = *(int *)v9;
+              v9 += 2;
+              v10 = (char *)v10 + 4;
+            }
+            while ( v13 < (signed int)v5->uWidth >> 1 );
+          }
+          v12 = (signed int)v5->uWidth >> 1;
+          ++v11;
+          v10 = (char *)v10 + 4 * ((Dst.lPitch >> 2) - v12);
+        }
+        while ( v11 < (signed int)v5->uHeight );
+      }
+      ErrD3D(v2->pTextureSurface->Unlock(0));
+    }
+    free(v5->pPixels);
+    free(v5);
+    result = (HWLTexture *)1;
+  }
+  return result;
+}
+
+//----- (004A51CB) --------------------------------------------------------
+void Render::BeginScene()
+{
+  Render *v1; // esi@1
+  unsigned int v2; // eax@1
+  int v3; // eax@5
+  unsigned __int16 **v4; // edi@6
+  char *v5; // ebx@7
+  DDSURFACEDESC2 Dst; // [sp+Ch] [bp-7Ch]@4
+
+  v1 = this;
+  v2 = this->uNumSceneBegins;
+  this->uNumSceneBegins = v2 + 1;
+  if ( !v2 )
+  {
+    if ( this->pRenderD3D )
+    {
+      if ( this->bColorKeySupported )
+      {
+        memset(&Dst, 0, 0x7Cu);
+        Dst.dwSize = 124;
+        if ( LockSurface_DDraw4(v1->pColorKeySurface4, &Dst, 0x801u) )
+        {
+          v1->pTargetSurface = (unsigned __int16 *)Dst.lpSurface;
+          v3 = Dst.lPitch >> 1;
+          v1->uTargetSurfacePitch = Dst.lPitch >> 1;
+LABEL_10:
+          v1->field_18_locked_pitch = v3;
+          goto LABEL_11;
+        }
+        goto LABEL_8;
+      }
+    }
+    else
+    {
+      v4 = &this->pTargetSurface;
+      if ( !this->pTargetSurface )
+      {
+        v5 = (char *)&this->uTargetSurfacePitch;
+        LockRenderSurface((void **)&this->pTargetSurface, &this->uTargetSurfacePitch);
+        if ( *v4 )
+        {
+          v3 = *(int *)v5;
+          goto LABEL_10;
+        }
+LABEL_8:
+        --v1->uNumSceneBegins;
+        return;
+      }
+    }
+LABEL_11:
+    RestoreFrontBuffer();
+  }
+}
+
+//----- (004A527D) --------------------------------------------------------
+void Render::EndScene()
+{
+  unsigned int v1; // edx@1
+  unsigned int v2; // edx@2
+  HRESULT v3; // eax@5
+
+  v1 = this->uNumSceneBegins;
+  if ( v1 )
+  {
+    v2 = v1 - 1;
+    this->uNumSceneBegins = v2;
+    if ( !v2 )
+    {
+      if ( this->pRenderD3D )
+      {
+        if ( this->bColorKeySupported )
+        {
+          this->pTargetSurface = 0;
+          this->uTargetSurfacePitch = 0;
+          this->field_18_locked_pitch = 0;
+          ErrD3D(this->pColorKeySurface4->Unlock(0));
+        }
+      }
+      else
+      {
+        this->pTargetSurface = 0;
+        this->uTargetSurfacePitch = 0;
+        this->field_18_locked_pitch = 0;
+        UnlockBackBuffer();
+      }
+    }
+  }
+}
+
+
+//----- ( ) --------------------------------------------------------
+unsigned int Render::_4A52F1(unsigned int this_, float a3)
+{
+  unsigned int v3; // esi@1
+  double v4; // st7@2
+  double v5; // st7@6
+  double v6; // st6@6
+  unsigned int v7; // eax@6
+  double v8; // st5@6
+  double v9; // st4@6
+  HRESULT v10; // eax@6
+  HRESULT v11; // eax@6
+  unsigned int result; // eax@6
+  unsigned int v13; // eax@7
+  unsigned __int16 *v14; // ecx@7
+  int *v15; // eax@7
+  unsigned int v16; // ecx@8
+  __int16 v17; // ax@10
+  int v18; // esi@10
+  float v19; // edi@10
+  void *v20; // esi@10
+  int v21; // edx@10
+  int v22; // ecx@11
+  int v23; // edx@12
+  __int16 v24; // ax@15
+  int v25; // esi@15
+  float v26; // edi@15
+  char *v27; // esi@15
+  int v28; // edx@15
+  int v29; // ecx@16
+  int v30; // edx@17
+  int v31; // [sp-Ch] [bp-ACh]@11
+  int v32; // [sp-Ch] [bp-ACh]@16
+  const char *v33; // [sp+0h] [bp-A0h]@0
+  int v34; // [sp+4h] [bp-9Ch]@0
+  unsigned int v35; // [sp+8h] [bp-98h]@0
+  RenderVertexD3D3 v36[4]; // [sp+Ch] [bp-94h]@6
+  unsigned int v37; // [sp+8Ch] [bp-14h]@7
+  int v38; // [sp+90h] [bp-10h]@7
+  double v39; // [sp+94h] [bp-Ch]@6
+  float v40; // [sp+9Ch] [bp-4h]@6
+
+  auto ecx0 = this;
+  v3 = 0;
+  if ( ecx0->pRenderD3D )
+  {
+    v4 = a3;
+    if ( a3 <= 1.0 )
+    {
+      if ( v4 < 0.0 )
+        v4 = 0.0;
+    }
+    else
+    {
+      v4 = 1.0;
+    }
+    a3 = v4 * 255.0;
+    v39 = a3 + 6.7553994e15;
+    LODWORD(v40) = LODWORD(v39);
+    v5 = (double)(signed int)pViewport->uViewportX;
+    v36[0].pos.x = v5;
+    v6 = (double)(signed int)pViewport->uViewportY;
+    v7 = this_ | (LODWORD(v39) << 24);
+    this_ = pViewport->uViewportW + 1;
+    v36[0].specular = 0;
+    v36[0].pos.y = v6;
+    v36[0].diffuse = v7;
+    v36[1].diffuse = v7;
+    v36[0].pos.z = 0.0;
+    v36[2].diffuse = v7;
+    v36[3].diffuse = v7;
+    v36[0].rhw = 1.0;
+    v36[1].specular = 0;
+    v36[0].texcoord.x = 0.0;
+    v36[2].specular = 0;
+    v36[3].specular = 0;
+    v36[0].texcoord.y = 0.0;
+    v36[1].pos.x = v5;
+    v8 = (double)(pViewport->uViewportW + 1);
+    v36[1].pos.y = v8;
+    v36[1].pos.z = 0.0;
+    v36[1].rhw = 1.0;
+    v36[1].texcoord.x = 0.0;
+    v36[1].texcoord.y = 0.0;
+    v9 = (double)(signed int)pViewport->uViewportZ;
+    v36[2].pos.x = v9;
+    v36[2].pos.y = v8;
+    v36[2].pos.z = 0.0;
+    v36[2].rhw = 1.0;
+    v36[2].texcoord.x = 0.0;
+    v36[2].texcoord.y = 0.0;
+    v36[3].pos.x = v9;
+    v36[3].pos.y = v6;
+    v36[3].pos.z = 0.0;
+    v36[3].rhw = 1.0;
+    v36[3].texcoord.x = 0.0;
+    v36[3].texcoord.y = 0.0;
+    ErrD3D(pRenderD3D->pDevice->SetTexture(0, 0));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 5u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 6u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 0));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, 8u));
+    ErrD3D(pRenderD3D->pDevice->DrawPrimitive(
+      D3DPT_TRIANGLEFAN,
+      D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+      v36,
+      4,
+      28));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 1u));
+    ErrD3D(pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, 2u));
+  }
+  else
+  {
+    v40 = (1.0 - a3) * 65536.0;
+    v39 = v40 + 6.7553994e15;
+    LODWORD(a3) = LODWORD(v39);
+    v38 = (signed int)(pViewport->uViewportZ - pViewport->uViewportX) >> 1;
+    HIDWORD(v39) = pViewport->uViewportW - pViewport->uViewportY + 1;
+    v13 = pViewport->uViewportX + ecx0->uTargetSurfacePitch - pViewport->uViewportZ;
+    v14 = &ecx0->pTargetSurface[pViewport->uViewportX + pViewport->uViewportY * ecx0->uTargetSurfacePitch];
+    v37 = 2 * v13;
+    LODWORD(v40) = (int)v14;
+
+    int __i = 0;
+    v15 = dword_F1B430;
+    do
+    {
+      v16 = v3;
+      v3 += LODWORD(a3);
+      dword_F1B430[__i++] = v16 >> 16;
+    }
+    //while ( (signed int)v15 < (signed int)&Aureal3D_SplashScreen );
+    while (__i < 32);
+
+    if ( pRenderer->uTargetGBits == 6 )
+    {
+      v17 = _42690D_colors_cvt(this_);
+      v18 = (65536 - LODWORD(a3)) * (v17 & 0x1F);
+      this_ = (((65536 - LODWORD(a3)) * (unsigned __int16)(v17 & 0xF800) & 0xF800FFFF | v18 & 0x1F0000 | (65536 - LODWORD(a3)) * (v17 & 0x7E0) & 0x7E00000u) >> 16 << 16) | (((65536 - LODWORD(a3)) * (unsigned __int16)(v17 & 0xF800) & 0xF800FFFF | v18 & 0x1F0000 | (65536 - LODWORD(a3)) * (v17 & 0x7E0) & 0x7E00000u) >> 16);
+      v19 = v40;
+      v20 = off_4EFDB0;
+      v21 = HIDWORD(v39);
+      do
+      {
+        v22 = v38;
+        v31 = v21;
+        do
+        {
+          v23 = (*(int *)((char *)v20
+                           + ((((unsigned __int16)(*(short *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF800u) >> 9)) << 11) | *(unsigned int *)LODWORD(v19) & 0x7FF) & 0x7C0u) >> 4)) << 6) | (*(int *)((char *)v20 + ((((*(int *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF800u) >> 9)) << 11) | (*(int *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF8000000u) >> 25)) << 27) | *(unsigned int *)LODWORD(v19) & 0x7FF07FF) & 0x7C00000u) >> 20)) << 22) | ((*(int *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF800u) >> 9)) << 11) | (*(int *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF8000000u) >> 25)) << 27) | *(unsigned int *)LODWORD(v19) & 0x7FF07FF) & 0xF81FF81F;
+          result = this_
+                 + (*((int *)v20
+                    + (((unsigned __int8)(*((char *)v20
+                                          + ((((unsigned __int16)(*(short *)((char *)v20
+                                                                           + ((*(unsigned int *)LODWORD(v19) & 0xF800u) >> 9)) << 11) | *(unsigned int *)LODWORD(v19) & 0x7FF) & 0x7C0u) >> 4)) << 6) | *(unsigned int *)LODWORD(v19) & 0x1F) & 0x1F)) | (*(int *)((char *)v20 + ((v23 & 0x1F0000u) >> 14)) << 16) | ((*(int *)((char *)v20 + ((((unsigned __int16)(*(short *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF800u) >> 9)) << 11) | *(unsigned int *)LODWORD(v19) & 0x7FF) & 0x7C0u) >> 4)) << 6) | (*(int *)((char *)v20 + ((((*(int *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF800u) >> 9)) << 11) | (*(int *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF8000000u) >> 25)) << 27) | *(unsigned int *)LODWORD(v19) & 0x7FF07FF) & 0x7C00000u) >> 20)) << 22) | ((*(int *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF800u) >> 9)) << 11) | (*(int *)((char *)v20 + ((*(unsigned int *)LODWORD(v19) & 0xF8000000u) >> 25)) << 27) | *(unsigned int *)LODWORD(v19) & 0x7FF07FF) & 0xF81FF81F) & 0xFFE0FFE0);
+          *(unsigned int *)LODWORD(v19) = result;
+          LODWORD(v19) += 4;
+          --v22;
+        }
+        while ( v22 );
+        LODWORD(v19) += v37;
+        v21 = v31 - 1;
+      }
+      while ( v31 != 1 );
+    }
+    else
+    {
+      v24 = _4268E3_smthn_to_a1r5g5b5(this_);
+      v25 = (65536 - LODWORD(a3)) * (v24 & 0x1F);
+      this_ = (((65536 - LODWORD(a3)) * (v24 & 0x7C00) & 0x7C000000 | v25 & 0x1F0000 | (65536 - LODWORD(a3))
+                                                                                    * (v24 & 0x3E0) & 0x3E00000u) >> 16 << 16) | (((65536 - LODWORD(a3)) * (v24 & 0x7C00) & 0x7C000000 | v25 & 0x1F0000 | (65536 - LODWORD(a3)) * (v24 & 0x3E0) & 0x3E00000u) >> 16);
+      v26 = v40;
+      v27 = (char *)off_4EFDB0;
+      v28 = HIDWORD(v39);
+      do
+      {
+        v29 = v38;
+        v32 = v28;
+        do
+        {
+          v30 = 32
+              * *(int *)&v27[(((unsigned __int16)(*(short *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C00u) >> 8] << 10) | *(unsigned int *)LODWORD(v26) & 0x3FF) & 0x3E0u) >> 3] | (*(int *)&v27[(((*(int *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C00u) >> 8] << 10) | (*(int *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C000000u) >> 24] << 26) | *(unsigned int *)LODWORD(v26) & 0x3FF03FF) & 0x3E00000u) >> 19] << 21) | ((*(int *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C00u) >> 8] << 10) | (*(int *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C000000u) >> 24] << 26) | *(unsigned int *)LODWORD(v26) & 0x3FF03FF) & 0x7C1F7C1F;
+          result = this_
+                 + (*(int *)&v27[4
+                                  * (((unsigned __int8)(32
+                                                      * v27[(((unsigned __int16)(*(short *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C00u) >> 8] << 10) | *(unsigned int *)LODWORD(v26) & 0x3FF) & 0x3E0u) >> 3]) | *(unsigned int *)LODWORD(v26) & 0x1F) & 0x1F)] | (*(int *)&v27[(v30 & 0x1F0000u) >> 14] << 16) | (32 * *(int *)&v27[(((unsigned __int16)(*(short *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C00u) >> 8] << 10) | *(unsigned int *)LODWORD(v26) & 0x3FF) & 0x3E0u) >> 3] | (*(int *)&v27[(((*(int *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C00u) >> 8] << 10) | (*(int *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C000000u) >> 24] << 26) | *(unsigned int *)LODWORD(v26) & 0x3FF03FF) & 0x3E00000u) >> 19] << 21) | ((*(int *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C00u) >> 8] << 10) | (*(int *)&v27[(*(unsigned int *)LODWORD(v26) & 0x7C000000u) >> 24] << 26) | *(unsigned int *)LODWORD(v26) & 0x3FF03FF) & 0x7C1F7C1F) & 0xFFE0FFE0);
+          *(unsigned int *)LODWORD(v26) = result;
+          LODWORD(v26) += 4;
+          --v29;
+        }
+        while ( v29 );
+        LODWORD(v26) += v37;
+        v28 = v32 - 1;
+      }
+      while ( v32 != 1 );
+    }
+  }
+  return result;
+}
+
+
+
+//----- (004A5B81) --------------------------------------------------------
+void Render::Clip(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW)
+{
+  this->bClip = 1;
+  this->uClipY = uY;
+  this->uClipX = uX;
+  this->uClipW = uW;
+  this->uClipZ = uZ;
+}
+
+
+//----- (004A5BB6) --------------------------------------------------------
+void Render::ResetClip()
+{
+  this->uClipY = 0;
+  this->uClipX = 0;
+  this->bClip = 1;
+  this->uClipW = 480;
+  this->uClipZ = 640;
+}
+
+
+//----- (004A5BE3) --------------------------------------------------------
+void Render::DrawTextureRGB(unsigned int uOutX, unsigned int uOutY, RGBTexture *a4)
+{
+  int v4; // edi@3
+  unsigned __int16 *v5; // edx@3
+  unsigned __int16 *v6; // esi@3
+  unsigned int v7; // ebx@4
+  unsigned int v8; // eax@5
+  unsigned int v9; // ebx@5
+  unsigned int v10; // eax@6
+  unsigned int v11; // eax@7
+  unsigned int v12; // ebx@8
+  unsigned int v13; // eax@10
+  unsigned int v14; // edi@11
+  unsigned int v15; // eax@14
+  unsigned int v16; // ebx@17
+  int v17; // eax@23
+  char v18; // zf@25
+  int v19; // [sp+10h] [bp-8h]@3
+  int v20; // [sp+14h] [bp-4h]@3
+  unsigned int uOutXa; // [sp+20h] [bp+8h]@16
+  int uOutXb; // [sp+20h] [bp+8h]@21
+  int v23; // [sp+28h] [bp+10h]@3
+
+  if ( this->uNumSceneBegins && a4 )
+  {
+    v4 = a4->uWidth;
+    v5 = &this->pTargetSurface[uOutX + uOutY * this->uTargetSurfacePitch];
+    v6 = a4->pPixels;
+    v20 = v4;
+    v23 = a4->uHeight;
+    v19 = v4;
+    if ( this->bClip )
+    {
+      v7 = this->uClipX;
+      if ( (signed int)uOutX < (signed int)v7 )
+      {
+        v8 = v7 - uOutX;
+        v9 = uOutX - v7;
+        v8 *= 2;
+        v4 += v9;
+        v6 = (unsigned __int16 *)((char *)v6 + v8);
+        v20 += v9;
+        v5 = (unsigned __int16 *)((char *)v5 + v8);
+      }
+      v10 = this->uClipY;
+      if ( (signed int)uOutY < (signed int)v10 )
+      {
+        v11 = v10 - uOutY;
+        v6 += v19 * v11;
+        v23 += uOutY - this->uClipY;
+        v4 = v20;
+        v5 += this->uTargetSurfacePitch * v11;
+      }
+      v12 = this->uClipX;
+      if ( (signed int)v12 < (signed int)uOutX )
+        v12 = uOutX;
+      v13 = this->uClipZ;
+      if ( (signed int)(v4 + v12) > (signed int)v13 )
+      {
+        v14 = this->uClipX;
+        if ( (signed int)v14 < (signed int)uOutX )
+          v14 = uOutX;
+        v4 = v13 - v14;
+      }
+      v15 = this->uClipY;
+      if ( (signed int)v15 < (signed int)uOutY )
+        v15 = uOutY;
+      uOutXa = this->uClipW;
+      if ( (signed int)(v15 + v23) > (signed int)uOutXa )
+      {
+        v16 = this->uClipY;
+        if ( (signed int)v16 < (signed int)uOutY )
+          v16 = uOutY;
+        v23 = uOutXa - v16;
+      }
+    }
+    if ( v23 > 0 )
+    {
+      uOutXb = v23;
+      do
+      {
+        if ( v4 > 0 )
+        {
+          v17 = v4;
+          do
+          {
+            *v5 = *v6;
+            ++v5;
+            ++v6;
+            --v17;
+          }
+          while ( v17 );
+        }
+        v6 += v19 - v4;
+        v18 = uOutXb-- == 1;
+        v5 += this->uTargetSurfacePitch - v4;
+      }
+      while ( !v18 );
+    }
+  }
+}
+
+
+//----- (004A5D33) --------------------------------------------------------
+void Render::_4A5D33(unsigned int pX, unsigned int pY, int a4, int a5, RGBTexture *pTexture)
+{
+  Render *v6; // esi@1
+  unsigned __int16 *v7; // ebx@3
+  int v8; // ecx@3
+  int v9; // edx@3
+  int v10; // ecx@3
+  int v11; // edi@3
+  signed int v12; // eax@4
+  unsigned int v13; // eax@5
+  signed int v14; // eax@6
+  unsigned int v15; // eax@7
+  unsigned int v16; // edx@8
+  int v17; // eax@10
+  unsigned int v18; // ecx@11
+  unsigned int v19; // ecx@14
+  int v20; // eax@16
+  unsigned int v21; // ecx@17
+  int v22; // eax@21
+  int v23; // edi@23
+  int v24; // [sp+Ch] [bp-4h]@3
+  int a2a; // [sp+18h] [bp+8h]@21
+  unsigned int teal; // [sp+1Ch] [bp+Ch]@20
+  int a4a; // [sp+20h] [bp+10h]@3
+  int a4b; // [sp+20h] [bp+10h]@21
+  unsigned __int16 *pTexturea; // [sp+28h] [bp+18h]@3
+
+  v6 = this;
+  if ( this->uNumSceneBegins && pTexture )
+  {
+    v7 = &this->pTargetSurface[pX + pY * this->uTargetSurfacePitch];
+    v8 = pTexture->uWidth;
+    v24 = pTexture->uWidth;
+    v9 = a4 + a5 * v8;
+    v10 = v8 - a4;
+    a4a = v10;
+    v11 = pTexture->uHeight - a5;
+    pTexturea = &pTexture->pPixels[v9];
+    if ( v6->bClip )
+    {
+      v12 = v6->uClipX;
+      if ( (signed int)pX < v12 )
+      {
+        v13 = 2 * (v12 - pX);
+        pTexturea = (unsigned __int16 *)((char *)pTexturea + v13);
+        v10 += pX - v6->uClipX;
+        v7 = (unsigned __int16 *)((char *)v7 + v13);
+        a4a = v10;
+      }
+      v14 = v6->uClipY;
+      if ( (signed int)pY < v14 )
+      {
+        v15 = v14 - pY;
+        pTexturea += v24 * v15;
+        v11 += pY - v6->uClipY;
+        v10 = a4a;
+        v7 += v6->uTargetSurfacePitch * v15;
+      }
+      v16 = v6->uClipX;
+      if ( (signed int)v16 < (signed int)pX )
+        v16 = pX;
+      v17 = v6->uClipZ;
+      if ( (signed int)(v10 + v16) > v17 )
+      {
+        v18 = v6->uClipX;
+        if ( (signed int)v18 < (signed int)pX )
+          v18 = pX;
+        a4a = v17 - v18;
+      }
+      v19 = v6->uClipY;
+      if ( (signed int)v19 < (signed int)pY )
+        v19 = pY;
+      v20 = v6->uClipW;
+      if ( (signed int)(v11 + v19) > v20 )
+      {
+        v21 = v6->uClipY;
+        if ( (signed int)v21 < (signed int)pY )
+          v21 = pY;
+        v11 = v20 - v21;
+      }
+    }
+    teal = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0xFFu);
+    if ( v11 > 0 )
+    {
+      v22 = a4a;
+      a2a = v11;
+      a4b = 2 * (v24 - a4a);
+      do
+      {
+        if ( v22 > 0 )
+        {
+          v23 = v22;
+          do
+          {
+            if ( *pTexturea != teal )
+              *v7 = *pTexturea;
+            ++pTexturea;
+            ++v7;
+            --v23;
+          }
+          while ( v23 );
+        }
+        v7 += v6->uTargetSurfacePitch - v22;
+        pTexturea = (unsigned __int16 *)((char *)pTexturea + a4b);
+        --a2a;
+      }
+      while ( a2a );
+    }
+  }
+}
+
+
+
+//----- (004A6E7E) --------------------------------------------------------
+void Render::_4A6E7E(unsigned int a2, unsigned int a3, Texture *a4)
+{
+  unsigned __int16 *v4; // eax@4
+  int v5; // edx@4
+  unsigned int v6; // edi@4
+  unsigned int v7; // edx@5
+  unsigned int v8; // edx@6
+  unsigned int v9; // edx@7
+  unsigned int v10; // edx@8
+  unsigned int v11; // ebx@9
+  unsigned int v12; // esi@11
+  unsigned int v13; // edx@12
+  unsigned int v14; // ebx@15
+  unsigned int v15; // esi@17
+  unsigned int v16; // edi@18
+  char v17; // zf@29
+  int v18; // [sp+14h] [bp-Ch]@4
+  int v19; // [sp+18h] [bp-8h]@4
+  unsigned __int8 *v20; // [sp+1Ch] [bp-4h]@4
+  int v21; // [sp+28h] [bp+8h]@25
+  int v22; // [sp+28h] [bp+8h]@34
+  unsigned int v23; // [sp+2Ch] [bp+Ch]@23
+  unsigned int v24; // [sp+2Ch] [bp+Ch]@32
+
+  if ( this->uNumSceneBegins && a4 && a4->pPalette16 )
+  {
+    v4 = &this->pTargetSurface[a2 + a3 * this->uTargetSurfacePitch];
+    v20 = a4->pLevelOfDetail0;
+    v5 = a4->uTextureWidth;
+    v6 = a4->uTextureHeight;
+    v19 = a4->uTextureWidth;
+    v18 = a4->uTextureWidth;
+    if ( this->bClip )
+    {
+      v7 = this->uClipX;
+      if ( (signed int)a2 < (signed int)v7 )
+      {
+        v8 = v7 - a2;
+        v20 += v8;
+        v19 += a2 - this->uClipX;
+        v4 += v8;
+      }
+      v9 = this->uClipY;
+      if ( (signed int)a3 < (signed int)v9 )
+      {
+        v10 = v9 - a3;
+        v20 += v18 * v10;
+        v6 = a3 - this->uClipY + a4->uTextureHeight;
+        v4 += this->uTargetSurfacePitch * v10;
+      }
+      v11 = this->uClipX;
+      v5 = v19;
+      if ( (signed int)v11 < (signed int)a2 )
+        v11 = a2;
+      v12 = this->uClipZ;
+      if ( (signed int)(v19 + v11) > (signed int)v12 )
+      {
+        v13 = this->uClipX;
+        if ( (signed int)v13 < (signed int)a2 )
+          v13 = a2;
+        v5 = v12 - v13;
+      }
+      v14 = this->uClipY;
+      if ( (signed int)v14 < (signed int)a3 )
+        v14 = a3;
+      v15 = this->uClipW;
+      if ( (signed int)(v6 + v14) > (signed int)v15 )
+      {
+        v16 = this->uClipY;
+        if ( (signed int)v16 < (signed int)a3 )
+          v16 = a3;
+        v6 = v15 - v16;
+      }
+    }
+    if ( pRenderer->uTargetGBits == 5 )
+    {
+      if ( (signed int)v6 > 0 )
+      {
+        v23 = v6;
+        do
+        {
+          if ( v5 > 0 )
+          {
+            v21 = v5;
+            do
+            {
+              if ( *v20 )
+                *v4 = ((unsigned int)a4->pPalette16[*v20] >> 1) & 0x3DEF;
+              ++v4;
+              ++v20;
+              --v21;
+            }
+            while ( v21 );
+          }
+          v20 += v18 - v5;
+          v17 = v23-- == 1;
+          v4 += this->uTargetSurfacePitch - v5;
+        }
+        while ( !v17 );
+      }
+    }
+    else
+    {
+      if ( (signed int)v6 > 0 )
+      {
+        v24 = v6;
+        do
+        {
+          if ( v5 > 0 )
+          {
+            v22 = v5;
+            do
+            {
+              if ( *v20 )
+                *v4 = ((unsigned int)a4->pPalette16[*v20] >> 1) & 0x7BEF;
+              ++v4;
+              ++v20;
+              --v22;
+            }
+            while ( v22 );
+          }
+          v20 += v18 - v5;
+          v17 = v24-- == 1;
+          v4 += this->uTargetSurfacePitch - v5;
+        }
+        while ( !v17 );
+      }
+    }
+  }
+}
+
+
+//----- (004A6DF5) --------------------------------------------------------
+int Render::_4A6DF5(unsigned __int16 *pBitmap, unsigned int uBitmapPitch, Vec2_int_ *pBitmapXY, unsigned __int16 *pTarget, unsigned int uTargetPitch, Vec4_int_ *a7)
+{
+  int result; // eax@0
+  int v8; // ecx@3
+  unsigned __int16 *v9; // edi@4
+  unsigned __int16 *v10; // ebx@4
+  int v11; // esi@4
+  unsigned __int16 *pBitmapa; // [sp+14h] [bp+8h]@3
+  unsigned __int16 *pTargeta; // [sp+20h] [bp+14h]@3
+
+  if ( pBitmap )
+  {
+    if ( pTarget )
+    {
+      pBitmapa = &pBitmap[pBitmapXY->x + uBitmapPitch * pBitmapXY->y];
+      pTargeta = &pTarget[a7->x + uTargetPitch * a7->y];
+      v8 = a7->z - a7->x;
+      result = a7->w - a7->y;
+      if ( result > 0 )
+      {
+        v9 = pBitmapa;
+        v10 = pTargeta;
+        v11 = a7->w - a7->y;
+        do
+        {
+          if ( v8 > 0 )
+          {
+            result = v8;
+            do
+            {
+              *v9 = *v10;
+              ++v9;
+              ++v10;
+              --result;
+            }
+            while ( result );
+          }
+          v9 += uBitmapPitch - v8;
+          v10 += uTargetPitch - v8;
+          --v11;
+        }
+        while ( v11 );
+      }
+    }
+  }
+  return result;
+}
+
+
+//----- (004A6D87) --------------------------------------------------------
+void Render::FillRectFast(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, unsigned int uColor16)
+{
+  if (!uNumSceneBegins)
+    return;
+
+  unsigned __int32 twoColors = (uColor16 << 16) | uColor16;
+  for (uint y = 0; y < uHeight; ++y)
+  {
+    auto pDst = &pTargetSurface[uX + (y + uY) * uTargetSurfacePitch];
+
+    memset32(pDst, twoColors, uWidth / 2);
+    if (uWidth & 1)
+      pDst[uWidth - 1] = uColor16;
+    }
+}
+
+
+
+//----- (004A6C4F) --------------------------------------------------------
+void Render::DrawText(signed int uOutX, signed int uOutY, unsigned __int8 *pFontPixels, unsigned int uCharWidth, unsigned int uCharHeight, unsigned __int16 *pFontPalette, unsigned __int16 uFaceColor, unsigned __int16 uShadowColor)
+{
+  unsigned int v9; // edi@2
+  unsigned int v10; // esi@2
+  unsigned __int16 *v11; // eax@2
+  unsigned int v12; // ebx@3
+  signed int v13; // edx@5
+  int v14; // edx@6
+  signed int v15; // ebx@7
+  unsigned int v16; // edx@9
+  signed int v17; // edi@10
+  signed int v18; // ebx@13
+  unsigned int v19; // edx@15
+  signed int v20; // esi@16
+  unsigned int v21; // esi@22
+  unsigned __int16 v22; // dx@24
+  char v23; // zf@28
+  unsigned __int8 *v24; // [sp+Ch] [bp-4h]@2
+  unsigned int uOutXa; // [sp+18h] [bp+8h]@20
+
+  if ( this->uNumSceneBegins )
+  {
+    v9 = uCharWidth;
+    v10 = uCharHeight;
+    v11 = &this->pTargetSurface[uOutX + uOutY * this->uTargetSurfacePitch];
+    v24 = pFontPixels;
+    if ( this->bClip )
+    {
+      v12 = this->uClipX;
+      if ( uOutX < (signed int)v12 )
+      {
+        v24 = &pFontPixels[v12 - uOutX];
+        v11 += v12 - uOutX;
+        v9 = uCharWidth + uOutX - v12;
+      }
+      v13 = this->uClipY;
+      if ( uOutY < v13 )
+      {
+        v14 = v13 - uOutY;
+        v24 += uCharWidth * v14;
+        v10 = uCharHeight + uOutY - this->uClipY;
+        v11 += this->uTargetSurfacePitch * v14;
+      }
+      v15 = this->uClipX;
+      if ( v15 < uOutX )
+        v15 = uOutX;
+      v16 = this->uClipZ;
+      if ( (signed int)(v9 + v15) > (signed int)v16 )
+      {
+        v17 = this->uClipX;
+        if ( v17 < uOutX )
+          v17 = uOutX;
+        v9 = v16 - v17;
+      }
+      v18 = this->uClipY;
+      if ( v18 < uOutY )
+        v18 = uOutY;
+      v19 = this->uClipW;
+      if ( (signed int)(v10 + v18) > (signed int)v19 )
+      {
+        v20 = this->uClipY;
+        if ( v20 < uOutY )
+          v20 = uOutY;
+        v10 = v19 - v20;
+      }
+    }
+    if ( (signed int)v10 > 0 )
+    {
+      uOutXa = v10;
+      do
+      {
+        if ( (signed int)v9 > 0 )
+        {
+          v21 = v9;
+          do
+          {
+            if ( *v24 )
+            {
+              v22 = uShadowColor;
+              if ( *v24 != 1 )
+                v22 = uFaceColor;
+              *v11 = v22;
+            }
+            ++v11;
+            ++v24;
+            --v21;
+          }
+          while ( v21 );
+        }
+        v24 += uCharWidth - v9;
+        v23 = uOutXa-- == 1;
+        v11 += this->uTargetSurfacePitch - v9;
+      }
+      while ( !v23 );
+    }
+  }
+}
+
+
+
+//----- (004A6A68) --------------------------------------------------------
+void Render::_4A6A68(unsigned int a2, unsigned int a3, Texture *a4, __int16 height)
+{
+  Render *v5; // ebx@1
+  unsigned __int16 v6; // ax@1
+
+  v5 = this;
+
+  Texture tex; // [sp+Ch] [bp-48h]@1
+  //Texture::Texture(&tex);
+
+  v6 = a4->uTextureHeight - height;
+  memcpy(&tex, a4, sizeof(tex));
+  tex.uTextureHeight = v6;
+  if ( (signed __int16)v6 > 0 )
+    DrawTextureIndexed(a2, a3, &tex);
+}
+
+
+
+//----- (004A6AB1) --------------------------------------------------------
+void Render::DrawTextPalette(int x, int y, int a4, int a5, unsigned int uFontHeight, unsigned __int16 *pPalette, int a8)
+{
+  int v8; // edi@2
+  unsigned int v9; // esi@2
+  unsigned __int16 *v10; // eax@2
+  unsigned char *v11; // edx@2
+  unsigned int v12; // ebx@3
+  signed int v13; // edx@5
+  int v14; // edx@6
+  signed int v15; // ebx@7
+  unsigned int v16; // edx@9
+  signed int v17; // edi@10
+  signed int v18; // ebx@13
+  unsigned int v19; // edx@15
+  signed int v20; // esi@16
+  int v21; // ebx@22
+  char v22; // zf@28
+  int v23; // ebx@31
+  unsigned __int16 v24; // si@35
+  int v25; // [sp+Ch] [bp-4h]@2
+  int v26; // [sp+1Ch] [bp+Ch]@24
+  int v27; // [sp+1Ch] [bp+Ch]@33
+  unsigned int v28; // [sp+20h] [bp+10h]@30
+  unsigned int v29; // [sp+24h] [bp+14h]@22
+  unsigned int v30; // [sp+24h] [bp+14h]@31
+
+  auto a2 = x;
+  auto a3 = y;
+  auto a6 = uFontHeight;
+  if ( this->uNumSceneBegins )
+  {
+    v8 = a5;
+    v9 = a6;
+    v10 = &pTargetSurface[x + y * uTargetSurfacePitch];
+    v11 = (unsigned char *)a4;
+    v25 = a4;
+    if ( this->bClip )
+    {
+      v12 = this->uClipX;
+      if ( a2 < (signed int)v12 )
+      {
+        v25 = v12 - a2 + a4;
+        v10 += v12 - a2;
+        v8 = a5 + a2 - v12;
+      }
+      v13 = this->uClipY;
+      if ( a3 < v13 )
+      {
+        v14 = v13 - a3;
+        v25 += a5 * v14;
+        v9 = a6 + a3 - this->uClipY;
+        v10 += this->uTargetSurfacePitch * v14;
+      }
+      v15 = this->uClipX;
+      if ( v15 < a2 )
+        v15 = a2;
+      v16 = this->uClipZ;
+      if ( v8 + v15 > (signed int)v16 )
+      {
+        v17 = this->uClipX;
+        if ( v17 < a2 )
+          v17 = a2;
+        v8 = v16 - v17;
+      }
+      v18 = this->uClipY;
+      if ( v18 < a3 )
+        v18 = a3;
+      v19 = this->uClipW;
+      if ( (signed int)(v9 + v18) > (signed int)v19 )
+      {
+        v20 = this->uClipY;
+        if ( v20 < a3 )
+          v20 = a3;
+        v9 = v19 - v20;
+      }
+      v11 = (unsigned char *)v25;
+    }
+    if ( a8 )
+    {
+      v28 = pRenderer->uTargetGMask | pRenderer->uTargetBMask;
+      if ( (signed int)v9 > 0 )
+      {
+        v23 = a5;
+        v30 = v9;
+        do
+        {
+          if ( v8 > 0 )
+          {
+            v27 = v8;
+            do
+            {
+              if ( *v11 )
+                v24 = pPalette[*v11];
+              else
+                v24 = v28;
+              *v10 = v24;
+              ++v10;
+              ++v11;
+              --v27;
+            }
+            while ( v27 );
+          }
+          v11 += v23 - v8;
+          v22 = v30-- == 1;
+          v10 += this->uTargetSurfacePitch - v8;
+        }
+        while ( !v22 );
+      }
+    }
+    else
+    {
+      if ( (signed int)v9 > 0 )
+      {
+        v21 = a5;
+        v29 = v9;
+        do
+        {
+          if ( v8 > 0 )
+          {
+            v26 = v8;
+            do
+            {
+              if ( *v11 )
+                *v10 = pPalette[*v11];
+              ++v10;
+              ++v11;
+              --v26;
+            }
+            while ( v26 );
+          }
+          v11 += v21 - v8;
+          v22 = v29-- == 1;
+          v10 += this->uTargetSurfacePitch - v8;
+        }
+        while ( !v22 );
+      }
+    }
+  }
+}
+
+//----- (004A68EF) --------------------------------------------------------
+void Render::DrawTransparentGreenShade(signed int a2, signed int a3, Texture *pTexture)
+{
+  Texture *v4; // edi@2
+  unsigned int v5; // ebx@4
+  unsigned __int16 *v6; // eax@4
+  signed int v7; // edx@5
+  int v8; // edx@6
+  signed int v9; // edx@7
+  int v10; // edx@8
+  signed int v11; // edx@9
+  signed int v12; // esi@12
+  signed int v13; // esi@15
+  unsigned int v14; // edx@17
+  signed int v15; // esi@18
+  unsigned __int8 *v16; // ebx@22
+  char v17; // zf@28
+  int v18; // [sp+10h] [bp-10h]@4
+  unsigned __int8 *v19; // [sp+18h] [bp-8h]@4
+  int v20; // [sp+1Ch] [bp-4h]@4
+  int v21; // [sp+28h] [bp+8h]@24
+  unsigned int v22; // [sp+2Ch] [bp+Ch]@22
+  unsigned int pTexturea; // [sp+30h] [bp+10h]@11
+
+  if ( this->uNumSceneBegins )
+  {
+    v4 = pTexture;
+    if ( pTexture )
+    {
+      if ( pTexture->pPalette16 )
+      {
+        v5 = pTexture->uTextureHeight;
+        v6 = &this->pTargetSurface[a2 + a3 * this->uTargetSurfacePitch];
+        v19 = pTexture->pLevelOfDetail0;
+        v20 = pTexture->uTextureWidth;
+        v18 = pTexture->uTextureWidth;
+        if ( this->bClip )
+        {
+          v7 = this->uClipX;
+          if ( a2 < v7 )
+          {
+            v8 = v7 - a2;
+            v19 += v8;
+            v20 += a2 - this->uClipX;
+            v6 += v8;
+          }
+          v9 = this->uClipY;
+          v5 = pTexture->uTextureHeight;
+          if ( a3 < v9 )
+          {
+            v10 = v9 - a3;
+            v19 += v18 * v10;
+            v5 = a3 - this->uClipY + pTexture->uTextureHeight;
+            v4 = pTexture;
+            v6 += this->uTargetSurfacePitch * v10;
+          }
+          v11 = this->uClipX;
+          if ( v11 < a2 )
+            v11 = a2;
+          pTexturea = this->uClipZ;
+          if ( v11 + v20 > (signed int)pTexturea )
+          {
+            v12 = this->uClipX;
+            if ( v12 < a2 )
+              v12 = a2;
+            v20 = pTexturea - v12;
+          }
+          v13 = this->uClipY;
+          if ( v13 < a3 )
+            v13 = a3;
+          v14 = this->uClipW;
+          if ( (signed int)(v5 + v13) > (signed int)v14 )
+          {
+            v15 = this->uClipY;
+            if ( v15 < a3 )
+              v15 = a3;
+            v5 = v14 - v15;
+          }
+        }
+        if ( (signed int)v5 > 0 )
+        {
+          v22 = v5;
+          v16 = v19;
+          do
+          {
+            if ( v20 > 0 )
+            {
+              v21 = v20;
+              do
+              {
+                if ( *v16 )
+                  *v6 = this->uTargetGMask & v4->pPalette16[*v16];
+                ++v6;
+                ++v16;
+                --v21;
+              }
+              while ( v21 );
+            }
+            v16 += v18 - v20;
+            v17 = v22-- == 1;
+            v6 += this->uTargetSurfacePitch - v20;
+          }
+          while ( !v17 );
+        }
+      }
+    }
+  }
+}
+
+
+//----- (004A6776) --------------------------------------------------------
+void Render::_4A6776(unsigned int a2, unsigned int a3, Texture *a4)
+{
+  Texture *v4; // edi@2
+  unsigned int v5; // ebx@4
+  unsigned __int16 *v6; // eax@4
+  unsigned int v7; // edx@5
+  unsigned int v8; // edx@6
+  unsigned int v9; // edx@7
+  unsigned int v10; // edx@8
+  unsigned int v11; // edx@9
+  unsigned int v12; // esi@12
+  unsigned int v13; // esi@15
+  unsigned int v14; // edx@17
+  unsigned int v15; // esi@18
+  unsigned __int8 *v16; // ebx@22
+  char v17; // zf@28
+  int v18; // [sp+10h] [bp-10h]@4
+  unsigned __int8 *v19; // [sp+18h] [bp-8h]@4
+  int v20; // [sp+1Ch] [bp-4h]@4
+  int a2a; // [sp+28h] [bp+8h]@24
+  unsigned int a3a; // [sp+2Ch] [bp+Ch]@22
+  unsigned int a4a; // [sp+30h] [bp+10h]@11
+
+  if ( this->uNumSceneBegins )
+  {
+    v4 = a4;
+    if ( a4 )
+    {
+      if ( a4->pPalette16 )
+      {
+        v5 = a4->uTextureHeight;
+        v6 = &this->pTargetSurface[a2 + a3 * this->uTargetSurfacePitch];
+        v19 = a4->pLevelOfDetail0;
+        v20 = a4->uTextureWidth;
+        v18 = a4->uTextureWidth;
+        if ( this->bClip )
+        {
+          v7 = this->uClipX;
+          if ( (signed int)a2 < (signed int)v7 )
+          {
+            v8 = v7 - a2;
+            v19 += v8;
+            v20 += a2 - this->uClipX;
+            v6 += v8;
+          }
+          v9 = this->uClipY;
+          v5 = a4->uTextureHeight;
+          if ( (signed int)a3 < (signed int)v9 )
+          {
+            v10 = v9 - a3;
+            v19 += v18 * v10;
+            v5 = a3 - this->uClipY + a4->uTextureHeight;
+            v4 = a4;
+            v6 += this->uTargetSurfacePitch * v10;
+          }
+          v11 = this->uClipX;
+          if ( (signed int)v11 < (signed int)a2 )
+            v11 = a2;
+          a4a = this->uClipZ;
+          if ( (signed int)(v11 + v20) > (signed int)a4a )
+          {
+            v12 = this->uClipX;
+            if ( (signed int)v12 < (signed int)a2 )
+              v12 = a2;
+            v20 = a4a - v12;
+          }
+          v13 = this->uClipY;
+          if ( (signed int)v13 < (signed int)a3 )
+            v13 = a3;
+          v14 = this->uClipW;
+          if ( (signed int)(v5 + v13) > (signed int)v14 )
+          {
+            v15 = this->uClipY;
+            if ( (signed int)v15 < (signed int)a3 )
+              v15 = a3;
+            v5 = v14 - v15;
+          }
+        }
+        if ( (signed int)v5 > 0 )
+        {
+          a3a = v5;
+          v16 = v19;
+          do
+          {
+            if ( v20 > 0 )
+            {
+              a2a = v20;
+              do
+              {
+                if ( *v16 )
+                  *v6 = this->uTargetRMask & v4->pPalette16[*v16];
+                ++v6;
+                ++v16;
+                --a2a;
+              }
+              while ( a2a );
+            }
+            v16 += v18 - v20;
+            v17 = a3a-- == 1;
+            v6 += this->uTargetSurfacePitch - v20;
+          }
+          while ( !v17 );
+        }
+      }
+    }
+  }
+}
+
+//----- (004A65CC) --------------------------------------------------------
+void Render::_4A65CC(unsigned int x, unsigned int y, Texture *a4, Texture *a5, int a6, int a7, int a8)
+{
+  unsigned __int16 *v8; // esi@6
+  unsigned int v9; // edi@6
+  unsigned int v10; // eax@7
+  unsigned int v11; // eax@8
+  unsigned int v12; // eax@9
+  unsigned int v13; // eax@10
+  unsigned int v14; // edx@11
+  unsigned int v15; // eax@13
+  unsigned int v16; // edx@14
+  unsigned int v17; // edx@17
+  unsigned int v18; // eax@19
+  unsigned int v19; // edx@20
+  int v20; // eax@27
+  int v21; // edx@29
+  int v22; // [sp+Ch] [bp-Ch]@6
+  int v23; // [sp+Ch] [bp-Ch]@24
+  unsigned __int8 *v24; // [sp+14h] [bp-4h]@6
+  int xa; // [sp+20h] [bp+8h]@26
+  unsigned int ya; // [sp+24h] [bp+Ch]@24
+  int v27; // [sp+2Ch] [bp+14h]@6
+
+  if ( this->uNumSceneBegins && a4 && a4->pPalette16 && a5 && a5->pPalette16 )
+  {
+    v8 = &this->pTargetSurface[x + y * this->uTargetSurfacePitch];
+    v24 = a4->pLevelOfDetail0;
+    v27 = a4->uTextureWidth;
+    v9 = a4->uTextureHeight;
+    v22 = a4->uTextureWidth;
+    if ( this->bClip )
+    {
+      v10 = this->uClipX;
+      if ( (signed int)x < (signed int)v10 )
+      {
+        v11 = v10 - x;
+        v24 += v11;
+        v27 += x - this->uClipX;
+        v8 += v11;
+      }
+      v12 = this->uClipY;
+      if ( (signed int)y < (signed int)v12 )
+      {
+        v13 = v12 - y;
+        v24 += v22 * v13;
+        v9 = y - this->uClipY + a4->uTextureHeight;
+        v8 += this->uTargetSurfacePitch * v13;
+      }
+      v14 = this->uClipX;
+      if ( (signed int)v14 < (signed int)x )
+        v14 = x;
+      v15 = this->uClipZ;
+      if ( (signed int)(v27 + v14) > (signed int)v15 )
+      {
+        v16 = this->uClipX;
+        if ( (signed int)v16 < (signed int)x )
+          v16 = x;
+        v27 = v15 - v16;
+      }
+      v17 = this->uClipY;
+      if ( (signed int)v17 < (signed int)y )
+        v17 = y;
+      v18 = this->uClipW;
+      if ( (signed int)(v9 + v17) > (signed int)v18 )
+      {
+        v19 = this->uClipY;
+        if ( (signed int)v19 < (signed int)y )
+          v19 = y;
+        v9 = v18 - v19;
+      }
+    }
+    if ( (signed int)v9 > 0 )
+    {
+      ya = v9;
+      v23 = v22 - v27;
+      do
+      {
+        if ( v27 > 0 )
+        {
+          xa = v27;
+          do
+          {
+            v20 = *v24;
+            if ( v20 >= a7 && v20 <= a8 )
+            {
+              v21 = a7 + (a6 + v20) % (2 * (a8 - a7));
+              if ( (a6 + v20) % (2 * (a8 - a7)) >= a8 - a7 )
+                v21 = 2 * a8 - v21 - a7;
+              *v8 = a4->pPalette16[v21];
+            }
+            ++v8;
+            ++v24;
+            --xa;
+          }
+          while ( xa );
+        }
+        v8 += this->uTargetSurfacePitch - v27;
+        v24 += v23;
+        --ya;
+      }
+      while ( ya );
+    }
+  }
+}
+
+
+//----- (004A63E6) --------------------------------------------------------
+void Render::_4A63E6(unsigned int a2, unsigned int a3, Texture *a4, Texture *a5, int a6, int a7, int a8)
+{
+  Texture *v8; // eax@2
+  Texture *v9; // ebx@4
+  unsigned __int16 *v10; // esi@6
+  unsigned int v11; // edi@7
+  unsigned int v12; // eax@9
+  unsigned int v13; // eax@10
+  unsigned int v14; // edx@11
+  unsigned int v15; // eax@13
+  unsigned int v16; // edx@14
+  unsigned int v17; // edx@17
+  unsigned int v18; // eax@19
+  unsigned int v19; // edx@20
+  int v20; // eax@27
+  int v21; // edx@29
+  int v22; // [sp+Ch] [bp-Ch]@6
+  int v23; // [sp+Ch] [bp-Ch]@24
+  int v24; // [sp+10h] [bp-8h]@6
+  int v25; // [sp+14h] [bp-4h]@6
+  int i; // [sp+20h] [bp+8h]@25
+  int v27; // [sp+24h] [bp+Ch]@23
+  unsigned __int8 *v28; // [sp+28h] [bp+10h]@6
+
+  if ( this->uNumSceneBegins )
+  {
+    v8 = a4;
+    if ( a4 )
+    {
+      if ( a4->pPalette16 )
+      {
+        v9 = a5;
+        if ( a5 )
+        {
+          if ( a5->pPalette16 )
+          {
+            v10 = &this->pTargetSurface[a2 + a3 * this->uTargetSurfacePitch];
+            v28 = a4->pLevelOfDetail0;
+            v25 = v8->uTextureWidth;
+            v24 = v8->uTextureHeight;
+            v22 = v8->uTextureWidth;
+            if ( this->bClip )
+            {
+              v11 = this->uClipX;
+              if ( (signed int)a2 < (signed int)v11 )
+              {
+                v28 += v11 - a2;
+                v25 += a2 - v11;
+                v9 = a5;
+                v10 += v11 - a2;
+              }
+              v12 = this->uClipY;
+              if ( (signed int)a3 < (signed int)v12 )
+              {
+                v13 = v12 - a3;
+                v9 = a5;
+                v28 += v22 * v13;
+                v24 += a3 - this->uClipY;
+                v10 += this->uTargetSurfacePitch * v13;
+              }
+              v14 = this->uClipX;
+              if ( (signed int)v14 < (signed int)a2 )
+                v14 = a2;
+              v15 = this->uClipZ;
+              if ( (signed int)(v25 + v14) > (signed int)v15 )
+              {
+                v16 = this->uClipX;
+                if ( (signed int)v16 < (signed int)a2 )
+                  v16 = a2;
+                v25 = v15 - v16;
+              }
+              v17 = this->uClipY;
+              if ( (signed int)v17 < (signed int)a3 )
+                v17 = a3;
+              v18 = this->uClipW;
+              if ( (signed int)(v24 + v17) > (signed int)v18 )
+              {
+                v19 = this->uClipY;
+                if ( (signed int)v19 < (signed int)a3 )
+                  v19 = a3;
+                v24 = v18 - v19;
+              }
+            }
+            v27 = 0;
+            if ( v24 > 0 )
+            {
+              v23 = v22 - v25;
+              do
+              {
+                for ( i = 0; i < v25; ++v28 )
+                {
+                  if ( *v28 )
+                  {
+                    v20 = *(&v9->pLevelOfDetail0[i & v9->uWidthMinus1] + v9->uTextureWidth * (v27 & v9->uHeightMinus1));
+                    if ( v20 >= a7 )
+                    {
+                      if ( v20 <= a8 )
+                      {
+                        v21 = a7 + (a6 + v20) % (2 * (a8 - a7));
+                        if ( (a6 + v20) % (2 * (a8 - a7)) >= a8 - a7 )
+                          v21 = 2 * a8 - v21 - a7;
+                        v9 = a5;
+                        *v10 = a5->pPalette16[v21];
+                      }
+                    }
+                  }
+                  ++i;
+                  ++v10;
+                }
+                ++v27;
+                v10 += this->uTargetSurfacePitch - v25;
+                v28 += v23;
+              }
+              while ( v27 < v24 );
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+
+//----- (004A6274) --------------------------------------------------------
+void Render::DrawTextureTransparent(unsigned int uX, unsigned int uY, Texture *pTexture)
+{
+  Texture *pCurrentTexture; // edi@2
+  int uHeight; // ebx@4
+  unsigned __int16 *v6; // eax@4
+  unsigned int v7; // edx@5
+  unsigned int v8; // edx@6
+  unsigned int v9; // edx@7
+  unsigned int v10; // edx@8
+  unsigned int v11; // edx@9
+  unsigned int v12; // esi@12
+  unsigned int v13; // esi@15
+  unsigned int v14; // edx@17
+  unsigned int v15; // esi@18
+  unsigned __int8 *v16; // ebx@22
+  char uFlag; // zf@28
+  int v18; // [sp+10h] [bp-10h]@4
+  unsigned __int8 *v19; // [sp+18h] [bp-8h]@4
+  int uWidth; // [sp+1Ch] [bp-4h]@4
+  int uXa; // [sp+28h] [bp+8h]@24
+  unsigned int uYa; // [sp+2Ch] [bp+Ch]@22
+  unsigned int pTexturea; // [sp+30h] [bp+10h]@11
+
+  if ( this->uNumSceneBegins )
+  {
+    pCurrentTexture = pTexture;
+    if ( pTexture )
+    {
+      if ( pTexture->pPalette16 )
+      {
+        uHeight = pTexture->uTextureHeight;
+        v6 = &this->pTargetSurface[uX + uY * this->uTargetSurfacePitch];
+        v19 = pTexture->pLevelOfDetail0;
+        uWidth = pTexture->uTextureWidth;
+        v18 = pTexture->uTextureWidth;
+        if ( this->bClip )
+        {
+          v7 = this->uClipX;
+          if ( (signed int)uX < (signed int)v7 )
+          {
+            v8 = v7 - uX;
+            v19 += v8;
+            uWidth += uX - this->uClipX;
+            v6 += v8;
+          }
+          v9 = this->uClipY;
+          uHeight = pTexture->uTextureHeight;
+          if ( (signed int)uY < (signed int)v9 )
+          {
+            v10 = v9 - uY;
+            v19 += v18 * v10;
+            uHeight = uY - this->uClipY + pTexture->uTextureHeight;
+            pCurrentTexture = pTexture;
+            v6 += this->uTargetSurfacePitch * v10;
+          }
+          v11 = this->uClipX;
+          if ( (signed int)v11 < (signed int)uX )
+            v11 = uX;
+          pTexturea = this->uClipZ;
+          if ( (signed int)(v11 + uWidth) > (signed int)pTexturea )
+          {
+            v12 = this->uClipX;
+            if ( (signed int)v12 < (signed int)uX )
+              v12 = uX;
+            uWidth = pTexturea - v12;
+          }
+          v13 = this->uClipY;
+          if ( (signed int)v13 < (signed int)uY )
+            v13 = uY;
+          v14 = this->uClipW;
+          if ( (signed int)(uHeight + v13) > (signed int)v14 )
+          {
+            v15 = this->uClipY;
+            if ( (signed int)v15 < (signed int)uY )
+              v15 = uY;
+            uHeight = v14 - v15;
+          }
+        }
+        if ( (signed int)uHeight > 0 )
+        {
+          uYa = uHeight;
+          v16 = v19;
+          do
+          {
+            if ( uWidth > 0 )
+            {
+              uXa = uWidth;
+              do
+              {
+                if ( *v16 )
+                  *v6 = pCurrentTexture->pPalette16[*v16];
+                ++v6;
+                ++v16;
+              }
+              while ( uXa-- !=1 );
+            }
+            v16 += v18 - uWidth;
+            uFlag = uYa-- == 1;
+            v6 += this->uTargetSurfacePitch - uWidth;
+          }
+          while ( !uFlag );
+        }
+      }
+    }
+  }
+}
+
+
+//----- (004A612A) --------------------------------------------------------
+void Render::_4A612A(signed int uOutX, unsigned int uOutY, Texture *pTexture, int zVal)
+{
+  Texture *v5; // eax@2
+  unsigned int v6; // edx@3
+  int v7; // ebx@3
+  int v8; // edi@3
+  signed int v9; // eax@4
+  int v10; // eax@5
+  unsigned int v11; // esi@6
+  signed int v12; // esi@8
+  unsigned int v13; // eax@10
+  signed int v14; // esi@11
+  unsigned int v15; // esi@14
+  unsigned int v16; // eax@16
+  unsigned int v17; // ecx@17
+  int v18; // edx@23
+  int v19; // [sp+Ch] [bp-Ch]@3
+  int v20; // [sp+10h] [bp-8h]@3
+  int uOutXa; // [sp+20h] [bp+8h]@21
+  unsigned __int8 *uOutYa; // [sp+24h] [bp+Ch]@3
+  int *pZBuffer; // [sp+28h] [bp+10h]@3
+
+  if ( this->uNumSceneBegins )
+  {
+    v5 = pTexture;
+    if ( pTexture )
+    {
+      v6 = uOutY;
+      v7 = pTexture->uTextureHeight;
+      pZBuffer = &this->pActiveZBuffer[uOutX + 640 * uOutY];
+      uOutYa = v5->pLevelOfDetail0;
+      v8 = v5->uTextureWidth;
+      v20 = v5->uTextureWidth;
+      v19 = v5->uTextureWidth;
+      if ( this->bClip )
+      {
+        v9 = this->uClipX;
+        if ( uOutX < v9 )
+        {
+          v10 = v9 - uOutX;
+          uOutYa += v10;
+          v8 += uOutX - this->uClipX;
+          v20 = v8;
+          pZBuffer += v10;
+        }
+        v11 = this->uClipY;
+        if ( (signed int)v6 < (signed int)v11 )
+        {
+          uOutYa += v19 * (v11 - v6);
+          v7 += v6 - v11;
+          pZBuffer += 640 * (v11 - v6);
+          v8 = v20;
+        }
+        v12 = this->uClipX;
+        if ( v12 < uOutX )
+          v12 = uOutX;
+        v13 = this->uClipZ;
+        if ( v8 + v12 > (signed int)v13 )
+        {
+          v14 = this->uClipX;
+          if ( v14 < uOutX )
+            v14 = uOutX;
+          v8 = v13 - v14;
+        }
+        v15 = this->uClipY;
+        if ( (signed int)v15 < (signed int)v6 )
+          v15 = v6;
+        v16 = this->uClipW;
+        if ( (signed int)(v7 + v15) > (signed int)v16 )
+        {
+          v17 = this->uClipY;
+          if ( (signed int)v17 >= (signed int)v6 )
+            v6 = v17;
+          v7 = v16 - v6;
+        }
+      }
+      if ( v7 > 0 )
+      {
+        uOutXa = v7;
+        do
+        {
+          if ( v8 > 0 )
+          {
+            v18 = v8;
+            do
+            {
+              if ( *uOutYa )
+                *pZBuffer = zVal;
+              ++pZBuffer;
+              ++uOutYa;
+              --v18;
+            }
+            while ( v18 );
+          }
+          pZBuffer += 640 - v8;
+          uOutYa += v19 - v8;
+          --uOutXa;
+        }
+        while ( uOutXa );
+      }
+    }
+  }
+}
+
+
+//----- (004A601E) --------------------------------------------------------
+void Render::_4A601E(signed int a2, signed int a3, Texture *pTexture, int a5)
+{
+  signed int v5; // edx@3
+  int v6; // ebx@3
+  int v7; // esi@3
+  void *v8; // esi@3
+  unsigned int v9; // eax@4
+  unsigned int v10; // eax@6
+  signed int v11; // edi@8
+  unsigned int v12; // eax@10
+  signed int v13; // edi@11
+  unsigned int v14; // edi@14
+  unsigned int v15; // eax@16
+  unsigned int v16; // ecx@17
+  int v17; // [sp+18h] [bp+Ch]@3
+  unsigned int pTexturea; // [sp+1Ch] [bp+10h]@3
+
+  if ( this->uNumSceneBegins && pTexture )
+  {
+    v5 = a3;
+    v6 = pTexture->uTextureHeight;
+    v7 = 5 * a3;
+    v17 = pTexture->uTextureHeight;
+    v8 = &this->pActiveZBuffer[a2 + (v7 << 7)];
+    pTexturea = pTexture->uTextureWidth;
+    if ( this->bClip )
+    {
+      v9 = this->uClipX;
+      if ( a2 < (signed int)v9 )
+      {
+        pTexturea += a2 - v9;
+        v8 = (char *)v8 + 4 * (v9 - a2);
+      }
+      v10 = this->uClipY;
+      if ( v5 < (signed int)v10 )
+      {
+        v17 += v5 - v10;
+        v8 = (char *)v8 + 2560 * (v10 - v5);
+      }
+      v11 = this->uClipX;
+      if ( v11 < a2 )
+        v11 = a2;
+      v12 = this->uClipZ;
+      if ( (signed int)(pTexturea + v11) > (signed int)v12 )
+      {
+        v13 = this->uClipX;
+        if ( v13 < a2 )
+          v13 = a2;
+        pTexturea = v12 - v13;
+      }
+      v14 = this->uClipY;
+      if ( (signed int)v14 < v5 )
+        v14 = v5;
+      v6 = v17;
+      v15 = this->uClipW;
+      if ( (signed int)(v17 + v14) > (signed int)v15 )
+      {
+        v16 = this->uClipY;
+        if ( (signed int)v16 < v5 )
+          v16 = v5;
+        v6 = v15 - v16;
+      }
+    }
+    if ( v6 > 0 )
+    {
+      do
+      {
+        if ( (signed int)pTexturea > 0 )
+        {
+          memset32(v8, a5, pTexturea);
+          v8 = (char *)v8 + 4 * pTexturea;
+        }
+        v8 = (char *)v8 + 4 * (640 - pTexturea);
+        --v6;
+      }
+      while ( v6 );
+    }
+  }
+}
+
+//----- (004A5EB2) --------------------------------------------------------
+void Render::DrawTextureIndexed(unsigned int uX, unsigned int uY, Texture *a4)
+{
+  Texture *v4; // edi@2
+  unsigned int v5; // ebx@4
+  unsigned __int16 *pTarget; // eax@4
+  unsigned int v7; // edx@5
+  unsigned int v8; // edx@6
+  unsigned int v9; // edx@7
+  unsigned int v10; // edx@8
+  unsigned int v11; // edx@9
+  unsigned int v12; // esi@12
+  unsigned int v13; // esi@15
+  unsigned int v14; // edx@17
+  unsigned int v15; // esi@18
+  unsigned __int8 *v16; // edx@22
+  char v17; // zf@26
+  int v18; // [sp+10h] [bp-10h]@4
+  unsigned __int8 *v19; // [sp+18h] [bp-8h]@4
+  int v20; // [sp+1Ch] [bp-4h]@4
+  int uXa; // [sp+28h] [bp+8h]@24
+  unsigned int uYa; // [sp+2Ch] [bp+Ch]@22
+  unsigned int v23; // [sp+30h] [bp+10h]@11
+
+  if ( this->uNumSceneBegins )
+  {
+    v4 = a4;
+    if ( a4 )
+    {
+      if ( a4->pPalette16 )
+      {
+        v5 = a4->uTextureHeight;
+        pTarget = &this->pTargetSurface[uX + uY * this->uTargetSurfacePitch];
+        v19 = a4->pLevelOfDetail0;
+        v20 = a4->uTextureWidth;
+        v18 = a4->uTextureWidth;
+        if ( this->bClip )
+        {
+          v7 = this->uClipX;
+          if ( (signed int)uX < (signed int)v7 )
+          {
+            v8 = v7 - uX;
+            v19 += v8;
+            v20 += uX - this->uClipX;
+            pTarget += v8;
+          }
+          v9 = this->uClipY;
+          v5 = a4->uTextureHeight;
+          if ( (signed int)uY < (signed int)v9 )
+          {
+            v10 = v9 - uY;
+            v19 += v18 * v10;
+            v5 = uY - this->uClipY + a4->uTextureHeight;
+            v4 = a4;
+            pTarget += this->uTargetSurfacePitch * v10;
+          }
+          v11 = this->uClipX;
+          if ( (signed int)v11 < (signed int)uX )
+            v11 = uX;
+          v23 = this->uClipZ;
+          if ( (signed int)(v11 + v20) > (signed int)v23 )
+          {
+            v12 = this->uClipX;
+            if ( (signed int)v12 < (signed int)uX )
+              v12 = uX;
+            v20 = v23 - v12;
+          }
+          v13 = this->uClipY;
+          if ( (signed int)v13 < (signed int)uY )
+            v13 = uY;
+          v14 = this->uClipW;
+          if ( (signed int)(v5 + v13) > (signed int)v14 )
+          {
+            v15 = this->uClipY;
+            if ( (signed int)v15 < (signed int)uY )
+              v15 = uY;
+            v5 = v14 - v15;
+          }
+        }
+        if ( (signed int)v5 > 0 )
+        {
+          uYa = v5;
+          v16 = v19;
+          do
+          {
+            if ( v20 > 0 )
+            {
+              uXa = v20;
+              do
+              {
+                *pTarget = v4->pPalette16[*v16];
+                ++pTarget;
+                ++v16;
+                --uXa;
+              }
+              while ( uXa );
+            }
+            v16 += v18 - v20;
+            v17 = uYa-- == 1;
+            pTarget += this->uTargetSurfacePitch - v20;
+          }
+          while ( !v17 );
+        }
+      }
+    }
+  }
+}
+
+//----- (004667E9) --------------------------------------------------------
+void Render::ChangeBetweenWinFullscreenModes()
+{
+  float v0; // ST14_4@17
+  int v1; // edx@24
+  signed int v2; // ecx@24
+  int v3; // esi@25
+  int v4; // edx@26
+  ObjectDesc *v5; // eax@26
+  RGBTexture *v6; // esi@33
+  const char *v7; // eax@34
+  const char *v8; // [sp-4h] [bp-28h]@33
+  int v9; // [sp+0h] [bp-24h]@33
+  struct tagRECT Rect; // [sp+14h] [bp-10h]@15
+
+  if ( pRenderer->bWindowMode )
+    goto LABEL_52;
+  if ( dword_6BE364_game_settings_1 & 2 )
+  {
+    ModalWindow(pGlobalTXT_LocalizationStrings[62], 0);// "Might and Magic VII requires your desktop to be in 16bit (32k or 65k) Color mode in order to operate in a window."
+    return;
+  }
+  if ( !pRenderer->pRenderD3D || pRenderer->pRenderD3D->pAvailableDevices->bIsDeviceCompatible )
+  {
+LABEL_52:
+    if ( pEventTimer->bPaused )
+      BYTE1(dword_6BE364_game_settings_1) |= 8u;
+    else
+      pEventTimer->Pause();
+    if ( pMiscTimer->bPaused )
+      BYTE1(dword_6BE364_game_settings_1) |= 0x10u;
+    else
+      pMiscTimer->Pause();
+    pMouse->bActive = 0;
+    if ( pRenderer->pRenderD3D )
+    {
+      pBitmaps_LOD->ReleaseHardwareTextures();
+      pSprites_LOD->ReleaseAll();
+    }
+    if ( pRenderer->bWindowMode )
+    {
+      if ( GetWindowRect(hWnd, &Rect) )
+      {
+        WriteWindowsRegistryInt("window X", Rect.left);
+        WriteWindowsRegistryInt("window Y", Rect.top);
+        uWindowX = Rect.left;
+        uWindowY = Rect.top;
+      }
+      SetMenu(hWnd, 0);
+      SetWindowLongA(hWnd, -20, 0);
+      SetWindowLongA(hWnd, -16, 0x10000000u);
+      pRenderer->InitializeFullscreen(hWnd);
+      v0 = (double)(signed int)uGammaPos * 0.1 + 0.6;
+      pGame->pGammaController->Initialize(v0);
+    }
+    else
+    {
+      ClipCursor(0);
+      pRenderer->SwitchToWindow(hWnd);
+      SetWindowLongA(hWnd, -16, uWindowStyle);
+      SetMenu(hWnd, hOSMenu);
+    }
+    if ( pRenderer->pRenderD3D )
+    {
+      pBitmaps_LOD->_410423_move_textures_to_device();
+      pSprites_LOD->MoveSpritesToVideoMemory();
+    }
+    if ( pPaletteManager->uNumTargetBBits == pRenderer->uTargetBBits
+      && pPaletteManager->uNumTargetGBits == pRenderer->uTargetGBits
+      && pPaletteManager->uNumTargetRBits == pRenderer->uTargetRBits )
+      goto LABEL_38;
+    pPaletteManager->SetColorChannelInfo(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);
+    pPaletteManager->RecalculateAll();
+    pBitmaps_LOD->SetupPalettes(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);
+    pIcons_LOD->SetupPalettes(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);
+    v2 = 0;
+    if ( (signed int)pObjectList->uNumObjects > 0 )
+    {
+      v3 = 0;
+      do
+      {
+        BYTE3(v4) = 0;
+        v5 = &pObjectList->pObjects[v3];
+        ++v3;
+        *(short *)((char *)&v4 + 1) = v5->uParticleTrailColorR;
+        LOBYTE(v4) = v5->uParticleTrailColorG;
+        v1 = v5->uParticleTrailColorB | (v4 << 8);
+        ++v2;
+        v5->uParticleTrailColor = v1;
+      }
+      while ( v2 < (signed int)pObjectList->uNumObjects );
+    }
+    LOBYTE(v1) = 1;
+    SetUserInterface(pParty->uAlignment, v1);
+    if ( pVideoPlayer->pVideoFrame.pPixels )
+      pVideoPlayer->pVideoFrame.Load(pVideoPlayer->pVideoFrameTextureFilename, 1);
+    if ( uCurrentMenuID )
+    {
+      if ( uCurrentMenuID != 6 )
+      {
+        if ( uCurrentMenuID == 8 )
+          dword_A74C88 = 1;
+        goto LABEL_38;
+      }
+      v6 = &pTexture_PCX;
+      pTexture_PCX.Release();
+      v9 = 0;
+      v8 = "makeme.pcx";
+    }
+    else
+    {
+      v6 = &pTexture_PCX;
+      pTexture_PCX.Release();
+      v7 = "title.pcx";
+      if ( uCurrentMenuID )
+        v7 = "lsave640.pcx";
+      v9 = 0;
+      v8 = v7;
+    }
+    v6->Load(v8, v9);
+LABEL_38:
+    viewparams->bRedrawGameUI = 1;
+    viewparams->_443343();
+    pMouse->SetCurrentCursorBitmap();
+    if ( pRenderer->bWindowMode )
+    {
+      InvalidateRect(0, 0, 0);
+      MoveWindow(hWnd, uWindowX, uWindowY, uWindowWidth, uWindowHeight, 0);
+      ShowWindow(hWnd, 1);
+    }
+    pMouse->bActive = 1;
+    if ( pVideoPlayer->AnyMovieLoaded() )
+      pVideoPlayer->_4BF73A();
+    if ( BYTE1(dword_6BE364_game_settings_1) & 8 )
+      BYTE1(dword_6BE364_game_settings_1) &= 0xF7u;
+    else
+      pEventTimer->Resume();
+    if ( BYTE1(dword_6BE364_game_settings_1) & 0x10 )
+      BYTE1(dword_6BE364_game_settings_1) &= 0xEFu;
+    else
+      pMiscTimer->Resume();
+    pAsyncMouse->Release();
+    CreateAsyncMouse();
+    if (pAsyncMouse)
+      pAsyncMouse->Clip();
+  }
+}
+// 6BE364: using guessed type int dword_6BE364_game_settings_1;
+// A74C88: using guessed type int dword_A74C88;
+
+
+//----- (0044EC20) --------------------------------------------------------
+bool RenderD3D::DoesRaiseExceptions()
+{
+  return true;
+}
+
+
+//----- (0040DBD3) --------------------------------------------------------
+void __fastcall Render::SetPixel(Vec2_int_ *pTargetXY, unsigned __int16 uColor)
+{
+  Vec2_int_ *pTargetXY_; // esi@1
+  unsigned __int16 v3; // di@1
+  signed int v4; // ecx@2
+  signed int v5; // eax@4
+
+  pTargetXY_ = pTargetXY;
+  v3 = uColor;
+  pRenderer->BeginScene();
+  if ( pRenderer->uNumSceneBegins )
+  {
+    v4 = pTargetXY_->x;
+    if ( pTargetXY_->x >= 0 )
+    {
+      if ( v4 <= 639 )
+      {
+        v5 = pTargetXY_->y;
+        if ( v5 >= 0 )
+        {
+          if ( v5 <= 479 )
+            pRenderer->pTargetSurface[v4 + pRenderer->uTargetSurfacePitch * v5] = v3;
+        }
+      }
+    }
+    pRenderer->EndScene();
+  }
+}
+
+
+//----- (004524D8) --------------------------------------------------------
+HWLTexture *RenderHWLContainer::LoadTexture(const char *pName, int bMipMaps)
+{
+  int v11; // eax@13
+  int v12; // ecx@13
+  void *v13; // eax@13
+  unsigned __int8 v14; // zf@13
+  unsigned __int8 v15; // sf@13
+  int v16; // esi@14
+  int v17; // ecx@16
+  int v18; // esi@16
+  unsigned __int16 *v19; // eax@16
+  int v20; // edx@16
+  int v21; // ecx@16
+  int v22; // eax@16
+  int v23; // esi@16
+  unsigned __int16 *v26; // [sp+24h] [bp-10h]@13
+  int v27; // [sp+28h] [bp-Ch]@14
+  int v28; // [sp+2Ch] [bp-8h]@13
+  int pDestb; // [sp+3Ch] [bp+8h]@15
+
+  //v3 = this;
+  //sprintf(Str1, "%s", pName);
+  //v4 = uNumItems;
+  if (!uNumItems)
+    return nullptr;
+
+  //{
+  //v5 = 0, pDesta = uNumItems;
+  uint idx1 = 0,
+       idx2 = uNumItems;
+  while (true)
+  {
+    auto i = idx1 + (idx2 - idx1) / 2;
+
+    auto res = strcmpi(pName, pSpriteNames[i]);
+    if (!res)
+    {
+      fseek(pFile, pSpriteOffsets[i], SEEK_SET);
+      break;
+    }
+    else if (res < 0)
+      idx2 = idx1 + (idx2 - idx1) / 2;
+    else
+      idx1 = i + 1;
+
+    if ( idx1 >= idx2 )
+      return false;
+  }
+
+
+  uint uCompressedSize = 0;
+  fread(&uCompressedSize, 4, 1, pFile);
+
+    auto pTex = new HWLTexture;
+    fread(&pTex->field_18, 4, 1, pFile);
+    fread(&pTex->field_1C, 4, 1, pFile);
+    fread(&pTex->field_20, 4, 1, pFile);
+    fread(&pTex->field_24, 4, 1, pFile);
+    fread(&pTex->uWidth, 4, 1, pFile);
+    fread(&pTex->uHeight, 4, 1, pFile);
+    fread(&pTex->field_30, 4, 1, pFile);
+    fread(&pTex->field_34, 4, 1, pFile);
+
+    pTex->pPixels = new unsigned __int16[pTex->uWidth * pTex->uHeight];
+    if (uCompressedSize)
+    {
+      auto pCompressedData = new char[uCompressedSize];
+      {
+        fread(pCompressedData, 1, uCompressedSize, pFile);
+        auto uDecompressedSize = pTex->uWidth * pTex->uHeight * sizeof(short);
+        zlib::MemUnzip(pTex->pPixels, &uDecompressedSize, pCompressedData, uCompressedSize);
+      }
+      delete [] pCompressedData;
+    }
+    else
+      fread(pTex->pPixels, 2, pTex->uWidth * pTex->uHeight, pFile);
+
+    if ( field_61A94_scale_hwls_to_half )
+    {
+      v11 = pTex->uHeight / 2;
+      v12 = pTex->uWidth / 2;
+      pTex->uHeight = v11;
+      pTex->uWidth = v12;
+      v13 = new unsigned __int16[v12 * v11];
+      v28 = 0;
+      v14 = pTex->uHeight == 0;
+      v15 = (pTex->uHeight & 0x80000000u) != 0;
+      v26 = (unsigned __int16 *)v13;
+      if ( !(v15 | v14) )
+      {
+        v16 = pTex->uWidth;
+        v27 = 1;
+        do
+        {
+          pDestb = 0;
+          if ( v16 > 0 )
+          {
+            do
+            {
+              v17 = v16 * v27;
+              v18 = v28 * v16;
+              v19 = pTex->pPixels;
+              v20 = pDestb + 2 * v18;
+              v21 = (int)&v19[2 * (pDestb + v17)];
+              v22 = (int)&v19[2 * v20];
+              LOWORD(v20) = *(unsigned short *)(v21 + 2);
+              LOWORD(v21) = *(unsigned short *)v21;
+              v23 = pDestb++ + v18;
+              v26[v23] = sub_452442(*(unsigned short *)v22, *(unsigned short *)(v22 + 2), v21, v20);
+              v16 = pTex->uWidth;
+            }
+            while (pDestb < pTex->uWidth);
+          }
+          ++v28;
+          v27 += 2;
+        }
+        while ( v28 < (signed int)pTex->uHeight );
+      }
+      delete [] pTex->pPixels;
+      pTex->pPixels = v26;
+    }
+    return pTex;
+    //result = pTex;
+//  }
+//  else
+//  {
+//LABEL_8:
+//    return nullptr;
+//  }
+}
+
+//----- (0045271F) --------------------------------------------------------
+bool RenderHWLContainer::Release()
+{
+  RenderHWLContainer *v1; // esi@1
+  int v2; // ebx@1
+  void **v3; // edi@3
+  __int32 v4; // eax@6
+  FILE *v5; // ST24_4@6
+  size_t *v6; // edi@6
+  int v7; // ebx@7
+  signed int v9; // [sp+0h] [bp-8h]@6
+  FILE *File; // [sp+4h] [bp-4h]@6
+
+  v1 = this;
+  v2 = 0;
+  if ( this->bDumpDebug )
+  {
+    File = fopen("logd3d.txt", "w");
+    v4 = ftell(v1->pFile);
+    v5 = v1->pFile;
+    v6 = &v1->uNumItems;
+    v1->uDataOffset = v4;
+    fwrite(&v1->uNumItems, 4u, 1u, v5);
+    v9 = 0;
+    if ( (signed int)v1->uNumItems > 0 )
+    {
+      v7 = (int)v1->pSpriteNames;
+      do
+      {
+        fwrite(*(const void **)v7, 1u, 0x14u, v1->pFile);
+        fprintf(File, "D3D texture name:  %s\t\toffset: %x\n", *(unsigned int *)v7, *(unsigned int *)(v7 + 200000));
+        ++v9;
+        v7 += 4;
+      }
+      while ( v9 < (signed int)*v6 );
+      v2 = 0;
+    }
+    fwrite(v1->pSpriteOffsets, 4u, *v6, v1->pFile);
+    fseek(v1->pFile, 4, v2);
+    fwrite(&v1->uDataOffset, 4u, 1u, v1->pFile);
+    fclose(v1->pFile);
+    fclose(File);
+  }
+  else
+  {
+    fclose(this->pFile);
+    if ( (signed int)v1->uNumItems > 0 )
+    {
+      v3 = (void **)v1->pSpriteNames;
+      do
+      {
+        free(*v3);
+        ++v2;
+        ++v3;
+      }
+      while ( v2 < (signed int)v1->uNumItems );
+    }
+  }
+  return 1;
+}
+
+//----- (00452347) --------------------------------------------------------
+RenderHWLContainer::RenderHWLContainer():
+  bDumpDebug(false)
+{
+  RenderHWLContainer *v1; // esi@1
+
+  v1 = this;
+  this->pFile = 0;
+  uSignature = 0;
+  v1->uDataOffset = 0;
+  memset(&v1->uNumItems, 0, 0x61A84u);
+  v1->uNumItems = 0;
+  v1->field_61A94_scale_hwls_to_half = 0;
+}
+
+//----- (0045237F) --------------------------------------------------------
+bool RenderHWLContainer::Load(const wchar_t *pFilename)
+{
+  pFile = _wfopen(pFilename, L"rb");
+  if (!pFile)
+  {
+    Log::Warning(L"Failed to open file: %s", pFilename);
+    return false;
+  }
+
+  fread(&uSignature, 1, 4, pFile);
+  if (uSignature != 'TD3D')
+  {
+    Log::Warning(L"Invalid format: %s", pFilename);
+    return false;
+  }
+  
+  fread(&uDataOffset, 4, 1, pFile);
+  fseek(pFile, uDataOffset, SEEK_SET);
+  fread(&uNumItems, 4, 1, pFile);
+
+  memset(pSpriteNames, 0, 50000 * sizeof(char *));
+  for (uint i = 0; i < uNumItems; ++i)
+  {
+    pSpriteNames[i] = new char[20];
+    fread(pSpriteNames[i], 1, 20, pFile);
+  }
+  fread(pSpriteOffsets, 4, uNumItems, pFile);
+
+  return true;
+}
+
+
+
+
+
+
+
+
+
+//----- (004A1C1E) --------------------------------------------------------
+void DoRenderBillboards_D3D()
+{
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 3u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1u));
+
+  for (uint i = pRenderer->uNumBillboardsToDraw - 1; i != (uint)-1; --i)
+  {
+    auto p = pRenderer->pBillboardRenderListD3D + i;
+
+    if (p->uOpacity != RenderBillboardD3D::InvalidOpacity)
+      SetBillboardBlendOptions(p->uOpacity);
+    
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, p->pTexture));
+    ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+        p->pQuards, p->uNumVertices, D3DDP_DONOTLIGHT | D3DDP_DONOTUPDATEEXTENTS));
+  }
+
+  if (pRenderer->bFogEnabled)
+  {
+    pRenderer->bFogEnabled = false;
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1));
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, GetLevelFogColor() & 0xFFFFFF));
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0));
+  }
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 2));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 1u));
+}
+
+
+
+
+
+//----- (004A1DA8) --------------------------------------------------------
+void SetBillboardBlendOptions(RenderBillboardD3D::OpacityType a1)
+{
+  switch (a1)
+  {
+    case RenderBillboardD3D::Transparent:
+    {
+      if (pRenderer->bFogEnabled)
+      {
+        pRenderer->bFogEnabled = false;
+        ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1u));
+        ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, GetLevelFogColor() & 0xFFFFFF));
+        ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0));
+      }
+
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 5));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 6u));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 1));
+    }
+    break;
+
+    case RenderBillboardD3D::Opaque_1:
+    case RenderBillboardD3D::Opaque_2:
+    case RenderBillboardD3D::Opaque_3:
+    {
+      if (pRenderer->bUsingSpecular)
+      {
+        if (!pRenderer->bFogEnabled)
+        {
+          pRenderer->bFogEnabled = true;
+          ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0));
+        }
+      }
+
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 2u));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 0));
+    }
+    break;
+
+    default:
+      Log::Warning(L"SetBillboardBlendOptions: invalid opacity type (%u)", a1);
+    break;
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Render.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,506 @@
+#pragma once
+#include <stdio.h>
+
+#include "lib\legacy_dx\d3d.h"
+#include "OSAPI.h"
+
+#include "Sprites.h"
+#include "VectorTypes.h"
+
+struct stru148;
+struct Texture;
+struct RGBTexture;
+struct RenderBillboardTransform_local0;
+struct ODMFace;
+
+
+/*  119 */
+#pragma pack(push, 1)
+struct RenderVertexSoft
+{
+  inline RenderVertexSoft():
+    flt_2C(0.0f)
+  {}
+
+  Vec3_float_ vWorldPosition;
+  Vec3_float_ vWorldViewPosition;
+  float vWorldViewProjX;
+  float vWorldViewProjY;
+  float flt_20;
+  float u;
+  float v;
+  float flt_2C;
+};
+#pragma pack(pop)
+
+
+
+/*  112 */
+#pragma pack(push, 1)
+struct RenderVertexD3D3
+{
+  Vec3_float_ pos;
+  float rhw;
+  unsigned int diffuse;
+  unsigned int specular;
+  Vec2_float_ texcoord;
+};
+
+
+
+/*  161 */
+#pragma pack(push, 1)
+struct RenderBillboard
+{
+  int field_0;
+  int field_4;
+  float fov_x;
+  float fov_y;
+  int sZValue;
+  int field_14;
+  unsigned __int16 uHwSpriteID;
+  __int16 uPalette;
+  __int16 uIndoorSectorID;
+  __int16 field_1E;
+  __int16 some_x;
+  __int16 some_y;
+  __int16 some_z;
+  __int16 uScreenSpaceX;
+  __int16 uScreenSpaceY;
+  unsigned __int16 uPaletteSubindex;
+  unsigned int uTintColor;
+  SpriteFrame *pSpriteFrame;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct RenderD3D__DevInfo
+{
+  unsigned int bIsDeviceCompatible;
+  char *pName;
+  char *pDescription;
+  GUID *pGUID;
+  unsigned int uCaps;
+  char *pDriverName;
+  char *pDeviceDesc;
+  char *pDDraw4DevDesc;
+  GUID *pDirectDrawGUID;
+  int uVideoMem;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct RenderD3D_D3DDevDesc
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  char *pDriverName;
+  char *pDeviceDesc;
+  char *pDDraw4DevDesc;
+  GUID *pGUID;
+  unsigned int uVideoMem;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+/*  280 */
+#pragma pack(push, 1)
+struct HWLTexture
+{
+  inline HWLTexture():
+    field_0(0), field_4(0), field_8(0),
+    field_C(0), field_10(0), field_14(0)
+  {}
+
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  unsigned int uWidth;
+  unsigned int uHeight;
+  int field_30;
+  int field_34;
+  unsigned __int16 *pPixels;
+};
+#pragma pack(pop)
+
+
+/*  185 */
+#pragma pack(push, 1)
+struct RenderHWLContainer
+{
+       RenderHWLContainer();
+  bool Load(const wchar_t *pFilename);
+  bool Release();
+
+  HWLTexture *LoadTexture(const char *pName, int bMipMaps);
+
+  FILE *pFile;
+  uint  uSignature;
+  unsigned int uDataOffset;
+  unsigned int uNumItems;
+  char *pSpriteNames[50000];
+  int pSpriteOffsets[50000];
+  int bDumpDebug;
+  int field_61A94_scale_hwls_to_half;
+};
+#pragma pack(pop)
+
+
+
+/*  242 */
+#pragma pack(push, 1)
+struct RenderBillboardD3D
+{
+  enum OpacityType: unsigned __int32
+  {
+    Transparent = 0,
+    Opaque_1 = 1,
+    Opaque_2 = 2,
+    Opaque_3 = 3,
+    InvalidOpacity = 0xFFFFFFFF
+  };
+
+  IDirect3DTexture2 *pTexture;
+  unsigned int uNumVertices;
+  RenderVertexD3D3 pQuards[4];
+  float flt_88;
+  OpacityType uOpacity;
+  int field_90;
+  int sZValue;
+  unsigned int uParentBillboardID;
+};
+#pragma pack(pop)
+
+
+
+
+#pragma pack(push, 1)
+struct RenderD3D_aux
+{
+  RenderD3D__DevInfo *pInfo;
+  RenderD3D_D3DDevDesc *ptr_4;
+};
+#pragma pack(pop)
+
+
+
+/*  183 */
+#pragma pack(push, 1)
+struct RenderD3D
+{
+  RenderD3D();
+
+  static bool DoesRaiseExceptions();
+  
+  void GetAvailableDevices(RenderD3D__DevInfo **pOutDevices);
+  void Release();
+  bool CreateDevice(unsigned int uDeviceID, int bWindowed, HWND hWnd);
+  unsigned int GetDeviceCaps();
+  void ClearTarget(unsigned int bClearColor, unsigned int uClearColor, unsigned int bClearDepth, float z_clear);
+  void Present(bool bForceBlit);
+  bool CreateTexture(unsigned int uTextureWidth, unsigned int uTextureHeight, IDirectDrawSurface4 **pOutSurface, IDirect3DTexture2 **pOutTexture, bool bAlphaChannel, bool bMipmaps, unsigned int uMinDeviceTexDim);
+  void HandleLostResources();
+
+
+  unsigned int bWindowed;
+  int field_4;
+  int field_8;
+  HWND hWindow;
+  int field_10;
+  int field_14;
+  int field_18;
+  RenderD3D__DevInfo *pAvailableDevices;
+  IDirectDraw4 *pHost;
+  IDirect3D3 *pDirect3D;
+  IUnknown *pUnk;
+  IDirectDrawSurface4 *pBackBuffer;
+  IDirectDrawSurface4 *pFrontBuffer;
+  IDirectDrawSurface4 *pZBuffer;
+  IDirect3DDevice3 *pDevice;
+  IDirect3DViewport3 *pViewport;
+  int field_40;
+  int field_44;
+  char pErrorMessage[48];
+  char field_78[208];
+};
+#pragma pack(pop)
+
+
+/*  182 */
+#pragma pack(push, 1)
+struct Render
+{
+  Render();
+  ~Render();
+
+  static Render *Create() {return new Render;}
+
+  bool Initialize(bool bWindowed, uint uDefaultDevice,
+                  bool bColoredLights, uint uDetailLevel, uint bTinting);
+
+  static void __fastcall SetPixel(struct Vec2_int_ *pTargetXY, unsigned __int16 uColor);
+
+  bool IsColorKeySupported(IDirectDraw4 *);
+  void _49EBF1();
+  void ClearBlack();
+  void PresentBlackScreen();
+  void SavePCXScreenshot();
+  void _49F1BC(const char *a1);
+  int _49F5A2(int a2, int a3, int a4, void *Dst, int a6, int a7);
+  FILE *SavePCXImage(const char *Filename, char *a3, int a4, int a5);
+  void ClearTarget(unsigned int uColor);
+  void Release2();
+  void Present();
+  void _49FD3A();
+  void CreateZBuffer();
+  void Release();
+  void CreateSomeTexture();
+  bool InitializeFullscreen(HWND hWnd);
+  bool SwitchToWindow(HWND hWnd);
+  char Line2D(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW, unsigned __int16 uColor);
+  void ClearZBuffer(int a2, int a3);
+  void Clip_v2(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW);
+  void ParseTargetPixelFormat();
+  bool LockSurface_DDraw4(IDirectDrawSurface4 *pSurface, DDSURFACEDESC2 *pDesc, unsigned int uLockFlags);
+  bool LockSurface_DDraw2(IDirectDrawSurface2 *pSurface, DDSURFACEDESC *pDesc, unsigned int uLockFlags);
+  void CreateDirectDraw();
+  void SetDirectDrawCooperationMode(HWND hWnd, bool bFullscreen);
+  void SetDirectDrawDisplayMode(unsigned int uWidth, unsigned int uHeight, unsigned int uBPP);
+  void CreateFrontBuffer();
+  void CreateBackBuffer();
+  void CreateDirectDrawPrimarySurface();
+  void CreateClipper(HWND a2);
+  void GetTargetPixelFormat(DDPIXELFORMAT *pOut);
+  void LockRenderSurface(void **pOutSurfacePtr, unsigned int *pOutPixelsPerRow);
+  bool UsingDirect3D();
+  void UnlockBackBuffer();
+  void LockFrontBuffer(void **pOutSurface, unsigned int *pOutPixelsPerRow);
+  void UnlockFrontBuffer();
+  void RestoreFrontBuffer();
+  HRESULT _4A184C();
+  void PresentRect(RECT *a2, RECT *a3);
+  void BltToFront(RECT *pDstRect, IDirectDrawSurface *pSrcSurface, RECT *pSrcRect, unsigned int uBltFlags);
+  void BltBackToFontFast(int a2, int a3, RECT *a4);
+  unsigned int Billboard_ProbablyAddToListAndSortByZOrder(unsigned int a1);
+  unsigned int GetBillboardDrawListSize();
+  unsigned int GetParentBillboardID(unsigned int uBillboardID);
+  void BeginSceneD3D();
+  void DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene();
+  unsigned int GetActorTintColor(float a2, int a3, int a4, int a5, RenderBillboard *a6);
+  void DrawPolygon(unsigned int uNumVertices, stru148 *a3, ODMFace *a4, IDirect3DTexture2 *pTexture);
+  void DrawTerrainPolygon(unsigned int uNumVertices, stru148 *a4, IDirect3DTexture2 *a5, int a6, int a7);
+  void DrawFan(unsigned int uNumVertices, stru148 *a3, IDirect3DTexture2 *a4);
+  void _4A2ED5(signed int a2, stru148 *a3, IDirect3DTexture2 *pHwTex);
+  void DrawIndoorPolygon(unsigned int uNumVertices, struct BLVFace *a3, IDirect3DTexture2 *pHwTex, Texture *pTex, int uPackedID, unsigned int uColor, int a8);
+  void MakeParticleBillboardAndPush_BLV(RenderBillboardTransform_local0 *a2, IDirect3DTexture2 *a3, unsigned int uDiffuse, int angle);
+  void MakeParticleBillboardAndPush_ODM(RenderBillboardTransform_local0 *a2, IDirect3DTexture2 *a3, unsigned int uDiffuse, int angle);
+  void TransformBillboard(RenderBillboardTransform_local0 *a2, Sprite *pSprite, int a1a, RenderBillboard *pBillboard);
+  void DrawBillboard_Indoor(RenderBillboardTransform_local0 *pSoftBillboard, Sprite *a3, int uPaletteSubindex);
+  int MakeParticleBillboardAndPush_BLV_Software(int screenSpaceX, int screenSpaceY, int z, int lightColor, int a6);
+  void DrawProjectile(float srcX, float srcY, float a3, float a4, float dstX, float dstY, float a7, float a8, IDirect3DTexture2 *a9);
+  void _4A4CC9(struct stru6_stru1_indoor_sw_billboard *a1, int a2);
+  bool LoadTexture(const char *pName, unsigned int bMipMaps, IDirectDrawSurface4 **pOutSurface, IDirect3DTexture2 **pOutTexture);
+  HWLTexture *MoveSpriteToDevice(Sprite *pSprite);
+  void BeginScene();
+  void EndScene();
+  unsigned int _4A52F1(unsigned int this_, float a3);
+  void Clip(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW);
+  void ResetClip();
+  void DrawTextureRGB(unsigned int uOutX, unsigned int uOutY, RGBTexture *a4);
+  void _4A5D33(unsigned int a2, unsigned int a3, int a4, int a5, RGBTexture *pTexture);
+  void DrawTextureIndexed(unsigned int uX, unsigned int uY, Texture *a4);
+  void _4A601E(signed int a2, signed int a3, Texture *pTexture, int a5);
+  void _4A612A(signed int uOutX, unsigned int uOutY, Texture *pTexture, int zVal);
+  void DrawTextureTransparent(unsigned int uX, unsigned int uY, Texture *pTexture);
+  void _4A63E6(unsigned int a2, unsigned int a3, Texture *a4, Texture *a5, int a6, int a7, int a8);
+  void _4A65CC(unsigned int x, unsigned int y, Texture *a4, Texture *a5, int a6, int a7, int a8);
+  void _4A6776(unsigned int a2, unsigned int a3, Texture *a4);
+  void DrawTransparentGreenShade(signed int a2, signed int a3, Texture *pTexture);
+  void _4A6A68(unsigned int a2, unsigned int a3, Texture *a4, __int16 height);
+  void DrawTextPalette(int x, int y, int a4, int a5, unsigned int uFontHeight, unsigned __int16 *pPalette, int a8);
+  void DrawText(signed int uOutX, signed int uOutY, unsigned __int8 *pFontPixels, unsigned int uCharWidth, unsigned int uCharHeight, unsigned __int16 *pFontPalette, unsigned __int16 uFaceColor, unsigned __int16 uShadowColor);
+  void FillRectFast(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, unsigned int uColor16);
+  int _4A6DF5(unsigned __int16 *pBitmap, unsigned int uBitmapPitch, struct Vec2_int_ *pBitmapXY, unsigned __int16 *pTarget, unsigned int uTargetPitch, Vec4_int_ *a7);
+  void _4A6E7E(unsigned int a2, unsigned int a3, Texture *a4);
+  char DrawBuildingsD3D();
+  struct BSPModel *DrawBuildingsSW();
+  int OnOutdoorRedrawSW();
+  void DrawSkyD3D();
+  int DrawSkySW(struct Span *a1, stru148 *a2, int a3);
+  void DrawDecorations();
+  void DrawLayingItems_Shooting_Magic_ODM();
+  void TransformBillboardsAndSetPalettesODM();
+  float DrawBezierTerrain();
+  void DrawTerrainD3D(int a1, int edx0, int a3);
+  void DrawTerrainSW(int a1, int a2, int a3);
+  __int16 ExecOutdoorDrawSW();
+  void ChangeBetweenWinFullscreenModes();
+  void DrawBillboardList_BLV();
+
+
+  unsigned int bUserDirect3D;
+  unsigned int bStartInWindow;
+  unsigned int uDesiredDirect3DDevice;
+  unsigned int uAcquiredDirect3DDevice;
+  int field_10;
+  int field_14;
+  int field_18_locked_pitch;
+  int field_1C_clipx;
+  int field_20_clipy;
+  int field_24_clipz;
+  int field_28_clipw;
+  __int16 field_2C[65536];
+  __int16 field_2002C[65536];
+  int field_4002C;
+  int field_40030;
+  int *pActiveZBuffer;
+  int *pDefaultZBuffer;
+  int field_4003C;
+  int field_40040;
+  int field_40044;
+  int field_40048;
+  int field_4004C;
+  HWND hWnd;
+  int field_40054;
+  unsigned int bWindowMode;
+  int field_4005C[11];
+  RenderD3D *pRenderD3D;
+  IDirectDraw4 *pDirectDraw4;
+  IDirectDrawSurface4 *pFrontBuffer4;
+  IDirectDrawSurface4 *pBackBuffer4;
+  IDirectDrawSurface4 *pColorKeySurface4;
+  IDirectDraw2 *pDirectDraw2;
+  IDirectDrawSurface2 *pFrontBuffer2;
+  IDirectDrawSurface2 *pBackBuffer2;
+  IDirectDrawSurface2 *pSomeSurface2;
+  DDPIXELFORMAT ddpfPrimareSuface;
+  unsigned int uTargetRBits;
+  unsigned int uTargetGBits;
+  unsigned int uTargetBBits;
+  unsigned int uTargetRMask;
+  unsigned int uTargetGMask;
+  unsigned int uTargetBMask;
+  unsigned int uNumSceneBegins;
+  int *ptr_400E8;
+  unsigned __int16 *pTargetSurface;
+  unsigned int uTargetSurfacePitch;
+  unsigned int uClipY;
+  unsigned int uClipX;
+  unsigned int uClipW;
+  unsigned int uClipZ;
+  unsigned int bClip;
+  unsigned int bColorKeySupported;
+  unsigned int uNumD3DSceneBegins;
+  int field_40110;
+  RenderHWLContainer pD3DBitmaps;
+  RenderHWLContainer pD3DSprites;
+  unsigned int bUseColoredLights;
+  unsigned int bRequiredTextureStagesAvailable;
+  unsigned int bTinting;
+  unsigned int uLevelOfDetail;
+  unsigned int uMaxDeviceTextureDim;
+  unsigned int uMinDeviceTextureDim;
+  int field_10365C;
+  unsigned int bUsingSpecular;
+  uint uFogColor;
+  int field_103668;
+  unsigned int pHDWaterBitmapIDs[7];
+  char field_103688[32];
+  int field_1036A8_bitmapid;
+  int field_1036AC_bitmapid;
+  IDirectDrawSurface4 *pSurface;
+  IDirect3DTexture2 *pTexture;
+  int field_1036B8;
+  int _gpu_memory_used;
+  void (__cdecl *pBeforePresentFunction)();
+  int field_1036C4;
+  uint bFogEnabled;
+  int field_1036CC;
+  RenderBillboardD3D pBillboardRenderListD3D[1000];
+  unsigned int uNumBillboardsToDraw;
+  int field_129834;
+  unsigned int uCurrentlyLockedSurfacePitch;
+  unsigned __int16 *pCurrentlyLockedSurfaceDataPtr;
+  unsigned __int16 *pCurrentlyLockedSoftSurface;
+};
+#pragma pack(pop)
+
+extern struct IDirectDrawClipper *pDDrawClipper;
+extern struct Render *pRenderer; // idb
+
+
+
+
+/*  248 */
+#pragma pack(push, 1)
+struct RenderBillboardTransform_local0
+{
+  unsigned __int16 *pTarget;
+  int *pTargetZ;
+  int uScreenSpaceX;
+  int uScreenSpaceY;
+  int field_10;
+  int field_14;
+  char field_18[8];
+  unsigned __int16 *pPalette;
+  unsigned __int16 *pPalette2;
+  int sZValue;
+  unsigned int uFlags;
+  unsigned int uTargetPitch;
+  unsigned int uViewportX;
+  unsigned int uViewportY;
+  unsigned int uViewportZ;
+  unsigned int uViewportW;
+  int field_44;
+  int uParentBillboardID;
+  int uTintColor;
+};
+#pragma pack(pop)
+
+
+
+
+extern int uNumDecorationsDrawnThisFrame; // weak
+extern RenderBillboard pBillboardRenderList[500];
+extern unsigned int uNumBillboardsToDraw;
+extern int uNumSpritesDrawnThisFrame; // weak
+
+
+
+
+extern RenderVertexSoft array_507D30[50];
+extern RenderVertexSoft array_508690[50];
+extern RenderVertexSoft array_508FF0[50];
+extern RenderVertexSoft array_509950[50];
+extern RenderVertexSoft array_50A2B0[50];
+extern RenderVertexSoft array_50AC10[50];
+
+extern RenderVertexSoft array_73D150[20];
+
+extern RenderVertexD3D3 arary_77E5C8[50];
+
+extern RenderVertexSoft *ptr_801A04;
+extern RenderVertexSoft *ptr_801A08;
+
+extern RenderVertexSoft pVerticesSR_801A10[384];
+extern RenderVertexSoft pVerticesSR_806210[384];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SaveLoad.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,695 @@
+#include <io.h>
+#include <direct.h>
+#include <assert.h>
+
+#include "SaveLoad.h"
+#include "NPC.h"
+#include "Party.h"
+#include "LOD.h"
+#include "Outdoor.h"
+#include "AudioPlayer.h"
+#include "Actor.h"
+#include "Chest.h"
+#include "Time.h"
+#include "GUIWindow.h"
+#include "GUIFont.h"
+#include "Overlays.h"
+#include "LayingItem.h"
+#include "Viewport.h"
+#include "stru123.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+struct SavegameList *pSavegameList = new SavegameList;
+unsigned int uNumSavegameFiles;
+unsigned int pSavegameUsedSlots[45];
+struct RGBTexture pSavegameThumbnails[45];
+SavegameHeader    pSavegameHeader[45];
+
+
+
+
+
+
+
+
+
+
+//----- (0045EE8A) --------------------------------------------------------
+void __fastcall LoadGame(unsigned int uSlot)
+{
+  bool v25; // esi@62
+  bool v26; // eax@62
+  int v30; // [sp-Ch] [bp-FCh]@65
+  int v31; // [sp-8h] [bp-F8h]@4
+  SavegameHeader header; // [sp+Ch] [bp-E4h]@23
+  char Str[123]; // [sp+70h] [bp-80h]@25
+
+  dword_5B65C8 = 0;
+  if (!pSavegameUsedSlots[uSlot])
+  {
+    pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+    Log::Warning(L"LoadGame: slot %u is empty", uSlot);
+    return;
+  }
+
+  for (uint i = 1; i < 5; ++i)
+    for (uint j = 1; j < 6; ++j)
+    {
+      sprintf(pTmpBuf, "data\\lloyd%d%d.pcx", i, j);
+      remove(pTmpBuf);
+    }
+
+
+  if (byte_4ED498)
+    for (uint i = 0; i < 4; ++i)
+    {
+      for (uint j = 0; j < pSoundList->uNumSounds; ++j)
+        if (pSoundList->pSounds[j].uSoundID == 2 * (byte_4ED498 + 50 * pParty->pPlayers[i].uVoiceID) + 4998)
+        {
+          pSoundList->_4A9DCD(j, 1);
+          break;
+        }
+
+        for (uint j = 0; j < pSoundList->uNumSounds; ++j)
+        if (pSoundList->pSounds[j].uSoundID == 2 * (byte_4ED498 + 50 * pParty->pPlayers[i].uVoiceID) + 4999)
+        {
+          pSoundList->_4A9DCD(j, 1);
+          break;
+        }
+    }
+
+  sprintf(pTmpBuf, "saves\\%s", pSavegameList->pSavesNames[uSlot]);
+
+  pNew_LOD->CloseWriteFile();
+  if (!CopyFileA(pTmpBuf, "data\\new.lod", 0))
+    int e = GetLastError();
+
+  pNew_LOD->LoadFile("data\\new.lod", 0);
+  auto *f = pNew_LOD->FindContainer("header.bin", 1);
+  if (!f)
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 100);
+    Log::Warning(L"%S", Str);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:549", 0);
+  }
+  assert(sizeof(SavegameHeader) == 100);
+  fread(&header, sizeof(SavegameHeader), 1, f);
+
+  f = pNew_LOD->FindContainer("party.bin", 1);
+  if (!f)
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 101);
+    Log::Warning(L"%S", Str);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:559", 0);
+  }
+  if (sizeof(Party) != 0x16238)
+    Log::Warning(L"class Party: deserialization warning");
+  fread(pParty, 0x16238u, 1, f);
+
+
+  f = pNew_LOD->FindContainer("clock.bin", 1);
+  if (!f)
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 102);
+    Log::Warning(L"%S", Str);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:569", 0);
+  }
+  if (sizeof(Timer) != 0x28)
+    Log::Warning(L"class Timer: deserialization warning");
+  fread(pEventTimer, 0x28u, 1u, f);
+
+  f = pNew_LOD->FindContainer("overlay.bin", 1);
+  if (!f)
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 103);
+    Log::Warning(L"%S", Str);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:579", 0);
+  }
+  if (sizeof(OtherOverlayList) != 0x3F0)
+    Log::Warning(L"class OtherOverlayList: deserialization warning");
+  fread(pOtherOverlayList, 0x3F0, 1, f);
+
+  f = pNew_LOD->FindContainer("npcdata.bin", 0);
+  if (!f)
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 104);
+    Log::Warning(L"%S", Str);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:590", 0);
+  }
+  if (sizeof(pNPCStats->pNewNPCData) != 0x94BC)
+    Log::Warning(L"NPCStats: deserialization warning");
+  fread(pNPCStats->pNewNPCData, 0x94BC, 1, f);
+  pNPCStats->_476C60();
+
+  f = pNew_LOD->FindContainer("npcgroup.bin", 0);
+  if (!f)
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 105);
+    Log::Warning(L"%S", Str);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:600", 0);
+  }
+  if (sizeof(pNPCStats->pGroups_copy) != 0x66)
+    Log::Warning(L"NPCStats: deserialization warning");
+  fread(pNPCStats->pGroups_copy, 0x66, 1, f);
+
+
+  uActiveCharacter = 0;
+  for (uint i = 0; i < 4; ++i)
+    if (pParty->pPlayers[i].CanAct())
+    {
+      uActiveCharacter = i + 1;
+      break;
+    }
+
+  for (uint i = 0; i < 4; ++i)
+  {
+    auto uQuickspell = pParty->pPlayers[i].uQuickSpell;
+    if (uQuickspell)
+      stru_AA1058[i]._494836(uQuickspell, i + 9 - 8);
+
+    for (uint j = 0; j < 2; ++j)
+    {
+      uint uEquipIdx = pParty->pPlayers[i].pEquipment.pIndices[j];
+      if (uEquipIdx)
+      {
+        auto uItemID = pParty->pPlayers[i].pInventoryItems[uEquipIdx - 1].uItemID;
+        if (pItemsTable->pItems[uItemID].uEquipType == 12)
+        {
+          __debugbreak();
+          v31 = *((int *)&pSpellDatas[66].field_8 + uItemID);
+          stru_A750F8[i]._494836(v31, i + 9);
+        }
+      }
+    }
+  }
+
+
+  pGUIWindow_CurrentMenu->Release();
+  pCurrentScreen = 0;
+
+  viewparams->bRedrawGameUI = true;
+
+  SetUserInterface(pParty->uAlignment, true);
+
+  pEventTimer->Resume();
+  pEventTimer->StopGameTime();
+
+  v25 = pGames_LOD->DoesContainerExist(header.pLocationName);
+  sprintf(pTmpBuf, "levels\\%s", header.pLocationName);
+  v26 = _access(pTmpBuf, 4) != -1;
+  if ( !v25 && !v26 )
+  {
+    sprintf(pTmpBuf, "Unable to find: %s!", header.pLocationName);
+    Abortf(pTmpBuf);
+  }
+
+  strcpy(pCurrentMapName, header.pLocationName);
+  dword_6BE364_game_settings_1 |= 0x2001;
+
+  for (uint i = 0; i < uNumSavegameFiles; ++i)
+    pSavegameThumbnails[i].Release();
+
+  pIcons_LOD->_4114F2();
+  pAudioPlayer->SetMusicVolume(pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0);
+  pAudioPlayer->SetMasterVolume(pSoundVolumeLevels[uSoundVolumeMultiplier] * 128.0);
+  if (uTurnSpeed)
+    pParty->sRotationY = uTurnSpeed * pParty->sRotationY / (signed int)uTurnSpeed;
+  MM7Initialization();
+  bFlashQuestBook = false;
+  viewparams->bRedrawGameUI = true;
+}
+
+
+//----- (0045F469) --------------------------------------------------------
+int __fastcall SaveGame(int a1, __int16 *a2)
+{
+  int result; // eax@1
+  void *pScreenshot; // edi@5
+  int v4; // eax@6
+  int v5; // eax@6
+  int v6; // eax@6
+  const char *v7; // edi@8
+  FILE *v8; // edi@24
+  int v9; // edi@30
+  void *v10; // esi@31
+  void *v11; // esi@31
+  void *v12; // esi@37
+  void *v13; // esi@37
+  void *v14; // esi@37
+  void *v15; // esi@37
+  void *v16; // esi@37
+  int v17; // esi@37
+  unsigned int v18; // ecx@38
+  unsigned int v19; // esi@39
+  char *v20; // edx@39
+  void *v21; // esi@41
+  void *v22; // esi@41
+  BSPModel *v23; // eax@42
+  signed int v24; // edi@42
+  unsigned __int8 v25; // zf@43
+  unsigned __int8 v26; // sf@43
+  signed int v27; // edi@47
+  void *v28; // esi@50
+  void *v29; // esi@50
+  void *v30; // esi@50
+  void *v31; // esi@50
+  int v32; // esi@51
+  int v33; // eax@51
+  DWORD v34; // eax@59
+  //std::string v35; // [sp-18h] [bp-288h]@8
+  const char *v36; // [sp-10h] [bp-280h]@6
+  const char *v37; // [sp-Ch] [bp-27Ch]@6
+  const char *v38; // [sp-8h] [bp-278h]@8
+  CHAR Buffer; // [sp+Ch] [bp-264h]@59
+  char Dir; // [sp+8Ch] [bp-1E4h]@51
+  char Drive; // [sp+ACh] [bp-1C4h]@51
+  SavegameHeader header; // [sp+CCh] [bp-1A4h]@10
+  //int v43; // [sp+CCh] [bp-1A4h]@10
+  //char Dest[20]; // [sp+E0h] [bp-190h]@10
+  //unsigned __int64 pTimePlayed; // [sp+F4h] [bp-17Ch]@10
+  char Filename; // [sp+130h] [bp-140h]@51
+  char Ext; // [sp+150h] [bp-120h]@51
+  char v48; // [sp+151h] [bp-11Fh]@51
+  char Source[32]; // [sp+170h] [bp-100h]@51
+  char Str[120]; // [sp+190h] [bp-E0h]@8
+  int v51; // [sp+208h] [bp-68h]@2
+  int pPositionX; // [sp+20Ch] [bp-64h]@2
+  int v53; // [sp+210h] [bp-60h]@2
+  int v54; // [sp+214h] [bp-5Ch]@2
+  int Src; // [sp+218h] [bp-58h]@30
+  char v56; // [sp+21Ch] [bp-54h]@30
+  char v57; // [sp+21Dh] [bp-53h]@30
+  char v58; // [sp+21Eh] [bp-52h]@30
+  char v59; // [sp+21Fh] [bp-51h]@30
+  int v60; // [sp+220h] [bp-50h]@30
+  int v61; // [sp+224h] [bp-4Ch]@30
+  int v62; // [sp+228h] [bp-48h]@2
+  LOD::Directory pDir; // [sp+22Ch] [bp-44h]@2
+  size_t Size; // [sp+250h] [bp-20h]@26
+  __int16 *v66; // [sp+254h] [bp-1Ch]@1
+  void *DstBuf; // [sp+258h] [bp-18h]@2
+  __int16 *v68; // [sp+25Ch] [bp-14h]@32
+  unsigned int v69; // [sp+260h] [bp-10h]@23
+  int v70; // [sp+264h] [bp-Ch]@22
+  std::string *v71; // [sp+268h] [bp-8h]@8
+  int a3; // [sp+26Fh] [bp-1h]@8
+  
+  v66 = a2;
+  strcpy(byte_6BE3B0, pCurrentMapName);
+  if (!_strcmpi(pCurrentMapName, "d05.blv"))
+    return false;
+  DstBuf = malloc(0xF4240);
+  pDir.Reset();
+  pPositionX = pParty->vPosition.x;
+  v51 = pParty->vPosition.y;
+  v62 = pParty->vPosition.z;
+  v53 = pParty->sRotationY;
+  v54 = pParty->sRotationX;
+  pParty->vPosition.x = pParty->vPrevPosition.x;
+  pParty->vPosition.y = pParty->vPrevPosition.z;
+  pParty->vPosition.z = pParty->vPrevPosition.y;
+  pParty->uFallStartY = pParty->vPrevPosition.y;
+  pParty->sRotationY = pParty->sPrevRotationY;
+  pParty->sRotationX = pParty->sPrevRotationX;
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    pIndoor->stru1.uLastVisitDay = pParty->uTimePlayed;
+  else
+    pOutdoor->uLastVisitDay = pParty->uTimePlayed;
+  pScreenshot = MakeScreenshot(150, 112);
+  strcpy(pDir.pFilename, "image.pcx");
+  pRenderer->_49F5A2((int)pScreenshot, 150, 112, DstBuf, 1000000, (int)&pDir.uDataSize);
+  free(pScreenshot);
+  if (pCurrentScreen == 11) //SaveScreen
+  {
+    pRenderer->DrawTextureIndexed(8, 8, (Texture *)(uTextureID_loadsave != -1 ? &pIcons_LOD->pTextures[uTextureID_loadsave] : 0));
+    pRenderer->DrawTextureIndexed(0x12, 0x8D, (Texture *)(uTextureID_save_up != -1 ? &pIcons_LOD->pTextures[uTextureID_save_up] : 0));
+    v4 = pFontSmallnum->AlignText_Center(0xBA, pGlobalTXT_LocalizationStrings[190]);
+    pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, v4 + 25, 219, 0, pGlobalTXT_LocalizationStrings[190], 0, 0, 0); //Ñîõðàíåíèå
+    v5 = pFontSmallnum->AlignText_Center(0xBA, (const char *)&pSavegameHeader + 100 * uLoadGameUI_SelectedSlot);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontSmallnum, v5 + 25, 0x103u, 0, (const char *)(&pSavegameHeader + uLoadGameUI_SelectedSlot), 185, 0);
+    v6 = pFontSmallnum->AlignText_Center(0xBA, pGlobalTXT_LocalizationStrings[165]);
+    pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, v6 + 25, 299, 0, pGlobalTXT_LocalizationStrings[165], 0, 0, 0); //Ïîæàëóéñòà, ïîäîæäèòå
+    pRenderer->Present();
+   }
+  if (pNew_LOD->Write(&pDir, DstBuf, 0))
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 200); //Ñîõðàíåííàÿ èãðà ïîâðåæäåíà! Code=%d
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:773", 0);
+  }
+
+  assert(sizeof(SavegameHeader) == 100);
+  memset(header.pName, 0, 20);
+  memset(header.pLocationName, 0, 20);
+  memset(header.field_30, 0, 52);
+  strcpy(header.pLocationName, pCurrentMapName);
+  header.uWordTime = pParty->uTimePlayed;
+  strcpy(pDir.pFilename, "header.bin");
+  pDir.uDataSize = sizeof(SavegameHeader);
+  if (pNew_LOD->Write(&pDir, &header, 0))
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 201);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:784", 0);
+  }
+  strcpy(pDir.pFilename, "party.bin");
+  pDir.uDataSize = 90680;
+  if ( pNew_LOD->Write(&pDir, pParty, 0) )
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 202);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:793", 0);
+  }
+  strcpy(pDir.pFilename, "clock.bin");
+  pDir.uDataSize = 40;
+  if ( pNew_LOD->Write(&pDir, pEventTimer, 0) )
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 203);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:802", 0);
+  }
+  strcpy(pDir.pFilename, "overlay.bin");
+  pDir.uDataSize = 1008;
+  if ( pNew_LOD->Write(&pDir, pOtherOverlayList, 0) )
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 204);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:811", 0);
+  }
+  strcpy(pDir.pFilename, "npcdata.bin");
+  pDir.uDataSize = 38076;
+  if ( pNew_LOD->Write(&pDir, pNPCStats->pNewNPCData, 0) )
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 205);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:820", 0);
+  }
+  strcpy(pDir.pFilename, "npcgroup.bin");
+  pDir.uDataSize = 102;
+  if ( pNew_LOD->Write(&pDir, pNPCStats->pGroups_copy, 0) )
+  {
+    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 206);
+    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:829", 0);
+  }
+  for (int i =  1; i <= 4; ++i) // 4 - players
+  {
+    for (int j =  1; j <= 5; ++j) // 5 - images
+    {
+      sprintf(Str, "data\\lloyd%d%d.pcx", i, j);
+      v8 = fopen(Str, "rb");
+      if ( v8 )
+      {
+        __debugbreak();
+        sprintf(Str, "lloyd%d%d.pcx", i, j);
+        fseek(v8, 0, 2);
+        pDir.uDataSize = ftell(v8);
+        rewind(v8);
+        fread(DstBuf, pDir.uDataSize, 1, v8);
+        strcpy((char *)&pDir, Str);
+        fclose(v8);
+        remove(Str);
+        if ( pNew_LOD->Write(&pDir, DstBuf, 0) )
+        {
+          sprintf(Str, pGlobalTXT_LocalizationStrings[612], 207);
+          MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:857", 0);
+          Size = 5080748;
+        }
+      }
+	}
+  }
+  if ( !a2 )
+  {
+    __debugbreak();
+    sub_42FA22_mess_with_laying_item_list();
+    v9 = (int)malloc(0xF4240);
+    v71 = (std::string *)v9;
+    Src = 91969;
+    v56 = 109;
+    v57 = 118;
+    v58 = 105;
+    v59 = 105;
+    v60 = 0;
+    v61 = 0;
+    memcpy((void *)v9, &Src, 0x10);
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    {
+      __debugbreak();
+      pIndoor->dlv.uNumFacesInBModels = pIndoor->uNumFaces;
+      pIndoor->dlv.uNumBModels = 0;
+      pIndoor->dlv.uNumDecorations = uNumLevelDecorations;
+      memcpy(DstBuf, &pIndoor->dlv, 0x28);
+      v10 = (char *)DstBuf + 40;
+      memcpy(v10, pIndoor->_visible_outlines, 0x36B);
+      v11 = (char *)v10 + 875;
+      if ( (signed int)pIndoor->uNumFaces > 0 )
+      {
+        v68 = 0;
+        for (int i =  0; i <= (signed int)pIndoor->uNumFaces; ++i)
+        {
+          v38 = (char *)v68 + (unsigned int)pIndoor->pFaces + 44;
+          memcpy(v11, v38, 4);
+          v68 += 48;
+          v11 = (char *)v11 + 4;
+        }
+      }
+      if ( (signed int)uNumLevelDecorations > 0 )
+      {
+        v68 = &pLevelDecorations[0].field_2;
+        for (int i =  0; i <= (signed int)uNumLevelDecorations; ++i)
+        {
+          memcpy(v11, v68, 2);
+          v68 += 16;
+          v11 = (char *)v11 + 2;
+        }
+      }
+      memcpy(v11, &uNumActors, 4);
+      v12 = (char *)v11 + 4;
+      memcpy(v12, pActors, 836 * uNumActors);
+      v13 = (char *)v12 + 836 * uNumActors;
+      memcpy(v13, &uNumLayingItems, 4);
+      v13 = (char *)v13 + 4;
+      memcpy(v13, pLayingItems, 112 * uNumLayingItems);
+      v14 = (char *)v13 + 112 * uNumLayingItems;
+      memcpy(v14, &uNumChests, 4);
+      v14 = (char *)v14 + 4;
+      memcpy(v14, pChests, 5324 * uNumChests);
+      v15 = (char *)v14 + 5324 * uNumChests;
+      memcpy(v15, pIndoor->pDoors, 0x3E80);
+      v15 = (char *)v15 + 16000;
+      memcpy(v15, pIndoor->ptr_0002B4_doors_ddata, pIndoor->blv.uDoors_ddata_Size);
+      v16 = (char *)v15 + pIndoor->blv.uDoors_ddata_Size;
+      memcpy(v16, &stru_5E4C90, 0xC8);
+      v17 = (int)((char *)v16 + 200);
+      memcpy((void *)v17, &pIndoor->stru1, 0x38);
+    }
+    else
+    {
+      v18 = 0;
+      pOutdoor->ddm.uNumFacesInBModels = 0;
+      if ( (signed int)pOutdoor->uNumBModels > 0 )
+      {
+        v19 = pOutdoor->uNumBModels;
+        v20 = (char *)&pOutdoor->pBModels->uNumFaces;
+        do
+        {
+          v18 += *(int *)v20;
+          v20 += 188;
+          --v19;
+          pOutdoor->ddm.uNumFacesInBModels = v18;
+        }
+        while ( v19 );
+      }
+      v21 = DstBuf;
+      pOutdoor->ddm.uNumBModels = pOutdoor->uNumBModels;
+      pOutdoor->ddm.uNumDecorations = uNumLevelDecorations;
+      memcpy(DstBuf, &pOutdoor->ddm, 0x28);
+      v21 = (char *)v21 + 40;
+      memcpy(v21, pOutdoor->array_528, 0x3C8);
+      v21 = (char *)v21 + 968;
+      memcpy(v21, pOutdoor->array_8F0, 0x3C8);
+      v22 = (char *)v21 + 968;
+      if ( (signed int)pOutdoor->uNumBModels > 0 )
+      {
+        v23 = pOutdoor->pBModels;
+        v24 = 76;
+        for (int i =  0; i <= (signed int)pOutdoor->uNumBModels ; ++i)
+        {
+          v25 = *(int *)&v23->pModelName[v24] == 0;
+          v26 = *(int *)&v23->pModelName[v24] < 0;
+          if ( !(v26 | v25) )
+          {
+            v68 = 0;
+            for (int j =  0; j <= *(int *)&pOutdoor->pBModels->pModelName[v24]; ++j)
+            {
+              v38 = (char *)v68 + *(int *)&v23->pModelName[v24 + 8] + 28;
+              memcpy(v22, v38, 4);
+              v23 = pOutdoor->pBModels;
+              v68 += 154;
+              v22 = (char *)v22 + 4;
+            }
+           }
+          v24 += 188;
+        }
+      }
+      if ( (signed int)uNumLevelDecorations > 0 )
+      {
+        v66 = &pLevelDecorations[0].field_2;
+        for (int i =  0; i <= (signed int)uNumLevelDecorations; ++i)
+        {
+          memcpy(v22, v66, 2);
+          v66 += 16;
+          v22 = (char *)v22 + 2;
+        }
+      }
+      memcpy(v22, &uNumActors, 4);
+      v28 = (char *)v22 + 4;
+      memcpy(v28, pActors, 836 * uNumActors);
+      v29 = (char *)v28 + 836 * uNumActors;
+      memcpy(v29, &uNumLayingItems, 4);
+      v29 = (char *)v29 + 4;
+      memcpy(v29, pLayingItems, 112 * uNumLayingItems);
+      v30 = (char *)v29 + 112 * uNumLayingItems;
+      memcpy(v30, &uNumChests, 4);
+      v30 = (char *)v30 + 4;
+      memcpy(v30, pChests, 5324 * uNumChests);
+      v31 = (char *)v30 + 5324 * uNumChests;
+      memcpy(v31, &stru_5E4C90, 0xC8);
+      v17 = (int)((char *)v31 + 200);
+      memcpy((void *)v17, &pOutdoor->uLastVisitDay, 0x38);
+      v9 = (int)v71;
+    }
+    v32 = v17 + 56;
+    strcpy(Source, pCurrentMapName);
+    _splitpath(Source, &Drive, &Dir, &Filename, &Ext);
+    v48 = 100;
+    Size = v32 - (int)DstBuf;
+    v69 = 999984;
+    LOBYTE(v33) = zlib::MemZip((char *)v9 + 16, (unsigned int *)&v69, DstBuf, v32 - (int)DstBuf);
+    if ( v33 || (signed int)v69 > (signed int)Size )
+    {
+      memcpy((void *)(v9 + 16), DstBuf, Size);
+      v69 = Size;
+    }
+    v69 += 16;
+    memcpy((void *)(v9 + 8), &v69, 4);
+    memcpy((void *)(v9 + 12), &Size, 4);
+    sprintf(Source, "%s%s", &Filename, &Ext);
+    strcpy((char *)&pDir, Source);
+    pDir.uDataSize = v69;
+    if ( pNew_LOD->Write(&pDir, (const void *)v9, 0) )
+    {
+      sprintf(Str, pGlobalTXT_LocalizationStrings[612], 208);
+      MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:1071", 0);
+    }
+    free((void *)v9);
+  }
+  free(DstBuf);
+  if ( a1 )
+  {
+    if ( !CopyFileA("data\\new.lod", "saves\\autosave.mm7", 0) )
+    {
+      v34 = GetLastError();
+      FormatMessageA(0x1000, 0, v34, 0x400, &Buffer, 0x80, 0);
+      sprintf(Str, pGlobalTXT_LocalizationStrings[612], 300);
+      MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:1097", 0);
+    }
+  }
+  pParty->vPosition.x = pPositionX;
+  pParty->vPosition.y = v51;
+  pParty->vPosition.z = v62;
+  pParty->uFallStartY = v62;
+  pParty->sRotationY = v53;
+  result = v54;
+  pParty->sRotationX = v54;
+  return result;
+}
+
+
+//----- (00460078) --------------------------------------------------------
+void __fastcall DoSavegame(unsigned int uSlot)
+{
+  unsigned int v1; // esi@1
+  int v2; // esi@2
+  RGBTexture *v3; // ebx@3
+  int bNotArena; // [sp+2Ch] [bp-8h]@1
+  unsigned int v6; // [sp+30h] [bp-4h]@1
+
+  __debugbreak();
+
+  v1 = uSlot;
+  v6 = uSlot;
+  bNotArena = _strcmpi(pCurrentMapName, "d05.blv");
+  if ( bNotArena )
+  {
+    LOD::Directory pDir; // [sp+Ch] [bp-28h]@2
+    SaveGame(0, 0);
+    v2 = 100 * v1;
+    strcpy(&pSavegameHeader->pLocationName[v2], pCurrentMapName);
+    *(int *)((char *)&pSavegameHeader->uWordTime + v2) = LODWORD(pParty->uTimePlayed);
+    *(int *)((char *)&pSavegameHeader->uWordTime + v2 + 4) = HIDWORD(pParty->uTimePlayed);
+    strcpy((char *)&pDir, "header.bin");
+    pDir.uDataSize = 100;
+    pNew_LOD->Write(&pDir, (char *)&pSavegameHeader + v2, 0);
+    sprintf(pTmpBuf, "saves\\save%03d.mm7", v6);
+    pNew_LOD->CloseWriteFile();
+    CopyFileA("data\\new.lod", pTmpBuf, 0);
+  }
+  GUI_UpdateWindows();
+  pGUIWindow_CurrentMenu->Release();
+  pCurrentScreen = 0;
+  v3 = pSavegameThumbnails;
+  viewparams->bRedrawGameUI = 1;
+  do
+  {
+    v3->Release();
+    ++v3;
+  }
+  while ( (signed int)v3 < (signed int)&unk_6A0758 );
+  if ( bNotArena )
+    pNew_LOD->_4621A7();
+  else
+    ShowStatusBarString(pGlobalTXT_LocalizationStrings[583], 2u);// "No saving in the Arena"
+  pIcons_LOD->_4355F7();
+  pEventTimer->Resume();
+  ShowStatusBarString(pGlobalTXT_LocalizationStrings[656], 2u);// "Game Saved!"
+  viewparams->bRedrawGameUI = 1;
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+
+
+
+
+
+
+
+
+
+
+//----- (0045E297) --------------------------------------------------------
+void SavegameList::Initialize(unsigned int bHideEmptySlots)
+{
+    memset(pSavegameList, 0, 0x3138);
+	uNumSavegameFiles = 0;
+
+  _chdir("saves");
+  {
+    if (!bHideEmptySlots && _access(pGlobalTXT_LocalizationStrings[613], 0) != -1 )
+      strcpy(pSavesNames[uNumSavegameFiles++], pGlobalTXT_LocalizationStrings[613]);
+
+    for (uint i = 0; i < 40; ++i)
+    {
+      sprintf(pTmpBuf, "save%03d.mm7", i);
+      if (_access(pTmpBuf, 0) == -1)
+        continue;
+
+      uint idx = i;
+      if (!bHideEmptySlots)
+        idx = uNumSavegameFiles;
+      strcpy(pSavesNames[idx], pTmpBuf);
+
+      ++uNumSavegameFiles;
+    }
+  }
+  _chdir("..");
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SaveLoad.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,34 @@
+#pragma once
+
+
+
+/*  243 */
+#pragma pack(push, 1)
+struct SavegameList
+{
+  void Initialize(unsigned int a1);
+
+  char field_0[20];
+  char pSavesNames[40][280];
+};
+#pragma pack(pop)
+
+
+/*  244 */
+#pragma pack(push, 1)
+struct SavegameHeader
+{
+  char pName[20];
+  char pLocationName[20];
+  unsigned __int64 uWordTime;
+  char field_30[52];
+};
+#pragma pack(pop)
+
+
+
+extern unsigned int uNumSavegameFiles;
+extern unsigned int pSavegameUsedSlots[45];
+extern struct SavegameList  *pSavegameList;
+extern struct RGBTexture     pSavegameThumbnails[];
+extern struct SavegameHeader pSavegameHeader[];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Spells.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,313 @@
+#include <stdlib.h>
+
+#include "Spells.h"
+#include "Overlays.h"
+#include "Allocator.h"
+#include "LOD.h"
+#include "stru123.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+struct SpellStats *pSpellStats;
+
+
+stru324_spell stru_4E3ACC[102];
+SpellData pSpellDatas[95];
+
+
+
+
+
+
+//----- (0042EB31) --------------------------------------------------------
+bool SpellBuff::NotExpired()
+{
+  bool result; // eax@1
+
+  result = 0;
+  if ( (signed __int64)this->uExpireTime > 0 )
+    result = 1;
+  return result;
+}
+
+
+//----- (00458585) --------------------------------------------------------
+void SpellBuff::Reset()
+{
+  SpellBuff *v1; // esi@1
+  unsigned __int16 v2; // ax@1
+
+  v1 = this;
+  v2 = this->uOverlayID;
+  this->uSkill = 0;
+  this->uPower = 0;
+  this->uExpireTime = 0i64;
+  this->uCaster = 0;
+  this->uFlags = 0;
+  if ( v2 )
+  {
+    ((OtherOverlay *)&stru_5E4C90._decor_events[20 * v2 + 105])->Reset();
+    pOtherOverlayList->field_3EC = 1;
+    v1->uOverlayID = 0;
+  }
+}
+
+//----- (004585CA) --------------------------------------------------------
+signed int SpellBuff::_4585CA(__int64 a2)
+{
+  signed int result; // eax@3
+
+  if ( this->uExpireTime && (signed __int64)this->uExpireTime < a2 )
+  {
+    this->uExpireTime = 0i64;
+    this->uPower = 0;
+    this->uSkill = 0;
+    this->uOverlayID = 0;
+    result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+//----- (004584E0) --------------------------------------------------------
+signed int SpellBuff::Apply(unsigned __int64 uExpireTime, unsigned __int16 uSkillLevel, unsigned __int16 uPower, int a5, unsigned __int8 a6)
+{
+  SpellBuff *v6; // esi@1
+  signed int result; // eax@3
+  int v8; // eax@4
+
+  v6 = this;
+  if ( this->uExpireTime && (signed __int64)uExpireTime < (signed __int64)this->uExpireTime )
+  {
+    result = 0;
+  }
+  else
+  {
+    this->uSkill = uSkillLevel;
+    this->uPower = uPower;
+    LOWORD(v8) = this->uOverlayID;
+    this->uExpireTime = uExpireTime;
+    if ( (short)v8 )
+    {
+      v8 = (unsigned __int16)v8;
+      if ( (unsigned __int16)v8 != a5 )
+      {
+        ((OtherOverlay *)&stru_5E4C90._decor_events[20 * v8 + 105])->Reset();
+        pOtherOverlayList->field_3EC = 1;
+        v6->uOverlayID = 0;
+      }
+    }
+    v6->uOverlayID = a5;
+    v6->uCaster = a6;
+    result = 1;
+  }
+  return result;
+}
+
+//----- (0045384A) --------------------------------------------------------
+void SpellStats::Initialize()
+{
+  SpellStats *v1; // esi@1
+  const char *v2; // ebp@3
+  char *v3; // edi@3
+  signed int v4; // ebx@4
+  char *v5; // esi@4
+  char v6; // cl@5
+  int v7; // eax@5
+  size_t v8; // ebp@40
+  int v9; // eax@41
+  int v10; // eax@42
+  int v11; // eax@43
+  char *v12; // [sp+10h] [bp-10h]@3
+  signed int v13; // [sp+14h] [bp-Ch]@4
+  signed int v14; // [sp+18h] [bp-8h]@3
+  int v15; // [sp+1Ch] [bp-4h]@9
+
+  v1 = this;
+  if ( pSpellsTXT_Raw )
+    pAllocator->FreeChunk(pSpellsTXT_Raw);
+  pSpellsTXT_Raw = 0;
+  v2 = "\r";
+  pSpellsTXT_Raw = (char *)pEvents_LOD->LoadRaw("spells.txt", 0);
+  strtok(pSpellsTXT_Raw, "\r");
+  strtok(0, "\r");
+  v14 = 1;
+  v12 = (char *)&pSpellDatas[1].field_10;
+  v3 = (char *)&v1->pInfos[1].uSchool;
+  do
+  {
+    v4 = 0;
+    v5 = strtok(0, v2) + 1;
+    v13 = 0;
+    do
+    {
+      v6 = *v5;
+      v7 = 0;
+      while ( v6 != 9 && v6 )
+      {
+        ++v7;
+        v6 = v5[v7];
+      }
+      v15 = (int)&v5[v7];
+      if ( !v5[v7] )
+        v13 = 1;
+      v5[v7] = 0;
+      if ( v7 )
+      {
+        switch ( v4 )
+        {
+          case 2:
+            *((char **)v3 - 7) = RemoveQuotes(v5);
+            break;
+          case 3:
+            *v3 = 4;
+            if ( _strcmpi("fire", v5) )
+            {
+              if ( _strcmpi("air", v5) )
+              {
+                if ( _strcmpi("water", v5) )
+                {
+                  if ( _strcmpi("earth", v5) )
+                  {
+                    if ( _strcmpi("spirit", v5) )
+                    {
+                      if ( _strcmpi("mind", v5) )
+                      {
+                        if ( _strcmpi("body", v5) )
+                        {
+                          if ( _strcmpi("light", v5) )
+                          {
+                            if ( _strcmpi("dark", v5) )
+                            {
+                              if ( !_strcmpi("magic", v5) )
+                                *v3 = 5;
+                            }
+                            else
+                            {
+                              *v3 = 10;
+                            }
+                          }
+                          else
+                          {
+                            *v3 = 9;
+                          }
+                        }
+                        else
+                        {
+                          *v3 = 8;
+                        }
+                      }
+                      else
+                      {
+                        *v3 = 7;
+                      }
+                    }
+                    else
+                    {
+                      *v3 = 6;
+                    }
+                  }
+                  else
+                  {
+                    *v3 = 3;
+                  }
+                }
+                else
+                {
+                  *v3 = 2;
+                }
+              }
+              else
+              {
+                *v3 = 1;
+              }
+            }
+            else
+            {
+              *v3 = 0;
+            }
+            break;
+          case 4:
+            *((char **)v3 - 6) = RemoveQuotes(v5);
+            break;
+          case 5:
+            *((char **)v3 - 5) = RemoveQuotes(v5);
+            break;
+          case 6:
+            *((char **)v3 - 4) = RemoveQuotes(v5);
+            break;
+          case 7:
+            *((char **)v3 - 3) = RemoveQuotes(v5);
+            break;
+          case 8:
+            *((char **)v3 - 2) = RemoveQuotes(v5);
+            break;
+          case 9:
+            *((char **)v3 - 1) = RemoveQuotes(v5);
+            break;
+          case 10:
+            v4 = 0;
+            v8 = strlen(v5);
+            if ( (signed int)v8 > 0 )
+            {
+              do
+              {
+                v9 = tolower((unsigned __int8)v5[v4]) - 99;
+                if ( v9 )
+                {
+                  v10 = v9 - 2;
+                  if ( v10 )
+                  {
+                    v11 = v10 - 8;
+                    if ( v11 )
+                    {
+                      if ( v11 == 11 )
+                        *v12 |= 8u;
+                    }
+                    else
+                    {
+                      *v12 |= 1u;
+                    }
+                  }
+                  else
+                  {
+                    *v12 |= 2u;
+                  }
+                }
+                else
+                {
+                  *v12 |= 4u;
+                }
+                ++v4;
+              }
+              while ( v4 < (signed int)v8 );
+            }
+            v2 = "\r";
+            break;
+          default:
+            break;
+        }
+      }
+      else
+      {
+        v13 = 1;
+      }
+      ++v4;
+      v5 = (char *)(v15 + 1);
+    }
+    while ( v4 - 1 <= 10 && !v13 );
+    if ( !(v14 % 11) )
+      strtok(0, v2);
+    v12 += 20;
+    ++v14;
+    v3 += 36;
+  }
+  while ( (signed int)v12 <= (signed int)&pSpellDatas[90].field_12 );
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Spells.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,136 @@
+#pragma once
+
+
+
+/*  360 */
+enum SPELL_TYPE
+{
+  SPELL_FIRE_PROTECTION_FROM_FIRE = 0x3,
+  SPELL_FIRE_HASTE = 0x5,
+  SPELL_FIRE_FIRE_RING = 0x8,
+  SPELL_AIR_FEATHER_FALL = 0xD,
+  SPELL_AIR_PROTECTION_FROM_AIR = 0xE,
+  SPELL_AIR_SHIELD = 0x11,
+  SPELL_WATER_PROTECTION_FROM_WATER = 0x19,
+  SPELL_WATER_WATER_WALK = 0x1B,
+  SPELL_EARTH_PROTECTION_FROM_EARTH = 0x24,
+  SPELL_EARTH_STONESKIN = 0x26,
+  SPELL_SPIRIT_DETECT_LIFE = 0x2D,
+  SPELL_SPIRIT_BLESS = 0x2E,
+  SPELL_SPIRIT_DOOM = 0x2F,
+  SPELL_SPIRIT_PRESERVE = 0x32,
+  SPELL_SPIRIT_HEROISM = 0x33,
+  SPELL_MIND_REMOVE_FEAR = 0x38,
+  SPELL_MIND_PROTECTION_FROM_MIND = 0x3A,
+  SPELL_MIND_CURE_PARALYSIS = 0x3D,
+  SPELL_BODY_CURE_WEAKNESS = 0x43,
+  SPELL_BODY_FIRST_AID = 0x44,
+  SPELL_BODY_CURE_POISON = 0x48,
+  SPELL_BODY_HAMMERHANDS = 0x49,
+  SPELL_BODY_CURE_DISEASE = 0x4A,
+  SPELL_BODY_PROTECTION_FROM_MAGIC = 0x4B,
+  SPELL_DARK_PAIN_REFLECTION = 0x5F,
+};
+
+
+
+
+/*   68 */
+#pragma pack(push, 1)
+struct SpellBuff
+{
+  inline SpellBuff()
+  {
+    uExpireTime = 0;
+    uPower = 0;
+    uSkill = 0;
+    uOverlayID = 0;
+    uCaster = 0;
+    uFlags = 0;
+  }
+
+  signed int Apply(unsigned __int64 uExpireTime, unsigned __int16 uSkillLevel, unsigned __int16 uPower, int a5, unsigned __int8 a6);
+  void Reset();
+  signed int _4585CA(__int64 a2);
+  bool NotExpired();
+
+  unsigned __int64 uExpireTime;
+  unsigned __int16 uPower;
+  unsigned __int16 uSkill;
+  unsigned __int16 uOverlayID;
+  unsigned __int8 uCaster;
+  unsigned __int8 uFlags;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct SpellInfo
+{
+  char *pName;
+  char *pShortName;
+  char *pDescription;
+  char *pBasicSkillDesc;
+  char *pExpertSkillDesc;
+  char *pMasterSkillDesc;
+  char *pGrandmasterSkillDesc;
+  unsigned int uSchool;
+  int field_20;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct SpellStats
+{
+  void Initialize();
+
+  SpellInfo pInfos[100];
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+/*  364 */
+#pragma pack(push, 1)
+struct stru324_spell
+{
+  __int16 uItemType;
+  __int16 field_2;
+};
+#pragma pack(pop)
+
+/*  151 */
+#pragma pack(push, 1)
+struct SpellData
+{
+  unsigned __int16 uNormalLevelMana;
+  unsigned __int16 uExpertLevelMana;
+  unsigned __int16 uMasterLevelMana;
+  unsigned __int16 uMagisterLevelMana;
+  unsigned __int16 field_8;
+  __int16 field_A;
+  __int16 field_C;
+  __int16 field_E;
+  __int16 field_10;
+  char field_12;
+  char field_13;
+  __int16 field_14;
+};
+#pragma pack(pop)
+
+
+
+
+extern struct SpellStats *pSpellStats;
+
+
+extern stru324_spell stru_4E3ACC[];
+extern SpellData pSpellDatas[95];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sprites.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,733 @@
+#include <string.h>
+
+#include "Allocator.h"
+#include "Sprites.h"
+#include "PaletteManager.h"
+#include "LOD.h"
+#include "FrameTableInc.h"
+
+#include "mm7_data.h"
+
+
+
+
+extern int (__cdecl *sprintfex)(char *a1, const char *a2, ...);
+
+struct SpriteFrameTable *pSpriteFrameTable;
+
+
+
+
+//----- (0044D4D8) --------------------------------------------------------
+void SpriteFrameTable::ReleaseSFrames()
+{
+  SpriteFrameTable *v1; // esi@1
+
+  v1 = this;
+  if ( this->pSpriteSFrames )
+  {
+    pAllocator->FreeChunk(this->pSpriteSFrames);
+    v1->pSpriteSFrames = 0;
+  }
+  v1->uNumSpriteFrames = 0;
+}
+
+//----- (0044D4F6) --------------------------------------------------------
+void SpriteFrameTable::ResetSomeSpriteFlags()
+{
+  int v1; // esi@1
+  signed int i; // edx@1
+  char *v3; // eax@2
+
+  v1 = 0;
+  for ( i = 0; i < (signed int)this->uNumSpriteFrames; ++i )
+  {
+    v3 = (char *)&this->pSpriteSFrames[v1].uFlags;
+    ++v1;
+    *v3 &= 0x7Fu;
+  }
+}
+
+//----- (0044D513) --------------------------------------------------------
+void SpriteFrameTable::InitializeSprite(unsigned int uSpriteID)
+{
+  //SpriteFrameTable *v2; // esi@1
+  unsigned int v3; // ebx@3
+  //char *v4; // edx@3
+  //int v5; // eax@3
+  SpriteFrame *v6; // ecx@5
+  int v7; // eax@5
+  __int16 v8; // ax@6
+  //signed int v9; // edx@6
+  //int v10; // ecx@6
+  signed int v11; // edi@10
+  __int16 v12; // ax@16
+  int v13; // ecx@16
+  size_t v14; // eax@19
+  signed int v15; // edi@19
+  __int16 v16; // ax@27
+  int v17; // ecx@27
+  signed int v18; // edi@29
+  SpriteFrame *v19; // eax@30
+  __int16 v20; // ax@45
+  int v21; // ecx@45
+  const char *v22; // [sp-8h] [bp-50h]@12
+  const char *v23; // [sp-8h] [bp-50h]@21
+  const char *v24; // [sp-8h] [bp-50h]@37
+  const char *v25; // [sp-4h] [bp-4Ch]@12
+  char *v26; // [sp-4h] [bp-4Ch]@21
+  const char *v27; // [sp-4h] [bp-4Ch]@37
+  char v28[3]; // [sp+9h] [bp-3Fh]@19
+  char Str; // [sp+Ch] [bp-3Ch]@19
+  char Size[20]; // [sp+2Ch] [bp-1Ch]@15
+  char Source[4]; // [sp+40h] [bp-8h]@19
+  int v32; // [sp+44h] [bp-4h]@19
+  unsigned int uSpriteIDa; // [sp+50h] [bp+8h]@4
+
+  //v2 = this;
+  if ( (signed int)uSpriteID <= (signed int)this->uNumSpriteFrames )
+  {
+    if ( (uSpriteID & 0x80000000u) == 0 )
+    {
+      v3 = uSpriteID;
+
+      auto uFlags = pSpriteSFrames[uSpriteID].uFlags;
+      if (uFlags & 0x7F)
+      {
+        pSpriteSFrames[uSpriteID].uFlags |= 0x80;
+
+        uSpriteIDa = 30 * uSpriteID + 12;
+        while ( 1 )
+        {
+          pSpriteSFrames[v3].uPaletteIndex = pPaletteManager->LoadPalette(pSpriteSFrames[uSpriteID].uPaletteID);
+          v6 = &pSpriteSFrames[uSpriteID];
+          v7 = v6->uFlags;
+          if ( v7 & 0x10 )
+          {
+            v8 = pSprites_LOD->LoadSprite(v6->pTextureName, v6->uPaletteID);
+
+            for (uint i = 0; i < 8; ++i)
+              pSpriteSFrames[v3].pHwSpriteIDs[i] = v8;
+            goto LABEL_46;
+          }
+          if ( v7 & 0x10000 )
+          {
+            v11 = 0;
+            do
+            {
+              switch ( v11 )
+              {
+                case 3:
+                case 4:
+                case 5:
+                  v25 = pSpriteSFrames[v3].pTextureName;
+                  v22 = "%s4";
+                  goto LABEL_15;
+                case 2:
+                case 6:
+                  v25 = pSpriteSFrames[v3].pTextureName;
+                  v22 = "%s2";
+                  goto LABEL_15;
+                case 0:
+                case 1:
+                case 7:
+                  v25 = pSpriteSFrames[v3].pTextureName;
+                  v22 = "%s0";
+LABEL_15:
+                  sprintf(Size, v22, v25);
+                  break;
+                default:
+                  break;
+              }
+              v12 = pSprites_LOD->LoadSprite(Size, pSpriteSFrames[v3].uPaletteID);
+              v13 = v11++ + uSpriteIDa;
+              *(short *)&pSpriteSFrames->pIconName[2 * v13] = v12;
+            }
+            while ( v11 < 8 );
+            goto LABEL_46;
+          }
+          if ( !(v7 & 0x40) )
+            break;
+          strcpy(Source, "stA");
+          v32 = 0;
+          strcpy(&Str, v6->pTextureName);
+          v14 = strlen(&Str);
+          strcpy(&v28[v14], Source);
+          v15 = 0;
+          do
+          {
+            switch ( v15 )
+            {
+              case 0:
+                v26 = pSpriteSFrames[v3].pTextureName;
+                v23 = "%s0";
+                goto LABEL_26;
+              case 4:
+                v26 = &Str;
+                v23 = "%s4";
+                goto LABEL_26;
+              case 3:
+              case 5:
+                v26 = &Str;
+                v23 = "%s3";
+                goto LABEL_26;
+              case 2:
+              case 6:
+                v26 = pSpriteSFrames[v3].pTextureName;
+                v23 = "%s2";
+                goto LABEL_26;
+              case 1:
+              case 7:
+                v26 = pSpriteSFrames[v3].pTextureName;
+                v23 = "%s1";
+LABEL_26:
+                sprintf(Size, v23, v26);
+                break;
+              default:
+                break;
+            }
+            v16 = pSprites_LOD->LoadSprite(Size, pSpriteSFrames[v3].uPaletteID);
+            v17 = v15++ + uSpriteIDa;
+            *(short *)&pSpriteSFrames->pIconName[2 * v17] = v16;
+          }
+          while ( v15 < 8 );
+LABEL_46:
+          if ( !(pSpriteSFrames[v3].uFlags & 1) )
+            return;
+          uSpriteIDa += 30;
+          ++v3;
+        }
+        v18 = 0;
+        while ( 1 )
+        {
+          v19 = &pSpriteSFrames[v3];
+          if ( !((256 << v18) & v19->uFlags) )
+          {
+            sprintf(Size, "%s%i", v19->pTextureName, v18);
+            goto LABEL_45;
+          }
+          if ( v18 == 1 )
+          {
+            v27 = v19->pTextureName;
+            v24 = "%s7";
+            goto LABEL_42;
+          }
+          if ( v18 == 2 )
+          {
+            v27 = v19->pTextureName;
+            v24 = "%s6";
+            goto LABEL_42;
+          }
+          if ( v18 == 3 )
+          {
+            v27 = v19->pTextureName;
+            v24 = "%s5";
+            goto LABEL_42;
+          }
+          if ( v18 == 5 )
+          {
+            v27 = v19->pTextureName;
+            v24 = "%s3";
+            goto LABEL_42;
+          }
+          if ( v18 == 6 )
+            break;
+          if ( v18 == 7 )
+          {
+            v27 = v19->pTextureName;
+            v24 = "%s1";
+LABEL_42:
+            sprintf(Size, v24, v27);
+          }
+LABEL_45:
+          v20 = pSprites_LOD->LoadSprite(Size, pSpriteSFrames[v3].uPaletteID);
+          v21 = v18++ + uSpriteIDa;
+          *(short *)&pSpriteSFrames->pIconName[2 * v21] = v20;
+          if ( v18 >= 8 )
+            goto LABEL_46;
+        }
+        v27 = v19->pTextureName;
+        v24 = "%s2";
+        goto LABEL_42;
+      }
+    }
+  }
+}
+
+//----- (0044D813) --------------------------------------------------------
+unsigned int SpriteFrameTable::FastFindSprite(char *pSpriteName)
+{
+  SpriteFrameTable *v2; // esi@1
+  int v3; // eax@1
+  unsigned int result; // eax@2
+
+  v2 = this;
+  BinarySearch(0, this->uNumEFrames, pSpriteName);
+  v3 = v2->field_8;
+  if ( v3 < 0 )
+    result = 0;
+  else
+    result = v2->pSpriteEFrames[v3];
+  return result;
+}
+
+//----- (0044D83A) --------------------------------------------------------
+void SpriteFrameTable::BinarySearch(int a2, int a3, const char *pSpriteName)
+{
+  int v4; // ebx@1
+  SpriteFrameTable *v5; // edi@1
+  int v6; // esi@2
+  int v7; // eax@2
+  int a2a; // [sp+14h] [bp+8h]@2
+
+  v4 = a2;
+  v5 = this;
+  while ( 1 )
+  {
+    a2a = a3 - v4;
+    v6 = (a3 - v4) / 2 + v4;
+    v7 = _strcmpi(pSpriteName, v5->pSpritePFrames[v6]->pIconName);
+    if ( !v7 )
+      v5->field_8 = v6;
+    if ( v4 == a3 )
+      break;
+    if ( v7 >= 0 )
+    {
+      if ( a2a <= 4 )
+      {
+        while ( v4 < a3 )
+        {
+          if ( !_strcmpi(pSpriteName, v5->pSpritePFrames[v4]->pIconName) )
+          {
+LABEL_19:
+            v5->field_8 = v4;
+            return;
+          }
+          ++v4;
+        }
+        break;
+      }
+      v4 += (a3 - v4) / 2;
+    }
+    else
+    {
+      if ( a2a <= 4 )
+      {
+        while ( v4 < a3 )
+        {
+          if ( !_strcmpi(pSpriteName, v5->pSpritePFrames[v4]->pIconName) )
+            goto LABEL_19;
+          ++v4;
+        }
+        break;
+      }
+      a3 = (a3 - v4) / 2 + v4;
+    }
+  }
+  v5->field_8 = -1;
+}
+
+//----- (0044D8D0) --------------------------------------------------------
+SpriteFrame *SpriteFrameTable::GetFrame(unsigned int uSpriteID, unsigned int uFrameID)
+{
+  SpriteFrame *v3; // edi@1
+  SpriteFrame *v4; // ecx@1
+  __int16 v5; // dx@2
+  int v6; // edx@3
+  unsigned int v7; // eax@3
+  char *i; // ecx@3
+  int v9; // esi@5
+  SpriteFrame *result; // eax@6
+
+  v3 = this->pSpriteSFrames;
+  v4 = &v3[uSpriteID];
+  if ( v4->uFlags & 1 && (v5 = v4->uAnimLength) != 0 )
+  {
+    v6 = ((signed int)uFrameID >> 3) % v5;
+    v7 = uSpriteID;
+    for ( i = (char *)&v4->uAnimTime; ; i += 60 )
+    {
+      v9 = *(short *)i;
+      if ( v6 <= v9 )
+        break;
+      v6 -= v9;
+      ++v7;
+    }
+    result = &v3[v7];
+  }
+  else
+  {
+    result = &v3[uSpriteID];
+  }
+  return result;
+}
+
+//----- (0044D91F) --------------------------------------------------------
+SpriteFrame *SpriteFrameTable::GetFrameBy_x(unsigned int uSpriteID, signed int a3)
+{
+  SpriteFrame *v3; // edi@1
+  SpriteFrame *v4; // esi@1
+  __int16 v5; // ax@2
+  int v6; // ecx@3
+  int v7; // edx@3
+  unsigned int v8; // eax@3
+  int v9; // ecx@3
+  char *i; // edx@3
+  int v11; // esi@5
+  SpriteFrame *result; // eax@6
+
+  v3 = this->pSpriteSFrames;
+  v4 = &v3[uSpriteID];
+  if ( v4->uFlags & 1 && (v5 = v4->uAnimLength) != 0 )
+  {
+    v6 = v5;
+    v7 = a3 % v5;
+    v8 = uSpriteID;
+    v9 = v6 - v7;
+    for ( i = (char *)&v4->uAnimTime; ; i += 60 )
+    {
+      v11 = *(short *)i;
+      if ( v9 <= v11 )
+        break;
+      v9 -= v11;
+      ++v8;
+    }
+    result = &v3[v8];
+  }
+  else
+  {
+    result = &v3[uSpriteID];
+  }
+  return result;
+}
+
+//----- (0044D96D) --------------------------------------------------------
+void SpriteFrameTable::ToFile()
+{
+  SpriteFrameTable *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  v1 = this;
+  v2 = fopen("data\\dsft.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dsft.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(&v1->uNumEFrames, 4u, 1u, v3);
+  fwrite(v1->pSpriteSFrames, 0x3Cu, v1->uNumSpriteFrames, v3);
+  fwrite(v1->pSpriteEFrames, 2u, v1->uNumEFrames, v3);
+  fclose(v3);
+}
+
+//----- (0044D9D7) --------------------------------------------------------
+void SpriteFrameTable::FromFile(void *pSerialized)
+{
+  //v2 = this;
+  uNumSpriteFrames = *(int *)pSerialized;
+  uNumEFrames = *((int *)pSerialized + 1);
+  //memcpy(this, pSerialized, 4u);
+  //memcpy(&v2->field_4, (char *)pSerialized + 4, 4u);
+  pSpriteSFrames = (SpriteFrame *)pAllocator->AllocNamedChunk(pSpriteSFrames, 60 * uNumSpriteFrames, "S Frames");
+  pSpriteEFrames = (__int16 *)pAllocator->AllocNamedChunk(pSpriteEFrames, 2 * uNumSpriteFrames, "E Frames");
+  //v3 = pAllocator->AllocNamedChunk(pSpritePFrames, 4 * uNumSpriteFrames, "P Frames");
+  //v4 = v2->uNumSpriteFrames;
+  pSpritePFrames = (SpriteFrame **)pAllocator->AllocNamedChunk(pSpritePFrames, 4 * uNumSpriteFrames, "P Frames");
+  auto uSpriteFramesSize = 60 * uNumSpriteFrames;
+  memcpy(pSpriteSFrames, (char *)pSerialized + 8, uSpriteFramesSize);
+  memcpy(pSpriteEFrames, (char *)pSerialized + uSpriteFramesSize + 8, 2 * uNumEFrames);
+  for (uint i = 0; i < uNumSpriteFrames; ++i)
+    pSpritePFrames[i] = &pSpriteSFrames[pSpriteEFrames[i]];
+}
+
+//----- (0044DA92) --------------------------------------------------------
+bool SpriteFrameTable::FromFileTxt(const char *Args)
+{
+  SpriteFrameTable *v2; // ebx@1
+  FILE *v3; // eax@1
+  unsigned int v4; // esi@3
+  signed int result; // eax@10
+  FILE *v6; // ST18_4@11
+  char *i; // eax@11
+  const char *v8; // ST20_4@14
+  __int16 v9; // ax@14
+  const char *v10; // ST0C_4@14
+  double v11; // st7@14
+  int v12; // eax@14
+  const char *v13; // ST04_4@14
+  __int16 v14; // ax@14
+  const char *v15; // ST00_4@14
+  int v16; // eax@14
+  int v17; // eax@17
+  int v18; // eax@23
+  int v19; // eax@24
+  int v20; // eax@25
+  int v21; // eax@28
+  int v22; // eax@29
+  int j; // edi@30
+  const char *v24; // esi@31
+  int v25; // eax@32
+  int v26; // edx@53
+  int v27; // ecx@54
+  int v28; // eax@55
+  signed int k; // edx@58
+  SpriteFrame *v30; // ecx@59
+  int v31; // esi@59
+  int l; // eax@60
+  signed int v33; // eax@65
+  int v34; // edi@66
+  int v35; // esi@66
+  SpriteFrame **v36; // eax@69
+  int v37; // ecx@69
+  SpriteFrame *v38; // edx@69
+  __int16 *v39; // eax@69
+  int v40; // ecx@69
+  char Buf[500]; // [sp+Ch] [bp-2F0h]@3
+  FrameTableTxtLine v42; // [sp+200h] [bp-FCh]@4
+  FrameTableTxtLine v43; // [sp+27Ch] [bp-80h]@4
+  FILE *File; // [sp+2F8h] [bp-4h]@1
+  unsigned int Argsa; // [sp+304h] [bp+8h]@3
+  int Argsb; // [sp+304h] [bp+8h]@59
+  FILE *Argsc; // [sp+304h] [bp+8h]@67
+
+  v2 = this;
+  ReleaseSFrames();
+  v3 = fopen(Args, "r");
+  File = v3;
+  if ( !v3 )
+    Abortf("CSpriteFrameTable::load - Unable to open file: %s.", Args);
+  v4 = 0;
+  Argsa = 0;
+  if ( fgets(Buf, 490, v3) )
+  {
+    do
+    {
+      *strchr(Buf, '\n') = 0;
+      memcpy(&v43, frame_table_txt_parser(Buf, &v42), sizeof(v43));
+      if ( v43.field_0 && *v43.pProperties[0] != '/' )
+        ++Argsa;
+    }
+    while ( fgets(Buf, 490, File) );
+    v4 = Argsa;
+  }
+  v2->uNumSpriteFrames = v4;
+  v2->pSpriteSFrames = (SpriteFrame *)pAllocator->AllocNamedChunk(v2->pSpriteSFrames, 60 * v4, "S Frames");
+  v2->pSpriteEFrames = (__int16 *)pAllocator->AllocNamedChunk(
+                                    v2->pSpriteEFrames,
+                                    2 * v2->uNumSpriteFrames,
+                                    "E Frames");
+  v2->pSpritePFrames = (SpriteFrame **)pAllocator->AllocNamedChunk(
+                                         v2->pSpritePFrames,
+                                         4 * v2->uNumSpriteFrames,
+                                         "P Frames");
+  if ( v2->pSpriteSFrames )
+  {
+    v6 = File;
+    v2->uNumSpriteFrames = 0;
+    fseek(v6, 0, 0);
+    for ( i = fgets(Buf, 490, File); i; i = fgets(Buf, 490, File) )
+    {
+      *strchr(Buf, 10) = 0;
+      memcpy(&v43, frame_table_txt_parser(Buf, &v42), sizeof(v43));
+      if ( v43.field_0 && *v43.pProperties[0] != '/' )
+      {
+        v8 = v43.pProperties[0];
+        v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags = 0;
+        v2->pSpriteSFrames[v2->uNumSpriteFrames].uPaletteIndex = 0;
+        strcpy(v2->pSpriteSFrames[v2->uNumSpriteFrames].pIconName, v8);
+        strcpy(v2->pSpriteSFrames[v2->uNumSpriteFrames].pTextureName, v43.pProperties[1]);
+        v9 = atoi(v43.pProperties[3]);
+        v10 = v43.pProperties[4];
+        v2->pSpriteSFrames[v2->uNumSpriteFrames].uPaletteID = v9;
+        v11 = atof(v10) * 65536.0;
+        v12 = abs((signed __int64)v11);
+        v13 = v43.pProperties[5];
+        v2->pSpriteSFrames[v2->uNumSpriteFrames].scale = v12;
+        v14 = atoi(v13);
+        v15 = v43.pProperties[6];
+        v2->pSpriteSFrames[v2->uNumSpriteFrames].uGlowRadius = v14;
+        v2->pSpriteSFrames[v2->uNumSpriteFrames].uAnimTime = atoi(v15);
+        v16 = (int)&v2->pSpriteSFrames[v2->uNumSpriteFrames];
+        if ( *(short *)(v16 + 48) )
+          *(int *)(v16 + 44) |= 2u;
+        if ( !_strcmpi(v43.pProperties[2], "new") )
+        {
+          v17 = (int)&v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags;
+          *(int *)v17 |= 4u;
+          v2->pSpritePFrames[v2->uNumEFrames] = &v2->pSpriteSFrames[v2->uNumSpriteFrames];
+          v2->pSpriteEFrames[v2->uNumEFrames++] = LOWORD(v2->uNumSpriteFrames);
+        }
+        if ( !_strcmpi(v43.pProperties[10], "1") )
+          BYTE2(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 4u;
+        if ( !_strcmpi(v43.pProperties[11], "1") )
+          BYTE2(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 2u;
+        if ( !_strcmpi(v43.pProperties[12], "1") )
+        {
+          v18 = (int)&v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags;
+          *(int *)v18 |= 0x20u;
+        }
+        v19 = atoi(v43.pProperties[7]) - 1;
+        if ( v19 )
+        {
+          v20 = v19 - 2;
+          if ( v20 )
+          {
+            if ( v20 == 2 )
+              BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 0xE0u;
+          }
+          else
+          {
+            v21 = (int)&v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags;
+            *(int *)v21 |= 0x1E000u;
+          }
+        }
+        else
+        {
+          v22 = (int)&v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags;
+          *(int *)v22 |= 0x10u;
+        }
+        for ( j = 13; j < v43.field_0; ++j )
+        {
+          v24 = v43.pProperties[j];
+          if ( _strcmpi(v43.pProperties[j], "Luminous") )
+          {
+            if ( _strcmpi(v24, "Mirror0") )
+            {
+              if ( _strcmpi(v24, "Mirror1") )
+              {
+                if ( _strcmpi(v24, "Mirror2") )
+                {
+                  if ( _strcmpi(v24, "Mirror3") )
+                  {
+                    if ( _strcmpi(v24, "Mirror4") )
+                    {
+                      if ( _strcmpi(v24, "Mirror5") )
+                      {
+                        if ( _strcmpi(v24, "Mirror6") )
+                        {
+                          if ( !_strcmpi(v24, "Mirror7") )
+                            BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 0x80u;
+                        }
+                        else
+                        {
+                          BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 0x40u;
+                        }
+                      }
+                      else
+                      {
+                        BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 0x20u;
+                      }
+                    }
+                    else
+                    {
+                      BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 0x10u;
+                    }
+                  }
+                  else
+                  {
+                    BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 8u;
+                  }
+                }
+                else
+                {
+                  BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 4u;
+                }
+              }
+              else
+              {
+                BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 2u;
+              }
+            }
+            else
+            {
+              BYTE1(v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags) |= 1u;
+            }
+          }
+          else
+          {
+            v25 = (int)&v2->pSpriteSFrames[v2->uNumSpriteFrames].uFlags;
+            *(int *)v25 |= 2u;
+          }
+        }
+        ++v2->uNumSpriteFrames;
+      }
+    }
+    fclose(File);
+    v26 = 0;
+    if ( (signed int)(v2->uNumSpriteFrames - 1) > 0 )
+    {
+      v27 = 0;
+      do
+      {
+        v28 = (int)&v2->pSpriteSFrames[v27];
+        if ( !(*(char *)(v28 + 104) & 4) )
+          *(int *)(v28 + 44) |= 1u;
+        ++v26;
+        ++v27;
+      }
+      while ( v26 < (signed int)(v2->uNumSpriteFrames - 1) );
+    }
+    for ( k = 0; k < (signed int)v2->uNumSpriteFrames; *(short *)(Argsb + 56) = v31 )
+    {
+      v30 = v2->pSpriteSFrames;
+      Argsb = (int)&v30[k];
+      v31 = *(short *)(Argsb + 54);
+      if ( *(char *)(Argsb + 44) & 1 )
+      {
+        ++k;
+        for ( l = (int)&v30[k]; *(char *)(l + 44) & 1; l += 60 )
+        {
+          v31 += *(short *)(l + 54);
+          ++k;
+        }
+        LOWORD(v31) = v30[k].uAnimTime + v31;
+      }
+      ++k;
+    }
+    v33 = v2->uNumEFrames;
+    if ( v33 > 0 )
+    {
+      v34 = 0;
+      v35 = 0;
+      File = (FILE *)1;
+      do
+      {
+        Argsc = File;
+        if ( (signed int)File < v33 )
+        {
+          do
+          {
+            if ( _strcmpi(v2->pSpritePFrames[(int)Argsc]->pIconName, v2->pSpritePFrames[v35]->pIconName) < 0 )
+            {
+              v36 = v2->pSpritePFrames;
+              v37 = (int)&v36[(int)Argsc];
+              v38 = *(SpriteFrame **)v37;
+              *(int *)v37 = (int)v36[v35];
+              v2->pSpritePFrames[v35] = v38;
+              v39 = v2->pSpriteEFrames;
+              v40 = (int)&v39[(int)Argsc];
+              LOWORD(v38) = *(short *)v40;
+              *(short *)v40 = v39[v34];
+              v2->pSpriteEFrames[v34] = (signed __int16)v38;
+            }
+            Argsc = (FILE *)((char *)Argsc + 1);
+          }
+          while ( (signed int)Argsc < v2->uNumEFrames );
+        }
+        File = (FILE *)((char *)File + 1);
+        v33 = v2->uNumEFrames;
+        ++v35;
+        ++v34;
+      }
+      while ( (signed int)((char *)File - 1) < v33 );
+    }
+    result = 1;
+  }
+  else
+  {
+    MessageBoxW(nullptr, L"CSpriteFrameTable::load - Out of Memory!", nullptr, 0);
+    fclose(File);
+    result = 0;
+  }
+  return result;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sprites.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,79 @@
+#pragma once
+
+
+/*   18 */
+#pragma pack(push, 1)
+struct Sprite
+{
+  void Release();
+
+  const char *pName;
+  int uPaletteID;
+  struct IDirectDrawSurface4 *pTextureSurface;
+  struct IDirect3DTexture2 *pTexture;
+  int uAreaX;
+  int uAreaY;
+  int uBufferWidth;
+  int uBufferHeight;
+  int uAreaWidth;
+  int uAreaHeight;
+};
+#pragma pack(pop)
+
+
+/*   42 */
+#pragma pack(push, 1)
+struct SpriteFrame
+{
+  char pIconName[12];
+  char pTextureName[12];
+  __int16 pHwSpriteIDs[8];
+  int scale;
+  int uFlags;
+  __int16 uGlowRadius;
+  __int16 uPaletteID;
+  __int16 uPaletteIndex;
+  __int16 uAnimTime;
+  __int16 uAnimLength;
+  __int16 _pad;
+};
+#pragma pack(pop)
+
+/*   43 */
+#pragma pack(push, 1)
+struct SpriteFrameTable
+{
+  //----- (0044D4BA) --------------------------------------------------------
+  inline SpriteFrameTable()
+  {
+    uNumSpriteFrames = 0;
+    pSpriteSFrames = nullptr;
+    pSpritePFrames = nullptr;
+    pSpriteEFrames = nullptr;
+  }
+  void ToFile();
+  void FromFile(void *pSerialized);
+  bool FromFileTxt(const char *Args);
+  void ReleaseSFrames();
+  void ResetSomeSpriteFlags();
+  void InitializeSprite(unsigned int uSpriteID);
+  unsigned int FastFindSprite(char *pSpriteName);
+  void BinarySearch(int a2, int a3, const char *pSpriteName);
+  SpriteFrame *GetFrame(unsigned int uSpriteID, unsigned int uFrameID);
+  SpriteFrame *GetFrameBy_x(unsigned int uSpriteID, signed int a3);
+
+  unsigned int uNumSpriteFrames;
+  unsigned int uNumEFrames;//field_4;
+  int field_8;
+  struct SpriteFrame *pSpriteSFrames;
+  struct SpriteFrame **pSpritePFrames;
+  __int16 *pSpriteEFrames;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+extern struct SpriteFrameTable *pSpriteFrameTable;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StorylineTextTable.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,15 @@
+#pragma once
+
+
+
+
+/*  173 */
+#pragma pack(push, 1)
+struct StorylineText
+{
+  void Initialize();
+
+  int field_0;
+  int field_4[87];
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Texture.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1667 @@
+#include <stdlib.h>
+
+#include "Texture.h"
+#include "FrameTableInc.h"
+#include "Allocator.h"
+#include "LOD.h"
+#include "PaletteManager.h"
+#include "Render.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+
+
+
+
+struct TextureFrameTable *pTextureFrameTable;
+
+
+
+
+
+Texture *pTexture_LloydBeacons[2];
+Texture *pTexture_50635C;
+Texture *pTexture_506368;
+Texture *pTexture_50636C;
+Texture *pTexture_506370;
+Texture *pTexture_506374;
+Texture *pTexture_506378;
+Texture *pTexture_50637C;
+Texture *pTexture_506380;
+Texture *pTexture_506384;
+Texture *pTexture_506388;
+Texture *pTexture_50638C;
+Texture *pTexture_506390;
+Texture *pTexture_506394;
+Texture *pTex_tab_an_7a__zoot_off;
+Texture *pTex_tab_an_6a__zoom_off;
+Texture *pTex_tab_an_7b__zoot_on;
+Texture *pTex_tab_an_6b__zoom_on;
+Texture *pTexture_TownPortalHarmn;
+Texture *pTexture_TownPortalElf;
+Texture *pTexture_TownPortalWarlock;
+Texture *pTexture_TownPortalIsland;
+Texture *pTexture_TownPortalHeaven;
+Texture *pTexture_TownPortalHell;
+Texture *dword_5063D8[777];
+Texture *dword_506404[777];
+Texture *dword_506434[777];
+Texture *pTexture_50643C; // idb
+Texture *ptr_506440;
+Texture *pTexture_506444;
+Texture *pTexture_506448; // idb
+Texture *pTextures_tabs[8][2];
+Texture *pTexture_mapbordr; // idb
+Texture *pTexture_pagemask; // idb
+Texture *pTextures_5064A0[14];
+Texture *pTexture_AutonotesBook;
+Texture *pTexture_CurrentBook;
+Texture *pTex_moon_new;
+Texture *pTex_moon_4;
+Texture *pTex_moon_2;
+Texture *pTex_moon_2_2;
+Texture *pTex_moon_ful;
+
+
+
+RGBTexture stru_506E40; // weak
+RGBTexture pTexture_PCX;
+
+
+int uTextureID_RestUI_restb4; // weak
+int uTextureID_RestUI_restexit; // weak
+int uTextureID_RestUI_restb3; // weak
+int uTextureID_RestUI_restb1; // weak
+int uTextureID_RestUI_restb2; // weak
+int uTextureID_RestUI_restmain; // weak
+unsigned int uTextureID_Leather;
+int uTextureID_ar_dn_dn; // weak
+int uTextureID_ar_dn_up; // weak
+int uTextureID_ar_up_dn; // weak
+int uTextureID_ar_up_up; // weak
+
+
+int uTextureID_507698; // weak
+int uTextureID_50769C; // weak
+int uTextureID_5076A0; // weak
+int uTextureID_5076A4; // weak
+int uTextureID_5076A8; // weak
+int uTextureID_5076AC; // weak
+int uTextureID_5076B0; // weak
+int uTextureID_5076B4; // weak
+int uTextureID_Parchment; // weak
+unsigned int uTextureID_mhp_yel;
+unsigned int uTextureID_mhp_red;
+unsigned int uTextureID_mhp_grn;
+unsigned int uTextureID_mhp_capr;
+unsigned int uTextureID_mhp_capl;
+unsigned int uTextureID_mhp_bd;
+unsigned int uTextureID_BUTTDESC2;
+unsigned int uTextureID_x_x_u;
+unsigned int uTextureID_BUTTMAKE2;
+unsigned int uTextureID_BUTTMAKE;
+unsigned int uTextureID_BUTTYES2;
+unsigned int uTextureID_x_ok_u;
+Texture *pPlayerPortraits[22];
+Texture *pTexture_IC_KNIGHT[8];
+Texture *pTexture_MAKESKY;
+Texture *pTexture_MAKETOP;
+Texture *pTextures_arrowr[20];
+Texture *pTextures_arrowl[20];
+Texture *pTexture_presleft;
+Texture *pTexture_pressrigh;
+Texture *pTexture_buttminu;
+Texture *pTexture_buttplus;
+unsigned int uTextureID_50792C; // weak
+unsigned int uTextureID_507930; // weak
+unsigned int uTextureID_507934; // weak
+unsigned int uTextureID_507938; // weak
+unsigned int uTextureID_50793C; // weak
+unsigned int uTextureID_507940; // weak
+unsigned int uTextureID_507944; // weak
+
+
+unsigned int uTextureID_ib_td5_A;
+unsigned int uTextureID_ib_td2_A; // weak
+unsigned int uTextureID_ib_td1_A;
+int uTextureID_507958; // weak
+int uTextureID_50795C; // weak
+
+
+unsigned int uTextureID_507970;
+
+
+unsigned int uTextureID_507978;
+unsigned int uTextureID_50797C;
+unsigned int uTextureID_507980;
+unsigned int uTextureID_507984;
+unsigned int uTextureID_FONTPAL;
+unsigned int uTextureID_50798C;
+unsigned int uTextureID_507990;
+unsigned int pTextureIDs_pMapDirs[8];
+
+
+unsigned int uTextureID_BarRed;
+unsigned int uTextureID_BarYellow;
+unsigned int uTextureID_BarGreen;
+unsigned int uTextureID_BarBlue;
+
+
+unsigned int uTextureID_right_panel; // weak
+
+
+RGBTexture *pTexture_StatusBar = new RGBTexture;
+RGBTexture *pTexture_LeftFrame = new RGBTexture;
+RGBTexture *pTexture_TopFrame = new RGBTexture;
+RGBTexture *pTexture_BottomFrame = new RGBTexture;
+RGBTexture *pTexture_RightFrame = new RGBTexture;
+
+
+unsigned int uTextureID_507B04; // weak
+
+
+Texture *pTexture_Leather;
+Texture *pTexture_RestUI_CurrentSkyFrame; // idb
+Texture *pTexture_RestUI_CurrentHourglassFrame; // idb
+
+
+unsigned int uTextureID_507BF4; // weak
+unsigned int uTextureID_507BF8; // weak
+unsigned int uTextureID_507BFC; // weak
+unsigned int uTextureID_507C00; // weak
+unsigned int uTextureID_507C04; // weak
+
+
+unsigned int uTextureID_507C10; // weak
+unsigned int uTextureID_507C14; // weak
+unsigned int uTextureID_507C18; // weak
+unsigned int uTextureID_507C1C; // weak
+unsigned int uTextureID_507C20; // weak
+unsigned int uTextureID_507C24; // weak
+unsigned int pTextureIDs_GammaPositions[10];
+unsigned int uTextureID_507C50; // weak
+unsigned int uTextureID_507C54; // weak
+unsigned int uTextureID_507C58; // weak
+unsigned int uTextureID_507C60; // weak
+unsigned int uTextureID_507C64[777]; // weak
+unsigned int uTextureID_507C68; // weak
+unsigned int uTextureID_507C6C; // weak
+unsigned int uTextureID_507C70; // weak
+unsigned int uTextureID_507C74; // weak
+unsigned int uTextureID_507C84; // weak
+unsigned int pTextureIDs_SoundLevels[10];
+unsigned int uTextureID_507CB0; // weak
+unsigned int uTextureID_507CB4; // weak
+unsigned int uTextureID_507CB8; // weak
+
+
+unsigned int uTextureID_5118C8; // weak
+unsigned int uTextureID_MAGNIF_B; // weak
+unsigned int uTextureID_BACKDOLL; // weak
+unsigned int uTextureID_BACKHAND; // weak
+
+
+Texture pTex_F7CE30;
+
+
+RGBTexture stru_5773C4; // idb
+
+
+
+
+
+
+
+
+
+
+
+/*  245 */
+#pragma pack(push, 1)
+struct PCXHeader1
+{
+  char magic;
+  char version;
+  char encoding;
+  char bpp;
+  __int16 left;
+  __int16 up;
+  __int16 right;
+  __int16 bottom;
+  __int16 hres;
+  __int16 vres;
+};
+#pragma pack(pop)
+
+/*  246 */
+#pragma pack(push, 1)
+struct PCXHeader2
+{
+  char reserved;
+  char planes;
+  __int16 pitch;
+  __int16 palette_info;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+//----- (0044E054) --------------------------------------------------------
+void TextureFrameTable::ToFile()
+{
+  TextureFrameTable *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  v1 = this;
+  v2 = fopen("data\\dtft.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dtft.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pTextures, 0x14u, v1->uNumTextures, v3);
+  fclose(v3);
+}
+
+//----- (0044E0A0) --------------------------------------------------------
+void TextureFrameTable::FromFile(void *pSerialized)
+{
+  uNumTextures = *(int *)pSerialized;
+  pTextures = (TextureFrame *)pAllocator->AllocNamedChunk(pTextures, 20 * uNumTextures, "Txt Frames");
+  memcpy(pTextures, (char *)pSerialized + 4, 20 * uNumTextures);
+}
+
+//----- (0044E0ED) --------------------------------------------------------
+unsigned int TextureFrameTable::LoadAnimationSequenceAndPalettes(unsigned int uIconID)
+{
+  unsigned int result; // eax@1
+  TextureFrameTable *v3; // ebx@1
+  unsigned int i; // edi@3
+
+  result = uIconID;
+  v3 = this;
+  if ( (signed int)uIconID <= (signed int)this->uNumTextures && (uIconID & 0x80000000u) == 0 )
+  {
+    for ( i = uIconID; ; ++i )
+    {
+      v3->pTextures[i].uTextureID = pBitmaps_LOD->LoadTexture(v3->pTextures[i].pTextureName, TEXTURE_DEFAULT);
+      auto pTex = (v3->pTextures[i].uTextureID != -1 ? &pBitmaps_LOD->pTextures[v3->pTextures[i].uTextureID] : 0);
+      if (pTex)
+        pTex->palette_id2 = pPaletteManager->LoadPalette(pTex->palette_id1);
+      result = (unsigned int)v3->pTextures;
+      if ( !(*(char *)(result + i * 20 + 18) & 1) )
+        break;
+    }
+  }
+  return result;
+}
+
+//----- (0044E163) --------------------------------------------------------
+unsigned int TextureFrameTable::FindTextureByName(const char *Str2)
+{
+  TextureFrameTable *v2; // esi@1
+  int v3; // ebx@1
+  unsigned int uID; // edi@1
+  unsigned int result; // eax@4
+
+  v2 = this;
+  v3 = 0;
+  uID = 0;
+  if ( (signed int)this->uNumTextures <= 0 )
+  {
+LABEL_4:
+    result = -1;
+  }
+  else
+  {
+    while ( _strcmpi(v2->pTextures[v3].pTextureName, Str2) )
+    {
+      ++uID;
+      ++v3;
+      if ( (signed int)uID >= (signed int)v2->uNumTextures )
+        goto LABEL_4;
+    }
+    result = uID;
+  }
+  return result;
+}
+
+//----- (0044E19A) --------------------------------------------------------
+unsigned int TextureFrameTable::GetFrameTexture(int uFrameID, signed int a3)
+{
+  int v3; // esi@1
+  TextureFrame *v4; // edi@1
+  TextureFrame *v5; // ecx@1
+  __int16 v6; // dx@2
+  int v7; // edx@3
+  char *i; // eax@3
+  int v9; // ecx@5
+  unsigned int result; // eax@6
+
+  v3 = uFrameID;
+  v4 = this->pTextures;
+  v5 = &v4[uFrameID];
+  if ( v5->uFlags & 1 && (v6 = v5->uAnimLength) != 0 )
+  {
+    v7 = (a3 >> 3) % v6;
+    for ( i = (char *)&v5->uAnimTime; ; i += 20 )
+    {
+      v9 = *(short *)i;
+      if ( v7 <= v9 )
+        break;
+      v7 -= v9;
+      ++v3;
+    }
+    result = v4[v3].uTextureID;
+  }
+  else
+  {
+    result = v5->uTextureID;
+  }
+  return result;
+}
+
+
+
+
+
+
+//----- (0040F806) --------------------------------------------------------
+void *Texture::UnzipPalette()
+{
+  Texture *v1; // esi@1
+  void *v2; // edi@1
+  Texture *pSource; // [sp+0h] [bp-4h]@1
+
+  pSource = this;
+  v1 = this;
+  v2 = malloc(this->uDecompressedSize);
+  zlib::MemUnzip(v2, (unsigned int *)&pSource, v1->pLevelOfDetail0, v1->uTextureSize);
+  return v2;
+}
+
+//----- (0040F77C) --------------------------------------------------------
+void Texture::Release()
+{
+  if (this)
+  {
+    pName[0] = 0;
+
+    if (pBits & 0x0400)
+    {
+      pAllocator->FreeChunk(pLevelOfDetail0);
+      pAllocator->FreeChunk(pPalette16);
+      pAllocator->FreeChunk(pPalette24);
+    }
+
+    pLevelOfDetail0 = nullptr;
+    pLevelOfDetail1 = nullptr;
+    pLevelOfDetail2 = nullptr;
+    pLevelOfDetail3 = nullptr;
+
+    pPalette16 = nullptr;
+    pPalette24 = nullptr;
+
+    uSizeOfMaxLevelOfDetail = 0;
+    uTextureSize = 0;
+    uTextureHeight = 0;
+    uTextureWidth = 0;
+    uHeightLn2 = 0;
+    uWidthLn2 = 0;
+    palette_id1 = 0;
+    palette_id2 = 0;
+    pBits &= 0xFFFF0000;
+  }
+}
+
+//----- (0040F5F5) --------------------------------------------------------
+int RGBTexture::Reload(const char *pContainer)
+{
+  RGBTexture *v2; // esi@1
+  FILE *v3; // eax@3
+  FILE *v4; // edi@3
+  void *v5; // ebx@7
+  signed int result; // eax@11
+  unsigned int v7; // ecx@12
+  unsigned __int16 *v8; // ST20_4@14
+  int v9; // eax@14
+  char color_map[48]; // [sp+8h] [bp-98h]@9
+  Texture DstBuf; // [sp+38h] [bp-68h]@1
+  PCXHeader1 header1; // [sp+80h] [bp-20h]@9
+  PCXHeader2 header2; // [sp+90h] [bp-10h]@9
+  FILE *File; // [sp+98h] [bp-8h]@3
+  size_t Count; // [sp+9Ch] [bp-4h]@6
+  void *uSourceLena; // [sp+A8h] [bp+8h]@7
+
+  v2 = this;
+  if ( !v2->pPixels )
+    return 2;
+  v3 = pIcons_LOD->FindContainer(pContainer, 0);
+  v4 = v3;
+  File = v3;
+  if ( !v3 )
+  {
+    sprintf(pTmpBuf, "Unable to load %s", pContainer);
+    Abortf(pTmpBuf);
+  }
+  fread(&DstBuf, 1u, 0x30u, v3);
+  Count = DstBuf.uTextureSize;
+  if ( DstBuf.uDecompressedSize )
+  {
+    v5 = malloc(DstBuf.uDecompressedSize);
+    uSourceLena = pAllocator->AllocNamedChunk(0, DstBuf.uTextureSize, DstBuf.pName);
+    fread(uSourceLena, 1u, Count, File);
+    zlib::MemUnzip(v5, &DstBuf.uDecompressedSize, uSourceLena, DstBuf.uTextureSize);
+    DstBuf.uTextureSize = DstBuf.uDecompressedSize;
+    pAllocator->FreeChunk(uSourceLena);
+  }
+  else
+  {
+    v5 = malloc(DstBuf.uTextureSize);
+    fread(v5, 1u, Count, v4);
+  }
+  memcpy(&header1, v5, 0x10u);
+  memcpy(color_map, (char *)v5 + 16, 0x30u);
+  memcpy(&header2, (char *)v5 + 64, 6u);
+  if ( header1.bpp != 8 )
+    return 3;
+  v7 = (signed __int16)(header1.right - header1.left + 1);
+  if ( (signed int)(v7 * (signed __int16)(header1.bottom - header1.up + 1)) <= (signed int)v2->uNumPixels )
+  {
+    v2->uWidth = header1.right - header1.left + 1;
+    v8 = v2->pPixels;
+    v9 = v7 * v2->uHeight;
+    v2->uNumPixels = v9;
+    v2->uHeight = v9;
+    v2->DecodePCX((char *)v5, v8, v7);
+    free(v5);
+    result = 0;
+  }
+  else
+  {
+    result = -1;
+  }
+  return result;
+}
+
+//----- (0040F5BE) --------------------------------------------------------
+Texture::Texture()
+{
+  pName[0] = 0;
+  uSizeOfMaxLevelOfDetail = 0;
+  uTextureSize = 0;
+  uTextureHeight = 0;
+  uTextureWidth = 0;
+  uHeightLn2 = 0;
+  uWidthLn2 = 0;
+  palette_id1 = 0;
+  palette_id2 = 0;
+  pLevelOfDetail0 = 0;
+  pLevelOfDetail3 = 0;
+  pLevelOfDetail2 = 0;
+  pLevelOfDetail1 = 0;
+  pPalette16 = 0;
+  pPalette24 = 0;
+}
+
+//----- (0040F414) --------------------------------------------------------
+int RGBTexture::Load(const char *pContainer, int mode)
+{
+  RGBTexture *v3; // esi@1
+  FILE *v4; // eax@1
+  FILE *v5; // ebx@1
+  void *v6; // ebx@5
+  unsigned __int16 v7; // ax@9
+  unsigned __int16 v8; // cx@9
+  int v9; // ecx@9
+  void *v10; // eax@9
+  void *v11; // eax@13
+  unsigned __int16 *v12; // eax@17
+  char color_map[48]; // [sp+Ch] [bp-98h]@7
+  Texture DstBuf; // [sp+3Ch] [bp-68h]@1
+  PCXHeader1 header1; // [sp+84h] [bp-20h]@7
+  PCXHeader2 header2; // [sp+94h] [bp-10h]@7
+  FILE *File; // [sp+9Ch] [bp-8h]@1
+  size_t Count; // [sp+A0h] [bp-4h]@4
+  char *Str1a; // [sp+ACh] [bp+8h]@5
+
+  v3 = this;
+  v4 = pIcons_LOD->FindContainer(pContainer, 0);
+  v5 = v4;
+  File = v4;
+  if ( !v4 )
+  {
+    sprintf(pTmpBuf, "Unable to load %s", pContainer);
+    Abortf(pTmpBuf);
+  }
+  fread(&DstBuf, 1u, 0x30u, v4);
+  Count = DstBuf.uTextureSize;
+  if ( DstBuf.uDecompressedSize )
+  {
+    Str1a = (char *)malloc(DstBuf.uDecompressedSize);
+    v6 = pAllocator->AllocNamedChunk(0, DstBuf.uTextureSize, DstBuf.pName);
+    fread(v6, 1u, Count, File);
+    zlib::MemUnzip(Str1a, &DstBuf.uDecompressedSize, v6, DstBuf.uTextureSize);
+    DstBuf.uTextureSize = DstBuf.uDecompressedSize;
+    pAllocator->FreeChunk(v6);
+  }
+  else
+  {
+    Str1a = (char *)malloc(DstBuf.uTextureSize);
+    fread(Str1a, 1u, Count, v5);
+  }
+  memcpy(&header1, Str1a, 0x10u);
+  memcpy(color_map, Str1a + 16, 0x30u);
+  memcpy(&header2, Str1a + 64, 6u);
+  if ( header1.bpp != 8 )
+    return 3;
+  v7 = header1.right - header1.left + 1;
+  v8 = header1.bottom - header1.up + 1;
+  v3->uWidth = v7;
+  v3->uHeight = v8;
+  v9 = (signed __int16)v7 * (signed __int16)v8;
+  v10 = v3->pPixels;
+  v3->uNumPixels = v9;
+  if ( v10 )
+  {
+    if ( mode )
+      goto LABEL_14;
+    pAllocator->FreeChunk(v10);
+  }
+  if ( !mode )
+  {
+    v11 = pAllocator->AllocNamedChunk(v3->pPixels, 2 * v3->uNumPixels + 4, "16bit PCX");
+    goto LABEL_16;
+  }
+LABEL_14:
+  if ( mode != 2 )
+    goto LABEL_17;
+  v11 = malloc(2 * v3->uNumPixels + 4);
+  *(unsigned int *)&v3->field_20 |= 1u;
+LABEL_16:
+  v3->pPixels = (unsigned __int16 *)v11;
+LABEL_17:
+  v12 = v3->pPixels;
+  if ( !v12 )
+    return 2;
+  v3->DecodePCX(Str1a, v12, v3->uWidth);
+  free(Str1a);
+  return 0;
+}
+
+
+//----- (0040F037) --------------------------------------------------------
+signed int RGBTexture::DecodePCX(char *pPcx, unsigned __int16 *pOutPixels, unsigned int uNumPixels)
+{
+  signed int result; // eax@2
+  unsigned char test_byte; // edx@3
+  unsigned int read_offset; // ebx@37
+  unsigned int row_position; // edi@40
+  unsigned char value; // cl@63
+  char count; // [sp+50h] [bp-Ch]@43
+  unsigned short current_line; // [sp+54h] [bp-8h]@38
+  unsigned short *dec_position; 
+  unsigned short *temp_dec_position; 
+  PCXHeader1 psx_head1;
+  PCXHeader2 psx_head2;
+	short int width, height;
+	BYTE  color_map[48];	// Colormap for 16-color images
+
+ 
+ memcpy(&psx_head1, pPcx , 16);
+ memcpy(&color_map, pPcx + 16, 48);
+ memcpy(&psx_head2, pPcx + 64, 6);
+
+
+ if (psx_head1.bpp!=8)
+		return 3; 
+ uWidth=(short int )(psx_head1.right-psx_head1.left+1);  // word @ 000014
+ uHeight=(short int )(psx_head1.bottom-psx_head1.up+1);  // word @ 000016
+ 
+
+ uNumPixels=uWidth*uHeight;		  // dword @ 000010
+ 
+ memset(pOutPixels, 0, uNumPixels * sizeof(__int16));
+  short i=1;
+  while ( (1<<i) !=uWidth)
+  {
+	  ++i;
+      if (i >= 15)
+	  break;
+  }
+  field_18=i;
+  short i_=1;
+  while ( (1<<i_) !=uHeight)
+  {
+	  ++i_;
+      if (i_ >= 15)
+	  break;
+  }
+  field_1A=i_;
+  switch (field_18)
+	  {
+  case 2:   field_1C = 3;    break;
+  case 3:   field_1C = 7;    break;
+  case 4:   field_1C = 15;   break;
+  case 5:   field_1C = 31;   break;
+  case 6:   field_1C = 63;   break;
+  case 7:   field_1C = 127;  break;
+  case 8:   field_1C = 255;  break;
+  case 9:   field_1C = 511;  break;
+  case 10:  field_1C = 1023; break;
+  case 11:  field_1C = 2047; break;
+  case 12:  field_1C = 4095; break;
+	  }
+
+  switch (field_1A)
+	  {
+  case 2:   field_1E = 3;    break;
+  case 3:   field_1E = 7;    break;
+  case 4:   field_1E = 15;   break;
+  case 5:   field_1E = 31;   break;
+  case 6:   field_1E = 63;   break;
+  case 7:   field_1E = 127;  break;
+  case 8:   field_1E = 255;  break;
+  case 9:   field_1E = 511;  break;
+  case 10:  field_1E = 1023; break;
+  case 11:  field_1E = 2047; break;
+  case 12:  field_1E = 4095; break;
+	  }
+
+ 
+ read_offset = 128;
+ if (psx_head2.planes != 3)
+ 	  return 0;
+  current_line = 0;
+  if ( uHeight > 0 )
+  {
+   dec_position = pOutPixels;
+   do
+   {
+    temp_dec_position = dec_position;
+    row_position = 0;
+	//decode red line
+    if (psx_head2.pitch)
+    {
+     do
+     {
+      test_byte = pPcx[read_offset];
+      ++read_offset;
+      if ((test_byte & 0xC0) == 0xC0)
+      {	
+	    value = pPcx[read_offset];
+       	++read_offset; 
+      
+       if ((test_byte & 0x3F) > 0)
+       {
+        count = test_byte & 0x3F;
+        do
+        {
+
+         ++row_position;
+          //*temp_dec_position =0xFF000000;
+		  //*temp_dec_position|=(unsigned long)value<<16;
+         *temp_dec_position |= LOWORD(pRenderer->uTargetRMask) & ((unsigned __int8)value << (LOBYTE(pRenderer->uTargetGBits)
+                                                                                    + LOBYTE(pRenderer->uTargetRBits)
+                                                                                    + LOBYTE(pRenderer->uTargetBBits)
+                                                                                    - 8));
+
+		   temp_dec_position++;
+       if (row_position == psx_head2.pitch)
+			 break;
+        }
+        while (count-- != 1);
+       }
+      }
+      else
+      {
+       ++row_position;
+	   //*temp_dec_position =0xFF000000; 
+	  //*temp_dec_position|= (unsigned long)test_byte<<16;
+       
+       *temp_dec_position |= LOWORD(pRenderer->uTargetRMask) & ((unsigned __int8)test_byte << (LOBYTE(pRenderer->uTargetGBits)
+                                                                                    + LOBYTE(pRenderer->uTargetRBits)
+                                                                                    + LOBYTE(pRenderer->uTargetBBits)
+                                                                                    - 8));
+
+       temp_dec_position++;
+      }
+    
+     }
+     while (row_position < psx_head2.pitch);
+    }
+ 
+    temp_dec_position = dec_position;
+	row_position=0;
+	//decode green line
+    while (row_position <  psx_head2.pitch)
+    {
+     test_byte = *(pPcx + read_offset);
+     ++read_offset;
+     if ((test_byte & 0xC0) == 0xC0)
+     {
+      value = *(pPcx + read_offset);
+	  ++read_offset;
+      if ((test_byte & 0x3F) > 0)
+      {
+       count = test_byte & 0x3F;
+       do
+       {
+        //*temp_dec_position|= (unsigned int)value<<8;
+		//temp_dec_position++;
+         
+         *temp_dec_position|= pRenderer->uTargetGMask & (unsigned __int16)((unsigned __int8)value << (LOBYTE(pRenderer->uTargetGBits)
+                                                                                             + LOBYTE(pRenderer->uTargetBBits)
+                                                                                             - 8));
+         
+       temp_dec_position++;
+        ++row_position;
+        if (row_position == psx_head2.pitch)
+			break;
+  
+       }
+       while (count-- != 1);
+      }
+     }
+     else
+     {
+      //*temp_dec_position |=(unsigned int) test_byte<<8;
+	  //temp_dec_position++;
+       
+         *temp_dec_position|= pRenderer->uTargetGMask & (unsigned __int16)((unsigned __int8)test_byte << (LOBYTE(pRenderer->uTargetGBits)
+                                                                                             + LOBYTE(pRenderer->uTargetBBits)
+                                                                                             - 8));
+       temp_dec_position++;
+      ++row_position;
+     }
+    }
+
+    temp_dec_position = dec_position;
+	row_position=0;
+	//decode blue line
+    while (row_position < psx_head2.pitch)
+    {
+     test_byte = *(pPcx + read_offset);
+	 read_offset++;
+     if ((test_byte & 0xC0) ==  0xC0)
+     {
+       value = *(pPcx + read_offset);
+	  ++read_offset;
+      if ((test_byte & 0x3F) > 0)
+      {
+       count = test_byte & 0x3F;
+       do
+       {
+        //*temp_dec_position|= value;
+		 //temp_dec_position++;
+
+         *temp_dec_position |= value >> (8 - LOBYTE(pRenderer->uTargetBBits));
+       temp_dec_position++;
+
+        ++row_position;
+        if (row_position == psx_head2.pitch)
+		 break;
+       }
+       while (count-- != 1);
+      }
+     }
+     else
+     {
+      //*temp_dec_position|= test_byte;
+	   //temp_dec_position++;
+         *temp_dec_position |= test_byte >> (8 - LOBYTE(pRenderer->uTargetBBits));
+       temp_dec_position++;
+
+      ++row_position;
+     }
+     
+    }
+    ++current_line;
+    dec_position += uWidth;
+   }
+   while (current_line < uHeight);
+  }
+   return 0;
+/*
+  RGBTexture *v4; // esi@1
+  signed int result; // eax@2
+  unsigned __int16 v6; // ax@3
+  unsigned __int16 *v7; // ecx@3
+  unsigned int v8; // edx@3
+  signed int v9; // ecx@3
+  signed int v10; // ecx@8
+  signed int v11; // ebx@37
+  unsigned __int16 *v12; // eax@40
+  int v13; // edi@40
+  int v14; // ebx@41
+  char v15; // bl@42
+  unsigned __int16 *v16; // eax@50
+  int v17; // ebx@51
+  char v18; // bl@52
+  unsigned __int16 *v19; // eax@61
+  unsigned __int8 v20; // dl@62
+  unsigned __int8 v21; // dl@63
+  unsigned __int8 v22; // cl@63
+  char color_map[48]; // [sp+8h] [bp-54h]@1
+  PCXHeader1 header1; // [sp+38h] [bp-24h]@1
+  PCXHeader2 header2; // [sp+48h] [bp-14h]@1
+  unsigned int v26; // [sp+50h] [bp-Ch]@43
+  int v27; // [sp+54h] [bp-8h]@38
+  unsigned __int16 *v28; // [sp+58h] [bp-4h]@3
+  int pOutPixelsa; // [sp+68h] [bp+Ch]@41
+  int pOutPixelsb; // [sp+68h] [bp+Ch]@51
+
+  v4 = this;
+  memcpy(&header1, pPcx, 0x10u);
+  memcpy(color_map, pPcx + 16, 0x30u);
+  memcpy(&header2, pPcx + 64, 6u);
+  if ( header1.bpp == 8 )
+  {
+    v6 = header1.right - header1.left + 1;
+    LOWORD(v7) = header1.bottom - header1.up + 1;
+    v4->uWidth = v6;
+    v4->uHeight = (unsigned __int16)v7;
+    v7 = (unsigned __int16 *)(signed __int16)v7;
+    v28 = v7;
+    v4->uNumPixels = (signed __int16)v7 * (signed __int16)v6;
+    HIWORD(v8) = 0;
+    v9 = 1;
+    while ( 1 << v9 != (signed __int16)v6 )
+    {
+      ++v9;
+      if ( v9 >= 15 )
+        goto LABEL_8;
+    }
+    v4->field_18 = v9;
+LABEL_8:
+    v10 = 1;
+    while ( (unsigned __int16 *)(1 << v10) != v28 )
+    {
+      ++v10;
+      if ( v10 >= 15 )
+        goto LABEL_13;
+    }
+    v4->field_1A = v10;
+LABEL_13:
+    switch ( v4->field_18 )
+    {
+      case 2:
+        v4->field_1C = 3;
+        break;
+      case 3:
+        v4->field_1C = 7;
+        break;
+      case 4:
+        v4->field_1C = 15;
+        break;
+      case 5:
+        v4->field_1C = 31;
+        break;
+      case 6:
+        v4->field_1C = 63;
+        break;
+      case 7:
+        v4->field_1C = 127;
+        break;
+      case 8:
+        v4->field_1C = 255;
+        break;
+      case 9:
+        v4->field_1C = 511;
+        break;
+      case 10:
+        v4->field_1C = 1023;
+        break;
+      case 11:
+        v4->field_1C = 2047;
+        break;
+      case 12:
+        v4->field_1C = 4095;
+        break;
+      default:
+        break;
+    }
+    switch ( v4->field_1A )
+    {
+      case 2:
+        v4->field_1E = 3;
+        break;
+      case 3:
+        v4->field_1E = 7;
+        break;
+      case 4:
+        v4->field_1E = 15;
+        break;
+      case 5:
+        v4->field_1E = 31;
+        break;
+      case 6:
+        v4->field_1E = 63;
+        break;
+      case 7:
+        v4->field_1E = 127;
+        break;
+      case 8:
+        v4->field_1E = 255;
+        break;
+      case 9:
+        v4->field_1E = 511;
+        break;
+      case 10:
+        v4->field_1E = 1023;
+        break;
+      case 11:
+        v4->field_1E = 2047;
+        break;
+      case 12:
+        v4->field_1E = 4095;
+        break;
+      default:
+        break;
+    }
+    v11 = 128;
+    if ( header2.planes == 3 )
+    {
+      v27 = 0;
+      if ( (signed int)v28 > 0 )
+      {
+        v28 = pOutPixels;
+        do
+        {
+          v12 = v28;
+          v13 = 0;
+          if ( header2.pitch )
+          {
+            do
+            {
+              LOBYTE(v8) = pPcx[v11];
+              v14 = v11 + 1;
+              pOutPixelsa = v14;
+              if ( (v8 & 0xC0) == -64 )
+              {
+                pOutPixelsa = v14 + 1;
+                v15 = pPcx[v14];
+                if ( (signed int)(v8 & 0x3F) > 0 )
+                {
+                  v26 = v8 & 0x3F;
+                  do
+                  {
+                    ++v13;
+                    *v12 = LOWORD(pRenderer->uTargetRMask) & ((unsigned __int8)v15 << (LOBYTE(pRenderer->uTargetGBits)
+                                                                                    + LOBYTE(pRenderer->uTargetRBits)
+                                                                                    + LOBYTE(pRenderer->uTargetBBits)
+                                                                                    - 8));
+                    ++v12;
+                    if ( v13 == (unsigned __int16)header2.pitch )
+                      v12 = &v12[uNumPixels - (unsigned __int16)header2.pitch - 1];
+                    --v26;
+                  }
+                  while ( v26 );
+                }
+              }
+              else
+              {
+                LOWORD(v8) = (unsigned __int8)v8;
+                v8 = pRenderer->uTargetRMask & (v8 << (LOBYTE(pRenderer->uTargetGBits)
+                                                    + LOBYTE(pRenderer->uTargetRBits)
+                                                    + LOBYTE(pRenderer->uTargetBBits)
+                                                    - 8));
+                ++v13;
+                *v12 = v8;
+                ++v12;
+              }
+              v11 = pOutPixelsa;
+            }
+            while ( v13 < (unsigned __int16)header2.pitch );
+          }
+          v16 = v28;
+          while ( v13 < 2 * (unsigned __int16)header2.pitch )
+          {
+            LOBYTE(v8) = pPcx[v11];
+            v17 = v11 + 1;
+            pOutPixelsb = v17;
+            if ( (v8 & 0xC0) == -64 )
+            {
+              pOutPixelsb = v17 + 1;
+              v18 = pPcx[v17];
+              if ( (signed int)(v8 & 0x3F) > 0 )
+              {
+                v26 = v8 & 0x3F;
+                do
+                {
+                  *v16 |= pRenderer->uTargetGMask & (unsigned __int16)((unsigned __int8)v18 << (LOBYTE(pRenderer->uTargetGBits)
+                                                                                             + LOBYTE(pRenderer->uTargetBBits)
+                                                                                             - 8));
+                  ++v13;
+                  ++v16;
+                  if ( v13 == (unsigned __int16)header2.pitch )
+                    v16 = &v16[uNumPixels - (unsigned __int16)header2.pitch - 1];
+                  --v26;
+                }
+                while ( v26 );
+              }
+            }
+            else
+            {
+              LOWORD(v8) = (unsigned __int8)v8;
+              v8 = pRenderer->uTargetGMask & (v8 << (LOBYTE(pRenderer->uTargetGBits) + LOBYTE(pRenderer->uTargetBBits) - 8));
+              *v16 |= v8;
+              ++v13;
+              ++v16;
+            }
+            v11 = pOutPixelsb;
+          }
+          v19 = v28;
+          while ( v13 < 3 * (unsigned __int16)header2.pitch )
+          {
+            v20 = pPcx[v11++];
+            if ( (v20 & 0xC0) == -64 )
+            {
+              v21 = v20 & 0x3F;
+              v22 = pPcx[v11++];
+              if ( (signed int)v21 > 0 )
+              {
+                v26 = v21;
+                do
+                {
+                  *v19 |= v22 >> (8 - LOBYTE(pRenderer->uTargetBBits));
+                  ++v13;
+                  ++v19;
+                  if ( v13 == (unsigned __int16)header2.pitch )
+                  {
+                    v8 = uNumPixels - (unsigned __int16)header2.pitch;
+                    v19 = &v19[uNumPixels - (unsigned __int16)header2.pitch - 1];
+                  }
+                  --v26;
+                }
+                while ( v26 );
+              }
+            }
+            else
+            {
+              *v19 |= v20 >> (8 - LOBYTE(pRenderer->uTargetBBits));
+              ++v13;
+              ++v19;
+            }
+          }
+          ++v27;
+          v28 += uNumPixels;
+        }
+        while ( v27 < v4->uHeight );
+      }
+    }
+    result = 0;
+  }
+  else
+  {
+    result = 3;
+  }
+  return result;
+  */
+}
+
+//----- (0040EAD8) --------------------------------------------------------
+unsigned int RGBTexture::LoadFromFILE(FILE *pFile, unsigned int mode, unsigned int bCloseFile)
+{
+  signed int result; // eax@2
+  unsigned char test_byte; // edx@3
+  //unsigned int read_offset; // ebx@37
+  unsigned int row_position; // edi@40
+  unsigned char value; // cl@63
+  char count; // [sp+50h] [bp-Ch]@43
+  unsigned short current_line; // [sp+54h] [bp-8h]@38
+  unsigned short *dec_position; 
+  unsigned short *temp_dec_position; 
+  PCXHeader1 psx_head1;
+  PCXHeader2 psx_head2;
+	short int width, height;
+	BYTE  color_map[48];	// Colormap for 16-color images
+
+  if (!pFile)
+    return 1;
+  
+ 
+ fread(&psx_head1, 1, 16, pFile);
+ fread(&color_map, 1, 48, pFile);
+ fread(&psx_head2, 1, 6, pFile);
+
+  if (psx_head1.bpp!=8)
+		return 3; 
+ uWidth=(short int )(psx_head1.right-psx_head1.left+1);  // word @ 000014
+ uHeight=(short int )(psx_head1.bottom-psx_head1.up+1);  // word @ 000016
+ 
+
+ uNumPixels=uWidth*uHeight;		  // dword @ 000010
+
+
+      if ( mode == 0 )
+      {
+        if ( pPixels )
+        {
+          pAllocator->FreeChunk(pPixels);
+          pPixels = 0;
+        }
+        pPixels = (unsigned __int16 *)pAllocator->AllocNamedChunk(
+                                            pPixels,
+                                            2 * uNumPixels + 4,
+                                            pName);
+      }
+      else
+      {
+        if ( mode != 1 && mode == 2 )
+        {
+          pPixels = (unsigned __int16 *)malloc((uNumPixels + 2) * sizeof(unsigned __int16));
+          field_20 |= 1;
+        }
+      }
+
+
+
+
+      auto pOutPixels = pPixels;
+ 
+ memset(pOutPixels, 0, uNumPixels * sizeof(__int16));
+
+  short i=1;
+  while ( (1<<i) !=uWidth)
+  {
+	  ++i;
+      if (i >= 15)
+	  break;
+  }
+  field_18=i;
+  short i_=1;
+  while ( (1<<i_) !=uHeight)
+  {
+	  ++i_;
+      if (i_ >= 15)
+	  break;
+  }
+  field_1A=i_;
+  switch (field_18)
+	  {
+  case 2:   field_1C = 3;    break;
+  case 3:   field_1C = 7;    break;
+  case 4:   field_1C = 15;   break;
+  case 5:   field_1C = 31;   break;
+  case 6:   field_1C = 63;   break;
+  case 7:   field_1C = 127;  break;
+  case 8:   field_1C = 255;  break;
+  case 9:   field_1C = 511;  break;
+  case 10:  field_1C = 1023; break;
+  case 11:  field_1C = 2047; break;
+  case 12:  field_1C = 4095; break;
+	  }
+
+  switch (field_1A)
+	  {
+  case 2:   field_1E = 3;    break;
+  case 3:   field_1E = 7;    break;
+  case 4:   field_1E = 15;   break;
+  case 5:   field_1E = 31;   break;
+  case 6:   field_1E = 63;   break;
+  case 7:   field_1E = 127;  break;
+  case 8:   field_1E = 255;  break;
+  case 9:   field_1E = 511;  break;
+  case 10:  field_1E = 1023; break;
+  case 11:  field_1E = 2047; break;
+  case 12:  field_1E = 4095; break;
+	  }
+
+
+  fseek(pFile, 128 - 70, SEEK_CUR);
+
+
+  for (uint y = 0; y < uHeight; ++y)
+  {
+    unsigned __int16 *pDst = pPixels + y * uWidth;
+
+    uint x = 0;
+    do
+    {
+      uint ctrl = 0;
+      fread(&ctrl, 1, 1, pFile);
+      if ((ctrl & 0xC0) == 0xC0)
+      {
+        uint uNumPixels = ctrl & 0x3F;
+        uint clr = 0;
+        fread(&clr, 1, 1, pFile);
+        for (uint i = 0; i < uNumPixels; ++i)
+          pDst[x++] = pRenderer->uTargetRMask & (clr << (pRenderer->uTargetGBits +
+                                                         pRenderer->uTargetRBits +
+                                                         pRenderer->uTargetBBits - 8));
+      }
+      else
+      {
+        pDst[x++] = pRenderer->uTargetRMask & (ctrl << (pRenderer->uTargetGBits +
+                                                        pRenderer->uTargetRBits +
+                                                        pRenderer->uTargetBBits - 8));
+      }
+    } while (x < psx_head2.pitch);
+
+
+
+
+
+    x = 0;
+    do
+    {
+      uint ctrl = 0;
+      fread(&ctrl, 1, 1, pFile);
+      if ((ctrl & 0xC0) == 0xC0)
+      {
+        uint uNumPixels = ctrl & 0x3F;
+        uint clr = 0;
+        fread(&clr, 1, 1, pFile);
+        for (uint i = 0; i < uNumPixels; ++i)
+          pDst[x++] |= pRenderer->uTargetGMask & (clr << (pRenderer->uTargetGBits +
+                                                         pRenderer->uTargetBBits - 8));
+      }
+      else
+      {
+        pDst[x++] |= pRenderer->uTargetGMask & (ctrl << (pRenderer->uTargetGBits +
+                                                        pRenderer->uTargetBBits - 8));
+      }
+    } while (x < psx_head2.pitch);
+ 
+
+
+
+
+    x = 0;
+    do
+    {
+      uint ctrl = 0;
+      fread(&ctrl, 1, 1, pFile);
+      if ((ctrl & 0xC0) == 0xC0)
+      {
+        uint uNumPixels = ctrl & 0x3F;
+        uint clr = 0;
+        fread(&clr, 1, 1, pFile);
+        for (uint i = 0; i < uNumPixels; ++i)
+          pDst[x++] |= pRenderer->uTargetBMask & (clr >> (8 - pRenderer->uTargetBBits));
+      }
+      else
+      {
+        pDst[x++] |= pRenderer->uTargetBMask & (ctrl >> (8 - pRenderer->uTargetRBits));
+      }
+    } while (x < psx_head2.pitch);
+  }
+
+  if (bCloseFile)
+    fclose(pFile);
+  return 0;
+}
+
+//----- (0040E51F) --------------------------------------------------------
+void RGBTexture::Release()
+{
+  RGBTexture *v1; // esi@1
+  char v2; // zf@1
+  void *v3; // [sp-4h] [bp-Ch]@1
+
+  v1 = this;
+  v2 = (this->field_20 & 1) == 0;
+  v3 = this->pPixels;
+  this->pName[0] = 0;
+  if ( v2 )
+    pAllocator->FreeChunk(v3);
+  else
+    free(v3);
+  *(unsigned int *)&v1->field_20 = 0;
+  v1->pPixels = 0;
+  v1->uNumPixels = 0;
+  v1->uHeight = 0;
+  v1->uWidth = 0;
+  v1->field_1A = 0;
+  v1->field_18 = 0;
+}
+
+//----- (0040E55E) --------------------------------------------------------
+int RGBTexture::_40E55E(const char *Filename, unsigned int a3)
+{
+  RGBTexture *v3; // esi@1
+  signed int result; // eax@2
+  FILE *v5; // edi@3
+  char *v6; // eax@3
+  int v7; // edx@3
+  char v8; // cl@4
+  unsigned __int16 v9; // cx@9
+  unsigned __int16 v10; // ax@9
+  int v11; // eax@9
+  char v12; // zf@9
+  void *v13; // eax@12
+  signed int v14; // ecx@19
+  signed int v15; // ecx@24
+  int v16; // eax@57
+  unsigned __int16 *v17; // ecx@57
+  unsigned __int16 *v18; // edi@57
+  signed int v19; // eax@59
+  unsigned __int16 *v20; // edi@64
+  signed int v21; // eax@66
+  unsigned __int16 *v22; // edi@71
+  signed int v23; // eax@73
+  int v24; // eax@78
+  char v25; // [sp+Ch] [bp-54h]@3
+  char DstBuf; // [sp+3Ch] [bp-24h]@3
+  char v27; // [sp+3Dh] [bp-23h]@3
+  char v28; // [sp+3Eh] [bp-22h]@3
+  char v29; // [sp+3Fh] [bp-21h]@3
+  int v30; // [sp+40h] [bp-20h]@3
+  int v31; // [sp+44h] [bp-1Ch]@3
+  char v32; // [sp+48h] [bp-18h]@3
+  char v33; // [sp+4Ah] [bp-16h]@3
+  char v34; // [sp+4Ch] [bp-14h]@3
+  char v35; // [sp+4Dh] [bp-13h]@3
+  unsigned __int16 v36; // [sp+4Eh] [bp-12h]@3
+  int v37; // [sp+54h] [bp-Ch]@3
+  int v38; // [sp+58h] [bp-8h]@57
+  FILE *File; // [sp+5Ch] [bp-4h]@1
+
+  v3 = this;
+  File = fopen(Filename, "rb");
+  if ( !File )
+    return 1;
+  v5 = File;
+  fread(&DstBuf, 1u, 1u, File);
+  fread(&v27, 1u, 1u, v5);
+  fread(&v28, 1u, 1u, v5);
+  fread(&v29, 1u, 1u, v5);
+  fread(&v30, 2u, 1u, v5);
+  fread((char *)&v30 + 2, 2u, 1u, File);
+  fread(&v31, 2u, 1u, File);
+  fread((char *)&v31 + 2, 2u, 1u, File);
+  fread(&v32, 2u, 1u, File);
+  fread(&v33, 2u, 1u, File);
+  fread(&v25, 0x30u, 1u, File);
+  fread(&v34, 1u, 1u, File);
+  fread(&v35, 1u, 1u, File);
+  fread(&v36, 2u, 1u, File);
+  v6 = (char *)Filename;
+  v37 = 0;
+  v7 = (char *)v3 - Filename;
+  do
+  {
+    v8 = *v6;
+    if ( !*v6 )
+      break;
+    if ( v8 == 46 )
+      break;
+    ++v37;
+    (v6++)[v7] = v8;
+  }
+  while ( v37 < 15 );
+  v3->pName[v37] = 0;
+  if ( v29 != 8 )
+    return 3;
+  v9 = v31 - (short)v30 + 1;
+  v10 = HIWORD(v31) - HIWORD(v30);
+  v3->uWidth = v9;
+  ++v10;
+  v3->uHeight = v10;
+  v11 = (signed __int16)v9 * (signed __int16)v10;
+  v12 = a3 == 0;
+  v3->uNumPixels = v11;
+  if ( v12 )
+  {
+    if ( v3->pPixels )
+      pAllocator->FreeChunk(v3->pPixels);
+    v13 = pAllocator->AllocNamedChunk(v3->pPixels, 2 * v3->uNumPixels + 4, v3->pName);
+    goto LABEL_16;
+  }
+  if ( a3 != 1 && a3 == 2 )
+  {
+    v13 = operator new(4 * v11 + 8);
+    *(unsigned int *)&v3->field_20 |= 1u;
+LABEL_16:
+    v3->pPixels = (unsigned __int16 *)v13;
+  }
+  if ( v3->pPixels )
+  {
+    v14 = 1;
+    while ( 1 << v14 != v3->uWidth )
+    {
+      ++v14;
+      if ( v14 >= 15 )
+        goto LABEL_24;
+    }
+    v3->field_18 = v14;
+LABEL_24:
+    v15 = 1;
+    while ( 1 << v15 != v3->uHeight )
+    {
+      ++v15;
+      if ( v15 >= 15 )
+        goto LABEL_29;
+    }
+    v3->field_1A = v15;
+LABEL_29:
+    switch ( v3->field_18 )
+    {
+      case 2:
+        v3->field_1C = 3;
+        break;
+      case 3:
+        v3->field_1C = 7;
+        break;
+      case 4:
+        v3->field_1C = 15;
+        break;
+      case 5:
+        v3->field_1C = 31;
+        break;
+      case 6:
+        v3->field_1C = 63;
+        break;
+      case 7:
+        v3->field_1C = 127;
+        break;
+      case 8:
+        v3->field_1C = 255;
+        break;
+      case 9:
+        v3->field_1C = 511;
+        break;
+      case 10:
+        v3->field_1C = 1023;
+        break;
+      case 11:
+        v3->field_1C = 2047;
+        break;
+      case 12:
+        v3->field_1C = 4095;
+        break;
+      default:
+        break;
+    }
+    switch ( v3->field_1A )
+    {
+      case 2:
+        v3->field_1E = 3;
+        break;
+      case 3:
+        v3->field_1E = 7;
+        break;
+      case 4:
+        v3->field_1E = 15;
+        break;
+      case 5:
+        v3->field_1E = 31;
+        break;
+      case 6:
+        v3->field_1E = 63;
+        break;
+      case 7:
+        v3->field_1E = 127;
+        break;
+      case 8:
+        v3->field_1E = 255;
+        break;
+      case 9:
+        v3->field_1E = 511;
+        break;
+      case 10:
+        v3->field_1E = 1023;
+        break;
+      case 11:
+        v3->field_1E = 2047;
+        break;
+      case 12:
+        v3->field_1E = 4095;
+        break;
+      default:
+        break;
+    }
+    fseek(File, 128, 0);
+    ftell(File);
+    if ( v35 == 1 )
+      Abortf("24bit PCX Only!");
+    if ( v35 == 3 )
+    {
+      v37 = 0;
+      if ( v3->uHeight > 0 )
+      {
+        do
+        {
+          v16 = v37 * v3->uWidth;
+          v17 = v3->pPixels;
+          v38 = 0;
+          v18 = &v17[v16];
+          if ( v36 )
+          {
+            do
+            {
+              fread((char *)&Filename + 3, 1u, 1u, File);
+              if ( (BYTE3(Filename) & 0xC0) == -64 )
+              {
+                BYTE3(Filename) &= 0x3Fu;
+                fread((char *)&a3 + 3, 1u, 1u, File);
+                v19 = 0;
+                if ( BYTE3(Filename) )
+                {
+                  do
+                  {
+                    ++v38;
+                    *v18 = LOWORD(pRenderer->uTargetRMask) & (BYTE3(a3) << (LOBYTE(pRenderer->uTargetGBits)
+                                                                         + LOBYTE(pRenderer->uTargetRBits)
+                                                                         + LOBYTE(pRenderer->uTargetBBits)
+                                                                         - 8));
+                    ++v18;
+                    ++v19;
+                  }
+                  while ( v19 < BYTE3(Filename) );
+                }
+              }
+              else
+              {
+                ++v38;
+                *v18 = LOWORD(pRenderer->uTargetRMask) & (BYTE3(Filename) << (LOBYTE(pRenderer->uTargetGBits)
+                                                                           + LOBYTE(pRenderer->uTargetRBits)
+                                                                           + LOBYTE(pRenderer->uTargetBBits)
+                                                                           - 8));
+                ++v18;
+              }
+            }
+            while ( v38 < v36 );
+          }
+          v20 = &v3->pPixels[v37 * v3->uWidth];
+          while ( v38 < 2 * v36 )
+          {
+            fread((char *)&Filename + 3, 1u, 1u, File);
+            if ( (BYTE3(Filename) & 0xC0) == -64 )
+            {
+              BYTE3(Filename) &= 0x3Fu;
+              fread((char *)&a3 + 3, 1u, 1u, File);
+              v21 = 0;
+              if ( BYTE3(Filename) )
+              {
+                do
+                {
+                  *v20 |= pRenderer->uTargetGMask & (unsigned __int16)(BYTE3(a3) << (LOBYTE(pRenderer->uTargetGBits)
+                                                                                  + LOBYTE(pRenderer->uTargetBBits)
+                                                                                  - 8));
+                  ++v38;
+                  ++v20;
+                  ++v21;
+                }
+                while ( v21 < BYTE3(Filename) );
+              }
+            }
+            else
+            {
+              *v20 |= pRenderer->uTargetGMask & (unsigned __int16)(BYTE3(Filename) << (LOBYTE(pRenderer->uTargetGBits)
+                                                                                    + LOBYTE(pRenderer->uTargetBBits)
+                                                                                    - 8));
+              ++v38;
+              ++v20;
+            }
+          }
+          v22 = &v3->pPixels[v37 * v3->uWidth];
+          while ( v38 < 3 * v36 )
+          {
+            fread((char *)&Filename + 3, 1u, 1u, File);
+            if ( (BYTE3(Filename) & 0xC0) == -64 )
+            {
+              BYTE3(Filename) &= 0x3Fu;
+              fread((char *)&a3 + 3, 1u, 1u, File);
+              v23 = 0;
+              if ( BYTE3(Filename) )
+              {
+                do
+                {
+                  *v22 |= BYTE3(a3) >> (8 - LOBYTE(pRenderer->uTargetBBits));
+                  ++v38;
+                  ++v22;
+                  ++v23;
+                }
+                while ( v23 < BYTE3(Filename) );
+              }
+            }
+            else
+            {
+              *v22 |= BYTE3(Filename) >> (8 - LOBYTE(pRenderer->uTargetBBits));
+              ++v38;
+              ++v22;
+            }
+          }
+          v24 = v3->uHeight;
+          ++v37;
+        }
+        while ( v37 < v24 );
+      }
+    }
+    fclose(File);
+    result = 0;
+  }
+  else
+  {
+    result = 2;
+  }
+  return result;
+}
+
+
+//----- (0040D73D) --------------------------------------------------------
+RGBTexture::RGBTexture()
+{
+  pName[0] = 0;
+  pPixels = 0;
+  uNumPixels = 0;
+  uHeight = 0;
+  uWidth = 0;
+  field_1A = 0;
+  field_18 = 0;
+  field_20 = 0;
+  field_22 = 0;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Texture.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,361 @@
+#pragma once
+#include <stdio.h>
+
+
+
+/*  194 */
+#pragma pack(push, 1)
+struct RGBTexture
+{
+  RGBTexture();
+  void Release();
+  int _40E55E(const char *Filename, unsigned int a3);
+  unsigned int LoadFromFILE(FILE *pFile, unsigned int mode, unsigned int bCloseFile);
+  int DecodePCX(char *pPcx, unsigned __int16 *pOutPixels, unsigned int uNumPixels);
+  int Load(const char *pContainer, int mode);
+  int Reload(const char *pContainer);
+
+  char pName[16];
+  unsigned int uNumPixels;
+  unsigned __int16 uWidth;
+  unsigned __int16 uHeight;
+  __int16 field_18;
+  __int16 field_1A;
+  __int16 field_1C;
+  __int16 field_1E;
+  __int16 field_20;
+  __int16 field_22;
+  unsigned __int16 *pPixels;
+};
+#pragma pack(pop)
+
+
+
+#pragma pack(push, 1)
+struct Texture
+{
+  Texture();
+  void Release();
+  void *UnzipPalette();
+
+  char pName[16];
+  unsigned int uSizeOfMaxLevelOfDetail;
+  unsigned int uTextureSize;
+  unsigned __int16 uTextureWidth;
+  unsigned __int16 uTextureHeight;
+  __int16 uWidthLn2;
+  __int16 uHeightLn2;
+  __int16 uWidthMinus1;
+  __int16 uHeightMinus1;
+  short palette_id1;
+  short palette_id2;
+  unsigned int uDecompressedSize;
+  int pBits;
+  unsigned __int8 *pLevelOfDetail0;
+  unsigned __int8 *pLevelOfDetail1;
+  unsigned __int8 *pLevelOfDetail2;
+  unsigned __int8 *pLevelOfDetail3;
+  unsigned __int16 *pPalette16;
+  unsigned __int8 *pPalette24;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*  323 */
+enum TEXTURE_FRAME_TABLE_FLAGS
+{
+  TEXTURE_FRAME_TABLE_MORE_FRAMES = 0x1,
+  TEXTURE_FRAME_TABLE_FIRST = 0x2,
+};
+
+
+
+/*   41 */
+#pragma pack(push, 1)
+struct TextureFrame
+{
+  char pTextureName[12];
+  __int16 uTextureID;
+  __int16 uAnimTime;
+  __int16 uAnimLength;
+  __int16 uFlags;
+};
+#pragma pack(pop)
+
+/*   40 */
+#pragma pack(push, 1)
+struct TextureFrameTable
+{
+  //----- (0044D4C9) --------------------------------------------------------
+  inline TextureFrameTable()
+  {
+    pTextures = 0;
+    uNumTextures = 0;
+  }
+  int FromFileTxt(const char *Args);
+  void ToFile();
+  void FromFile(void *pSerialized);
+  unsigned int LoadAnimationSequenceAndPalettes(unsigned int uIconID);
+  unsigned int GetFrameTexture(int uFrameID, signed int a3);
+  unsigned int FindTextureByName(const char *Str2);
+
+
+  unsigned int uNumTextures;
+  struct TextureFrame *pTextures;
+};
+#pragma pack(pop)
+
+extern struct TextureFrameTable *pTextureFrameTable;
+
+
+
+
+
+extern Texture *pTexture_LloydBeacons[2];
+extern Texture *pTexture_50635C;
+extern Texture *pTexture_506368;
+extern Texture *pTexture_50636C;
+extern Texture *pTexture_506370;
+extern Texture *pTexture_506374;
+extern Texture *pTexture_506378;
+extern Texture *pTexture_50637C;
+extern Texture *pTexture_506380;
+extern Texture *pTexture_506384;
+extern Texture *pTexture_506388;
+extern Texture *pTexture_50638C;
+extern Texture *pTexture_506390;
+extern Texture *pTexture_506394;
+extern Texture *pTex_tab_an_7a__zoot_off;
+extern Texture *pTex_tab_an_6a__zoom_off;
+extern Texture *pTex_tab_an_7b__zoot_on;
+extern Texture *pTex_tab_an_6b__zoom_on;
+extern Texture *pTexture_TownPortalHarmn;
+extern Texture *pTexture_TownPortalElf;
+extern Texture *pTexture_TownPortalWarlock;
+extern Texture *pTexture_TownPortalIsland;
+extern Texture *pTexture_TownPortalHeaven;
+extern Texture *pTexture_TownPortalHell;
+extern Texture *dword_5063D8[];
+extern Texture *dword_506404[];
+extern Texture *dword_506434[];
+extern Texture *pTexture_50643C; // idb
+extern Texture *ptr_506440;
+extern Texture *pTexture_506444;
+extern Texture *pTexture_506448; // idb
+extern Texture *pTextures_tabs[8][2];
+extern Texture *pTexture_mapbordr; // idb
+extern Texture *pTexture_pagemask; // idb
+extern Texture *pTextures_5064A0[14];
+extern Texture *pTexture_AutonotesBook;
+extern Texture *pTexture_CurrentBook;
+extern Texture *pTex_moon_new;
+extern Texture *pTex_moon_4;
+extern Texture *pTex_moon_2;
+extern Texture *pTex_moon_2_2;
+extern Texture *pTex_moon_ful;
+
+
+
+extern RGBTexture stru_506E40; // weak
+extern RGBTexture pTexture_PCX;
+
+
+extern int uTextureID_RestUI_restb4; // weak
+extern int uTextureID_RestUI_restexit; // weak
+extern int uTextureID_RestUI_restb3; // weak
+extern int uTextureID_RestUI_restb1; // weak
+extern int uTextureID_RestUI_restb2; // weak
+extern int uTextureID_RestUI_restmain; // weak
+extern unsigned int uTextureID_Leather;
+extern int uTextureID_ar_dn_dn; // weak
+extern int uTextureID_ar_dn_up; // weak
+extern int uTextureID_ar_up_dn; // weak
+extern int uTextureID_ar_up_up; // weak
+
+
+extern int uTextureID_507698; // weak
+extern int uTextureID_50769C; // weak
+extern int uTextureID_5076A0; // weak
+extern int uTextureID_5076A4; // weak
+extern int uTextureID_5076A8; // weak
+extern int uTextureID_5076AC; // weak
+extern int uTextureID_5076B0; // weak
+extern int uTextureID_5076B4; // weak
+extern int uTextureID_Parchment; // weak
+extern unsigned int uTextureID_mhp_yel;
+extern unsigned int uTextureID_mhp_red;
+extern unsigned int uTextureID_mhp_grn;
+extern unsigned int uTextureID_mhp_capr;
+extern unsigned int uTextureID_mhp_capl;
+extern unsigned int uTextureID_mhp_bd;
+extern unsigned int uTextureID_BUTTDESC2;
+extern unsigned int uTextureID_x_x_u;
+extern unsigned int uTextureID_BUTTMAKE2;
+extern unsigned int uTextureID_BUTTMAKE;
+extern unsigned int uTextureID_BUTTYES2;
+extern unsigned int uTextureID_x_ok_u;
+extern Texture *pPlayerPortraits[22];
+extern Texture *pTexture_IC_KNIGHT[8];
+extern Texture *pTexture_MAKESKY;
+extern Texture *pTexture_MAKETOP;
+extern Texture *pTextures_arrowr[20];
+extern Texture *pTextures_arrowl[20];
+extern Texture *pTexture_presleft;
+extern Texture *pTexture_pressrigh;
+extern Texture *pTexture_buttminu;
+extern Texture *pTexture_buttplus;
+extern unsigned int uTextureID_50792C; // weak
+extern unsigned int uTextureID_507930; // weak
+extern unsigned int uTextureID_507934; // weak
+extern unsigned int uTextureID_507938; // weak
+extern unsigned int uTextureID_50793C; // weak
+extern unsigned int uTextureID_507940; // weak
+extern unsigned int uTextureID_507944; // weak
+
+
+extern unsigned int uTextureID_ib_td5_A;
+extern unsigned int uTextureID_ib_td2_A; // weak
+extern unsigned int uTextureID_ib_td1_A;
+extern int uTextureID_507958; // weak
+extern int uTextureID_50795C; // weak
+
+
+extern unsigned int uTextureID_507970;
+
+
+extern unsigned int uTextureID_507978;
+extern unsigned int uTextureID_50797C;
+extern unsigned int uTextureID_507980;
+extern unsigned int uTextureID_507984;
+extern unsigned int uTextureID_FONTPAL;
+extern unsigned int uTextureID_50798C;
+extern unsigned int uTextureID_507990;
+extern unsigned int pTextureIDs_pMapDirs[8];
+
+
+extern unsigned int uTextureID_BarRed;
+extern unsigned int uTextureID_BarYellow;
+extern unsigned int uTextureID_BarGreen;
+extern unsigned int uTextureID_BarBlue;
+
+
+extern unsigned int uTextureID_right_panel; // weak
+
+
+extern RGBTexture *pTexture_StatusBar;
+extern RGBTexture *pTexture_LeftFrame;
+extern RGBTexture *pTexture_TopFrame;
+extern RGBTexture *pTexture_BottomFrame;
+extern RGBTexture *pTexture_RightFrame;
+
+
+extern unsigned int uTextureID_507B04; // weak
+
+
+extern Texture *pTexture_Leather;
+extern Texture *pTexture_RestUI_CurrentSkyFrame; // idb
+extern Texture *pTexture_RestUI_CurrentHourglassFrame; // idb
+
+
+extern unsigned int uTextureID_507BF4; // weak
+extern unsigned int uTextureID_507BF8; // weak
+extern unsigned int uTextureID_507BFC; // weak
+extern unsigned int uTextureID_507C00; // weak
+extern unsigned int uTextureID_507C04; // weak
+
+
+extern unsigned int uTextureID_507C10; // weak
+extern unsigned int uTextureID_507C14; // weak
+extern unsigned int uTextureID_507C18; // weak
+extern unsigned int uTextureID_507C1C; // weak
+extern unsigned int uTextureID_507C20; // weak
+extern unsigned int uTextureID_507C24; // weak
+extern unsigned int pTextureIDs_GammaPositions[10];
+extern unsigned int uTextureID_507C50; // weak
+extern unsigned int uTextureID_507C54; // weak
+extern unsigned int uTextureID_507C58; // weak
+extern unsigned int uTextureID_507C60; // weak
+extern unsigned int uTextureID_507C64[]; // weak
+extern unsigned int uTextureID_507C68; // weak
+extern unsigned int uTextureID_507C6C; // weak
+extern unsigned int uTextureID_507C70; // weak
+extern unsigned int uTextureID_507C74; // weak
+extern unsigned int uTextureID_507C84; // weak
+extern unsigned int pTextureIDs_SoundLevels[10];
+extern unsigned int uTextureID_507CB0; // weak
+extern unsigned int uTextureID_507CB4; // weak
+extern unsigned int uTextureID_507CB8; // weak
+
+
+extern unsigned int uTextureID_5118C8; // weak
+extern unsigned int uTextureID_MAGNIF_B; // weak
+extern unsigned int uTextureID_BACKDOLL; // weak
+extern unsigned int uTextureID_BACKHAND; // weak
+
+
+extern Texture pTex_F7CE30;
+
+
+extern RGBTexture stru_5773C4; // idb
+
+
+
+
+
+
+
+
+
+
+
+struct stru355
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+};
+
+/*  390 */
+#pragma pack(push, 1)
+struct stru350
+{
+  stru350 *_450DDE();
+  bool _450DF1(const stru355 *p1, const stru355 *p2);
+  unsigned int _450F55(int a2);
+  int _450FB1(int a2);
+  int sub_451007_scale_image_bicubic(unsigned short *pSrc, int srcWidth, int srcHeight, int srcPitch,
+                                     unsigned short *pDst, int dstWidth, int dstHeight, int dstPitch,
+                                     int a9, int a10);
+
+  stru355 field_0;
+  stru355 field_20;
+  int field_40;
+  int field_44;
+  int field_48;
+  int field_4C;
+  int field_50;
+  int field_54;
+  int field_58;
+  int field_5C;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TileFrameTable.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,61 @@
+#pragma once
+
+
+
+/*  327 */
+enum TILE_DESC_FLAGS
+{
+  TILE_DESC_BURNS = 0x1,
+  TILE_DESC_WATER = 0x2,
+  TILE_DESC_BLOCK = 0x4,
+  TILE_DESC_REPULSE = 0x8,
+  TILE_DESC_FLAT = 0x10,
+  TILE_DESC_WAVY = 0x20,
+  TILE_DESC_DONT_DRAW = 0x40,
+  TILE_DESC_WATER_2 = 0x100,
+  TILE_DESC_TRANSITION = 0x200,
+  TILE_DESC_SCROLL_DOWN = 0x400,
+  TILE_DESC_SCROLL_UP = 0x800,
+  TILE_DESC_SCROLL_LEFT = 0x1000,
+  TILE_DESC_SCROLL_RIGHT = 0x2000,
+};
+
+
+
+/*   48 */
+#pragma pack(push, 1)
+struct TileDesc
+{
+  char pTileName[16];
+  unsigned __int16 uTileID;
+  unsigned __int16 uBitmapID;
+  unsigned __int16 uTerrainType;
+  unsigned __int16 uSection;
+  unsigned __int16 uAttributes;
+};
+#pragma pack(pop)
+
+/*   49 */
+#pragma pack(push, 1)
+struct TileTable
+{
+  //----- (00487E13) --------------------------------------------------------
+  TileTable()
+  {
+    this->pTiles = nullptr;
+    this->uNumTiles = 0;
+  }
+  ~TileTable();
+
+  TileDesc *GetTileById(unsigned int uTileID);
+  void InitializeTileset(int uTerrainType);
+  int method_487ED6(signed int a1, int a2);
+  unsigned int GetTileId(unsigned int uTerrainType, unsigned int uSection);
+  void ToFile();
+  void FromFile(void *pSerialized);
+  int FromFileTxt(const char *pFilename);
+
+  unsigned int uNumTiles;
+  struct TileDesc *pTiles;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Time.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,109 @@
+#include "OSAPI.h"
+
+#include "Time.h"
+#include "Keyboard.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+Timer *pMiscTimer = new Timer;
+Timer *pEventTimer;
+
+
+
+
+
+
+//----- (00426317) --------------------------------------------------------
+unsigned __int64 Timer::Time()
+{
+  uint v2 = (timeGetTime() << 7) / 0x3E8;
+  if (v2 < uStartTime)
+    uStartTime = 0;
+  return v2;
+}
+
+
+
+//----- (00426349) --------------------------------------------------------
+void Timer::Pause()
+{
+  if (!bPaused)
+  {
+    uStopTime = Time();
+    bPaused = true;
+  }
+}
+
+
+//----- (00426363) --------------------------------------------------------
+void Timer::Resume()
+{
+  if (bPaused)
+  {
+    pKeyActionMap->ResetKeys();
+    bPaused = 0;
+    uStartTime = Time();
+  }
+}
+
+//----- (00426386) --------------------------------------------------------
+void Timer::TrackGameTime()
+{
+  if (!bTackGameTime)
+  {
+    uGameTimeStart = Time();
+    bTackGameTime = true;
+  }
+}
+
+
+
+//----- (004263A0) --------------------------------------------------------
+void Timer::StopGameTime()
+{
+  if (bTackGameTime)
+  {
+    bTackGameTime = 0;
+    uStartTime = Time();
+  }
+}
+
+//----- (004263B7) --------------------------------------------------------
+int Timer::Update()
+{
+  Timer *v1; // esi@1
+  unsigned int v2; // eax@2
+  signed int v3; // eax@3
+  char v4; // zf@5
+  int result; // eax@8
+
+  v1 = this;
+  do
+  {
+    v2 = Time() - v1->uStartTime;
+    v1->uTimeElapsed = v2;
+  }
+  while ( (signed int)v2 <= 0 );
+  v1->uStartTime = Time();
+  v3 = v1->uTimeElapsed;
+  if ( v3 > 32 )
+    v3 = 32;
+  v4 = v1->bPaused == 0;
+  v1->uTimeElapsed = v3;
+  if ( v4 && !v1->bTackGameTime )
+    v1->uTotalGameTimeElapsed += v3;
+  result = (v3 << 16) / 128;
+  v1->dt_in_some_format = result;
+  return result;
+}
+
+//----- (00426402) --------------------------------------------------------
+void Timer::Initialize()
+{
+  uTotalGameTimeElapsed = 0;
+  bReady = true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Time.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,47 @@
+#pragma once
+
+
+/*   61 */
+#pragma pack(push, 1)
+struct Timer
+{
+  static Timer *Create() {return new Timer;}
+
+  Timer():
+    bReady(false), bPaused(false)
+  {
+    bTackGameTime = 0;
+    uStartTime = 0;
+    uStopTime = 0;
+    uGameTimeStart = 0;
+    field_18 = 0;
+    uTimeElapsed = 0;
+    dt_in_some_format = 0;
+    uTotalGameTimeElapsed = 0;
+  }
+
+  void Initialize();
+  unsigned __int64 Time();
+  int Update();
+  void Pause();
+  void Resume();
+  void TrackGameTime();
+  void StopGameTime();
+
+  unsigned int bReady;
+  unsigned int bPaused;
+  int bTackGameTime;
+  unsigned int uStartTime;
+  unsigned int uStopTime;
+  int uGameTimeStart;
+  int field_18;
+  unsigned int uTimeElapsed;
+  int dt_in_some_format;
+  unsigned int uTotalGameTimeElapsed;
+};
+#pragma pack(pop)
+
+
+
+extern Timer *pMiscTimer;
+extern Timer *pEventTimer;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TurnEngine.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,54 @@
+#pragma once
+
+
+
+/*  299 */
+#pragma pack(push, 1)
+struct TurnBased_QueueElem
+{
+  int uPackedID;
+  int field_4;
+  int uActionLength;
+  int field_C;
+};
+#pragma pack(pop)
+
+/*  254 */
+#pragma pack(push, 1)
+struct stru262_TurnBased
+{
+  signed int _404544();
+  void _40471C();
+  signed int Start();
+  void End(bool bPlaySound);
+  void _405E14();
+  __int16 StartTurn();
+  void NextTurn();
+  int _4063A1();
+  int _406457(int a2);
+  void _40652A();
+  __int16 _4065B0();
+  __int16 _406648(unsigned int a2);
+  __int16 _40680F(int a2);
+  void _406A63();
+  void _406AFE();
+  int _406B9F();
+  bool _406D10(signed int a2);
+  void _406FA8();
+
+
+  int field_0;
+  int field_4;
+  int field_8;
+  int uActorQueueSize;
+  int field_10;
+  int uActionPointsLeft;
+  int field_18;
+  int field_1C;
+  TurnBased_QueueElem pQueue[2];
+};
+#pragma pack(pop)
+
+
+
+extern struct stru262_TurnBased *pTurnEngine;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VectorTypes.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,169 @@
+#pragma once
+
+typedef unsigned __int32 uint;
+
+#pragma pack(push, 1)
+struct Vec2_short_
+{
+  __int16 x;
+  __int16 y;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct Vec3_float_
+{
+  void Normalize();
+
+  
+  //----- (0049B32D) --------------------------------------------------------
+  static Vec3_float_ *Vec3_float_::Cross(Vec3_float_ *v1, Vec3_float_ *pOut, float x, float y, float z)
+  {
+    double v6; // st7@1
+    double v7; // st6@1
+
+    v6 = x * v1->z - z * v1->x;
+    v7 = y * v1->x - x * v1->y;
+    pOut->x = z * v1->y - y * v1->z;
+    pOut->y = v6;
+    pOut->z = v7;
+    return pOut;
+  }
+ 
+  //----- (0049B02E) --------------------------------------------------------
+  inline static float NegDot(Vec3_float_ *a1, Vec3_float_ *a2, float *a3)
+  {
+    return *a3 = -(a1->z * a2->z + a1->y * a2->y + a1->x * a2->x);
+  }
+
+  float x;
+  float y;
+  float z;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct Vec2_int_
+{
+  int x;
+  int y;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct Vec2_float_
+{
+  float x;
+  float y;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct Vec3_short_
+{
+  __int16 x;
+  __int16 y;
+  __int16 z;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct Vec3_int_
+{
+  inline Vec3_int_():
+    x(0), y(0), z(0)
+  {}
+  inline Vec3_int_(int a, int b = 0, int c = 0):
+    x(a), y(b), z(c)
+  {}
+
+  void Normalize_float();
+
+  static void __fastcall Rotate(int sDepth, int sRotY, int sRotX, Vec3_int_ v, int *outx, int *outy, int *outz);
+  static void Normalize(int *x, int *y, int *z);
+
+  int x;
+  int y;
+  int z;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct Vec4_int_
+{
+  int x;
+  int y;
+  int z;
+  int w;
+};
+#pragma pack(pop)
+
+
+
+
+
+
+/*   82 */
+#pragma pack(push, 1)
+struct Plane_int_
+{
+  Vec3_int_ vNormal;
+  int dist;
+};
+#pragma pack(pop)
+
+
+#pragma pack(push, 1)
+struct BBox_short_
+{
+  __int16 x1;
+  __int16 x2;
+  __int16 y1;
+  __int16 y2;
+  __int16 z1;
+  __int16 z2;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct BBox_int_
+{
+  int x1;
+  int x2;
+  int y1;
+  int y2;
+  int z1;
+  int z2;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct Plane_float_
+{
+  struct Vec3_float_ vNormal;
+  float dist;
+};
+#pragma pack(pop)
+
+
+
+
+/*  196 */
+#pragma pack(push, 1)
+struct Matrix3x3_float_
+{
+  union
+  {
+    struct
+    {
+      float _11; float _12; float _13;
+      float _21; float _22; float _23;
+      float _31; float _32; float _33;
+    };
+    float v[3][3];
+  };
+};
+#pragma pack(pop)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VideoPlayer.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1173 @@
+#include "OSAPI.h"
+
+#include "Bink_Smacker.h"
+
+#include "OSInfo.h"
+#include "VideoPlayer.h"
+#include "AudioPlayer.h"
+#include "Game.h"
+#include "Render.h"
+#include "Party.h"
+#include "GUIWindow.h"
+#include "Allocator.h"
+#include "Time.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+VideoPlayer *pVideoPlayer = nullptr;
+
+
+
+
+
+
+
+#pragma comment(lib, "Version.lib")
+bool GetDllVersion(const wchar_t *pDllName, uint *pMajor, uint *pMinor)
+{
+  uint uVersionSize = GetFileVersionInfoSizeW(pDllName, nullptr);
+  void *pVersionData = HeapAlloc(GetProcessHeap(), 0, uVersionSize);
+  {
+    GetFileVersionInfoW(pDllName, 0, uVersionSize, pVersionData);
+
+    VS_FIXEDFILEINFO *pInfo = nullptr;
+    UINT              uInfoSize = 0;
+    VerQueryValueW(pVersionData, L"\\", (void **)&pInfo, &uInfoSize);
+
+    if (!pMajor || !pMinor)
+    {
+      HeapFree(GetProcessHeap(), 0, pVersionData);
+      return false;
+    }
+    *pMajor = pInfo->dwFileVersionMS;
+    *pMinor = pInfo->dwFileVersionLS;
+  }
+  HeapFree(GetProcessHeap(), 0, pVersionData);
+  return true;
+}
+
+
+// 3.15.1.0:
+//      3  15   1   0
+// 0x0003000F00010000
+unsigned __int64 uBinkVersion;
+
+
+
+
+
+
+//----- (004BFE2D) --------------------------------------------------------
+_BINKBUF *VideoPlayer::CreateBinkBuffer(HWND hWindow, unsigned int uWidth, unsigned int uHeight, char a4)
+{
+  __int32 v4; // edi@3
+  _BINKBUF *v5; // esi@3
+  HRESULT v6; // eax@5
+  IDirectDrawSurface *v7; // eax@6
+  HRESULT v8; // eax@9
+  char v9; // al@11
+  DDSURFACEDESC2 v11; // [sp+Ch] [bp-108h]@7
+  DDSURFACEDESC Dst; // [sp+88h] [bp-8Ch]@3
+  unsigned int v13; // [sp+F4h] [bp-20h]@1
+  struct tagRECT Rect; // [sp+F8h] [bp-1Ch]@11
+  IDirectDrawSurface4 *v15; // [sp+108h] [bp-Ch]@7
+  IDirectDrawSurface2 *a2; // [sp+10Ch] [bp-8h]@3
+  HWND hWnd; // [sp+110h] [bp-4h]@1
+
+  v13 = uWidth;
+  hWnd = hWindow;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion >= 5u )
+  {
+    v4 = 0;
+    v15 = 0;
+
+    if (uBinkVersion == 0x0001000500150000)
+    {
+      v5 = new _BINKBUF_1_5_21_0;
+      memset(v5, 0, sizeof(_BINKBUF_1_5_21_0));
+    }
+    else if (uBinkVersion == 0x0003000000000000)
+    {
+      v5 = new _BINKBUF_3_0_0_0;
+      memset(v5, 0, sizeof(_BINKBUF_3_0_0_0));
+    }
+
+    memset(&v11, 0, 0x7Cu);
+    v11.dwSize = 124;
+    v11.dwWidth = v13;
+    v11.dwFlags = 0x1007u;                      // DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT
+    v11.ddsCaps.dwCaps = 0x4040u;               // DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY
+    v11.dwHeight = uHeight;
+    *(_QWORD *)&v11.ddpfPixelFormat.dwSize = 0x400000020ui64;// DDPF_FOURCC
+    v11.ddpfPixelFormat.dwFourCC = 0x32595559u;
+    if ( dword_6BE384_2dacceloff || pRenderer->pDirectDraw4->CreateSurface(&v11, &v15, 0) )
+    {
+      memset(&v11.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT));
+
+      v11.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+      v11.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+
+      auto hr = pRenderer->pDirectDraw4->CreateSurface(&v11, &v15, 0);
+      ErrD3D(hr, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Video.cpp:1476");
+    }
+    v5->uWidth = v11.dwWidth;
+    v5->uHeight = v11.dwHeight;
+    v5->uBinkDDSurfaceType = BinkDDSurfaceType((IDirectDrawSurface *)v15);
+    v5->field_38 = 0;
+    v7 = (IDirectDrawSurface *)v15;
+  }
+  else
+  {
+    v4 = 0;
+    a2 = 0;
+    
+
+    if (uBinkVersion == 0x0001000500150000)
+    {
+      v5 = new _BINKBUF_1_5_21_0;
+      memset(v5, 0, sizeof(_BINKBUF_1_5_21_0));
+    }
+    else if (uBinkVersion == 0x0003000000000000)
+    {
+      v5 = new _BINKBUF_3_0_0_0;
+      memset(v5, 0, sizeof(_BINKBUF_3_0_0_0));
+    }
+
+    memset(&Dst, 0, 0x6Cu);
+    Dst.dwSize = 108;
+    Dst.dwWidth = v13;
+    Dst.dwFlags = 4103;
+    Dst.ddsCaps.dwCaps = 16448;
+    Dst.dwHeight = uHeight;
+    Dst.ddpfPixelFormat.dwSize = 32;
+    Dst.ddpfPixelFormat.dwFlags = 4;
+    Dst.ddpfPixelFormat.dwFourCC = 844715353;
+    if ( dword_6BE384_2dacceloff
+      || pRenderer->pDirectDraw2->CreateSurface(&Dst, (LPDIRECTDRAWSURFACE *)&a2, 0) )
+    {
+      memset(&Dst.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT));
+
+      Dst.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+      Dst.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+
+      auto hr = pRenderer->pDirectDraw2->CreateSurface(&Dst, (LPDIRECTDRAWSURFACE *)&a2, 0);
+      ErrD3D(hr, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Video.cpp:1426");
+    }
+    v5->uWidth = Dst.dwWidth;
+    v5->uHeight = Dst.dwHeight;
+    v5->uBinkDDSurfaceType = BinkDDSurfaceType((IDirectDrawSurface *)a2);
+    v5->field_38 = 0;
+    v7 = (IDirectDrawSurface *)a2;
+  }
+  v5->pTargetDDrawSurface = v7;
+  v5->hWnd = hWnd;
+  v9 = a4;
+  v5->field_4C = v4;
+  v5->field_68 = v4;
+  v5->field_5C = v4;
+  v5->field_74 = v9 & 0x1F;
+  v5->field_78 = 1;
+  v5->field_24 = GetSystemMetrics(v4);
+  v5->field_28 = GetSystemMetrics(SM_CYSCREEN);
+  v5->field_2C = 16;
+  GetWindowRect(hWnd, &Rect);
+  v5->field_8 = Rect.right - Rect.left;
+  v5->field_C = Rect.bottom - Rect.top;
+  v5->field_1C = Rect.left;
+  v5->field_20 = Rect.top;
+  Rect.left = v4;
+  Rect.top = v4;
+  ClientToScreen(hWnd, (LPPOINT)&Rect);
+  v5->field_1C = Rect.left - v5->field_1C;
+  v5->field_20 = Rect.top - v5->field_20;
+  GetClientRect(hWnd, &Rect);
+  v5->field_30 = v5->field_8 - Rect.right;
+  v5->field_34 = v5->field_C - Rect.bottom;
+  v5->field_8 = v5->uWidth + v5->field_30;
+  v5->field_C = v5->uHeight + v5->field_34;
+  BinkBufferSetOffset(v5, v4, v4);
+  BinkBufferSetScale(v5, v5->uWidth, v5->uHeight);
+  return v5;
+}
+
+
+//----- (004C0133) --------------------------------------------------------
+bool BinkLockBuffer(_BINKBUF *_this)
+{
+  _BINKBUF *v1; // esi@1
+  IDirectDrawSurface *v2; // edi@5
+  DWORD v4; // eax@8
+  DWORD v5; // eax@8
+  IDirectDrawSurface4 *v6; // edi@11
+  LPVOID v7; // eax@14
+
+  v1 = _this;
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion >= 5u )
+  {
+  DDSURFACEDESC2 v8; // [sp+Ch] [bp-7Ch]@4
+    if ( _this->pTargetDDrawSurface )
+    {
+      memset(&v8, 0, 0x7Cu);
+      v8.dwSize = 124;
+      while ( 1 )
+      {
+        v6 = (IDirectDrawSurface4 *)v1->pTargetDDrawSurface;
+        if ( !v6->Lock(0, &v8, 1u, 0) )
+          break;
+        
+        if (uBinkVersion < 0x0003000000000000)
+          BYTE3(v1->uBinkDDSurfaceType) |= 0x80u;
+        else
+          BYTE3(v1->uBinkDDSurfaceType) |= 0x04;
+
+        if ( v6->Restore() )
+          return 0;
+      }
+      v7 = v8.lpSurface;
+      v1->pDDrawSurfaceData_ = v8.lpSurface;
+      v1->pDDrawSurfaceData = v7;
+      v5 = v8.lPitch;
+      goto LABEL_15;
+    }
+  }
+  else
+  {
+  DDSURFACEDESC v8; // [sp+Ch] [bp-7Ch]@4
+    if ( _this->pTargetDDrawSurface )
+    {
+      memset(&v8.lPitch, 0, 0x6Cu);
+      v8.lPitch = 108;
+      while ( 1 )
+      {
+        v2 = v1->pTargetDDrawSurface;
+        if ( !v2->Lock(0, (LPDDSURFACEDESC)&v8.lPitch, 1u, 0) )
+          break;
+        
+        if (uBinkVersion < 0x0003000000000000)
+          __asm int 3;
+        else
+          BYTE3(v1->uBinkDDSurfaceType) |= 4u;
+
+        if ( v2->Restore() )
+          return 0;
+      }
+      v4 = (DWORD)v8.lpSurface;
+      v1->pDDrawSurfaceData_ = (void *)v8.lpSurface;
+      v1->pDDrawSurfaceData = (void *)v4;
+      v5 = v8.dwReserved;
+LABEL_15:
+      v1->uDDrawSurfacePitch = v5;
+      return 1;
+    }
+  }
+  return 1;
+}
+
+//----- (004C01FB) --------------------------------------------------------
+void BinkUnlockBuffer(_BINKBUF *_this)
+{
+  _BINKBUF *v1; // esi@1
+  IDirectDrawSurface *v2; // eax@1
+
+  v1 = _this;
+  v2 = _this->pTargetDDrawSurface;
+  if ( v2 )
+  {
+    v2->Unlock(0);
+    v1->uDDrawSurfacePitch = 0;
+    v1->pDDrawSurfaceData = 0;
+
+    if (uBinkVersion < 0x0003000000000000)
+      BYTE3(_this->uBinkDDSurfaceType) &= 0x7F;
+    else
+      BYTE3(_this->uBinkDDSurfaceType) &= 0xFB;
+  }
+}
+//----- (004BF794) --------------------------------------------------------
+void __cdecl ShowIntroVideo_and_LoadingScreen()
+{
+  RGBTexture tex; // [sp+Ch] [bp-30h]@1
+  unsigned int uTrackStartMS; // [sp+34h] [bp-8h]@8
+  unsigned int uTrackEndMS; // [sp+38h] [bp-4h]@8
+
+  pVideoPlayer->bStopBeforeSchedule = false;
+  pVideoPlayer->field_40 = 0;
+  bGameoverLoop = 1;
+  if ( !bNoVideo )
+  {
+    bNoVideo = 0;
+    pRenderer->PresentBlackScreen();
+    pGame->pCShow->PlayMovie(MOVIE_3DOLogo, 1);
+    if ( !pVideoPlayer->bStopBeforeSchedule )
+    {
+      pGame->pCShow->PlayMovie(MOVIE_NWCLogo, 1);
+      if ( !pVideoPlayer->bStopBeforeSchedule )
+      {
+        pGame->pCShow->PlayMovie(MOVIE_JVC, 1);
+        if ( !pVideoPlayer->bStopBeforeSchedule )
+          pGame->pCShow->PlayMovie(MOVIE_Intro, 1);
+      }
+    }
+  }
+  tex.Load("mm6title.pcx", 2);
+  pRenderer->BeginScene();
+  pRenderer->DrawTextureRGB(0, 0, &tex);
+  free(tex.pPixels);
+  tex.pPixels = 0;
+  MainMenuUI_LoadFontsAndSomeStuff();
+  DrawCopyrightWindow();
+  pRenderer->EndScene();
+  pRenderer->Present();
+  if (!bNoSound && pAudioPlayer->hAILRedbook )
+  {
+    pAudioPlayer->SetMusicVolume((signed __int64)(pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0));
+    AIL_redbook_stop(pAudioPlayer->hAILRedbook);
+    AIL_redbook_track_info(pAudioPlayer->hAILRedbook, 0xE, &uTrackStartMS, &uTrackEndMS);
+    AIL_redbook_play(pAudioPlayer->hAILRedbook, uTrackStartMS + 1, uTrackEndMS);
+  }
+  bGameoverLoop = 0;
+}
+
+
+
+
+//----- (004BE70E) --------------------------------------------------------
+void __fastcall VideoPlayer::MovieLoop(const char *pMovieName, int a2, int ScreenSizeFlag, int a4)
+{
+  int v4; // ebp@1
+  const char *pName; // edi@1
+  MSG Msg; // [sp+Ch] [bp-1Ch]@12
+
+  v4 = a2;
+  pName = pMovieName;
+  if ( !(dword_6BE364_game_settings_1 & 0x44) )
+  {
+    if ( a2 == 2 )
+      v4 = 0;
+    ShowCursor(0);
+    pVideoPlayer->OpenMovie(pName, 0, ScreenSizeFlag);
+    pVideoPlayer->bPlayingMovie = 1;
+    pVideoPlayer->field_44 = v4;
+    if ( pRenderer->pRenderD3D )
+    {
+      pRenderer->ClearTarget(0);
+    }
+    else
+    {
+      pRenderer->BeginScene();
+      pRenderer->ClearTarget(0);
+      pRenderer->EndScene();
+    }
+    pCurrentScreen = 16; //îêíî âèäåî ðîëèêà 
+    if ( pVideoPlayer->uMovieFormat == 2 )
+    {
+      if ( pVideoPlayer->pBinkMovie )
+      {
+        pVideoPlayer->BinkDrawFrame(pVideoPlayer->hWindow, v4, ScreenSizeFlag);
+        while ( pVideoPlayer->pBinkMovie )
+        {
+          if ( pVideoPlayer->bStopBeforeSchedule )
+            break;
+          while ( PeekMessageA(&Msg, 0, 0, 0, 1) )
+          {
+            if ( Msg.message == 18 )
+              Game_DeinitializeAndTerminate(0);
+            if ( Msg.message == 15 )
+              break;
+            TranslateMessage(&Msg);
+            DispatchMessageA(&Msg);
+          }
+          GUI_MainMenuMessageProc();
+          if ( !pVideoPlayer->pBinkMovie )
+            break;
+          if ( !BinkWait(pVideoPlayer->pBinkMovie) && !pVideoPlayer->bStopBeforeSchedule )
+            pVideoPlayer->BinkDrawFrame(pVideoPlayer->hWindow, v4, ScreenSizeFlag);
+        }
+      }
+      if ( pVideoPlayer->bStopBeforeSchedule == 1 )
+        Sleep(0x3E8u);
+    }
+    else
+    {
+      if ( pVideoPlayer->uMovieFormat == 1 )
+      {
+        if ( pVideoPlayer->pSmackerMovie )
+        {
+          pVideoPlayer->SmackDrawFrame(pVideoPlayer->hWindow, v4, ScreenSizeFlag);
+          while ( pVideoPlayer->pSmackerMovie )
+          {
+            if ( pVideoPlayer->bStopBeforeSchedule )
+              break;
+            while ( PeekMessageW(&Msg, 0, 0, 0, 1) )
+            {
+              if (Msg.message == WM_QUIT)
+                Game_DeinitializeAndTerminate(0);
+              if (Msg.message == WM_PAINT)
+                break;
+              TranslateMessage(&Msg);
+              DispatchMessageW(&Msg);
+            }
+            GUI_MainMenuMessageProc();
+            if ( !pVideoPlayer->pSmackerMovie )
+              break;
+            if ( !SmackWait(pVideoPlayer->pSmackerMovie) && !pVideoPlayer->bStopBeforeSchedule )
+              pVideoPlayer->SmackDrawFrame(pVideoPlayer->hWindow, v4, ScreenSizeFlag);
+          }
+        }
+      }
+    }
+    if ( a4 == 1 )
+      pCurrentScreen = 0;
+    pVideoPlayer->bPlayingMovie = 0;
+    ShowCursor(1);
+    if ( pCurrentScreen == 16 )//îêíî âèäåî ðîëèêà 
+      pCurrentScreen = 0;
+  }
+}
+
+
+
+
+//----- (004BE95A) --------------------------------------------------------
+unsigned int VideoPlayer::SmackCheckSurfaceFromat()
+{
+  DDPIXELFORMAT a2; // [sp+0h] [bp-20h]@1
+
+  a2.dwSize = 32;
+  a2.dwFlags = 64;
+  pRenderer->GetTargetPixelFormat(&a2);
+  if ( a2.dwRGBBitCount != 8 )
+  {
+    if ( a2.dwRBitMask == 0xF800 )
+    {
+      if ( a2.dwGBitMask == 0x7E0 && a2.dwBBitMask == 0x1F )
+        return 0xC0000000u;
+    }
+    else
+    {
+      if ( a2.dwRBitMask == 0x7C00
+        && a2.dwGBitMask == 0x3E0
+        && a2.dwBBitMask == 0x1F )
+        return 0x80000000u;
+    }
+    MessageBoxA(0, "Unsupported pixel format.", "Smacker Error", 0);
+  }
+  return 0;
+}
+
+//----- (004BE9D8) --------------------------------------------------------
+void VideoPlayer::Initialize()
+{
+  DWORD NumberOfBytesRead; // [sp+10h] [bp-4h]@9
+    
+  uint uBinkVersionMajor = -1,
+       uBinkVersionMinor = -1;
+  GetDllVersion(L"BINKW32.DLL", &uBinkVersionMajor, &uBinkVersionMinor);
+  uBinkVersion = (unsigned __int64)uBinkVersionMajor << 32 | uBinkVersionMinor;
+
+  strcpy(pTmpBuf, "anims\\might7.vid");
+  hMightVid = CreateFileW(L"anims\\might7.vid", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0x8000080u, 0);
+  if ( hMightVid == INVALID_HANDLE_VALUE )
+  {
+    sprintf(pTmpBuf2, "Can't open file - anims\\%s.smk", pTmpBuf);
+    MessageBoxA(0, pTmpBuf2, "Video File Error", 0);
+    return;
+  }
+  strcpy(pTmpBuf, "anims\\magic7.vid");
+  hMagicVid = CreateFileW(L"anims\\magic7.vid", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0x8000080u, 0);
+  if ( hMagicVid == INVALID_HANDLE_VALUE )
+  {
+    if ( !bCanLoadFromCD )
+      {
+       sprintf(pTmpBuf2, "Can't open file - anims\\%s.smk", pTmpBuf);
+       MessageBoxA(0, pTmpBuf2, "Video File Error", 0);
+       return;
+	  }
+    sprintf(pTmpBuf2, "%c:\\%s", (unsigned __int8)cMM7GameCDDriveLetter, pTmpBuf);
+    hMagicVid = CreateFileA(pTmpBuf2, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0x8000080u, 0);
+    if ( hMagicVid == (HANDLE)INVALID_HANDLE_VALUE )
+    {
+	  sprintf(pTmpBuf2, "Can't open file - %s", pTmpBuf);
+      MessageBoxA(0, pTmpBuf2, "Video File Error", 0);
+      return;
+    }
+  }
+  ReadFile(hMightVid, &uNumMightVideoHeaders, 4, &NumberOfBytesRead, 0);
+  ReadFile(hMagicVid, &uNumMagicVideoHeaders, 4, &NumberOfBytesRead, 0);
+  pMagicVideoHeaders = 0;
+  pMightVideoHeaders = 0;
+  pMightVideoHeaders = (MovieHeader *)pAllocator->AllocNamedChunk(0, 44 * uNumMightVideoHeaders + 2, 0);
+  pMagicVideoHeaders = (MovieHeader *)pAllocator->AllocNamedChunk(pMagicVideoHeaders, 44 * uNumMagicVideoHeaders + 2, 0);
+  ReadFile(hMightVid, pMightVideoHeaders, 44 * uNumMightVideoHeaders, &NumberOfBytesRead, 0);
+  ReadFile(hMagicVid, pMagicVideoHeaders, 44 * uNumMagicVideoHeaders, &NumberOfBytesRead, 0);
+}
+
+//----- (004BEB41) --------------------------------------------------------
+void VideoPlayer::Prepare()
+{
+  VideoPlayer *pVideoPlayer; // esi@1
+  IDirectDrawSurface *v2; // [sp-4h] [bp-Ch]@5
+
+  pVideoPlayer = this;
+  pEventTimer->Pause();
+  pVideoPlayer->bStopBeforeSchedule = 0;
+  if ( pAudioPlayer->hAILRedbook )
+    AIL_redbook_pause(pAudioPlayer->hAILRedbook);
+  pVideoPlayer->field_54 = 1;
+  pVideoPlayer->hWindow = hWnd;
+  pVideoPlayer->pSmackerMovie = 0;
+  pVideoPlayer->pSmackerBuffer = 0;
+  pVideoPlayer->pBinkMovie = 0;
+  pVideoPlayer->pBinkBuffer = 0;
+  pVideoPlayer->bPlayingMovie = 0;
+  pVideoPlayer->bFirstFrame = 0;
+  pVideoPlayer->bUsingSmackerMMX = SmackUseMMX(1);
+  BinkSetSoundSystem(BinkOpenMiles, pAudioPlayer->hDigDriver);
+  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion >= 5 )
+    v2 = (IDirectDrawSurface*)pRenderer->pBackBuffer4;
+  else
+    v2 = (IDirectDrawSurface*)pRenderer->pBackBuffer2;
+  pVideoPlayer->uBinkDirectDrawSurfaceType = BinkDDSurfaceType(v2);
+  _flushall();
+}
+
+
+//----- (004BEBD7) --------------------------------------------------------
+void VideoPlayer::Unload()
+{
+  VideoPlayer *pVideoPlayer; // esi@1
+  _BINK *pBinkMovie; // eax@1
+  _BINKBUF *pBinkBuffer; // eax@3
+  _SMACK *pSmackerMovie; // eax@5
+
+  pVideoPlayer = this;
+  pBinkMovie = this->pBinkMovie;
+  if ( pBinkMovie )
+  {
+    BinkPause(pBinkMovie, 1);
+    Sleep(300);
+    BinkClose(pVideoPlayer->pBinkMovie);
+    pVideoPlayer->pBinkMovie = 0;
+  }
+  pBinkBuffer = pVideoPlayer->pBinkBuffer;
+  if ( pBinkBuffer )
+  {
+    pBinkBuffer->pTargetDDrawSurface->Release();
+    pVideoPlayer->pBinkBuffer->pTargetDDrawSurface = 0;
+    free(pVideoPlayer->pBinkBuffer);
+    pVideoPlayer->pBinkBuffer = 0;
+  }
+  pSmackerMovie = pVideoPlayer->pSmackerMovie;
+  if ( pSmackerMovie )
+  {
+    SmackSoundOnOff(pSmackerMovie, 0);
+    SmackClose(pVideoPlayer->pSmackerMovie);
+    pVideoPlayer->pSmackerMovie = 0;
+  }
+  if ( pVideoPlayer->pSmackerBuffer )
+  {
+    SmackBufferClose(pVideoPlayer->pSmackerBuffer);
+    pVideoPlayer->pSmackerBuffer = 0;
+  }
+  if ( pVideoPlayer->pSmackMovieBlit )
+  {
+    SmackBlitClose(pVideoPlayer->pSmackMovieBlit);
+    pVideoPlayer->pSmackMovieBlit = 0;
+  }
+  pVideoPlayer->field_54 = 0;
+  pVideoPlayer->uMovieFormat = 0;
+  pVideoPlayer->dword_0000A0 = 0;
+  memset(pVideoPlayer->pCurrentMovieName, 0, 0x40);
+  if ( pAudioPlayer->hAILRedbook && !bGameoverLoop )
+    AIL_redbook_resume(pAudioPlayer->hAILRedbook);
+  pEventTimer->Resume();
+}
+
+//----- (004BECD5) --------------------------------------------------------
+void VideoPlayer::FastForwardToFrame(unsigned int uDstFrameNum)
+{
+  VideoPlayer *v2; // esi@1
+  unsigned int v3; // eax@1
+
+  v2 = this;
+  v3 = this->uMovieFormat;
+  if ( v3 == 2 )
+  {
+    if (uDstFrameNum)
+    {
+      int *pCurrentFrame = uBinkVersion == 0x0001000500150000 ? &((_BINK_1_5_21_0 *)pBinkMovie)->uCurrentFrame :
+                           uBinkVersion == 0x0003000000000000 ? &((_BINK_3_0_0_0  *)pBinkMovie)->uCurrentFrame :
+                           nullptr;
+      while (*pCurrentFrame < uDstFrameNum)
+      {
+        BinkDoFrame(pBinkMovie);
+        BinkNextFrame(pBinkMovie);
+      }
+    }
+  }
+  else
+  {
+    if ( v3 != 1 )
+      return;
+    SmackSoundOnOff(this->pSmackerMovie, 0);
+    if (uDstFrameNum)
+    {
+      while ( v2->pSmackerMovie->FrameNum < uDstFrameNum)
+      {
+        SmackDoFrame(v2->pSmackerMovie);
+        SmackNextFrame(v2->pSmackerMovie);
+      }
+    }
+  }
+  Unload();
+}
+
+
+//----- (004BED4F) --------------------------------------------------------
+void VideoPlayer::BinkDrawFrame(HWND hWnd, int a3, int a4)
+{
+  //VideoPlayer *v4; // esi@1
+  _BINKBUF *v5; // eax@5
+  LONG v6; // edx@6
+  int v7; // ecx@6
+  LONG v8; // edx@6
+  struct tagRECT a3a; // [sp+8h] [bp-20h]@10
+  struct tagRECT a1; // [sp+18h] [bp-10h]@6
+
+  //v4 = this;
+  if ( this->pBinkMovie && this->pBinkBuffer )
+  {
+    BinkDoFrame(pBinkMovie);
+    BinkGetRects(pBinkMovie, pBinkBuffer->uBinkDDSurfaceType);
+    if ( BinkLockBuffer(pBinkBuffer) )
+    {
+      BinkCopyToBuffer(pBinkMovie, pBinkBuffer->pDDrawSurfaceData, pBinkBuffer->uDDrawSurfacePitch, pBinkBuffer->uHeight,
+        0, 0, pBinkBuffer->uBinkDDSurfaceType);
+      BinkUnlockBuffer(pBinkBuffer);
+    }
+    v5 = pBinkBuffer;
+    if ( pRenderer->bWindowMode )
+    {
+      v6 = v5->uRectX;
+      a1.left = v6;
+      a1.top = v5->uRectY;
+      v7 = v6 + v5->uWidth;
+      a1.right = v6 + v5->uWidth;
+      v8 = a1.top + v5->uHeight;
+    }
+    else
+    {
+      a1.left = 0;
+      a1.top = 0;
+      v7 = v5->uWidth;
+      a1.right = v5->uWidth;
+      v8 = v5->uHeight;
+    }
+    a1.bottom = v8;
+    if ( a4 )
+    {
+      a1.right = v5->uWidth + v7;
+      a1.bottom = v5->uHeight + v8;
+    }
+    a3a.left = 0;
+    a3a.top = 0;
+    a3a.right = v5->uWidth;
+    a3a.bottom = v5->uHeight;
+    pRenderer->BltToFront(&a1, v5->pTargetDDrawSurface, &a3a, 0x1000000u);
+    
+    
+    int *pCurrentFrame = uBinkVersion == 0x0001000500150000 ? &((_BINK_1_5_21_0 *)pBinkMovie)->uCurrentFrame :
+                         uBinkVersion == 0x0003000000000000 ? &((_BINK_3_0_0_0  *)pBinkMovie)->uCurrentFrame:
+                         nullptr;
+    int *pNumFrames = uBinkVersion == 0x0001000500150000 ? &((_BINK_1_5_21_0 *)pBinkMovie)->uNumFrames :
+                      uBinkVersion == 0x0003000000000000 ? &((_BINK_3_0_0_0  *)pBinkMovie)->uNumFrames :
+                      nullptr;
+
+    if (*pCurrentFrame != *pNumFrames - 1 || bLoopPlaying)
+      BinkNextFrame(pBinkMovie);
+    else
+      Unload();
+  }
+}
+
+
+
+//----- (004BEE6B) --------------------------------------------------------
+void VideoPlayer::SmackDrawFrame(HWND hWnd, int a3, int a4)
+{
+  VideoPlayer *v4; // esi@1
+  _SMACK *v5; // eax@3
+  unsigned int v6; // eax@5
+  char v7; // zf@5
+  int v8; // eax@11
+  _SMACK *v9; // eax@13
+  _SMACK *v10; // eax@16
+  _SMACK *v11; // eax@20
+  unsigned int v12; // [sp-1Ch] [bp-34h]@7
+  LONG v13; // [sp-18h] [bp-30h]@7
+  LONG v14; // [sp-14h] [bp-2Ch]@7
+  signed int v15; // [sp-10h] [bp-28h]@7
+  signed int v16; // [sp-Ch] [bp-24h]@7
+  signed int v17; // [sp-8h] [bp-20h]@7
+  struct tagPOINT Point; // [sp+8h] [bp-10h]@7
+  unsigned short *pOutSurface; // [sp+10h] [bp-8h]@5
+  unsigned int uPixelsPerRow; // [sp+14h] [bp-4h]@5
+
+  v4 = this;
+  if ( !pRenderer->bWindowMode || GetFocus() == hWnd )
+  {
+    v5 = v4->pSmackerMovie;
+    if ( v5->NewPalette )
+      SmackBlitSetPalette(v4->pSmackMovieBlit, v5->Palette, v5->PalType);
+    SmackDoFrame(v4->pSmackerMovie);
+    pRenderer->LockFrontBuffer((void **)&pOutSurface, &uPixelsPerRow);
+    v6 = 2 * uPixelsPerRow;
+    v7 = v4->bFirstFrame == 0;
+    uPixelsPerRow *= 2;
+    if ( !v7 )
+    {
+      if ( pRenderer->bWindowMode )
+      {
+        Point.y = 0;
+        Point.x = 0;
+        ClientToScreen(hWnd, &Point);
+        v17 = -1;
+        v16 = 480;
+        v15 = 640;
+        v14 = Point.y;
+        v13 = Point.x;
+        v12 = uPixelsPerRow;
+      }
+      else
+      {
+        v17 = -1;
+        v16 = 480;
+        v15 = 640;
+        v14 = 0;
+        v13 = 0;
+        v12 = v6;
+      }
+      SmackBlitClear(v4->pSmackMovieBlit, pOutSurface, v12, v13, v14, v15, v16, v17);
+      v4->bFirstFrame = 0;
+    }
+    pRenderer->RestoreFrontBuffer();
+    if ( pRenderer->bWindowMode )
+    {
+      Point.y = 0;
+      Point.x = 0;
+      ClientToScreen(hWnd, &Point);
+      v8 = SmackToBufferRect(v4->pSmackerMovie, 0);
+      if ( a4 )
+      {
+        while ( v8 )
+        {
+          v9 = v4->pSmackerMovie;
+          SmackBlit(
+            v4->pSmackMovieBlit,
+            pOutSurface,
+            uPixelsPerRow,
+            v9->LastRectx + Point.x / 2,
+            a3 + v9->LastRecty + Point.y / 2,
+            v4->pSomeSmackerBuffer,
+            v9->Width,
+            v9->LastRectx,
+            v9->LastRecty,
+            v9->LastRectw,
+            v9->LastRecth);
+          v8 = SmackToBufferRect(v4->pSmackerMovie, 0);
+        }
+      }
+      else
+      {
+        while ( v8 )
+        {
+          v10 = v4->pSmackerMovie;
+          SmackBlit(v4->pSmackMovieBlit, pOutSurface, uPixelsPerRow, Point.x + v10->LastRectx, a3 + Point.y + v10->LastRecty,
+            v4->pSomeSmackerBuffer, v10->Width, v10->LastRectx, v10->LastRecty, v10->LastRectw, v10->LastRecth);
+          v8 = SmackToBufferRect(v4->pSmackerMovie, 0);
+        }
+      }
+    }
+    else
+    {
+      while ( SmackToBufferRect(v4->pSmackerMovie, 0) )
+      {
+        v11 = v4->pSmackerMovie;
+        SmackBlit(v4->pSmackMovieBlit, pOutSurface, uPixelsPerRow, v11->LastRectx, a3 + v11->LastRecty, v4->pSomeSmackerBuffer,
+          v11->Width, v11->LastRectx, v11->LastRecty, v11->LastRectw, v11->LastRecth);
+      }
+    }
+    pRenderer->UnlockFrontBuffer();
+    if ( v4->pSmackerMovie->FrameNum != v4->pSmackerMovie->Frames - 1 || v4->bLoopPlaying )
+      SmackNextFrame(v4->pSmackerMovie);
+    else
+      Unload();
+  }
+}
+// 4D83D8: using guessed type int __stdcall SmackBlitSetPalette(int, int, int);
+// 4D83DC: using guessed type int __stdcall SmackBlitClear(int, int, int, int, int, int, int, int);
+// 4D83E0: using guessed type int __stdcall SmackToBufferRect(int, int);
+// 4D83E4: using guessed type int __stdcall SmackDoFrame(int);
+// 4D83E8: using guessed type int __stdcall SmackNextFrame(int);
+// 4D8404: using guessed type int __stdcall SmackBlit(int, int, int, int, int, int, int, int, int, int, int);
+
+//----- (004BF08B) --------------------------------------------------------
+void VideoPlayer::SmackUpdatePalette(HWND hWnd)
+{
+  VideoPlayer *v2; // esi@1
+  unsigned __int16 *v3; // ebx@1
+  unsigned int v4; // edi@1
+  unsigned int v5; // eax@1
+  _SMACK *v6; // eax@1
+
+  v2 = this;
+  pRenderer->BeginScene();
+  v3 = pRenderer->pTargetSurface;
+  v4 = pRenderer->uTargetSurfacePitch;
+  v5 = SmackCheckSurfaceFromat();
+  SmackToBuffer(v2->pSmackerMovie, 8, 8, 2 * v4, pRenderer->field_14, v3, v5);
+  v6 = v2->pSmackerMovie;
+  if ( v6->NewPalette )
+  {
+    SmackBufferNewPalette((long)pSmackerBuffer, (long)v6->Palette, LOWORD(v6->PalType));
+    SmackColorRemapWithTrans(
+      (long)pSmackerMovie,
+      (long)pSmackerBuffer->Palette,
+      (long)pSmackerBuffer->MaxPalColors,
+      (long)pSmackerBuffer->PalType,
+      1000);
+  }
+  SmackDoFrame(v2->pSmackerMovie);
+  if ( v2->pSmackerMovie->FrameNum != v2->pSmackerMovie->Frames - 1 || v2->bLoopPlaying )
+    SmackNextFrame(v2->pSmackerMovie);
+  else
+    Unload();
+  pRenderer->EndScene();
+}
+
+
+
+
+
+//----- (004BF141) --------------------------------------------------------
+_BINK *VideoPlayer::OpenBink(const char *pName)
+{
+  //VideoPlayer *v2; // esi@1
+  signed int v3; // edi@1
+  int v4; // ebx@2
+  signed int v5; // edi@5
+  int v6; // ebx@6
+  HANDLE v8; // [sp-8h] [bp-18h]@10
+  unsigned int v9; // [sp-4h] [bp-14h]@10
+
+  for (uint i = 0; i < uNumMightVideoHeaders; ++i)
+    if (!strcmpi(pName, pMightVideoHeaders[i].pVideoName))
+    {
+      SetFilePointer(hMightVid, pMightVideoHeaders[i].uFileOffset, 0, FILE_BEGIN);
+
+      if (uBinkVersion < 0x0003000000000000)
+        return BinkOpen(hMightVid, 0x8800000);
+      else
+        return BinkOpen(hMightVid, 0x82000000);
+    }
+
+  for (uint i = 0; i < uNumMagicVideoHeaders; ++i)
+    if (!strcmpi(pName, pMagicVideoHeaders[i].pVideoName))
+    {
+      SetFilePointer(hMagicVid, pMagicVideoHeaders[i].uFileOffset, 0, FILE_BEGIN);
+
+      if (uBinkVersion < 0x0003000000000000)
+        return BinkOpen(hMagicVid, 0x8800000);
+      else
+        return BinkOpen(hMagicVid, 0x82000000);
+    }
+
+  return nullptr;
+}
+//----- (004BF1E6) --------------------------------------------------------
+_SMACK *VideoPlayer::OpenSmack(const char *pFilename)
+{
+  VideoPlayer *pVideoPlayer; // esi@1
+  signed int v3; // edi@1
+  int v4; // ebx@2
+  signed int v5; // edi@5
+  //int v6; // ebx@6
+  //HANDLE v8; // [sp-Ch] [bp-1Ch]@10
+  //unsigned int v9; // [sp-8h] [bp-18h]@10
+  //signed int v10; // [sp-4h] [bp-14h]@10
+
+  pVideoPlayer = this;
+  if ( (signed int)this->uNumMightVideoHeaders > 0 )
+  {
+	for ( v3 = 0; v3 < (signed int)pVideoPlayer->uNumMightVideoHeaders; ++v3)
+    {
+      v4 = _strcmpi(pVideoPlayer->pMightVideoHeaders[v3].pVideoName, pFilename);
+	  if ( !v4 )
+	  {
+	    SetFilePointer(pVideoPlayer->hMightVid, pVideoPlayer->pMightVideoHeaders[v3].uFileOffset, 0, 0);
+        return SmackOpen(pVideoPlayer->hMightVid, 0x7140, -1);
+	  }
+    }
+  }
+  v5 = 0;
+  if ( (signed int)pVideoPlayer->uNumMagicVideoHeaders > 0 )
+  {
+    while ( _strcmpi(pVideoPlayer->pMagicVideoHeaders[v5].pVideoName, pFilename) )
+    {
+      ++v5;
+      if ( v5 >= (signed int)pVideoPlayer->uNumMagicVideoHeaders )
+        return 0;
+    }
+    SetFilePointer(pVideoPlayer->hMagicVid, pVideoPlayer->pMagicVideoHeaders[v5].uFileOffset, 0, 0);
+    return SmackOpen(pVideoPlayer->hMagicVid, 0x7140, -1);
+  }
+  return 0;
+}
+
+//----- (004BF28F) --------------------------------------------------------
+void VideoPlayer::_4BF28F(const char *pMovieName, unsigned int a3_1)
+{
+  VideoPlayer *v3; // esi@1
+  std::string *v4; // ecx@3
+  _SMACK *v5; // eax@4
+  _SMACK *v6; // eax@7
+  int v7; // eax@7
+  int v8; // ecx@7
+  unsigned int v9; // ebx@8
+  unsigned int v10; // eax@8
+  signed __int64 v11; // qax@9
+  char *v12; // [sp-20h] [bp-54h]@3
+  int v13; // [sp-1Ch] [bp-50h]@3
+  std::string v14; // [sp-18h] [bp-4Ch]@3
+  const char *v15; // [sp-8h] [bp-3Ch]@3
+  int v16; // [sp-4h] [bp-38h]@3
+  char Str2[0x30]; // [sp+Ch] [bp-28h]@4
+  std::string *v18; // [sp+3Ch] [bp+8h]@3
+  std::string *v19; // [sp+3Ch] [bp+8h]@5
+  unsigned __int16 *v20; // [sp+3Ch] [bp+8h]@8
+
+  v3 = this;
+  if ( !this->field_54 )
+  {
+    Prepare();
+    v3->bLoopPlaying = a3_1;
+    __debugbreak();  // VideoPlayer is larger than this
+    if ( v3[1].pVideoFrame.pName[0] == 1 )
+    {
+      v15 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Video.cpp:925";
+      v12 = "Unsupported Bink playback!";
+LABEL_6:
+    MessageBoxA(nullptr, v12, v15, 0);
+      return;
+    }
+    sprintf(Str2, "%s.smk", pMovieName);
+    v5 = OpenSmack(Str2);
+    v3->pSmackerMovie = v5;
+    if ( !v5 )
+    {
+      v3->Unload();
+      sprintf(pTmpBuf, "Can't load %s", &Str2);
+      v15 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Video.cpp:937";
+      v12 = pTmpBuf;
+      goto LABEL_6;
+    }
+    v16 = (int)pMovieName;
+    v3->uMovieFormat = 1;
+    strcpy(v3->pCurrentMovieName, (const char *)v16);
+    v6 = v3->pSmackerMovie;
+    v3->dword_0000A0 = 1;
+    v7 = SmackBufferOpen(v3->hWindow, 4, LOWORD(v6->Width), LOWORD(v6->Height), LOWORD(v6->Width), LOWORD(v6->Height));
+    v3->pSmackerBuffer = (_SMACKBUF *)v7;
+    if ( v7 )
+    {
+      pRenderer->BeginScene();
+      v9 = pRenderer->uTargetSurfacePitch;
+      v20 = pRenderer->pTargetSurface;
+      v10 = SmackCheckSurfaceFromat();
+      SmackToBuffer(v3->pSmackerMovie, 8, 8, 2 * v9, pRenderer->field_14, v20, v10);
+      pRenderer->EndScene();
+    }
+    v16 = 32767;
+    v11 = (signed __int64)(pSoundVolumeLevels[(char)uSoundVolumeMultiplier] * 32767.0);
+    SmackVolumePan(v8, HIDWORD(v11), v3->pSmackerMovie, 1040384, v11, 32767);
+  }
+}
+
+//----- (004BF3F9) --------------------------------------------------------
+bool VideoPlayer::AnyMovieLoaded()
+{
+  return pSmackerMovie || pBinkMovie;
+}
+
+//----- (004BF411) --------------------------------------------------------
+void VideoPlayer::OpenMovie(const char *pFilename, unsigned int bLoop, int a4)
+{
+  VideoPlayer *pVideoPlayer; // esi@1
+  _BINK *pVideoOpen; // eax@2
+  _SMACK *v6; // eax@3
+  _BINK *pBinkMovie; // eax@5
+  _SMACK *v8; // eax@7
+  char *v9; // eax@7
+  unsigned int v10; // eax@11
+  _SMACKBLIT *v11; // eax@14
+  const char *v12; // [sp-4h] [bp-38h]@8
+  char pVideoName[120]; // [sp+Ch] [bp-28h]@2
+
+  pVideoPlayer = this;
+  if ( !this->field_54 )
+  {
+    Prepare();
+    pVideoPlayer->bLoopPlaying = bLoop;
+    sprintf(pVideoName, "%s.bik", pFilename);
+    pVideoOpen = OpenBink(pVideoName);
+    pVideoPlayer->pBinkMovie = pVideoOpen;
+    if ( pVideoOpen )
+    {
+      pVideoPlayer->uMovieFormat = 2;
+      strcpy(pVideoPlayer->pCurrentMovieName, pFilename);
+      pBinkMovie = pVideoPlayer->pBinkMovie;
+      pVideoPlayer->dword_0000A0 = 1;
+      if ( pBinkMovie )
+        pVideoPlayer->pBinkBuffer = CreateBinkBuffer(pVideoPlayer->hWindow, pBinkMovie->uWidth, pBinkMovie->uHeight, 0);
+    }
+    else
+    {
+      Unload();
+      sprintf(pVideoName, "%s.smk", pFilename);
+      v6 = OpenSmack(pVideoName);
+      pVideoPlayer->pSmackerMovie = v6;
+      if ( !v6 )
+      {
+        Unload();
+        sprintf(pVideoName, "Can't load file - anims\\%s.smk", pFilename);
+        MessageBoxA(0, pVideoName, "Smacker Error", 0);
+        return;
+      }
+      pVideoPlayer->uMovieFormat = 1;
+      strcpy(pVideoPlayer->pCurrentMovieName, pFilename);
+      v8 = pVideoPlayer->pSmackerMovie;
+      pVideoPlayer->dword_0000A0 = 2;
+      v9 = (char *)malloc(v8->Width * v8->Height);
+      pVideoPlayer->pSomeSmackerBuffer = v9;
+      if ( !v9 )
+      {
+        Unload();
+        v12 = "Can't allocate memory for buffer";
+        sprintf(pVideoName, v12);
+		MessageBoxA(0, pVideoName, "Smacker Error", 0);
+        return;
+      }
+      SmackToBuffer(pVideoPlayer->pSmackerMovie, 0, 0, pVideoPlayer->pSmackerMovie->Width, pVideoPlayer->pSmackerMovie->Height, v9, 0);
+      if ( a4 )
+      {
+        if ( (unsigned int)uCPUSpeed < 165 )
+        {
+          v10 = SmackCheckSurfaceFromat() | 2;
+        }
+        else
+        {
+          v10 = SmackCheckSurfaceFromat();
+          LOBYTE(v10) = v10 | 6;
+        }
+      }
+      else
+      {
+        v10 = SmackCheckSurfaceFromat();
+      }
+      v11 = SmackBlitOpen(v10);
+      pVideoPlayer->pSmackMovieBlit = v11;
+      if ( !v11 )
+      {
+        Unload();
+        v12 = "Failed to open Blit API";
+		sprintf(pVideoName, v12);
+        MessageBoxA(0, pVideoName, "Smacker Error", 0);
+        return;
+      }
+    }
+  }
+}
+
+
+//----- (004BF5B2) --------------------------------------------------------
+void VideoPlayer::_4BF5B2()
+{
+  VideoPlayer *v1; // esi@1
+  unsigned int v2; // eax@1
+  _BINK **v3; // edi@2
+
+  v1 = this;
+  v2 = this->uMovieFormat;
+  if ( v2 == 2 )
+  {
+    v3 = &this->pBinkMovie;
+    BinkGoto(pBinkMovie, 1, 0);
+    BinkDoFrame(pBinkMovie);
+    BinkNextFrame(pBinkMovie);
+  }
+  else
+  {
+    if ( v2 != 1 )
+      return;
+    SmackGoto(pSmackerMovie, 1);
+    if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+    {
+      SmackDoFrame(pSmackerMovie);
+      SmackNextFrame(pSmackerMovie);
+    }
+  }
+  pMouse->_469E24();
+  if ( ptr_507BC0 && ptr_507BC0->ptr_1C == (void *)165 && !v1->pSmackerMovie )
+  {
+    bGameoverLoop = 1;
+    sub_4BD8B5();
+    ptr_507BC0->Release();
+    pParty->uFlags &= 0xFFFFFFFDu;
+    if ( EnterHouse((enum HOUSE_TYPE)165) )
+    {
+      pAudioPlayer->PlaySound(SOUND_0, 0, 0, -1, 0, 0, 0, 0);
+      ptr_507BC0 = GUIWindow::Create(0, 0, 640, 480, WINDOW_HouseInterior, 165, 0);
+      ptr_507BC0->CreateButton(0x3Du, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+      ptr_507BC0->CreateButton(0xB1u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+      ptr_507BC0->CreateButton(0x124u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+      ptr_507BC0->CreateButton(0x197u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+    }
+    bGameoverLoop = 0;
+  }
+}
+
+//----- (004BF73A) --------------------------------------------------------
+void VideoPlayer::_4BF73A()
+{
+  VideoPlayer *v1; // esi@1
+  int v2; // edi@1
+  unsigned __int8 v3; // bl@1
+  int v4; // edi@1
+  char Source[32]; // [sp+Ch] [bp-40h]@1
+
+  v1 = this;
+  v2 = this->dword_0000A0;
+  v3 = LOBYTE(this->bLoopPlaying);
+  strcpy(Source, this->pCurrentMovieName);
+  Unload();
+  v4 = v2 - 1;
+  if ( v4 )
+  {
+    if ( v4 == 1 )
+      OpenMovie(Source, v3, 1);
+  }
+  else
+  {
+    _4BF28F(Source, v3);
+  }
+}
+
+//----- (004BF8F6) --------------------------------------------------------
+void VideoPlayer::PlayDeathMovie()
+{
+  bStopBeforeSchedule = 0;
+  field_40 = 0;
+  pGame->pCShow->PlayMovie(MOVIE_Death, 1);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VideoPlayer.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,195 @@
+#pragma once
+#include "OSAPI.h"
+
+#include "Texture.h"
+#include "mm7_data.h"
+
+
+
+#pragma pack(push, 1)
+
+
+
+struct _BINK
+{
+  int uWidth;
+  int uHeight;
+};
+
+struct _BINK_1_5_21_0: public _BINK
+{
+  int uNumFrames;
+  int uCurrentFrame;
+  int Data1;
+  int uFrameRate;
+  int field_18[3];
+  int uFlags;
+};
+
+struct _BINK_3_0_0_0: public _BINK
+{
+  int unk_0;
+  int unk_1;
+  int uNumFrames;
+  int uCurrentFrame;
+  int _unk2;
+  int _unk_[10];
+};
+
+
+struct _BINKBUF
+{
+  int uWidth;
+  int uHeight;
+  int field_8;
+  int field_C;
+  int uBinkDDSurfaceType;
+  void *pDDrawSurfaceData;
+  int uDDrawSurfacePitch;
+  int field_1C;
+  int field_20;
+  int field_24;
+  int field_28;
+  int field_2C;
+  int field_30;
+  int field_34;
+  int field_38;
+  int field_3C;
+  int field_40;
+  int field_44;
+  struct IDirectDrawSurface *pTargetDDrawSurface;
+  int field_4C;
+  int uRectX;
+  int uRectY;
+  HWND hWnd;
+  int field_5C;
+  float field_60;
+  float field_64;
+  int field_68;
+  int field_6C;
+  void *pDDrawSurfaceData_;
+  int field_74;
+  int field_78;
+};
+struct _BINKBUF_1_5_21_0: public _BINKBUF
+{
+  int field_7C;
+  int field_80;
+  int field_84;
+  int field_88;
+  int field_8C;
+  int field_90;
+  int field_94;
+  int field_98;
+  int field_9C;
+  int field_A0;
+};
+
+struct _BINKBUF_3_0_0_0: public _BINKBUF
+{
+};
+#pragma pack(pop)
+
+
+
+
+#pragma pack(push, 1)
+struct MovieHeader
+{
+  char pVideoName[40];
+  unsigned int uFileOffset;
+};
+#pragma pack(pop)
+
+
+
+
+
+void __cdecl ShowIntroVideo_and_LoadingScreen();
+
+
+
+
+#pragma pack(push, 1)
+struct VideoPlayer
+{
+  //----- (004BE6F5) --------------------------------------------------------
+  inline VideoPlayer():
+    field_54(0),
+    pBinkMovie(nullptr), pBinkBuffer(nullptr),
+    pSmackerMovie(nullptr), pSmackerBuffer(nullptr), pSmackMovieBlit(nullptr)
+  {
+    //RGBTexture::RGBTexture(&pVideoPlayer->pVideoFrame);
+    bStopBeforeSchedule = false;
+    field_40 = 0;
+    byte_F8BC0C = 0;
+    //pBinkMovie = nullptr;
+  }
+  //----- (004BECBD) --------------------------------------------------------
+  virtual ~VideoPlayer()
+  {
+    bStopBeforeSchedule = false;
+    field_40 = 0;
+    pVideoFrame.Release();
+  }
+
+  void PlayDeathMovie();
+  unsigned int SmackCheckSurfaceFromat();
+  void Initialize();
+  void Prepare();
+  void Unload();
+  void FastForwardToFrame(unsigned int uFrameNum);
+  void BinkDrawFrame(HWND hWnd, int a3, int a4);
+  void BinkUpdatePalette(HWND hWnd) {}
+  void SmackDrawFrame(HWND hWnd, int a3, int a4);
+  void SmackUpdatePalette(HWND hWnd);
+  _BINK *OpenBink(const char *pName);
+  struct _SMACK *OpenSmack(const char *pFilename);
+  void _4BF28F(const char *pMovieName, unsigned int a3_1);
+  bool AnyMovieLoaded();
+  void OpenMovie(const char *pFilename, unsigned int bLoop, int a4);
+  void _4BF5B2();
+  void _4BF73A();
+  _BINKBUF *CreateBinkBuffer(HWND a1, unsigned int uWidth, unsigned int uHeight, char a4);
+
+  static void __fastcall MovieLoop(const char *pMovieName, int a2, int a3, int a4);
+
+
+  RGBTexture pVideoFrame;
+  struct _SMACK *pSmackerMovie;
+  struct _SMACKBUF *pSmackerBuffer;
+  char *pSomeSmackerBuffer;
+  int field_34;
+  MovieHeader *pMightVideoHeaders;
+  MovieHeader *pMagicVideoHeaders;
+  int field_40;
+  int field_44;
+  unsigned int uNumMightVideoHeaders;
+  unsigned int uNumMagicVideoHeaders;
+  int uBinkDirectDrawSurfaceType;
+  int field_54;
+  unsigned int bPlayingMovie;
+  unsigned int bFirstFrame;
+  unsigned int bUsingSmackerMMX;
+  unsigned int bLoopPlaying;
+  int field_68;
+  unsigned int bStopBeforeSchedule;
+  HWND hWindow;
+  struct _SMACKBLIT *pSmackMovieBlit;
+  HANDLE hMightVid;
+  HANDLE hMagicVid;
+  _BINK *pBinkMovie;
+  _BINKBUF *pBinkBuffer;
+  char field_88[20];
+  unsigned int uMovieFormat;
+  int dword_0000A0;
+  char pCurrentMovieName[64];
+  char pVideoFrameTextureFilename[32];
+};
+#pragma pack(pop)
+
+
+
+
+
+extern VideoPlayer *pVideoPlayer;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Viewport.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,92 @@
+#pragma once
+
+/*  149 */
+#pragma pack(push, 1)
+struct Viewport
+{
+  void SetScreen(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW);
+  void _4C02F8(int a2);
+  void SetViewport(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW);
+
+
+  unsigned int uScreenX;
+  unsigned int uScreenY;
+  unsigned int uScreenZ;
+  unsigned int uScreenW;
+  unsigned int uViewportX;
+  unsigned int uViewportY;
+  unsigned int uViewportZ;
+  unsigned int uViewportW;
+  int uScreenWidth;
+  int uScreenHeight;
+  int uScreenCenterX;
+  int uScreenCenterY;
+  int field_30;
+};
+#pragma pack(pop)
+
+
+
+extern struct Viewport *pViewport;
+
+
+
+
+
+
+
+
+
+
+
+/*  201 */
+#pragma pack(push, 1)
+struct ViewingParams
+{
+  int _443291();
+  unsigned int _443343();
+  int _443219();
+  int _443225();
+  int _443231();
+  int _44323D();
+  int _443249();
+  int _4432E7();
+  int _443365();
+
+
+
+  int uSomeX;
+  int uSomeY;
+  int uSomeZ;
+  int uSomeW;
+  unsigned int uScreenX;
+  unsigned int uScreenY;
+  unsigned int uScreenZ;
+  unsigned int uScreenW;
+  int field_20;
+  unsigned int uMinimapZoom;
+  int field_28;
+  int field_2C;
+  int sPartyPosX;
+  int sPartyPosZ;
+  __int16 field_38;
+  __int16 field_3A;
+  int field_3C;
+  unsigned int uTextureID_LocationMap;
+  int bRedrawGameUI;
+  int field_48;
+  int field_4C;
+  int field_50_draw_debug_outlines;
+  int field_54;
+  int field_58;
+  int field_5C;
+  int field_60;
+  int field_64;
+  int field_68;
+  unsigned __int16 pPalette[256];
+};
+#pragma pack(pop)
+
+
+
+extern struct ViewingParams *viewparams;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vis.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2108 @@
+#include "Vis.h"
+#include "Outdoor.h"
+#include "Game.h"
+#include "Actor.h"
+#include "IndoorCamera.h"
+#include "Viewport.h"
+#include "stru157.h"
+
+#include "mm7_data.h"
+//#include "MM7.h"
+
+
+static Vis_stru1 Vis_static_sub_4C1944_stru_F8BDE8;
+
+
+
+//----- (004C1026) --------------------------------------------------------
+Vis_stru1_stru0 *Vis::_4C1026(BLVFace *a2, unsigned int a3, float a4)
+{
+  char *v4; // eax@4
+  signed int v5; // ecx@4
+  BLVFace *v6; // ecx@7
+  unsigned int v7; // edi@7
+  Vec3_short_ *v8; // eax@9
+  char *v9; // edx@9
+  signed int v10; // esi@10
+  Vec3_int_ **v11; // edx@13
+  char *v12; // eax@13
+  double v13; // st7@14
+  signed int v14; // ebx@14
+  Vis *v15; // ebx@15
+  Vis_stru1_stru0 *result; // eax@21
+  Vis_stru1_stru0 *v17; // ecx@24
+  RenderVertexSoft pRay[2]; // [sp+20h] [bp-70h]@17
+  int v20; // [sp+84h] [bp-Ch]@10
+  int v21; // [sp+88h] [bp-8h]@16
+  int v22; // [sp+8Ch] [bp-4h]@16
+  signed int v23; // [sp+98h] [bp+8h]@7
+
+  auto ecx0 = this;
+
+  static Vis_stru1 static_sub_4C1026_stru_F8FE00;
+  static_sub_4C1026_stru_F8FE00.uNumPointers = 0;
+
+  static bool _init_flag = false;
+  static RenderVertexSoft static_sub_4C1026_array_F8F200[64];
+  if (!_init_flag)
+  {
+    _init_flag = true;
+    for (uint i = 0; i < 64; ++i)
+      static_sub_4C1026_array_F8F200[i].flt_2C = 0.0f;
+  }
+
+  v6 = a2;
+  v23 = 0;
+  v7 = v6->uNumVertices;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    if ( (signed int)v7 > 0 )
+    {
+      v8 = pIndoor->pVertices;
+      v9 = (char *)&static_sub_4C1026_array_F8F200[0].vWorldPosition.y;
+      do
+      {
+        v10 = v23++;
+        v20 = v8[v6->pVertexIDs[v10]].x;
+        *((float *)v9 - 1) = (double)v20;
+        v20 = v8[v6->pVertexIDs[v10]].y;
+        *(float *)v9 = (double)v20;
+        v9 += 48;
+        v20 = v8[v6->pVertexIDs[v10]].z;
+        *((float *)v9 - 11) = (double)v20;
+      }
+      while ( v23 < (signed int)v7 );
+    }
+  }
+  else
+  {
+    if ( (signed int)v7 > 0 )
+    {
+      v11 = &pOutdoor->pBModels[a3 >> 9].pVertices.pVertices;
+      v12 = (char *)&static_sub_4C1026_array_F8F200[0].vWorldPosition.y;
+      do
+      {
+        *((float *)v12 - 1) = (double)(*v11)[v6->pVertexIDs[v23]].x;
+        v13 = (double)(*v11)[v6->pVertexIDs[v23]].y;
+        v14 = v23++;
+        *(float *)v12 = v13;
+        v12 += 48;
+        *((float *)v12 - 11) = (double)(*v11)[v6->pVertexIDs[v14]].z;
+      }
+      while ( v23 < (signed int)v7 );
+    }
+  }
+  pGame->pIndoorCameraD3D->ViewTransform(static_sub_4C1026_array_F8F200, v7);
+  pGame->pIndoorCameraD3D->Project(static_sub_4C1026_array_F8F200, v7, 1);
+  v15 = this;
+  SortVectors_x(static_sub_4C1026_array_F8F200, 0, v7 - 1);
+  if ( static_sub_4C1026_array_F8F200[0].vWorldViewPosition.x > (double)a4
+    || (_4C1495(static_sub_4C1026_array_F8F200, v7, (float *)&v21, (float *)&v22),
+        _4C12C3_FindSomeBillboard(static_sub_4C1026_array_F8F200, v7, *(float *)&v21, *(float *)&v22))
+    || ((CastPickRay(pRay, *(float *)&v21, *(float *)&v22, a4), uCurrentlyLoadedLevelType != LEVEL_Indoor) ? PickOutdoor(a4, pRay, &static_sub_4C1026_stru_F8FE00, &a5, 1) : PickIndoor(a4, pRay, &static_sub_4C1026_stru_F8FE00, &a5),
+        (static_sub_4C1026_stru_F8FE00.create_object_pointers(0),
+         sort_object_pointers(
+           static_sub_4C1026_stru_F8FE00.array_1804,
+           0,
+           static_sub_4C1026_stru_F8FE00.uNumPointers - 1),
+         !static_sub_4C1026_stru_F8FE00.uNumPointers)
+     || (result = static_sub_4C1026_stru_F8FE00.sub_4C2551(2, a3)) == 0
+     || (signed int)static_sub_4C1026_stru_F8FE00.uNumPointers > 1
+     && ((signed int)static_sub_4C1026_stru_F8FE00.uNumPointers <= 0 ? (v17 = 0) : (v17 = static_sub_4C1026_stru_F8FE00.array_1804[0]),
+         result != v17)) )
+    result = 0;
+  return result;
+}
+// F91E08: using guessed type char static_sub_4C1026_byte_F91E08__init_flags;
+
+//----- (004C12C3) --------------------------------------------------------
+char Vis::_4C12C3_FindSomeBillboard(RenderVertexSoft *a1, int a2, float a3, float a4)
+{
+  signed int v5; // esi@1
+  char *v6; // edi@2
+  double v7; // st7@9
+  int v8; // edx@9
+  char *v9; // ecx@10
+  char result; // al@24
+  Vis *thisa; // [sp+10h] [bp-8h]@1
+  float thisb; // [sp+10h] [bp-8h]@9
+  signed int v13; // [sp+14h] [bp-4h]@1
+  float a3a; // [sp+28h] [bp+10h]@9
+  float a4a; // [sp+2Ch] [bp+14h]@9
+
+  v13 = -1;
+  v5 = 0;
+  thisa = this;
+  if ( (signed int)pRenderer->uNumBillboardsToDraw <= 0 )
+    goto LABEL_28;
+  v6 = (char *)&pRenderer->pBillboardRenderListD3D[0].uParentBillboardID;
+  do
+  {
+    if ( IsPointInsideD3DBillboard((RenderBillboardD3D *)(v6 - 152), a3, a4)
+      && (v13 == -1
+       || (unsigned int)pBillboardRenderList[*(int *)v6].sZValue < pBillboardRenderList[pRenderer->pBillboardRenderListD3D[v13].uParentBillboardID].sZValue) )
+      v13 = v5;
+    ++v5;
+    v6 += 156;
+  }
+  while ( v5 < (signed int)pRenderer->uNumBillboardsToDraw );
+  if ( v13 == -1 )
+    goto LABEL_28;
+  v7 = 3.4028235e38;
+  v8 = a2;
+  a4a = 3.4028235e38;
+  a3a = -3.4028235e38;
+  thisb = -3.4028235e38;
+  if ( a2 > 0 )
+  {
+    v9 = (char *)&a1->vWorldViewProjY;
+    do
+    {
+      if ( *((float *)v9 - 1) < v7 )
+        v7 = *((float *)v9 - 1);
+      if ( *((float *)v9 - 1) > (double)a3a )
+        a3a = *((float *)v9 - 1);
+      if ( *(float *)v9 < (double)a4a )
+        a4a = *(float *)v9;
+      if ( *(float *)v9 > (double)thisb )
+        thisb = *(float *)v9;
+      v9 += 48;
+      --v8;
+    }
+    while ( v8 );
+  }
+  if ( v7 < pRenderer->pBillboardRenderListD3D[v13].pQuards[0].pos.x
+    || pRenderer->pBillboardRenderListD3D[v13].pQuards[0].pos.y > (double)a4a
+    || pRenderer->pBillboardRenderListD3D[v13].pQuards[3].pos.x < (double)a3a
+    || pRenderer->pBillboardRenderListD3D[v13].pQuards[1].pos.y < (double)thisb )
+LABEL_28:
+    result = 0;
+  else
+    result = 1;
+  return result;
+}
+
+//----- (004C1417) --------------------------------------------------------
+void Vis::GetPolygonCenter(RenderVertexD3D3 *pVertices, unsigned int uNumVertices, float *pCenterX, float *pCenterY)
+{
+  static RenderVertexD3D3 unk_F8EA00[64];
+
+  memcpy(unk_F8EA00, pVertices, 32 * uNumVertices);
+
+  SortVerticesByX(unk_F8EA00, 0, uNumVertices - 1);
+  *pCenterX = (unk_F8EA00[uNumVertices - 1].pos.x - unk_F8EA00[0].pos.x) * 0.5 + unk_F8EA00[0].pos.x;
+
+  SortVerticesByY(unk_F8EA00, 0, uNumVertices - 1);
+  *pCenterY = (unk_F8EA00[uNumVertices - 1].pos.y - unk_F8EA00[0].pos.y) * 0.5 + unk_F8EA00[0].pos.y;
+}
+
+//----- (004C1495) --------------------------------------------------------
+float *Vis::_4C1495(RenderVertexSoft *Src, int a2, float *a3, float *a4)
+{
+  char *v5; // eax@2
+  signed int v6; // ecx@2
+  float *result; // eax@5
+  Vis *thisa; // [sp+0h] [bp-4h]@1
+
+  thisa = this;
+
+  static bool static_sub_4C1495_byte_F8E9F8__init_flags = false; // weak
+  static RenderVertexSoft static_sub_4C1495_array_F8DDF8[64];
+  if ( !static_sub_4C1495_byte_F8E9F8__init_flags )
+  {
+    static_sub_4C1495_byte_F8E9F8__init_flags = true;
+
+    for (uint i = 0; i < 64; ++i)
+      static_sub_4C1495_array_F8DDF8[i].flt_2C = 0.0f;
+  }
+
+  memcpy(static_sub_4C1495_array_F8DDF8, Src, 48 * a2);
+  sort_objects_2(static_sub_4C1495_array_F8DDF8, 0, a2 - 1);
+  *a3 = (*(float *)&Vis_static_sub_4C1944_stru_F8BDE8.array_1804[12 * a2 + 509]
+       - static_sub_4C1495_array_F8DDF8[0].vWorldViewProjX)
+      * 0.5
+      + static_sub_4C1495_array_F8DDF8[0].vWorldViewProjX;
+  sort_objects_3(static_sub_4C1495_array_F8DDF8, 0, a2 - 1);
+  result = a4;
+  *a4 = (*(float *)&Vis_static_sub_4C1944_stru_F8BDE8.array_1804[12 * a2 + 510]
+       - static_sub_4C1495_array_F8DDF8[0].vWorldViewProjY)
+      * 0.5
+      + static_sub_4C1495_array_F8DDF8[0].vWorldViewProjY;
+  return result;
+}
+
+//----- (004C1542) --------------------------------------------------------
+void Vis::PickBillboards(float fPickDepth, float fX, float fY, Vis_stru1 *a4, stru157 *a2)
+{
+  int v6; // ST1C_4@6
+  Vis_stru1_stru0 *v7; // edi@6
+  Vis *thisa; // [sp+20h] [bp-Ch]@1
+  void **v9; // [sp+24h] [bp-8h]@2
+  unsigned int uD3DBillboardIdx; // [sp+28h] [bp-4h]@1
+
+  uD3DBillboardIdx = 0;
+  thisa = this;
+  if ( (signed int)pRenderer->uNumBillboardsToDraw > 0 )
+  {
+    v9 = (void **)&pRenderer->pBillboardRenderListD3D[0].uParentBillboardID;
+    do
+    {
+      if ( is_part_of_selection((BLVFace *)uD3DBillboardIdx, a2)
+        && IsPointInsideD3DBillboard((RenderBillboardD3D *)(v9 - 38), fX, fY) )
+      {
+        if ( DoesRayIntersectBillboard(fPickDepth, uD3DBillboardIdx) )
+        {
+          v6 = pBillboardRenderList[(int)*v9].sZValue;
+          v7 = &a4->array_0004[a4->uNumPointers];
+          v7->pObjectInfo = *v9;
+          v7 = (Vis_stru1_stru0 *)((char *)v7 + 4);
+          v7->pObjectInfo = (void *)v6;
+          v7->sZValue = 1;
+          ++a4->uNumPointers;
+        }
+      }
+      ++uD3DBillboardIdx;
+      v9 += 39;
+    }
+    while ( (signed int)uD3DBillboardIdx < (signed int)pRenderer->uNumBillboardsToDraw );
+  }
+}
+
+//----- (004C1607) --------------------------------------------------------
+bool Vis::IsPointInsideD3DBillboard(RenderBillboardD3D *a1, float x, float y)
+{
+  RenderBillboardD3D *result; // eax@1
+  double v5; // st7@2
+  float v6; // ecx@2
+  float v7; // ST00_4@3
+  __int16 v8; // fps@6
+  double v9; // st6@6
+  char v10; // c0@6
+  char v11; // c2@6
+  char v12; // c3@6
+  __int16 v13; // fps@7
+  double v14; // st6@7
+  unsigned __int8 v15; // c0@7
+  char v16; // c2@7
+  unsigned __int8 v17; // c3@7
+  __int16 v18; // fps@8
+  double v19; // st6@8
+  char v20; // c0@8
+  char v21; // c2@8
+  char v22; // c3@8
+  __int16 v23; // fps@9
+  double v24; // st6@9
+  unsigned __int8 v25; // c0@9
+  char v26; // c2@9
+  unsigned __int8 v27; // c3@9
+  float v28; // [sp+4h] [bp-8h]@2
+  float v29; // [sp+8h] [bp-4h]@2
+  float a1a; // [sp+14h] [bp+8h]@2
+
+  result = a1;
+  if ( a1->uParentBillboardID == -1 )
+    goto LABEL_14;
+  v5 = a1->pQuards[0].pos.x;
+  a1a = a1->pQuards[3].pos.x;
+  v6 = result->pQuards[0].pos.y;
+  result = (RenderBillboardD3D *)LODWORD(result->pQuards[1].pos.y);
+  v29 = v6;
+  LODWORD(v28) = (int)result;
+  if ( v5 > a1a )
+  {
+    v7 = v5;
+    HIWORD(result) = HIWORD(v7);
+    v5 = a1a;
+    a1a = v7;
+  }
+  if ( v6 > (double)v28 )
+  {
+    result = (RenderBillboardD3D *)LODWORD(v28);
+    v28 = v6;
+    LODWORD(v29) = (int)result;
+  }
+  v9 = x + 1.0;
+  //UNDEF(v8);
+  v10 = v9 < v5;
+  v11 = 0;
+  v12 = v9 == v5;
+  BYTE1(result) = HIBYTE(v8);
+  if ( v9 >= v5
+    && (v14 = x - 1.0, /*UNDEF(v13),*/ v15 = v14 < a1a, v16 = 0, v17 = v14 == a1a, BYTE1(result) = HIBYTE(v13), v15 | v17)
+    && (v19 = y + 1.0, /*UNDEF(v18),*/ v20 = v19 < v29, v21 = 0, v22 = v19 == v29, BYTE1(result) = HIBYTE(v18), v19 >= v29)
+    && (v24 = y - 1.0, /*UNDEF(v23),*/ v25 = v24 < v28, v26 = 0, v27 = v24 == v28, BYTE1(result) = HIBYTE(v23), v25 | v27) )
+    LOBYTE(result) = 1;
+  else
+LABEL_14:
+    LOBYTE(result) = 0;
+  return (bool)result;
+}
+
+//----- (004C16B4) --------------------------------------------------------
+void Vis::PickIndoor(float fDepth, RenderVertexSoft *pRay, Vis_stru1 *a4, stru157 *a5)
+{
+  int v5; // eax@1
+  signed int v6; // edi@2
+  signed int v7; // esi@4
+  int v8; // ecx@7
+  int v9; // eax@7
+  unsigned int *pNumPointers; // eax@7
+  unsigned int v11; // ecx@7
+  Vis_stru1_stru0 *v12; // edi@7
+  RenderVertexSoft a1; // [sp+Ch] [bp-44h]@1
+  BLVFace *v14; // [sp+3Ch] [bp-14h]@7
+  void *v15; // [sp+40h] [bp-10h]@7
+  int v16; // [sp+44h] [bp-Ch]@7
+  int v17; // [sp+48h] [bp-8h]@1
+  Vis *thisa; // [sp+4Ch] [bp-4h]@1
+
+  v5 = 0;
+  thisa = this;
+  v17 = 0;
+  for ( a1.flt_2C = 0.0; v17 < (signed int)pBspRenderer->uNumFaceIDs; ++v17 )
+  {
+    v6 = pBspRenderer->pFaceIDs[2 * v5];
+    if ( v6 >= 0 )
+    {
+      if ( v6 < (signed int)pIndoor->uNumFaces )
+      {
+        v7 = v6;
+        if ( is_part_of_selection(&pIndoor->pFaces[v6], a5) )
+        {
+          if ( !pGame->pIndoorCameraD3D->IsCulled(&pIndoor->pFaces[v7]) )
+          {
+            if ( Intersect_Ray_Face(pRay, pRay + 1, &fDepth, &a1, &pIndoor->pFaces[v7], 0xFFFFFFFFu) )
+            {
+              pGame->pIndoorCameraD3D->ViewTransform(&a1, 1u);
+              v9 = _48B561_mess_with_scaling_along_z(/*v8, */a1.vWorldViewPosition.x);
+              LOWORD(v9) = 0;
+              v15 = (void *)((8 * v6 | 6) + v9);
+              pNumPointers = &a4->uNumPointers;
+              v16 = 2;
+              v11 = a4->uNumPointers;
+              v14 = &pIndoor->pFaces[v7];
+              v12 = &a4->array_0004[v11];
+              v12->pObjectInfo = &pIndoor->pFaces[v7];
+              v12 = (Vis_stru1_stru0 *)((char *)v12 + 4);
+              v12->pObjectInfo = v15;
+              v12->sZValue = v16;
+              ++*pNumPointers;
+            }
+          }
+        }
+      }
+    }
+    v5 = v17 + 1;
+  }
+}
+
+//----- (004C17CF) --------------------------------------------------------
+void Vis::PickOutdoor(float fDepth, RenderVertexSoft *pRay, Vis_stru1 *a4, stru157 *a5, char a6)
+{
+  int v6; // esi@1
+  unsigned int v7; // ecx@1
+  BSPModel *v8; // ebx@3
+  bool v9; // eax@3
+  int v10; // eax@8
+  ODMFace *v11; // esi@10
+  int v12; // ecx@12
+  int v13; // eax@12
+  unsigned int *pNumPointers; // eax@12
+  Vis_stru1_stru0 *v15; // edi@12
+  BLVFace thisa; // [sp+10h] [bp-B8h]@1
+  RenderVertexSoft a1; // [sp+70h] [bp-58h]@1
+  void *v18; // [sp+A0h] [bp-28h]@12
+  void *v19; // [sp+A4h] [bp-24h]@12
+  int v20; // [sp+A8h] [bp-20h]@12
+  int v21; // [sp+ACh] [bp-1Ch]@8
+  Vis *v22; // [sp+B0h] [bp-18h]@1
+  int v23; // [sp+B4h] [bp-14h]@9
+  int v24; // [sp+B8h] [bp-10h]@1
+  unsigned int v25; // [sp+BCh] [bp-Ch]@2
+  unsigned int v26; // [sp+C0h] [bp-8h]@1
+  int v27; // [sp+C4h] [bp-4h]@8
+
+  v22 = this;
+  v6 = 0;
+  v7 = 0;
+  v24 = 0;
+  v26 = 0;
+  a1.flt_2C = 0.0;
+  if (!pOutdoor)
+    return;
+  if ( (signed int)pOutdoor->uNumBModels > 0 )
+  {
+    v25 = 0;
+    do
+    {
+      v8 = &pOutdoor->pBModels[v25 / 0xBC];
+      v9 = IsBModelVisible(v7, &v24);
+      if ( a6 )
+      {
+        if ( v9 && v24 != v6 )
+        {
+LABEL_8:
+          v10 = v8->uNumFaces;
+          v27 = v6;
+          v21 = v10;
+          if ( v10 > v6 )
+          {
+            v23 = v6;
+            do
+            {
+              v11 = (ODMFace *)((char *)v8->pFaces + v23);
+              if ( is_part_of_selection((BLVFace *)((char *)v8->pFaces + v23), a5) )
+              {
+                thisa.FromODM(v11);
+                if ( Intersect_Ray_Face(pRay, pRay + 1, &fDepth, &a1, &thisa, v26) )
+                {
+                  pGame->pIndoorCameraD3D->ViewTransform(&a1, 1u);
+                  v18 = v11;
+                  v13 = _48B561_mess_with_scaling_along_z(/*v12, */a1.vWorldViewPosition.x);
+                  LOWORD(v13) = 0;
+                  v20 = 2;
+                  v19 = (void *)((8 * (v27 | (v26 << 6)) | 6) + v13);
+                  pNumPointers = &a4->uNumPointers;
+                  v15 = &a4->array_0004[a4->uNumPointers];
+                  v15->pObjectInfo = v18;
+                  v15 = (Vis_stru1_stru0 *)((char *)v15 + 4);
+                  v15->pObjectInfo = v19;
+                  v15->sZValue = v20;
+                  ++*pNumPointers;
+                }
+              }
+              ++v27;
+              v23 += 308;
+            }
+            while ( v27 < v21 );
+            v6 = 0;
+          }
+          goto LABEL_15;
+        }
+      }
+      else
+      {
+        if ( v9 )
+          goto LABEL_8;
+      }
+LABEL_15:
+      v25 += 188;
+      v7 = v26++ + 1;
+    }
+    while ( (signed int)v26 < (signed int)pOutdoor->uNumBModels );
+  }
+}
+
+//----- (004C1930) --------------------------------------------------------
+//bool Vis::j_DoesRayIntersectBillboard(float fDepth, unsigned int uD3DBillboardIdx)
+//{return DoesRayIntersectBillboard(fDepth, uD3DBillboardIdx);}
+
+//----- (004C1944) --------------------------------------------------------
+int Vis::_4C1944(int a2, unsigned int a3, int a4, int a5, int a6)
+{
+  float v6; // ST00_4@3
+  int result; // eax@4
+  stru157 v8; // [sp+18h] [bp-20h]@3
+  __int64 v9; // [sp+2Ch] [bp-Ch]@3
+  Vis *v14; // [sp+34h] [bp-4h]@1
+
+  v14 = this;
+
+  static Vis_stru1 Vis_static_sub_4C1944_stru_F8BDE8;
+
+  v8.field_4 = a2;
+  v8.field_8 = a6;
+  v8.field_C = a5;
+  v8.field_10 = a4;
+  v9 = a3;
+  Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers = 0;
+  v6 = (double)a3;
+  v8.field_0 = 1;
+  _4C06F8(v6, &Vis_static_sub_4C1944_stru_F8BDE8, &v8);
+  Vis_static_sub_4C1944_stru_F8BDE8.create_object_pointers(1u);
+  sort_object_pointers(
+    Vis_static_sub_4C1944_stru_F8BDE8.array_1804,
+    0,
+    Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers - 1);
+  if ( (signed int)Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers <= 0 )
+    result = -1;
+  else
+    result = Vis_static_sub_4C1944_stru_F8BDE8.array_1804[0]->sZValue;
+  return result;
+}
+// F8DDF0: using guessed type char Vis_static_sub_4C1944_byte_F8DDF0_init;
+
+//----- (004C1A02) --------------------------------------------------------
+void Vis::_4C1A02()
+{
+  RenderVertexSoft v1; // [sp+8h] [bp-C0h]@1
+  RenderVertexSoft v2; // [sp+38h] [bp-90h]@1
+  RenderVertexSoft v3; // [sp+68h] [bp-60h]@1
+  RenderVertexSoft v4; // [sp+98h] [bp-30h]@1
+
+  v4.flt_2C = 0.0;
+  v4.vWorldPosition.x = 0.0;
+  v4.vWorldPosition.y = 65536.0;
+  v4.vWorldPosition.z = 0.0;
+  v3.flt_2C = 0.0;
+  v3.vWorldPosition.x = 65536.0;
+  v3.vWorldPosition.y = 0.0;
+  v3.vWorldPosition.z = 0.0;
+  memcpy(&v1, &v3, sizeof(v1));
+  v3.flt_2C = 0.0;
+  v3.vWorldPosition.x = 0.0;
+  v3.vWorldPosition.y = 65536.0;
+  v3.vWorldPosition.z = 0.0;
+  memcpy(&v2, &v4, sizeof(v2));
+  v4.flt_2C = 0.0;
+  v4.vWorldPosition.x = 65536.0;
+  v4.vWorldPosition.y = 0.0;
+  v4.vWorldPosition.z = 0.0;
+  memcpy(&this->stru_200C, &v1, 0x60u);
+  memcpy(&v1, &v4, sizeof(v1));
+  memcpy(&v2, &v3, sizeof(v2));
+  memcpy(&this->stru_206C, &v1, 0x60u);
+}
+
+//----- (004C1ABA) --------------------------------------------------------
+bool Vis::SortVectors_x(RenderVertexSoft *a2, int a3, int a4)
+{
+  bool result; // eax@1
+  RenderVertexSoft *v5; // edx@2
+  int v6; // ebx@2
+  int i; // ecx@2
+  int v8; // esi@3
+  int v9; // esi@5
+  RenderVertexSoft *v10; // eax@8
+  RenderVertexSoft v11; // [sp+4h] [bp-6Ch]@8
+  RenderVertexSoft v12; // [sp+34h] [bp-3Ch]@2
+  int v13; // [sp+64h] [bp-Ch]@7
+  Vis *thisa; // [sp+68h] [bp-8h]@1
+  RenderVertexSoft *v15; // [sp+6Ch] [bp-4h]@2
+
+  result = a4;
+  thisa = this;
+  if ( a4 > a3 )
+  {
+    v5 = a2;
+    v15 = &a2[a4];
+    v6 = a3 - 1;
+    memcpy(&v12, &a2[a4], sizeof(v12));
+    for ( i = a4; ; i = v13 )
+    {
+      v8 = (int)&v5[v6].vWorldViewPosition;
+      do
+      {
+        v8 += 48;
+        ++v6;
+      }
+      while ( *(float *)v8 < (double)v12.vWorldViewPosition.x );
+      v9 = (int)&v5[i].vWorldViewPosition;
+      do
+      {
+        v9 -= 48;
+        --i;
+      }
+      while ( *(float *)v9 > (double)v12.vWorldViewPosition.x );
+      v13 = i;
+      if ( v6 >= i )
+        break;
+      v10 = &v5[i];
+      memcpy(&v11, &a2[v6], sizeof(v11));
+      v5 = a2;
+      memcpy(&a2[v6], v10, sizeof(a2[v6]));
+      memcpy(v10, &v11, 0x30u);
+    }
+    memcpy(&v11, &v5[v6], sizeof(v11));
+    memcpy(&v5[v6], v15, sizeof(v5[v6]));
+    memcpy(v15, &v11, 0x30u);
+    SortVectors_x(v5, a3, v6 - 1);
+    SortVectors_x(a2, v6 + 1, a4);
+  }
+  return true;
+}
+
+//----- (004C1BAA) --------------------------------------------------------
+int Vis::get_object_zbuf_val(Vis_stru1_stru0 *a2)
+{
+  unsigned int v2; // eax@1
+  int result; // eax@3
+  std::string v4; // [sp-18h] [bp-1Ch]@4
+  const char *v5; // [sp-8h] [bp-Ch]@4
+  int v6; // [sp-4h] [bp-8h]@4
+  Vis *v7; // [sp+0h] [bp-4h]@1
+
+  v7 = this;
+  v2 = a2->uObjectType;
+  if ( (signed int)v2 <= 0 || (signed int)v2 > 2 )
+  {
+    MessageBoxW(nullptr, L"Undefined type requested for: CVis::get_object_zbuf_val()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:1037", 0);
+    result = -1;
+  }
+  else
+  {
+    result = a2->sZValue;
+  }
+  return result;
+}
+
+//----- (004C1BF1) --------------------------------------------------------
+int Vis::get_picked_object_zbuf_val()
+{
+  int result; // eax@2
+
+  if ( (signed int)this->stru1.uNumPointers <= 0 )
+    result = -1;
+  else
+    result = get_object_zbuf_val(this->stru1.array_1804[0]);
+  return result;
+}
+
+//----- (004C1C0C) --------------------------------------------------------
+bool Vis::Intersect_Ray_Face(RenderVertexSoft *pRayStart, RenderVertexSoft *pRayEnd, float *pDepth, RenderVertexSoft *a4, BLVFace *a5, unsigned int a6)
+{
+  BLVFace *v7; // ebx@1
+  bool result; // eax@1
+  double v9; // st7@3
+  __int16 v10; // fps@3
+  char v11; // c0@3
+  char v12; // c2@3
+  char v13; // c3@3
+  __int16 v14; // fps@5
+  char v15; // c0@5
+  char v16; // c2@5
+  char v17; // c3@5
+  double v18; // st5@6
+  __int16 v19; // fps@6
+  char v20; // c0@6
+  char v21; // c2@6
+  char v22; // c3@6
+  unsigned __int8 v23; // c0@6
+  char v24; // c2@6
+  unsigned __int8 v25; // c3@6
+  char v26; // zf@6
+  double v27; // st6@10
+  __int16 v28; // fps@10
+  unsigned __int8 v29; // c0@10
+  char v30; // c2@10
+  unsigned __int8 v31; // c3@10
+  double v32; // st7@11
+  Vec2_short_ v33; // ST1E_4@11
+  Vec3_short_ v34; // ST04_6@11
+  float a5a; // [sp+30h] [bp+18h]@10
+  float a5b; // [sp+30h] [bp+18h]@13
+
+  v7 = a5;
+  result = a5->uAttributes;
+  if ( result & 1
+    || BYTE1(result) & 0x20
+    || (v9 = pRayEnd->vWorldPosition.z * a5->pFacePlane.vNormal.z
+           + a5->pFacePlane.vNormal.y * pRayEnd->vWorldPosition.y
+           + pRayEnd->vWorldPosition.x * a5->pFacePlane.vNormal.x,
+        //UNDEF(v10),
+        v11 = v9 < 0.0,
+        v12 = 0,
+        v13 = v9 == 0.0,
+        BYTE1(result) = HIBYTE(v10),
+        v9 == 0.0)
+    || (/*UNDEF(v14),*/ v15 = v9 < 0.0, v16 = 0, v17 = v9 == 0.0, BYTE1(result) = HIBYTE(v14), v9 > 0.0) )// ray's away (>) from face surface or parallel (==)
+    goto LABEL_12;
+  v18 = -(a5->pFacePlane.vNormal.y * pRayStart->vWorldPosition.y// ray-plane intersection
+        + pRayStart->vWorldPosition.x * a5->pFacePlane.vNormal.x
+        + pRayStart->vWorldPosition.z * a5->pFacePlane.vNormal.z
+        + a5->pFacePlane.dist);
+  //UNDEF(v19);
+  v20 = v9 < 0.0;
+  v21 = 0;
+  v22 = v9 == 0.0;
+  BYTE1(result) = HIBYTE(v19);
+  v23 = v18 < 0.0;
+  v24 = 0;
+  v25 = v18 == 0.0;
+  v26 = (BYTE1(result) & 0x41) == 0;
+  BYTE1(result) = HIBYTE(v19);
+  if ( v26 )
+  {
+    if ( v18 < 0.0 )
+      goto LABEL_12;
+  }
+  else
+  {
+    if ( !(v23 | v25) )
+    {
+LABEL_12:
+      LOBYTE(result) = 0;
+      return result;
+    }
+  }
+  a5a = v18;
+  v27 = a5a / v9;
+  HIWORD(result) = HIWORD(pDepth);
+  //UNDEF(v28);
+  v29 = v27 < *pDepth;
+  v30 = 0;
+  v31 = v27 == *pDepth;
+  BYTE1(result) = HIBYTE(v28);
+  if ( !(v29 | v31)
+    || (a4->vWorldPosition.x = v27 * pRayEnd->vWorldPosition.x + pRayStart->vWorldPosition.x,
+        a4->vWorldPosition.y = v27 * pRayEnd->vWorldPosition.y + pRayStart->vWorldPosition.y,
+        v32 = v27 * pRayEnd->vWorldPosition.z + pRayStart->vWorldPosition.z,
+        a4->vWorldPosition.z = v32,
+        v33.x = (signed __int64)a4->vWorldPosition.x,
+        v33.y = (signed __int64)a4->vWorldPosition.y,
+        *(int *)&v34.x = v33.x,
+        v34.z = (signed __int64)v32,
+        result = _4C1D2B(v7, v34, a6),
+        *(float *)&result == 0.0) )
+    goto LABEL_12;
+  *(float *)&result = v27;
+  a5b = v27;
+  *(int *)pDepth = LODWORD(a5b);
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (004C1D2B) --------------------------------------------------------
+int Vis::_4C1D2B(BLVFace *pFace, Vec3_short_ a2, unsigned int uModelID)
+{
+  BLVFace *v4; // esi@1
+  int v5; // esi@10
+  bool v6; // edi@10
+  int v7; // ecx@12
+  signed int v8; // edx@12
+  signed int v9; // eax@13
+  signed int v10; // ebx@14
+  int v11; // edi@16
+  signed int v12; // ST28_4@18
+  signed __int64 v13; // qtt@18
+  signed int result; // eax@21
+  int v15; // [sp+10h] [bp-Ch]@10
+  signed int v16; // [sp+18h] [bp-4h]@10
+
+  v4 = pFace;
+  if ( a2.z < pFace->pBounding.z1
+    || a2.z > pFace->pBounding.z2
+    || a2.x < pFace->pBounding.x1
+    || a2.x > pFace->pBounding.x2
+    || a2.y < pFace->pBounding.y1
+    || a2.y > pFace->pBounding.y2
+    || (uModelID != -1 ? _4C2186_BLV_IntersectBModel(
+                           (int *)&pFace,
+                           (int *)&uModelID,
+                           &word_F8BC48_displaced_face_intersect_plane_coords_a,
+                           &word_F8BD18_displaced_face_intersect_plane_coords_b,
+                           &a2,
+                           pFace,
+                           uModelID) : _4C1EE5_BLV_IntersectBModel_2(
+                                         (int *)&pFace,
+                                         (int *)&uModelID,
+                                         &word_F8BC48_displaced_face_intersect_plane_coords_a,
+                                         &word_F8BD18_displaced_face_intersect_plane_coords_b,
+                                         &a2,
+                                         pFace),
+        v5 = 2 * v4->uNumVertices,
+        v16 = 0,
+        *(&word_F8BC48_displaced_face_intersect_plane_coords_a + v5) = word_F8BC48_displaced_face_intersect_plane_coords_a,
+        *(&word_F8BD18_displaced_face_intersect_plane_coords_b + v5) = word_F8BD18_displaced_face_intersect_plane_coords_b,
+        v15 = 0,
+        v6 = word_F8BD18_displaced_face_intersect_plane_coords_b >= (signed int)uModelID,
+        v5 <= 0) )
+    goto LABEL_25;
+  do
+  {
+    if ( v16 >= 2 )
+      break;
+    v7 = 2 * v15;
+    v8 = *(&word_F8BD18_displaced_face_intersect_plane_coords_b + v15 + 1);
+    if ( v6 ^ v8 >= (signed int)uModelID )
+    {
+      v9 = *(__int16 *)((char *)&word_F8BC48_displaced_face_intersect_plane_coords_a + v7 + 2);
+      if ( v9 >= (signed int)pFace )
+        v10 = 0;
+      else
+        v10 = 2;
+      v11 = v10 | *(__int16 *)((char *)&word_F8BC48_displaced_face_intersect_plane_coords_a + v7) < (signed int)pFace;
+      if ( v11 != 3 )
+      {
+        if ( !v11
+          || (v12 = v9 - *(__int16 *)((char *)&word_F8BC48_displaced_face_intersect_plane_coords_a + v7),
+              LODWORD(v13) = v12 << 16,
+              HIDWORD(v13) = v12 >> 16,
+              *(__int16 *)((char *)&word_F8BC48_displaced_face_intersect_plane_coords_a + v7)
+            + ((signed int)(((unsigned __int64)(v13
+                                              / (v8
+                                               - *(__int16 *)((char *)&word_F8BD18_displaced_face_intersect_plane_coords_b
+                                                            + v7))
+                                              * (signed int)((uModelID
+                                                            - *(__int16 *)((char *)&word_F8BD18_displaced_face_intersect_plane_coords_b
+                                                                         + v7)) << 16)) >> 16)
+                          + 32768) >> 16) >= (signed int)pFace) )
+          ++v16;
+      }
+    }
+    ++v15;
+    v6 = v8 >= (signed int)uModelID;
+  }
+  while ( v15 < v5 );
+  result = 1;
+  if ( v16 != 1 )
+LABEL_25:
+    result = 0;
+  return result;
+}
+
+//----- (004C1EE5) --------------------------------------------------------
+bool Vis::_4C1EE5_BLV_IntersectBModel_2(int *a1, int *a2, __int16 *a3, __int16 *a4, Vec3_short_ *a5, BLVFace *pFace)
+{
+  bool result; // eax@1
+  unsigned int v8; // ecx@1
+  Vec3_short_ *v9; // ecx@2
+  __int16 *v10; // edx@3
+  signed int v11; // ecx@4
+  char v12; // zf@6
+  Vec3_short_ *v13; // ecx@6
+  int v14; // edx@7
+  __int16 *v15; // edx@8
+  signed int v16; // ecx@9
+  int v17; // edx@11
+  __int16 *v18; // edx@12
+  signed int v19; // ecx@13
+  signed int a5a; // [sp+24h] [bp+18h]@2
+  signed int a5b; // [sp+24h] [bp+18h]@7
+  signed int a5c; // [sp+24h] [bp+18h]@11
+
+  result = (bool)pFace;
+  v8 = pFace->uAttributes;
+  if ( BYTE1(v8) & 1 )
+  {
+    v9 = a5;
+    a5a = 0;
+    *a1 = v9->x;
+    *a2 = v9->y;
+    if ( pFace->uNumVertices )
+    {
+      v10 = a4 + 1;
+      do
+      {
+        v11 = a5a;
+        a3[2 * a5a] = pFace->pXInterceptDisplacements[a5a] + pIndoor->pVertices[pFace->pVertexIDs[a5a]].x;
+        *(v10 - 1) = pFace->pYInterceptDisplacements[v11] + pIndoor->pVertices[pFace->pVertexIDs[v11]].y;
+        *(__int16 *)((char *)v10 + (int)a3 - (int)a4) = pFace->pXInterceptDisplacements[v11 + 1]
+                                                            + pIndoor->pVertices[pFace->pVertexIDs[v11 + 1]].x;
+        ++a5a;
+        *v10 = pFace->pYInterceptDisplacements[v11 + 1] + pIndoor->pVertices[pFace->pVertexIDs[v11 + 1]].y;
+        v10 += 2;
+      }
+      while ( a5a < pFace->uNumVertices );
+    }
+  }
+  else
+  {
+    v12 = (BYTE1(v8) & 2) == 0;
+    v13 = a5;
+    if ( v12 )
+    {
+      v17 = a5->y;
+      a5c = 0;
+      *a1 = v17;
+      *a2 = v13->z;
+      if ( pFace->uNumVertices )
+      {
+        v18 = a4 + 1;
+        do
+        {
+          v19 = a5c;
+          a3[2 * a5c] = pFace->pYInterceptDisplacements[a5c] + pIndoor->pVertices[pFace->pVertexIDs[a5c]].y;
+          *(v18 - 1) = pFace->pZInterceptDisplacements[v19] + pIndoor->pVertices[pFace->pVertexIDs[v19]].z;
+          *(__int16 *)((char *)v18 + (int)(char *)a3 - (char *)a4) = pFace->pYInterceptDisplacements[v19 + 1]
+                                                              + pIndoor->pVertices[pFace->pVertexIDs[v19 + 1]].y;
+          ++a5c;
+          *v18 = pFace->pZInterceptDisplacements[v19 + 1] + pIndoor->pVertices[pFace->pVertexIDs[v19 + 1]].z;
+          v18 += 2;
+        }
+        while ( a5c < pFace->uNumVertices );
+      }
+    }
+    else
+    {
+      v14 = a5->x;
+      a5b = 0;
+      *a1 = v14;
+      *a2 = v13->z;
+      if ( pFace->uNumVertices )
+      {
+        v15 = a4 + 1;
+        do
+        {
+          v16 = a5b;
+          a3[2 * a5b] = pFace->pXInterceptDisplacements[a5b] + pIndoor->pVertices[pFace->pVertexIDs[a5b]].x;
+          *(v15 - 1) = pFace->pZInterceptDisplacements[v16] + pIndoor->pVertices[pFace->pVertexIDs[v16]].z;
+          *(__int16 *)((char *)v15 + (int)a3 - (int)a4) = pFace->pXInterceptDisplacements[v16 + 1]
+                                                              + pIndoor->pVertices[pFace->pVertexIDs[v16 + 1]].x;
+          ++a5b;
+          *v15 = pFace->pZInterceptDisplacements[v16 + 1] + pIndoor->pVertices[pFace->pVertexIDs[v16 + 1]].z;
+          v15 += 2;
+        }
+        while ( a5b < pFace->uNumVertices );
+      }
+    }
+  }
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (004C2186) --------------------------------------------------------
+bool Vis::_4C2186_BLV_IntersectBModel(int *a1, int *a2, __int16 *a3, __int16 *a4, Vec3_short_ *a5, BLVFace *a6, unsigned int uModelID)
+{
+  bool result; // eax@1
+  int *v9; // esi@1
+  unsigned int v10; // ecx@1
+  unsigned int v11; // edx@3
+  signed int v12; // ecx@4
+  __int16 v13; // si@4
+  __int16 *v14; // ecx@4
+  unsigned int v15; // edx@8
+  signed int v16; // ecx@9
+  __int16 v17; // si@9
+  __int16 *v18; // ecx@9
+  unsigned int v19; // edx@12
+  signed int v20; // ecx@13
+  __int16 v21; // si@13
+  __int16 *v22; // ecx@13
+  signed int a1a; // [sp+14h] [bp+8h]@1
+  __int16 *a5a; // [sp+24h] [bp+18h]@3
+  __int16 *a5b; // [sp+24h] [bp+18h]@8
+  __int16 *a5c; // [sp+24h] [bp+18h]@12
+
+  result = (bool)a6;
+  v9 = a1;
+  v10 = a6->uAttributes;
+  a1a = 0;
+  if ( BYTE1(v10) & 1 )
+  {
+    *v9 = a5->x;
+    *a2 = a5->y;
+    if ( a6->uNumVertices )
+    {
+      v11 = 188 * uModelID + 72;
+      a5a = a4 + 1;
+      do
+      {
+        v12 = a1a;
+        a3[2 * a1a] = a6->pXInterceptDisplacements[a1a]
+                    + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v11] + 12 * a6->pVertexIDs[a1a]);
+        *(a5a - 1) = a6->pYInterceptDisplacements[v12]
+                   + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v11] + 12 * a6->pVertexIDs[v12] + 4);
+        *(__int16 *)((char *)a5a + (int)(char *)a3 - (char *)a4) = a6->pXInterceptDisplacements[v12 + 1]
+                                                            + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v11]
+                                                                       + 12 * a6->pVertexIDs[v12 + 1]);
+        v13 = a6->pYInterceptDisplacements[v12 + 1]
+            + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v11] + 12 * a6->pVertexIDs[v12 + 1] + 4);
+        v14 = a5a;
+        ++a1a;
+        a5a += 2;
+        *v14 = v13;
+      }
+      while ( a1a < a6->uNumVertices );
+    }
+  }
+  else
+  {
+    if ( BYTE1(v10) & 2 )
+    {
+      *v9 = a5->x;
+      *a2 = a5->z;
+      if ( a6->uNumVertices )
+      {
+        v15 = 188 * uModelID + 72;
+        a5b = a4 + 1;
+        do
+        {
+          v16 = a1a;
+          a3[2 * a1a] = a6->pXInterceptDisplacements[a1a]
+                      + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v15] + 12 * a6->pVertexIDs[a1a]);
+          *(a5b - 1) = a6->pZInterceptDisplacements[v16]
+                     + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v15] + 12 * a6->pVertexIDs[v16] + 8);
+          *(__int16 *)((char *)a5b + (int)a3 - (int)a4) = a6->pXInterceptDisplacements[v16 + 1]
+                                                              + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v15]
+                                                                         + 12 * a6->pVertexIDs[v16 + 1]);
+          v17 = a6->pZInterceptDisplacements[v16 + 1]
+              + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v15] + 12 * a6->pVertexIDs[v16 + 1] + 8);
+          v18 = a5b;
+          ++a1a;
+          a5b += 2;
+          *v18 = v17;
+        }
+        while ( a1a < a6->uNumVertices );
+      }
+    }
+    else
+    {
+      *v9 = a5->y;
+      *a2 = a5->z;
+      if ( a6->uNumVertices )
+      {
+        v19 = 188 * uModelID + 72;
+        a5c = a4 + 1;
+        do
+        {
+          v20 = a1a;
+          a3[2 * a1a] = a6->pYInterceptDisplacements[a1a]
+                      + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v19] + 12 * a6->pVertexIDs[a1a] + 4);
+          *(a5c - 1) = a6->pZInterceptDisplacements[v20]
+                     + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v19] + 12 * a6->pVertexIDs[v20] + 8);
+          *(__int16 *)((char *)a5c + (int)(char *)a3 - (char *)a4) = a6->pYInterceptDisplacements[v20 + 1]
+                                                              + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v19]
+                                                                         + 12 * a6->pVertexIDs[v20 + 1]
+                                                                         + 4);
+          v21 = a6->pZInterceptDisplacements[v20 + 1]
+              + *(short *)(*(int *)&pOutdoor->pBModels->pModelName[v19] + 12 * a6->pVertexIDs[v20 + 1] + 8);
+          v22 = a5c;
+          ++a1a;
+          a5c += 2;
+          *v22 = v21;
+        }
+        while ( a1a < a6->uNumVertices );
+      }
+    }
+  }
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (004C248E) --------------------------------------------------------
+void Vis::CastPickRay(RenderVertexSoft *pRay, float fMouseX, float fMouseY, float fPickDepth)
+{
+  int v5; // ebx@1
+  int v6; // edi@1
+  int v7; // esi@1
+  Vec3_int_ v8; // ST08_12@1
+  int v9; // ST04_4@1
+  int v10; // eax@1
+  RenderVertexSoft v11[2]; // [sp+2Ch] [bp-74h]@1
+  int v12; // [sp+8Ch] [bp-14h]@1
+  int v13; // [sp+90h] [bp-10h]@1
+  int outz; // [sp+94h] [bp-Ch]@1
+  int outy; // [sp+98h] [bp-8h]@1
+  int v16; // [sp+9Ch] [bp-4h]@1
+
+  v5 = pIndoorCamera->pos.y;
+  v6 = pIndoorCamera->pos.x;
+  v13 = pIndoorCamera->pos.x;
+  v12 = pIndoorCamera->pos.y;
+  v16 = pIndoorCamera->pos.z;
+  v7 = pIndoorCamera->sRotationY + UnprojectX((signed __int64)fMouseX);
+  v8.z = v16;
+  v8.x = v6;
+  v8.y = v5;
+  v9 = pIndoorCamera->sRotationX + UnprojectY((signed __int64)fMouseY);
+  v10 = _48B561_mess_with_scaling_along_z(/*(int)&fMouseX, */fPickDepth);
+  Vec3_int_::Rotate(v10, v7, v9, v8, (int *)&fMouseX, &outy, &outz);
+  v11[0].flt_2C = 0.0;
+  v11[0].vWorldPosition.x = (double)SLODWORD(fMouseX);
+  v11[0].vWorldPosition.y = (double)outy;
+  v11[0].vWorldPosition.z = (double)outz;
+  v11[1].flt_2C = 0.0;
+  v11[1].vWorldPosition.x = (double)v13;
+  v11[1].vWorldPosition.y = (double)v12;
+  v11[1].vWorldPosition.z = (double)v16;
+  memcpy(pRay, &v11[1], 0x30u);
+  memcpy(&pRay[1], v11, sizeof(pRay[1]));
+}
+
+//----- (004C2551) --------------------------------------------------------
+Vis_stru1_stru0 *Vis_stru1::sub_4C2551(int a2, int a3)
+{
+  unsigned int v3; // esi@1
+  signed int v4; // edx@1
+  char *v5; // eax@2
+  Vis_stru1_stru0 *result; // eax@6
+
+  v3 = this->uNumPointers;
+  v4 = 0;
+  if ( (signed int)v3 <= 0 )
+  {
+LABEL_6:
+    result = 0;
+  }
+  else
+  {
+    v5 = (char *)&this->array_0004[0].sZValue;
+    while ( *((int *)v5 + 1) != a2 || (*(int *)v5 & 0xFFFF) != a3 )
+    {
+      ++v4;
+      v5 += 12;
+      if ( v4 >= (signed int)v3 )
+        goto LABEL_6;
+    }
+    result = &this->array_0004[v4];
+  }
+  return result;
+}
+
+//----- (004C2591) --------------------------------------------------------
+Vis_stru1_stru0 **Vis_stru1::create_object_pointers(unsigned int flag)
+{
+  Vis_stru1_stru0 **result; // eax@1
+  signed int v3; // esi@2
+  Vis_stru1_stru0 *v4; // edx@3
+  unsigned __int8 v5; // zf@7
+  unsigned __int8 v6; // sf@7
+  Vis_stru1_stru0 **v7; // ebx@8
+  Vis_stru1_stru0 *v8; // esi@8
+  signed int v9; // edi@9
+  Vis_stru1_stru0 **v10; // edx@10
+  std::string v11; // [sp-18h] [bp-28h]@19
+  const char *v12; // [sp-8h] [bp-18h]@19
+  int v13; // [sp-4h] [bp-14h]@19
+  char v14; // [sp+Ch] [bp-4h]@19
+
+  result = 0;
+  if ( flag )
+  {
+    if ( flag == 1 )
+    {
+      v5 = this->uNumPointers == 0;
+      v6 = (this->uNumPointers & 0x80000000u) != 0;
+      BYTE3(flag) = 1;
+      if ( !(v6 | v5) )
+      {
+        v7 = this->array_1804;
+        v8 = this->array_0004;
+        do
+        {
+          v9 = 0;
+          if ( (signed int)result > 0 )
+          {
+            v10 = this->array_1804;
+            while ( *v10 != v8 )
+            {
+              ++v9;
+              ++v10;
+              if ( v9 >= (signed int)result )
+                goto LABEL_15;
+            }
+            BYTE3(flag) = 0;
+          }
+LABEL_15:
+          if ( BYTE3(flag) )
+            *v7 = v8;
+          result = (Vis_stru1_stru0 **)((char *)result + 1);
+          ++v7;
+          ++v8;
+        }
+        while ( (signed int)result < (signed int)this->uNumPointers );
+      }
+    }
+    else
+    {
+      MessageBoxW(nullptr, L"Unknown pointer creation flag passed to ::create_object_pointers()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:1358", 0);
+    }
+  }
+  else
+  {
+    v3 = 0;
+    if ( (signed int)this->uNumPointers > 0 )
+    {
+      result = this->array_1804;
+      v4 = this->array_0004;
+      do
+      {
+        *result = v4;
+        ++v3;
+        ++result;
+        ++v4;
+      }
+      while ( v3 < (signed int)this->uNumPointers );
+    }
+  }
+  return result;
+}
+
+//----- (004C264A) --------------------------------------------------------
+void Vis::sort_object_pointers(Vis_stru1_stru0 **pPointers, int left, int right)
+{
+  int v4; // edx@1
+  int v5; // ebx@1
+  int v6; // esi@2
+  signed int i; // ecx@2
+  int v8; // eax@3
+  int v9; // ebx@4
+  int v10; // ebx@6
+  Vis_stru1_stru0 *v11; // eax@7
+  Vis *thisa; // [sp+4h] [bp-4h]@1
+  Vis_stru1_stru0 *a3a; // [sp+14h] [bp+Ch]@2
+
+  v4 = left;
+  v5 = right;
+  thisa = this;
+  if ( right > left )
+  {
+    do
+    {
+      v6 = v4 - 1;
+      a3a = pPointers[v5];
+      for ( i = v5; ; pPointers[i] = v11 )
+      {
+        v8 = a3a->sZValue;
+        LOWORD(v8) = 0;
+        do
+        {
+          ++v6;
+          v9 = pPointers[v6]->sZValue;
+          LOWORD(v9) = 0;
+        }
+        while ( v9 < (unsigned int)v8 );
+        do
+        {
+          if ( i < 1 )
+            break;
+          --i;
+          v10 = pPointers[i]->sZValue;
+          LOWORD(v10) = 0;
+        }
+        while ( v10 > (unsigned int)v8 );
+        v11 = pPointers[v6];
+        if ( v6 >= i )
+          break;
+        pPointers[v6] = pPointers[i];
+      }
+      v5 = right;
+      pPointers[v6] = pPointers[right];
+      pPointers[right] = v11;
+      sort_object_pointers(pPointers, v4, v6 - 1);
+      v4 = v6 + 1;
+    }
+    while ( right > v6 + 1 );
+  }
+}
+
+//----- (004C26D0) --------------------------------------------------------
+bool Vis::SortVerticesByX(RenderVertexD3D3 *a2, unsigned int uStart, unsigned int uEnd)
+{
+  bool result; // eax@1
+  RenderVertexD3D3 *v5; // edx@2
+  RenderVertexD3D3 *v6; // esi@2
+  void *v7; // edi@2
+  unsigned int v8; // ebx@2
+  RenderVertexD3D3 *v9; // ecx@3
+  RenderVertexD3D3 *v10; // ecx@5
+  RenderVertexD3D3 *v11; // eax@8
+  RenderVertexD3D3 v12; // [sp+4h] [bp-4Ch]@8
+  RenderVertexD3D3 v13; // [sp+24h] [bp-2Ch]@2
+  Vis *thisa; // [sp+44h] [bp-Ch]@1
+  RenderVertexD3D3 *v15; // [sp+48h] [bp-8h]@2
+  unsigned int v16; // [sp+4Ch] [bp-4h]@2
+
+  result = uEnd;
+  thisa = this;
+  if ( (signed int)uEnd > (signed int)uStart )
+  {
+    v5 = a2;
+    v6 = &a2[uEnd];
+    v7 = &v13;
+    v15 = &a2[uEnd];
+    v8 = uStart - 1;
+    v16 = uEnd;
+    while ( 1 )
+    {
+      memcpy(v7, v6, 0x20u);
+      v9 = &v5[v8];
+      do
+      {
+        ++v9;
+        ++v8;
+      }
+      while ( v9->pos.x < (double)v13.pos.x );
+      v10 = &v5[v16];
+      do
+      {
+        --v10;
+        --v16;
+      }
+      while ( v10->pos.x > (double)v13.pos.x );
+      if ( (signed int)v8 >= (signed int)v16 )
+        break;
+      v11 = &v5[v16];
+      memcpy(&v12, &a2[v8], sizeof(v12));
+      v5 = a2;
+      memcpy(&a2[v8], v11, sizeof(a2[v8]));
+      v6 = &v12;
+      v7 = v11;
+    }
+    memcpy(&v12, &v5[v8], sizeof(v12));
+    memcpy(&v5[v8], v15, sizeof(v5[v8]));
+    memcpy(v15, &v12, 0x20u);
+    SortVerticesByX(v5, uStart, v8 - 1);
+    SortVerticesByX(a2, v8 + 1, uEnd);
+  }
+  return true;
+}
+
+//----- (004C27AD) --------------------------------------------------------
+bool Vis::SortVerticesByY(RenderVertexD3D3 *a2, unsigned int uStart, unsigned int uEnd)
+{
+  bool result; // eax@1
+  RenderVertexD3D3 *v5; // edx@2
+  RenderVertexD3D3 *v6; // esi@2
+  RenderVertexD3D3 v7; // qdi@2
+  unsigned int v8; // ebx@2
+  int v9; // ecx@3
+  int v10; // ecx@5
+  float v11; // eax@8
+  RenderVertexD3D3 v12; // [sp+4h] [bp-4Ch]@8
+  char v13; // [sp+24h] [bp-2Ch]@2
+  float v14; // [sp+28h] [bp-28h]@4
+  Vis *thisa; // [sp+44h] [bp-Ch]@1
+  RenderVertexD3D3 *v16; // [sp+48h] [bp-8h]@2
+  unsigned int v17; // [sp+4Ch] [bp-4h]@2
+
+  result = uEnd;
+  thisa = this;
+  if ( (signed int)uEnd > (signed int)uStart )
+  {
+    v5 = a2;
+    v6 = &a2[uEnd];
+    LODWORD(v7.pos.x) = (int)&v13;
+    v16 = &a2[uEnd];
+    v8 = uStart - 1;
+    v17 = uEnd;
+    while ( 1 )
+    {
+      memcpy(*(void **)&v7.pos.x, v6, 0x20u);
+      v9 = (int)&v5[v8].pos.y;
+      do
+      {
+        v9 += 32;
+        ++v8;
+      }
+      while ( *(float *)v9 < (double)v14 );
+      v10 = (int)&v5[v17].pos.y;
+      do
+      {
+        v10 -= 32;
+        --v17;
+      }
+      while ( *(float *)v10 > (double)v14 );
+      if ( (signed int)v8 >= (signed int)v17 )
+        break;
+      LODWORD(v11) = (int)&v5[v17];
+      memcpy(&v12, &a2[v8], sizeof(v12));
+      v5 = a2;
+      memcpy(&a2[v8], *(void **)&v11, sizeof(a2[v8]));
+      v6 = &v12;
+      v7.pos.x = v11;
+    }
+    memcpy(&v12, &v5[v8], sizeof(v12));
+    memcpy(&v5[v8], v16, sizeof(v5[v8]));
+    memcpy(v16, &v12, 0x20u);
+    SortVerticesByY(v5, uStart, v8 - 1);
+    SortVerticesByY(a2, v8 + 1, uEnd);
+  }
+  return true;
+}
+
+//----- (004C288E) --------------------------------------------------------
+bool Vis::sort_objects_2(RenderVertexSoft *pArray, int sLeft, int sRight)
+{
+  bool result; // eax@1
+  RenderVertexSoft *v5; // edx@2
+  int v6; // ebx@2
+  int i; // ecx@2
+  int v8; // esi@3
+  int v9; // esi@5
+  RenderVertexSoft *v10; // eax@8
+  RenderVertexSoft v11; // [sp+4h] [bp-6Ch]@8
+  RenderVertexSoft v12; // [sp+34h] [bp-3Ch]@2
+  float v13; // [sp+4Ch] [bp-24h]@4
+  int v14; // [sp+64h] [bp-Ch]@7
+  Vis *thisa; // [sp+68h] [bp-8h]@1
+  RenderVertexSoft *v16; // [sp+6Ch] [bp-4h]@2
+
+  __debugbreak();
+
+  result = sRight;
+  thisa = this;
+  if ( sRight > sLeft )
+  {
+    v5 = pArray;
+    v16 = &pArray[sRight];
+    v6 = sLeft - 1;
+    memcpy(&v12, &pArray[sRight], sizeof(v12));
+    for ( i = sRight; ; i = v14 )
+    {
+      v8 = (int)&v5[v6].vWorldViewProjX;
+      do
+      {
+        v8 += 48;
+        ++v6;
+      }
+      while ( *(float *)v8 < (double)v13 );
+      v9 = (int)&v5[i].vWorldViewProjX;
+      do
+      {
+        v9 -= 48;
+        --i;
+      }
+      while ( *(float *)v9 > (double)v13 );
+      v14 = i;
+      if ( v6 >= i )
+        break;
+      v10 = &v5[i];
+      memcpy(&v11, &pArray[v6], sizeof(v11));
+      v5 = pArray;
+      memcpy(&pArray[v6], v10, sizeof(pArray[v6]));
+      memcpy(v10, &v11, 0x30u);
+    }
+    memcpy(&v11, &v5[v6], sizeof(v11));
+    memcpy(&v5[v6], v16, sizeof(v5[v6]));
+    memcpy(v16, &v11, 0x30u);
+    sort_objects_2(v5, sLeft, v6 - 1);
+    sort_objects_2(pArray, v6 + 1, sRight);
+  }
+  return true;
+}
+
+//----- (004C297E) --------------------------------------------------------
+bool Vis::sort_objects_3(RenderVertexSoft *pArray, int sLeft, int sRight)
+{
+  bool result; // eax@1
+  RenderVertexSoft *v5; // edx@2
+  int v6; // ebx@2
+  int i; // ecx@2
+  int v8; // esi@3
+  int v9; // esi@5
+  RenderVertexSoft *v10; // eax@8
+  char v11; // [sp+4h] [bp-6Ch]@8
+  RenderVertexSoft v12; // [sp+34h] [bp-3Ch]@2
+  float v13; // [sp+50h] [bp-20h]@4
+  int v14; // [sp+64h] [bp-Ch]@7
+  Vis *thisa; // [sp+68h] [bp-8h]@1
+  RenderVertexSoft *v16; // [sp+6Ch] [bp-4h]@2
+
+  result = sRight;
+  thisa = this;
+  if ( sRight > sLeft )
+  {
+    v5 = pArray;
+    v16 = &pArray[sRight];
+    v6 = sLeft - 1;
+    memcpy(&v12, &pArray[sRight], sizeof(v12));
+    for ( i = sRight; ; i = v14 )
+    {
+      v8 = (int)&v5[v6].vWorldViewProjY;
+      do
+      {
+        v8 += 48;
+        ++v6;
+      }
+      while ( *(float *)v8 < (double)v13 );
+      v9 = (int)&v5[i].vWorldViewProjY;
+      do
+      {
+        v9 -= 48;
+        --i;
+      }
+      while ( *(float *)v9 > (double)v13 );
+      v14 = i;
+      if ( v6 >= i )
+        break;
+      v10 = &v5[i];
+      memcpy(&v11, &pArray[v6], 0x30u);
+      v5 = pArray;
+      memcpy(&pArray[v6], v10, sizeof(pArray[v6]));
+      memcpy(v10, &v11, 0x30u);
+    }
+    memcpy(&v11, &v5[v6], 0x30u);
+    memcpy(&v5[v6], v16, sizeof(v5[v6]));
+    memcpy(v16, &v11, 0x30u);
+    sort_objects_3(v5, sLeft, v6 - 1);
+    sort_objects_3(pArray, v6 + 1, sRight);
+  }
+  return true;
+}
+
+
+//----- (004C04AF) --------------------------------------------------------
+Vis::Vis()
+{
+  Vis *v1; // ebx@1
+  Vis *result; // eax@1
+  RenderVertexSoft v3; // [sp+Ch] [bp-60h]@1
+  RenderVertexSoft v4; // [sp+3Ch] [bp-30h]@1
+
+  v1 = this;
+  v3.flt_2C = 0.0;
+  v3.vWorldPosition.x = 0.0;
+  v3.vWorldPosition.y = 65536.0;
+  v3.vWorldPosition.z = 0.0;
+  v4.flt_2C = 0.0;
+  v4.vWorldPosition.x = 65536.0;
+  v4.vWorldPosition.y = 0.0;
+  v4.vWorldPosition.z = 0.0;
+  memcpy(&v1->stru_200C, &v4, sizeof(v1->stru_200C));
+  v4.flt_2C = 0.0;
+  v4.vWorldPosition.x = 0.0;
+  v4.vWorldPosition.y = 65536.0;
+  v4.vWorldPosition.z = 0.0;
+  memcpy(&v1->stru_203C, &v3, sizeof(v1->stru_203C));
+  v3.flt_2C = 0.0;
+  v3.vWorldPosition.x = 65536.0;
+  v3.vWorldPosition.y = 0.0;
+  v3.vWorldPosition.z = 0.0;
+  memcpy(&v1->stru_206C, &v3, sizeof(v1->stru_206C));
+  result = v1;
+  memcpy(&v1->stru_209C, &v4, sizeof(v1->stru_209C));
+  v1->field_20CC = 512;
+}
+
+//----- (004C055C) --------------------------------------------------------
+Vis_stru1::Vis_stru1()
+{
+  for (uint i = 0; i < 512; ++i)
+  {
+    array_0004[i].pObjectInfo = 0;
+    array_0004[i].sZValue = -1;
+    array_0004[i].uObjectType = 0;
+  }
+  uNumPointers = 0;
+}
+
+
+
+
+//----- (004C05CC) --------------------------------------------------------
+bool Vis::_4C05CC(Vis_stru1 *a2, stru157 *a3, stru157 *a4)
+{
+  Vis_stru1 *v4; // esi@1
+  Vis *v5; // ebx@1
+  char *v6; // edi@3
+  float v7; // ST00_4@3
+  bool result; // eax@6
+  float v9; // [sp+4h] [bp-14h]@3
+
+  v4 = a2;
+  v5 = this;
+  if ( !a2 )
+    v4 = &this->stru1;
+  v4->uNumPointers = 0;
+  v6 = (char *)&this->field_20CC;
+  v7 = (double)this->field_20CC;
+  _4C06F8(v7, v4, a3);
+  v9 = (double)*(signed int *)v6;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    _4C0D32_BLV(v9, v4, a4);
+  else
+    _4C0DEA_ODM(v9, v4, a4);
+  v4->create_object_pointers(1u);
+  sort_object_pointers(v4->array_1804, 0, v4->uNumPointers - 1);
+  return true;
+}
+
+//----- (004C0646) --------------------------------------------------------
+bool Vis::PickMouse(float fDepth, float fMouseX, float fMouseY, stru157 *a5, stru157 *a6)
+{
+  RenderVertexSoft pMouseRay[2]; // [sp+1Ch] [bp-60h]@1
+
+  stru1.uNumPointers = 0;
+  CastPickRay(pMouseRay, fMouseX, fMouseY, fDepth);
+  PickBillboards(fDepth, fMouseX, fMouseY, &stru1, a5);
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    PickIndoor(fDepth, pMouseRay, &stru1, a6);
+  else
+    PickOutdoor(fDepth, pMouseRay, &stru1, a6, 0);
+  stru1.create_object_pointers(0);
+  sort_object_pointers(stru1.array_1804, 0, stru1.uNumPointers - 1);
+  return true;
+}
+
+//----- (004C06F8) --------------------------------------------------------
+void Vis::_4C06F8(float arg0, Vis_stru1 *a3, stru157 *a2)
+{
+  int v4; // ST18_4@5
+  Vis_stru1_stru0 *v5; // edi@5
+  void **v7; // [sp+24h] [bp-8h]@2
+  unsigned int uD3DBillboardIdx; // [sp+28h] [bp-4h]@1
+
+  uD3DBillboardIdx = 0;
+  auto ecx0 = this;
+  if ( (signed int)pRenderer->uNumBillboardsToDraw > 0 )
+  {
+    v7 = (void **)&pRenderer->pBillboardRenderListD3D[0].uParentBillboardID;
+    do
+    {
+      if ( is_part_of_selection((BLVFace *)uD3DBillboardIdx, a2) )
+      {
+        if ( DoesRayIntersectBillboard(arg0, uD3DBillboardIdx) )
+        {
+          v4 = pBillboardRenderList[(int)*v7].sZValue;
+          v5 = &a3->array_0004[a3->uNumPointers];
+          v5->pObjectInfo = *v7;
+          v5 = (Vis_stru1_stru0 *)((char *)v5 + 4);
+          v5->pObjectInfo = (void *)v4;
+          v5->sZValue = 1;
+          ++a3->uNumPointers;
+        }
+      }
+      ++uD3DBillboardIdx;
+      v7 += 39;
+    }
+    while ( (signed int)uD3DBillboardIdx < (signed int)pRenderer->uNumBillboardsToDraw );
+  }
+}
+
+//----- (004C0791) --------------------------------------------------------
+bool Vis::is_part_of_selection(BLVFace *uD3DBillboardIdx_or_pBLVFace_or_pODMFace, stru157 *a2)
+{
+  stru157 *v3; // esi@1
+  int result; // eax@1
+  int v5; // edx@2
+  int v6; // ecx@2
+  char v7; // zf@3
+  int v8; // esi@5
+  std::string *v9; // ecx@7
+  Actor *v10; // edi@18
+  char v11; // zf@26
+  const char *v12; // [sp-20h] [bp-2Ch]@7
+  int v13; // [sp-1Ch] [bp-28h]@7
+  std::string v14; // [sp-18h] [bp-24h]@7
+  const char *v15; // [sp-8h] [bp-14h]@7
+  int v16; // [sp-4h] [bp-10h]@7
+
+  v3 = a2;
+  result = a2->field_0;
+  if ( a2->field_0 != 1 )
+  {
+    if ( result != 2
+      || (uCurrentlyLoadedLevelType != LEVEL_Indoor ? (v11 = LOWORD(uD3DBillboardIdx_or_pBLVFace_or_pODMFace[3].pFacePlane.vNormal.y) == 0,
+                                            result = uD3DBillboardIdx_or_pBLVFace_or_pODMFace->pFacePlane_old.dist) : (v11 = pIndoor->pFaceExtras[uD3DBillboardIdx_or_pBLVFace_or_pODMFace->uFaceExtraID].uEventID == 0, result = uD3DBillboardIdx_or_pBLVFace_or_pODMFace->uAttributes),
+          a2->field_4 != 1) )
+      goto LABEL_16;
+    if ( v11 || result & a2->field_C )
+      goto LABEL_33;
+    v7 = (result & a2->field_8) == 0;
+    goto LABEL_32;
+  }
+  v5 = a2->field_10;
+  result = (pBillboardRenderList[pRenderer->pBillboardRenderListD3D[(int)uD3DBillboardIdx_or_pBLVFace_or_pODMFace].uParentBillboardID].sZValue & 0xFFFF) >> 3;
+  v6 = pBillboardRenderList[pRenderer->pBillboardRenderListD3D[(int)uD3DBillboardIdx_or_pBLVFace_or_pODMFace].uParentBillboardID].sZValue & 7;
+  if ( v5 & 2 )
+  {
+    v7 = v6 == a2->field_4;
+    goto LABEL_32;
+  }
+  if ( v5 & 4 )
+  {
+    v8 = a2->field_4;
+    if ( v6 != v8 )
+      goto LABEL_16;
+    if ( v8 != 5 )
+    {
+      v15 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:207";
+      v12 = "Unsupported \"exclusion if no event\" type in CVis::is_part_of_selection";
+LABEL_15:
+          MessageBoxA(nullptr, v12, v15, 0);
+      return true;
+    }
+    result *= 32;
+    if ( *(__int16 *)((char *)&pLevelDecorations[0].uCog + result)
+      || *(__int16 *)((char *)&pLevelDecorations[0].field_16_event_id + result) )
+      goto LABEL_16;
+    result = pLevelDecorations[result / sizeof(LevelDecoration)].IsInteractive();
+    goto LABEL_11;
+  }
+  if ( v6 == a2->field_4 )
+  {
+    if ( v6 != 3 )
+    {
+      v15 = "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:245";
+      v12 = "Default case reached in VIS";
+      goto LABEL_15;
+    }
+    v10 = &pActors[result];
+    result = 1 << LOBYTE(v10->uAIState);
+    if ( result & a2->field_C
+      || !(result & a2->field_8)
+      || v5 & 8 && (result = MonsterStats::BelongsToSupertype(v10->pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD)) == 0 )
+      goto LABEL_33;
+    if ( !(v3->field_10 & 1) )
+      goto LABEL_16;
+    result = v10->GetActorsRelation(nullptr);
+LABEL_11:
+    v7 = result == 0;
+LABEL_32:
+    if ( v7 )
+      goto LABEL_33;
+LABEL_16:
+    return true;
+  }
+LABEL_33:
+  LOBYTE(result) = 0;
+  return result;
+}
+
+//----- (004C091D) --------------------------------------------------------
+bool Vis::DoesRayIntersectBillboard(float fDepth, unsigned int uD3DBillboardIdx)
+{
+  unsigned int v3; // esi@3
+  bool result; // eax@3
+  int v5; // ecx@4
+  double v6; // st7@4
+  __int16 v7; // fps@4
+  double v8; // st7@4
+  unsigned __int8 v9; // c0@4
+  char v10; // c2@4
+  unsigned __int8 v11; // c3@4
+  Vis_stru1_stru0 *v12; // eax@10
+  __int16 v13; // fps@16
+  double v14; // st7@16
+  char v15; // c0@16
+  char v16; // c2@16
+  char v17; // c3@16
+  double v18; // st7@18
+  double v19; // st6@18
+  double v20; // st4@18
+  float v21; // ST0C_4@22
+  float v22; // ST08_4@22
+  signed int v23; // eax@27
+  double v24; // st7@32
+  double v25; // st6@32
+  float v26; // eax@32
+  double v27; // st7@36
+  double v28; // st6@36
+  __int16 v29; // fps@36
+  char v30; // c0@36
+  char v31; // c2@36
+  char v32; // c3@36
+  double v33; // st6@37
+  __int16 v34; // fps@37
+  char v35; // c0@37
+  char v36; // c2@37
+  char v37; // c3@37
+  __int16 v38; // fps@38
+  double v39; // st6@38
+  unsigned __int8 v40; // c0@38
+  char v41; // c2@38
+  unsigned __int8 v42; // c3@38
+  __int16 v43; // fps@39
+  double v44; // st6@39
+  char v45; // c0@39
+  char v46; // c2@39
+  char v47; // c3@39
+  Vis *v48; // esi@40
+  float v49; // ST08_4@40
+  Vis_stru1_stru0 *v50; // eax@45
+  RenderVertexSoft pRay[2]; // [sp+20h] [bp-DCh]@5
+  RenderVertexSoft a3[2]; // [sp+80h] [bp-7Ch]@22
+  float v53; // [sp+E0h] [bp-1Ch]@33
+  float v54; // [sp+E4h] [bp-18h]@32
+  float fBillboardCenterX; // [sp+E8h] [bp-14h]@5
+  float fBillboardCenterY; // [sp+ECh] [bp-10h]@5
+  unsigned int v57; // [sp+F0h] [bp-Ch]@5
+  float v58; // [sp+F4h] [bp-8h]@17
+  Vis *thisa; // [sp+F8h] [bp-4h]@1
+  signed int a3a; // [sp+108h] [bp+Ch]@17
+  float a3b; // [sp+108h] [bp+Ch]@32
+
+  thisa = this;
+
+  static Vis_stru1 Vis_static_stru_F91E10;
+
+  Vis_static_stru_F91E10.uNumPointers = 0;
+  v3 = uD3DBillboardIdx;
+  result = pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].uParentBillboardID;
+  if ( result != -1
+    && (v5 = pBillboardRenderList[result].sZValue,
+        v6 = (double)(unsigned __int16)pBillboardRenderList[result].sZValue,
+        result = v5 >> 16,
+        v8 = v6 * 0.000015259022 + (double)(v5 >> 16),
+        //UNDEF(v7),
+        v9 = v8 < fDepth,
+        v10 = 0,
+        v11 = v8 == fDepth,
+        BYTE1(result) = HIBYTE(v7),
+        v9 | v11) )
+  {
+    LOWORD(v5) = 0;
+    v57 = v5;
+    GetPolygonCenter(
+      pRenderer->pBillboardRenderListD3D[v3].pQuards,
+      4u,
+      &fBillboardCenterX,
+      &fBillboardCenterY);
+    CastPickRay(pRay, fBillboardCenterX, fBillboardCenterY, fDepth);
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+      PickIndoor(fDepth, pRay, &Vis_static_stru_F91E10, &a5);
+    else
+      PickOutdoor(fDepth, pRay, &Vis_static_stru_F91E10, &a5, 0);
+    Vis_static_stru_F91E10.create_object_pointers(0);
+    sort_object_pointers(Vis_static_stru_F91E10.array_1804, 0, Vis_static_stru_F91E10.uNumPointers - 1);
+    HIWORD(result) = HIWORD(Vis_static_stru_F91E10.uNumPointers);
+    if ( Vis_static_stru_F91E10.uNumPointers
+      && ((signed int)Vis_static_stru_F91E10.uNumPointers <= 0 ? (v12 = 0) : (v12 = Vis_static_stru_F91E10.array_1804[0]),
+          result = v12->sZValue,
+          LOWORD(result) = 0,
+          result <= v57)
+      || (double)(signed int)pViewport->uScreenX > fBillboardCenterX
+      || (double)(signed int)pViewport->uScreenZ < fBillboardCenterX
+      || (double)(signed int)pViewport->uScreenY > fBillboardCenterY
+      || (v14 = (double)(signed int)pViewport->uScreenW,
+          //UNDEF(v13),
+          v15 = v14 < fBillboardCenterY,
+          v16 = 0,
+          v17 = v14 == fBillboardCenterY,
+          BYTE1(result) = HIBYTE(v13),
+          v14 < fBillboardCenterY) )
+    {
+      a3a = 0;
+      result = (bool)&pRenderer->pBillboardRenderListD3D[v3].pQuards[0].pos.y;
+
+      __debugbreak();
+      {
+      LODWORD(v58) = (int)((char *)&pRenderer + v3 * 156 + 1062620);// pBillboardRenderListD3D+0x0C
+      }
+
+      while ( 1 )
+      {
+        v18 = *(float *)(result - 4);
+        v19 = *(float *)result;
+        v20 = *(float *)(result - 4);
+        Vis_static_stru_F91E10.uNumPointers = 0;
+        if ( v20 >= (double)(signed int)pViewport->uScreenX )
+        {
+          if ( v18 <= (double)(signed int)pViewport->uScreenZ
+            && v19 >= (double)(signed int)pViewport->uScreenY
+            && v19 <= (double)(signed int)pViewport->uScreenW )
+          {
+            v21 = v19;
+            v22 = v18;
+            CastPickRay(a3, v22, v21, fDepth);
+            if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+              PickIndoor(fDepth, a3, &Vis_static_stru_F91E10, &a5);
+            else
+              PickOutdoor(fDepth, a3, &Vis_static_stru_F91E10, &a5, 0);
+            Vis_static_stru_F91E10.create_object_pointers(0);
+            sort_object_pointers(
+              Vis_static_stru_F91E10.array_1804,
+              0,
+              Vis_static_stru_F91E10.uNumPointers - 1);
+            result = Vis_static_stru_F91E10.uNumPointers;
+            if ( !Vis_static_stru_F91E10.uNumPointers )
+              break;
+            v23 = (signed int)(Vis_static_stru_F91E10.uNumPointers <= 0 ? 0 : Vis_static_stru_F91E10.array_1804[0]);
+            result = *(int *)(v23 + 4);
+            LOWORD(result) = 0;
+            if ( result > v57 )
+              break;
+          }
+        }
+        ++a3a;
+        result = LODWORD(v58) + 32;
+        LODWORD(v58) += 32;
+        if ( a3a >= 4 )
+        {
+          if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+            goto LABEL_49;
+          v24 = pRenderer->pBillboardRenderListD3D[v3].pQuards[0].pos.x;
+          v25 = pRenderer->pBillboardRenderListD3D[v3].pQuards[3].pos.x;
+          v26 = pRenderer->pBillboardRenderListD3D[v3].pQuards[0].pos.y;
+          v54 = pRenderer->pBillboardRenderListD3D[v3].pQuards[3].pos.x;
+          v58 = v26;
+          result = LODWORD(pRenderer->pBillboardRenderListD3D[v3].pQuards[1].pos.y);
+          a3b = pRenderer->pBillboardRenderListD3D[v3].pQuards[1].pos.y;
+          if ( v24 > v25 )
+          {
+            v53 = v24;
+            v24 = v54;
+            v25 = v53;
+          }
+          if ( v58 > (double)a3b )
+            a3b = v58;
+          if ( (Vis_static_stru_F91E10.uNumPointers = 0,
+                v27 = (v25 - v24) * 0.5,
+                v28 = (double)(signed int)pViewport->uScreenX,
+                //UNDEF(v29),
+                v30 = v27 < v28,
+                v31 = 0,
+                v32 = v27 == v28,
+                BYTE1(result) = HIBYTE(v29),
+                v27 < v28)
+            || (v33 = (double)(signed int)pViewport->uScreenZ,
+                //UNDEF(v34),
+                v35 = v27 < v33,
+                v36 = 0,
+                v37 = v27 == v33,
+                BYTE1(result) = HIBYTE(v34),
+                v27 > v33)
+            || (v39 = (double)(signed int)pViewport->uScreenY,
+                //UNDEF(v38),
+                v40 = v39 < a3b,
+                v41 = 0,
+                v42 = v39 == a3b,
+                BYTE1(result) = HIBYTE(v38),
+                !(v40 | v42))
+            || (v44 = (double)(signed int)pViewport->uScreenW,
+                //UNDEF(v43),
+                v45 = v44 < a3b,
+                v46 = 0,
+                v47 = v44 == a3b,
+                BYTE1(result) = HIBYTE(v43),
+                v44 < a3b)
+            || ((v48 = thisa, v49 = v27, CastPickRay(a3, v49, a3b, fDepth), uCurrentlyLoadedLevelType != LEVEL_Indoor) ? PickOutdoor(fDepth, a3, &Vis_static_stru_F91E10, &a5, 0) : PickIndoor(fDepth, a3, &Vis_static_stru_F91E10, &a5),
+                (Vis_static_stru_F91E10.create_object_pointers(0),
+                 sort_object_pointers(
+                   Vis_static_stru_F91E10.array_1804,
+                   0,
+                   Vis_static_stru_F91E10.uNumPointers - 1),
+                 (result = Vis_static_stru_F91E10.uNumPointers) != 0)
+             && ((signed int)Vis_static_stru_F91E10.uNumPointers <= 0 ? (v50 = 0) : (v50 = Vis_static_stru_F91E10.array_1804[0]),
+                 result = v50->sZValue,
+                 LOWORD(result) = 0,
+                 result <= v57)) )
+            goto LABEL_49;
+          break;
+        }
+      }
+    }
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+LABEL_49:
+    return false;
+  }
+  return result;
+}
+// F93E18: using guessed type char static_byte_F93E18_init;
+
+//----- (004C0D32) --------------------------------------------------------
+int Vis::_4C0D32_BLV(float a1, Vis_stru1 *arg4, stru157 *a2)
+{
+  int result; // eax@1
+  signed int v5; // esi@2
+  BLVFace *v6; // edi@4
+  unsigned int v7; // eax@6
+  Vis_stru1_stru0 *v8; // eax@6
+  int v9; // ST18_4@7
+  unsigned int v10; // ST1C_4@7
+  unsigned int v11; // ecx@7
+  signed int i; // [sp+18h] [bp-8h]@1
+  Vis *thisa; // [sp+1Ch] [bp-4h]@1
+
+  result = 0;
+  thisa = this;
+  for ( i = 0; i < (signed int)pBspRenderer->uNumFaceIDs; ++i )
+  {
+    v5 = pBspRenderer->pFaceIDs[2 * result];
+    if ( v5 >= 0 )
+    {
+      if ( v5 < (signed int)pIndoor->uNumFaces )
+      {
+        v6 = &pIndoor->pFaces[v5];
+        if ( !pGame->pIndoorCameraD3D->IsCulled(&pIndoor->pFaces[v5]) )
+        {
+          if ( is_part_of_selection(v6, a2) )
+          {
+            v7 = 8 * v5;
+            LOBYTE(v7) = 8 * v5 | 6;
+            v8 = _4C1026(v6, v7, a1);
+            if ( v8 )
+            {
+              v9 = v8->sZValue;
+              v10 = v8->uObjectType;
+              v11 = 3 * arg4->uNumPointers;
+              arg4->array_0004[arg4->uNumPointers].pObjectInfo = v8->pObjectInfo;
+              arg4->array_0004[4 * v11 / 0xC].sZValue = v9;
+              arg4->array_0004[4 * v11 / 0xC].uObjectType = v10;
+              ++arg4->uNumPointers;
+            }
+          }
+        }
+      }
+    }
+    result = i + 1;
+  }
+  return result;
+}
+
+//----- (004C0DEA) --------------------------------------------------------
+void Vis::_4C0DEA_ODM(float arg0, Vis_stru1 *a3, stru157 *a2)
+{
+  int v4; // esi@1
+  BSPModel *v5; // ebx@3
+  unsigned __int8 v6; // zf@5
+  char v7; // sf@5
+  unsigned __int8 v8; // of@5
+  ODMFace *v9; // esi@7
+  unsigned int v10; // eax@8
+  Vis_stru1_stru0 *v11; // eax@8
+  unsigned int v12; // ecx@9
+  BLVFace f; // [sp+10h] [bp-84h]@1
+  void *v14; // [sp+70h] [bp-24h]@9
+  int v15; // [sp+74h] [bp-20h]@9
+  unsigned int v16; // [sp+78h] [bp-1Ch]@9
+  int v17; // [sp+7Ch] [bp-18h]@1
+  Vis *v18; // [sp+80h] [bp-14h]@1
+  int v19; // [sp+84h] [bp-10h]@6
+  unsigned int v20; // [sp+88h] [bp-Ch]@2
+  int v21; // [sp+8Ch] [bp-8h]@5
+  int a1; // [sp+90h] [bp-4h]@1
+
+  auto ecx0 = this;
+  v18 = ecx0;
+  v4 = 0;
+  v17 = 0;
+  a1 = 0;
+  if ( (signed int)pOutdoor->uNumBModels > 0 )
+  {
+    v20 = 0;
+    do
+    {
+      v5 = &pOutdoor->pBModels[v20 / 0xBC];
+      if ( IsBModelVisible(a1, &v17) )
+      {
+        if ( v17 != v4 )
+        {
+          v8 = __OFSUB__(v5->uNumFaces, v4);
+          v6 = v5->uNumFaces == v4;
+          v7 = ((v5->uNumFaces - v4) & 0x80000000u) != 0;
+          v21 = v4;
+          if ( !((unsigned __int8)(v7 ^ v8) | v6) )
+          {
+            v19 = v4;
+            do
+            {
+              v9 = (ODMFace *)((char *)v5->pFaces + v19);
+              if ( is_part_of_selection((BLVFace *)((char *)v5->pFaces + v19), a2) )
+              {
+                f.FromODM(v9);
+                v10 = 8 * (v21 | (a1 << 6));
+                LOBYTE(v10) = v10 | 6;
+                v11 = _4C1026(&f, v10, arg0);
+                if ( v11 )
+                {
+                  v14 = v11->pObjectInfo;
+                  v15 = v11->sZValue;
+                  v12 = a3->uNumPointers;
+                  v16 = v11->uObjectType;
+                  v12 *= 3;
+                  *((int *)&a3->array_0004[0].pObjectInfo + v12) = (int)v14;
+                  *(&a3->array_0004[0].sZValue + v12) = v15;
+                  *(&a3->array_0004[0].uObjectType + v12) = v16;
+                  ++a3->uNumPointers;
+                }
+              }
+              ++v21;
+              v19 += 308;
+            }
+            while ( v21 < (signed int)v5->uNumFaces );
+            v4 = 0;
+          }
+        }
+      }
+      ++a1;
+      v20 += 188;
+    }
+    while ( a1 < (signed int)pOutdoor->uNumBModels );
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vis.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,84 @@
+#pragma once
+#include "Render.h"
+
+
+
+
+
+
+#pragma pack(push, 1)
+struct Vis_stru1_stru0
+{
+  void *pObjectInfo;
+  int sZValue;
+  unsigned int uObjectType;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct Vis_stru1
+{
+  Vis_stru1();
+  //----- (004C0585) --------------------------------------------------------
+  ~Vis_stru1() {}
+  Vis_stru1_stru0 *sub_4C2551(int a2, int a3);
+  Vis_stru1_stru0 **create_object_pointers(unsigned int flag);
+
+  void (__thiscall ***vdestructor_ptr)(Vis_stru1 *, bool);
+  Vis_stru1_stru0 array_0004[512];
+  Vis_stru1_stru0 *array_1804[512];
+  unsigned int uNumPointers;
+};
+#pragma pack(pop)
+
+
+
+/*  116 */
+#pragma pack(push, 1)
+struct Vis
+{
+  Vis();
+  //----- (004C05A2) --------------------------------------------------------
+  //virtual ~Vis() {}
+  //----- (004C05BE) --------------------------------------------------------
+  ~Vis() {}
+  bool _4C05CC(Vis_stru1 *a2, struct stru157 *a3, struct stru157 *a4);
+  bool PickMouse(float fDepth, float fMouseX, float fMouseY, struct stru157 *a5, struct stru157 *a6);
+  void _4C06F8(float arg0, Vis_stru1 *a3, struct stru157 *a2);
+  bool is_part_of_selection(struct BLVFace *uD3DBillboardIdx_or_pBLVFace_or_pODMFace, struct stru157 *a2);
+  bool DoesRayIntersectBillboard(float fDepth, unsigned int uD3DBillboardIdx);
+  int _4C0D32_BLV(float a1, Vis_stru1 *arg4, struct stru157 *a2);
+  void _4C0DEA_ODM(float arg0, Vis_stru1 *a3, struct stru157 *a2);
+  Vis_stru1_stru0 *_4C1026(struct BLVFace *a2, unsigned int a3, float a4);
+  char _4C12C3_FindSomeBillboard(struct RenderVertexSoft *a1, int a2, float a3, float a4);
+  void GetPolygonCenter(struct RenderVertexD3D3 *pVertices, unsigned int uNumVertices, float *pCenterX, float *pCenterY);
+  float *_4C1495(struct RenderVertexSoft *Src, int a2, float *a3, float *a4);
+  void PickBillboards(float fPickDepth, float fX, float fY, Vis_stru1 *a4, stru157 *a2);
+  bool IsPointInsideD3DBillboard(struct RenderBillboardD3D *a1, float x, float y);
+  void PickIndoor(float fDepth, struct RenderVertexSoft *pRay, Vis_stru1 *a4, stru157 *a5);
+  void PickOutdoor(float fDepth, struct RenderVertexSoft *pRay, Vis_stru1 *a4, stru157 *a5, char a6);
+  int _4C1944(int a2, unsigned int a3, int a4, int a5, int a6);
+  void _4C1A02();
+  bool SortVectors_x(RenderVertexSoft *a2, int a3, int a4);
+  int get_object_zbuf_val(Vis_stru1_stru0 *a2);
+  int get_picked_object_zbuf_val();
+  bool Intersect_Ray_Face(struct RenderVertexSoft *pRayStart, struct RenderVertexSoft *pRayEnd, float *pDepth, RenderVertexSoft *a4, BLVFace *a5, unsigned int a6);
+  int _4C1D2B(BLVFace *pFace, Vec3_short_ a2, unsigned int uModelID);
+  bool _4C1EE5_BLV_IntersectBModel_2(int *a1, int *a2, __int16 *a3, __int16 *a4, Vec3_short_ *a5, BLVFace *pFace);
+  bool _4C2186_BLV_IntersectBModel(int *a1, int *a2, __int16 *a3, __int16 *a4, Vec3_short_ *a5, BLVFace *a6, unsigned int uModelID);
+  void CastPickRay(RenderVertexSoft *pRay, float fMouseX, float fMouseY, float fPickDepth);
+  void sort_object_pointers(Vis_stru1_stru0 **pPointers, int left, int right);
+  bool SortVerticesByX(struct RenderVertexD3D3 *a2, unsigned int uStart, unsigned int uEnd);
+  bool SortVerticesByY(struct RenderVertexD3D3 *a2, unsigned int uStart, unsigned int uEnd);
+  bool sort_objects_2(struct RenderVertexSoft *pArray, int sLeft, int sRight);
+  bool sort_objects_3(struct RenderVertexSoft *pArray, int sLeft, int sRight);
+
+  void (__thiscall ***vdestructor_ptr)(Vis *, bool);
+  Vis_stru1 stru1;
+  RenderVertexSoft stru_200C;
+  RenderVertexSoft stru_203C;
+  RenderVertexSoft stru_206C;
+  RenderVertexSoft stru_209C;
+  int field_20CC;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Weather.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,244 @@
+#include <stdlib.h>
+
+#include "Weather.h"
+#include "Viewport.h"
+#include "Render.h"
+
+#include "mm7_data.h"
+
+
+
+
+struct Weather *pWeather = new Weather;
+
+
+
+//----- (004C2AA6) --------------------------------------------------------
+int Weather::DrawSnow()
+{
+  unsigned __int16 *v1; // edi@1
+  __int16 *v2; // esi@2
+  int v3; // eax@2
+  signed int v4; // eax@6
+  int v5; // edx@8
+  __int16 *v6; // esi@11
+  __int16 *v7; // eax@11
+  int v8; // ecx@11
+  int v9; // eax@12
+  int v10; // ecx@16
+  int v11; // edx@18
+  Weather *v12; // eax@20
+  __int16 *v13; // esi@20
+  int v14; // eax@21
+  int v15; // eax@21
+  int v16; // edx@23
+  int v17; // eax@24
+  int v18; // edx@26
+  int v19; // ecx@27
+  int v20; // eax@27
+  char v21; // zf@27
+  unsigned int v23; // [sp+Ch] [bp-20h]@1
+  unsigned int v24; // [sp+10h] [bp-1Ch]@1
+  unsigned int v25; // [sp+14h] [bp-18h]@1
+  Weather *v26; // [sp+18h] [bp-14h]@1
+  signed int v27; // [sp+18h] [bp-14h]@20
+  unsigned int v28; // [sp+1Ch] [bp-10h]@1
+  unsigned int v29; // [sp+20h] [bp-Ch]@1
+  __int16 *v30; // [sp+24h] [bp-8h]@2
+  signed int v31; // [sp+28h] [bp-4h]@1
+  signed int v32; // [sp+28h] [bp-4h]@10
+
+  v26 = this;
+  v25 = viewparams->uScreenZ;
+  v28 = viewparams->uScreenY;
+  v31 = 0;
+  v1 = pRenderer->pTargetSurface;
+  v29 = viewparams->uScreenX;
+  v23 = viewparams->uScreenW;
+  v24 = viewparams->uScreenZ - viewparams->uScreenX;
+  do
+  {
+    v2 = &v26->field_0[2 * v31];
+    v30 = &v26->field_0[2 * v31 + 1];
+    *v2 += rand() % 3 + 1;
+    *v30 += rand() % 2 + 1;
+    v3 = *v2;
+    if ( v3 < (signed int)(v25 - 1) )
+    {
+      if ( v3 < (signed int)v29 )
+        *v2 = v25 - rand() % 8;
+    }
+    else
+    {
+      *v2 = v29 + rand() % 8;
+    }
+    v4 = *v30;
+    if ( v4 < (signed int)v28 || v4 >= (signed int)v23 )
+    {
+      v5 = rand() % (signed int)(v24 - 2);
+      *v30 = v28;
+      *v2 = v29 + v5;
+    }
+    ++v31;
+    v1[*v2 + 640 * *v30] = 0xFFFFu;
+  }
+  while ( v31 < 700 );
+  v32 = 700;
+  do
+  {
+    v6 = &v26->field_0[2 * v32];
+    *v6 += rand() % 5 - 3;
+    v7 = &v26->field_0[2 * v32 + 1];
+    v8 = *v6;
+    *v7 += 4;
+    if ( v8 < (signed int)v29 )
+    {
+      LOWORD(v9) = v25 - rand() % 4 - 2;
+LABEL_15:
+      *v6 = v9;
+      v7 = &v26->field_0[2 * v32 + 1];
+      goto LABEL_16;
+    }
+    if ( v8 >= (signed int)(v25 - 2) )
+    {
+      v9 = rand() % 4 + v29 + 2;
+      goto LABEL_15;
+    }
+LABEL_16:
+    v10 = *v7;
+    if ( v10 < (signed int)v28 || v10 >= (signed int)(v23 - 1) )
+    {
+      v11 = rand() % (signed int)(v24 - 2);
+      v26->field_0[2 * v32 + 1] = v28;
+      v7 = &v26->field_0[2 * v32 + 1];
+      *v6 = v29 + v11;
+    }
+    *(&v1[640 * *v7 + 1] + *v6) = 0xFFFFu;
+    *(&v1[640 * *v7 + 641] + *v6) = 0xFFFFu;
+    v1[*v6 + 640 * (*v7 + 1)] = 0xFFFFu;
+    ++v32;
+    v1[*v6 + 640 * *v7] = 0xFFFFu;
+  }
+  while ( v32 < 950 );
+  v12 = v26;
+  v27 = 50;
+  v13 = &v12->field_0[1901];
+  do
+  {
+    v14 = rand();
+    *v13 += 8;
+    *(v13 - 1) += v14 % 11 - 5;
+    v15 = *(v13 - 1);
+    if ( v15 < (signed int)v29 || v15 >= (signed int)(v25 - 5) )
+    {
+      v16 = rand() % (signed int)(v24 - 5);
+      *v13 = v28;
+      *(v13 - 1) = v29 + v16;
+    }
+    v17 = *v13;
+    if ( v17 < (signed int)v28 || v17 >= (signed int)(v23 - 5) )
+    {
+      v18 = rand() % (signed int)(v24 - 5);
+      *v13 = v28;
+      *(v13 - 1) = v29 + v18;
+    }
+    *(&v1[640 * *v13 + 1] + *(v13 - 1)) = 0xFFFFu;
+    *(&v1[640 * *v13 + 641] + *(v13 - 1)) = 0xFFFFu;
+    v1[*(v13 - 1) + 640 * (*v13 + 1)] = 0xFFFFu;
+    v1[*(v13 - 1) + 640 * *v13] = 0xFFFFu;
+    *(&v1[640 * *v13 + 1281] + *(v13 - 1)) = 0xFFFFu;
+    *(&v1[640 * *v13 + 1921] + *(v13 - 1)) = 0xFFFFu;
+    v1[*(v13 - 1) + 640 * (*v13 + 3)] = 0xFFFFu;
+    v1[*(v13 - 1) + 640 * (*v13 + 2)] = 0xFFFFu;
+    *(&v1[640 * *v13 + 3] + *(v13 - 1)) = 0xFFFFu;
+    *(&v1[640 * *v13 + 643] + *(v13 - 1)) = 0xFFFFu;
+    *(&v1[640 * *v13 + 642] + *(v13 - 1)) = 0xFFFFu;
+    *(&v1[640 * *v13 + 2] + *(v13 - 1)) = 0xFFFFu;
+    *(&v1[640 * *v13 + 1283] + *(v13 - 1)) = 0xFFFFu;
+    *(&v1[640 * *v13 + 1923] + *(v13 - 1)) = 0xFFFFu;
+    *(&v1[640 * *v13 + 1922] + *(v13 - 1)) = 0xFFFFu;
+    v19 = *(v13 - 1);
+    v20 = 5 * *v13;
+    v13 += 2;
+    v21 = v27-- == 1;
+    *(&v1[128 * v20 + 1282] + v19) = 0xFFFFu;
+  }
+  while ( !v21 );
+  return 0;
+}
+
+//----- (004C2EA0) --------------------------------------------------------
+int Weather::Initialize()
+{
+  Weather *v1; // edi@1
+  signed int v2; // esi@1
+  signed int v3; // ebx@1
+  signed int v4; // ebp@1
+
+  v1 = this;
+  v2 = 0;
+  v3 = pViewport->uScreenZ - pViewport->uScreenX - 4;
+  v4 = pViewport->uScreenW - pViewport->uScreenY - 4;
+  do
+  {
+    v1->field_0[2 * v2++] = LOWORD(pViewport->uViewportX) + rand() % v3;
+    *((short *)v1 + 2 * v2 - 1) = LOWORD(pViewport->uViewportY) + rand() % v4;
+  }
+  while ( v2 < 1000 );
+  return 0;
+}
+
+//----- (004C2EFA) --------------------------------------------------------
+int Weather::Draw()
+{
+  if (bRenderSnow)
+    DrawSnow();
+  return 0;
+}
+
+//----- (004C2F0B) --------------------------------------------------------
+bool Weather::_4C2F0B(__int16 a2)
+{
+  int v3; // edx@3
+  signed int v4; // ebx@3
+  unsigned int screen_width; // esi@3
+  __int16 *v6; // eax@5
+  signed int v7; // edi@5
+  unsigned int screen_x; // [sp+0h] [bp-Ch]@3
+  unsigned int screen_z_minus_4; // [sp+4h] [bp-8h]@3
+  Weather *v10; // [sp+8h] [bp-4h]@1
+
+  v10 = this;
+  if ( this->bRenderSnow != 1 )
+    return 0;
+  HIWORD(v3) = HIWORD(viewparams->uScreenX);
+  v4 = 0;
+  screen_width = viewparams->uScreenZ - viewparams->uScreenX;
+  screen_x = viewparams->uScreenX;
+  screen_z_minus_4 = viewparams->uScreenZ - 4;
+
+  auto _this = this->field_0;
+  while ( 1 )
+  {
+    v6 = &_this[2 * v4];
+    *v6 += a2;
+    LOWORD(v3) = *v6;
+    v7 = *v6;
+    if ( v7 < (signed int)screen_z_minus_4 )
+    {
+      if ( v7 >= (signed int)screen_x )
+        goto LABEL_10;
+      v3 += screen_width;
+    }
+    else
+    {
+      v3 = v3 - screen_width + 4;
+    }
+    *v6 = v3;
+LABEL_10:
+    ++v4;
+    if ( v4 >= 1000 )
+      return 1;
+    //_this = v10;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Weather.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,27 @@
+#pragma once
+
+
+
+
+
+
+/*  255 */
+#pragma pack(push, 1)
+struct Weather
+{
+  int DrawSnow();
+  int Initialize();
+  int Draw();
+  bool _4C2F0B(__int16 a2);
+
+
+
+  __int16 field_0[2000];
+  int field_FA0;
+  int bRenderSnow;
+};
+#pragma pack(pop)
+
+
+
+extern struct Weather *pWeather;
\ No newline at end of file
Binary file ipch/mm7-91968f84/mm7-c5fbce5d.ipch has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/d3d.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1688 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:   d3d.h
+ *  Content:    Direct3D include file
+ *
+ ****************************************************************************/
+
+#ifndef _D3D_H_
+#define _D3D_H_
+
+#ifndef DIRECT3D_VERSION
+#define DIRECT3D_VERSION         0x0700
+#endif
+
+// include this file content only if compiling for <=DX7 interfaces
+#if(DIRECT3D_VERSION < 0x0800)
+
+
+#include <stdlib.h>
+
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+
+#define D3DAPI WINAPI
+
+/*
+ * Interface IID's
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM)
+DEFINE_GUID( IID_IDirect3D,             0x3BBA0080,0x2421,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+#if(DIRECT3D_VERSION >= 0x0500)
+DEFINE_GUID( IID_IDirect3D2,            0x6aae1ec1,0x662a,0x11d0,0x88,0x9d,0x00,0xaa,0x00,0xbb,0xb7,0x6a);
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+#if(DIRECT3D_VERSION >= 0x0600)
+DEFINE_GUID( IID_IDirect3D3,            0xbb223240,0xe72b,0x11d0,0xa9,0xb4,0x00,0xaa,0x00,0xc0,0x99,0x3e);
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0700)
+DEFINE_GUID( IID_IDirect3D7,            0xf5049e77,0x4861,0x11d2,0xa4,0x7,0x0,0xa0,0xc9,0x6,0x29,0xa8);
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#if(DIRECT3D_VERSION >= 0x0500)
+DEFINE_GUID( IID_IDirect3DRampDevice,   0xF2086B20,0x259F,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirect3DRGBDevice,    0xA4665C60,0x2673,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirect3DHALDevice,    0x84E63dE0,0x46AA,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+DEFINE_GUID( IID_IDirect3DMMXDevice,    0x881949a1,0xd6f3,0x11d0,0x89,0xab,0x00,0xa0,0xc9,0x05,0x41,0x29 );
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+DEFINE_GUID( IID_IDirect3DRefDevice,    0x50936643, 0x13e9, 0x11d1, 0x89, 0xaa, 0x0, 0xa0, 0xc9, 0x5, 0x41, 0x29);
+DEFINE_GUID( IID_IDirect3DNullDevice, 0x8767df22, 0xbacc, 0x11d1, 0x89, 0x69, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8);
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0700)
+DEFINE_GUID( IID_IDirect3DTnLHalDevice, 0xf5049e78, 0x4861, 0x11d2, 0xa4, 0x7, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8);
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+/*
+ * Internal Guid to distinguish requested MMX from MMX being used as an RGB rasterizer
+ */
+
+DEFINE_GUID( IID_IDirect3DDevice,       0x64108800,0x957d,0X11d0,0x89,0xab,0x00,0xa0,0xc9,0x05,0x41,0x29 );
+#if(DIRECT3D_VERSION >= 0x0500)
+DEFINE_GUID( IID_IDirect3DDevice2,  0x93281501, 0x8cf8, 0x11d0, 0x89, 0xab, 0x0, 0xa0, 0xc9, 0x5, 0x41, 0x29);
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+#if(DIRECT3D_VERSION >= 0x0600)
+DEFINE_GUID( IID_IDirect3DDevice3,  0xb0ab3b60, 0x33d7, 0x11d1, 0xa9, 0x81, 0x0, 0xc0, 0x4f, 0xd7, 0xb1, 0x74);
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0700)
+DEFINE_GUID( IID_IDirect3DDevice7,  0xf5049e79, 0x4861, 0x11d2, 0xa4, 0x7, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8);
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+DEFINE_GUID( IID_IDirect3DTexture,      0x2CDCD9E0,0x25A0,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+#if(DIRECT3D_VERSION >= 0x0500)
+DEFINE_GUID( IID_IDirect3DTexture2, 0x93281502, 0x8cf8, 0x11d0, 0x89, 0xab, 0x0, 0xa0, 0xc9, 0x5, 0x41, 0x29);
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+DEFINE_GUID( IID_IDirect3DLight,        0x4417C142,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+
+DEFINE_GUID( IID_IDirect3DMaterial,     0x4417C144,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+#if(DIRECT3D_VERSION >= 0x0500)
+DEFINE_GUID( IID_IDirect3DMaterial2,    0x93281503, 0x8cf8, 0x11d0, 0x89, 0xab, 0x0, 0xa0, 0xc9, 0x5, 0x41, 0x29);
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+#if(DIRECT3D_VERSION >= 0x0600)
+DEFINE_GUID( IID_IDirect3DMaterial3,    0xca9c46f4, 0xd3c5, 0x11d1, 0xb7, 0x5a, 0x0, 0x60, 0x8, 0x52, 0xb3, 0x12);
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+DEFINE_GUID( IID_IDirect3DExecuteBuffer,0x4417C145,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+DEFINE_GUID( IID_IDirect3DViewport,     0x4417C146,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+#if(DIRECT3D_VERSION >= 0x0500)
+DEFINE_GUID( IID_IDirect3DViewport2,    0x93281500, 0x8cf8, 0x11d0, 0x89, 0xab, 0x0, 0xa0, 0xc9, 0x5, 0x41, 0x29);
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+#if(DIRECT3D_VERSION >= 0x0600)
+DEFINE_GUID( IID_IDirect3DViewport3,    0xb0ab3b61, 0x33d7, 0x11d1, 0xa9, 0x81, 0x0, 0xc0, 0x4f, 0xd7, 0xb1, 0x74);
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0600)
+DEFINE_GUID( IID_IDirect3DVertexBuffer, 0x7a503555, 0x4a83, 0x11d1, 0xa5, 0xdb, 0x0, 0xa0, 0xc9, 0x3, 0x67, 0xf8);
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0700)
+DEFINE_GUID( IID_IDirect3DVertexBuffer7, 0xf5049e7d, 0x4861, 0x11d2, 0xa4, 0x7, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8);
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+#endif
+
+#ifdef __cplusplus
+struct IDirect3D;
+struct IDirect3DDevice;
+struct IDirect3DLight;
+struct IDirect3DMaterial;
+struct IDirect3DExecuteBuffer;
+struct IDirect3DTexture;
+struct IDirect3DViewport;
+typedef struct IDirect3D            *LPDIRECT3D;
+typedef struct IDirect3DDevice      *LPDIRECT3DDEVICE;
+typedef struct IDirect3DExecuteBuffer   *LPDIRECT3DEXECUTEBUFFER;
+typedef struct IDirect3DLight       *LPDIRECT3DLIGHT;
+typedef struct IDirect3DMaterial    *LPDIRECT3DMATERIAL;
+typedef struct IDirect3DTexture     *LPDIRECT3DTEXTURE;
+typedef struct IDirect3DViewport    *LPDIRECT3DVIEWPORT;
+
+#if(DIRECT3D_VERSION >= 0x0500)
+struct IDirect3D2;
+struct IDirect3DDevice2;
+struct IDirect3DMaterial2;
+struct IDirect3DTexture2;
+struct IDirect3DViewport2;
+typedef struct IDirect3D2           *LPDIRECT3D2;
+typedef struct IDirect3DDevice2     *LPDIRECT3DDEVICE2;
+typedef struct IDirect3DMaterial2   *LPDIRECT3DMATERIAL2;
+typedef struct IDirect3DTexture2    *LPDIRECT3DTEXTURE2;
+typedef struct IDirect3DViewport2   *LPDIRECT3DVIEWPORT2;
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+struct IDirect3D3;
+struct IDirect3DDevice3;
+struct IDirect3DMaterial3;
+struct IDirect3DViewport3;
+struct IDirect3DVertexBuffer;
+typedef struct IDirect3D3            *LPDIRECT3D3;
+typedef struct IDirect3DDevice3      *LPDIRECT3DDEVICE3;
+typedef struct IDirect3DMaterial3    *LPDIRECT3DMATERIAL3;
+typedef struct IDirect3DViewport3    *LPDIRECT3DVIEWPORT3;
+typedef struct IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER;
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+struct IDirect3D7;
+struct IDirect3DDevice7;
+struct IDirect3DVertexBuffer7;
+typedef struct IDirect3D7             *LPDIRECT3D7;
+typedef struct IDirect3DDevice7       *LPDIRECT3DDEVICE7;
+typedef struct IDirect3DVertexBuffer7 *LPDIRECT3DVERTEXBUFFER7;
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#else
+
+typedef struct IDirect3D        *LPDIRECT3D;
+typedef struct IDirect3DDevice      *LPDIRECT3DDEVICE;
+typedef struct IDirect3DExecuteBuffer   *LPDIRECT3DEXECUTEBUFFER;
+typedef struct IDirect3DLight       *LPDIRECT3DLIGHT;
+typedef struct IDirect3DMaterial    *LPDIRECT3DMATERIAL;
+typedef struct IDirect3DTexture     *LPDIRECT3DTEXTURE;
+typedef struct IDirect3DViewport    *LPDIRECT3DVIEWPORT;
+
+#if(DIRECT3D_VERSION >= 0x0500)
+typedef struct IDirect3D2           *LPDIRECT3D2;
+typedef struct IDirect3DDevice2     *LPDIRECT3DDEVICE2;
+typedef struct IDirect3DMaterial2   *LPDIRECT3DMATERIAL2;
+typedef struct IDirect3DTexture2    *LPDIRECT3DTEXTURE2;
+typedef struct IDirect3DViewport2   *LPDIRECT3DVIEWPORT2;
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+typedef struct IDirect3D3            *LPDIRECT3D3;
+typedef struct IDirect3DDevice3      *LPDIRECT3DDEVICE3;
+typedef struct IDirect3DMaterial3    *LPDIRECT3DMATERIAL3;
+typedef struct IDirect3DViewport3    *LPDIRECT3DVIEWPORT3;
+typedef struct IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER;
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+typedef struct IDirect3D7             *LPDIRECT3D7;
+typedef struct IDirect3DDevice7       *LPDIRECT3DDEVICE7;
+typedef struct IDirect3DVertexBuffer7 *LPDIRECT3DVERTEXBUFFER7;
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#endif
+
+#include "d3dtypes.h"
+#include "d3dcaps.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Direct3D interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3D
+
+DECLARE_INTERFACE_(IDirect3D, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3D methods ***/
+    STDMETHOD(Initialize)(THIS_ REFCLSID) PURE;
+    STDMETHOD(EnumDevices)(THIS_ LPD3DENUMDEVICESCALLBACK,LPVOID) PURE;
+    STDMETHOD(CreateLight)(THIS_ LPDIRECT3DLIGHT*,IUnknown*) PURE;
+    STDMETHOD(CreateMaterial)(THIS_ LPDIRECT3DMATERIAL*,IUnknown*) PURE;
+    STDMETHOD(CreateViewport)(THIS_ LPDIRECT3DVIEWPORT*,IUnknown*) PURE;
+    STDMETHOD(FindDevice)(THIS_ LPD3DFINDDEVICESEARCH,LPD3DFINDDEVICERESULT) PURE;
+};
+
+typedef struct IDirect3D *LPDIRECT3D;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3D_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3D_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3D_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3D_Initialize(p,a) (p)->lpVtbl->Initialize(p,a)
+#define IDirect3D_EnumDevices(p,a,b) (p)->lpVtbl->EnumDevices(p,a,b)
+#define IDirect3D_CreateLight(p,a,b) (p)->lpVtbl->CreateLight(p,a,b)
+#define IDirect3D_CreateMaterial(p,a,b) (p)->lpVtbl->CreateMaterial(p,a,b)
+#define IDirect3D_CreateViewport(p,a,b) (p)->lpVtbl->CreateViewport(p,a,b)
+#define IDirect3D_FindDevice(p,a,b) (p)->lpVtbl->FindDevice(p,a,b)
+#else
+#define IDirect3D_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3D_AddRef(p) (p)->AddRef()
+#define IDirect3D_Release(p) (p)->Release()
+#define IDirect3D_Initialize(p,a) (p)->Initialize(a)
+#define IDirect3D_EnumDevices(p,a,b) (p)->EnumDevices(a,b)
+#define IDirect3D_CreateLight(p,a,b) (p)->CreateLight(a,b)
+#define IDirect3D_CreateMaterial(p,a,b) (p)->CreateMaterial(a,b)
+#define IDirect3D_CreateViewport(p,a,b) (p)->CreateViewport(a,b)
+#define IDirect3D_FindDevice(p,a,b) (p)->FindDevice(a,b)
+#endif
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#undef INTERFACE
+#define INTERFACE IDirect3D2
+
+DECLARE_INTERFACE_(IDirect3D2, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3D2 methods ***/
+    STDMETHOD(EnumDevices)(THIS_ LPD3DENUMDEVICESCALLBACK,LPVOID) PURE;
+    STDMETHOD(CreateLight)(THIS_ LPDIRECT3DLIGHT*,IUnknown*) PURE;
+    STDMETHOD(CreateMaterial)(THIS_ LPDIRECT3DMATERIAL2*,IUnknown*) PURE;
+    STDMETHOD(CreateViewport)(THIS_ LPDIRECT3DVIEWPORT2*,IUnknown*) PURE;
+    STDMETHOD(FindDevice)(THIS_ LPD3DFINDDEVICESEARCH,LPD3DFINDDEVICERESULT) PURE;
+    STDMETHOD(CreateDevice)(THIS_ REFCLSID,LPDIRECTDRAWSURFACE,LPDIRECT3DDEVICE2*) PURE;
+};
+
+typedef struct IDirect3D2 *LPDIRECT3D2;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3D2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3D2_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3D2_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3D2_EnumDevices(p,a,b) (p)->lpVtbl->EnumDevices(p,a,b)
+#define IDirect3D2_CreateLight(p,a,b) (p)->lpVtbl->CreateLight(p,a,b)
+#define IDirect3D2_CreateMaterial(p,a,b) (p)->lpVtbl->CreateMaterial(p,a,b)
+#define IDirect3D2_CreateViewport(p,a,b) (p)->lpVtbl->CreateViewport(p,a,b)
+#define IDirect3D2_FindDevice(p,a,b) (p)->lpVtbl->FindDevice(p,a,b)
+#define IDirect3D2_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+#else
+#define IDirect3D2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3D2_AddRef(p) (p)->AddRef()
+#define IDirect3D2_Release(p) (p)->Release()
+#define IDirect3D2_EnumDevices(p,a,b) (p)->EnumDevices(a,b)
+#define IDirect3D2_CreateLight(p,a,b) (p)->CreateLight(a,b)
+#define IDirect3D2_CreateMaterial(p,a,b) (p)->CreateMaterial(a,b)
+#define IDirect3D2_CreateViewport(p,a,b) (p)->CreateViewport(a,b)
+#define IDirect3D2_FindDevice(p,a,b) (p)->FindDevice(a,b)
+#define IDirect3D2_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+#undef INTERFACE
+#define INTERFACE IDirect3D3
+
+DECLARE_INTERFACE_(IDirect3D3, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3D3 methods ***/
+    STDMETHOD(EnumDevices)(THIS_ LPD3DENUMDEVICESCALLBACK,LPVOID) PURE;
+    STDMETHOD(CreateLight)(THIS_ LPDIRECT3DLIGHT*,LPUNKNOWN) PURE;
+    STDMETHOD(CreateMaterial)(THIS_ LPDIRECT3DMATERIAL3*,LPUNKNOWN) PURE;
+    STDMETHOD(CreateViewport)(THIS_ LPDIRECT3DVIEWPORT3*,LPUNKNOWN) PURE;
+    STDMETHOD(FindDevice)(THIS_ LPD3DFINDDEVICESEARCH,LPD3DFINDDEVICERESULT) PURE;
+    STDMETHOD(CreateDevice)(THIS_ REFCLSID,LPDIRECTDRAWSURFACE4,LPDIRECT3DDEVICE3*,LPUNKNOWN) PURE;
+    STDMETHOD(CreateVertexBuffer)(THIS_ LPD3DVERTEXBUFFERDESC,LPDIRECT3DVERTEXBUFFER*,DWORD,LPUNKNOWN) PURE;
+    STDMETHOD(EnumZBufferFormats)(THIS_ REFCLSID,LPD3DENUMPIXELFORMATSCALLBACK,LPVOID) PURE;
+    STDMETHOD(EvictManagedTextures)(THIS) PURE;
+};
+
+typedef struct IDirect3D3 *LPDIRECT3D3;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3D3_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3D3_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3D3_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3D3_EnumDevices(p,a,b) (p)->lpVtbl->EnumDevices(p,a,b)
+#define IDirect3D3_CreateLight(p,a,b) (p)->lpVtbl->CreateLight(p,a,b)
+#define IDirect3D3_CreateMaterial(p,a,b) (p)->lpVtbl->CreateMaterial(p,a,b)
+#define IDirect3D3_CreateViewport(p,a,b) (p)->lpVtbl->CreateViewport(p,a,b)
+#define IDirect3D3_FindDevice(p,a,b) (p)->lpVtbl->FindDevice(p,a,b)
+#define IDirect3D3_CreateDevice(p,a,b,c,d) (p)->lpVtbl->CreateDevice(p,a,b,c,d)
+#define IDirect3D3_CreateVertexBuffer(p,a,b,c,d) (p)->lpVtbl->CreateVertexBuffer(p,a,b,c,d)
+#define IDirect3D3_EnumZBufferFormats(p,a,b,c) (p)->lpVtbl->EnumZBufferFormats(p,a,b,c)
+#define IDirect3D3_EvictManagedTextures(p) (p)->lpVtbl->EvictManagedTextures(p)
+#else
+#define IDirect3D3_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3D3_AddRef(p) (p)->AddRef()
+#define IDirect3D3_Release(p) (p)->Release()
+#define IDirect3D3_EnumDevices(p,a,b) (p)->EnumDevices(a,b)
+#define IDirect3D3_CreateLight(p,a,b) (p)->CreateLight(a,b)
+#define IDirect3D3_CreateMaterial(p,a,b) (p)->CreateMaterial(a,b)
+#define IDirect3D3_CreateViewport(p,a,b) (p)->CreateViewport(a,b)
+#define IDirect3D3_FindDevice(p,a,b) (p)->FindDevice(a,b)
+#define IDirect3D3_CreateDevice(p,a,b,c,d) (p)->CreateDevice(a,b,c,d)
+#define IDirect3D3_CreateVertexBuffer(p,a,b,c,d) (p)->CreateVertexBuffer(a,b,c,d)
+#define IDirect3D3_EnumZBufferFormats(p,a,b,c) (p)->EnumZBufferFormats(a,b,c)
+#define IDirect3D3_EvictManagedTextures(p) (p)->EvictManagedTextures()
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+#undef INTERFACE
+#define INTERFACE IDirect3D7
+
+DECLARE_INTERFACE_(IDirect3D7, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3D7 methods ***/
+    STDMETHOD(EnumDevices)(THIS_ LPD3DENUMDEVICESCALLBACK7,LPVOID) PURE;
+    STDMETHOD(CreateDevice)(THIS_ REFCLSID,LPDIRECTDRAWSURFACE7,LPDIRECT3DDEVICE7*) PURE;
+    STDMETHOD(CreateVertexBuffer)(THIS_ LPD3DVERTEXBUFFERDESC,LPDIRECT3DVERTEXBUFFER7*,DWORD) PURE;
+    STDMETHOD(EnumZBufferFormats)(THIS_ REFCLSID,LPD3DENUMPIXELFORMATSCALLBACK,LPVOID) PURE;
+    STDMETHOD(EvictManagedTextures)(THIS) PURE;
+};
+
+typedef struct IDirect3D7 *LPDIRECT3D7;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3D7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3D7_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3D7_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3D7_EnumDevices(p,a,b) (p)->lpVtbl->EnumDevices(p,a,b)
+#define IDirect3D7_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+#define IDirect3D7_CreateVertexBuffer(p,a,b,c) (p)->lpVtbl->CreateVertexBuffer(p,a,b,c)
+#define IDirect3D7_EnumZBufferFormats(p,a,b,c) (p)->lpVtbl->EnumZBufferFormats(p,a,b,c)
+#define IDirect3D7_EvictManagedTextures(p) (p)->lpVtbl->EvictManagedTextures(p)
+#else
+#define IDirect3D7_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3D7_AddRef(p) (p)->AddRef()
+#define IDirect3D7_Release(p) (p)->Release()
+#define IDirect3D7_EnumDevices(p,a,b) (p)->EnumDevices(a,b)
+#define IDirect3D7_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+#define IDirect3D7_CreateVertexBuffer(p,a,b,c) (p)->CreateVertexBuffer(a,b,c)
+#define IDirect3D7_EnumZBufferFormats(p,a,b,c) (p)->EnumZBufferFormats(a,b,c)
+#define IDirect3D7_EvictManagedTextures(p) (p)->EvictManagedTextures()
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+/*
+ * Direct3D Device interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DDevice
+
+DECLARE_INTERFACE_(IDirect3DDevice, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DDevice methods ***/
+    STDMETHOD(Initialize)(THIS_ LPDIRECT3D,LPGUID,LPD3DDEVICEDESC) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPD3DDEVICEDESC,LPD3DDEVICEDESC) PURE;
+    STDMETHOD(SwapTextureHandles)(THIS_ LPDIRECT3DTEXTURE,LPDIRECT3DTEXTURE) PURE;
+    STDMETHOD(CreateExecuteBuffer)(THIS_ LPD3DEXECUTEBUFFERDESC,LPDIRECT3DEXECUTEBUFFER*,IUnknown*) PURE;
+    STDMETHOD(GetStats)(THIS_ LPD3DSTATS) PURE;
+    STDMETHOD(Execute)(THIS_ LPDIRECT3DEXECUTEBUFFER,LPDIRECT3DVIEWPORT,DWORD) PURE;
+    STDMETHOD(AddViewport)(THIS_ LPDIRECT3DVIEWPORT) PURE;
+    STDMETHOD(DeleteViewport)(THIS_ LPDIRECT3DVIEWPORT) PURE;
+    STDMETHOD(NextViewport)(THIS_ LPDIRECT3DVIEWPORT,LPDIRECT3DVIEWPORT*,DWORD) PURE;
+    STDMETHOD(Pick)(THIS_ LPDIRECT3DEXECUTEBUFFER,LPDIRECT3DVIEWPORT,DWORD,LPD3DRECT) PURE;
+    STDMETHOD(GetPickRecords)(THIS_ LPDWORD,LPD3DPICKRECORD) PURE;
+    STDMETHOD(EnumTextureFormats)(THIS_ LPD3DENUMTEXTUREFORMATSCALLBACK,LPVOID) PURE;
+    STDMETHOD(CreateMatrix)(THIS_ LPD3DMATRIXHANDLE) PURE;
+    STDMETHOD(SetMatrix)(THIS_ D3DMATRIXHANDLE,const LPD3DMATRIX) PURE;
+    STDMETHOD(GetMatrix)(THIS_ D3DMATRIXHANDLE,LPD3DMATRIX) PURE;
+    STDMETHOD(DeleteMatrix)(THIS_ D3DMATRIXHANDLE) PURE;
+    STDMETHOD(BeginScene)(THIS) PURE;
+    STDMETHOD(EndScene)(THIS) PURE;
+    STDMETHOD(GetDirect3D)(THIS_ LPDIRECT3D*) PURE;
+};
+
+typedef struct IDirect3DDevice *LPDIRECT3DDEVICE;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DDevice_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#define IDirect3DDevice_GetCaps(p,a,b) (p)->lpVtbl->GetCaps(p,a,b)
+#define IDirect3DDevice_SwapTextureHandles(p,a,b) (p)->lpVtbl->SwapTextureHandles(p,a,b)
+#define IDirect3DDevice_CreateExecuteBuffer(p,a,b,c) (p)->lpVtbl->CreateExecuteBuffer(p,a,b,c)
+#define IDirect3DDevice_GetStats(p,a) (p)->lpVtbl->GetStats(p,a)
+#define IDirect3DDevice_Execute(p,a,b,c) (p)->lpVtbl->Execute(p,a,b,c)
+#define IDirect3DDevice_AddViewport(p,a) (p)->lpVtbl->AddViewport(p,a)
+#define IDirect3DDevice_DeleteViewport(p,a) (p)->lpVtbl->DeleteViewport(p,a)
+#define IDirect3DDevice_NextViewport(p,a,b,c) (p)->lpVtbl->NextViewport(p,a,b,c)
+#define IDirect3DDevice_Pick(p,a,b,c,d) (p)->lpVtbl->Pick(p,a,b,c,d)
+#define IDirect3DDevice_GetPickRecords(p,a,b) (p)->lpVtbl->GetPickRecords(p,a,b)
+#define IDirect3DDevice_EnumTextureFormats(p,a,b) (p)->lpVtbl->EnumTextureFormats(p,a,b)
+#define IDirect3DDevice_CreateMatrix(p,a) (p)->lpVtbl->CreateMatrix(p,a)
+#define IDirect3DDevice_SetMatrix(p,a,b) (p)->lpVtbl->SetMatrix(p,a,b)
+#define IDirect3DDevice_GetMatrix(p,a,b) (p)->lpVtbl->GetMatrix(p,a,b)
+#define IDirect3DDevice_DeleteMatrix(p,a) (p)->lpVtbl->DeleteMatrix(p,a)
+#define IDirect3DDevice_BeginScene(p) (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice_EndScene(p) (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice_GetDirect3D(p,a) (p)->lpVtbl->GetDirect3D(p,a)
+#else
+#define IDirect3DDevice_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DDevice_AddRef(p) (p)->AddRef()
+#define IDirect3DDevice_Release(p) (p)->Release()
+#define IDirect3DDevice_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+#define IDirect3DDevice_GetCaps(p,a,b) (p)->GetCaps(a,b)
+#define IDirect3DDevice_SwapTextureHandles(p,a,b) (p)->SwapTextureHandles(a,b)
+#define IDirect3DDevice_CreateExecuteBuffer(p,a,b,c) (p)->CreateExecuteBuffer(a,b,c)
+#define IDirect3DDevice_GetStats(p,a) (p)->GetStats(a)
+#define IDirect3DDevice_Execute(p,a,b,c) (p)->Execute(a,b,c)
+#define IDirect3DDevice_AddViewport(p,a) (p)->AddViewport(a)
+#define IDirect3DDevice_DeleteViewport(p,a) (p)->DeleteViewport(a)
+#define IDirect3DDevice_NextViewport(p,a,b,c) (p)->NextViewport(a,b,c)
+#define IDirect3DDevice_Pick(p,a,b,c,d) (p)->Pick(a,b,c,d)
+#define IDirect3DDevice_GetPickRecords(p,a,b) (p)->GetPickRecords(a,b)
+#define IDirect3DDevice_EnumTextureFormats(p,a,b) (p)->EnumTextureFormats(a,b)
+#define IDirect3DDevice_CreateMatrix(p,a) (p)->CreateMatrix(a)
+#define IDirect3DDevice_SetMatrix(p,a,b) (p)->SetMatrix(a,b)
+#define IDirect3DDevice_GetMatrix(p,a,b) (p)->GetMatrix(a,b)
+#define IDirect3DDevice_DeleteMatrix(p,a) (p)->DeleteMatrix(a)
+#define IDirect3DDevice_BeginScene(p) (p)->BeginScene()
+#define IDirect3DDevice_EndScene(p) (p)->EndScene()
+#define IDirect3DDevice_GetDirect3D(p,a) (p)->GetDirect3D(a)
+#endif
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#undef INTERFACE
+#define INTERFACE IDirect3DDevice2
+
+DECLARE_INTERFACE_(IDirect3DDevice2, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DDevice2 methods ***/
+    STDMETHOD(GetCaps)(THIS_ LPD3DDEVICEDESC,LPD3DDEVICEDESC) PURE;
+    STDMETHOD(SwapTextureHandles)(THIS_ LPDIRECT3DTEXTURE2,LPDIRECT3DTEXTURE2) PURE;
+    STDMETHOD(GetStats)(THIS_ LPD3DSTATS) PURE;
+    STDMETHOD(AddViewport)(THIS_ LPDIRECT3DVIEWPORT2) PURE;
+    STDMETHOD(DeleteViewport)(THIS_ LPDIRECT3DVIEWPORT2) PURE;
+    STDMETHOD(NextViewport)(THIS_ LPDIRECT3DVIEWPORT2,LPDIRECT3DVIEWPORT2*,DWORD) PURE;
+    STDMETHOD(EnumTextureFormats)(THIS_ LPD3DENUMTEXTUREFORMATSCALLBACK,LPVOID) PURE;
+    STDMETHOD(BeginScene)(THIS) PURE;
+    STDMETHOD(EndScene)(THIS) PURE;
+    STDMETHOD(GetDirect3D)(THIS_ LPDIRECT3D2*) PURE;
+    STDMETHOD(SetCurrentViewport)(THIS_ LPDIRECT3DVIEWPORT2) PURE;
+    STDMETHOD(GetCurrentViewport)(THIS_ LPDIRECT3DVIEWPORT2 *) PURE;
+    STDMETHOD(SetRenderTarget)(THIS_ LPDIRECTDRAWSURFACE,DWORD) PURE;
+    STDMETHOD(GetRenderTarget)(THIS_ LPDIRECTDRAWSURFACE *) PURE;
+    STDMETHOD(Begin)(THIS_ D3DPRIMITIVETYPE,D3DVERTEXTYPE,DWORD) PURE;
+    STDMETHOD(BeginIndexed)(THIS_ D3DPRIMITIVETYPE,D3DVERTEXTYPE,LPVOID,DWORD,DWORD) PURE;
+    STDMETHOD(Vertex)(THIS_ LPVOID) PURE;
+    STDMETHOD(Index)(THIS_ WORD) PURE;
+    STDMETHOD(End)(THIS_ DWORD) PURE;
+    STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE,LPDWORD) PURE;
+    STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE,DWORD) PURE;
+    STDMETHOD(GetLightState)(THIS_ D3DLIGHTSTATETYPE,LPDWORD) PURE;
+    STDMETHOD(SetLightState)(THIS_ D3DLIGHTSTATETYPE,DWORD) PURE;
+    STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE,D3DVERTEXTYPE,LPVOID,DWORD,DWORD) PURE;
+    STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE,D3DVERTEXTYPE,LPVOID,DWORD,LPWORD,DWORD,DWORD) PURE;
+    STDMETHOD(SetClipStatus)(THIS_ LPD3DCLIPSTATUS) PURE;
+    STDMETHOD(GetClipStatus)(THIS_ LPD3DCLIPSTATUS) PURE;
+};
+
+typedef struct IDirect3DDevice2 *LPDIRECT3DDEVICE2;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DDevice2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DDevice2_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice2_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DDevice2_GetCaps(p,a,b) (p)->lpVtbl->GetCaps(p,a,b)
+#define IDirect3DDevice2_SwapTextureHandles(p,a,b) (p)->lpVtbl->SwapTextureHandles(p,a,b)
+#define IDirect3DDevice2_GetStats(p,a) (p)->lpVtbl->GetStats(p,a)
+#define IDirect3DDevice2_AddViewport(p,a) (p)->lpVtbl->AddViewport(p,a)
+#define IDirect3DDevice2_DeleteViewport(p,a) (p)->lpVtbl->DeleteViewport(p,a)
+#define IDirect3DDevice2_NextViewport(p,a,b,c) (p)->lpVtbl->NextViewport(p,a,b,c)
+#define IDirect3DDevice2_EnumTextureFormats(p,a,b) (p)->lpVtbl->EnumTextureFormats(p,a,b)
+#define IDirect3DDevice2_BeginScene(p) (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice2_EndScene(p) (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice2_GetDirect3D(p,a) (p)->lpVtbl->GetDirect3D(p,a)
+#define IDirect3DDevice2_SetCurrentViewport(p,a) (p)->lpVtbl->SetCurrentViewport(p,a)
+#define IDirect3DDevice2_GetCurrentViewport(p,a) (p)->lpVtbl->GetCurrentViewport(p,a)
+#define IDirect3DDevice2_SetRenderTarget(p,a,b) (p)->lpVtbl->SetRenderTarget(p,a,b)
+#define IDirect3DDevice2_GetRenderTarget(p,a) (p)->lpVtbl->GetRenderTarget(p,a)
+#define IDirect3DDevice2_Begin(p,a,b,c) (p)->lpVtbl->Begin(p,a,b,c)
+#define IDirect3DDevice2_BeginIndexed(p,a,b,c,d,e) (p)->lpVtbl->BeginIndexed(p,a,b,c,d,e)
+#define IDirect3DDevice2_Vertex(p,a) (p)->lpVtbl->Vertex(p,a)
+#define IDirect3DDevice2_Index(p,a) (p)->lpVtbl->Index(p,a)
+#define IDirect3DDevice2_End(p,a) (p)->lpVtbl->End(p,a)
+#define IDirect3DDevice2_GetRenderState(p,a,b) (p)->lpVtbl->GetRenderState(p,a,b)
+#define IDirect3DDevice2_SetRenderState(p,a,b) (p)->lpVtbl->SetRenderState(p,a,b)
+#define IDirect3DDevice2_GetLightState(p,a,b) (p)->lpVtbl->GetLightState(p,a,b)
+#define IDirect3DDevice2_SetLightState(p,a,b) (p)->lpVtbl->SetLightState(p,a,b)
+#define IDirect3DDevice2_SetTransform(p,a,b) (p)->lpVtbl->SetTransform(p,a,b)
+#define IDirect3DDevice2_GetTransform(p,a,b) (p)->lpVtbl->GetTransform(p,a,b)
+#define IDirect3DDevice2_MultiplyTransform(p,a,b) (p)->lpVtbl->MultiplyTransform(p,a,b)
+#define IDirect3DDevice2_DrawPrimitive(p,a,b,c,d,e) (p)->lpVtbl->DrawPrimitive(p,a,b,c,d,e)
+#define IDirect3DDevice2_DrawIndexedPrimitive(p,a,b,c,d,e,f,g) (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice2_SetClipStatus(p,a) (p)->lpVtbl->SetClipStatus(p,a)
+#define IDirect3DDevice2_GetClipStatus(p,a) (p)->lpVtbl->GetClipStatus(p,a)
+#else
+#define IDirect3DDevice2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DDevice2_AddRef(p) (p)->AddRef()
+#define IDirect3DDevice2_Release(p) (p)->Release()
+#define IDirect3DDevice2_GetCaps(p,a,b) (p)->GetCaps(a,b)
+#define IDirect3DDevice2_SwapTextureHandles(p,a,b) (p)->SwapTextureHandles(a,b)
+#define IDirect3DDevice2_GetStats(p,a) (p)->GetStats(a)
+#define IDirect3DDevice2_AddViewport(p,a) (p)->AddViewport(a)
+#define IDirect3DDevice2_DeleteViewport(p,a) (p)->DeleteViewport(a)
+#define IDirect3DDevice2_NextViewport(p,a,b,c) (p)->NextViewport(a,b,c)
+#define IDirect3DDevice2_EnumTextureFormats(p,a,b) (p)->EnumTextureFormats(a,b)
+#define IDirect3DDevice2_BeginScene(p) (p)->BeginScene()
+#define IDirect3DDevice2_EndScene(p) (p)->EndScene()
+#define IDirect3DDevice2_GetDirect3D(p,a) (p)->GetDirect3D(a)
+#define IDirect3DDevice2_SetCurrentViewport(p,a) (p)->SetCurrentViewport(a)
+#define IDirect3DDevice2_GetCurrentViewport(p,a) (p)->GetCurrentViewport(a)
+#define IDirect3DDevice2_SetRenderTarget(p,a,b) (p)->SetRenderTarget(a,b)
+#define IDirect3DDevice2_GetRenderTarget(p,a) (p)->GetRenderTarget(a)
+#define IDirect3DDevice2_Begin(p,a,b,c) (p)->Begin(a,b,c)
+#define IDirect3DDevice2_BeginIndexed(p,a,b,c,d,e) (p)->BeginIndexed(a,b,c,d,e)
+#define IDirect3DDevice2_Vertex(p,a) (p)->Vertex(a)
+#define IDirect3DDevice2_Index(p,a) (p)->Index(a)
+#define IDirect3DDevice2_End(p,a) (p)->End(a)
+#define IDirect3DDevice2_GetRenderState(p,a,b) (p)->GetRenderState(a,b)
+#define IDirect3DDevice2_SetRenderState(p,a,b) (p)->SetRenderState(a,b)
+#define IDirect3DDevice2_GetLightState(p,a,b) (p)->GetLightState(a,b)
+#define IDirect3DDevice2_SetLightState(p,a,b) (p)->SetLightState(a,b)
+#define IDirect3DDevice2_SetTransform(p,a,b) (p)->SetTransform(a,b)
+#define IDirect3DDevice2_GetTransform(p,a,b) (p)->GetTransform(a,b)
+#define IDirect3DDevice2_MultiplyTransform(p,a,b) (p)->MultiplyTransform(a,b)
+#define IDirect3DDevice2_DrawPrimitive(p,a,b,c,d,e) (p)->DrawPrimitive(a,b,c,d,e)
+#define IDirect3DDevice2_DrawIndexedPrimitive(p,a,b,c,d,e,f,g) (p)->DrawIndexedPrimitive(a,b,c,d,e,f,g)
+#define IDirect3DDevice2_SetClipStatus(p,a) (p)->SetClipStatus(a)
+#define IDirect3DDevice2_GetClipStatus(p,a) (p)->GetClipStatus(a)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+#undef INTERFACE
+#define INTERFACE IDirect3DDevice3
+
+DECLARE_INTERFACE_(IDirect3DDevice3, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DDevice3 methods ***/
+    STDMETHOD(GetCaps)(THIS_ LPD3DDEVICEDESC,LPD3DDEVICEDESC) PURE;
+    STDMETHOD(GetStats)(THIS_ LPD3DSTATS) PURE;
+    STDMETHOD(AddViewport)(THIS_ LPDIRECT3DVIEWPORT3) PURE;
+    STDMETHOD(DeleteViewport)(THIS_ LPDIRECT3DVIEWPORT3) PURE;
+    STDMETHOD(NextViewport)(THIS_ LPDIRECT3DVIEWPORT3,LPDIRECT3DVIEWPORT3*,DWORD) PURE;
+    STDMETHOD(EnumTextureFormats)(THIS_ LPD3DENUMPIXELFORMATSCALLBACK,LPVOID) PURE;
+    STDMETHOD(BeginScene)(THIS) PURE;
+    STDMETHOD(EndScene)(THIS) PURE;
+    STDMETHOD(GetDirect3D)(THIS_ LPDIRECT3D3*) PURE;
+    STDMETHOD(SetCurrentViewport)(THIS_ LPDIRECT3DVIEWPORT3) PURE;
+    STDMETHOD(GetCurrentViewport)(THIS_ LPDIRECT3DVIEWPORT3 *) PURE;
+    STDMETHOD(SetRenderTarget)(THIS_ LPDIRECTDRAWSURFACE4,DWORD) PURE;
+    STDMETHOD(GetRenderTarget)(THIS_ LPDIRECTDRAWSURFACE4 *) PURE;
+    STDMETHOD(Begin)(THIS_ D3DPRIMITIVETYPE,DWORD,DWORD) PURE;
+    STDMETHOD(BeginIndexed)(THIS_ D3DPRIMITIVETYPE,DWORD,LPVOID,DWORD,DWORD) PURE;
+    STDMETHOD(Vertex)(THIS_ LPVOID) PURE;
+    STDMETHOD(Index)(THIS_ WORD) PURE;
+    STDMETHOD(End)(THIS_ DWORD) PURE;
+    STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE,LPDWORD) PURE;
+    STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE,DWORD) PURE;
+    STDMETHOD(GetLightState)(THIS_ D3DLIGHTSTATETYPE,LPDWORD) PURE;
+    STDMETHOD(SetLightState)(THIS_ D3DLIGHTSTATETYPE,DWORD) PURE;
+    STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE,DWORD,LPVOID,DWORD,DWORD) PURE;
+    STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE,DWORD,LPVOID,DWORD,LPWORD,DWORD,DWORD) PURE;
+    STDMETHOD(SetClipStatus)(THIS_ LPD3DCLIPSTATUS) PURE;
+    STDMETHOD(GetClipStatus)(THIS_ LPD3DCLIPSTATUS) PURE;
+    STDMETHOD(DrawPrimitiveStrided)(THIS_ D3DPRIMITIVETYPE,DWORD,LPD3DDRAWPRIMITIVESTRIDEDDATA,DWORD,DWORD) PURE;
+    STDMETHOD(DrawIndexedPrimitiveStrided)(THIS_ D3DPRIMITIVETYPE,DWORD,LPD3DDRAWPRIMITIVESTRIDEDDATA,DWORD,LPWORD,DWORD,DWORD) PURE;
+    STDMETHOD(DrawPrimitiveVB)(THIS_ D3DPRIMITIVETYPE,LPDIRECT3DVERTEXBUFFER,DWORD,DWORD,DWORD) PURE;
+    STDMETHOD(DrawIndexedPrimitiveVB)(THIS_ D3DPRIMITIVETYPE,LPDIRECT3DVERTEXBUFFER,LPWORD,DWORD,DWORD) PURE;
+    STDMETHOD(ComputeSphereVisibility)(THIS_ LPD3DVECTOR,LPD3DVALUE,DWORD,DWORD,LPDWORD) PURE;
+    STDMETHOD(GetTexture)(THIS_ DWORD,LPDIRECT3DTEXTURE2 *) PURE;
+    STDMETHOD(SetTexture)(THIS_ DWORD,LPDIRECT3DTEXTURE2) PURE;
+    STDMETHOD(GetTextureStageState)(THIS_ DWORD,D3DTEXTURESTAGESTATETYPE,LPDWORD) PURE;
+    STDMETHOD(SetTextureStageState)(THIS_ DWORD,D3DTEXTURESTAGESTATETYPE,DWORD) PURE;
+    STDMETHOD(ValidateDevice)(THIS_ LPDWORD) PURE;
+};
+
+typedef struct IDirect3DDevice3 *LPDIRECT3DDEVICE3;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DDevice3_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DDevice3_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice3_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DDevice3_GetCaps(p,a,b) (p)->lpVtbl->GetCaps(p,a,b)
+#define IDirect3DDevice3_GetStats(p,a) (p)->lpVtbl->GetStats(p,a)
+#define IDirect3DDevice3_AddViewport(p,a) (p)->lpVtbl->AddViewport(p,a)
+#define IDirect3DDevice3_DeleteViewport(p,a) (p)->lpVtbl->DeleteViewport(p,a)
+#define IDirect3DDevice3_NextViewport(p,a,b,c) (p)->lpVtbl->NextViewport(p,a,b,c)
+#define IDirect3DDevice3_EnumTextureFormats(p,a,b) (p)->lpVtbl->EnumTextureFormats(p,a,b)
+#define IDirect3DDevice3_BeginScene(p) (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice3_EndScene(p) (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice3_GetDirect3D(p,a) (p)->lpVtbl->GetDirect3D(p,a)
+#define IDirect3DDevice3_SetCurrentViewport(p,a) (p)->lpVtbl->SetCurrentViewport(p,a)
+#define IDirect3DDevice3_GetCurrentViewport(p,a) (p)->lpVtbl->GetCurrentViewport(p,a)
+#define IDirect3DDevice3_SetRenderTarget(p,a,b) (p)->lpVtbl->SetRenderTarget(p,a,b)
+#define IDirect3DDevice3_GetRenderTarget(p,a) (p)->lpVtbl->GetRenderTarget(p,a)
+#define IDirect3DDevice3_Begin(p,a,b,c) (p)->lpVtbl->Begin(p,a,b,c)
+#define IDirect3DDevice3_BeginIndexed(p,a,b,c,d,e) (p)->lpVtbl->BeginIndexed(p,a,b,c,d,e)
+#define IDirect3DDevice3_Vertex(p,a) (p)->lpVtbl->Vertex(p,a)
+#define IDirect3DDevice3_Index(p,a) (p)->lpVtbl->Index(p,a)
+#define IDirect3DDevice3_End(p,a) (p)->lpVtbl->End(p,a)
+#define IDirect3DDevice3_GetRenderState(p,a,b) (p)->lpVtbl->GetRenderState(p,a,b)
+#define IDirect3DDevice3_SetRenderState(p,a,b) (p)->lpVtbl->SetRenderState(p,a,b)
+#define IDirect3DDevice3_GetLightState(p,a,b) (p)->lpVtbl->GetLightState(p,a,b)
+#define IDirect3DDevice3_SetLightState(p,a,b) (p)->lpVtbl->SetLightState(p,a,b)
+#define IDirect3DDevice3_SetTransform(p,a,b) (p)->lpVtbl->SetTransform(p,a,b)
+#define IDirect3DDevice3_GetTransform(p,a,b) (p)->lpVtbl->GetTransform(p,a,b)
+#define IDirect3DDevice3_MultiplyTransform(p,a,b) (p)->lpVtbl->MultiplyTransform(p,a,b)
+#define IDirect3DDevice3_DrawPrimitive(p,a,b,c,d,e) (p)->lpVtbl->DrawPrimitive(p,a,b,c,d,e)
+#define IDirect3DDevice3_DrawIndexedPrimitive(p,a,b,c,d,e,f,g) (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice3_SetClipStatus(p,a) (p)->lpVtbl->SetClipStatus(p,a)
+#define IDirect3DDevice3_GetClipStatus(p,a) (p)->lpVtbl->GetClipStatus(p,a)
+#define IDirect3DDevice3_DrawPrimitiveStrided(p,a,b,c,d,e) (p)->lpVtbl->DrawPrimitiveStrided(p,a,b,c,d,e)
+#define IDirect3DDevice3_DrawIndexedPrimitiveStrided(p,a,b,c,d,e,f,g) (p)->lpVtbl->DrawIndexedPrimitiveStrided(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice3_DrawPrimitiveVB(p,a,b,c,d,e) (p)->lpVtbl->DrawPrimitiveVB(p,a,b,c,d,e)
+#define IDirect3DDevice3_DrawIndexedPrimitiveVB(p,a,b,c,d,e) (p)->lpVtbl->DrawIndexedPrimitiveVB(p,a,b,c,d,e)
+#define IDirect3DDevice3_ComputeSphereVisibility(p,a,b,c,d,e) (p)->lpVtbl->ComputeSphereVisibility(p,a,b,c,d,e)
+#define IDirect3DDevice3_GetTexture(p,a,b) (p)->lpVtbl->GetTexture(p,a,b)
+#define IDirect3DDevice3_SetTexture(p,a,b) (p)->lpVtbl->SetTexture(p,a,b)
+#define IDirect3DDevice3_GetTextureStageState(p,a,b,c) (p)->lpVtbl->GetTextureStageState(p,a,b,c)
+#define IDirect3DDevice3_SetTextureStageState(p,a,b,c) (p)->lpVtbl->SetTextureStageState(p,a,b,c)
+#define IDirect3DDevice3_ValidateDevice(p,a) (p)->lpVtbl->ValidateDevice(p,a)
+#else
+#define IDirect3DDevice3_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DDevice3_AddRef(p) (p)->AddRef()
+#define IDirect3DDevice3_Release(p) (p)->Release()
+#define IDirect3DDevice3_GetCaps(p,a,b) (p)->GetCaps(a,b)
+#define IDirect3DDevice3_GetStats(p,a) (p)->GetStats(a)
+#define IDirect3DDevice3_AddViewport(p,a) (p)->AddViewport(a)
+#define IDirect3DDevice3_DeleteViewport(p,a) (p)->DeleteViewport(a)
+#define IDirect3DDevice3_NextViewport(p,a,b,c) (p)->NextViewport(a,b,c)
+#define IDirect3DDevice3_EnumTextureFormats(p,a,b) (p)->EnumTextureFormats(a,b)
+#define IDirect3DDevice3_BeginScene(p) (p)->BeginScene()
+#define IDirect3DDevice3_EndScene(p) (p)->EndScene()
+#define IDirect3DDevice3_GetDirect3D(p,a) (p)->GetDirect3D(a)
+#define IDirect3DDevice3_SetCurrentViewport(p,a) (p)->SetCurrentViewport(a)
+#define IDirect3DDevice3_GetCurrentViewport(p,a) (p)->GetCurrentViewport(a)
+#define IDirect3DDevice3_SetRenderTarget(p,a,b) (p)->SetRenderTarget(a,b)
+#define IDirect3DDevice3_GetRenderTarget(p,a) (p)->GetRenderTarget(a)
+#define IDirect3DDevice3_Begin(p,a,b,c) (p)->Begin(a,b,c)
+#define IDirect3DDevice3_BeginIndexed(p,a,b,c,d,e) (p)->BeginIndexed(a,b,c,d,e)
+#define IDirect3DDevice3_Vertex(p,a) (p)->Vertex(a)
+#define IDirect3DDevice3_Index(p,a) (p)->Index(a)
+#define IDirect3DDevice3_End(p,a) (p)->End(a)
+#define IDirect3DDevice3_GetRenderState(p,a,b) (p)->GetRenderState(a,b)
+#define IDirect3DDevice3_SetRenderState(p,a,b) (p)->SetRenderState(a,b)
+#define IDirect3DDevice3_GetLightState(p,a,b) (p)->GetLightState(a,b)
+#define IDirect3DDevice3_SetLightState(p,a,b) (p)->SetLightState(a,b)
+#define IDirect3DDevice3_SetTransform(p,a,b) (p)->SetTransform(a,b)
+#define IDirect3DDevice3_GetTransform(p,a,b) (p)->GetTransform(a,b)
+#define IDirect3DDevice3_MultiplyTransform(p,a,b) (p)->MultiplyTransform(a,b)
+#define IDirect3DDevice3_DrawPrimitive(p,a,b,c,d,e) (p)->DrawPrimitive(a,b,c,d,e)
+#define IDirect3DDevice3_DrawIndexedPrimitive(p,a,b,c,d,e,f,g) (p)->DrawIndexedPrimitive(a,b,c,d,e,f,g)
+#define IDirect3DDevice3_SetClipStatus(p,a) (p)->SetClipStatus(a)
+#define IDirect3DDevice3_GetClipStatus(p,a) (p)->GetClipStatus(a)
+#define IDirect3DDevice3_DrawPrimitiveStrided(p,a,b,c,d,e) (p)->DrawPrimitiveStrided(a,b,c,d,e)
+#define IDirect3DDevice3_DrawIndexedPrimitiveStrided(p,a,b,c,d,e,f,g) (p)->DrawIndexedPrimitiveStrided(a,b,c,d,e,f,g)
+#define IDirect3DDevice3_DrawPrimitiveVB(p,a,b,c,d,e) (p)->DrawPrimitiveVB(a,b,c,d,e)
+#define IDirect3DDevice3_DrawIndexedPrimitiveVB(p,a,b,c,d,e) (p)->DrawIndexedPrimitiveVB(a,b,c,d,e)
+#define IDirect3DDevice3_ComputeSphereVisibility(p,a,b,c,d,e) (p)->ComputeSphereVisibility(a,b,c,d,e)
+#define IDirect3DDevice3_GetTexture(p,a,b) (p)->GetTexture(a,b)
+#define IDirect3DDevice3_SetTexture(p,a,b) (p)->SetTexture(a,b)
+#define IDirect3DDevice3_GetTextureStageState(p,a,b,c) (p)->GetTextureStageState(a,b,c)
+#define IDirect3DDevice3_SetTextureStageState(p,a,b,c) (p)->SetTextureStageState(a,b,c)
+#define IDirect3DDevice3_ValidateDevice(p,a) (p)->ValidateDevice(a)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+#undef INTERFACE
+#define INTERFACE IDirect3DDevice7
+
+DECLARE_INTERFACE_(IDirect3DDevice7, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DDevice7 methods ***/
+    STDMETHOD(GetCaps)(THIS_ LPD3DDEVICEDESC7) PURE;
+    STDMETHOD(EnumTextureFormats)(THIS_ LPD3DENUMPIXELFORMATSCALLBACK,LPVOID) PURE;
+    STDMETHOD(BeginScene)(THIS) PURE;
+    STDMETHOD(EndScene)(THIS) PURE;
+    STDMETHOD(GetDirect3D)(THIS_ LPDIRECT3D7*) PURE;
+    STDMETHOD(SetRenderTarget)(THIS_ LPDIRECTDRAWSURFACE7,DWORD) PURE;
+    STDMETHOD(GetRenderTarget)(THIS_ LPDIRECTDRAWSURFACE7 *) PURE;
+    STDMETHOD(Clear)(THIS_ DWORD,LPD3DRECT,DWORD,D3DCOLOR,D3DVALUE,DWORD) PURE;
+    STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(SetViewport)(THIS_ LPD3DVIEWPORT7) PURE;
+    STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE,LPD3DMATRIX) PURE;
+    STDMETHOD(GetViewport)(THIS_ LPD3DVIEWPORT7) PURE;
+    STDMETHOD(SetMaterial)(THIS_ LPD3DMATERIAL7) PURE;
+    STDMETHOD(GetMaterial)(THIS_ LPD3DMATERIAL7) PURE;
+    STDMETHOD(SetLight)(THIS_ DWORD,LPD3DLIGHT7) PURE;
+    STDMETHOD(GetLight)(THIS_ DWORD,LPD3DLIGHT7) PURE;
+    STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE,DWORD) PURE;
+    STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE,LPDWORD) PURE;
+    STDMETHOD(BeginStateBlock)(THIS) PURE;
+    STDMETHOD(EndStateBlock)(THIS_ LPDWORD) PURE;
+    STDMETHOD(PreLoad)(THIS_ LPDIRECTDRAWSURFACE7) PURE;
+    STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE,DWORD,LPVOID,DWORD,DWORD) PURE;
+    STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE,DWORD,LPVOID,DWORD,LPWORD,DWORD,DWORD) PURE;
+    STDMETHOD(SetClipStatus)(THIS_ LPD3DCLIPSTATUS) PURE;
+    STDMETHOD(GetClipStatus)(THIS_ LPD3DCLIPSTATUS) PURE;
+    STDMETHOD(DrawPrimitiveStrided)(THIS_ D3DPRIMITIVETYPE,DWORD,LPD3DDRAWPRIMITIVESTRIDEDDATA,DWORD,DWORD) PURE;
+    STDMETHOD(DrawIndexedPrimitiveStrided)(THIS_ D3DPRIMITIVETYPE,DWORD,LPD3DDRAWPRIMITIVESTRIDEDDATA,DWORD,LPWORD,DWORD,DWORD) PURE;
+    STDMETHOD(DrawPrimitiveVB)(THIS_ D3DPRIMITIVETYPE,LPDIRECT3DVERTEXBUFFER7,DWORD,DWORD,DWORD) PURE;
+    STDMETHOD(DrawIndexedPrimitiveVB)(THIS_ D3DPRIMITIVETYPE,LPDIRECT3DVERTEXBUFFER7,DWORD,DWORD,LPWORD,DWORD,DWORD) PURE;
+    STDMETHOD(ComputeSphereVisibility)(THIS_ LPD3DVECTOR,LPD3DVALUE,DWORD,DWORD,LPDWORD) PURE;
+    STDMETHOD(GetTexture)(THIS_ DWORD,LPDIRECTDRAWSURFACE7 *) PURE;
+    STDMETHOD(SetTexture)(THIS_ DWORD,LPDIRECTDRAWSURFACE7) PURE;
+    STDMETHOD(GetTextureStageState)(THIS_ DWORD,D3DTEXTURESTAGESTATETYPE,LPDWORD) PURE;
+    STDMETHOD(SetTextureStageState)(THIS_ DWORD,D3DTEXTURESTAGESTATETYPE,DWORD) PURE;
+    STDMETHOD(ValidateDevice)(THIS_ LPDWORD) PURE;
+    STDMETHOD(ApplyStateBlock)(THIS_ DWORD) PURE;
+    STDMETHOD(CaptureStateBlock)(THIS_ DWORD) PURE;
+    STDMETHOD(DeleteStateBlock)(THIS_ DWORD) PURE;
+    STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE,LPDWORD) PURE;
+    STDMETHOD(Load)(THIS_ LPDIRECTDRAWSURFACE7,LPPOINT,LPDIRECTDRAWSURFACE7,LPRECT,DWORD) PURE;
+    STDMETHOD(LightEnable)(THIS_ DWORD,BOOL) PURE;
+    STDMETHOD(GetLightEnable)(THIS_ DWORD,BOOL*) PURE;
+    STDMETHOD(SetClipPlane)(THIS_ DWORD,D3DVALUE*) PURE;
+    STDMETHOD(GetClipPlane)(THIS_ DWORD,D3DVALUE*) PURE;
+    STDMETHOD(GetInfo)(THIS_ DWORD,LPVOID,DWORD) PURE;
+};
+
+typedef struct IDirect3DDevice7 *LPDIRECT3DDEVICE7;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DDevice7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DDevice7_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice7_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DDevice7_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a)
+#define IDirect3DDevice7_EnumTextureFormats(p,a,b) (p)->lpVtbl->EnumTextureFormats(p,a,b)
+#define IDirect3DDevice7_BeginScene(p) (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice7_EndScene(p) (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice7_GetDirect3D(p,a) (p)->lpVtbl->GetDirect3D(p,a)
+#define IDirect3DDevice7_SetRenderTarget(p,a,b) (p)->lpVtbl->SetRenderTarget(p,a,b)
+#define IDirect3DDevice7_GetRenderTarget(p,a) (p)->lpVtbl->GetRenderTarget(p,a)
+#define IDirect3DDevice7_Clear(p,a,b,c,d,e,f) (p)->lpVtbl->Clear(p,a,b,c,d,e,f)
+#define IDirect3DDevice7_SetTransform(p,a,b) (p)->lpVtbl->SetTransform(p,a,b)
+#define IDirect3DDevice7_GetTransform(p,a,b) (p)->lpVtbl->GetTransform(p,a,b)
+#define IDirect3DDevice7_SetViewport(p,a) (p)->lpVtbl->SetViewport(p,a)
+#define IDirect3DDevice7_MultiplyTransform(p,a,b) (p)->lpVtbl->MultiplyTransform(p,a,b)
+#define IDirect3DDevice7_GetViewport(p,a) (p)->lpVtbl->GetViewport(p,a)
+#define IDirect3DDevice7_SetMaterial(p,a) (p)->lpVtbl->SetMaterial(p,a)
+#define IDirect3DDevice7_GetMaterial(p,a) (p)->lpVtbl->GetMaterial(p,a)
+#define IDirect3DDevice7_SetLight(p,a,b) (p)->lpVtbl->SetLight(p,a,b)
+#define IDirect3DDevice7_GetLight(p,a,b) (p)->lpVtbl->GetLight(p,a,b)
+#define IDirect3DDevice7_SetRenderState(p,a,b) (p)->lpVtbl->SetRenderState(p,a,b)
+#define IDirect3DDevice7_GetRenderState(p,a,b) (p)->lpVtbl->GetRenderState(p,a,b)
+#define IDirect3DDevice7_BeginStateBlock(p) (p)->lpVtbl->BeginStateBlock(p)
+#define IDirect3DDevice7_EndStateBlock(p,a) (p)->lpVtbl->EndStateBlock(p,a)
+#define IDirect3DDevice7_PreLoad(p,a) (p)->lpVtbl->PreLoad(p,a)
+#define IDirect3DDevice7_DrawPrimitive(p,a,b,c,d,e) (p)->lpVtbl->DrawPrimitive(p,a,b,c,d,e)
+#define IDirect3DDevice7_DrawIndexedPrimitive(p,a,b,c,d,e,f,g) (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice7_SetClipStatus(p,a) (p)->lpVtbl->SetClipStatus(p,a)
+#define IDirect3DDevice7_GetClipStatus(p,a) (p)->lpVtbl->GetClipStatus(p,a)
+#define IDirect3DDevice7_DrawPrimitiveStrided(p,a,b,c,d,e) (p)->lpVtbl->DrawPrimitiveStrided(p,a,b,c,d,e)
+#define IDirect3DDevice7_DrawIndexedPrimitiveStrided(p,a,b,c,d,e,f,g) (p)->lpVtbl->DrawIndexedPrimitiveStrided(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice7_DrawPrimitiveVB(p,a,b,c,d,e) (p)->lpVtbl->DrawPrimitiveVB(p,a,b,c,d,e)
+#define IDirect3DDevice7_DrawIndexedPrimitiveVB(p,a,b,c,d,e,f,g) (p)->lpVtbl->DrawIndexedPrimitiveVB(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice7_ComputeSphereVisibility(p,a,b,c,d,e) (p)->lpVtbl->ComputeSphereVisibility(p,a,b,c,d,e)
+#define IDirect3DDevice7_GetTexture(p,a,b) (p)->lpVtbl->GetTexture(p,a,b)
+#define IDirect3DDevice7_SetTexture(p,a,b) (p)->lpVtbl->SetTexture(p,a,b)
+#define IDirect3DDevice7_GetTextureStageState(p,a,b,c) (p)->lpVtbl->GetTextureStageState(p,a,b,c)
+#define IDirect3DDevice7_SetTextureStageState(p,a,b,c) (p)->lpVtbl->SetTextureStageState(p,a,b,c)
+#define IDirect3DDevice7_ValidateDevice(p,a) (p)->lpVtbl->ValidateDevice(p,a)
+#define IDirect3DDevice7_ApplyStateBlock(p,a) (p)->lpVtbl->ApplyStateBlock(p,a)
+#define IDirect3DDevice7_CaptureStateBlock(p,a) (p)->lpVtbl->CaptureStateBlock(p,a)
+#define IDirect3DDevice7_DeleteStateBlock(p,a) (p)->lpVtbl->DeleteStateBlock(p,a)
+#define IDirect3DDevice7_CreateStateBlock(p,a,b) (p)->lpVtbl->CreateStateBlock(p,a,b)
+#define IDirect3DDevice7_Load(p,a,b,c,d,e) (p)->lpVtbl->Load(p,a,b,c,d,e)
+#define IDirect3DDevice7_LightEnable(p,a,b) (p)->lpVtbl->LightEnable(p,a,b)
+#define IDirect3DDevice7_GetLightEnable(p,a,b) (p)->lpVtbl->GetLightEnable(p,a,b)
+#define IDirect3DDevice7_SetClipPlane(p,a,b) (p)->lpVtbl->SetClipPlane(p,a,b)
+#define IDirect3DDevice7_GetClipPlane(p,a,b) (p)->lpVtbl->GetClipPlane(p,a,b)
+#define IDirect3DDevice7_GetInfo(p,a,b,c) (p)->lpVtbl->GetInfo(p,a,b,c)
+#else
+#define IDirect3DDevice7_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DDevice7_AddRef(p) (p)->AddRef()
+#define IDirect3DDevice7_Release(p) (p)->Release()
+#define IDirect3DDevice7_GetCaps(p,a) (p)->GetCaps(a)
+#define IDirect3DDevice7_EnumTextureFormats(p,a,b) (p)->EnumTextureFormats(a,b)
+#define IDirect3DDevice7_BeginScene(p) (p)->BeginScene()
+#define IDirect3DDevice7_EndScene(p) (p)->EndScene()
+#define IDirect3DDevice7_GetDirect3D(p,a) (p)->GetDirect3D(a)
+#define IDirect3DDevice7_SetRenderTarget(p,a,b) (p)->SetRenderTarget(a,b)
+#define IDirect3DDevice7_GetRenderTarget(p,a) (p)->GetRenderTarget(a)
+#define IDirect3DDevice7_Clear(p,a,b,c,d,e,f) (p)->Clear(a,b,c,d,e,f)
+#define IDirect3DDevice7_SetTransform(p,a,b) (p)->SetTransform(a,b)
+#define IDirect3DDevice7_GetTransform(p,a,b) (p)->GetTransform(a,b)
+#define IDirect3DDevice7_SetViewport(p,a) (p)->SetViewport(a)
+#define IDirect3DDevice7_MultiplyTransform(p,a,b) (p)->MultiplyTransform(a,b)
+#define IDirect3DDevice7_GetViewport(p,a) (p)->GetViewport(a)
+#define IDirect3DDevice7_SetMaterial(p,a) (p)->SetMaterial(a)
+#define IDirect3DDevice7_GetMaterial(p,a) (p)->GetMaterial(a)
+#define IDirect3DDevice7_SetLight(p,a,b) (p)->SetLight(a,b)
+#define IDirect3DDevice7_GetLight(p,a,b) (p)->GetLight(a,b)
+#define IDirect3DDevice7_SetRenderState(p,a,b) (p)->SetRenderState(a,b)
+#define IDirect3DDevice7_GetRenderState(p,a,b) (p)->GetRenderState(a,b)
+#define IDirect3DDevice7_BeginStateBlock(p) (p)->BeginStateBlock()
+#define IDirect3DDevice7_EndStateBlock(p,a) (p)->EndStateBlock(a)
+#define IDirect3DDevice7_PreLoad(p,a) (p)->PreLoad(a)
+#define IDirect3DDevice7_DrawPrimitive(p,a,b,c,d,e) (p)->DrawPrimitive(a,b,c,d,e)
+#define IDirect3DDevice7_DrawIndexedPrimitive(p,a,b,c,d,e,f,g) (p)->DrawIndexedPrimitive(a,b,c,d,e,f,g)
+#define IDirect3DDevice7_SetClipStatus(p,a) (p)->SetClipStatus(a)
+#define IDirect3DDevice7_GetClipStatus(p,a) (p)->GetClipStatus(a)
+#define IDirect3DDevice7_DrawPrimitiveStrided(p,a,b,c,d,e) (p)->DrawPrimitiveStrided(a,b,c,d,e)
+#define IDirect3DDevice7_DrawIndexedPrimitiveStrided(p,a,b,c,d,e,f,g) (p)->DrawIndexedPrimitiveStrided(a,b,c,d,e,f,g)
+#define IDirect3DDevice7_DrawPrimitiveVB(p,a,b,c,d,e) (p)->DrawPrimitiveVB(a,b,c,d,e)
+#define IDirect3DDevice7_DrawIndexedPrimitiveVB(p,a,b,c,d,e,f,g) (p)->DrawIndexedPrimitiveVB(a,b,c,d,e,f,g)
+#define IDirect3DDevice7_ComputeSphereVisibility(p,a,b,c,d,e) (p)->ComputeSphereVisibility(a,b,c,d,e)
+#define IDirect3DDevice7_GetTexture(p,a,b) (p)->GetTexture(a,b)
+#define IDirect3DDevice7_SetTexture(p,a,b) (p)->SetTexture(a,b)
+#define IDirect3DDevice7_GetTextureStageState(p,a,b,c) (p)->GetTextureStageState(a,b,c)
+#define IDirect3DDevice7_SetTextureStageState(p,a,b,c) (p)->SetTextureStageState(a,b,c)
+#define IDirect3DDevice7_ValidateDevice(p,a) (p)->ValidateDevice(a)
+#define IDirect3DDevice7_ApplyStateBlock(p,a) (p)->ApplyStateBlock(a)
+#define IDirect3DDevice7_CaptureStateBlock(p,a) (p)->CaptureStateBlock(a)
+#define IDirect3DDevice7_DeleteStateBlock(p,a) (p)->DeleteStateBlock(a)
+#define IDirect3DDevice7_CreateStateBlock(p,a,b) (p)->CreateStateBlock(a,b)
+#define IDirect3DDevice7_Load(p,a,b,c,d,e) (p)->Load(a,b,c,d,e)
+#define IDirect3DDevice7_LightEnable(p,a,b) (p)->LightEnable(a,b)
+#define IDirect3DDevice7_GetLightEnable(p,a,b) (p)->GetLightEnable(a,b)
+#define IDirect3DDevice7_SetClipPlane(p,a,b) (p)->SetClipPlane(a,b)
+#define IDirect3DDevice7_GetClipPlane(p,a,b) (p)->GetClipPlane(a,b)
+#define IDirect3DDevice7_GetInfo(p,a,b,c) (p)->GetInfo(a,b,c)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+/*
+ * Execute Buffer interface
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DExecuteBuffer
+
+DECLARE_INTERFACE_(IDirect3DExecuteBuffer, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DExecuteBuffer methods ***/
+    STDMETHOD(Initialize)(THIS_ LPDIRECT3DDEVICE,LPD3DEXECUTEBUFFERDESC) PURE;
+    STDMETHOD(Lock)(THIS_ LPD3DEXECUTEBUFFERDESC) PURE;
+    STDMETHOD(Unlock)(THIS) PURE;
+    STDMETHOD(SetExecuteData)(THIS_ LPD3DEXECUTEDATA) PURE;
+    STDMETHOD(GetExecuteData)(THIS_ LPD3DEXECUTEDATA) PURE;
+    STDMETHOD(Validate)(THIS_ LPDWORD,LPD3DVALIDATECALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Optimize)(THIS_ DWORD) PURE;
+};
+
+typedef struct IDirect3DExecuteBuffer *LPDIRECT3DEXECUTEBUFFER;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DExecuteBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DExecuteBuffer_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DExecuteBuffer_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DExecuteBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+#define IDirect3DExecuteBuffer_Lock(p,a) (p)->lpVtbl->Lock(p,a)
+#define IDirect3DExecuteBuffer_Unlock(p) (p)->lpVtbl->Unlock(p)
+#define IDirect3DExecuteBuffer_SetExecuteData(p,a) (p)->lpVtbl->SetExecuteData(p,a)
+#define IDirect3DExecuteBuffer_GetExecuteData(p,a) (p)->lpVtbl->GetExecuteData(p,a)
+#define IDirect3DExecuteBuffer_Validate(p,a,b,c,d) (p)->lpVtbl->Validate(p,a,b,c,d)
+#define IDirect3DExecuteBuffer_Optimize(p,a) (p)->lpVtbl->Optimize(p,a)
+#else
+#define IDirect3DExecuteBuffer_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DExecuteBuffer_AddRef(p) (p)->AddRef()
+#define IDirect3DExecuteBuffer_Release(p) (p)->Release()
+#define IDirect3DExecuteBuffer_Initialize(p,a,b) (p)->Initialize(a,b)
+#define IDirect3DExecuteBuffer_Lock(p,a) (p)->Lock(a)
+#define IDirect3DExecuteBuffer_Unlock(p) (p)->Unlock()
+#define IDirect3DExecuteBuffer_SetExecuteData(p,a) (p)->SetExecuteData(a)
+#define IDirect3DExecuteBuffer_GetExecuteData(p,a) (p)->GetExecuteData(a)
+#define IDirect3DExecuteBuffer_Validate(p,a,b,c,d) (p)->Validate(a,b,c,d)
+#define IDirect3DExecuteBuffer_Optimize(p,a) (p)->Optimize(a)
+#endif
+
+/*
+ * Light interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DLight
+
+DECLARE_INTERFACE_(IDirect3DLight, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DLight methods ***/
+    STDMETHOD(Initialize)(THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(SetLight)(THIS_ LPD3DLIGHT) PURE;
+    STDMETHOD(GetLight)(THIS_ LPD3DLIGHT) PURE;
+};
+
+typedef struct IDirect3DLight *LPDIRECT3DLIGHT;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DLight_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DLight_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DLight_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DLight_Initialize(p,a) (p)->lpVtbl->Initialize(p,a)
+#define IDirect3DLight_SetLight(p,a) (p)->lpVtbl->SetLight(p,a)
+#define IDirect3DLight_GetLight(p,a) (p)->lpVtbl->GetLight(p,a)
+#else
+#define IDirect3DLight_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DLight_AddRef(p) (p)->AddRef()
+#define IDirect3DLight_Release(p) (p)->Release()
+#define IDirect3DLight_Initialize(p,a) (p)->Initialize(a)
+#define IDirect3DLight_SetLight(p,a) (p)->SetLight(a)
+#define IDirect3DLight_GetLight(p,a) (p)->GetLight(a)
+#endif
+
+/*
+ * Material interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DMaterial
+
+DECLARE_INTERFACE_(IDirect3DMaterial, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DMaterial methods ***/
+    STDMETHOD(Initialize)(THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(SetMaterial)(THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetMaterial)(THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetHandle)(THIS_ LPDIRECT3DDEVICE,LPD3DMATERIALHANDLE) PURE;
+    STDMETHOD(Reserve)(THIS) PURE;
+    STDMETHOD(Unreserve)(THIS) PURE;
+};
+
+typedef struct IDirect3DMaterial *LPDIRECT3DMATERIAL;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DMaterial_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DMaterial_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DMaterial_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DMaterial_Initialize(p,a) (p)->lpVtbl->Initialize(p,a)
+#define IDirect3DMaterial_SetMaterial(p,a) (p)->lpVtbl->SetMaterial(p,a)
+#define IDirect3DMaterial_GetMaterial(p,a) (p)->lpVtbl->GetMaterial(p,a)
+#define IDirect3DMaterial_GetHandle(p,a,b) (p)->lpVtbl->GetHandle(p,a,b)
+#define IDirect3DMaterial_Reserve(p) (p)->lpVtbl->Reserve(p)
+#define IDirect3DMaterial_Unreserve(p) (p)->lpVtbl->Unreserve(p)
+#else
+#define IDirect3DMaterial_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DMaterial_AddRef(p) (p)->AddRef()
+#define IDirect3DMaterial_Release(p) (p)->Release()
+#define IDirect3DMaterial_Initialize(p,a) (p)->Initialize(a)
+#define IDirect3DMaterial_SetMaterial(p,a) (p)->SetMaterial(a)
+#define IDirect3DMaterial_GetMaterial(p,a) (p)->GetMaterial(a)
+#define IDirect3DMaterial_GetHandle(p,a,b) (p)->GetHandle(a,b)
+#define IDirect3DMaterial_Reserve(p) (p)->Reserve()
+#define IDirect3DMaterial_Unreserve(p) (p)->Unreserve()
+#endif
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#undef INTERFACE
+#define INTERFACE IDirect3DMaterial2
+
+DECLARE_INTERFACE_(IDirect3DMaterial2, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DMaterial2 methods ***/
+    STDMETHOD(SetMaterial)(THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetMaterial)(THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetHandle)(THIS_ LPDIRECT3DDEVICE2,LPD3DMATERIALHANDLE) PURE;
+};
+
+typedef struct IDirect3DMaterial2 *LPDIRECT3DMATERIAL2;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DMaterial2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DMaterial2_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DMaterial2_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DMaterial2_SetMaterial(p,a) (p)->lpVtbl->SetMaterial(p,a)
+#define IDirect3DMaterial2_GetMaterial(p,a) (p)->lpVtbl->GetMaterial(p,a)
+#define IDirect3DMaterial2_GetHandle(p,a,b) (p)->lpVtbl->GetHandle(p,a,b)
+#else
+#define IDirect3DMaterial2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DMaterial2_AddRef(p) (p)->AddRef()
+#define IDirect3DMaterial2_Release(p) (p)->Release()
+#define IDirect3DMaterial2_SetMaterial(p,a) (p)->SetMaterial(a)
+#define IDirect3DMaterial2_GetMaterial(p,a) (p)->GetMaterial(a)
+#define IDirect3DMaterial2_GetHandle(p,a,b) (p)->GetHandle(a,b)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+#undef INTERFACE
+#define INTERFACE IDirect3DMaterial3
+
+DECLARE_INTERFACE_(IDirect3DMaterial3, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DMaterial3 methods ***/
+    STDMETHOD(SetMaterial)(THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetMaterial)(THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetHandle)(THIS_ LPDIRECT3DDEVICE3,LPD3DMATERIALHANDLE) PURE;
+};
+
+typedef struct IDirect3DMaterial3 *LPDIRECT3DMATERIAL3;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DMaterial3_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DMaterial3_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DMaterial3_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DMaterial3_SetMaterial(p,a) (p)->lpVtbl->SetMaterial(p,a)
+#define IDirect3DMaterial3_GetMaterial(p,a) (p)->lpVtbl->GetMaterial(p,a)
+#define IDirect3DMaterial3_GetHandle(p,a,b) (p)->lpVtbl->GetHandle(p,a,b)
+#else
+#define IDirect3DMaterial3_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DMaterial3_AddRef(p) (p)->AddRef()
+#define IDirect3DMaterial3_Release(p) (p)->Release()
+#define IDirect3DMaterial3_SetMaterial(p,a) (p)->SetMaterial(a)
+#define IDirect3DMaterial3_GetMaterial(p,a) (p)->GetMaterial(a)
+#define IDirect3DMaterial3_GetHandle(p,a,b) (p)->GetHandle(a,b)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+/*
+ * Texture interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DTexture
+
+DECLARE_INTERFACE_(IDirect3DTexture, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DTexture methods ***/
+    STDMETHOD(Initialize)(THIS_ LPDIRECT3DDEVICE,LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(GetHandle)(THIS_ LPDIRECT3DDEVICE,LPD3DTEXTUREHANDLE) PURE;
+    STDMETHOD(PaletteChanged)(THIS_ DWORD,DWORD) PURE;
+    STDMETHOD(Load)(THIS_ LPDIRECT3DTEXTURE) PURE;
+    STDMETHOD(Unload)(THIS) PURE;
+};
+
+typedef struct IDirect3DTexture *LPDIRECT3DTEXTURE;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DTexture_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DTexture_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DTexture_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DTexture_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+#define IDirect3DTexture_GetHandle(p,a,b) (p)->lpVtbl->GetHandle(p,a,b)
+#define IDirect3DTexture_PaletteChanged(p,a,b) (p)->lpVtbl->PaletteChanged(p,a,b)
+#define IDirect3DTexture_Load(p,a) (p)->lpVtbl->Load(p,a)
+#define IDirect3DTexture_Unload(p) (p)->lpVtbl->Unload(p)
+#else
+#define IDirect3DTexture_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DTexture_AddRef(p) (p)->AddRef()
+#define IDirect3DTexture_Release(p) (p)->Release()
+#define IDirect3DTexture_Initialize(p,a,b) (p)->Initialize(a,b)
+#define IDirect3DTexture_GetHandle(p,a,b) (p)->GetHandle(a,b)
+#define IDirect3DTexture_PaletteChanged(p,a,b) (p)->PaletteChanged(a,b)
+#define IDirect3DTexture_Load(p,a) (p)->Load(a)
+#define IDirect3DTexture_Unload(p) (p)->Unload()
+#endif
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#undef INTERFACE
+#define INTERFACE IDirect3DTexture2
+
+DECLARE_INTERFACE_(IDirect3DTexture2, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DTexture2 methods ***/
+    STDMETHOD(GetHandle)(THIS_ LPDIRECT3DDEVICE2,LPD3DTEXTUREHANDLE) PURE;
+    STDMETHOD(PaletteChanged)(THIS_ DWORD,DWORD) PURE;
+    STDMETHOD(Load)(THIS_ LPDIRECT3DTEXTURE2) PURE;
+};
+
+typedef struct IDirect3DTexture2 *LPDIRECT3DTEXTURE2;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DTexture2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DTexture2_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DTexture2_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DTexture2_GetHandle(p,a,b) (p)->lpVtbl->GetHandle(p,a,b)
+#define IDirect3DTexture2_PaletteChanged(p,a,b) (p)->lpVtbl->PaletteChanged(p,a,b)
+#define IDirect3DTexture2_Load(p,a) (p)->lpVtbl->Load(p,a)
+#else
+#define IDirect3DTexture2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DTexture2_AddRef(p) (p)->AddRef()
+#define IDirect3DTexture2_Release(p) (p)->Release()
+#define IDirect3DTexture2_GetHandle(p,a,b) (p)->GetHandle(a,b)
+#define IDirect3DTexture2_PaletteChanged(p,a,b) (p)->PaletteChanged(a,b)
+#define IDirect3DTexture2_Load(p,a) (p)->Load(a)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+/*
+ * OldViewport interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DViewport
+
+DECLARE_INTERFACE_(IDirect3DViewport, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DViewport methods ***/
+    STDMETHOD(Initialize)(THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(GetViewport)(THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(SetViewport)(THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(TransformVertices)(THIS_ DWORD,LPD3DTRANSFORMDATA,DWORD,LPDWORD) PURE;
+    STDMETHOD(LightElements)(THIS_ DWORD,LPD3DLIGHTDATA) PURE;
+    STDMETHOD(SetBackground)(THIS_ D3DMATERIALHANDLE) PURE;
+    STDMETHOD(GetBackground)(THIS_ LPD3DMATERIALHANDLE,LPBOOL) PURE;
+    STDMETHOD(SetBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(GetBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE*,LPBOOL) PURE;
+    STDMETHOD(Clear)(THIS_ DWORD,LPD3DRECT,DWORD) PURE;
+    STDMETHOD(AddLight)(THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(NextLight)(THIS_ LPDIRECT3DLIGHT,LPDIRECT3DLIGHT*,DWORD) PURE;
+};
+
+typedef struct IDirect3DViewport *LPDIRECT3DVIEWPORT;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DViewport_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DViewport_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DViewport_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DViewport_Initialize(p,a) (p)->lpVtbl->Initialize(p,a)
+#define IDirect3DViewport_GetViewport(p,a) (p)->lpVtbl->GetViewport(p,a)
+#define IDirect3DViewport_SetViewport(p,a) (p)->lpVtbl->SetViewport(p,a)
+#define IDirect3DViewport_TransformVertices(p,a,b,c,d) (p)->lpVtbl->TransformVertices(p,a,b,c,d)
+#define IDirect3DViewport_LightElements(p,a,b) (p)->lpVtbl->LightElements(p,a,b)
+#define IDirect3DViewport_SetBackground(p,a) (p)->lpVtbl->SetBackground(p,a)
+#define IDirect3DViewport_GetBackground(p,a,b) (p)->lpVtbl->GetBackground(p,a,b)
+#define IDirect3DViewport_SetBackgroundDepth(p,a) (p)->lpVtbl->SetBackgroundDepth(p,a)
+#define IDirect3DViewport_GetBackgroundDepth(p,a,b) (p)->lpVtbl->GetBackgroundDepth(p,a,b)
+#define IDirect3DViewport_Clear(p,a,b,c) (p)->lpVtbl->Clear(p,a,b,c)
+#define IDirect3DViewport_AddLight(p,a) (p)->lpVtbl->AddLight(p,a)
+#define IDirect3DViewport_DeleteLight(p,a) (p)->lpVtbl->DeleteLight(p,a)
+#define IDirect3DViewport_NextLight(p,a,b,c) (p)->lpVtbl->NextLight(p,a,b,c)
+#else
+#define IDirect3DViewport_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DViewport_AddRef(p) (p)->AddRef()
+#define IDirect3DViewport_Release(p) (p)->Release()
+#define IDirect3DViewport_Initialize(p,a) (p)->Initialize(a)
+#define IDirect3DViewport_GetViewport(p,a) (p)->GetViewport(a)
+#define IDirect3DViewport_SetViewport(p,a) (p)->SetViewport(a)
+#define IDirect3DViewport_TransformVertices(p,a,b,c,d) (p)->TransformVertices(a,b,c,d)
+#define IDirect3DViewport_LightElements(p,a,b) (p)->LightElements(a,b)
+#define IDirect3DViewport_SetBackground(p,a) (p)->SetBackground(a)
+#define IDirect3DViewport_GetBackground(p,a,b) (p)->GetBackground(a,b)
+#define IDirect3DViewport_SetBackgroundDepth(p,a) (p)->SetBackgroundDepth(a)
+#define IDirect3DViewport_GetBackgroundDepth(p,a,b) (p)->GetBackgroundDepth(a,b)
+#define IDirect3DViewport_Clear(p,a,b,c) (p)->Clear(a,b,c)
+#define IDirect3DViewport_AddLight(p,a) (p)->AddLight(a)
+#define IDirect3DViewport_DeleteLight(p,a) (p)->DeleteLight(a)
+#define IDirect3DViewport_NextLight(p,a,b,c) (p)->NextLight(a,b,c)
+#endif
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#undef INTERFACE
+#define INTERFACE IDirect3DViewport2
+
+DECLARE_INTERFACE_(IDirect3DViewport2, IDirect3DViewport)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DViewport methods ***/
+    STDMETHOD(Initialize)(THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(GetViewport)(THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(SetViewport)(THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(TransformVertices)(THIS_ DWORD,LPD3DTRANSFORMDATA,DWORD,LPDWORD) PURE;
+    STDMETHOD(LightElements)(THIS_ DWORD,LPD3DLIGHTDATA) PURE;
+    STDMETHOD(SetBackground)(THIS_ D3DMATERIALHANDLE) PURE;
+    STDMETHOD(GetBackground)(THIS_ LPD3DMATERIALHANDLE,LPBOOL) PURE;
+    STDMETHOD(SetBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(GetBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE*,LPBOOL) PURE;
+    STDMETHOD(Clear)(THIS_ DWORD,LPD3DRECT,DWORD) PURE;
+    STDMETHOD(AddLight)(THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(NextLight)(THIS_ LPDIRECT3DLIGHT,LPDIRECT3DLIGHT*,DWORD) PURE;
+    STDMETHOD(GetViewport2)(THIS_ LPD3DVIEWPORT2) PURE;
+    STDMETHOD(SetViewport2)(THIS_ LPD3DVIEWPORT2) PURE;
+};
+
+typedef struct IDirect3DViewport2 *LPDIRECT3DVIEWPORT2;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DViewport2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DViewport2_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DViewport2_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DViewport2_Initialize(p,a) (p)->lpVtbl->Initialize(p,a)
+#define IDirect3DViewport2_GetViewport(p,a) (p)->lpVtbl->GetViewport(p,a)
+#define IDirect3DViewport2_SetViewport(p,a) (p)->lpVtbl->SetViewport(p,a)
+#define IDirect3DViewport2_TransformVertices(p,a,b,c,d) (p)->lpVtbl->TransformVertices(p,a,b,c,d)
+#define IDirect3DViewport2_LightElements(p,a,b) (p)->lpVtbl->LightElements(p,a,b)
+#define IDirect3DViewport2_SetBackground(p,a) (p)->lpVtbl->SetBackground(p,a)
+#define IDirect3DViewport2_GetBackground(p,a,b) (p)->lpVtbl->GetBackground(p,a,b)
+#define IDirect3DViewport2_SetBackgroundDepth(p,a) (p)->lpVtbl->SetBackgroundDepth(p,a)
+#define IDirect3DViewport2_GetBackgroundDepth(p,a,b) (p)->lpVtbl->GetBackgroundDepth(p,a,b)
+#define IDirect3DViewport2_Clear(p,a,b,c) (p)->lpVtbl->Clear(p,a,b,c)
+#define IDirect3DViewport2_AddLight(p,a) (p)->lpVtbl->AddLight(p,a)
+#define IDirect3DViewport2_DeleteLight(p,a) (p)->lpVtbl->DeleteLight(p,a)
+#define IDirect3DViewport2_NextLight(p,a,b,c) (p)->lpVtbl->NextLight(p,a,b,c)
+#define IDirect3DViewport2_GetViewport2(p,a) (p)->lpVtbl->GetViewport2(p,a)
+#define IDirect3DViewport2_SetViewport2(p,a) (p)->lpVtbl->SetViewport2(p,a)
+#else
+#define IDirect3DViewport2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DViewport2_AddRef(p) (p)->AddRef()
+#define IDirect3DViewport2_Release(p) (p)->Release()
+#define IDirect3DViewport2_Initialize(p,a) (p)->Initialize(a)
+#define IDirect3DViewport2_GetViewport(p,a) (p)->GetViewport(a)
+#define IDirect3DViewport2_SetViewport(p,a) (p)->SetViewport(a)
+#define IDirect3DViewport2_TransformVertices(p,a,b,c,d) (p)->TransformVertices(a,b,c,d)
+#define IDirect3DViewport2_LightElements(p,a,b) (p)->LightElements(a,b)
+#define IDirect3DViewport2_SetBackground(p,a) (p)->SetBackground(a)
+#define IDirect3DViewport2_GetBackground(p,a,b) (p)->GetBackground(a,b)
+#define IDirect3DViewport2_SetBackgroundDepth(p,a) (p)->SetBackgroundDepth(a)
+#define IDirect3DViewport2_GetBackgroundDepth(p,a,b) (p)->GetBackgroundDepth(a,b)
+#define IDirect3DViewport2_Clear(p,a,b,c) (p)->Clear(a,b,c)
+#define IDirect3DViewport2_AddLight(p,a) (p)->AddLight(a)
+#define IDirect3DViewport2_DeleteLight(p,a) (p)->DeleteLight(a)
+#define IDirect3DViewport2_NextLight(p,a,b,c) (p)->NextLight(a,b,c)
+#define IDirect3DViewport2_GetViewport2(p,a) (p)->GetViewport2(a)
+#define IDirect3DViewport2_SetViewport2(p,a) (p)->SetViewport2(a)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+
+#undef INTERFACE
+#define INTERFACE IDirect3DViewport3
+
+DECLARE_INTERFACE_(IDirect3DViewport3, IDirect3DViewport2)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DViewport2 methods ***/
+    STDMETHOD(Initialize)(THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(GetViewport)(THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(SetViewport)(THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(TransformVertices)(THIS_ DWORD,LPD3DTRANSFORMDATA,DWORD,LPDWORD) PURE;
+    STDMETHOD(LightElements)(THIS_ DWORD,LPD3DLIGHTDATA) PURE;
+    STDMETHOD(SetBackground)(THIS_ D3DMATERIALHANDLE) PURE;
+    STDMETHOD(GetBackground)(THIS_ LPD3DMATERIALHANDLE,LPBOOL) PURE;
+    STDMETHOD(SetBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(GetBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE*,LPBOOL) PURE;
+    STDMETHOD(Clear)(THIS_ DWORD,LPD3DRECT,DWORD) PURE;
+    STDMETHOD(AddLight)(THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(NextLight)(THIS_ LPDIRECT3DLIGHT,LPDIRECT3DLIGHT*,DWORD) PURE;
+    STDMETHOD(GetViewport2)(THIS_ LPD3DVIEWPORT2) PURE;
+    STDMETHOD(SetViewport2)(THIS_ LPD3DVIEWPORT2) PURE;
+    STDMETHOD(SetBackgroundDepth2)(THIS_ LPDIRECTDRAWSURFACE4) PURE;
+    STDMETHOD(GetBackgroundDepth2)(THIS_ LPDIRECTDRAWSURFACE4*,LPBOOL) PURE;
+    STDMETHOD(Clear2)(THIS_ DWORD,LPD3DRECT,DWORD,D3DCOLOR,D3DVALUE,DWORD) PURE;
+};
+
+typedef struct IDirect3DViewport3 *LPDIRECT3DVIEWPORT3;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DViewport3_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DViewport3_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DViewport3_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DViewport3_Initialize(p,a) (p)->lpVtbl->Initialize(p,a)
+#define IDirect3DViewport3_GetViewport(p,a) (p)->lpVtbl->GetViewport(p,a)
+#define IDirect3DViewport3_SetViewport(p,a) (p)->lpVtbl->SetViewport(p,a)
+#define IDirect3DViewport3_TransformVertices(p,a,b,c,d) (p)->lpVtbl->TransformVertices(p,a,b,c,d)
+#define IDirect3DViewport3_LightElements(p,a,b) (p)->lpVtbl->LightElements(p,a,b)
+#define IDirect3DViewport3_SetBackground(p,a) (p)->lpVtbl->SetBackground(p,a)
+#define IDirect3DViewport3_GetBackground(p,a,b) (p)->lpVtbl->GetBackground(p,a,b)
+#define IDirect3DViewport3_SetBackgroundDepth(p,a) (p)->lpVtbl->SetBackgroundDepth(p,a)
+#define IDirect3DViewport3_GetBackgroundDepth(p,a,b) (p)->lpVtbl->GetBackgroundDepth(p,a,b)
+#define IDirect3DViewport3_Clear(p,a,b,c) (p)->lpVtbl->Clear(p,a,b,c)
+#define IDirect3DViewport3_AddLight(p,a) (p)->lpVtbl->AddLight(p,a)
+#define IDirect3DViewport3_DeleteLight(p,a) (p)->lpVtbl->DeleteLight(p,a)
+#define IDirect3DViewport3_NextLight(p,a,b,c) (p)->lpVtbl->NextLight(p,a,b,c)
+#define IDirect3DViewport3_GetViewport2(p,a) (p)->lpVtbl->GetViewport2(p,a)
+#define IDirect3DViewport3_SetViewport2(p,a) (p)->lpVtbl->SetViewport2(p,a)
+#define IDirect3DViewport3_SetBackgroundDepth2(p,a) (p)->lpVtbl->SetBackgroundDepth2(p,a)
+#define IDirect3DViewport3_GetBackgroundDepth2(p,a,b) (p)->lpVtbl->GetBackgroundDepth2(p,a,b)
+#define IDirect3DViewport3_Clear2(p,a,b,c,d,e,f) (p)->lpVtbl->Clear2(p,a,b,c,d,e,f)
+#else
+#define IDirect3DViewport3_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DViewport3_AddRef(p) (p)->AddRef()
+#define IDirect3DViewport3_Release(p) (p)->Release()
+#define IDirect3DViewport3_Initialize(p,a) (p)->Initialize(a)
+#define IDirect3DViewport3_GetViewport(p,a) (p)->GetViewport(a)
+#define IDirect3DViewport3_SetViewport(p,a) (p)->SetViewport(a)
+#define IDirect3DViewport3_TransformVertices(p,a,b,c,d) (p)->TransformVertices(a,b,c,d)
+#define IDirect3DViewport3_LightElements(p,a,b) (p)->LightElements(a,b)
+#define IDirect3DViewport3_SetBackground(p,a) (p)->SetBackground(a)
+#define IDirect3DViewport3_GetBackground(p,a,b) (p)->GetBackground(a,b)
+#define IDirect3DViewport3_SetBackgroundDepth(p,a) (p)->SetBackgroundDepth(a)
+#define IDirect3DViewport3_GetBackgroundDepth(p,a,b) (p)->GetBackgroundDepth(a,b)
+#define IDirect3DViewport3_Clear(p,a,b,c) (p)->Clear(a,b,c)
+#define IDirect3DViewport3_AddLight(p,a) (p)->AddLight(a)
+#define IDirect3DViewport3_DeleteLight(p,a) (p)->DeleteLight(a)
+#define IDirect3DViewport3_NextLight(p,a,b,c) (p)->NextLight(a,b,c)
+#define IDirect3DViewport3_GetViewport2(p,a) (p)->GetViewport2(a)
+#define IDirect3DViewport3_SetViewport2(p,a) (p)->SetViewport2(a)
+#define IDirect3DViewport3_SetBackgroundDepth2(p,a) (p)->SetBackgroundDepth2(a)
+#define IDirect3DViewport3_GetBackgroundDepth2(p,a,b) (p)->GetBackgroundDepth2(a,b)
+#define IDirect3DViewport3_Clear2(p,a,b,c,d,e,f) (p)->Clear2(a,b,c,d,e,f)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+#undef INTERFACE
+#define INTERFACE IDirect3DVertexBuffer
+
+DECLARE_INTERFACE_(IDirect3DVertexBuffer, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DVertexBuffer methods ***/
+    STDMETHOD(Lock)(THIS_ DWORD,LPVOID*,LPDWORD) PURE;
+    STDMETHOD(Unlock)(THIS) PURE;
+    STDMETHOD(ProcessVertices)(THIS_ DWORD,DWORD,DWORD,LPDIRECT3DVERTEXBUFFER,DWORD,LPDIRECT3DDEVICE3,DWORD) PURE;
+    STDMETHOD(GetVertexBufferDesc)(THIS_ LPD3DVERTEXBUFFERDESC) PURE;
+    STDMETHOD(Optimize)(THIS_ LPDIRECT3DDEVICE3,DWORD) PURE;
+};
+
+typedef struct IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DVertexBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVertexBuffer_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DVertexBuffer_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DVertexBuffer_Lock(p,a,b,c) (p)->lpVtbl->Lock(p,a,b,c)
+#define IDirect3DVertexBuffer_Unlock(p) (p)->lpVtbl->Unlock(p)
+#define IDirect3DVertexBuffer_ProcessVertices(p,a,b,c,d,e,f,g) (p)->lpVtbl->ProcessVertices(p,a,b,c,d,e,f,g)
+#define IDirect3DVertexBuffer_GetVertexBufferDesc(p,a) (p)->lpVtbl->GetVertexBufferDesc(p,a)
+#define IDirect3DVertexBuffer_Optimize(p,a,b) (p)->lpVtbl->Optimize(p,a,b)
+#else
+#define IDirect3DVertexBuffer_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DVertexBuffer_AddRef(p) (p)->AddRef()
+#define IDirect3DVertexBuffer_Release(p) (p)->Release()
+#define IDirect3DVertexBuffer_Lock(p,a,b,c) (p)->Lock(a,b,c)
+#define IDirect3DVertexBuffer_Unlock(p) (p)->Unlock()
+#define IDirect3DVertexBuffer_ProcessVertices(p,a,b,c,d,e,f,g) (p)->ProcessVertices(a,b,c,d,e,f,g)
+#define IDirect3DVertexBuffer_GetVertexBufferDesc(p,a) (p)->GetVertexBufferDesc(a)
+#define IDirect3DVertexBuffer_Optimize(p,a,b) (p)->Optimize(a,b)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+#undef INTERFACE
+#define INTERFACE IDirect3DVertexBuffer7
+
+DECLARE_INTERFACE_(IDirect3DVertexBuffer7, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirect3DVertexBuffer7 methods ***/
+    STDMETHOD(Lock)(THIS_ DWORD,LPVOID*,LPDWORD) PURE;
+    STDMETHOD(Unlock)(THIS) PURE;
+    STDMETHOD(ProcessVertices)(THIS_ DWORD,DWORD,DWORD,LPDIRECT3DVERTEXBUFFER7,DWORD,LPDIRECT3DDEVICE7,DWORD) PURE;
+    STDMETHOD(GetVertexBufferDesc)(THIS_ LPD3DVERTEXBUFFERDESC) PURE;
+    STDMETHOD(Optimize)(THIS_ LPDIRECT3DDEVICE7,DWORD) PURE;
+    STDMETHOD(ProcessVerticesStrided)(THIS_ DWORD,DWORD,DWORD,LPD3DDRAWPRIMITIVESTRIDEDDATA,DWORD,LPDIRECT3DDEVICE7,DWORD) PURE;
+};
+
+typedef struct IDirect3DVertexBuffer7 *LPDIRECT3DVERTEXBUFFER7;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DVertexBuffer7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVertexBuffer7_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DVertexBuffer7_Release(p) (p)->lpVtbl->Release(p)
+#define IDirect3DVertexBuffer7_Lock(p,a,b,c) (p)->lpVtbl->Lock(p,a,b,c)
+#define IDirect3DVertexBuffer7_Unlock(p) (p)->lpVtbl->Unlock(p)
+#define IDirect3DVertexBuffer7_ProcessVertices(p,a,b,c,d,e,f,g) (p)->lpVtbl->ProcessVertices(p,a,b,c,d,e,f,g)
+#define IDirect3DVertexBuffer7_GetVertexBufferDesc(p,a) (p)->lpVtbl->GetVertexBufferDesc(p,a)
+#define IDirect3DVertexBuffer7_Optimize(p,a,b) (p)->lpVtbl->Optimize(p,a,b)
+#define IDirect3DVertexBuffer7_ProcessVerticesStrided(p,a,b,c,d,e,f,g) (p)->lpVtbl->ProcessVerticesStrided(p,a,b,c,d,e,f,g)
+#else
+#define IDirect3DVertexBuffer7_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DVertexBuffer7_AddRef(p) (p)->AddRef()
+#define IDirect3DVertexBuffer7_Release(p) (p)->Release()
+#define IDirect3DVertexBuffer7_Lock(p,a,b,c) (p)->Lock(a,b,c)
+#define IDirect3DVertexBuffer7_Unlock(p) (p)->Unlock()
+#define IDirect3DVertexBuffer7_ProcessVertices(p,a,b,c,d,e,f,g) (p)->ProcessVertices(a,b,c,d,e,f,g)
+#define IDirect3DVertexBuffer7_GetVertexBufferDesc(p,a) (p)->GetVertexBufferDesc(a)
+#define IDirect3DVertexBuffer7_Optimize(p,a,b) (p)->Optimize(a,b)
+#define IDirect3DVertexBuffer7_ProcessVerticesStrided(p,a,b,c,d,e,f,g) (p)->ProcessVerticesStrided(a,b,c,d,e,f,g)
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#if(DIRECT3D_VERSION >= 0x0500)
+/****************************************************************************
+ *
+ * Flags for IDirect3DDevice::NextViewport
+ *
+ ****************************************************************************/
+
+/*
+ * Return the next OldViewport
+ */
+#define D3DNEXT_NEXT    0x00000001l
+
+/*
+ * Return the first OldViewport
+ */
+#define D3DNEXT_HEAD    0x00000002l
+
+/*
+ * Return the last OldViewport
+ */
+#define D3DNEXT_TAIL    0x00000004l
+
+
+/****************************************************************************
+ *
+ * Flags for DrawPrimitive/DrawIndexedPrimitive
+ *   Also valid for Begin/BeginIndexed
+ *   Also valid for VertexBuffer::CreateVertexBuffer
+ ****************************************************************************/
+
+/*
+ * Wait until the device is ready to draw the primitive
+ * This will cause DP to not return DDERR_WASSTILLDRAWING
+ */
+#define D3DDP_WAIT                  0x00000001l
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if (DIRECT3D_VERSION == 0x0500)
+/*
+ * Hint that it is acceptable to render the primitive out of order.
+ */
+#define D3DDP_OUTOFORDER            0x00000002l
+#endif
+
+
+#if(DIRECT3D_VERSION >= 0x0500)
+/*
+ * Hint that the primitives have been clipped by the application.
+ */
+#define D3DDP_DONOTCLIP             0x00000004l
+
+/*
+ * Hint that the extents need not be updated.
+ */
+#define D3DDP_DONOTUPDATEEXTENTS    0x00000008l
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+
+/*
+ * Hint that the lighting should not be applied on vertices.
+ */
+
+#define D3DDP_DONOTLIGHT            0x00000010l
+
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+/*
+ * Direct3D Errors
+ * DirectDraw error codes are used when errors not specified here.
+ */
+#define D3D_OK              DD_OK
+#define D3DERR_BADMAJORVERSION      MAKE_DDHRESULT(700)
+#define D3DERR_BADMINORVERSION      MAKE_DDHRESULT(701)
+
+#if(DIRECT3D_VERSION >= 0x0500)
+/*
+ * An invalid device was requested by the application.
+ */
+#define D3DERR_INVALID_DEVICE   MAKE_DDHRESULT(705)
+#define D3DERR_INITFAILED       MAKE_DDHRESULT(706)
+
+/*
+ * SetRenderTarget attempted on a device that was
+ * QI'd off the render target.
+ */
+#define D3DERR_DEVICEAGGREGATED MAKE_DDHRESULT(707)
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#define D3DERR_EXECUTE_CREATE_FAILED    MAKE_DDHRESULT(710)
+#define D3DERR_EXECUTE_DESTROY_FAILED   MAKE_DDHRESULT(711)
+#define D3DERR_EXECUTE_LOCK_FAILED  MAKE_DDHRESULT(712)
+#define D3DERR_EXECUTE_UNLOCK_FAILED    MAKE_DDHRESULT(713)
+#define D3DERR_EXECUTE_LOCKED       MAKE_DDHRESULT(714)
+#define D3DERR_EXECUTE_NOT_LOCKED   MAKE_DDHRESULT(715)
+
+#define D3DERR_EXECUTE_FAILED       MAKE_DDHRESULT(716)
+#define D3DERR_EXECUTE_CLIPPED_FAILED   MAKE_DDHRESULT(717)
+
+#define D3DERR_TEXTURE_NO_SUPPORT   MAKE_DDHRESULT(720)
+#define D3DERR_TEXTURE_CREATE_FAILED    MAKE_DDHRESULT(721)
+#define D3DERR_TEXTURE_DESTROY_FAILED   MAKE_DDHRESULT(722)
+#define D3DERR_TEXTURE_LOCK_FAILED  MAKE_DDHRESULT(723)
+#define D3DERR_TEXTURE_UNLOCK_FAILED    MAKE_DDHRESULT(724)
+#define D3DERR_TEXTURE_LOAD_FAILED  MAKE_DDHRESULT(725)
+#define D3DERR_TEXTURE_SWAP_FAILED  MAKE_DDHRESULT(726)
+#define D3DERR_TEXTURE_LOCKED       MAKE_DDHRESULT(727)
+#define D3DERR_TEXTURE_NOT_LOCKED   MAKE_DDHRESULT(728)
+#define D3DERR_TEXTURE_GETSURF_FAILED   MAKE_DDHRESULT(729)
+
+#define D3DERR_MATRIX_CREATE_FAILED MAKE_DDHRESULT(730)
+#define D3DERR_MATRIX_DESTROY_FAILED    MAKE_DDHRESULT(731)
+#define D3DERR_MATRIX_SETDATA_FAILED    MAKE_DDHRESULT(732)
+#define D3DERR_MATRIX_GETDATA_FAILED    MAKE_DDHRESULT(733)
+#define D3DERR_SETVIEWPORTDATA_FAILED   MAKE_DDHRESULT(734)
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#define D3DERR_INVALIDCURRENTVIEWPORT   MAKE_DDHRESULT(735)
+#define D3DERR_INVALIDPRIMITIVETYPE     MAKE_DDHRESULT(736)
+#define D3DERR_INVALIDVERTEXTYPE        MAKE_DDHRESULT(737)
+#define D3DERR_TEXTURE_BADSIZE          MAKE_DDHRESULT(738)
+#define D3DERR_INVALIDRAMPTEXTURE       MAKE_DDHRESULT(739)
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#define D3DERR_MATERIAL_CREATE_FAILED   MAKE_DDHRESULT(740)
+#define D3DERR_MATERIAL_DESTROY_FAILED  MAKE_DDHRESULT(741)
+#define D3DERR_MATERIAL_SETDATA_FAILED  MAKE_DDHRESULT(742)
+#define D3DERR_MATERIAL_GETDATA_FAILED  MAKE_DDHRESULT(743)
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#define D3DERR_INVALIDPALETTE           MAKE_DDHRESULT(744)
+
+#define D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY MAKE_DDHRESULT(745)
+#define D3DERR_ZBUFF_NEEDS_VIDEOMEMORY  MAKE_DDHRESULT(746)
+#define D3DERR_SURFACENOTINVIDMEM       MAKE_DDHRESULT(747)
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#define D3DERR_LIGHT_SET_FAILED     MAKE_DDHRESULT(750)
+#if(DIRECT3D_VERSION >= 0x0500)
+#define D3DERR_LIGHTHASVIEWPORT     MAKE_DDHRESULT(751)
+#define D3DERR_LIGHTNOTINTHISVIEWPORT           MAKE_DDHRESULT(752)
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#define D3DERR_SCENE_IN_SCENE       MAKE_DDHRESULT(760)
+#define D3DERR_SCENE_NOT_IN_SCENE   MAKE_DDHRESULT(761)
+#define D3DERR_SCENE_BEGIN_FAILED   MAKE_DDHRESULT(762)
+#define D3DERR_SCENE_END_FAILED     MAKE_DDHRESULT(763)
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#define D3DERR_INBEGIN                  MAKE_DDHRESULT(770)
+#define D3DERR_NOTINBEGIN               MAKE_DDHRESULT(771)
+#define D3DERR_NOVIEWPORTS              MAKE_DDHRESULT(772)
+#define D3DERR_VIEWPORTDATANOTSET       MAKE_DDHRESULT(773)
+#define D3DERR_VIEWPORTHASNODEVICE      MAKE_DDHRESULT(774)
+#define D3DERR_NOCURRENTVIEWPORT        MAKE_DDHRESULT(775)
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+#define D3DERR_INVALIDVERTEXFORMAT              MAKE_DDHRESULT(2048)
+
+/*
+ * Attempted to CreateTexture on a surface that had a color key
+ */
+#define D3DERR_COLORKEYATTACHED                 MAKE_DDHRESULT(2050)
+
+#define D3DERR_VERTEXBUFFEROPTIMIZED            MAKE_DDHRESULT(2060)
+#define D3DERR_VBUF_CREATE_FAILED               MAKE_DDHRESULT(2061)
+#define D3DERR_VERTEXBUFFERLOCKED               MAKE_DDHRESULT(2062)
+#define D3DERR_VERTEXBUFFERUNLOCKFAILED         MAKE_DDHRESULT(2063)
+
+#define D3DERR_ZBUFFER_NOTPRESENT               MAKE_DDHRESULT(2070)
+#define D3DERR_STENCILBUFFER_NOTPRESENT         MAKE_DDHRESULT(2071)
+
+#define D3DERR_WRONGTEXTUREFORMAT               MAKE_DDHRESULT(2072)
+#define D3DERR_UNSUPPORTEDCOLOROPERATION        MAKE_DDHRESULT(2073)
+#define D3DERR_UNSUPPORTEDCOLORARG              MAKE_DDHRESULT(2074)
+#define D3DERR_UNSUPPORTEDALPHAOPERATION        MAKE_DDHRESULT(2075)
+#define D3DERR_UNSUPPORTEDALPHAARG              MAKE_DDHRESULT(2076)
+#define D3DERR_TOOMANYOPERATIONS                MAKE_DDHRESULT(2077)
+#define D3DERR_CONFLICTINGTEXTUREFILTER         MAKE_DDHRESULT(2078)
+#define D3DERR_UNSUPPORTEDFACTORVALUE           MAKE_DDHRESULT(2079)
+#define D3DERR_CONFLICTINGRENDERSTATE           MAKE_DDHRESULT(2081)
+#define D3DERR_UNSUPPORTEDTEXTUREFILTER         MAKE_DDHRESULT(2082)
+#define D3DERR_TOOMANYPRIMITIVES                MAKE_DDHRESULT(2083)
+#define D3DERR_INVALIDMATRIX                    MAKE_DDHRESULT(2084)
+#define D3DERR_TOOMANYVERTICES                  MAKE_DDHRESULT(2085)
+#define D3DERR_CONFLICTINGTEXTUREPALETTE        MAKE_DDHRESULT(2086)
+
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+#define D3DERR_INVALIDSTATEBLOCK        MAKE_DDHRESULT(2100)
+#define D3DERR_INBEGINSTATEBLOCK        MAKE_DDHRESULT(2101)
+#define D3DERR_NOTINBEGINSTATEBLOCK     MAKE_DDHRESULT(2102)
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* (DIRECT3D_VERSION < 0x0800) */
+#endif /* _D3D_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/d3dcaps.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,601 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) Microsoft Corporation.  All Rights Reserved. 
+ *
+ *  File:       d3dcaps.h
+ *  Content:    Direct3D capabilities include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DCAPS_H
+#define _D3DCAPS_H
+
+/*
+ *  Pull in DirectDraw include file automatically:
+ */
+#include "ddraw.h"
+
+#ifndef DIRECT3D_VERSION
+#define DIRECT3D_VERSION         0x0700
+#endif
+
+#if defined(_X86_) || defined(_IA64_)
+#pragma pack(4)
+#endif
+
+/* Description of capabilities of transform */
+
+typedef struct _D3DTRANSFORMCAPS {
+    DWORD dwSize;
+    DWORD dwCaps;
+} D3DTRANSFORMCAPS, *LPD3DTRANSFORMCAPS;
+
+#define D3DTRANSFORMCAPS_CLIP           0x00000001L /* Will clip whilst transforming */
+
+/* Description of capabilities of lighting */
+
+typedef struct _D3DLIGHTINGCAPS {
+    DWORD dwSize;
+    DWORD dwCaps;                   /* Lighting caps */
+    DWORD dwLightingModel;          /* Lighting model - RGB or mono */
+    DWORD dwNumLights;              /* Number of lights that can be handled */
+} D3DLIGHTINGCAPS, *LPD3DLIGHTINGCAPS;
+
+#define D3DLIGHTINGMODEL_RGB            0x00000001L
+#define D3DLIGHTINGMODEL_MONO           0x00000002L
+
+#define D3DLIGHTCAPS_POINT              0x00000001L /* Point lights supported */
+#define D3DLIGHTCAPS_SPOT               0x00000002L /* Spot lights supported */
+#define D3DLIGHTCAPS_DIRECTIONAL        0x00000004L /* Directional lights supported */
+#if(DIRECT3D_VERSION < 0x700)
+#define D3DLIGHTCAPS_PARALLELPOINT      0x00000008L /* Parallel point lights supported */
+#endif
+#if(DIRECT3D_VERSION < 0x500)
+#define D3DLIGHTCAPS_GLSPOT             0x00000010L /* GL syle spot lights supported */
+#endif
+
+/* Description of capabilities for each primitive type */
+
+typedef struct _D3DPrimCaps {
+    DWORD dwSize;
+    DWORD dwMiscCaps;                 /* Capability flags */
+    DWORD dwRasterCaps;
+    DWORD dwZCmpCaps;
+    DWORD dwSrcBlendCaps;
+    DWORD dwDestBlendCaps;
+    DWORD dwAlphaCmpCaps;
+    DWORD dwShadeCaps;
+    DWORD dwTextureCaps;
+    DWORD dwTextureFilterCaps;
+    DWORD dwTextureBlendCaps;
+    DWORD dwTextureAddressCaps;
+    DWORD dwStippleWidth;             /* maximum width and height of */
+    DWORD dwStippleHeight;            /* of supported stipple (up to 32x32) */
+} D3DPRIMCAPS, *LPD3DPRIMCAPS;
+
+/* D3DPRIMCAPS dwMiscCaps */
+
+#define D3DPMISCCAPS_MASKPLANES         0x00000001L
+#define D3DPMISCCAPS_MASKZ              0x00000002L
+#define D3DPMISCCAPS_LINEPATTERNREP     0x00000004L
+#define D3DPMISCCAPS_CONFORMANT         0x00000008L
+#define D3DPMISCCAPS_CULLNONE           0x00000010L
+#define D3DPMISCCAPS_CULLCW             0x00000020L
+#define D3DPMISCCAPS_CULLCCW            0x00000040L
+
+/* D3DPRIMCAPS dwRasterCaps */
+
+#define D3DPRASTERCAPS_DITHER                   0x00000001L
+#define D3DPRASTERCAPS_ROP2                     0x00000002L
+#define D3DPRASTERCAPS_XOR                      0x00000004L
+#define D3DPRASTERCAPS_PAT                      0x00000008L
+#define D3DPRASTERCAPS_ZTEST                    0x00000010L
+#define D3DPRASTERCAPS_SUBPIXEL                 0x00000020L
+#define D3DPRASTERCAPS_SUBPIXELX                0x00000040L
+#define D3DPRASTERCAPS_FOGVERTEX                0x00000080L
+#define D3DPRASTERCAPS_FOGTABLE                 0x00000100L
+#define D3DPRASTERCAPS_STIPPLE                  0x00000200L
+#if(DIRECT3D_VERSION >= 0x0500)
+#define D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT   0x00000400L
+#define D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT 0x00000800L
+#define D3DPRASTERCAPS_ANTIALIASEDGES           0x00001000L
+#define D3DPRASTERCAPS_MIPMAPLODBIAS            0x00002000L
+#define D3DPRASTERCAPS_ZBIAS                    0x00004000L
+#define D3DPRASTERCAPS_ZBUFFERLESSHSR           0x00008000L
+#define D3DPRASTERCAPS_FOGRANGE                 0x00010000L
+#define D3DPRASTERCAPS_ANISOTROPY               0x00020000L
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+#if(DIRECT3D_VERSION >= 0x0600)
+#define D3DPRASTERCAPS_WBUFFER                      0x00040000L
+#define D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT   0x00080000L
+#define D3DPRASTERCAPS_WFOG                         0x00100000L
+#define D3DPRASTERCAPS_ZFOG                         0x00200000L
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+/* D3DPRIMCAPS dwZCmpCaps, dwAlphaCmpCaps */
+
+#define D3DPCMPCAPS_NEVER               0x00000001L
+#define D3DPCMPCAPS_LESS                0x00000002L
+#define D3DPCMPCAPS_EQUAL               0x00000004L
+#define D3DPCMPCAPS_LESSEQUAL           0x00000008L
+#define D3DPCMPCAPS_GREATER             0x00000010L
+#define D3DPCMPCAPS_NOTEQUAL            0x00000020L
+#define D3DPCMPCAPS_GREATEREQUAL        0x00000040L
+#define D3DPCMPCAPS_ALWAYS              0x00000080L
+
+/* D3DPRIMCAPS dwSourceBlendCaps, dwDestBlendCaps */
+
+#define D3DPBLENDCAPS_ZERO              0x00000001L
+#define D3DPBLENDCAPS_ONE               0x00000002L
+#define D3DPBLENDCAPS_SRCCOLOR          0x00000004L
+#define D3DPBLENDCAPS_INVSRCCOLOR       0x00000008L
+#define D3DPBLENDCAPS_SRCALPHA          0x00000010L
+#define D3DPBLENDCAPS_INVSRCALPHA       0x00000020L
+#define D3DPBLENDCAPS_DESTALPHA         0x00000040L
+#define D3DPBLENDCAPS_INVDESTALPHA      0x00000080L
+#define D3DPBLENDCAPS_DESTCOLOR         0x00000100L
+#define D3DPBLENDCAPS_INVDESTCOLOR      0x00000200L
+#define D3DPBLENDCAPS_SRCALPHASAT       0x00000400L
+#define D3DPBLENDCAPS_BOTHSRCALPHA      0x00000800L
+#define D3DPBLENDCAPS_BOTHINVSRCALPHA   0x00001000L
+
+/* D3DPRIMCAPS dwShadeCaps */
+
+#define D3DPSHADECAPS_COLORFLATMONO             0x00000001L
+#define D3DPSHADECAPS_COLORFLATRGB              0x00000002L
+#define D3DPSHADECAPS_COLORGOURAUDMONO          0x00000004L
+#define D3DPSHADECAPS_COLORGOURAUDRGB           0x00000008L
+#define D3DPSHADECAPS_COLORPHONGMONO            0x00000010L
+#define D3DPSHADECAPS_COLORPHONGRGB             0x00000020L
+
+#define D3DPSHADECAPS_SPECULARFLATMONO          0x00000040L
+#define D3DPSHADECAPS_SPECULARFLATRGB           0x00000080L
+#define D3DPSHADECAPS_SPECULARGOURAUDMONO       0x00000100L
+#define D3DPSHADECAPS_SPECULARGOURAUDRGB        0x00000200L
+#define D3DPSHADECAPS_SPECULARPHONGMONO         0x00000400L
+#define D3DPSHADECAPS_SPECULARPHONGRGB          0x00000800L
+
+#define D3DPSHADECAPS_ALPHAFLATBLEND            0x00001000L
+#define D3DPSHADECAPS_ALPHAFLATSTIPPLED         0x00002000L
+#define D3DPSHADECAPS_ALPHAGOURAUDBLEND         0x00004000L
+#define D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED      0x00008000L
+#define D3DPSHADECAPS_ALPHAPHONGBLEND           0x00010000L
+#define D3DPSHADECAPS_ALPHAPHONGSTIPPLED        0x00020000L
+
+#define D3DPSHADECAPS_FOGFLAT                   0x00040000L
+#define D3DPSHADECAPS_FOGGOURAUD                0x00080000L
+#define D3DPSHADECAPS_FOGPHONG                  0x00100000L
+
+/* D3DPRIMCAPS dwTextureCaps */
+
+/*
+ * Perspective-correct texturing is supported
+ */
+#define D3DPTEXTURECAPS_PERSPECTIVE     0x00000001L
+
+/*
+ * Power-of-2 texture dimensions are required
+ */
+#define D3DPTEXTURECAPS_POW2            0x00000002L
+
+/*
+ * Alpha in texture pixels is supported
+ */
+#define D3DPTEXTURECAPS_ALPHA           0x00000004L
+
+/*
+ * Color-keyed textures are supported
+ */
+#define D3DPTEXTURECAPS_TRANSPARENCY    0x00000008L
+
+/*
+ * obsolete, see D3DPTADDRESSCAPS_BORDER
+ */
+#define D3DPTEXTURECAPS_BORDER          0x00000010L
+
+/*
+ * Only square textures are supported
+ */
+#define D3DPTEXTURECAPS_SQUAREONLY      0x00000020L
+
+#if(DIRECT3D_VERSION >= 0x0600)
+/*
+ * Texture indices are not scaled by the texture size prior
+ * to interpolation.
+ */
+#define D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE 0x00000040L
+
+/*
+ * Device can draw alpha from texture palettes
+ */
+#define D3DPTEXTURECAPS_ALPHAPALETTE    0x00000080L
+
+/*
+ * Device can use non-POW2 textures if:
+ *  1) D3DTEXTURE_ADDRESS is set to CLAMP for this texture's stage
+ *  2) D3DRS_WRAP(N) is zero for this texture's coordinates
+ *  3) mip mapping is not enabled (use magnification filter only)
+ */
+#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL  0x00000100L
+
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0700)
+
+// 0x00000200L unused
+
+/*
+ * Device can divide transformed texture coordinates by the
+ * COUNTth texture coordinate (can do D3DTTFF_PROJECTED)
+ */
+#define D3DPTEXTURECAPS_PROJECTED  0x00000400L
+
+/*
+ * Device can do cubemap textures
+ */
+#define D3DPTEXTURECAPS_CUBEMAP           0x00000800L
+
+#define D3DPTEXTURECAPS_COLORKEYBLEND     0x00001000L
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+/* D3DPRIMCAPS dwTextureFilterCaps */
+
+#define D3DPTFILTERCAPS_NEAREST         0x00000001L
+#define D3DPTFILTERCAPS_LINEAR          0x00000002L
+#define D3DPTFILTERCAPS_MIPNEAREST      0x00000004L
+#define D3DPTFILTERCAPS_MIPLINEAR       0x00000008L
+#define D3DPTFILTERCAPS_LINEARMIPNEAREST 0x00000010L
+#define D3DPTFILTERCAPS_LINEARMIPLINEAR 0x00000020L
+
+#if(DIRECT3D_VERSION >= 0x0600)
+/* Device3 Min Filter */
+#define D3DPTFILTERCAPS_MINFPOINT       0x00000100L
+#define D3DPTFILTERCAPS_MINFLINEAR      0x00000200L
+#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L
+
+/* Device3 Mip Filter */
+#define D3DPTFILTERCAPS_MIPFPOINT       0x00010000L
+#define D3DPTFILTERCAPS_MIPFLINEAR      0x00020000L
+
+/* Device3 Mag Filter */
+#define D3DPTFILTERCAPS_MAGFPOINT         0x01000000L
+#define D3DPTFILTERCAPS_MAGFLINEAR        0x02000000L
+#define D3DPTFILTERCAPS_MAGFANISOTROPIC   0x04000000L
+#define D3DPTFILTERCAPS_MAGFAFLATCUBIC    0x08000000L
+#define D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC 0x10000000L
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+/* D3DPRIMCAPS dwTextureBlendCaps */
+
+#define D3DPTBLENDCAPS_DECAL            0x00000001L
+#define D3DPTBLENDCAPS_MODULATE         0x00000002L
+#define D3DPTBLENDCAPS_DECALALPHA       0x00000004L
+#define D3DPTBLENDCAPS_MODULATEALPHA    0x00000008L
+#define D3DPTBLENDCAPS_DECALMASK        0x00000010L
+#define D3DPTBLENDCAPS_MODULATEMASK     0x00000020L
+#define D3DPTBLENDCAPS_COPY             0x00000040L
+#if(DIRECT3D_VERSION >= 0x0500)
+#define D3DPTBLENDCAPS_ADD              0x00000080L
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+/* D3DPRIMCAPS dwTextureAddressCaps */
+#define D3DPTADDRESSCAPS_WRAP           0x00000001L
+#define D3DPTADDRESSCAPS_MIRROR         0x00000002L
+#define D3DPTADDRESSCAPS_CLAMP          0x00000004L
+#if(DIRECT3D_VERSION >= 0x0500)
+#define D3DPTADDRESSCAPS_BORDER         0x00000008L
+#define D3DPTADDRESSCAPS_INDEPENDENTUV  0x00000010L
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+
+/* D3DDEVICEDESC dwStencilCaps */
+
+#define D3DSTENCILCAPS_KEEP     0x00000001L
+#define D3DSTENCILCAPS_ZERO     0x00000002L
+#define D3DSTENCILCAPS_REPLACE  0x00000004L
+#define D3DSTENCILCAPS_INCRSAT  0x00000008L
+#define D3DSTENCILCAPS_DECRSAT  0x00000010L
+#define D3DSTENCILCAPS_INVERT   0x00000020L
+#define D3DSTENCILCAPS_INCR     0x00000040L
+#define D3DSTENCILCAPS_DECR     0x00000080L
+
+/* D3DDEVICEDESC dwTextureOpCaps */
+
+#define D3DTEXOPCAPS_DISABLE                    0x00000001L
+#define D3DTEXOPCAPS_SELECTARG1                 0x00000002L
+#define D3DTEXOPCAPS_SELECTARG2                 0x00000004L
+#define D3DTEXOPCAPS_MODULATE                   0x00000008L
+#define D3DTEXOPCAPS_MODULATE2X                 0x00000010L
+#define D3DTEXOPCAPS_MODULATE4X                 0x00000020L
+#define D3DTEXOPCAPS_ADD                        0x00000040L
+#define D3DTEXOPCAPS_ADDSIGNED                  0x00000080L
+#define D3DTEXOPCAPS_ADDSIGNED2X                0x00000100L
+#define D3DTEXOPCAPS_SUBTRACT                   0x00000200L
+#define D3DTEXOPCAPS_ADDSMOOTH                  0x00000400L
+#define D3DTEXOPCAPS_BLENDDIFFUSEALPHA          0x00000800L
+#define D3DTEXOPCAPS_BLENDTEXTUREALPHA          0x00001000L
+#define D3DTEXOPCAPS_BLENDFACTORALPHA           0x00002000L
+#define D3DTEXOPCAPS_BLENDTEXTUREALPHAPM        0x00004000L
+#define D3DTEXOPCAPS_BLENDCURRENTALPHA          0x00008000L
+#define D3DTEXOPCAPS_PREMODULATE                0x00010000L
+#define D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR     0x00020000L
+#define D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA     0x00040000L
+#define D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR  0x00080000L
+#define D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA  0x00100000L
+#define D3DTEXOPCAPS_BUMPENVMAP                 0x00200000L
+#define D3DTEXOPCAPS_BUMPENVMAPLUMINANCE        0x00400000L
+#define D3DTEXOPCAPS_DOTPRODUCT3                0x00800000L
+
+/* D3DDEVICEDESC dwFVFCaps flags */
+
+#define D3DFVFCAPS_TEXCOORDCOUNTMASK    0x0000ffffL /* mask for texture coordinate count field */
+#define D3DFVFCAPS_DONOTSTRIPELEMENTS   0x00080000L /* Device prefers that vertex elements not be stripped */
+
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+/*
+ * Description for a device.
+ * This is used to describe a device that is to be created or to query
+ * the current device.
+ */
+typedef struct _D3DDeviceDesc {
+    DWORD            dwSize;                 /* Size of D3DDEVICEDESC structure */
+    DWORD            dwFlags;                /* Indicates which fields have valid data */
+    D3DCOLORMODEL    dcmColorModel;          /* Color model of device */
+    DWORD            dwDevCaps;              /* Capabilities of device */
+    D3DTRANSFORMCAPS dtcTransformCaps;       /* Capabilities of transform */
+    BOOL             bClipping;              /* Device can do 3D clipping */
+    D3DLIGHTINGCAPS  dlcLightingCaps;        /* Capabilities of lighting */
+    D3DPRIMCAPS      dpcLineCaps;
+    D3DPRIMCAPS      dpcTriCaps;
+    DWORD            dwDeviceRenderBitDepth; /* One of DDBB_8, 16, etc.. */
+    DWORD            dwDeviceZBufferBitDepth;/* One of DDBD_16, 32, etc.. */
+    DWORD            dwMaxBufferSize;        /* Maximum execute buffer size */
+    DWORD            dwMaxVertexCount;       /* Maximum vertex count */
+#if(DIRECT3D_VERSION >= 0x0500)
+    // *** New fields for DX5 *** //
+
+    // Width and height caps are 0 for legacy HALs.
+    DWORD        dwMinTextureWidth, dwMinTextureHeight;
+    DWORD        dwMaxTextureWidth, dwMaxTextureHeight;
+    DWORD        dwMinStippleWidth, dwMaxStippleWidth;
+    DWORD        dwMinStippleHeight, dwMaxStippleHeight;
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+    // New fields for DX6
+    DWORD       dwMaxTextureRepeat;
+    DWORD       dwMaxTextureAspectRatio;
+    DWORD       dwMaxAnisotropy;
+
+    // Guard band that the rasterizer can accommodate
+    // Screen-space vertices inside this space but outside the OldViewport
+    // will get clipped properly.
+    D3DVALUE    dvGuardBandLeft;
+    D3DVALUE    dvGuardBandTop;
+    D3DVALUE    dvGuardBandRight;
+    D3DVALUE    dvGuardBandBottom;
+
+    D3DVALUE    dvExtentsAdjust;
+    DWORD       dwStencilCaps;
+
+    DWORD       dwFVFCaps;
+    DWORD       dwTextureOpCaps;
+    WORD        wMaxTextureBlendStages;
+    WORD        wMaxSimultaneousTextures;
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+} D3DDEVICEDESC, *LPD3DDEVICEDESC;
+
+#if(DIRECT3D_VERSION >= 0x0700)
+typedef struct _D3DDeviceDesc7 {
+    DWORD            dwDevCaps;              /* Capabilities of device */
+    D3DPRIMCAPS      dpcLineCaps;
+    D3DPRIMCAPS      dpcTriCaps;
+    DWORD            dwDeviceRenderBitDepth; /* One of DDBB_8, 16, etc.. */
+    DWORD            dwDeviceZBufferBitDepth;/* One of DDBD_16, 32, etc.. */
+
+    DWORD       dwMinTextureWidth, dwMinTextureHeight;
+    DWORD       dwMaxTextureWidth, dwMaxTextureHeight;
+
+    DWORD       dwMaxTextureRepeat;
+    DWORD       dwMaxTextureAspectRatio;
+    DWORD       dwMaxAnisotropy;
+
+    D3DVALUE    dvGuardBandLeft;
+    D3DVALUE    dvGuardBandTop;
+    D3DVALUE    dvGuardBandRight;
+    D3DVALUE    dvGuardBandBottom;
+
+    D3DVALUE    dvExtentsAdjust;
+    DWORD       dwStencilCaps;
+
+    DWORD       dwFVFCaps;
+    DWORD       dwTextureOpCaps;
+    WORD        wMaxTextureBlendStages;
+    WORD        wMaxSimultaneousTextures;
+
+    DWORD       dwMaxActiveLights;
+    D3DVALUE    dvMaxVertexW;
+    GUID        deviceGUID;
+
+    WORD        wMaxUserClipPlanes;
+    WORD        wMaxVertexBlendMatrices;
+
+    DWORD       dwVertexProcessingCaps;
+
+    DWORD       dwReserved1;
+    DWORD       dwReserved2;
+    DWORD       dwReserved3;
+    DWORD       dwReserved4;
+} D3DDEVICEDESC7, *LPD3DDEVICEDESC7;
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#define D3DDEVICEDESCSIZE (sizeof(D3DDEVICEDESC))
+#define D3DDEVICEDESC7SIZE (sizeof(D3DDEVICEDESC7))
+
+typedef HRESULT (CALLBACK * LPD3DENUMDEVICESCALLBACK)(GUID FAR *lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC, LPD3DDEVICEDESC, LPVOID);
+
+#if(DIRECT3D_VERSION >= 0x0700)
+typedef HRESULT (CALLBACK * LPD3DENUMDEVICESCALLBACK7)(LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC7, LPVOID);
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+/* D3DDEVICEDESC dwFlags indicating valid fields */
+
+#define D3DDD_COLORMODEL            0x00000001L /* dcmColorModel is valid */
+#define D3DDD_DEVCAPS               0x00000002L /* dwDevCaps is valid */
+#define D3DDD_TRANSFORMCAPS         0x00000004L /* dtcTransformCaps is valid */
+#define D3DDD_LIGHTINGCAPS          0x00000008L /* dlcLightingCaps is valid */
+#define D3DDD_BCLIPPING             0x00000010L /* bClipping is valid */
+#define D3DDD_LINECAPS              0x00000020L /* dpcLineCaps is valid */
+#define D3DDD_TRICAPS               0x00000040L /* dpcTriCaps is valid */
+#define D3DDD_DEVICERENDERBITDEPTH  0x00000080L /* dwDeviceRenderBitDepth is valid */
+#define D3DDD_DEVICEZBUFFERBITDEPTH 0x00000100L /* dwDeviceZBufferBitDepth is valid */
+#define D3DDD_MAXBUFFERSIZE         0x00000200L /* dwMaxBufferSize is valid */
+#define D3DDD_MAXVERTEXCOUNT        0x00000400L /* dwMaxVertexCount is valid */
+
+/* D3DDEVICEDESC dwDevCaps flags */
+
+#define D3DDEVCAPS_FLOATTLVERTEX        0x00000001L /* Device accepts floating point */
+                                                    /* for post-transform vertex data */
+#define D3DDEVCAPS_SORTINCREASINGZ      0x00000002L /* Device needs data sorted for increasing Z */
+#define D3DDEVCAPS_SORTDECREASINGZ      0X00000004L /* Device needs data sorted for decreasing Z */
+#define D3DDEVCAPS_SORTEXACT            0x00000008L /* Device needs data sorted exactly */
+
+#define D3DDEVCAPS_EXECUTESYSTEMMEMORY  0x00000010L /* Device can use execute buffers from system memory */
+#define D3DDEVCAPS_EXECUTEVIDEOMEMORY   0x00000020L /* Device can use execute buffers from video memory */
+#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */
+#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY  0x00000080L /* Device can use TL buffers from video memory */
+#define D3DDEVCAPS_TEXTURESYSTEMMEMORY  0x00000100L /* Device can texture from system memory */
+#define D3DDEVCAPS_TEXTUREVIDEOMEMORY   0x00000200L /* Device can texture from device memory */
+#if(DIRECT3D_VERSION >= 0x0500)
+#define D3DDEVCAPS_DRAWPRIMTLVERTEX     0x00000400L /* Device can draw TLVERTEX primitives */
+#define D3DDEVCAPS_CANRENDERAFTERFLIP   0x00000800L /* Device can render without waiting for flip to complete */
+#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+#if(DIRECT3D_VERSION >= 0x0600)
+#define D3DDEVCAPS_DRAWPRIMITIVES2         0x00002000L /* Device can support DrawPrimitives2 */
+#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */
+#define D3DDEVCAPS_DRAWPRIMITIVES2EX       0x00008000L /* Device can support Extended DrawPrimitives2 i.e. DX7 compliant driver*/
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0700)
+#define D3DDEVCAPS_HWTRANSFORMANDLIGHT     0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */
+#define D3DDEVCAPS_CANBLTSYSTONONLOCAL     0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */
+#define D3DDEVCAPS_HWRASTERIZATION         0x00080000L /* Device has HW acceleration for rasterization */
+
+/*
+ * These are the flags in the D3DDEVICEDESC7.dwVertexProcessingCaps field
+ */
+
+/* device can do texgen */
+#define D3DVTXPCAPS_TEXGEN              0x00000001L
+/* device can do IDirect3DDevice7 colormaterialsource ops */
+#define D3DVTXPCAPS_MATERIALSOURCE7     0x00000002L
+/* device can do vertex fog */
+#define D3DVTXPCAPS_VERTEXFOG           0x00000004L
+/* device can do directional lights */
+#define D3DVTXPCAPS_DIRECTIONALLIGHTS   0x00000008L
+/* device can do positional lights (includes point and spot) */
+#define D3DVTXPCAPS_POSITIONALLIGHTS    0x00000010L
+/* device can do local viewer */
+#define D3DVTXPCAPS_LOCALVIEWER         0x00000020L
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#define D3DFDS_COLORMODEL        0x00000001L /* Match color model */
+#define D3DFDS_GUID              0x00000002L /* Match guid */
+#define D3DFDS_HARDWARE          0x00000004L /* Match hardware/software */
+#define D3DFDS_TRIANGLES         0x00000008L /* Match in triCaps */
+#define D3DFDS_LINES             0x00000010L /* Match in lineCaps  */
+#define D3DFDS_MISCCAPS          0x00000020L /* Match primCaps.dwMiscCaps */
+#define D3DFDS_RASTERCAPS        0x00000040L /* Match primCaps.dwRasterCaps */
+#define D3DFDS_ZCMPCAPS          0x00000080L /* Match primCaps.dwZCmpCaps */
+#define D3DFDS_ALPHACMPCAPS      0x00000100L /* Match primCaps.dwAlphaCmpCaps */
+#define D3DFDS_SRCBLENDCAPS      0x00000200L /* Match primCaps.dwSourceBlendCaps */
+#define D3DFDS_DSTBLENDCAPS      0x00000400L /* Match primCaps.dwDestBlendCaps */
+#define D3DFDS_SHADECAPS         0x00000800L /* Match primCaps.dwShadeCaps */
+#define D3DFDS_TEXTURECAPS       0x00001000L /* Match primCaps.dwTextureCaps */
+#define D3DFDS_TEXTUREFILTERCAPS 0x00002000L /* Match primCaps.dwTextureFilterCaps */
+#define D3DFDS_TEXTUREBLENDCAPS  0x00004000L /* Match primCaps.dwTextureBlendCaps */
+#define D3DFDS_TEXTUREADDRESSCAPS  0x00008000L /* Match primCaps.dwTextureBlendCaps */
+
+/*
+ * FindDevice arguments
+ */
+typedef struct _D3DFINDDEVICESEARCH {
+    DWORD               dwSize;
+    DWORD               dwFlags;
+    BOOL                bHardware;
+    D3DCOLORMODEL       dcmColorModel;
+    GUID                guid;
+    DWORD               dwCaps;
+    D3DPRIMCAPS         dpcPrimCaps;
+} D3DFINDDEVICESEARCH, *LPD3DFINDDEVICESEARCH;
+
+typedef struct _D3DFINDDEVICERESULT {
+    DWORD               dwSize;
+    GUID                guid;           /* guid which matched */
+    D3DDEVICEDESC       ddHwDesc;       /* hardware D3DDEVICEDESC */
+    D3DDEVICEDESC       ddSwDesc;       /* software D3DDEVICEDESC */
+} D3DFINDDEVICERESULT, *LPD3DFINDDEVICERESULT;
+
+/*
+ * Description of execute buffer.
+ */
+typedef struct _D3DExecuteBufferDesc {
+    DWORD               dwSize;         /* size of this structure */
+    DWORD               dwFlags;        /* flags indicating which fields are valid */
+    DWORD               dwCaps;         /* capabilities of execute buffer */
+    DWORD               dwBufferSize;   /* size of execute buffer data */
+    LPVOID              lpData;         /* pointer to actual data */
+} D3DEXECUTEBUFFERDESC, *LPD3DEXECUTEBUFFERDESC;
+
+/* D3DEXECUTEBUFFER dwFlags indicating valid fields */
+
+#define D3DDEB_BUFSIZE          0x00000001l     /* buffer size valid */
+#define D3DDEB_CAPS             0x00000002l     /* caps valid */
+#define D3DDEB_LPDATA           0x00000004l     /* lpData valid */
+
+/* D3DEXECUTEBUFFER dwCaps */
+
+#define D3DDEBCAPS_SYSTEMMEMORY 0x00000001l     /* buffer in system memory */
+#define D3DDEBCAPS_VIDEOMEMORY  0x00000002l     /* buffer in device memory */
+#define D3DDEBCAPS_MEM (D3DDEBCAPS_SYSTEMMEMORY|D3DDEBCAPS_VIDEOMEMORY)
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+#if(DIRECT3D_VERSION >= 0x0700)
+typedef struct _D3DDEVINFO_TEXTUREMANAGER {
+    BOOL    bThrashing;                 /* indicates if thrashing */
+    DWORD   dwApproxBytesDownloaded;    /* Approximate number of bytes downloaded by texture manager */
+    DWORD   dwNumEvicts;                /* number of textures evicted */
+    DWORD   dwNumVidCreates;            /* number of textures created in video memory */
+    DWORD   dwNumTexturesUsed;          /* number of textures used */
+    DWORD   dwNumUsedTexInVid;          /* number of used textures present in video memory */
+    DWORD   dwWorkingSet;               /* number of textures in video memory */
+    DWORD   dwWorkingSetBytes;          /* number of bytes in video memory */
+    DWORD   dwTotalManaged;             /* total number of managed textures */
+    DWORD   dwTotalBytes;               /* total number of bytes of managed textures */
+    DWORD   dwLastPri;                  /* priority of last texture evicted */
+} D3DDEVINFO_TEXTUREMANAGER, *LPD3DDEVINFO_TEXTUREMANAGER;
+
+typedef struct _D3DDEVINFO_TEXTURING {
+    DWORD   dwNumLoads;                 /* counts Load() API calls */
+    DWORD   dwApproxBytesLoaded;        /* Approximate number bytes loaded via Load() */
+    DWORD   dwNumPreLoads;              /* counts PreLoad() API calls */
+    DWORD   dwNumSet;                   /* counts SetTexture() API calls */
+    DWORD   dwNumCreates;               /* counts texture creates */
+    DWORD   dwNumDestroys;              /* counts texture destroys */
+    DWORD   dwNumSetPriorities;         /* counts SetPriority() API calls */
+    DWORD   dwNumSetLODs;               /* counts SetLOD() API calls */
+    DWORD   dwNumLocks;                 /* counts number of texture locks */
+    DWORD   dwNumGetDCs;                /* counts number of GetDCs to textures */
+} D3DDEVINFO_TEXTURING, *LPD3DDEVINFO_TEXTURING;
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+#pragma pack()
+
+
+#endif /* _D3DCAPS_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/d3drm.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,342 @@
+/*==========================================================================;
+ *
+ *  Copyright (c) Microsoft Corporation.  All rights reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRM_H__
+#define __D3DRM_H__
+
+#include "ddraw.h"
+
+#ifdef __cplusplus
+struct IDirect3DRM;
+#endif
+
+typedef struct IDirect3DRM *LPDIRECT3DRM;
+
+#include "d3drmobj.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+DEFINE_GUID(IID_IDirect3DRM,    0x2bc49361, 0x8327, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRM2,   0x4516ecc8, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRM3,   0x4516ec83, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3);
+WIN_TYPES(IDirect3DRM, DIRECT3DRM);
+WIN_TYPES(IDirect3DRM2, DIRECT3DRM2);
+WIN_TYPES(IDirect3DRM3, DIRECT3DRM3);
+
+/*
+ * Direct3DRM Object Class (for CoCreateInstance())
+ */
+DEFINE_GUID(CLSID_CDirect3DRM,  0x4516ec41, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3);
+
+
+/* Create a Direct3DRM API */
+STDAPI Direct3DRMCreate(LPDIRECT3DRM FAR *lplpDirect3DRM);
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRM
+
+DECLARE_INTERFACE_(IDirect3DRM, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD(CreateObject)
+        (THIS_ REFCLSID rclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv) PURE;
+    STDMETHOD(CreateFrame)      (THIS_ LPDIRECT3DRMFRAME, LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(CreateMesh)       (THIS_ LPDIRECT3DRMMESH *) PURE;
+    STDMETHOD(CreateMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER *) PURE;
+    STDMETHOD(CreateFace)       (THIS_ LPDIRECT3DRMFACE *) PURE;
+    STDMETHOD(CreateAnimation)  (THIS_ LPDIRECT3DRMANIMATION *) PURE;
+    STDMETHOD(CreateAnimationSet)(THIS_ LPDIRECT3DRMANIMATIONSET *) PURE;
+    STDMETHOD(CreateTexture)    (THIS_ LPD3DRMIMAGE, LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(CreateLight)      (THIS_ D3DRMLIGHTTYPE, D3DCOLOR, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateLightRGB)
+        (THIS_ D3DRMLIGHTTYPE, D3DVALUE, D3DVALUE, D3DVALUE, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateMaterial)   (THIS_ D3DVALUE, LPDIRECT3DRMMATERIAL *) PURE;
+    STDMETHOD(CreateDevice)     (THIS_ DWORD, DWORD, LPDIRECT3DRMDEVICE *) PURE;
+
+    /* Create a Windows Device using DirectDraw surfaces */
+    STDMETHOD(CreateDeviceFromSurface)
+    (   THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD,
+        LPDIRECTDRAWSURFACE lpDDSBack, LPDIRECT3DRMDEVICE *
+    ) PURE;
+
+    /* Create a Windows Device using D3D objects */
+    STDMETHOD(CreateDeviceFromD3D)
+    (   THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev,
+        LPDIRECT3DRMDEVICE *
+    ) PURE;
+
+    STDMETHOD(CreateDeviceFromClipper)
+    (   THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID,
+        int width, int height, LPDIRECT3DRMDEVICE *) PURE;
+
+    STDMETHOD(CreateTextureFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS, LPDIRECT3DRMTEXTURE *) PURE;
+
+    STDMETHOD(CreateShadow)
+    (   THIS_ LPDIRECT3DRMVISUAL, LPDIRECT3DRMLIGHT,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz,
+        LPDIRECT3DRMVISUAL *
+    ) PURE;
+    STDMETHOD(CreateViewport)
+    (   THIS_ LPDIRECT3DRMDEVICE, LPDIRECT3DRMFRAME, DWORD, DWORD,
+        DWORD, DWORD, LPDIRECT3DRMVIEWPORT *
+    ) PURE;
+    STDMETHOD(CreateWrap)
+    (   THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME,
+        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz,
+        D3DVALUE ou, D3DVALUE ov,
+        D3DVALUE su, D3DVALUE sv,
+        LPDIRECT3DRMWRAP *
+    ) PURE;
+    STDMETHOD(CreateUserVisual) (THIS_ D3DRMUSERVISUALCALLBACK, LPVOID lPArg, LPDIRECT3DRMUSERVISUAL *) PURE;
+    STDMETHOD(LoadTexture)      (THIS_ const char *, LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(LoadTextureFromResource)  (THIS_ HRSRC rs, LPDIRECT3DRMTEXTURE *) PURE;
+
+    STDMETHOD(SetSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(AddSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(GetSearchPath)    (THIS_ DWORD *size_return, LPSTR path_return) PURE;
+    STDMETHOD(SetDefaultTextureColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDefaultTextureShades)(THIS_ DWORD) PURE;
+
+    STDMETHOD(GetDevices)       (THIS_ LPDIRECT3DRMDEVICEARRAY *) PURE;
+    STDMETHOD(GetNamedObject)   (THIS_ const char *, LPDIRECT3DRMOBJECT *) PURE;
+
+    STDMETHOD(EnumerateObjects) (THIS_ D3DRMOBJECTCALLBACK, LPVOID) PURE;
+
+    STDMETHOD(Load)
+    (   THIS_ LPVOID, LPVOID, LPIID *, DWORD, D3DRMLOADOPTIONS,
+        D3DRMLOADCALLBACK, LPVOID, D3DRMLOADTEXTURECALLBACK, LPVOID,
+        LPDIRECT3DRMFRAME
+    ) PURE;
+    STDMETHOD(Tick)             (THIS_ D3DVALUE) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRM2
+
+DECLARE_INTERFACE_(IDirect3DRM2, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD(CreateObject)
+        (THIS_ REFCLSID rclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv) PURE;
+    STDMETHOD(CreateFrame)      (THIS_ LPDIRECT3DRMFRAME, LPDIRECT3DRMFRAME2 *) PURE;
+    STDMETHOD(CreateMesh)       (THIS_ LPDIRECT3DRMMESH *) PURE;
+    STDMETHOD(CreateMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER2 *) PURE;
+    STDMETHOD(CreateFace)       (THIS_ LPDIRECT3DRMFACE *) PURE;
+    STDMETHOD(CreateAnimation)  (THIS_ LPDIRECT3DRMANIMATION *) PURE;
+    STDMETHOD(CreateAnimationSet)(THIS_ LPDIRECT3DRMANIMATIONSET *) PURE;
+    STDMETHOD(CreateTexture)    (THIS_ LPD3DRMIMAGE, LPDIRECT3DRMTEXTURE2 *) PURE;
+    STDMETHOD(CreateLight)      (THIS_ D3DRMLIGHTTYPE, D3DCOLOR, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateLightRGB)
+        (THIS_ D3DRMLIGHTTYPE, D3DVALUE, D3DVALUE, D3DVALUE, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateMaterial)   (THIS_ D3DVALUE, LPDIRECT3DRMMATERIAL *) PURE;
+    STDMETHOD(CreateDevice)     (THIS_ DWORD, DWORD, LPDIRECT3DRMDEVICE2 *) PURE;
+
+    /* Create a Windows Device using DirectDraw surfaces */
+    STDMETHOD(CreateDeviceFromSurface)
+    (   THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD,
+        LPDIRECTDRAWSURFACE lpDDSBack, LPDIRECT3DRMDEVICE2 *
+    ) PURE;
+
+    /* Create a Windows Device using D3D objects */
+    STDMETHOD(CreateDeviceFromD3D)
+    (   THIS_ LPDIRECT3D2 lpD3D, LPDIRECT3DDEVICE2 lpD3DDev,
+        LPDIRECT3DRMDEVICE2 *
+    ) PURE;
+
+    STDMETHOD(CreateDeviceFromClipper)
+    (   THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID,
+        int width, int height, LPDIRECT3DRMDEVICE2 *) PURE;
+
+    STDMETHOD(CreateTextureFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS, LPDIRECT3DRMTEXTURE2 *) PURE;
+
+    STDMETHOD(CreateShadow)
+    (   THIS_ LPDIRECT3DRMVISUAL, LPDIRECT3DRMLIGHT,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz,
+        LPDIRECT3DRMVISUAL *
+    ) PURE;
+    STDMETHOD(CreateViewport)
+    (   THIS_ LPDIRECT3DRMDEVICE, LPDIRECT3DRMFRAME, DWORD, DWORD,
+        DWORD, DWORD, LPDIRECT3DRMVIEWPORT *
+    ) PURE;
+    STDMETHOD(CreateWrap)
+    (   THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME,
+        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz,
+        D3DVALUE ou, D3DVALUE ov,
+        D3DVALUE su, D3DVALUE sv,
+        LPDIRECT3DRMWRAP *
+    ) PURE;
+    STDMETHOD(CreateUserVisual) (THIS_ D3DRMUSERVISUALCALLBACK, LPVOID lPArg, LPDIRECT3DRMUSERVISUAL *) PURE;
+    STDMETHOD(LoadTexture)      (THIS_ const char *, LPDIRECT3DRMTEXTURE2 *) PURE;
+    STDMETHOD(LoadTextureFromResource)  (THIS_ HMODULE hModule, LPCTSTR strName, LPCTSTR strType, LPDIRECT3DRMTEXTURE2 *) PURE;
+
+    STDMETHOD(SetSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(AddSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(GetSearchPath)    (THIS_ DWORD *size_return, LPSTR path_return) PURE;
+    STDMETHOD(SetDefaultTextureColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDefaultTextureShades)(THIS_ DWORD) PURE;
+
+    STDMETHOD(GetDevices)       (THIS_ LPDIRECT3DRMDEVICEARRAY *) PURE;
+    STDMETHOD(GetNamedObject)   (THIS_ const char *, LPDIRECT3DRMOBJECT *) PURE;
+
+    STDMETHOD(EnumerateObjects) (THIS_ D3DRMOBJECTCALLBACK, LPVOID) PURE;
+
+    STDMETHOD(Load)
+    (   THIS_ LPVOID, LPVOID, LPIID *, DWORD, D3DRMLOADOPTIONS,
+        D3DRMLOADCALLBACK, LPVOID, D3DRMLOADTEXTURECALLBACK, LPVOID,
+        LPDIRECT3DRMFRAME
+    ) PURE;
+    STDMETHOD(Tick)             (THIS_ D3DVALUE) PURE;
+
+    STDMETHOD(CreateProgressiveMesh)(THIS_ LPDIRECT3DRMPROGRESSIVEMESH *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRM3
+
+DECLARE_INTERFACE_(IDirect3DRM3, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD(CreateObject)
+        (THIS_ REFCLSID rclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv) PURE;
+    STDMETHOD(CreateFrame)      (THIS_ LPDIRECT3DRMFRAME3, LPDIRECT3DRMFRAME3 *) PURE;
+    STDMETHOD(CreateMesh)       (THIS_ LPDIRECT3DRMMESH *) PURE;
+    STDMETHOD(CreateMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER3 *) PURE;
+    STDMETHOD(CreateFace)       (THIS_ LPDIRECT3DRMFACE2 *) PURE;
+    STDMETHOD(CreateAnimation)  (THIS_ LPDIRECT3DRMANIMATION2 *) PURE;
+    STDMETHOD(CreateAnimationSet)(THIS_ LPDIRECT3DRMANIMATIONSET2 *) PURE;
+    STDMETHOD(CreateTexture)    (THIS_ LPD3DRMIMAGE, LPDIRECT3DRMTEXTURE3 *) PURE;
+    STDMETHOD(CreateLight)      (THIS_ D3DRMLIGHTTYPE, D3DCOLOR, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateLightRGB)
+        (THIS_ D3DRMLIGHTTYPE, D3DVALUE, D3DVALUE, D3DVALUE, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateMaterial)   (THIS_ D3DVALUE, LPDIRECT3DRMMATERIAL2 *) PURE;
+    STDMETHOD(CreateDevice)     (THIS_ DWORD, DWORD, LPDIRECT3DRMDEVICE3 *) PURE;
+
+    /* Create a Windows Device using DirectDraw surfaces */
+    STDMETHOD(CreateDeviceFromSurface)
+    (   THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD,
+        LPDIRECTDRAWSURFACE lpDDSBack, DWORD dwFlags, LPDIRECT3DRMDEVICE3 *
+    ) PURE;
+
+    /* Create a Windows Device using D3D objects */
+    STDMETHOD(CreateDeviceFromD3D)
+    (   THIS_ LPDIRECT3D2 lpD3D, LPDIRECT3DDEVICE2 lpD3DDev,
+        LPDIRECT3DRMDEVICE3 *
+    ) PURE;
+
+    STDMETHOD(CreateDeviceFromClipper)
+    (   THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID,
+        int width, int height, LPDIRECT3DRMDEVICE3 *) PURE;
+
+    STDMETHOD(CreateTextureFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS, LPDIRECT3DRMTEXTURE3 *) PURE;
+
+    STDMETHOD(CreateShadow)
+    (   THIS_ LPUNKNOWN, LPDIRECT3DRMLIGHT,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz,
+        LPDIRECT3DRMSHADOW2 *
+    ) PURE;
+    STDMETHOD(CreateViewport)
+    (   THIS_ LPDIRECT3DRMDEVICE3, LPDIRECT3DRMFRAME3, DWORD, DWORD,
+        DWORD, DWORD, LPDIRECT3DRMVIEWPORT2 *
+    ) PURE;
+    STDMETHOD(CreateWrap)
+    (   THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME3,
+        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz,
+        D3DVALUE ou, D3DVALUE ov,
+        D3DVALUE su, D3DVALUE sv,
+        LPDIRECT3DRMWRAP *
+    ) PURE;
+    STDMETHOD(CreateUserVisual) (THIS_ D3DRMUSERVISUALCALLBACK, LPVOID lPArg, LPDIRECT3DRMUSERVISUAL *) PURE;
+    STDMETHOD(LoadTexture)      (THIS_ const char *, LPDIRECT3DRMTEXTURE3 *) PURE;
+    STDMETHOD(LoadTextureFromResource)  (THIS_ HMODULE hModule, LPCTSTR strName, LPCTSTR strType, LPDIRECT3DRMTEXTURE3 *) PURE;
+
+    STDMETHOD(SetSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(AddSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(GetSearchPath)    (THIS_ DWORD *size_return, LPSTR path_return) PURE;
+    STDMETHOD(SetDefaultTextureColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDefaultTextureShades)(THIS_ DWORD) PURE;
+
+    STDMETHOD(GetDevices)       (THIS_ LPDIRECT3DRMDEVICEARRAY *) PURE;
+    STDMETHOD(GetNamedObject)   (THIS_ const char *, LPDIRECT3DRMOBJECT *) PURE;
+
+    STDMETHOD(EnumerateObjects) (THIS_ D3DRMOBJECTCALLBACK, LPVOID) PURE;
+
+    STDMETHOD(Load)
+    (   THIS_ LPVOID, LPVOID, LPIID *, DWORD, D3DRMLOADOPTIONS,
+        D3DRMLOADCALLBACK, LPVOID, D3DRMLOADTEXTURE3CALLBACK, LPVOID,
+        LPDIRECT3DRMFRAME3
+    ) PURE;
+    STDMETHOD(Tick)             (THIS_ D3DVALUE) PURE;
+
+    STDMETHOD(CreateProgressiveMesh)(THIS_ LPDIRECT3DRMPROGRESSIVEMESH *) PURE;
+
+    /* Used with IDirect3DRMObject2 */
+    STDMETHOD(RegisterClient)   (THIS_ REFGUID rguid, LPDWORD lpdwID) PURE;
+    STDMETHOD(UnregisterClient) (THIS_ REFGUID rguid) PURE;
+
+    STDMETHOD(CreateClippedVisual) (THIS_ LPDIRECT3DRMVISUAL, LPDIRECT3DRMCLIPPEDVISUAL *) PURE;
+    STDMETHOD(SetOptions) (THIS_ DWORD);
+    STDMETHOD(GetOptions) (THIS_ LPDWORD);
+};
+
+#define D3DRM_OK                        DD_OK
+#define D3DRMERR_BADOBJECT              MAKE_DDHRESULT(781)
+#define D3DRMERR_BADTYPE                MAKE_DDHRESULT(782)
+#define D3DRMERR_BADALLOC               MAKE_DDHRESULT(783)
+#define D3DRMERR_FACEUSED               MAKE_DDHRESULT(784)
+#define D3DRMERR_NOTFOUND               MAKE_DDHRESULT(785)
+#define D3DRMERR_NOTDONEYET             MAKE_DDHRESULT(786)
+#define D3DRMERR_FILENOTFOUND           MAKE_DDHRESULT(787)
+#define D3DRMERR_BADFILE                MAKE_DDHRESULT(788)
+#define D3DRMERR_BADDEVICE              MAKE_DDHRESULT(789)
+#define D3DRMERR_BADVALUE               MAKE_DDHRESULT(790)
+#define D3DRMERR_BADMAJORVERSION        MAKE_DDHRESULT(791)
+#define D3DRMERR_BADMINORVERSION        MAKE_DDHRESULT(792)
+#define D3DRMERR_UNABLETOEXECUTE        MAKE_DDHRESULT(793)
+#define D3DRMERR_LIBRARYNOTFOUND        MAKE_DDHRESULT(794)
+#define D3DRMERR_INVALIDLIBRARY         MAKE_DDHRESULT(795)
+#define D3DRMERR_PENDING                MAKE_DDHRESULT(796)
+#define D3DRMERR_NOTENOUGHDATA          MAKE_DDHRESULT(797)
+#define D3DRMERR_REQUESTTOOLARGE        MAKE_DDHRESULT(798)
+#define D3DRMERR_REQUESTTOOSMALL        MAKE_DDHRESULT(799)
+#define D3DRMERR_CONNECTIONLOST         MAKE_DDHRESULT(800)
+#define D3DRMERR_LOADABORTED            MAKE_DDHRESULT(801)
+#define D3DRMERR_NOINTERNET             MAKE_DDHRESULT(802)
+#define D3DRMERR_BADCACHEFILE           MAKE_DDHRESULT(803)
+#define D3DRMERR_BOXNOTSET              MAKE_DDHRESULT(804)
+#define D3DRMERR_BADPMDATA              MAKE_DDHRESULT(805)
+#define D3DRMERR_CLIENTNOTREGISTERED    MAKE_DDHRESULT(806)
+#define D3DRMERR_NOTCREATEDFROMDDS      MAKE_DDHRESULT(807)
+#define D3DRMERR_NOSUCHKEY              MAKE_DDHRESULT(808)
+#define D3DRMERR_INCOMPATABLEKEY        MAKE_DDHRESULT(809)
+#define D3DRMERR_ELEMENTINUSE           MAKE_DDHRESULT(810)
+#define D3DRMERR_TEXTUREFORMATNOTFOUND  MAKE_DDHRESULT(811)
+#define D3DRMERR_NOTAGGREGATED          MAKE_DDHRESULT(812)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _D3DRMAPI_H_ */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/d3drmdef.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,695 @@
+/*==========================================================================;
+ *
+ *  Copyright (c) Microsoft Corporation.  All rights reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRMDEFS_H__
+#define __D3DRMDEFS_H__
+
+#include <stddef.h>
+#include "d3dtypes.h"
+
+#ifdef WIN32
+#define D3DRMAPI  __stdcall
+#else
+#define D3DRMAPI
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef TRUE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+typedef struct _D3DRMVECTOR4D
+{   D3DVALUE x, y, z, w;
+} D3DRMVECTOR4D, *LPD3DRMVECTOR4D;
+
+typedef D3DVALUE D3DRMMATRIX4D[4][4];
+
+typedef struct _D3DRMQUATERNION
+{   D3DVALUE s;
+    D3DVECTOR v;
+} D3DRMQUATERNION, *LPD3DRMQUATERNION;
+
+typedef struct _D3DRMRAY
+{   D3DVECTOR dvDir;
+    D3DVECTOR dvPos;
+} D3DRMRAY, *LPD3DRMRAY;
+
+typedef struct _D3DRMBOX
+{   D3DVECTOR min, max;
+} D3DRMBOX, *LPD3DRMBOX;
+
+typedef void (*D3DRMWRAPCALLBACK)
+    (LPD3DVECTOR, int* u, int* v, LPD3DVECTOR a, LPD3DVECTOR b, LPVOID);
+
+typedef enum _D3DRMLIGHTTYPE
+{   D3DRMLIGHT_AMBIENT,
+    D3DRMLIGHT_POINT,
+    D3DRMLIGHT_SPOT,
+    D3DRMLIGHT_DIRECTIONAL,
+    D3DRMLIGHT_PARALLELPOINT
+} D3DRMLIGHTTYPE, *LPD3DRMLIGHTTYPE;
+
+typedef enum _D3DRMSHADEMODE {
+    D3DRMSHADE_FLAT     = 0,
+    D3DRMSHADE_GOURAUD  = 1,
+    D3DRMSHADE_PHONG    = 2,
+
+    D3DRMSHADE_MASK     = 7,
+    D3DRMSHADE_MAX      = 8
+} D3DRMSHADEMODE, *LPD3DRMSHADEMODE;
+
+typedef enum _D3DRMLIGHTMODE {
+    D3DRMLIGHT_OFF      = 0 * D3DRMSHADE_MAX,
+    D3DRMLIGHT_ON       = 1 * D3DRMSHADE_MAX,
+
+    D3DRMLIGHT_MASK     = 7 * D3DRMSHADE_MAX,
+    D3DRMLIGHT_MAX      = 8 * D3DRMSHADE_MAX
+} D3DRMLIGHTMODE, *LPD3DRMLIGHTMODE;
+
+typedef enum _D3DRMFILLMODE {
+    D3DRMFILL_POINTS    = 0 * D3DRMLIGHT_MAX,
+    D3DRMFILL_WIREFRAME = 1 * D3DRMLIGHT_MAX,
+    D3DRMFILL_SOLID     = 2 * D3DRMLIGHT_MAX,
+
+    D3DRMFILL_MASK      = 7 * D3DRMLIGHT_MAX,
+    D3DRMFILL_MAX       = 8 * D3DRMLIGHT_MAX
+} D3DRMFILLMODE, *LPD3DRMFILLMODE;
+
+typedef DWORD D3DRMRENDERQUALITY, *LPD3DRMRENDERQUALITY;
+
+#define D3DRMRENDER_WIREFRAME   (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_WIREFRAME)
+#define D3DRMRENDER_UNLITFLAT   (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_SOLID)
+#define D3DRMRENDER_FLAT        (D3DRMSHADE_FLAT+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+#define D3DRMRENDER_GOURAUD     (D3DRMSHADE_GOURAUD+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+#define D3DRMRENDER_PHONG       (D3DRMSHADE_PHONG+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+
+#define D3DRMRENDERMODE_BLENDEDTRANSPARENCY     1
+#define D3DRMRENDERMODE_SORTEDTRANSPARENCY      2
+#define D3DRMRENDERMODE_LIGHTINMODELSPACE       8
+#define D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR   16
+#define D3DRMRENDERMODE_DISABLESORTEDALPHAZWRITE 32
+
+typedef enum _D3DRMTEXTUREQUALITY
+{   D3DRMTEXTURE_NEAREST,               /* choose nearest texel */
+    D3DRMTEXTURE_LINEAR,                /* interpolate 4 texels */
+    D3DRMTEXTURE_MIPNEAREST,            /* nearest texel in nearest mipmap  */
+    D3DRMTEXTURE_MIPLINEAR,             /* interpolate 2 texels from 2 mipmaps */
+    D3DRMTEXTURE_LINEARMIPNEAREST,      /* interpolate 4 texels in nearest mipmap */
+    D3DRMTEXTURE_LINEARMIPLINEAR        /* interpolate 8 texels from 2 mipmaps */
+} D3DRMTEXTUREQUALITY, *LPD3DRMTEXTUREQUALITY;
+
+/*
+ * Texture flags
+ */
+#define D3DRMTEXTURE_FORCERESIDENT          0x00000001 /* texture should be kept in video memory */
+#define D3DRMTEXTURE_STATIC                 0x00000002 /* texture will not change */
+#define D3DRMTEXTURE_DOWNSAMPLEPOINT        0x00000004 /* point filtering should be used when downsampling */
+#define D3DRMTEXTURE_DOWNSAMPLEBILINEAR     0x00000008 /* bilinear filtering should be used when downsampling */
+#define D3DRMTEXTURE_DOWNSAMPLEREDUCEDEPTH  0x00000010 /* reduce bit depth when downsampling */
+#define D3DRMTEXTURE_DOWNSAMPLENONE         0x00000020 /* texture should never be downsampled */
+#define D3DRMTEXTURE_CHANGEDPIXELS          0x00000040 /* pixels have changed */
+#define D3DRMTEXTURE_CHANGEDPALETTE         0x00000080 /* palette has changed */
+#define D3DRMTEXTURE_INVALIDATEONLY         0x00000100 /* dirty regions are invalid */
+
+/*
+ * Shadow flags
+ */
+#define D3DRMSHADOW_TRUEALPHA               0x00000001 /* shadow should render without artifacts when true alpha is on */
+
+typedef enum _D3DRMCOMBINETYPE
+{   D3DRMCOMBINE_REPLACE,
+    D3DRMCOMBINE_BEFORE,
+    D3DRMCOMBINE_AFTER
+} D3DRMCOMBINETYPE, *LPD3DRMCOMBINETYPE;
+
+typedef D3DCOLORMODEL D3DRMCOLORMODEL, *LPD3DRMCOLORMODEL;
+
+typedef enum _D3DRMPALETTEFLAGS
+{   D3DRMPALETTE_FREE,                  /* renderer may use this entry freely */
+    D3DRMPALETTE_READONLY,              /* fixed but may be used by renderer */
+    D3DRMPALETTE_RESERVED               /* may not be used by renderer */
+} D3DRMPALETTEFLAGS, *LPD3DRMPALETTEFLAGS;
+
+typedef struct _D3DRMPALETTEENTRY
+{   unsigned char red;          /* 0 .. 255 */
+    unsigned char green;        /* 0 .. 255 */
+    unsigned char blue;         /* 0 .. 255 */
+    unsigned char flags;        /* one of D3DRMPALETTEFLAGS */
+} D3DRMPALETTEENTRY, *LPD3DRMPALETTEENTRY;
+
+typedef struct _D3DRMIMAGE
+{   int width, height;          /* width and height in pixels */
+    int aspectx, aspecty;       /* aspect ratio for non-square pixels */
+    int depth;                  /* bits per pixel */
+    int rgb;                    /* if false, pixels are indices into a
+                                   palette otherwise, pixels encode
+                                   RGB values. */
+    int bytes_per_line;         /* number of bytes of memory for a
+                                   scanline. This must be a multiple
+                                   of 4. */
+    void* buffer1;              /* memory to render into (first buffer). */
+    void* buffer2;              /* second rendering buffer for double
+                                   buffering, set to NULL for single
+                                   buffering. */
+    unsigned long red_mask;
+    unsigned long green_mask;
+    unsigned long blue_mask;
+    unsigned long alpha_mask;   /* if rgb is true, these are masks for
+                                   the red, green and blue parts of a
+                                   pixel.  Otherwise, these are masks
+                                   for the significant bits of the
+                                   red, green and blue elements in the
+                                   palette.  For instance, most SVGA
+                                   displays use 64 intensities of red,
+                                   green and blue, so the masks should
+                                   all be set to 0xfc. */
+    int palette_size;           /* number of entries in palette */
+    D3DRMPALETTEENTRY* palette; /* description of the palette (only if
+                                   rgb is false).  Must be (1<<depth)
+                                   elements. */
+} D3DRMIMAGE, *LPD3DRMIMAGE;
+
+typedef enum _D3DRMWRAPTYPE
+{   D3DRMWRAP_FLAT,
+    D3DRMWRAP_CYLINDER,
+    D3DRMWRAP_SPHERE,
+    D3DRMWRAP_CHROME,
+    D3DRMWRAP_SHEET,
+    D3DRMWRAP_BOX
+} D3DRMWRAPTYPE, *LPD3DRMWRAPTYPE;
+
+#define D3DRMWIREFRAME_CULL             1 /* cull backfaces */
+#define D3DRMWIREFRAME_HIDDENLINE       2 /* lines are obscured by closer objects */
+
+/*
+ * Do not use righthanded perspective in Viewport2::SetProjection().
+ * Set up righthanded mode by using IDirect3DRM3::SetOptions().
+ */
+typedef enum _D3DRMPROJECTIONTYPE
+{   D3DRMPROJECT_PERSPECTIVE,
+    D3DRMPROJECT_ORTHOGRAPHIC,
+    D3DRMPROJECT_RIGHTHANDPERSPECTIVE, /* Only valid pre-DX6 */
+    D3DRMPROJECT_RIGHTHANDORTHOGRAPHIC /* Only valid pre-DX6 */
+} D3DRMPROJECTIONTYPE, *LPD3DRMPROJECTIONTYPE;
+
+#define D3DRMOPTIONS_LEFTHANDED  0x00000001L /* Default */
+#define D3DRMOPTIONS_RIGHTHANDED 0x00000002L
+
+typedef enum _D3DRMXOFFORMAT
+{   D3DRMXOF_BINARY,
+    D3DRMXOF_COMPRESSED,
+    D3DRMXOF_TEXT
+} D3DRMXOFFORMAT, *LPD3DRMXOFFORMAT;
+
+typedef DWORD D3DRMSAVEOPTIONS;
+#define D3DRMXOFSAVE_NORMALS 1
+#define D3DRMXOFSAVE_TEXTURECOORDINATES 2
+#define D3DRMXOFSAVE_MATERIALS 4
+#define D3DRMXOFSAVE_TEXTURENAMES 8
+#define D3DRMXOFSAVE_ALL 15
+#define D3DRMXOFSAVE_TEMPLATES 16
+#define D3DRMXOFSAVE_TEXTURETOPOLOGY 32
+
+typedef enum _D3DRMCOLORSOURCE
+{   D3DRMCOLOR_FROMFACE,
+    D3DRMCOLOR_FROMVERTEX
+} D3DRMCOLORSOURCE, *LPD3DRMCOLORSOURCE;
+
+typedef enum _D3DRMFRAMECONSTRAINT
+{   D3DRMCONSTRAIN_Z,           /* use only X and Y rotations */
+    D3DRMCONSTRAIN_Y,           /* use only X and Z rotations */
+    D3DRMCONSTRAIN_X            /* use only Y and Z rotations */
+} D3DRMFRAMECONSTRAINT, *LPD3DRMFRAMECONSTRAINT;
+
+typedef enum _D3DRMMATERIALMODE
+{   D3DRMMATERIAL_FROMMESH,
+    D3DRMMATERIAL_FROMPARENT,
+    D3DRMMATERIAL_FROMFRAME
+} D3DRMMATERIALMODE, *LPD3DRMMATERIALMODE;
+
+typedef enum _D3DRMFOGMODE
+{   D3DRMFOG_LINEAR,            /* linear between start and end */
+    D3DRMFOG_EXPONENTIAL,       /* density * exp(-distance) */
+    D3DRMFOG_EXPONENTIALSQUARED /* density * exp(-distance*distance) */
+} D3DRMFOGMODE, *LPD3DRMFOGMODE;
+
+typedef enum _D3DRMZBUFFERMODE {
+    D3DRMZBUFFER_FROMPARENT,    /* default */
+    D3DRMZBUFFER_ENABLE,        /* enable zbuffering */
+    D3DRMZBUFFER_DISABLE        /* disable zbuffering */
+} D3DRMZBUFFERMODE, *LPD3DRMZBUFFERMODE;
+
+typedef enum _D3DRMSORTMODE {
+    D3DRMSORT_FROMPARENT,       /* default */
+    D3DRMSORT_NONE,             /* don't sort child frames */
+    D3DRMSORT_FRONTTOBACK,      /* sort child frames front-to-back */
+    D3DRMSORT_BACKTOFRONT       /* sort child frames back-to-front */
+} D3DRMSORTMODE, *LPD3DRMSORTMODE;
+
+typedef struct _D3DRMMATERIALOVERRIDE
+{
+    DWORD         dwSize;       /* Size of this structure */
+    DWORD         dwFlags;      /* Indicate which fields are valid */
+    D3DCOLORVALUE dcDiffuse;    /* RGBA */
+    D3DCOLORVALUE dcAmbient;    /* RGB */
+    D3DCOLORVALUE dcEmissive;   /* RGB */
+    D3DCOLORVALUE dcSpecular;   /* RGB */
+    D3DVALUE      dvPower;
+    LPUNKNOWN     lpD3DRMTex;
+} D3DRMMATERIALOVERRIDE, *LPD3DRMMATERIALOVERRIDE;
+
+#define D3DRMMATERIALOVERRIDE_DIFFUSE_ALPHAONLY     0x00000001L
+#define D3DRMMATERIALOVERRIDE_DIFFUSE_RGBONLY       0x00000002L
+#define D3DRMMATERIALOVERRIDE_DIFFUSE               0x00000003L
+#define D3DRMMATERIALOVERRIDE_AMBIENT               0x00000004L
+#define D3DRMMATERIALOVERRIDE_EMISSIVE              0x00000008L
+#define D3DRMMATERIALOVERRIDE_SPECULAR              0x00000010L
+#define D3DRMMATERIALOVERRIDE_POWER                 0x00000020L
+#define D3DRMMATERIALOVERRIDE_TEXTURE               0x00000040L
+#define D3DRMMATERIALOVERRIDE_DIFFUSE_ALPHAMULTIPLY 0x00000080L
+#define D3DRMMATERIALOVERRIDE_ALL                   0x000000FFL
+
+#define D3DRMFPTF_ALPHA                           0x00000001L
+#define D3DRMFPTF_NOALPHA                         0x00000002L
+#define D3DRMFPTF_PALETTIZED                      0x00000004L
+#define D3DRMFPTF_NOTPALETTIZED                   0x00000008L
+
+#define D3DRMSTATECHANGE_UPDATEONLY               0x000000001L
+#define D3DRMSTATECHANGE_VOLATILE                 0x000000002L
+#define D3DRMSTATECHANGE_NONVOLATILE              0x000000004L
+#define D3DRMSTATECHANGE_RENDER                   0x000000020L
+#define D3DRMSTATECHANGE_LIGHT                    0x000000040L
+
+/*
+ * Values for flags in RM3::CreateDeviceFromSurface
+ */
+#define D3DRMDEVICE_NOZBUFFER           0x00000001L
+
+/*
+ * Values for flags in Object2::SetClientData
+ */
+#define D3DRMCLIENTDATA_NONE            0x00000001L
+#define D3DRMCLIENTDATA_LOCALFREE       0x00000002L
+#define D3DRMCLIENTDATA_IUNKNOWN        0x00000004L
+
+/*
+ * Values for flags in Frame2::AddMoveCallback.
+ */
+#define D3DRMCALLBACK_PREORDER          0
+#define D3DRMCALLBACK_POSTORDER         1
+
+/*
+ * Values for flags in MeshBuilder2::RayPick.
+ */
+#define D3DRMRAYPICK_ONLYBOUNDINGBOXES          1
+#define D3DRMRAYPICK_IGNOREFURTHERPRIMITIVES    2
+#define D3DRMRAYPICK_INTERPOLATEUV              4
+#define D3DRMRAYPICK_INTERPOLATECOLOR           8
+#define D3DRMRAYPICK_INTERPOLATENORMAL          0x10
+
+/*
+ * Values for flags in MeshBuilder3::AddFacesIndexed.
+ */
+#define D3DRMADDFACES_VERTICESONLY              1
+
+/*
+ * Values for flags in MeshBuilder2::GenerateNormals.
+ */
+#define D3DRMGENERATENORMALS_PRECOMPACT         1
+#define D3DRMGENERATENORMALS_USECREASEANGLE     2
+
+/*
+ * Values for MeshBuilder3::GetParentMesh
+ */
+#define D3DRMMESHBUILDER_DIRECTPARENT           1
+#define D3DRMMESHBUILDER_ROOTMESH               2
+
+/*
+ * Flags for MeshBuilder3::Enable
+ */
+#define D3DRMMESHBUILDER_RENDERENABLE   0x00000001L
+#define D3DRMMESHBUILDER_PICKENABLE     0x00000002L
+
+/*
+ * Flags for MeshBuilder3::AddMeshBuilder
+ */
+#define D3DRMADDMESHBUILDER_DONTCOPYAPPDATA     1
+#define D3DRMADDMESHBUILDER_FLATTENSUBMESHES    2
+#define D3DRMADDMESHBUILDER_NOSUBMESHES         4
+
+/*
+ * Flags for Object2::GetAge when used with MeshBuilders
+ */
+#define D3DRMMESHBUILDERAGE_GEOMETRY    0x00000001L
+#define D3DRMMESHBUILDERAGE_MATERIALS   0x00000002L
+#define D3DRMMESHBUILDERAGE_TEXTURES    0x00000004L
+
+/*
+ * Format flags for MeshBuilder3::AddTriangles.
+ */
+#define D3DRMFVF_TYPE                   0x00000001L
+#define D3DRMFVF_NORMAL                 0x00000002L
+#define D3DRMFVF_COLOR                  0x00000004L
+#define D3DRMFVF_TEXTURECOORDS          0x00000008L
+
+#define D3DRMVERTEX_STRIP               0x00000001L
+#define D3DRMVERTEX_FAN                 0x00000002L
+#define D3DRMVERTEX_LIST                0x00000004L
+
+/*
+ * Values for flags in Viewport2::Clear2
+ */
+#define D3DRMCLEAR_TARGET               0x00000001L
+#define D3DRMCLEAR_ZBUFFER              0x00000002L
+#define D3DRMCLEAR_DIRTYRECTS           0x00000004L
+#define D3DRMCLEAR_ALL                  (D3DRMCLEAR_TARGET | \
+                                         D3DRMCLEAR_ZBUFFER | \
+                                         D3DRMCLEAR_DIRTYRECTS)
+
+/*
+ * Values for flags in Frame3::SetSceneFogMethod
+ */
+#define D3DRMFOGMETHOD_VERTEX          0x00000001L
+#define D3DRMFOGMETHOD_TABLE           0x00000002L
+#define D3DRMFOGMETHOD_ANY             0x00000004L
+
+/*
+ * Values for flags in Frame3::SetTraversalOptions
+ */
+#define D3DRMFRAME_RENDERENABLE        0x00000001L
+#define D3DRMFRAME_PICKENABLE          0x00000002L
+
+typedef DWORD D3DRMANIMATIONOPTIONS;
+#define D3DRMANIMATION_OPEN 0x01L
+#define D3DRMANIMATION_CLOSED 0x02L
+#define D3DRMANIMATION_LINEARPOSITION 0x04L
+#define D3DRMANIMATION_SPLINEPOSITION 0x08L
+#define D3DRMANIMATION_SCALEANDROTATION 0x00000010L
+#define D3DRMANIMATION_POSITION 0x00000020L
+
+typedef DWORD D3DRMINTERPOLATIONOPTIONS;
+#define D3DRMINTERPOLATION_OPEN 0x01L
+#define D3DRMINTERPOLATION_CLOSED 0x02L
+#define D3DRMINTERPOLATION_NEAREST 0x0100L
+#define D3DRMINTERPOLATION_LINEAR 0x04L
+#define D3DRMINTERPOLATION_SPLINE 0x08L
+#define D3DRMINTERPOLATION_VERTEXCOLOR 0x40L
+#define D3DRMINTERPOLATION_SLERPNORMALS 0x80L
+
+typedef DWORD D3DRMLOADOPTIONS;
+
+#define D3DRMLOAD_FROMFILE  0x00L
+#define D3DRMLOAD_FROMRESOURCE 0x01L
+#define D3DRMLOAD_FROMMEMORY 0x02L
+#define D3DRMLOAD_FROMSTREAM 0x04L
+#define D3DRMLOAD_FROMURL 0x08L
+
+#define D3DRMLOAD_BYNAME 0x10L
+#define D3DRMLOAD_BYPOSITION 0x20L
+#define D3DRMLOAD_BYGUID 0x40L
+#define D3DRMLOAD_FIRST 0x80L
+
+#define D3DRMLOAD_INSTANCEBYREFERENCE 0x100L
+#define D3DRMLOAD_INSTANCEBYCOPYING 0x200L
+
+#define D3DRMLOAD_ASYNCHRONOUS 0x400L
+
+typedef struct _D3DRMLOADRESOURCE {
+  HMODULE hModule;
+  LPCTSTR lpName;
+  LPCTSTR lpType;
+} D3DRMLOADRESOURCE, *LPD3DRMLOADRESOURCE;
+
+typedef struct _D3DRMLOADMEMORY {
+  LPVOID lpMemory;
+  DWORD dSize;
+} D3DRMLOADMEMORY, *LPD3DRMLOADMEMORY;
+
+#define D3DRMPMESHSTATUS_VALID 0x01L
+#define D3DRMPMESHSTATUS_INTERRUPTED 0x02L
+#define D3DRMPMESHSTATUS_BASEMESHCOMPLETE 0x04L
+#define D3DRMPMESHSTATUS_COMPLETE 0x08L
+#define D3DRMPMESHSTATUS_RENDERABLE 0x10L
+
+#define D3DRMPMESHEVENT_BASEMESH 0x01L
+#define D3DRMPMESHEVENT_COMPLETE 0x02L
+
+typedef struct _D3DRMPMESHLOADSTATUS {
+  DWORD dwSize;            // Size of this structure
+  DWORD dwPMeshSize;       // Total Size (bytes)
+  DWORD dwBaseMeshSize;    // Total Size of the Base Mesh
+  DWORD dwBytesLoaded;     // Total bytes loaded
+  DWORD dwVerticesLoaded;  // Number of vertices loaded
+  DWORD dwFacesLoaded;     // Number of faces loaded
+  HRESULT dwLoadResult;    // Result of the load operation
+  DWORD dwFlags;
+} D3DRMPMESHLOADSTATUS, *LPD3DRMPMESHLOADSTATUS;
+
+typedef enum _D3DRMUSERVISUALREASON {
+    D3DRMUSERVISUAL_CANSEE,
+    D3DRMUSERVISUAL_RENDER
+} D3DRMUSERVISUALREASON, *LPD3DRMUSERVISUALREASON;
+
+
+typedef struct _D3DRMANIMATIONKEY
+{
+    DWORD dwSize;
+    DWORD dwKeyType;
+    D3DVALUE dvTime;
+    DWORD dwID;
+#if (!defined __cplusplus) || (!defined D3D_OVERLOADS)
+    union
+    {
+        D3DRMQUATERNION dqRotateKey;
+        D3DVECTOR dvScaleKey;
+        D3DVECTOR dvPositionKey;
+    };
+#else
+    /*
+     * We do this as D3D_OVERLOADS defines constructors for D3DVECTOR,
+     * this can then not be used in a union.  Use the inlines provided
+     * to extract and set the required component.
+     */
+    D3DVALUE dvK[4];
+#endif
+} D3DRMANIMATIONKEY;
+typedef D3DRMANIMATIONKEY *LPD3DRMANIMATIONKEY;
+
+#if (defined __cplusplus) && (defined D3D_OVERLOADS)
+inline VOID
+D3DRMAnimationGetRotateKey(const D3DRMANIMATIONKEY& rmKey,
+                           D3DRMQUATERNION& rmQuat)
+{
+    rmQuat.s = rmKey.dvK[0];
+    rmQuat.v = D3DVECTOR(rmKey.dvK[1], rmKey.dvK[2], rmKey.dvK[3]);
+}
+
+inline VOID
+D3DRMAnimationGetScaleKey(const D3DRMANIMATIONKEY& rmKey,
+                          D3DVECTOR& dvVec)
+{
+    dvVec = D3DVECTOR(rmKey.dvK[0], rmKey.dvK[1], rmKey.dvK[2]);
+}
+
+inline VOID
+D3DRMAnimationGetPositionKey(const D3DRMANIMATIONKEY& rmKey,
+                             D3DVECTOR& dvVec)
+{
+    dvVec = D3DVECTOR(rmKey.dvK[0], rmKey.dvK[1], rmKey.dvK[2]);
+}
+inline VOID
+D3DRMAnimationSetRotateKey(D3DRMANIMATIONKEY& rmKey,
+                           const D3DRMQUATERNION& rmQuat)
+{
+    rmKey.dvK[0] = rmQuat.s;
+    rmKey.dvK[1] = rmQuat.v.x;
+    rmKey.dvK[2] = rmQuat.v.y;
+    rmKey.dvK[3] = rmQuat.v.z;
+}
+
+inline VOID
+D3DRMAnimationSetScaleKey(D3DRMANIMATIONKEY& rmKey,
+                          const D3DVECTOR& dvVec)
+{
+    rmKey.dvK[0] = dvVec.x;
+    rmKey.dvK[1] = dvVec.y;
+    rmKey.dvK[2] = dvVec.z;
+}
+
+inline VOID
+D3DRMAnimationSetPositionKey(D3DRMANIMATIONKEY& rmKey,
+                             const D3DVECTOR& dvVec)
+{
+    rmKey.dvK[0] = dvVec.x;
+    rmKey.dvK[1] = dvVec.y;
+    rmKey.dvK[2] = dvVec.z;
+}
+#endif
+
+#define D3DRMANIMATION_ROTATEKEY 0x01
+#define D3DRMANIMATION_SCALEKEY 0x02
+#define D3DRMANIMATION_POSITIONKEY 0x03
+
+
+typedef DWORD D3DRMMAPPING, D3DRMMAPPINGFLAG, *LPD3DRMMAPPING;
+static const D3DRMMAPPINGFLAG D3DRMMAP_WRAPU = 1;
+static const D3DRMMAPPINGFLAG D3DRMMAP_WRAPV = 2;
+static const D3DRMMAPPINGFLAG D3DRMMAP_PERSPCORRECT = 4;
+
+typedef struct _D3DRMVERTEX
+{   D3DVECTOR       position;
+    D3DVECTOR       normal;
+    D3DVALUE        tu, tv;
+    D3DCOLOR        color;
+} D3DRMVERTEX, *LPD3DRMVERTEX;
+
+typedef LONG D3DRMGROUPINDEX; /* group indexes begin a 0 */
+static const D3DRMGROUPINDEX D3DRMGROUP_ALLGROUPS = -1;
+
+/*
+ * Create a color from three components in the range 0-1 inclusive.
+ */
+extern D3DCOLOR D3DRMAPI        D3DRMCreateColorRGB(D3DVALUE red,
+                                          D3DVALUE green,
+                                          D3DVALUE blue);
+
+/*
+ * Create a color from four components in the range 0-1 inclusive.
+ */
+extern D3DCOLOR D3DRMAPI        D3DRMCreateColorRGBA(D3DVALUE red,
+                                                 D3DVALUE green,
+                                                 D3DVALUE blue,
+                                                 D3DVALUE alpha);
+
+/*
+ * Get the red component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetRed(D3DCOLOR);
+
+/*
+ * Get the green component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetGreen(D3DCOLOR);
+
+/*
+ * Get the blue component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetBlue(D3DCOLOR);
+
+/*
+ * Get the alpha component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetAlpha(D3DCOLOR);
+
+/*
+ * Add two vectors.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorAdd(LPD3DVECTOR d,
+                                          LPD3DVECTOR s1,
+                                          LPD3DVECTOR s2);
+
+/*
+ * Subtract two vectors.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorSubtract(LPD3DVECTOR d,
+                                               LPD3DVECTOR s1,
+                                               LPD3DVECTOR s2);
+/*
+ * Reflect a ray about a given normal.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorReflect(LPD3DVECTOR d,
+                                              LPD3DVECTOR ray,
+                                              LPD3DVECTOR norm);
+
+/*
+ * Calculate the vector cross product.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorCrossProduct(LPD3DVECTOR d,
+                                                   LPD3DVECTOR s1,
+                                                   LPD3DVECTOR s2);
+/*
+ * Return the vector dot product.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMVectorDotProduct(LPD3DVECTOR s1,
+                                                 LPD3DVECTOR s2);
+
+/*
+ * Scale a vector so that its modulus is 1.  Returns its argument or
+ * NULL if there was an error (e.g. a zero vector was passed).
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorNormalize(LPD3DVECTOR);
+#define D3DRMVectorNormalise D3DRMVectorNormalize
+
+/*
+ * Return the length of a vector (e.g. sqrt(x*x + y*y + z*z)).
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMVectorModulus(LPD3DVECTOR v);
+
+/*
+ * Set the rotation part of a matrix to be a rotation of theta radians
+ * around the given axis.
+ */
+
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorRotate(LPD3DVECTOR r, LPD3DVECTOR v, LPD3DVECTOR axis, D3DVALUE theta);
+
+/*
+ * Scale a vector uniformly in all three axes
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorScale(LPD3DVECTOR d, LPD3DVECTOR s, D3DVALUE factor);
+
+/*
+ * Return a random unit vector
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorRandom(LPD3DVECTOR d);
+
+/*
+ * Returns a unit quaternion that represents a rotation of theta radians
+ * around the given axis.
+ */
+
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION quat,
+                                                              LPD3DVECTOR v,
+                                                              D3DVALUE theta);
+
+/*
+ * Calculate the product of two quaternions
+ */
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionMultiply(LPD3DRMQUATERNION q,
+                                                          LPD3DRMQUATERNION a,
+                                                          LPD3DRMQUATERNION b);
+
+/*
+ * Interpolate between two quaternions
+ */
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q,
+                                                       LPD3DRMQUATERNION a,
+                                                       LPD3DRMQUATERNION b,
+                                                       D3DVALUE alpha);
+
+/*
+ * Calculate the matrix for the rotation that a unit quaternion represents
+ */
+extern void             D3DRMAPI D3DRMMatrixFromQuaternion(D3DRMMATRIX4D dmMat, LPD3DRMQUATERNION lpDqQuat);
+
+/*
+ * Calculate the quaternion that corresponds to a rotation matrix
+ */
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionFromMatrix(LPD3DRMQUATERNION, D3DRMMATRIX4D);
+
+
+#if defined(__cplusplus)
+};
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/d3drmobj.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1666 @@
+/*==========================================================================;
+ *
+ *  Copyright (c) Microsoft Corporation.  All rights reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DRMOBJ_H_
+#define _D3DRMOBJ_H_
+
+#include <objbase.h> /* Use Windows header files */
+#define VIRTUAL
+#include "d3drmdef.h"
+
+#include "d3d.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The methods for IUnknown
+ */
+#define IUNKNOWN_METHODS(kind) \
+    STDMETHOD(QueryInterface)           (THIS_ REFIID riid, LPVOID *ppvObj) kind; \
+    STDMETHOD_(ULONG, AddRef)           (THIS) kind; \
+    STDMETHOD_(ULONG, Release)          (THIS) kind
+
+/*
+ * The methods for IDirect3DRMObject
+ */
+#define IDIRECT3DRMOBJECT_METHODS(kind) \
+    STDMETHOD(Clone)                    (THIS_ LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) kind; \
+    STDMETHOD(AddDestroyCallback)       (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \
+    STDMETHOD(DeleteDestroyCallback)    (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \
+    STDMETHOD(SetAppData)               (THIS_ DWORD data) kind; \
+    STDMETHOD_(DWORD, GetAppData)       (THIS) kind; \
+    STDMETHOD(SetName)                  (THIS_ LPCSTR) kind; \
+    STDMETHOD(GetName)                  (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind; \
+    STDMETHOD(GetClassName)             (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind
+
+
+#define WIN_TYPES(itype, ptype) \
+    typedef interface itype FAR *LP##ptype, FAR **LPLP##ptype
+
+WIN_TYPES(IDirect3DRMObject, DIRECT3DRMOBJECT);
+WIN_TYPES(IDirect3DRMObject2, DIRECT3DRMOBJECT2);
+WIN_TYPES(IDirect3DRMDevice, DIRECT3DRMDEVICE);
+WIN_TYPES(IDirect3DRMDevice2, DIRECT3DRMDEVICE2);
+WIN_TYPES(IDirect3DRMDevice3, DIRECT3DRMDEVICE3);
+WIN_TYPES(IDirect3DRMViewport, DIRECT3DRMVIEWPORT);
+WIN_TYPES(IDirect3DRMViewport2, DIRECT3DRMVIEWPORT2);
+WIN_TYPES(IDirect3DRMFrame, DIRECT3DRMFRAME);
+WIN_TYPES(IDirect3DRMFrame2, DIRECT3DRMFRAME2);
+WIN_TYPES(IDirect3DRMFrame3, DIRECT3DRMFRAME3);
+WIN_TYPES(IDirect3DRMVisual, DIRECT3DRMVISUAL);
+WIN_TYPES(IDirect3DRMMesh, DIRECT3DRMMESH);
+WIN_TYPES(IDirect3DRMMeshBuilder, DIRECT3DRMMESHBUILDER);
+WIN_TYPES(IDirect3DRMMeshBuilder2, DIRECT3DRMMESHBUILDER2);
+WIN_TYPES(IDirect3DRMMeshBuilder3, DIRECT3DRMMESHBUILDER3);
+WIN_TYPES(IDirect3DRMFace, DIRECT3DRMFACE);
+WIN_TYPES(IDirect3DRMFace2, DIRECT3DRMFACE2);
+WIN_TYPES(IDirect3DRMLight, DIRECT3DRMLIGHT);
+WIN_TYPES(IDirect3DRMTexture, DIRECT3DRMTEXTURE);
+WIN_TYPES(IDirect3DRMTexture2, DIRECT3DRMTEXTURE2);
+WIN_TYPES(IDirect3DRMTexture3, DIRECT3DRMTEXTURE3);
+WIN_TYPES(IDirect3DRMWrap, DIRECT3DRMWRAP);
+WIN_TYPES(IDirect3DRMMaterial, DIRECT3DRMMATERIAL);
+WIN_TYPES(IDirect3DRMMaterial2, DIRECT3DRMMATERIAL2);
+WIN_TYPES(IDirect3DRMInterpolator, DIRECT3DRMINTERPOLATOR);
+WIN_TYPES(IDirect3DRMAnimation, DIRECT3DRMANIMATION);
+WIN_TYPES(IDirect3DRMAnimation2, DIRECT3DRMANIMATION2);
+WIN_TYPES(IDirect3DRMAnimationSet, DIRECT3DRMANIMATIONSET);
+WIN_TYPES(IDirect3DRMAnimationSet2, DIRECT3DRMANIMATIONSET2);
+WIN_TYPES(IDirect3DRMUserVisual, DIRECT3DRMUSERVISUAL);
+WIN_TYPES(IDirect3DRMShadow, DIRECT3DRMSHADOW);
+WIN_TYPES(IDirect3DRMShadow2, DIRECT3DRMSHADOW2);
+WIN_TYPES(IDirect3DRMArray, DIRECT3DRMARRAY);
+WIN_TYPES(IDirect3DRMObjectArray, DIRECT3DRMOBJECTARRAY);
+WIN_TYPES(IDirect3DRMDeviceArray, DIRECT3DRMDEVICEARRAY);
+WIN_TYPES(IDirect3DRMFaceArray, DIRECT3DRMFACEARRAY);
+WIN_TYPES(IDirect3DRMViewportArray, DIRECT3DRMVIEWPORTARRAY);
+WIN_TYPES(IDirect3DRMFrameArray, DIRECT3DRMFRAMEARRAY);
+WIN_TYPES(IDirect3DRMAnimationArray, DIRECT3DRMANIMATIONARRAY);
+WIN_TYPES(IDirect3DRMVisualArray, DIRECT3DRMVISUALARRAY);
+WIN_TYPES(IDirect3DRMPickedArray, DIRECT3DRMPICKEDARRAY);
+WIN_TYPES(IDirect3DRMPicked2Array, DIRECT3DRMPICKED2ARRAY);
+WIN_TYPES(IDirect3DRMLightArray, DIRECT3DRMLIGHTARRAY);
+WIN_TYPES(IDirect3DRMProgressiveMesh, DIRECT3DRMPROGRESSIVEMESH);
+WIN_TYPES(IDirect3DRMClippedVisual, DIRECT3DRMCLIPPEDVISUAL);
+
+/*
+ * Direct3DRM Object classes
+ */
+DEFINE_GUID(CLSID_CDirect3DRMDevice,        0x4fa3568e, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMViewport,      0x4fa3568f, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMFrame,         0x4fa35690, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMesh,          0x4fa35691, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMeshBuilder,   0x4fa35692, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMFace,          0x4fa35693, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMLight,         0x4fa35694, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMTexture,       0x4fa35695, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMWrap,          0x4fa35696, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMaterial,      0x4fa35697, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMAnimation,     0x4fa35698, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMAnimationSet,  0x4fa35699, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMUserVisual,    0x4fa3569a, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMShadow,        0x4fa3569b, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMViewportInterpolator,
+0xde9eaa1, 0x3b84, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(CLSID_CDirect3DRMFrameInterpolator,
+0xde9eaa2, 0x3b84, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(CLSID_CDirect3DRMMeshInterpolator,
+0xde9eaa3, 0x3b84, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(CLSID_CDirect3DRMLightInterpolator,
+0xde9eaa6, 0x3b84, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(CLSID_CDirect3DRMMaterialInterpolator,
+0xde9eaa7, 0x3b84, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(CLSID_CDirect3DRMTextureInterpolator,
+0xde9eaa8, 0x3b84, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(CLSID_CDirect3DRMProgressiveMesh, 0x4516ec40, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(CLSID_CDirect3DRMClippedVisual,   0x5434e72d, 0x6d66, 0x11d1, 0xbb, 0xb, 0x0, 0x0, 0xf8, 0x75, 0x86, 0x5a);
+
+
+/*
+ * Direct3DRM Object interfaces
+ */
+DEFINE_GUID(IID_IDirect3DRMObject,          0xeb16cb00, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMObject2,         0x4516ec7c, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMDevice,          0xe9e19280, 0x6e05, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMDevice2,         0x4516ec78, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMDevice3,     0x549f498b, 0xbfeb, 0x11d1, 0x8e, 0xd8, 0x0, 0xa0, 0xc9, 0x67, 0xa4, 0x82);
+DEFINE_GUID(IID_IDirect3DRMViewport,        0xeb16cb02, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMViewport2,   0x4a1b1be6, 0xbfed, 0x11d1, 0x8e, 0xd8, 0x0, 0xa0, 0xc9, 0x67, 0xa4, 0x82);
+DEFINE_GUID(IID_IDirect3DRMFrame,           0xeb16cb03, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFrame2,          0xc3dfbd60, 0x3988, 0x11d0, 0x9e, 0xc2, 0x0, 0x0, 0xc0, 0x29, 0x1a, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMFrame3,              0xff6b7f70, 0xa40e, 0x11d1, 0x91, 0xf9, 0x0, 0x0, 0xf8, 0x75, 0x8e, 0x66);
+DEFINE_GUID(IID_IDirect3DRMVisual,          0xeb16cb04, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMesh,            0xa3a80d01, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMeshBuilder,     0xa3a80d02, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMeshBuilder2,    0x4516ec77, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMMeshBuilder3,    0x4516ec82, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMFace,            0xeb16cb07, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFace2,           0x4516ec81, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMLight,           0xeb16cb08, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMTexture,         0xeb16cb09, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMTexture2,        0x120f30c0, 0x1629, 0x11d0, 0x94, 0x1c, 0x0, 0x80, 0xc8, 0xc, 0xfa, 0x7b);
+DEFINE_GUID(IID_IDirect3DRMTexture3,        0xff6b7f73, 0xa40e, 0x11d1, 0x91, 0xf9, 0x0, 0x0, 0xf8, 0x75, 0x8e, 0x66);
+DEFINE_GUID(IID_IDirect3DRMWrap,            0xeb16cb0a, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMaterial,        0xeb16cb0b, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMaterial2,       0xff6b7f75, 0xa40e, 0x11d1, 0x91, 0xf9, 0x0, 0x0, 0xf8, 0x75, 0x8e, 0x66);
+DEFINE_GUID(IID_IDirect3DRMAnimation,       0xeb16cb0d, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMAnimation2,      0xff6b7f77, 0xa40e, 0x11d1, 0x91, 0xf9, 0x0, 0x0, 0xf8, 0x75, 0x8e, 0x66);
+DEFINE_GUID(IID_IDirect3DRMAnimationSet,    0xeb16cb0e, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMAnimationSet2,   0xff6b7f79, 0xa40e, 0x11d1, 0x91, 0xf9, 0x0, 0x0, 0xf8, 0x75, 0x8e, 0x66);
+DEFINE_GUID(IID_IDirect3DRMObjectArray,     0x242f6bc2, 0x3849, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMDeviceArray,     0xeb16cb10, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMViewportArray,   0xeb16cb11, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFrameArray,      0xeb16cb12, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMVisualArray,     0xeb16cb13, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMLightArray,      0xeb16cb14, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMPickedArray,     0xeb16cb16, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFaceArray,       0xeb16cb17, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMAnimationArray,
+0xd5f1cae0, 0x4bd7, 0x11d1, 0xb9, 0x74, 0x0, 0x60, 0x8, 0x3e, 0x45, 0xf3);
+DEFINE_GUID(IID_IDirect3DRMUserVisual,      0x59163de0, 0x6d43, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMShadow,          0xaf359780, 0x6ba3, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMShadow2,         0x86b44e25, 0x9c82, 0x11d1, 0xbb, 0xb, 0x0, 0xa0, 0xc9, 0x81, 0xa0, 0xa6);
+DEFINE_GUID(IID_IDirect3DRMInterpolator,    0x242f6bc1, 0x3849, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMProgressiveMesh, 0x4516ec79, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMPicked2Array,    0x4516ec7b, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x0, 0x0, 0xc0, 0x78, 0x1b, 0xc3);
+DEFINE_GUID(IID_IDirect3DRMClippedVisual,   0x5434e733, 0x6d66, 0x11d1, 0xbb, 0xb, 0x0, 0x0, 0xf8, 0x75, 0x86, 0x5a);
+
+typedef void (__cdecl *D3DRMOBJECTCALLBACK)(LPDIRECT3DRMOBJECT obj, LPVOID arg);
+typedef void (__cdecl *D3DRMFRAMEMOVECALLBACK)(LPDIRECT3DRMFRAME obj, LPVOID arg, D3DVALUE delta);
+typedef void (__cdecl *D3DRMFRAME3MOVECALLBACK)(LPDIRECT3DRMFRAME3 obj, LPVOID arg, D3DVALUE delta);
+typedef void (__cdecl *D3DRMUPDATECALLBACK)(LPDIRECT3DRMDEVICE obj, LPVOID arg, int, LPD3DRECT);
+typedef void (__cdecl *D3DRMDEVICE3UPDATECALLBACK)(LPDIRECT3DRMDEVICE3 obj, LPVOID arg, int, LPD3DRECT);
+typedef int (__cdecl *D3DRMUSERVISUALCALLBACK)
+    (   LPDIRECT3DRMUSERVISUAL obj, LPVOID arg, D3DRMUSERVISUALREASON reason,
+        LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMVIEWPORT view
+    );
+typedef HRESULT (__cdecl *D3DRMLOADTEXTURECALLBACK)
+    (char *tex_name, void *arg, LPDIRECT3DRMTEXTURE *);
+typedef HRESULT (__cdecl *D3DRMLOADTEXTURE3CALLBACK)
+    (char *tex_name, void *arg, LPDIRECT3DRMTEXTURE3 *);
+typedef void (__cdecl *D3DRMLOADCALLBACK)
+    (LPDIRECT3DRMOBJECT object, REFIID objectguid, LPVOID arg);
+
+typedef HRESULT (__cdecl *D3DRMDOWNSAMPLECALLBACK)
+    (LPDIRECT3DRMTEXTURE3 lpDirect3DRMTexture, LPVOID pArg,
+     LPDIRECTDRAWSURFACE pDDSSrc, LPDIRECTDRAWSURFACE pDDSDst);
+typedef HRESULT (__cdecl *D3DRMVALIDATIONCALLBACK)
+    (LPDIRECT3DRMTEXTURE3 lpDirect3DRMTexture, LPVOID pArg,
+     DWORD dwFlags, DWORD dwcRects, LPRECT pRects);
+
+
+typedef struct _D3DRMPICKDESC
+{
+    ULONG       ulFaceIdx;
+    LONG        lGroupIdx;
+    D3DVECTOR   vPosition;
+
+} D3DRMPICKDESC, *LPD3DRMPICKDESC;
+
+typedef struct _D3DRMPICKDESC2
+{
+    ULONG       ulFaceIdx;
+    LONG        lGroupIdx;
+    D3DVECTOR   dvPosition;
+    D3DVALUE    tu;
+    D3DVALUE    tv;
+    D3DVECTOR   dvNormal;
+    D3DCOLOR    dcColor;
+
+} D3DRMPICKDESC2, *LPD3DRMPICKDESC2;
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMObject
+
+/*
+ * Base class
+ */
+DECLARE_INTERFACE_(IDirect3DRMObject, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMObject2
+
+DECLARE_INTERFACE_(IDirect3DRMObject2, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    /*
+     * IDirect3DRMObject2 methods
+     */
+    STDMETHOD(AddDestroyCallback)(THIS_ D3DRMOBJECTCALLBACK lpFunc, LPVOID pvArg) PURE;
+    STDMETHOD(Clone)(THIS_ LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) PURE; \
+    STDMETHOD(DeleteDestroyCallback)(THIS_ D3DRMOBJECTCALLBACK lpFunc, LPVOID pvArg) PURE; \
+    STDMETHOD(GetClientData)(THIS_ DWORD dwID, LPVOID* lplpvData) PURE;
+    STDMETHOD(GetDirect3DRM)(THIS_ LPDIRECT3DRM* lplpDirect3DRM) PURE;
+    STDMETHOD(GetName)(THIS_ LPDWORD lpdwSize, LPSTR lpName) PURE;
+    STDMETHOD(SetClientData)(THIS_ DWORD dwID, LPVOID lpvData, DWORD dwFlags) PURE;
+    STDMETHOD(SetName)(THIS_ LPCSTR lpName) PURE;
+    STDMETHOD(GetAge)(THIS_ DWORD dwFlags, LPDWORD pdwAge) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMVisual
+
+DECLARE_INTERFACE_(IDirect3DRMVisual, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMDevice
+
+DECLARE_INTERFACE_(IDirect3DRMDevice, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMDevice methods
+     */
+    STDMETHOD(Init)(THIS_ ULONG width, ULONG height) PURE;
+    STDMETHOD(InitFromD3D)(THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev) PURE;
+    STDMETHOD(InitFromClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, int width, int height) PURE;
+
+    STDMETHOD(Update)(THIS) PURE;
+    STDMETHOD(AddUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(DeleteUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(SetBufferCount)(THIS_ DWORD) PURE;
+    STDMETHOD_(DWORD, GetBufferCount)(THIS) PURE;
+
+    STDMETHOD(SetDither)(THIS_ BOOL) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetTextureQuality)(THIS_ D3DRMTEXTUREQUALITY) PURE;
+
+    STDMETHOD(GetViewports)(THIS_ LPDIRECT3DRMVIEWPORTARRAY *return_views) PURE;
+
+    STDMETHOD_(BOOL, GetDither)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetTrianglesDrawn)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWireframeOptions)(THIS) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(D3DCOLORMODEL, GetColorModel)(THIS) PURE;
+    STDMETHOD_(D3DRMTEXTUREQUALITY, GetTextureQuality)(THIS) PURE;
+    STDMETHOD(GetDirect3DDevice)(THIS_ LPDIRECT3DDEVICE *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMDevice2
+
+DECLARE_INTERFACE_(IDirect3DRMDevice2, IDirect3DRMDevice)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMDevice methods
+     */
+    STDMETHOD(Init)(THIS_ ULONG width, ULONG height) PURE;
+    STDMETHOD(InitFromD3D)(THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev) PURE;
+    STDMETHOD(InitFromClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, int width, int height) PURE;
+
+    STDMETHOD(Update)(THIS) PURE;
+    STDMETHOD(AddUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(DeleteUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(SetBufferCount)(THIS_ DWORD) PURE;
+    STDMETHOD_(DWORD, GetBufferCount)(THIS) PURE;
+
+    STDMETHOD(SetDither)(THIS_ BOOL) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetTextureQuality)(THIS_ D3DRMTEXTUREQUALITY) PURE;
+
+    STDMETHOD(GetViewports)(THIS_ LPDIRECT3DRMVIEWPORTARRAY *return_views) PURE;
+
+    STDMETHOD_(BOOL, GetDither)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetTrianglesDrawn)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWireframeOptions)(THIS) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(D3DCOLORMODEL, GetColorModel)(THIS) PURE;
+    STDMETHOD_(D3DRMTEXTUREQUALITY, GetTextureQuality)(THIS) PURE;
+    STDMETHOD(GetDirect3DDevice)(THIS_ LPDIRECT3DDEVICE *) PURE;
+
+    /*
+     * IDirect3DRMDevice2 methods
+     */
+    STDMETHOD(InitFromD3D2)(THIS_ LPDIRECT3D2 lpD3D, LPDIRECT3DDEVICE2 lpD3DDev) PURE;
+    STDMETHOD(InitFromSurface)(THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD, LPDIRECTDRAWSURFACE lpDDSBack) PURE;
+    STDMETHOD(SetRenderMode)(THIS_ DWORD dwFlags) PURE;
+    STDMETHOD_(DWORD, GetRenderMode)(THIS) PURE;
+    STDMETHOD(GetDirect3DDevice2)(THIS_ LPDIRECT3DDEVICE2 *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMDevice3
+
+DECLARE_INTERFACE_(IDirect3DRMDevice3, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMDevice methods
+     */
+    STDMETHOD(Init)(THIS_ ULONG width, ULONG height) PURE;
+    STDMETHOD(InitFromD3D)(THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev) PURE;
+    STDMETHOD(InitFromClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, int width, int height) PURE;
+
+    STDMETHOD(Update)(THIS) PURE;
+    STDMETHOD(AddUpdateCallback)(THIS_ D3DRMDEVICE3UPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(DeleteUpdateCallback)(THIS_ D3DRMDEVICE3UPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(SetBufferCount)(THIS_ DWORD) PURE;
+    STDMETHOD_(DWORD, GetBufferCount)(THIS) PURE;
+
+    STDMETHOD(SetDither)(THIS_ BOOL) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetTextureQuality)(THIS_ D3DRMTEXTUREQUALITY) PURE;
+
+    STDMETHOD(GetViewports)(THIS_ LPDIRECT3DRMVIEWPORTARRAY *return_views) PURE;
+
+    STDMETHOD_(BOOL, GetDither)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetTrianglesDrawn)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWireframeOptions)(THIS) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(D3DCOLORMODEL, GetColorModel)(THIS) PURE;
+    STDMETHOD_(D3DRMTEXTUREQUALITY, GetTextureQuality)(THIS) PURE;
+    STDMETHOD(GetDirect3DDevice)(THIS_ LPDIRECT3DDEVICE *) PURE;
+
+    /*
+     * IDirect3DRMDevice2 methods
+     */
+    STDMETHOD(InitFromD3D2)(THIS_ LPDIRECT3D2 lpD3D, LPDIRECT3DDEVICE2 lpD3DDev) PURE;
+    STDMETHOD(InitFromSurface)(THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD, LPDIRECTDRAWSURFACE lpDDSBack, DWORD dwFlags) PURE;
+    STDMETHOD(SetRenderMode)(THIS_ DWORD dwFlags) PURE;
+    STDMETHOD_(DWORD, GetRenderMode)(THIS) PURE;
+    STDMETHOD(GetDirect3DDevice2)(THIS_ LPDIRECT3DDEVICE2 *) PURE;
+
+    /*
+     * IDirect3DRMDevice3 methods
+     */
+    STDMETHOD(FindPreferredTextureFormat)(THIS_ DWORD dwBitDepths, DWORD dwFlags, LPDDPIXELFORMAT lpDDPF) PURE;
+    STDMETHOD(RenderStateChange)(THIS_ D3DRENDERSTATETYPE drsType, DWORD dwVal, DWORD dwFlags) PURE;
+    STDMETHOD(LightStateChange)(THIS_ D3DLIGHTSTATETYPE drsType, DWORD dwVal, DWORD dwFlags) PURE;
+    STDMETHOD(GetStateChangeOptions)(THIS_ DWORD dwStateClass, DWORD dwStateNum, LPDWORD pdwFlags) PURE;
+    STDMETHOD(SetStateChangeOptions)(THIS_ DWORD dwStateClass, DWORD dwStateNum, DWORD dwFlags) PURE;
+};
+
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMViewport
+
+DECLARE_INTERFACE_(IDirect3DRMViewport, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMViewport methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMFRAME Camera,
+        DWORD xpos, DWORD ypos, DWORD width, DWORD height
+    ) PURE;
+    STDMETHOD(Clear)(THIS) PURE;
+    STDMETHOD(Render)(THIS_ LPDIRECT3DRMFRAME) PURE;
+
+    STDMETHOD(SetFront)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetBack)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetField)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetUniformScaling)(THIS_ BOOL) PURE;
+    STDMETHOD(SetCamera)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(SetProjection)(THIS_ D3DRMPROJECTIONTYPE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DRMVECTOR4D *d, D3DVECTOR *s) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DRMVECTOR4D *s) PURE;
+    STDMETHOD(Configure)(THIS_ LONG x, LONG y, DWORD width, DWORD height) PURE;
+    STDMETHOD(ForceUpdate)(THIS_ DWORD x1, DWORD y1, DWORD x2, DWORD y2) PURE;
+    STDMETHOD(SetPlane)(THIS_ D3DVALUE left, D3DVALUE right, D3DVALUE bottom, D3DVALUE top) PURE;
+
+    STDMETHOD(GetCamera)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(GetDevice)(THIS_ LPDIRECT3DRMDEVICE *) PURE;
+    STDMETHOD(GetPlane)(THIS_ D3DVALUE *left, D3DVALUE *right, D3DVALUE *bottom, D3DVALUE *top) PURE;
+    STDMETHOD(Pick)(THIS_ LONG x, LONG y, LPDIRECT3DRMPICKEDARRAY *return_visuals) PURE;
+
+    STDMETHOD_(BOOL, GetUniformScaling)(THIS) PURE;
+    STDMETHOD_(LONG, GetX)(THIS) PURE;
+    STDMETHOD_(LONG, GetY)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetField)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetBack)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetFront)(THIS) PURE;
+    STDMETHOD_(D3DRMPROJECTIONTYPE, GetProjection)(THIS) PURE;
+    STDMETHOD(GetDirect3DViewport)(THIS_ LPDIRECT3DVIEWPORT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMViewport2
+DECLARE_INTERFACE_(IDirect3DRMViewport2, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMViewport2 methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ LPDIRECT3DRMDEVICE3 dev, LPDIRECT3DRMFRAME3 Camera,
+        DWORD xpos, DWORD ypos, DWORD width, DWORD height
+    ) PURE;
+    STDMETHOD(Clear)(THIS_ DWORD dwFlags) PURE;
+    STDMETHOD(Render)(THIS_ LPDIRECT3DRMFRAME3) PURE;
+
+    STDMETHOD(SetFront)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetBack)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetField)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetUniformScaling)(THIS_ BOOL) PURE;
+    STDMETHOD(SetCamera)(THIS_ LPDIRECT3DRMFRAME3) PURE;
+    STDMETHOD(SetProjection)(THIS_ D3DRMPROJECTIONTYPE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DRMVECTOR4D *d, D3DVECTOR *s) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DRMVECTOR4D *s) PURE;
+    STDMETHOD(Configure)(THIS_ LONG x, LONG y, DWORD width, DWORD height) PURE;
+    STDMETHOD(ForceUpdate)(THIS_ DWORD x1, DWORD y1, DWORD x2, DWORD y2) PURE;
+    STDMETHOD(SetPlane)(THIS_ D3DVALUE left, D3DVALUE right, D3DVALUE bottom, D3DVALUE top) PURE;
+
+    STDMETHOD(GetCamera)(THIS_ LPDIRECT3DRMFRAME3 *) PURE;
+    STDMETHOD(GetDevice)(THIS_ LPDIRECT3DRMDEVICE3 *) PURE;
+    STDMETHOD(GetPlane)(THIS_ D3DVALUE *left, D3DVALUE *right, D3DVALUE *bottom, D3DVALUE *top) PURE;
+    STDMETHOD(Pick)(THIS_ LONG x, LONG y, LPDIRECT3DRMPICKEDARRAY *return_visuals) PURE;
+
+    STDMETHOD_(BOOL, GetUniformScaling)(THIS) PURE;
+    STDMETHOD_(LONG, GetX)(THIS) PURE;
+    STDMETHOD_(LONG, GetY)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetField)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetBack)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetFront)(THIS) PURE;
+    STDMETHOD_(D3DRMPROJECTIONTYPE, GetProjection)(THIS) PURE;
+    STDMETHOD(GetDirect3DViewport)(THIS_ LPDIRECT3DVIEWPORT *) PURE;
+    STDMETHOD(TransformVectors)(THIS_ DWORD dwNumVectors,
+                                LPD3DRMVECTOR4D lpDstVectors,
+                                LPD3DVECTOR lpSrcVectors) PURE;
+    STDMETHOD(InverseTransformVectors)(THIS_ DWORD dwNumVectors,
+                                       LPD3DVECTOR lpDstVectors,
+                                       LPD3DRMVECTOR4D lpSrcVectors) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFrame
+
+DECLARE_INTERFACE_(IDirect3DRMFrame, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFrame methods
+     */
+    STDMETHOD(AddChild)(THIS_ LPDIRECT3DRMFRAME child) PURE;
+    STDMETHOD(AddLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(AddMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(AddTransform)(THIS_ D3DRMCOMBINETYPE, D3DRMMATRIX4D) PURE;
+    STDMETHOD(AddTranslation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScale)(THIS_ D3DRMCOMBINETYPE, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(AddRotation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(AddVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD(GetChildren)(THIS_ LPDIRECT3DRMFRAMEARRAY *children) PURE;
+    STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+    STDMETHOD(GetLights)(THIS_ LPDIRECT3DRMLIGHTARRAY *lights) PURE;
+    STDMETHOD_(D3DRMMATERIALMODE, GetMaterialMode)(THIS) PURE;
+    STDMETHOD(GetParent)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(GetPosition)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_position) PURE;
+    STDMETHOD(GetRotation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR axis, LPD3DVALUE return_theta) PURE;
+    STDMETHOD(GetScene)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD_(D3DRMSORTMODE, GetSortMode)(THIS) PURE;
+    STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DRMMATRIX4D return_matrix) PURE;
+    STDMETHOD(GetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_velocity, BOOL with_rotation) PURE;
+    STDMETHOD(GetOrientation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR dir, LPD3DVECTOR up) PURE;
+    STDMETHOD(GetVisuals)(THIS_ LPDIRECT3DRMVISUALARRAY *visuals) PURE;
+    STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg)PURE;
+    STDMETHOD(LookAt)(THIS_ LPDIRECT3DRMFRAME target, LPDIRECT3DRMFRAME reference, D3DRMFRAMECONSTRAINT) PURE;
+    STDMETHOD(Move)(THIS_ D3DVALUE delta) PURE;
+    STDMETHOD(DeleteChild)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(DeleteMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(DeleteVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneBackground)(THIS) PURE;
+    STDMETHOD(GetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE *) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneFogColor)(THIS) PURE;
+    STDMETHOD_(BOOL, GetSceneFogEnable)(THIS) PURE;
+    STDMETHOD_(D3DRMFOGMODE, GetSceneFogMode)(THIS) PURE;
+    STDMETHOD(GetSceneFogParams)(THIS_ D3DVALUE *return_start, D3DVALUE *return_end, D3DVALUE *return_density) PURE;
+    STDMETHOD(SetSceneBackground)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneBackgroundRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(SetSceneBackgroundImage)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetSceneFogEnable)(THIS_ BOOL) PURE;
+    STDMETHOD(SetSceneFogColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneFogMode)(THIS_ D3DRMFOGMODE) PURE;
+    STDMETHOD(SetSceneFogParams)(THIS_ D3DVALUE start, D3DVALUE end, D3DVALUE density) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD_(D3DRMZBUFFERMODE, GetZbufferMode)(THIS) PURE;
+    STDMETHOD(SetMaterialMode)(THIS_ D3DRMMATERIALMODE) PURE;
+    STDMETHOD(SetOrientation)
+    (   THIS_ LPDIRECT3DRMFRAME reference,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz
+    ) PURE;
+    STDMETHOD(SetPosition)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetRotation)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(SetSortMode)(THIS_ D3DRMSORTMODE) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation) PURE;
+    STDMETHOD(SetZbufferMode)(THIS_ D3DRMZBUFFERMODE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFrame2
+
+DECLARE_INTERFACE_(IDirect3DRMFrame2, IDirect3DRMFrame)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFrame methods
+     */
+    STDMETHOD(AddChild)(THIS_ LPDIRECT3DRMFRAME child) PURE;
+    STDMETHOD(AddLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(AddMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(AddTransform)(THIS_ D3DRMCOMBINETYPE, D3DRMMATRIX4D) PURE;
+    STDMETHOD(AddTranslation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScale)(THIS_ D3DRMCOMBINETYPE, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(AddRotation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(AddVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD(GetChildren)(THIS_ LPDIRECT3DRMFRAMEARRAY *children) PURE;
+    STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+    STDMETHOD(GetLights)(THIS_ LPDIRECT3DRMLIGHTARRAY *lights) PURE;
+    STDMETHOD_(D3DRMMATERIALMODE, GetMaterialMode)(THIS) PURE;
+    STDMETHOD(GetParent)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(GetPosition)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_position) PURE;
+    STDMETHOD(GetRotation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR axis, LPD3DVALUE return_theta) PURE;
+    STDMETHOD(GetScene)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD_(D3DRMSORTMODE, GetSortMode)(THIS) PURE;
+    STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DRMMATRIX4D return_matrix) PURE;
+    STDMETHOD(GetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_velocity, BOOL with_rotation) PURE;
+    STDMETHOD(GetOrientation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR dir, LPD3DVECTOR up) PURE;
+    STDMETHOD(GetVisuals)(THIS_ LPDIRECT3DRMVISUALARRAY *visuals) PURE;
+    STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg)PURE;
+    STDMETHOD(LookAt)(THIS_ LPDIRECT3DRMFRAME target, LPDIRECT3DRMFRAME reference, D3DRMFRAMECONSTRAINT) PURE;
+    STDMETHOD(Move)(THIS_ D3DVALUE delta) PURE;
+    STDMETHOD(DeleteChild)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(DeleteMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(DeleteVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneBackground)(THIS) PURE;
+    STDMETHOD(GetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE *) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneFogColor)(THIS) PURE;
+    STDMETHOD_(BOOL, GetSceneFogEnable)(THIS) PURE;
+    STDMETHOD_(D3DRMFOGMODE, GetSceneFogMode)(THIS) PURE;
+    STDMETHOD(GetSceneFogParams)(THIS_ D3DVALUE *return_start, D3DVALUE *return_end, D3DVALUE *return_density) PURE;
+    STDMETHOD(SetSceneBackground)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneBackgroundRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(SetSceneBackgroundImage)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetSceneFogEnable)(THIS_ BOOL) PURE;
+    STDMETHOD(SetSceneFogColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneFogMode)(THIS_ D3DRMFOGMODE) PURE;
+    STDMETHOD(SetSceneFogParams)(THIS_ D3DVALUE start, D3DVALUE end, D3DVALUE density) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD_(D3DRMZBUFFERMODE, GetZbufferMode)(THIS) PURE;
+    STDMETHOD(SetMaterialMode)(THIS_ D3DRMMATERIALMODE) PURE;
+    STDMETHOD(SetOrientation)
+    (   THIS_ LPDIRECT3DRMFRAME reference,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz
+    ) PURE;
+    STDMETHOD(SetPosition)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetRotation)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(SetSortMode)(THIS_ D3DRMSORTMODE) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation) PURE;
+    STDMETHOD(SetZbufferMode)(THIS_ D3DRMZBUFFERMODE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+
+    /*
+     * IDirect3DRMFrame2 methods
+     */
+    STDMETHOD(AddMoveCallback2)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg, DWORD dwFlags) PURE;
+    STDMETHOD(GetBox)(THIS_ LPD3DRMBOX) PURE;
+    STDMETHOD_(BOOL, GetBoxEnable)(THIS) PURE;
+    STDMETHOD(GetAxes)(THIS_ LPD3DVECTOR dir, LPD3DVECTOR up);
+    STDMETHOD(GetMaterial)(THIS_ LPDIRECT3DRMMATERIAL *) PURE;
+    STDMETHOD_(BOOL, GetInheritAxes)(THIS);
+    STDMETHOD(GetHierarchyBox)(THIS_ LPD3DRMBOX) PURE;
+
+    STDMETHOD(SetBox)(THIS_ LPD3DRMBOX) PURE;
+    STDMETHOD(SetBoxEnable)(THIS_ BOOL) PURE;
+    STDMETHOD(SetAxes)(THIS_ D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+                       D3DVALUE ux, D3DVALUE uy, D3DVALUE uz);
+    STDMETHOD(SetInheritAxes)(THIS_ BOOL inherit_from_parent);
+    STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE;
+    STDMETHOD(SetQuaternion)(THIS_ LPDIRECT3DRMFRAME reference, D3DRMQUATERNION *q) PURE;
+
+    STDMETHOD(RayPick)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DRMRAY ray, DWORD dwFlags, LPDIRECT3DRMPICKED2ARRAY *return_visuals) PURE;
+    STDMETHOD(Save)(THIS_ LPCSTR filename, D3DRMXOFFORMAT d3dFormat,
+                    D3DRMSAVEOPTIONS d3dSaveFlags);
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFrame3
+
+DECLARE_INTERFACE_(IDirect3DRMFrame3, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFrame3 methods
+     */
+    STDMETHOD(AddChild)(THIS_ LPDIRECT3DRMFRAME3 child) PURE;
+    STDMETHOD(AddLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(AddMoveCallback)(THIS_ D3DRMFRAME3MOVECALLBACK, VOID *arg, DWORD dwFlags) PURE;
+    STDMETHOD(AddTransform)(THIS_ D3DRMCOMBINETYPE, D3DRMMATRIX4D) PURE;
+    STDMETHOD(AddTranslation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScale)(THIS_ D3DRMCOMBINETYPE, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(AddRotation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(AddVisual)(THIS_ LPUNKNOWN) PURE;
+    STDMETHOD(GetChildren)(THIS_ LPDIRECT3DRMFRAMEARRAY *children) PURE;
+    STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+    STDMETHOD(GetLights)(THIS_ LPDIRECT3DRMLIGHTARRAY *lights) PURE;
+    STDMETHOD_(D3DRMMATERIALMODE, GetMaterialMode)(THIS) PURE;
+    STDMETHOD(GetParent)(THIS_ LPDIRECT3DRMFRAME3 *) PURE;
+    STDMETHOD(GetPosition)(THIS_ LPDIRECT3DRMFRAME3 reference, LPD3DVECTOR return_position) PURE;
+    STDMETHOD(GetRotation)(THIS_ LPDIRECT3DRMFRAME3 reference, LPD3DVECTOR axis, LPD3DVALUE return_theta) PURE;
+    STDMETHOD(GetScene)(THIS_ LPDIRECT3DRMFRAME3 *) PURE;
+    STDMETHOD_(D3DRMSORTMODE, GetSortMode)(THIS) PURE;
+    STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE3 *) PURE;
+    STDMETHOD(GetTransform)(THIS_ LPDIRECT3DRMFRAME3 reference,
+                             D3DRMMATRIX4D rmMatrix) PURE;
+    STDMETHOD(GetVelocity)(THIS_ LPDIRECT3DRMFRAME3 reference, LPD3DVECTOR return_velocity, BOOL with_rotation) PURE;
+    STDMETHOD(GetOrientation)(THIS_ LPDIRECT3DRMFRAME3 reference, LPD3DVECTOR dir, LPD3DVECTOR up) PURE;
+    STDMETHOD(GetVisuals)(THIS_ LPDWORD lpdwCount, LPUNKNOWN *) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURE3CALLBACK, LPVOID lpArg)PURE;
+    STDMETHOD(LookAt)(THIS_ LPDIRECT3DRMFRAME3 target, LPDIRECT3DRMFRAME3 reference, D3DRMFRAMECONSTRAINT) PURE;
+    STDMETHOD(Move)(THIS_ D3DVALUE delta) PURE;
+    STDMETHOD(DeleteChild)(THIS_ LPDIRECT3DRMFRAME3) PURE;
+    STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(DeleteMoveCallback)(THIS_ D3DRMFRAME3MOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(DeleteVisual)(THIS_ LPUNKNOWN) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneBackground)(THIS) PURE;
+    STDMETHOD(GetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE *) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneFogColor)(THIS) PURE;
+    STDMETHOD_(BOOL, GetSceneFogEnable)(THIS) PURE;
+    STDMETHOD_(D3DRMFOGMODE, GetSceneFogMode)(THIS) PURE;
+    STDMETHOD(GetSceneFogParams)(THIS_ D3DVALUE *return_start, D3DVALUE *return_end, D3DVALUE *return_density) PURE;
+    STDMETHOD(SetSceneBackground)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneBackgroundRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(SetSceneBackgroundImage)(THIS_ LPDIRECT3DRMTEXTURE3) PURE;
+    STDMETHOD(SetSceneFogEnable)(THIS_ BOOL) PURE;
+    STDMETHOD(SetSceneFogColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneFogMode)(THIS_ D3DRMFOGMODE) PURE;
+    STDMETHOD(SetSceneFogParams)(THIS_ D3DVALUE start, D3DVALUE end, D3DVALUE density) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD_(D3DRMZBUFFERMODE, GetZbufferMode)(THIS) PURE;
+    STDMETHOD(SetMaterialMode)(THIS_ D3DRMMATERIALMODE) PURE;
+    STDMETHOD(SetOrientation)
+    (   THIS_ LPDIRECT3DRMFRAME3 reference,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz
+    ) PURE;
+    STDMETHOD(SetPosition)(THIS_ LPDIRECT3DRMFRAME3 reference, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetRotation)(THIS_ LPDIRECT3DRMFRAME3 reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(SetSortMode)(THIS_ D3DRMSORTMODE) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE3) PURE;
+    STDMETHOD(SetVelocity)(THIS_ LPDIRECT3DRMFRAME3 reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation) PURE;
+    STDMETHOD(SetZbufferMode)(THIS_ D3DRMZBUFFERMODE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+    STDMETHOD(GetBox)(THIS_ LPD3DRMBOX) PURE;
+    STDMETHOD_(BOOL, GetBoxEnable)(THIS) PURE;
+    STDMETHOD(GetAxes)(THIS_ LPD3DVECTOR dir, LPD3DVECTOR up);
+    STDMETHOD(GetMaterial)(THIS_ LPDIRECT3DRMMATERIAL2 *) PURE;
+    STDMETHOD_(BOOL, GetInheritAxes)(THIS);
+    STDMETHOD(GetHierarchyBox)(THIS_ LPD3DRMBOX) PURE;
+
+    STDMETHOD(SetBox)(THIS_ LPD3DRMBOX) PURE;
+    STDMETHOD(SetBoxEnable)(THIS_ BOOL) PURE;
+    STDMETHOD(SetAxes)(THIS_ D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+                       D3DVALUE ux, D3DVALUE uy, D3DVALUE uz);
+    STDMETHOD(SetInheritAxes)(THIS_ BOOL inherit_from_parent);
+    STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL2) PURE;
+    STDMETHOD(SetQuaternion)(THIS_ LPDIRECT3DRMFRAME3 reference, D3DRMQUATERNION *q) PURE;
+
+    STDMETHOD(RayPick)(THIS_ LPDIRECT3DRMFRAME3 reference, LPD3DRMRAY ray, DWORD dwFlags, LPDIRECT3DRMPICKED2ARRAY *return_visuals) PURE;
+    STDMETHOD(Save)(THIS_ LPCSTR filename, D3DRMXOFFORMAT d3dFormat,
+                    D3DRMSAVEOPTIONS d3dSaveFlags);
+    STDMETHOD(TransformVectors)(THIS_ LPDIRECT3DRMFRAME3 reference,
+                                DWORD dwNumVectors,
+                                LPD3DVECTOR lpDstVectors,
+                                LPD3DVECTOR lpSrcVectors) PURE;
+    STDMETHOD(InverseTransformVectors)(THIS_ LPDIRECT3DRMFRAME3 reference,
+                                       DWORD dwNumVectors,
+                                       LPD3DVECTOR lpDstVectors,
+                                       LPD3DVECTOR lpSrcVectors) PURE;
+    STDMETHOD(SetTraversalOptions)(THIS_ DWORD dwFlags) PURE;
+    STDMETHOD(GetTraversalOptions)(THIS_ LPDWORD lpdwFlags) PURE;
+    STDMETHOD(SetSceneFogMethod)(THIS_ DWORD dwFlags) PURE;
+    STDMETHOD(GetSceneFogMethod)(THIS_ LPDWORD lpdwFlags) PURE;
+    STDMETHOD(SetMaterialOverride)(THIS_ LPD3DRMMATERIALOVERRIDE) PURE;
+    STDMETHOD(GetMaterialOverride)(THIS_ LPD3DRMMATERIALOVERRIDE) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMesh
+
+DECLARE_INTERFACE_(IDirect3DRMMesh, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMesh methods
+     */
+    STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE;
+    STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE;
+    STDMETHOD(AddGroup)(THIS_ unsigned vCount, unsigned fCount, unsigned vPerFace, unsigned *fData, D3DRMGROUPINDEX *returnId) PURE;
+    STDMETHOD(SetVertices)(THIS_ D3DRMGROUPINDEX id, unsigned index, unsigned count, D3DRMVERTEX *values) PURE;
+    STDMETHOD(SetGroupColor)(THIS_ D3DRMGROUPINDEX id, D3DCOLOR value) PURE;
+    STDMETHOD(SetGroupColorRGB)(THIS_ D3DRMGROUPINDEX id, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetGroupMapping)(THIS_ D3DRMGROUPINDEX id, D3DRMMAPPING value) PURE;
+    STDMETHOD(SetGroupQuality)(THIS_ D3DRMGROUPINDEX id, D3DRMRENDERQUALITY value) PURE;
+    STDMETHOD(SetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL value) PURE;
+    STDMETHOD(SetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE value) PURE;
+
+    STDMETHOD_(unsigned, GetGroupCount)(THIS) PURE;
+    STDMETHOD(GetGroup)(THIS_ D3DRMGROUPINDEX id, unsigned *vCount, unsigned *fCount, unsigned *vPerFace, DWORD *fDataSize, unsigned *fData) PURE;
+    STDMETHOD(GetVertices)(THIS_ D3DRMGROUPINDEX id, DWORD index, DWORD count, D3DRMVERTEX *returnPtr) PURE;
+    STDMETHOD_(D3DCOLOR, GetGroupColor)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD_(D3DRMMAPPING, GetGroupMapping)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetGroupQuality)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD(GetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL *returnPtr) PURE;
+    STDMETHOD(GetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE *returnPtr) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMProgressiveMesh
+
+DECLARE_INTERFACE_(IDirect3DRMProgressiveMesh, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMProgressiveMesh methods
+     */
+    STDMETHOD(Load) (THIS_ LPVOID lpObjLocation, LPVOID lpObjId,
+                     D3DRMLOADOPTIONS dloLoadflags, D3DRMLOADTEXTURECALLBACK lpCallback,
+                     LPVOID lpArg) PURE;
+    STDMETHOD(GetLoadStatus) (THIS_ LPD3DRMPMESHLOADSTATUS lpStatus) PURE;
+    STDMETHOD(SetMinRenderDetail) (THIS_ D3DVALUE d3dVal) PURE;
+    STDMETHOD(Abort) (THIS_ DWORD dwFlags) PURE;
+
+    STDMETHOD(GetFaceDetail) (THIS_ LPDWORD lpdwCount) PURE;
+    STDMETHOD(GetVertexDetail) (THIS_ LPDWORD lpdwCount) PURE;
+    STDMETHOD(SetFaceDetail) (THIS_ DWORD dwCount) PURE;
+    STDMETHOD(SetVertexDetail) (THIS_ DWORD dwCount) PURE;
+    STDMETHOD(GetFaceDetailRange) (THIS_ LPDWORD lpdwMin, LPDWORD lpdwMax) PURE;
+    STDMETHOD(GetVertexDetailRange) (THIS_ LPDWORD lpdwMin, LPDWORD lpdwMax) PURE;
+    STDMETHOD(GetDetail) (THIS_ D3DVALUE *lpdvVal) PURE;
+    STDMETHOD(SetDetail) (THIS_ D3DVALUE d3dVal) PURE;
+
+    STDMETHOD(RegisterEvents) (THIS_ HANDLE hEvent, DWORD dwFlags, DWORD dwReserved) PURE;
+    STDMETHOD(CreateMesh) (THIS_ LPDIRECT3DRMMESH *lplpD3DRMMesh) PURE;
+    STDMETHOD(Duplicate) (THIS_ LPDIRECT3DRMPROGRESSIVEMESH *lplpD3DRMPMesh) PURE;
+    STDMETHOD(GetBox) (THIS_ LPD3DRMBOX lpBBox) PURE;
+    STDMETHOD(SetQuality) (THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(GetQuality) (THIS_ LPD3DRMRENDERQUALITY lpdwquality) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMShadow
+
+DECLARE_INTERFACE_(IDirect3DRMShadow, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMShadow methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ LPDIRECT3DRMVISUAL visual, LPDIRECT3DRMLIGHT light,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz
+    ) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMShadow2
+
+DECLARE_INTERFACE_(IDirect3DRMShadow2, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMShadow methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ LPUNKNOWN pUNK, LPDIRECT3DRMLIGHT light,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz
+    ) PURE;
+
+    /*
+     * IDirect3DRMShadow2 methods
+     */
+    STDMETHOD(GetVisual)(THIS_ LPDIRECT3DRMVISUAL *) PURE;
+    STDMETHOD(SetVisual)(THIS_ LPUNKNOWN pUNK, DWORD) PURE;
+    STDMETHOD(GetLight)(THIS_ LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(SetLight)(THIS_ LPDIRECT3DRMLIGHT, DWORD) PURE;
+    STDMETHOD(GetPlane)(THIS_ LPD3DVALUE px, LPD3DVALUE py, LPD3DVALUE pz,
+                        LPD3DVALUE nx, LPD3DVALUE ny, LPD3DVALUE nz) PURE;
+    STDMETHOD(SetPlane)(THIS_ D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+                        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz, DWORD) PURE;
+    STDMETHOD(GetOptions)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SetOptions)(THIS_ DWORD) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFace
+
+DECLARE_INTERFACE_(IDirect3DRMFace, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFace methods
+     */
+     STDMETHOD(AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+     STDMETHOD(AddVertexAndNormalIndexed)(THIS_ DWORD vertex, DWORD normal) PURE;
+     STDMETHOD(SetColorRGB)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE) PURE;
+     STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+     STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+     STDMETHOD(SetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE u, D3DVALUE v) PURE;
+     STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE;
+     STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+
+     STDMETHOD(GetVertex)(THIS_ DWORD index, D3DVECTOR *vertex, D3DVECTOR *normal) PURE;
+     STDMETHOD(GetVertices)(THIS_ DWORD *vertex_count, D3DVECTOR *coords, D3DVECTOR *normals);
+     STDMETHOD(GetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE *u, D3DVALUE *v) PURE;
+     STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE;
+     STDMETHOD(GetNormal)(THIS_ D3DVECTOR *) PURE;
+     STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE;
+     STDMETHOD(GetMaterial)(THIS_ LPDIRECT3DRMMATERIAL *) PURE;
+
+     STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+     STDMETHOD_(int, GetVertexIndex)(THIS_ DWORD which) PURE;
+     STDMETHOD_(int, GetTextureCoordinateIndex)(THIS_ DWORD which) PURE;
+     STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFace2
+
+DECLARE_INTERFACE_(IDirect3DRMFace2, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFace methods
+     */
+     STDMETHOD(AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+     STDMETHOD(AddVertexAndNormalIndexed)(THIS_ DWORD vertex, DWORD normal) PURE;
+     STDMETHOD(SetColorRGB)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE) PURE;
+     STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+     STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE3) PURE;
+     STDMETHOD(SetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE u, D3DVALUE v) PURE;
+     STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL2) PURE;
+     STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+
+     STDMETHOD(GetVertex)(THIS_ DWORD index, D3DVECTOR *vertex, D3DVECTOR *normal) PURE;
+     STDMETHOD(GetVertices)(THIS_ DWORD *vertex_count, D3DVECTOR *coords, D3DVECTOR *normals);
+     STDMETHOD(GetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE *u, D3DVALUE *v) PURE;
+     STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE;
+     STDMETHOD(GetNormal)(THIS_ D3DVECTOR *) PURE;
+     STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE3 *) PURE;
+     STDMETHOD(GetMaterial)(THIS_ LPDIRECT3DRMMATERIAL2 *) PURE;
+
+     STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+     STDMETHOD_(int, GetVertexIndex)(THIS_ DWORD which) PURE;
+     STDMETHOD_(int, GetTextureCoordinateIndex)(THIS_ DWORD which) PURE;
+     STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMeshBuilder
+
+DECLARE_INTERFACE_(IDirect3DRMMeshBuilder, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMeshBuilder methods
+     */
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg) PURE;
+    STDMETHOD(Save)(THIS_ const char *filename, D3DRMXOFFORMAT, D3DRMSAVEOPTIONS save) PURE;
+    STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE;
+    STDMETHOD(SetColorSource)(THIS_ D3DRMCOLORSOURCE) PURE;
+    STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE;
+    STDMETHOD(GenerateNormals)(THIS) PURE;
+    STDMETHOD_(D3DRMCOLORSOURCE, GetColorSource)(THIS) PURE;
+
+    STDMETHOD(AddMesh)(THIS_ LPDIRECT3DRMMESH) PURE;
+    STDMETHOD(AddMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER) PURE;
+    STDMETHOD(AddFrame)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(AddFace)(THIS_ LPDIRECT3DRMFACE) PURE;
+    STDMETHOD(AddFaces)
+    (   THIS_ DWORD vcount, D3DVECTOR *vertices, DWORD ncount, D3DVECTOR *normals,
+        DWORD *data, LPDIRECT3DRMFACEARRAY*
+    ) PURE;
+    STDMETHOD(ReserveSpace)(THIS_ DWORD vertex_Count, DWORD normal_count, DWORD face_count) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetPerspective)(THIS_ BOOL) PURE;
+    STDMETHOD(SetVertex)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetNormal)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetTextureCoordinates)(THIS_ DWORD index, D3DVALUE u, D3DVALUE v) PURE;
+    STDMETHOD(SetVertexColor)(THIS_ DWORD index, D3DCOLOR) PURE;
+    STDMETHOD(SetVertexColorRGB)(THIS_ DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+
+    STDMETHOD(GetFaces)(THIS_ LPDIRECT3DRMFACEARRAY*) PURE;
+    STDMETHOD(GetVertices)
+    (   THIS_ DWORD *vcount, D3DVECTOR *vertices, DWORD *ncount, D3DVECTOR *normals, DWORD *face_data_size, DWORD *face_data
+    ) PURE;
+    STDMETHOD(GetTextureCoordinates)(THIS_ DWORD index, D3DVALUE *u, D3DVALUE *v) PURE;
+
+    STDMETHOD_(int, AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD_(int, AddNormal)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(CreateFace)(THIS_ LPDIRECT3DRMFACE*) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(BOOL, GetPerspective)(THIS) PURE;
+    STDMETHOD_(int, GetFaceCount)(THIS) PURE;
+    STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetVertexColor)(THIS_ DWORD index) PURE;
+
+    STDMETHOD(CreateMesh)(THIS_ LPDIRECT3DRMMESH*) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMeshBuilder2
+
+DECLARE_INTERFACE_(IDirect3DRMMeshBuilder2, IDirect3DRMMeshBuilder)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMeshBuilder methods
+     */
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg) PURE;
+    STDMETHOD(Save)(THIS_ const char *filename, D3DRMXOFFORMAT, D3DRMSAVEOPTIONS save) PURE;
+    STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE;
+    STDMETHOD(SetColorSource)(THIS_ D3DRMCOLORSOURCE) PURE;
+    STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE;
+    STDMETHOD(GenerateNormals)(THIS) PURE;
+    STDMETHOD_(D3DRMCOLORSOURCE, GetColorSource)(THIS) PURE;
+
+    STDMETHOD(AddMesh)(THIS_ LPDIRECT3DRMMESH) PURE;
+    STDMETHOD(AddMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER) PURE;
+    STDMETHOD(AddFrame)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(AddFace)(THIS_ LPDIRECT3DRMFACE) PURE;
+    STDMETHOD(AddFaces)
+    (   THIS_ DWORD vcount, D3DVECTOR *vertices, DWORD ncount, D3DVECTOR *normals,
+        DWORD *data, LPDIRECT3DRMFACEARRAY*
+    ) PURE;
+    STDMETHOD(ReserveSpace)(THIS_ DWORD vertex_Count, DWORD normal_count, DWORD face_count) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetPerspective)(THIS_ BOOL) PURE;
+    STDMETHOD(SetVertex)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetNormal)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetTextureCoordinates)(THIS_ DWORD index, D3DVALUE u, D3DVALUE v) PURE;
+    STDMETHOD(SetVertexColor)(THIS_ DWORD index, D3DCOLOR) PURE;
+    STDMETHOD(SetVertexColorRGB)(THIS_ DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+
+    STDMETHOD(GetFaces)(THIS_ LPDIRECT3DRMFACEARRAY*) PURE;
+    STDMETHOD(GetVertices)
+    (   THIS_ DWORD *vcount, D3DVECTOR *vertices, DWORD *ncount, D3DVECTOR *normals, DWORD *face_data_size, DWORD *face_data
+    ) PURE;
+    STDMETHOD(GetTextureCoordinates)(THIS_ DWORD index, D3DVALUE *u, D3DVALUE *v) PURE;
+
+    STDMETHOD_(int, AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD_(int, AddNormal)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(CreateFace)(THIS_ LPDIRECT3DRMFACE*) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(BOOL, GetPerspective)(THIS) PURE;
+    STDMETHOD_(int, GetFaceCount)(THIS) PURE;
+    STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetVertexColor)(THIS_ DWORD index) PURE;
+
+    STDMETHOD(CreateMesh)(THIS_ LPDIRECT3DRMMESH*) PURE;
+
+    /*
+     * IDirect3DRMMeshBuilder2 methods
+     */
+    STDMETHOD(GenerateNormals2)(THIS_ D3DVALUE crease, DWORD dwFlags) PURE;
+    STDMETHOD(GetFace)(THIS_ DWORD index, LPDIRECT3DRMFACE*) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMeshBuilder3
+
+DECLARE_INTERFACE_(IDirect3DRMMeshBuilder3, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMeshBuilder3 methods
+     */
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURE3CALLBACK, LPVOID lpArg) PURE;
+    STDMETHOD(Save)(THIS_ const char *filename, D3DRMXOFFORMAT, D3DRMSAVEOPTIONS save) PURE;
+    STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE;
+    STDMETHOD(SetColorSource)(THIS_ D3DRMCOLORSOURCE) PURE;
+    STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE;
+    STDMETHOD(GenerateNormals)(THIS_ D3DVALUE crease, DWORD dwFlags) PURE;
+    STDMETHOD_(D3DRMCOLORSOURCE, GetColorSource)(THIS) PURE;
+
+    STDMETHOD(AddMesh)(THIS_ LPDIRECT3DRMMESH) PURE;
+    STDMETHOD(AddMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER3, DWORD dwFlags) PURE;
+    STDMETHOD(AddFrame)(THIS_ LPDIRECT3DRMFRAME3) PURE;
+    STDMETHOD(AddFace)(THIS_ LPDIRECT3DRMFACE2) PURE;
+    STDMETHOD(AddFaces)
+    (   THIS_ DWORD vcount, D3DVECTOR *vertices, DWORD ncount, D3DVECTOR *normals,
+        DWORD *data, LPDIRECT3DRMFACEARRAY*
+    ) PURE;
+    STDMETHOD(ReserveSpace)(THIS_ DWORD vertex_Count, DWORD normal_count, DWORD face_count) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE3) PURE;
+    STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL2) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetPerspective)(THIS_ BOOL) PURE;
+    STDMETHOD(SetVertex)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetNormal)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetTextureCoordinates)(THIS_ DWORD index, D3DVALUE u, D3DVALUE v) PURE;
+    STDMETHOD(SetVertexColor)(THIS_ DWORD index, D3DCOLOR) PURE;
+    STDMETHOD(SetVertexColorRGB)(THIS_ DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(GetFaces)(THIS_ LPDIRECT3DRMFACEARRAY*) PURE;
+    STDMETHOD(GetGeometry)
+    (   THIS_ DWORD *vcount, D3DVECTOR *vertices, DWORD *ncount, D3DVECTOR *normals, DWORD *face_data_size, DWORD *face_data
+    ) PURE;
+    STDMETHOD(GetTextureCoordinates)(THIS_ DWORD index, D3DVALUE *u, D3DVALUE *v) PURE;
+    STDMETHOD_(int, AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD_(int, AddNormal)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(CreateFace)(THIS_ LPDIRECT3DRMFACE2 *) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(BOOL, GetPerspective)(THIS) PURE;
+    STDMETHOD_(int, GetFaceCount)(THIS) PURE;
+    STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetVertexColor)(THIS_ DWORD index) PURE;
+    STDMETHOD(CreateMesh)(THIS_ LPDIRECT3DRMMESH*) PURE;
+    STDMETHOD(GetFace)(THIS_ DWORD index, LPDIRECT3DRMFACE2 *) PURE;
+    STDMETHOD(GetVertex)(THIS_ DWORD dwIndex, LPD3DVECTOR lpVector) PURE;
+    STDMETHOD(GetNormal)(THIS_ DWORD dwIndex, LPD3DVECTOR lpVector) PURE;
+    STDMETHOD(DeleteVertices)(THIS_ DWORD dwIndexFirst, DWORD dwCount) PURE;
+    STDMETHOD(DeleteNormals)(THIS_ DWORD dwIndexFirst, DWORD dwCount) PURE;
+    STDMETHOD(DeleteFace)(THIS_ LPDIRECT3DRMFACE2) PURE;
+    STDMETHOD(Empty)(THIS_ DWORD dwFlags) PURE;
+    STDMETHOD(Optimize)(THIS_ DWORD dwFlags) PURE;
+    STDMETHOD(AddFacesIndexed)(THIS_ DWORD dwFlags, DWORD *lpdwvIndices, DWORD *dwIndexFirst, DWORD *dwCount) PURE;
+    STDMETHOD(CreateSubMesh)(THIS_ LPUNKNOWN *) PURE;
+    STDMETHOD(GetParentMesh)(THIS_ DWORD, LPUNKNOWN *) PURE;
+    STDMETHOD(GetSubMeshes)(THIS_ LPDWORD lpdwCount, LPUNKNOWN *) PURE;
+    STDMETHOD(DeleteSubMesh)(THIS_ LPUNKNOWN) PURE;
+    STDMETHOD(Enable)(THIS_ DWORD) PURE;
+    STDMETHOD(GetEnable)(THIS_ DWORD *) PURE;
+    STDMETHOD(AddTriangles)(THIS_ DWORD dwFlags, DWORD dwFormat,
+                            DWORD dwVertexCount, LPVOID lpvData) PURE;
+    STDMETHOD(SetVertices)(THIS_ DWORD dwIndexFirst, DWORD dwCount, LPD3DVECTOR) PURE;
+    STDMETHOD(GetVertices)(THIS_ DWORD dwIndexFirst, LPDWORD lpdwCount, LPD3DVECTOR) PURE;
+    STDMETHOD(SetNormals)(THIS_ DWORD dwIndexFirst, DWORD dwCount, LPD3DVECTOR) PURE;
+    STDMETHOD(GetNormals)(THIS_ DWORD dwIndexFirst, LPDWORD lpdwCount, LPD3DVECTOR) PURE;
+    STDMETHOD_(int, GetNormalCount)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMLight
+
+DECLARE_INTERFACE_(IDirect3DRMLight, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMLight methods
+     */
+    STDMETHOD(SetType)(THIS_ D3DRMLIGHTTYPE) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetRange)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetUmbra)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetPenumbra)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetConstantAttenuation)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetLinearAttenuation)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetQuadraticAttenuation)(THIS_ D3DVALUE) PURE;
+
+    STDMETHOD_(D3DVALUE, GetRange)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetUmbra)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetPenumbra)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetConstantAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetLinearAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetQuadraticAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+    STDMETHOD_(D3DRMLIGHTTYPE, GetType)(THIS) PURE;
+
+    STDMETHOD(SetEnableFrame)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(GetEnableFrame)(THIS_ LPDIRECT3DRMFRAME*) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMTexture
+
+DECLARE_INTERFACE_(IDirect3DRMTexture, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMTexture methods
+     */
+    STDMETHOD(InitFromFile)(THIS_ const char *filename) PURE;
+    STDMETHOD(InitFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS) PURE;
+    STDMETHOD(InitFromResource)(THIS_ HRSRC) PURE;
+    STDMETHOD(Changed)(THIS_ BOOL pixels, BOOL palette) PURE;
+
+    STDMETHOD(SetColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalSize)(THIS_ D3DVALUE width, D3DVALUE height) PURE;
+    STDMETHOD(SetDecalOrigin)(THIS_ LONG x, LONG y) PURE;
+    STDMETHOD(SetDecalScale)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalTransparency)(THIS_ BOOL) PURE;
+    STDMETHOD(SetDecalTransparentColor)(THIS_ D3DCOLOR) PURE;
+
+    STDMETHOD(GetDecalSize)(THIS_ D3DVALUE *width_return, D3DVALUE *height_return) PURE;
+    STDMETHOD(GetDecalOrigin)(THIS_ LONG *x_return, LONG *y_return) PURE;
+
+    STDMETHOD_(D3DRMIMAGE *, GetImage)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetColors)(THIS) PURE;
+    STDMETHOD_(DWORD, GetDecalScale)(THIS) PURE;
+    STDMETHOD_(BOOL, GetDecalTransparency)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetDecalTransparentColor)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMTexture2
+
+DECLARE_INTERFACE_(IDirect3DRMTexture2, IDirect3DRMTexture)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMTexture methods
+     */
+    STDMETHOD(InitFromFile)(THIS_ const char *filename) PURE;
+    STDMETHOD(InitFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS) PURE;
+    STDMETHOD(InitFromResource)(THIS_ HRSRC) PURE;
+    STDMETHOD(Changed)(THIS_ BOOL pixels, BOOL palette) PURE;
+
+    STDMETHOD(SetColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalSize)(THIS_ D3DVALUE width, D3DVALUE height) PURE;
+    STDMETHOD(SetDecalOrigin)(THIS_ LONG x, LONG y) PURE;
+    STDMETHOD(SetDecalScale)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalTransparency)(THIS_ BOOL) PURE;
+    STDMETHOD(SetDecalTransparentColor)(THIS_ D3DCOLOR) PURE;
+
+    STDMETHOD(GetDecalSize)(THIS_ D3DVALUE *width_return, D3DVALUE *height_return) PURE;
+    STDMETHOD(GetDecalOrigin)(THIS_ LONG *x_return, LONG *y_return) PURE;
+
+    STDMETHOD_(D3DRMIMAGE *, GetImage)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetColors)(THIS) PURE;
+    STDMETHOD_(DWORD, GetDecalScale)(THIS) PURE;
+    STDMETHOD_(BOOL, GetDecalTransparency)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetDecalTransparentColor)(THIS) PURE;
+
+    /*
+     * IDirect3DRMTexture2 methods
+     */
+    STDMETHOD(InitFromImage)(THIS_ LPD3DRMIMAGE) PURE;
+    STDMETHOD(InitFromResource2)(THIS_ HMODULE hModule, LPCTSTR strName, LPCTSTR strType) PURE;
+    STDMETHOD(GenerateMIPMap)(THIS_ DWORD) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMTexture3
+
+DECLARE_INTERFACE_(IDirect3DRMTexture3, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMTexture3 methods
+     */
+    STDMETHOD(InitFromFile)(THIS_ const char *filename) PURE;
+    STDMETHOD(InitFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS) PURE;
+    STDMETHOD(InitFromResource)(THIS_ HRSRC) PURE;
+    STDMETHOD(Changed)(THIS_ DWORD dwFlags, DWORD dwcRects, LPRECT pRects) PURE;
+    STDMETHOD(SetColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalSize)(THIS_ D3DVALUE width, D3DVALUE height) PURE;
+    STDMETHOD(SetDecalOrigin)(THIS_ LONG x, LONG y) PURE;
+    STDMETHOD(SetDecalScale)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalTransparency)(THIS_ BOOL) PURE;
+    STDMETHOD(SetDecalTransparentColor)(THIS_ D3DCOLOR) PURE;
+
+    STDMETHOD(GetDecalSize)(THIS_ D3DVALUE *width_return, D3DVALUE *height_return) PURE;
+    STDMETHOD(GetDecalOrigin)(THIS_ LONG *x_return, LONG *y_return) PURE;
+
+    STDMETHOD_(D3DRMIMAGE *, GetImage)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetColors)(THIS) PURE;
+    STDMETHOD_(DWORD, GetDecalScale)(THIS) PURE;
+    STDMETHOD_(BOOL, GetDecalTransparency)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetDecalTransparentColor)(THIS) PURE;
+    STDMETHOD(InitFromImage)(THIS_ LPD3DRMIMAGE) PURE;
+    STDMETHOD(InitFromResource2)(THIS_ HMODULE hModule, LPCTSTR strName, LPCTSTR strType) PURE;
+    STDMETHOD(GenerateMIPMap)(THIS_ DWORD) PURE;
+    STDMETHOD(GetSurface)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE* lplpDDS) PURE;
+    STDMETHOD(SetCacheOptions)(THIS_ LONG lImportance, DWORD dwFlags) PURE;
+    STDMETHOD(GetCacheOptions)(THIS_ LPLONG lplImportance, LPDWORD lpdwFlags) PURE;
+    STDMETHOD(SetDownsampleCallback)(THIS_ D3DRMDOWNSAMPLECALLBACK pCallback, LPVOID pArg) PURE;
+    STDMETHOD(SetValidationCallback)(THIS_ D3DRMVALIDATIONCALLBACK pCallback, LPVOID pArg) PURE;
+};
+
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMWrap
+
+DECLARE_INTERFACE_(IDirect3DRMWrap, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMWrap methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME ref,
+        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz,
+        D3DVALUE ou, D3DVALUE ov,
+        D3DVALUE su, D3DVALUE sv
+    ) PURE;
+    STDMETHOD(Apply)(THIS_ LPDIRECT3DRMOBJECT) PURE;
+    STDMETHOD(ApplyRelative)(THIS_ LPDIRECT3DRMFRAME frame, LPDIRECT3DRMOBJECT) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMaterial
+
+DECLARE_INTERFACE_(IDirect3DRMMaterial, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMaterial methods
+     */
+    STDMETHOD(SetPower)(THIS_ D3DVALUE power) PURE;
+    STDMETHOD(SetSpecular)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+    STDMETHOD(SetEmissive)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+
+    STDMETHOD_(D3DVALUE, GetPower)(THIS) PURE;
+    STDMETHOD(GetSpecular)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+    STDMETHOD(GetEmissive)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+};
+
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMaterial2
+
+DECLARE_INTERFACE_(IDirect3DRMMaterial2, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMaterial2 methods
+     */
+    STDMETHOD(SetPower)(THIS_ D3DVALUE power) PURE;
+    STDMETHOD(SetSpecular)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+    STDMETHOD(SetEmissive)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+    STDMETHOD_(D3DVALUE, GetPower)(THIS) PURE;
+    STDMETHOD(GetSpecular)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+    STDMETHOD(GetEmissive)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+    STDMETHOD(GetAmbient)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+    STDMETHOD(SetAmbient)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+};
+
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimation
+
+DECLARE_INTERFACE_(IDirect3DRMAnimation, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMAnimation methods
+     */
+    STDMETHOD(SetOptions)(THIS_ D3DRMANIMATIONOPTIONS flags) PURE;
+    STDMETHOD(AddRotateKey)(THIS_ D3DVALUE time, D3DRMQUATERNION *q) PURE;
+    STDMETHOD(AddPositionKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScaleKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(DeleteKey)(THIS_ D3DVALUE time) PURE;
+    STDMETHOD(SetFrame)(THIS_ LPDIRECT3DRMFRAME frame) PURE;
+    STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE;
+
+    STDMETHOD_(D3DRMANIMATIONOPTIONS, GetOptions)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimation2
+
+DECLARE_INTERFACE_(IDirect3DRMAnimation2, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMAnimation2 methods
+     */
+    STDMETHOD(SetOptions)(THIS_ D3DRMANIMATIONOPTIONS flags) PURE;
+    STDMETHOD(AddRotateKey)(THIS_ D3DVALUE time, D3DRMQUATERNION *q) PURE;
+    STDMETHOD(AddPositionKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScaleKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(DeleteKey)(THIS_ D3DVALUE time) PURE;
+    STDMETHOD(SetFrame)(THIS_ LPDIRECT3DRMFRAME3 frame) PURE;
+    STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE;
+
+    STDMETHOD_(D3DRMANIMATIONOPTIONS, GetOptions)(THIS) PURE;
+    STDMETHOD(GetFrame)(THIS_ LPDIRECT3DRMFRAME3 *lpD3DFrame) PURE;
+    STDMETHOD(DeleteKeyByID)(THIS_ DWORD dwID) PURE;
+    STDMETHOD(AddKey)(THIS_ LPD3DRMANIMATIONKEY lpKey) PURE;
+    STDMETHOD(ModifyKey)(THIS_ LPD3DRMANIMATIONKEY lpKey) PURE;
+    STDMETHOD(GetKeys)(THIS_ D3DVALUE dvTimeMin,
+                       D3DVALUE dvTimeMax, LPDWORD lpdwNumKeys,
+                       LPD3DRMANIMATIONKEY lpKey);
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimationSet
+
+DECLARE_INTERFACE_(IDirect3DRMAnimationSet, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMAnimationSet methods
+     */
+    STDMETHOD(AddAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg, LPDIRECT3DRMFRAME parent)PURE;
+    STDMETHOD(DeleteAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE;
+    STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimationSet2
+
+DECLARE_INTERFACE_(IDirect3DRMAnimationSet2, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMAnimationSet2 methods
+     */
+    STDMETHOD(AddAnimation)(THIS_ LPDIRECT3DRMANIMATION2 aid) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURE3CALLBACK, LPVOID lpArg, LPDIRECT3DRMFRAME3 parent)PURE;
+    STDMETHOD(DeleteAnimation)(THIS_ LPDIRECT3DRMANIMATION2 aid) PURE;
+    STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE;
+    STDMETHOD(GetAnimations)(THIS_ LPDIRECT3DRMANIMATIONARRAY *) PURE;
+};
+
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMUserVisual
+
+DECLARE_INTERFACE_(IDirect3DRMUserVisual, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMUserVisual methods
+     */
+    STDMETHOD(Init)(THIS_ D3DRMUSERVISUALCALLBACK fn, void *arg) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMArray
+
+DECLARE_INTERFACE_(IDirect3DRMArray, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    /* No GetElement method as it would get overloaded
+     * in derived classes, and overloading is
+     * a no-no in COM
+     */
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMObjectArray
+
+DECLARE_INTERFACE_(IDirect3DRMObjectArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMOBJECT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMDeviceArray
+
+DECLARE_INTERFACE_(IDirect3DRMDeviceArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMDEVICE *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFrameArray
+
+DECLARE_INTERFACE_(IDirect3DRMFrameArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFRAME *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMViewportArray
+
+DECLARE_INTERFACE_(IDirect3DRMViewportArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVIEWPORT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMVisualArray
+
+DECLARE_INTERFACE_(IDirect3DRMVisualArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimationArray
+
+DECLARE_INTERFACE_(IDirect3DRMAnimationArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMANIMATION2 *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMPickedArray
+
+DECLARE_INTERFACE_(IDirect3DRMPickedArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetPick)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *, LPDIRECT3DRMFRAMEARRAY *, LPD3DRMPICKDESC) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMLightArray
+
+DECLARE_INTERFACE_(IDirect3DRMLightArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMLIGHT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFaceArray
+
+DECLARE_INTERFACE_(IDirect3DRMFaceArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFACE *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMPicked2Array
+
+DECLARE_INTERFACE_(IDirect3DRMPicked2Array, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetPick)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *, LPDIRECT3DRMFRAMEARRAY *, LPD3DRMPICKDESC2) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMInterpolator
+
+DECLARE_INTERFACE_(IDirect3DRMInterpolator, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMInterpolator methods
+     */
+    STDMETHOD(AttachObject)(THIS_ LPDIRECT3DRMOBJECT) PURE;
+    STDMETHOD(GetAttachedObjects)(THIS_ LPDIRECT3DRMOBJECTARRAY *) PURE;
+    STDMETHOD(DetachObject)(THIS_ LPDIRECT3DRMOBJECT) PURE;
+    STDMETHOD(SetIndex)(THIS_ D3DVALUE) PURE;
+    STDMETHOD_(D3DVALUE, GetIndex)(THIS) PURE;
+    STDMETHOD(Interpolate)(THIS_ D3DVALUE, LPDIRECT3DRMOBJECT, D3DRMINTERPOLATIONOPTIONS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMClippedVisual
+
+DECLARE_INTERFACE_(IDirect3DRMClippedVisual, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMClippedVisual methods
+     */
+    STDMETHOD(Init) (THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD(AddPlane) (THIS_ LPDIRECT3DRMFRAME3, LPD3DVECTOR, LPD3DVECTOR, DWORD, LPDWORD) PURE;
+    STDMETHOD(DeletePlane)(THIS_ DWORD, DWORD) PURE;
+    STDMETHOD(GetPlaneIDs)(THIS_ LPDWORD, LPDWORD, DWORD) PURE;
+    STDMETHOD(GetPlane) (THIS_ DWORD, LPDIRECT3DRMFRAME3, LPD3DVECTOR, LPD3DVECTOR, DWORD) PURE;
+    STDMETHOD(SetPlane) (THIS_ DWORD, LPDIRECT3DRMFRAME3, LPD3DVECTOR, LPD3DVECTOR, DWORD) PURE;
+};
+
+#ifdef __cplusplus
+};
+#endif
+#endif /* _D3DRMOBJ_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/d3drmwin.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,50 @@
+/*==========================================================================;
+ *
+ *  Copyright (c) Microsoft Corporation.  All rights reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRMWIN_H__
+#define __D3DRMWIN_H__
+
+#ifndef WIN32
+#define WIN32
+#endif
+
+#include "d3drm.h"
+
+#include "ddraw.h"
+#include "d3d.h"
+
+/*
+ * GUIDS used by Direct3DRM Windows interface
+ */
+DEFINE_GUID(IID_IDirect3DRMWinDevice,   0xc5016cc0, 0xd273, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+
+WIN_TYPES(IDirect3DRMWinDevice, DIRECT3DRMWINDEVICE);
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMWinDevice
+
+DECLARE_INTERFACE_(IDirect3DRMWinDevice, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMWinDevice methods
+     */
+
+    /* Repaint the window with the last frame which was rendered. */
+    STDMETHOD(HandlePaint)(THIS_ HDC hdc) PURE;
+
+    /* Respond to a WM_ACTIVATE message. */
+    STDMETHOD(HandleActivate)(THIS_ WORD wparam) PURE;
+};
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/d3dtypes.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2119 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:   d3dtypes.h
+ *  Content:    Direct3D types include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DTYPES_H_
+#define _D3DTYPES_H_
+
+#ifndef DIRECT3D_VERSION
+#define DIRECT3D_VERSION         0x0700
+#endif
+
+#if (DIRECT3D_VERSION >= 0x0800)
+#pragma message("should not include d3dtypes.h when compiling for DX8 or newer interfaces")
+#endif
+
+#include <windows.h>
+
+#include <float.h>
+#include "ddraw.h"
+
+#pragma warning(disable:4201) // anonymous unions warning
+#if defined(_X86_) || defined(_IA64_)
+#pragma pack(4)
+#endif
+
+
+/* D3DVALUE is the fundamental Direct3D fractional data type */
+
+#define D3DVALP(val, prec) ((float)(val))
+#define D3DVAL(val) ((float)(val))
+
+#ifndef DX_SHARED_DEFINES
+
+/*
+ * This definition is shared with other DirectX components whose header files
+ * might already have defined it. Therefore, we don't define this type if
+ * someone else already has (as indicated by the definition of
+ * DX_SHARED_DEFINES). We don't set DX_SHARED_DEFINES here as there are
+ * other types in this header that are also shared. The last of these
+ * shared defines in this file will set DX_SHARED_DEFINES.
+ */
+typedef float D3DVALUE, *LPD3DVALUE;
+
+#endif /* DX_SHARED_DEFINES */
+
+#define D3DDivide(a, b)    (float)((double) (a) / (double) (b))
+#define D3DMultiply(a, b)    ((a) * (b))
+
+typedef LONG D3DFIXED;
+
+#ifndef RGB_MAKE
+/*
+ * Format of CI colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    alpha      |         color index           |   fraction    |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define CI_GETALPHA(ci)    ((ci) >> 24)
+#define CI_GETINDEX(ci)    (((ci) >> 8) & 0xffff)
+#define CI_GETFRACTION(ci) ((ci) & 0xff)
+#define CI_ROUNDINDEX(ci)  CI_GETINDEX((ci) + 0x80)
+#define CI_MASKALPHA(ci)   ((ci) & 0xffffff)
+#define CI_MAKE(a, i, f)    (((a) << 24) | ((i) << 8) | (f))
+
+/*
+ * Format of RGBA colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    alpha      |      red      |     green     |     blue      |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define RGBA_GETALPHA(rgb)      ((rgb) >> 24)
+#define RGBA_GETRED(rgb)        (((rgb) >> 16) & 0xff)
+#define RGBA_GETGREEN(rgb)      (((rgb) >> 8) & 0xff)
+#define RGBA_GETBLUE(rgb)       ((rgb) & 0xff)
+#define RGBA_MAKE(r, g, b, a)   ((D3DCOLOR) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))
+
+/* D3DRGB and D3DRGBA may be used as initialisers for D3DCOLORs
+ * The float values must be in the range 0..1
+ */
+#define D3DRGB(r, g, b) \
+    (0xff000000L | ( ((long)((r) * 255)) << 16) | (((long)((g) * 255)) << 8) | (long)((b) * 255))
+#define D3DRGBA(r, g, b, a) \
+    (   (((long)((a) * 255)) << 24) | (((long)((r) * 255)) << 16) \
+    |   (((long)((g) * 255)) << 8) | (long)((b) * 255) \
+    )
+
+/*
+ * Format of RGB colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    ignored    |      red      |     green     |     blue      |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define RGB_GETRED(rgb)         (((rgb) >> 16) & 0xff)
+#define RGB_GETGREEN(rgb)       (((rgb) >> 8) & 0xff)
+#define RGB_GETBLUE(rgb)        ((rgb) & 0xff)
+#define RGBA_SETALPHA(rgba, x) (((x) << 24) | ((rgba) & 0x00ffffff))
+#define RGB_MAKE(r, g, b)       ((D3DCOLOR) (((r) << 16) | ((g) << 8) | (b)))
+#define RGBA_TORGB(rgba)       ((D3DCOLOR) ((rgba) & 0xffffff))
+#define RGB_TORGBA(rgb)        ((D3DCOLOR) ((rgb) | 0xff000000))
+
+#endif
+
+/*
+ * Flags for Enumerate functions
+ */
+
+/*
+ * Stop the enumeration
+ */
+#define D3DENUMRET_CANCEL                        DDENUMRET_CANCEL
+
+/*
+ * Continue the enumeration
+ */
+#define D3DENUMRET_OK                            DDENUMRET_OK
+
+typedef HRESULT (CALLBACK* LPD3DVALIDATECALLBACK)(LPVOID lpUserArg, DWORD dwOffset);
+typedef HRESULT (CALLBACK* LPD3DENUMTEXTUREFORMATSCALLBACK)(LPDDSURFACEDESC lpDdsd, LPVOID lpContext);
+typedef HRESULT (CALLBACK* LPD3DENUMPIXELFORMATSCALLBACK)(LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext);
+
+#ifndef DX_SHARED_DEFINES
+
+/*
+ * This definition is shared with other DirectX components whose header files
+ * might already have defined it. Therefore, we don't define this type if
+ * someone else already has (as indicated by the definition of
+ * DX_SHARED_DEFINES). We don't set DX_SHARED_DEFINES here as there are
+ * other types in this header that are also shared. The last of these
+ * shared defines in this file will set DX_SHARED_DEFINES.
+ */
+#ifndef D3DCOLOR_DEFINED
+typedef DWORD D3DCOLOR;
+#define D3DCOLOR_DEFINED
+#endif
+typedef DWORD *LPD3DCOLOR;
+
+#endif /* DX_SHARED_DEFINES */
+
+typedef DWORD D3DMATERIALHANDLE, *LPD3DMATERIALHANDLE;
+typedef DWORD D3DTEXTUREHANDLE, *LPD3DTEXTUREHANDLE;
+typedef DWORD D3DMATRIXHANDLE, *LPD3DMATRIXHANDLE;
+
+#ifndef D3DCOLORVALUE_DEFINED
+typedef struct _D3DCOLORVALUE {
+    union {
+    D3DVALUE r;
+    D3DVALUE dvR;
+    };
+    union {
+    D3DVALUE g;
+    D3DVALUE dvG;
+    };
+    union {
+    D3DVALUE b;
+    D3DVALUE dvB;
+    };
+    union {
+    D3DVALUE a;
+    D3DVALUE dvA;
+    };
+} D3DCOLORVALUE;
+#define D3DCOLORVALUE_DEFINED
+#endif
+typedef struct _D3DCOLORVALUE *LPD3DCOLORVALUE;
+
+#ifndef D3DRECT_DEFINED
+typedef struct _D3DRECT {
+    union {
+    LONG x1;
+    LONG lX1;
+    };
+    union {
+    LONG y1;
+    LONG lY1;
+    };
+    union {
+    LONG x2;
+    LONG lX2;
+    };
+    union {
+    LONG y2;
+    LONG lY2;
+    };
+} D3DRECT;
+#define D3DRECT_DEFINED
+#endif
+typedef struct _D3DRECT *LPD3DRECT;
+
+#ifndef DX_SHARED_DEFINES
+
+/*
+ * This definition is shared with other DirectX components whose header files
+ * might already have defined it. Therefore, we don't define this type if
+ * someone else already has (as indicated by the definition of
+ * DX_SHARED_DEFINES).
+ */
+
+#ifndef D3DVECTOR_DEFINED
+typedef struct _D3DVECTOR {
+    union {
+    D3DVALUE x;
+    D3DVALUE dvX;
+    };
+    union {
+    D3DVALUE y;
+    D3DVALUE dvY;
+    };
+    union {
+    D3DVALUE z;
+    D3DVALUE dvZ;
+    };
+#if(DIRECT3D_VERSION >= 0x0500)
+#if (defined __cplusplus) && (defined D3D_OVERLOADS)
+
+public:
+
+    // =====================================
+    // Constructors
+    // =====================================
+
+    _D3DVECTOR() { }
+    _D3DVECTOR(D3DVALUE f);
+    _D3DVECTOR(D3DVALUE _x, D3DVALUE _y, D3DVALUE _z);
+    _D3DVECTOR(const D3DVALUE f[3]);
+
+    // =====================================
+    // Access grants
+    // =====================================
+
+    const D3DVALUE&operator[](int i) const;
+    D3DVALUE&operator[](int i);
+
+    // =====================================
+    // Assignment operators
+    // =====================================
+
+    _D3DVECTOR& operator += (const _D3DVECTOR& v);
+    _D3DVECTOR& operator -= (const _D3DVECTOR& v);
+    _D3DVECTOR& operator *= (const _D3DVECTOR& v);
+    _D3DVECTOR& operator /= (const _D3DVECTOR& v);
+    _D3DVECTOR& operator *= (D3DVALUE s);
+    _D3DVECTOR& operator /= (D3DVALUE s);
+
+    // =====================================
+    // Unary operators
+    // =====================================
+
+    friend _D3DVECTOR operator + (const _D3DVECTOR& v);
+    friend _D3DVECTOR operator - (const _D3DVECTOR& v);
+
+
+    // =====================================
+    // Binary operators
+    // =====================================
+
+    // Addition and subtraction
+        friend _D3DVECTOR operator + (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+        friend _D3DVECTOR operator - (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+    // Scalar multiplication and division
+        friend _D3DVECTOR operator * (const _D3DVECTOR& v, D3DVALUE s);
+        friend _D3DVECTOR operator * (D3DVALUE s, const _D3DVECTOR& v);
+        friend _D3DVECTOR operator / (const _D3DVECTOR& v, D3DVALUE s);
+    // Memberwise multiplication and division
+        friend _D3DVECTOR operator * (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+        friend _D3DVECTOR operator / (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+
+    // Vector dominance
+        friend int operator < (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+        friend int operator <= (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+
+    // Bitwise equality
+        friend int operator == (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+
+    // Length-related functions
+        friend D3DVALUE SquareMagnitude (const _D3DVECTOR& v);
+        friend D3DVALUE Magnitude (const _D3DVECTOR& v);
+
+    // Returns vector with same direction and unit length
+        friend _D3DVECTOR Normalize (const _D3DVECTOR& v);
+
+    // Return min/max component of the input vector
+        friend D3DVALUE Min (const _D3DVECTOR& v);
+        friend D3DVALUE Max (const _D3DVECTOR& v);
+
+    // Return memberwise min/max of input vectors
+        friend _D3DVECTOR Minimize (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+        friend _D3DVECTOR Maximize (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+
+    // Dot and cross product
+        friend D3DVALUE DotProduct (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+        friend _D3DVECTOR CrossProduct (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
+
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DVECTOR;
+#define D3DVECTOR_DEFINED
+#endif
+typedef struct _D3DVECTOR *LPD3DVECTOR;
+
+/*
+ * As this is the last of the shared defines to be defined we now set
+ * D3D_SHARED_DEFINES to flag that fact that this header has defined these
+ * types.
+ */
+#define DX_SHARED_DEFINES
+
+#endif /* DX_SHARED_DEFINES */
+
+/*
+ * Vertex data types supported in an ExecuteBuffer.
+ */
+
+/*
+ * Homogeneous vertices
+ */
+
+typedef struct _D3DHVERTEX {
+    DWORD           dwFlags;        /* Homogeneous clipping flags */
+    union {
+    D3DVALUE    hx;
+    D3DVALUE    dvHX;
+    };
+    union {
+    D3DVALUE    hy;
+    D3DVALUE    dvHY;
+    };
+    union {
+    D3DVALUE    hz;
+    D3DVALUE    dvHZ;
+    };
+} D3DHVERTEX, *LPD3DHVERTEX;
+
+/*
+ * Transformed/lit vertices
+ */
+typedef struct _D3DTLVERTEX {
+    union {
+    D3DVALUE    sx;             /* Screen coordinates */
+    D3DVALUE    dvSX;
+    };
+    union {
+    D3DVALUE    sy;
+    D3DVALUE    dvSY;
+    };
+    union {
+    D3DVALUE    sz;
+    D3DVALUE    dvSZ;
+    };
+    union {
+    D3DVALUE    rhw;        /* Reciprocal of homogeneous w */
+    D3DVALUE    dvRHW;
+    };
+    union {
+    D3DCOLOR    color;          /* Vertex color */
+    D3DCOLOR    dcColor;
+    };
+    union {
+    D3DCOLOR    specular;       /* Specular component of vertex */
+    D3DCOLOR    dcSpecular;
+    };
+    union {
+    D3DVALUE    tu;             /* Texture coordinates */
+    D3DVALUE    dvTU;
+    };
+    union {
+    D3DVALUE    tv;
+    D3DVALUE    dvTV;
+    };
+#if(DIRECT3D_VERSION >= 0x0500)
+#if (defined __cplusplus) && (defined D3D_OVERLOADS)
+    _D3DTLVERTEX() { }
+    _D3DTLVERTEX(const D3DVECTOR& v, float _rhw,
+                 D3DCOLOR _color, D3DCOLOR _specular,
+                 float _tu, float _tv)
+        { sx = v.x; sy = v.y; sz = v.z; rhw = _rhw;
+          color = _color; specular = _specular;
+          tu = _tu; tv = _tv;
+        }
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DTLVERTEX, *LPD3DTLVERTEX;
+
+/*
+ * Untransformed/lit vertices
+ */
+typedef struct _D3DLVERTEX {
+    union {
+    D3DVALUE     x;             /* Homogeneous coordinates */
+    D3DVALUE     dvX;
+    };
+    union {
+    D3DVALUE     y;
+    D3DVALUE     dvY;
+    };
+    union {
+    D3DVALUE     z;
+    D3DVALUE     dvZ;
+    };
+    DWORD            dwReserved;
+    union {
+    D3DCOLOR     color;         /* Vertex color */
+    D3DCOLOR     dcColor;
+    };
+    union {
+    D3DCOLOR     specular;      /* Specular component of vertex */
+    D3DCOLOR     dcSpecular;
+    };
+    union {
+    D3DVALUE     tu;            /* Texture coordinates */
+    D3DVALUE     dvTU;
+    };
+    union {
+    D3DVALUE     tv;
+    D3DVALUE     dvTV;
+    };
+#if(DIRECT3D_VERSION >= 0x0500)
+#if (defined __cplusplus) && (defined D3D_OVERLOADS)
+    _D3DLVERTEX() { }
+    _D3DLVERTEX(const D3DVECTOR& v,
+                D3DCOLOR _color, D3DCOLOR _specular,
+                float _tu, float _tv)
+        { x = v.x; y = v.y; z = v.z; dwReserved = 0;
+          color = _color; specular = _specular;
+          tu = _tu; tv = _tv;
+        }
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DLVERTEX, *LPD3DLVERTEX;
+
+/*
+ * Untransformed/unlit vertices
+ */
+
+typedef struct _D3DVERTEX {
+    union {
+    D3DVALUE     x;             /* Homogeneous coordinates */
+    D3DVALUE     dvX;
+    };
+    union {
+    D3DVALUE     y;
+    D3DVALUE     dvY;
+    };
+    union {
+    D3DVALUE     z;
+    D3DVALUE     dvZ;
+    };
+    union {
+    D3DVALUE     nx;            /* Normal */
+    D3DVALUE     dvNX;
+    };
+    union {
+    D3DVALUE     ny;
+    D3DVALUE     dvNY;
+    };
+    union {
+    D3DVALUE     nz;
+    D3DVALUE     dvNZ;
+    };
+    union {
+    D3DVALUE     tu;            /* Texture coordinates */
+    D3DVALUE     dvTU;
+    };
+    union {
+    D3DVALUE     tv;
+    D3DVALUE     dvTV;
+    };
+#if(DIRECT3D_VERSION >= 0x0500)
+#if (defined __cplusplus) && (defined D3D_OVERLOADS)
+    _D3DVERTEX() { }
+    _D3DVERTEX(const D3DVECTOR& v, const D3DVECTOR& n, float _tu, float _tv)
+        { x = v.x; y = v.y; z = v.z;
+          nx = n.x; ny = n.y; nz = n.z;
+          tu = _tu; tv = _tv;
+        }
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DVERTEX, *LPD3DVERTEX;
+
+
+/*
+ * Matrix, OldViewport, and tranformation structures and definitions.
+ */
+
+#ifndef D3DMATRIX_DEFINED
+typedef struct _D3DMATRIX {
+#if(DIRECT3D_VERSION >= 0x0500)
+#if (defined __cplusplus) && (defined D3D_OVERLOADS)
+    union {
+        struct {
+#endif
+
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+            D3DVALUE        _11, _12, _13, _14;
+            D3DVALUE        _21, _22, _23, _24;
+            D3DVALUE        _31, _32, _33, _34;
+            D3DVALUE        _41, _42, _43, _44;
+
+#if(DIRECT3D_VERSION >= 0x0500)
+#if (defined __cplusplus) && (defined D3D_OVERLOADS)
+        };
+        D3DVALUE m[4][4];
+    };
+    _D3DMATRIX() { }
+    _D3DMATRIX( D3DVALUE _m00, D3DVALUE _m01, D3DVALUE _m02, D3DVALUE _m03,
+                D3DVALUE _m10, D3DVALUE _m11, D3DVALUE _m12, D3DVALUE _m13,
+                D3DVALUE _m20, D3DVALUE _m21, D3DVALUE _m22, D3DVALUE _m23,
+                D3DVALUE _m30, D3DVALUE _m31, D3DVALUE _m32, D3DVALUE _m33
+        )
+        {
+                m[0][0] = _m00; m[0][1] = _m01; m[0][2] = _m02; m[0][3] = _m03;
+                m[1][0] = _m10; m[1][1] = _m11; m[1][2] = _m12; m[1][3] = _m13;
+                m[2][0] = _m20; m[2][1] = _m21; m[2][2] = _m22; m[2][3] = _m23;
+                m[3][0] = _m30; m[3][1] = _m31; m[3][2] = _m32; m[3][3] = _m33;
+        }
+
+    D3DVALUE& operator()(int iRow, int iColumn) { return m[iRow][iColumn]; }
+    const D3DVALUE& operator()(int iRow, int iColumn) const { return m[iRow][iColumn]; }
+#if(DIRECT3D_VERSION >= 0x0600)
+    friend _D3DMATRIX operator* (const _D3DMATRIX&, const _D3DMATRIX&);
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#endif
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DMATRIX;
+#define D3DMATRIX_DEFINED
+#endif
+typedef struct _D3DMATRIX *LPD3DMATRIX;
+
+#if (defined __cplusplus) && (defined D3D_OVERLOADS)
+#include "d3dvec.inl"
+#endif
+
+typedef struct _D3DVIEWPORT {
+    DWORD       dwSize;
+    DWORD       dwX;
+    DWORD       dwY;        /* Top left */
+    DWORD       dwWidth;
+    DWORD       dwHeight;   /* Dimensions */
+    D3DVALUE    dvScaleX;   /* Scale homogeneous to screen */
+    D3DVALUE    dvScaleY;   /* Scale homogeneous to screen */
+    D3DVALUE    dvMaxX;     /* Min/max homogeneous x coord */
+    D3DVALUE    dvMaxY;     /* Min/max homogeneous y coord */
+    D3DVALUE    dvMinZ;
+    D3DVALUE    dvMaxZ;     /* Min/max homogeneous z coord */
+} D3DVIEWPORT, *LPD3DVIEWPORT;
+
+#if(DIRECT3D_VERSION >= 0x0500)
+typedef struct _D3DVIEWPORT2 {
+    DWORD       dwSize;
+    DWORD       dwX;
+    DWORD       dwY;        /* OldViewport Top left */
+    DWORD       dwWidth;
+    DWORD       dwHeight;   /* OldViewport Dimensions */
+    D3DVALUE    dvClipX;        /* Top left of clip volume */
+    D3DVALUE    dvClipY;
+    D3DVALUE    dvClipWidth;    /* Clip Volume Dimensions */
+    D3DVALUE    dvClipHeight;
+    D3DVALUE    dvMinZ;         /* Min/max of clip Volume */
+    D3DVALUE    dvMaxZ;
+} D3DVIEWPORT2, *LPD3DVIEWPORT2;
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+typedef struct _D3DVIEWPORT7 {
+    DWORD       dwX;
+    DWORD       dwY;            /* OldViewport Top left */
+    DWORD       dwWidth;
+    DWORD       dwHeight;       /* OldViewport Dimensions */
+    D3DVALUE    dvMinZ;         /* Min/max of clip Volume */
+    D3DVALUE    dvMaxZ;
+} D3DVIEWPORT7, *LPD3DVIEWPORT7;
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+/*
+ * Values for clip fields.
+ */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+
+// Max number of user clipping planes, supported in D3D.
+#define D3DMAXUSERCLIPPLANES 32
+
+// These bits could be ORed together to use with D3DRENDERSTATE_CLIPPLANEENABLE
+//
+#define D3DCLIPPLANE0 (1 << 0)
+#define D3DCLIPPLANE1 (1 << 1)
+#define D3DCLIPPLANE2 (1 << 2)
+#define D3DCLIPPLANE3 (1 << 3)
+#define D3DCLIPPLANE4 (1 << 4)
+#define D3DCLIPPLANE5 (1 << 5)
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#define D3DCLIP_LEFT                0x00000001L
+#define D3DCLIP_RIGHT               0x00000002L
+#define D3DCLIP_TOP             0x00000004L
+#define D3DCLIP_BOTTOM              0x00000008L
+#define D3DCLIP_FRONT               0x00000010L
+#define D3DCLIP_BACK                0x00000020L
+#define D3DCLIP_GEN0                0x00000040L
+#define D3DCLIP_GEN1                0x00000080L
+#define D3DCLIP_GEN2                0x00000100L
+#define D3DCLIP_GEN3                0x00000200L
+#define D3DCLIP_GEN4                0x00000400L
+#define D3DCLIP_GEN5                0x00000800L
+
+/*
+ * Values for d3d status.
+ */
+#define D3DSTATUS_CLIPUNIONLEFT         D3DCLIP_LEFT
+#define D3DSTATUS_CLIPUNIONRIGHT        D3DCLIP_RIGHT
+#define D3DSTATUS_CLIPUNIONTOP          D3DCLIP_TOP
+#define D3DSTATUS_CLIPUNIONBOTTOM       D3DCLIP_BOTTOM
+#define D3DSTATUS_CLIPUNIONFRONT        D3DCLIP_FRONT
+#define D3DSTATUS_CLIPUNIONBACK         D3DCLIP_BACK
+#define D3DSTATUS_CLIPUNIONGEN0         D3DCLIP_GEN0
+#define D3DSTATUS_CLIPUNIONGEN1         D3DCLIP_GEN1
+#define D3DSTATUS_CLIPUNIONGEN2         D3DCLIP_GEN2
+#define D3DSTATUS_CLIPUNIONGEN3         D3DCLIP_GEN3
+#define D3DSTATUS_CLIPUNIONGEN4         D3DCLIP_GEN4
+#define D3DSTATUS_CLIPUNIONGEN5         D3DCLIP_GEN5
+
+#define D3DSTATUS_CLIPINTERSECTIONLEFT      0x00001000L
+#define D3DSTATUS_CLIPINTERSECTIONRIGHT     0x00002000L
+#define D3DSTATUS_CLIPINTERSECTIONTOP       0x00004000L
+#define D3DSTATUS_CLIPINTERSECTIONBOTTOM    0x00008000L
+#define D3DSTATUS_CLIPINTERSECTIONFRONT     0x00010000L
+#define D3DSTATUS_CLIPINTERSECTIONBACK      0x00020000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN0      0x00040000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN1      0x00080000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN2      0x00100000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN3      0x00200000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN4      0x00400000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN5      0x00800000L
+#define D3DSTATUS_ZNOTVISIBLE               0x01000000L
+/* Do not use 0x80000000 for any status flags in future as it is reserved */
+
+#define D3DSTATUS_CLIPUNIONALL  (       \
+        D3DSTATUS_CLIPUNIONLEFT |   \
+        D3DSTATUS_CLIPUNIONRIGHT    |   \
+        D3DSTATUS_CLIPUNIONTOP  |   \
+        D3DSTATUS_CLIPUNIONBOTTOM   |   \
+        D3DSTATUS_CLIPUNIONFRONT    |   \
+        D3DSTATUS_CLIPUNIONBACK |   \
+        D3DSTATUS_CLIPUNIONGEN0 |   \
+        D3DSTATUS_CLIPUNIONGEN1 |   \
+        D3DSTATUS_CLIPUNIONGEN2 |   \
+        D3DSTATUS_CLIPUNIONGEN3 |   \
+        D3DSTATUS_CLIPUNIONGEN4 |   \
+        D3DSTATUS_CLIPUNIONGEN5     \
+        )
+
+#define D3DSTATUS_CLIPINTERSECTIONALL   (       \
+        D3DSTATUS_CLIPINTERSECTIONLEFT  |   \
+        D3DSTATUS_CLIPINTERSECTIONRIGHT |   \
+        D3DSTATUS_CLIPINTERSECTIONTOP   |   \
+        D3DSTATUS_CLIPINTERSECTIONBOTTOM    |   \
+        D3DSTATUS_CLIPINTERSECTIONFRONT |   \
+        D3DSTATUS_CLIPINTERSECTIONBACK  |   \
+        D3DSTATUS_CLIPINTERSECTIONGEN0  |   \
+        D3DSTATUS_CLIPINTERSECTIONGEN1  |   \
+        D3DSTATUS_CLIPINTERSECTIONGEN2  |   \
+        D3DSTATUS_CLIPINTERSECTIONGEN3  |   \
+        D3DSTATUS_CLIPINTERSECTIONGEN4  |   \
+        D3DSTATUS_CLIPINTERSECTIONGEN5      \
+        )
+
+#define D3DSTATUS_DEFAULT   (           \
+        D3DSTATUS_CLIPINTERSECTIONALL   |   \
+        D3DSTATUS_ZNOTVISIBLE)
+
+
+/*
+ * Options for direct transform calls
+ */
+#define D3DTRANSFORM_CLIPPED       0x00000001l
+#define D3DTRANSFORM_UNCLIPPED     0x00000002l
+
+typedef struct _D3DTRANSFORMDATA {
+    DWORD           dwSize;
+    LPVOID      lpIn;           /* Input vertices */
+    DWORD           dwInSize;       /* Stride of input vertices */
+    LPVOID      lpOut;          /* Output vertices */
+    DWORD           dwOutSize;      /* Stride of output vertices */
+    LPD3DHVERTEX    lpHOut;         /* Output homogeneous vertices */
+    DWORD           dwClip;         /* Clipping hint */
+    DWORD           dwClipIntersection;
+    DWORD           dwClipUnion;    /* Union of all clip flags */
+    D3DRECT         drExtent;       /* Extent of transformed vertices */
+} D3DTRANSFORMDATA, *LPD3DTRANSFORMDATA;
+
+/*
+ * Structure defining position and direction properties for lighting.
+ */
+typedef struct _D3DLIGHTINGELEMENT {
+    D3DVECTOR dvPosition;           /* Lightable point in model space */
+    D3DVECTOR dvNormal;             /* Normalised unit vector */
+} D3DLIGHTINGELEMENT, *LPD3DLIGHTINGELEMENT;
+
+/*
+ * Structure defining material properties for lighting.
+ */
+typedef struct _D3DMATERIAL {
+    DWORD           dwSize;
+    union {
+    D3DCOLORVALUE   diffuse;        /* Diffuse color RGBA */
+    D3DCOLORVALUE   dcvDiffuse;
+    };
+    union {
+    D3DCOLORVALUE   ambient;        /* Ambient color RGB */
+    D3DCOLORVALUE   dcvAmbient;
+    };
+    union {
+    D3DCOLORVALUE   specular;       /* Specular 'shininess' */
+    D3DCOLORVALUE   dcvSpecular;
+    };
+    union {
+    D3DCOLORVALUE   emissive;       /* Emissive color RGB */
+    D3DCOLORVALUE   dcvEmissive;
+    };
+    union {
+    D3DVALUE        power;          /* Sharpness if specular highlight */
+    D3DVALUE        dvPower;
+    };
+    D3DTEXTUREHANDLE    hTexture;       /* Handle to texture map */
+    DWORD           dwRampSize;
+} D3DMATERIAL, *LPD3DMATERIAL;
+
+#if(DIRECT3D_VERSION >= 0x0700)
+
+typedef struct _D3DMATERIAL7 {
+    union {
+    D3DCOLORVALUE   diffuse;        /* Diffuse color RGBA */
+    D3DCOLORVALUE   dcvDiffuse;
+    };
+    union {
+    D3DCOLORVALUE   ambient;        /* Ambient color RGB */
+    D3DCOLORVALUE   dcvAmbient;
+    };
+    union {
+    D3DCOLORVALUE   specular;       /* Specular 'shininess' */
+    D3DCOLORVALUE   dcvSpecular;
+    };
+    union {
+    D3DCOLORVALUE   emissive;       /* Emissive color RGB */
+    D3DCOLORVALUE   dcvEmissive;
+    };
+    union {
+    D3DVALUE        power;          /* Sharpness if specular highlight */
+    D3DVALUE        dvPower;
+    };
+} D3DMATERIAL7, *LPD3DMATERIAL7;
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DLIGHTTYPE {
+    D3DLIGHT_POINT          = 1,
+    D3DLIGHT_SPOT           = 2,
+    D3DLIGHT_DIRECTIONAL    = 3,
+// Note: The following light type (D3DLIGHT_PARALLELPOINT)
+// is no longer supported from D3D for DX7 onwards.
+    D3DLIGHT_PARALLELPOINT  = 4,
+#if(DIRECT3D_VERSION < 0x0500) // For backward compatible headers
+    D3DLIGHT_GLSPOT         = 5,
+#endif
+    D3DLIGHT_FORCEuint    = 0x7fffffff, /* force 32-bit size enum */
+} D3DLIGHTTYPE;
+
+#else
+typedef enum _D3DLIGHTTYPE D3DLIGHTTYPE;
+#define D3DLIGHT_PARALLELPOINT  (D3DLIGHTTYPE)4
+#define D3DLIGHT_GLSPOT         (D3DLIGHTTYPE)5
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+/*
+ * Structure defining a light source and its properties.
+ */
+typedef struct _D3DLIGHT {
+    DWORD           dwSize;
+    D3DLIGHTTYPE    dltType;            /* Type of light source */
+    D3DCOLORVALUE   dcvColor;           /* Color of light */
+    D3DVECTOR       dvPosition;         /* Position in world space */
+    D3DVECTOR       dvDirection;        /* Direction in world space */
+    D3DVALUE        dvRange;            /* Cutoff range */
+    D3DVALUE        dvFalloff;          /* Falloff */
+    D3DVALUE        dvAttenuation0;     /* Constant attenuation */
+    D3DVALUE        dvAttenuation1;     /* Linear attenuation */
+    D3DVALUE        dvAttenuation2;     /* Quadratic attenuation */
+    D3DVALUE        dvTheta;            /* Inner angle of spotlight cone */
+    D3DVALUE        dvPhi;              /* Outer angle of spotlight cone */
+} D3DLIGHT, *LPD3DLIGHT;
+
+#if(DIRECT3D_VERSION >= 0x0700)
+
+typedef struct _D3DLIGHT7 {
+    D3DLIGHTTYPE    dltType;            /* Type of light source */
+    D3DCOLORVALUE   dcvDiffuse;         /* Diffuse color of light */
+    D3DCOLORVALUE   dcvSpecular;        /* Specular color of light */
+    D3DCOLORVALUE   dcvAmbient;         /* Ambient color of light */
+    D3DVECTOR       dvPosition;         /* Position in world space */
+    D3DVECTOR       dvDirection;        /* Direction in world space */
+    D3DVALUE        dvRange;            /* Cutoff range */
+    D3DVALUE        dvFalloff;          /* Falloff */
+    D3DVALUE        dvAttenuation0;     /* Constant attenuation */
+    D3DVALUE        dvAttenuation1;     /* Linear attenuation */
+    D3DVALUE        dvAttenuation2;     /* Quadratic attenuation */
+    D3DVALUE        dvTheta;            /* Inner angle of spotlight cone */
+    D3DVALUE        dvPhi;              /* Outer angle of spotlight cone */
+} D3DLIGHT7, *LPD3DLIGHT7;
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#if(DIRECT3D_VERSION >= 0x0500)
+/*
+ * Structure defining a light source and its properties.
+ */
+
+/* flags bits */
+#define D3DLIGHT_ACTIVE         0x00000001
+#define D3DLIGHT_NO_SPECULAR    0x00000002
+#define D3DLIGHT_ALL (D3DLIGHT_ACTIVE | D3DLIGHT_NO_SPECULAR)
+
+/* maximum valid light range */
+#define D3DLIGHT_RANGE_MAX      ((float)sqrt(FLT_MAX))
+
+typedef struct _D3DLIGHT2 {
+    DWORD           dwSize;
+    D3DLIGHTTYPE    dltType;        /* Type of light source */
+    D3DCOLORVALUE   dcvColor;       /* Color of light */
+    D3DVECTOR       dvPosition;     /* Position in world space */
+    D3DVECTOR       dvDirection;    /* Direction in world space */
+    D3DVALUE        dvRange;        /* Cutoff range */
+    D3DVALUE        dvFalloff;      /* Falloff */
+    D3DVALUE        dvAttenuation0; /* Constant attenuation */
+    D3DVALUE        dvAttenuation1; /* Linear attenuation */
+    D3DVALUE        dvAttenuation2; /* Quadratic attenuation */
+    D3DVALUE        dvTheta;        /* Inner angle of spotlight cone */
+    D3DVALUE        dvPhi;          /* Outer angle of spotlight cone */
+    DWORD           dwFlags;
+} D3DLIGHT2, *LPD3DLIGHT2;
+
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+typedef struct _D3DLIGHTDATA {
+    DWORD                dwSize;
+    LPD3DLIGHTINGELEMENT lpIn;      /* Input positions and normals */
+    DWORD                dwInSize;  /* Stride of input elements */
+    LPD3DTLVERTEX        lpOut;     /* Output colors */
+    DWORD                dwOutSize; /* Stride of output colors */
+} D3DLIGHTDATA, *LPD3DLIGHTDATA;
+
+#if(DIRECT3D_VERSION >= 0x0500)
+/*
+ * Before DX5, these values were in an enum called
+ * D3DCOLORMODEL. This was not correct, since they are
+ * bit flags. A driver can surface either or both flags
+ * in the dcmColorModel member of D3DDEVICEDESC.
+ */
+#define D3DCOLOR_MONO   1
+#define D3DCOLOR_RGB    2
+
+typedef DWORD D3DCOLORMODEL;
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+/*
+ * Options for clearing
+ */
+#define D3DCLEAR_TARGET            0x00000001l  /* Clear target surface */
+#define D3DCLEAR_ZBUFFER           0x00000002l  /* Clear target z buffer */
+#if(DIRECT3D_VERSION >= 0x0600)
+#define D3DCLEAR_STENCIL           0x00000004l  /* Clear stencil planes */
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+/*
+ * Execute buffers are allocated via Direct3D.  These buffers may then
+ * be filled by the application with instructions to execute along with
+ * vertex data.
+ */
+
+/*
+ * Supported op codes for execute instructions.
+ */
+typedef enum _D3DOPCODE {
+    D3DOP_POINT                 = 1,
+    D3DOP_LINE                  = 2,
+    D3DOP_TRIANGLE      = 3,
+    D3DOP_MATRIXLOAD        = 4,
+    D3DOP_MATRIXMULTIPLY    = 5,
+    D3DOP_STATETRANSFORM        = 6,
+    D3DOP_STATELIGHT        = 7,
+    D3DOP_STATERENDER       = 8,
+    D3DOP_PROCESSVERTICES       = 9,
+    D3DOP_TEXTURELOAD       = 10,
+    D3DOP_EXIT                  = 11,
+    D3DOP_BRANCHFORWARD     = 12,
+    D3DOP_SPAN          = 13,
+    D3DOP_SETSTATUS     = 14,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DOP_FORCEuint           = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DOPCODE;
+
+typedef struct _D3DINSTRUCTION {
+    BYTE bOpcode;   /* Instruction opcode */
+    BYTE bSize;     /* Size of each instruction data unit */
+    WORD wCount;    /* Count of instruction data units to follow */
+} D3DINSTRUCTION, *LPD3DINSTRUCTION;
+
+/*
+ * Structure for texture loads
+ */
+typedef struct _D3DTEXTURELOAD {
+    D3DTEXTUREHANDLE hDestTexture;
+    D3DTEXTUREHANDLE hSrcTexture;
+} D3DTEXTURELOAD, *LPD3DTEXTURELOAD;
+
+/*
+ * Structure for picking
+ */
+typedef struct _D3DPICKRECORD {
+    BYTE     bOpcode;
+    BYTE     bPad;
+    DWORD    dwOffset;
+    D3DVALUE dvZ;
+} D3DPICKRECORD, *LPD3DPICKRECORD;
+
+/*
+ * The following defines the rendering states which can be set in the
+ * execute buffer.
+ */
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DSHADEMODE {
+    D3DSHADE_FLAT              = 1,
+    D3DSHADE_GOURAUD           = 2,
+    D3DSHADE_PHONG             = 3,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DSHADE_FORCEuint       = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DSHADEMODE;
+
+typedef enum _D3DFILLMODE {
+    D3DFILL_POINT          = 1,
+    D3DFILL_WIREFRAME          = 2,
+    D3DFILL_SOLID          = 3,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DFILL_FORCEuint        = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DFILLMODE;
+
+typedef struct _D3DLINEPATTERN {
+    WORD    wRepeatFactor;
+    WORD    wLinePattern;
+} D3DLINEPATTERN;
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DTEXTUREFILTER {
+    D3DFILTER_NEAREST          = 1,
+    D3DFILTER_LINEAR           = 2,
+    D3DFILTER_MIPNEAREST       = 3,
+    D3DFILTER_MIPLINEAR        = 4,
+    D3DFILTER_LINEARMIPNEAREST = 5,
+    D3DFILTER_LINEARMIPLINEAR  = 6,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DFILTER_FORCEuint      = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DTEXTUREFILTER;
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DBLEND {
+    D3DBLEND_ZERO              = 1,
+    D3DBLEND_ONE               = 2,
+    D3DBLEND_SRCCOLOR          = 3,
+    D3DBLEND_INVSRCCOLOR       = 4,
+    D3DBLEND_SRCALPHA          = 5,
+    D3DBLEND_INVSRCALPHA       = 6,
+    D3DBLEND_DESTALPHA         = 7,
+    D3DBLEND_INVDESTALPHA      = 8,
+    D3DBLEND_DESTCOLOR         = 9,
+    D3DBLEND_INVDESTCOLOR      = 10,
+    D3DBLEND_SRCALPHASAT       = 11,
+    D3DBLEND_BOTHSRCALPHA      = 12,
+    D3DBLEND_BOTHINVSRCALPHA   = 13,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DBLEND_FORCEuint       = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DBLEND;
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DTEXTUREBLEND {
+    D3DTBLEND_DECAL            = 1,
+    D3DTBLEND_MODULATE         = 2,
+    D3DTBLEND_DECALALPHA       = 3,
+    D3DTBLEND_MODULATEALPHA    = 4,
+    D3DTBLEND_DECALMASK        = 5,
+    D3DTBLEND_MODULATEMASK     = 6,
+    D3DTBLEND_COPY             = 7,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DTBLEND_ADD              = 8,
+    D3DTBLEND_FORCEuint      = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DTEXTUREBLEND;
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DTEXTUREADDRESS {
+    D3DTADDRESS_WRAP           = 1,
+    D3DTADDRESS_MIRROR         = 2,
+    D3DTADDRESS_CLAMP          = 3,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DTADDRESS_BORDER         = 4,
+    D3DTADDRESS_FORCEuint    = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DTEXTUREADDRESS;
+
+typedef enum _D3DCULL {
+    D3DCULL_NONE               = 1,
+    D3DCULL_CW                 = 2,
+    D3DCULL_CCW                = 3,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DCULL_FORCEuint        = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DCULL;
+
+typedef enum _D3DCMPFUNC {
+    D3DCMP_NEVER               = 1,
+    D3DCMP_LESS                = 2,
+    D3DCMP_EQUAL               = 3,
+    D3DCMP_LESSEQUAL           = 4,
+    D3DCMP_GREATER             = 5,
+    D3DCMP_NOTEQUAL            = 6,
+    D3DCMP_GREATEREQUAL        = 7,
+    D3DCMP_ALWAYS              = 8,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DCMP_FORCEuint         = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DCMPFUNC;
+
+#if(DIRECT3D_VERSION >= 0x0600)
+typedef enum _D3DSTENCILOP {
+    D3DSTENCILOP_KEEP           = 1,
+    D3DSTENCILOP_ZERO           = 2,
+    D3DSTENCILOP_REPLACE        = 3,
+    D3DSTENCILOP_INCRSAT        = 4,
+    D3DSTENCILOP_DECRSAT        = 5,
+    D3DSTENCILOP_INVERT         = 6,
+    D3DSTENCILOP_INCR           = 7,
+    D3DSTENCILOP_DECR           = 8,
+    D3DSTENCILOP_FORCEuint    = 0x7fffffff, /* force 32-bit size enum */
+} D3DSTENCILOP;
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+typedef enum _D3DFOGMODE {
+    D3DFOG_NONE                = 0,
+    D3DFOG_EXP                 = 1,
+    D3DFOG_EXP2                = 2,
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DFOG_LINEAR              = 3,
+    D3DFOG_FORCEuint         = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DFOGMODE;
+
+#if(DIRECT3D_VERSION >= 0x0600)
+typedef enum _D3DZBUFFERTYPE {
+    D3DZB_FALSE                 = 0,
+    D3DZB_TRUE                  = 1, // Z buffering
+    D3DZB_USEW                  = 2, // W buffering
+    D3DZB_FORCEuint           = 0x7fffffff, /* force 32-bit size enum */
+} D3DZBUFFERTYPE;
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+#if(DIRECT3D_VERSION >= 0x0500)
+typedef enum _D3DANTIALIASMODE {
+    D3DANTIALIAS_NONE          = 0,
+    D3DANTIALIAS_SORTDEPENDENT = 1,
+    D3DANTIALIAS_SORTINDEPENDENT = 2,
+    D3DANTIALIAS_FORCEuint   = 0x7fffffff, /* force 32-bit size enum */
+} D3DANTIALIASMODE;
+
+// Vertex types supported by Direct3D
+typedef enum _D3DVERTEXTYPE {
+    D3DVT_VERTEX        = 1,
+    D3DVT_LVERTEX       = 2,
+    D3DVT_TLVERTEX      = 3,
+    D3DVT_FORCEuint   = 0x7fffffff, /* force 32-bit size enum */
+} D3DVERTEXTYPE;
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+// Primitives supported by draw-primitive API
+typedef enum _D3DPRIMITIVETYPE {
+    D3DPT_POINTLIST     = 1,
+    D3DPT_LINELIST      = 2,
+    D3DPT_LINESTRIP     = 3,
+    D3DPT_TRIANGLELIST  = 4,
+    D3DPT_TRIANGLESTRIP = 5,
+    D3DPT_TRIANGLEFAN   = 6,
+    D3DPT_FORCEuint   = 0x7fffffff, /* force 32-bit size enum */
+} D3DPRIMITIVETYPE;
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+/*
+ * Amount to add to a state to generate the override for that state.
+ */
+#define D3DSTATE_OVERRIDE_BIAS      256
+
+/*
+ * A state which sets the override flag for the specified state type.
+ */
+#define D3DSTATE_OVERRIDE(type) (D3DRENDERSTATETYPE)(((DWORD) (type) + D3DSTATE_OVERRIDE_BIAS))
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DTRANSFORMSTATETYPE {
+    D3DTRANSFORMSTATE_WORLD         = 1,
+    D3DTRANSFORMSTATE_VIEW          = 2,
+    D3DTRANSFORMSTATE_PROJECTION    = 3,
+#if(DIRECT3D_VERSION >= 0x0700)
+    D3DTRANSFORMSTATE_WORLD1        = 4,  // 2nd matrix to blend
+    D3DTRANSFORMSTATE_WORLD2        = 5,  // 3rd matrix to blend
+    D3DTRANSFORMSTATE_WORLD3        = 6,  // 4th matrix to blend
+    D3DTRANSFORMSTATE_TEXTURE0      = 16,
+    D3DTRANSFORMSTATE_TEXTURE1      = 17,
+    D3DTRANSFORMSTATE_TEXTURE2      = 18,
+    D3DTRANSFORMSTATE_TEXTURE3      = 19,
+    D3DTRANSFORMSTATE_TEXTURE4      = 20,
+    D3DTRANSFORMSTATE_TEXTURE5      = 21,
+    D3DTRANSFORMSTATE_TEXTURE6      = 22,
+    D3DTRANSFORMSTATE_TEXTURE7      = 23,
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DTRANSFORMSTATE_FORCEuint     = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DTRANSFORMSTATETYPE;
+
+#else
+
+//
+// legacy transform state names
+//
+typedef enum _D3DTRANSFORMSTATETYPE D3DTRANSFORMSTATETYPE;
+#define D3DTRANSFORMSTATE_WORLD         (D3DTRANSFORMSTATETYPE)1
+#define D3DTRANSFORMSTATE_VIEW          (D3DTRANSFORMSTATETYPE)2
+#define D3DTRANSFORMSTATE_PROJECTION    (D3DTRANSFORMSTATETYPE)3
+#define D3DTRANSFORMSTATE_WORLD1        (D3DTRANSFORMSTATETYPE)4
+#define D3DTRANSFORMSTATE_WORLD2        (D3DTRANSFORMSTATETYPE)5
+#define D3DTRANSFORMSTATE_WORLD3        (D3DTRANSFORMSTATETYPE)6
+#define D3DTRANSFORMSTATE_TEXTURE0      (D3DTRANSFORMSTATETYPE)16
+#define D3DTRANSFORMSTATE_TEXTURE1      (D3DTRANSFORMSTATETYPE)17
+#define D3DTRANSFORMSTATE_TEXTURE2      (D3DTRANSFORMSTATETYPE)18
+#define D3DTRANSFORMSTATE_TEXTURE3      (D3DTRANSFORMSTATETYPE)19
+#define D3DTRANSFORMSTATE_TEXTURE4      (D3DTRANSFORMSTATETYPE)20
+#define D3DTRANSFORMSTATE_TEXTURE5      (D3DTRANSFORMSTATETYPE)21
+#define D3DTRANSFORMSTATE_TEXTURE6      (D3DTRANSFORMSTATETYPE)22
+#define D3DTRANSFORMSTATE_TEXTURE7      (D3DTRANSFORMSTATETYPE)23
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DLIGHTSTATETYPE {
+    D3DLIGHTSTATE_MATERIAL          = 1,
+    D3DLIGHTSTATE_AMBIENT           = 2,
+    D3DLIGHTSTATE_COLORMODEL        = 3,
+    D3DLIGHTSTATE_FOGMODE           = 4,
+    D3DLIGHTSTATE_FOGSTART          = 5,
+    D3DLIGHTSTATE_FOGEND            = 6,
+    D3DLIGHTSTATE_FOGDENSITY        = 7,
+#if(DIRECT3D_VERSION >= 0x0600)
+    D3DLIGHTSTATE_COLORVERTEX       = 8,
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DLIGHTSTATE_FORCEuint         = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DLIGHTSTATETYPE;
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+typedef enum _D3DRENDERSTATETYPE {
+    D3DRENDERSTATE_ANTIALIAS          = 2,    /* D3DANTIALIASMODE */
+    D3DRENDERSTATE_TEXTUREPERSPECTIVE = 4,    /* TRUE for perspective correction */
+    D3DRENDERSTATE_ZENABLE            = 7,    /* D3DZBUFFERTYPE (or TRUE/FALSE for legacy) */
+    D3DRENDERSTATE_FILLMODE           = 8,    /* D3DFILL_MODE        */
+    D3DRENDERSTATE_SHADEMODE          = 9,    /* D3DSHADEMODE */
+    D3DRENDERSTATE_LINEPATTERN        = 10,   /* D3DLINEPATTERN */
+    D3DRENDERSTATE_ZWRITEENABLE       = 14,   /* TRUE to enable z writes */
+    D3DRENDERSTATE_ALPHATESTENABLE    = 15,   /* TRUE to enable alpha tests */
+    D3DRENDERSTATE_LASTPIXEL          = 16,   /* TRUE for last-pixel on lines */
+    D3DRENDERSTATE_SRCBLEND           = 19,   /* D3DBLEND */
+    D3DRENDERSTATE_DESTBLEND          = 20,   /* D3DBLEND */
+    D3DRENDERSTATE_CULLMODE           = 22,   /* D3DCULL */
+    D3DRENDERSTATE_ZFUNC              = 23,   /* D3DCMPFUNC */
+    D3DRENDERSTATE_ALPHAREF           = 24,   /* D3DFIXED */
+    D3DRENDERSTATE_ALPHAFUNC          = 25,   /* D3DCMPFUNC */
+    D3DRENDERSTATE_DITHERENABLE       = 26,   /* TRUE to enable dithering */
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DRENDERSTATE_ALPHABLENDENABLE   = 27,   /* TRUE to enable alpha blending */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+    D3DRENDERSTATE_FOGENABLE          = 28,   /* TRUE to enable fog blending */
+    D3DRENDERSTATE_SPECULARENABLE     = 29,   /* TRUE to enable specular */
+    D3DRENDERSTATE_ZVISIBLE           = 30,   /* TRUE to enable z checking */
+    D3DRENDERSTATE_STIPPLEDALPHA      = 33,   /* TRUE to enable stippled alpha (RGB device only) */
+    D3DRENDERSTATE_FOGCOLOR           = 34,   /* D3DCOLOR */
+    D3DRENDERSTATE_FOGTABLEMODE       = 35,   /* D3DFOGMODE */
+#if(DIRECT3D_VERSION >= 0x0700)
+    D3DRENDERSTATE_FOGSTART           = 36,   /* Fog start (for both vertex and pixel fog) */
+    D3DRENDERSTATE_FOGEND             = 37,   /* Fog end      */
+    D3DRENDERSTATE_FOGDENSITY         = 38,   /* Fog density  */
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DRENDERSTATE_EDGEANTIALIAS      = 40,   /* TRUE to enable edge antialiasing */
+    D3DRENDERSTATE_COLORKEYENABLE     = 41,   /* TRUE to enable source colorkeyed textures */
+    D3DRENDERSTATE_ZBIAS              = 47,   /* LONG Z bias */
+    D3DRENDERSTATE_RANGEFOGENABLE     = 48,   /* Enables range-based fog */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+    D3DRENDERSTATE_STENCILENABLE      = 52,   /* BOOL enable/disable stenciling */
+    D3DRENDERSTATE_STENCILFAIL        = 53,   /* D3DSTENCILOP to do if stencil test fails */
+    D3DRENDERSTATE_STENCILZFAIL       = 54,   /* D3DSTENCILOP to do if stencil test passes and Z test fails */
+    D3DRENDERSTATE_STENCILPASS        = 55,   /* D3DSTENCILOP to do if both stencil and Z tests pass */
+    D3DRENDERSTATE_STENCILFUNC        = 56,   /* D3DCMPFUNC fn.  Stencil Test passes if ((ref & mask) stencilfn (stencil & mask)) is true */
+    D3DRENDERSTATE_STENCILREF         = 57,   /* Reference value used in stencil test */
+    D3DRENDERSTATE_STENCILMASK        = 58,   /* Mask value used in stencil test */
+    D3DRENDERSTATE_STENCILWRITEMASK   = 59,   /* Write mask applied to values written to stencil buffer */
+    D3DRENDERSTATE_TEXTUREFACTOR      = 60,   /* D3DCOLOR used for multi-texture blend */
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+
+    /*
+     * 128 values [128, 255] are reserved for texture coordinate wrap flags.
+     * These are constructed with the D3DWRAP_U and D3DWRAP_V macros. Using
+     * a flags word preserves forward compatibility with texture coordinates
+     * that are >2D.
+     */
+    D3DRENDERSTATE_WRAP0              = 128,  /* wrap for 1st texture coord. set */
+    D3DRENDERSTATE_WRAP1              = 129,  /* wrap for 2nd texture coord. set */
+    D3DRENDERSTATE_WRAP2              = 130,  /* wrap for 3rd texture coord. set */
+    D3DRENDERSTATE_WRAP3              = 131,  /* wrap for 4th texture coord. set */
+    D3DRENDERSTATE_WRAP4              = 132,  /* wrap for 5th texture coord. set */
+    D3DRENDERSTATE_WRAP5              = 133,  /* wrap for 6th texture coord. set */
+    D3DRENDERSTATE_WRAP6              = 134,  /* wrap for 7th texture coord. set */
+    D3DRENDERSTATE_WRAP7              = 135,  /* wrap for 8th texture coord. set */
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+#if(DIRECT3D_VERSION >= 0x0700)
+    D3DRENDERSTATE_CLIPPING            = 136,
+    D3DRENDERSTATE_LIGHTING            = 137,
+    D3DRENDERSTATE_EXTENTS             = 138,
+    D3DRENDERSTATE_AMBIENT             = 139,
+    D3DRENDERSTATE_FOGVERTEXMODE       = 140,
+    D3DRENDERSTATE_COLORVERTEX         = 141,
+    D3DRENDERSTATE_LOCALVIEWER         = 142,
+    D3DRENDERSTATE_NORMALIZENORMALS    = 143,
+    D3DRENDERSTATE_COLORKEYBLENDENABLE = 144,
+    D3DRENDERSTATE_DIFFUSEMATERIALSOURCE    = 145,
+    D3DRENDERSTATE_SPECULARMATERIALSOURCE   = 146,
+    D3DRENDERSTATE_AMBIENTMATERIALSOURCE    = 147,
+    D3DRENDERSTATE_EMISSIVEMATERIALSOURCE   = 148,
+    D3DRENDERSTATE_VERTEXBLEND              = 151,
+    D3DRENDERSTATE_CLIPPLANEENABLE          = 152,
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+//
+// retired renderstates - not supported for DX7 interfaces
+//
+    D3DRENDERSTATE_TEXTUREHANDLE      = 1,    /* Texture handle for legacy interfaces (Texture,Texture2) */
+    D3DRENDERSTATE_TEXTUREADDRESS     = 3,    /* D3DTEXTUREADDRESS  */
+    D3DRENDERSTATE_WRAPU              = 5,    /* TRUE for wrapping in u */
+    D3DRENDERSTATE_WRAPV              = 6,    /* TRUE for wrapping in v */
+    D3DRENDERSTATE_MONOENABLE         = 11,   /* TRUE to enable mono rasterization */
+    D3DRENDERSTATE_ROP2               = 12,   /* ROP2 */
+    D3DRENDERSTATE_PLANEMASK          = 13,   /* DWORD physical plane mask */
+    D3DRENDERSTATE_TEXTUREMAG         = 17,   /* D3DTEXTUREFILTER */
+    D3DRENDERSTATE_TEXTUREMIN         = 18,   /* D3DTEXTUREFILTER */
+    D3DRENDERSTATE_TEXTUREMAPBLEND    = 21,   /* D3DTEXTUREBLEND */
+    D3DRENDERSTATE_SUBPIXEL           = 31,   /* TRUE to enable subpixel correction */
+    D3DRENDERSTATE_SUBPIXELX          = 32,   /* TRUE to enable correction in X only */
+    D3DRENDERSTATE_STIPPLEENABLE      = 39,   /* TRUE to enable stippling */
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DRENDERSTATE_BORDERCOLOR        = 43,   /* Border color for texturing w/border */
+    D3DRENDERSTATE_TEXTUREADDRESSU    = 44,   /* Texture addressing mode for U coordinate */
+    D3DRENDERSTATE_TEXTUREADDRESSV    = 45,   /* Texture addressing mode for V coordinate */
+    D3DRENDERSTATE_MIPMAPLODBIAS      = 46,   /* D3DVALUE Mipmap LOD bias */
+    D3DRENDERSTATE_ANISOTROPY         = 49,   /* Max. anisotropy. 1 = no anisotropy */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+    D3DRENDERSTATE_FLUSHBATCH         = 50,   /* Explicit flush for DP batching (DX5 Only) */
+#if(DIRECT3D_VERSION >= 0x0600)
+    D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT=51, /* BOOL enable sort-independent transparency */
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+    D3DRENDERSTATE_STIPPLEPATTERN00   = 64,   /* Stipple pattern 01...  */
+    D3DRENDERSTATE_STIPPLEPATTERN01   = 65,
+    D3DRENDERSTATE_STIPPLEPATTERN02   = 66,
+    D3DRENDERSTATE_STIPPLEPATTERN03   = 67,
+    D3DRENDERSTATE_STIPPLEPATTERN04   = 68,
+    D3DRENDERSTATE_STIPPLEPATTERN05   = 69,
+    D3DRENDERSTATE_STIPPLEPATTERN06   = 70,
+    D3DRENDERSTATE_STIPPLEPATTERN07   = 71,
+    D3DRENDERSTATE_STIPPLEPATTERN08   = 72,
+    D3DRENDERSTATE_STIPPLEPATTERN09   = 73,
+    D3DRENDERSTATE_STIPPLEPATTERN10   = 74,
+    D3DRENDERSTATE_STIPPLEPATTERN11   = 75,
+    D3DRENDERSTATE_STIPPLEPATTERN12   = 76,
+    D3DRENDERSTATE_STIPPLEPATTERN13   = 77,
+    D3DRENDERSTATE_STIPPLEPATTERN14   = 78,
+    D3DRENDERSTATE_STIPPLEPATTERN15   = 79,
+    D3DRENDERSTATE_STIPPLEPATTERN16   = 80,
+    D3DRENDERSTATE_STIPPLEPATTERN17   = 81,
+    D3DRENDERSTATE_STIPPLEPATTERN18   = 82,
+    D3DRENDERSTATE_STIPPLEPATTERN19   = 83,
+    D3DRENDERSTATE_STIPPLEPATTERN20   = 84,
+    D3DRENDERSTATE_STIPPLEPATTERN21   = 85,
+    D3DRENDERSTATE_STIPPLEPATTERN22   = 86,
+    D3DRENDERSTATE_STIPPLEPATTERN23   = 87,
+    D3DRENDERSTATE_STIPPLEPATTERN24   = 88,
+    D3DRENDERSTATE_STIPPLEPATTERN25   = 89,
+    D3DRENDERSTATE_STIPPLEPATTERN26   = 90,
+    D3DRENDERSTATE_STIPPLEPATTERN27   = 91,
+    D3DRENDERSTATE_STIPPLEPATTERN28   = 92,
+    D3DRENDERSTATE_STIPPLEPATTERN29   = 93,
+    D3DRENDERSTATE_STIPPLEPATTERN30   = 94,
+    D3DRENDERSTATE_STIPPLEPATTERN31   = 95,
+
+//
+// retired renderstate names - the values are still used under new naming conventions
+//
+    D3DRENDERSTATE_FOGTABLESTART      = 36,   /* Fog table start    */
+    D3DRENDERSTATE_FOGTABLEEND        = 37,   /* Fog table end      */
+    D3DRENDERSTATE_FOGTABLEDENSITY    = 38,   /* Fog table density  */
+
+#if(DIRECT3D_VERSION >= 0x0500)
+    D3DRENDERSTATE_FORCEuint        = 0x7fffffff, /* force 32-bit size enum */
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+} D3DRENDERSTATETYPE;
+
+#else
+
+typedef enum _D3DRENDERSTATETYPE D3DRENDERSTATETYPE;
+
+//
+// legacy renderstate names
+//
+#define D3DRENDERSTATE_TEXTUREPERSPECTIVE       (D3DRENDERSTATETYPE)4
+#define D3DRENDERSTATE_ZENABLE                  (D3DRENDERSTATETYPE)7
+#define D3DRENDERSTATE_FILLMODE                 (D3DRENDERSTATETYPE)8
+#define D3DRENDERSTATE_SHADEMODE                (D3DRENDERSTATETYPE)9
+#define D3DRENDERSTATE_LINEPATTERN              (D3DRENDERSTATETYPE)10
+#define D3DRENDERSTATE_ZWRITEENABLE             (D3DRENDERSTATETYPE)14
+#define D3DRENDERSTATE_ALPHATESTENABLE          (D3DRENDERSTATETYPE)15
+#define D3DRENDERSTATE_LASTPIXEL                (D3DRENDERSTATETYPE)16
+#define D3DRENDERSTATE_SRCBLEND                 (D3DRENDERSTATETYPE)19
+#define D3DRENDERSTATE_DESTBLEND                (D3DRENDERSTATETYPE)20
+#define D3DRENDERSTATE_CULLMODE                 (D3DRENDERSTATETYPE)22
+#define D3DRENDERSTATE_ZFUNC                    (D3DRENDERSTATETYPE)23
+#define D3DRENDERSTATE_ALPHAREF                 (D3DRENDERSTATETYPE)24
+#define D3DRENDERSTATE_ALPHAFUNC                (D3DRENDERSTATETYPE)25
+#define D3DRENDERSTATE_DITHERENABLE             (D3DRENDERSTATETYPE)26
+#define D3DRENDERSTATE_ALPHABLENDENABLE         (D3DRENDERSTATETYPE)27
+#define D3DRENDERSTATE_FOGENABLE                (D3DRENDERSTATETYPE)28
+#define D3DRENDERSTATE_SPECULARENABLE           (D3DRENDERSTATETYPE)29
+#define D3DRENDERSTATE_ZVISIBLE                 (D3DRENDERSTATETYPE)30
+#define D3DRENDERSTATE_STIPPLEDALPHA            (D3DRENDERSTATETYPE)33
+#define D3DRENDERSTATE_FOGCOLOR                 (D3DRENDERSTATETYPE)34
+#define D3DRENDERSTATE_FOGTABLEMODE             (D3DRENDERSTATETYPE)35
+#define D3DRENDERSTATE_FOGSTART                 (D3DRENDERSTATETYPE)36
+#define D3DRENDERSTATE_FOGEND                   (D3DRENDERSTATETYPE)37
+#define D3DRENDERSTATE_FOGDENSITY               (D3DRENDERSTATETYPE)38
+#define D3DRENDERSTATE_EDGEANTIALIAS            (D3DRENDERSTATETYPE)40
+#define D3DRENDERSTATE_ZBIAS                    (D3DRENDERSTATETYPE)47
+#define D3DRENDERSTATE_RANGEFOGENABLE           (D3DRENDERSTATETYPE)48
+#define D3DRENDERSTATE_STENCILENABLE            (D3DRENDERSTATETYPE)52
+#define D3DRENDERSTATE_STENCILFAIL              (D3DRENDERSTATETYPE)53
+#define D3DRENDERSTATE_STENCILZFAIL             (D3DRENDERSTATETYPE)54
+#define D3DRENDERSTATE_STENCILPASS              (D3DRENDERSTATETYPE)55
+#define D3DRENDERSTATE_STENCILFUNC              (D3DRENDERSTATETYPE)56
+#define D3DRENDERSTATE_STENCILREF               (D3DRENDERSTATETYPE)57
+#define D3DRENDERSTATE_STENCILMASK              (D3DRENDERSTATETYPE)58
+#define D3DRENDERSTATE_STENCILWRITEMASK         (D3DRENDERSTATETYPE)59
+#define D3DRENDERSTATE_TEXTUREFACTOR            (D3DRENDERSTATETYPE)60
+#define D3DRENDERSTATE_WRAP0                    (D3DRENDERSTATETYPE)128
+#define D3DRENDERSTATE_WRAP1                    (D3DRENDERSTATETYPE)129
+#define D3DRENDERSTATE_WRAP2                    (D3DRENDERSTATETYPE)130
+#define D3DRENDERSTATE_WRAP3                    (D3DRENDERSTATETYPE)131
+#define D3DRENDERSTATE_WRAP4                    (D3DRENDERSTATETYPE)132
+#define D3DRENDERSTATE_WRAP5                    (D3DRENDERSTATETYPE)133
+#define D3DRENDERSTATE_WRAP6                    (D3DRENDERSTATETYPE)134
+#define D3DRENDERSTATE_WRAP7                    (D3DRENDERSTATETYPE)135
+
+#define D3DRENDERSTATE_CLIPPING                 (D3DRENDERSTATETYPE)136
+#define D3DRENDERSTATE_LIGHTING                 (D3DRENDERSTATETYPE)137
+#define D3DRENDERSTATE_EXTENTS                  (D3DRENDERSTATETYPE)138
+#define D3DRENDERSTATE_AMBIENT                  (D3DRENDERSTATETYPE)139
+#define D3DRENDERSTATE_FOGVERTEXMODE            (D3DRENDERSTATETYPE)140
+#define D3DRENDERSTATE_COLORVERTEX              (D3DRENDERSTATETYPE)141
+#define D3DRENDERSTATE_LOCALVIEWER              (D3DRENDERSTATETYPE)142
+#define D3DRENDERSTATE_NORMALIZENORMALS         (D3DRENDERSTATETYPE)143
+#define D3DRENDERSTATE_COLORKEYBLENDENABLE      (D3DRENDERSTATETYPE)144
+#define D3DRENDERSTATE_DIFFUSEMATERIALSOURCE    (D3DRENDERSTATETYPE)145
+#define D3DRENDERSTATE_SPECULARMATERIALSOURCE   (D3DRENDERSTATETYPE)146
+#define D3DRENDERSTATE_AMBIENTMATERIALSOURCE    (D3DRENDERSTATETYPE)147
+#define D3DRENDERSTATE_EMISSIVEMATERIALSOURCE   (D3DRENDERSTATETYPE)148
+#define D3DRENDERSTATE_VERTEXBLEND              (D3DRENDERSTATETYPE)151
+#define D3DRENDERSTATE_CLIPPLANEENABLE          (D3DRENDERSTATETYPE)152
+
+//
+// retired renderstates - not supported for DX7 interfaces
+//
+#define D3DRENDERSTATE_TEXTUREHANDLE     (D3DRENDERSTATETYPE)1
+#define D3DRENDERSTATE_ANTIALIAS         (D3DRENDERSTATETYPE)2
+#define D3DRENDERSTATE_TEXTUREADDRESS    (D3DRENDERSTATETYPE)3
+#define D3DRENDERSTATE_WRAPU             (D3DRENDERSTATETYPE)5
+#define D3DRENDERSTATE_WRAPV             (D3DRENDERSTATETYPE)6
+#define D3DRENDERSTATE_MONOENABLE        (D3DRENDERSTATETYPE)11
+#define D3DRENDERSTATE_ROP2              (D3DRENDERSTATETYPE)12
+#define D3DRENDERSTATE_PLANEMASK         (D3DRENDERSTATETYPE)13
+#define D3DRENDERSTATE_TEXTUREMAG        (D3DRENDERSTATETYPE)17
+#define D3DRENDERSTATE_TEXTUREMIN        (D3DRENDERSTATETYPE)18
+#define D3DRENDERSTATE_TEXTUREMAPBLEND   (D3DRENDERSTATETYPE)21
+#define D3DRENDERSTATE_SUBPIXEL          (D3DRENDERSTATETYPE)31
+#define D3DRENDERSTATE_SUBPIXELX         (D3DRENDERSTATETYPE)32
+#define D3DRENDERSTATE_STIPPLEENABLE     (D3DRENDERSTATETYPE)39
+#define D3DRENDERSTATE_OLDALPHABLENDENABLE  (D3DRENDERSTATETYPE)42
+#define D3DRENDERSTATE_BORDERCOLOR       (D3DRENDERSTATETYPE)43
+#define D3DRENDERSTATE_TEXTUREADDRESSU   (D3DRENDERSTATETYPE)44
+#define D3DRENDERSTATE_TEXTUREADDRESSV   (D3DRENDERSTATETYPE)45
+#define D3DRENDERSTATE_MIPMAPLODBIAS     (D3DRENDERSTATETYPE)46
+#define D3DRENDERSTATE_ANISOTROPY        (D3DRENDERSTATETYPE)49
+#define D3DRENDERSTATE_FLUSHBATCH        (D3DRENDERSTATETYPE)50
+#define D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT (D3DRENDERSTATETYPE)51
+#define D3DRENDERSTATE_STIPPLEPATTERN00  (D3DRENDERSTATETYPE)64
+#define D3DRENDERSTATE_STIPPLEPATTERN01  (D3DRENDERSTATETYPE)65
+#define D3DRENDERSTATE_STIPPLEPATTERN02  (D3DRENDERSTATETYPE)66
+#define D3DRENDERSTATE_STIPPLEPATTERN03  (D3DRENDERSTATETYPE)67
+#define D3DRENDERSTATE_STIPPLEPATTERN04  (D3DRENDERSTATETYPE)68
+#define D3DRENDERSTATE_STIPPLEPATTERN05  (D3DRENDERSTATETYPE)69
+#define D3DRENDERSTATE_STIPPLEPATTERN06  (D3DRENDERSTATETYPE)70
+#define D3DRENDERSTATE_STIPPLEPATTERN07  (D3DRENDERSTATETYPE)71
+#define D3DRENDERSTATE_STIPPLEPATTERN08  (D3DRENDERSTATETYPE)72
+#define D3DRENDERSTATE_STIPPLEPATTERN09  (D3DRENDERSTATETYPE)73
+#define D3DRENDERSTATE_STIPPLEPATTERN10  (D3DRENDERSTATETYPE)74
+#define D3DRENDERSTATE_STIPPLEPATTERN11  (D3DRENDERSTATETYPE)75
+#define D3DRENDERSTATE_STIPPLEPATTERN12  (D3DRENDERSTATETYPE)76
+#define D3DRENDERSTATE_STIPPLEPATTERN13  (D3DRENDERSTATETYPE)77
+#define D3DRENDERSTATE_STIPPLEPATTERN14  (D3DRENDERSTATETYPE)78
+#define D3DRENDERSTATE_STIPPLEPATTERN15  (D3DRENDERSTATETYPE)79
+#define D3DRENDERSTATE_STIPPLEPATTERN16  (D3DRENDERSTATETYPE)80
+#define D3DRENDERSTATE_STIPPLEPATTERN17  (D3DRENDERSTATETYPE)81
+#define D3DRENDERSTATE_STIPPLEPATTERN18  (D3DRENDERSTATETYPE)82
+#define D3DRENDERSTATE_STIPPLEPATTERN19  (D3DRENDERSTATETYPE)83
+#define D3DRENDERSTATE_STIPPLEPATTERN20  (D3DRENDERSTATETYPE)84
+#define D3DRENDERSTATE_STIPPLEPATTERN21  (D3DRENDERSTATETYPE)85
+#define D3DRENDERSTATE_STIPPLEPATTERN22  (D3DRENDERSTATETYPE)86
+#define D3DRENDERSTATE_STIPPLEPATTERN23  (D3DRENDERSTATETYPE)87
+#define D3DRENDERSTATE_STIPPLEPATTERN24  (D3DRENDERSTATETYPE)88
+#define D3DRENDERSTATE_STIPPLEPATTERN25  (D3DRENDERSTATETYPE)89
+#define D3DRENDERSTATE_STIPPLEPATTERN26  (D3DRENDERSTATETYPE)90
+#define D3DRENDERSTATE_STIPPLEPATTERN27  (D3DRENDERSTATETYPE)91
+#define D3DRENDERSTATE_STIPPLEPATTERN28  (D3DRENDERSTATETYPE)92
+#define D3DRENDERSTATE_STIPPLEPATTERN29  (D3DRENDERSTATETYPE)93
+#define D3DRENDERSTATE_STIPPLEPATTERN30  (D3DRENDERSTATETYPE)94
+#define D3DRENDERSTATE_STIPPLEPATTERN31  (D3DRENDERSTATETYPE)95
+
+//
+// retired renderstates - not supported for DX8 interfaces
+//
+#define D3DRENDERSTATE_COLORKEYENABLE        (D3DRENDERSTATETYPE)41
+#define D3DRENDERSTATE_COLORKEYBLENDENABLE   (D3DRENDERSTATETYPE)144
+
+//
+// retired renderstate names - the values are still used under new naming conventions
+//
+#define D3DRENDERSTATE_BLENDENABLE       (D3DRENDERSTATETYPE)27
+#define D3DRENDERSTATE_FOGTABLESTART     (D3DRENDERSTATETYPE)36
+#define D3DRENDERSTATE_FOGTABLEEND       (D3DRENDERSTATETYPE)37
+#define D3DRENDERSTATE_FOGTABLEDENSITY   (D3DRENDERSTATETYPE)38
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+// Values for material source
+typedef enum _D3DMATERIALCOLORSOURCE
+{
+    D3DMCS_MATERIAL = 0,                // Color from material is used
+    D3DMCS_COLOR1   = 1,                // Diffuse vertex color is used
+    D3DMCS_COLOR2   = 2,                // Specular vertex color is used
+    D3DMCS_FORCEuint = 0x7fffffff,    // force 32-bit size enum
+} D3DMATERIALCOLORSOURCE;
+
+
+#if(DIRECT3D_VERSION >= 0x0500)
+// For back-compatibility with legacy compilations
+#define D3DRENDERSTATE_BLENDENABLE      D3DRENDERSTATE_ALPHABLENDENABLE
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+
+#if(DIRECT3D_VERSION >= 0x0600)
+
+// Bias to apply to the texture coordinate set to apply a wrap to.
+#define D3DRENDERSTATE_WRAPBIAS                 128UL
+
+/* Flags to construct the WRAP render states */
+#define D3DWRAP_U   0x00000001L
+#define D3DWRAP_V   0x00000002L
+
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION >= 0x0700)
+
+/* Flags to construct the WRAP render states for 1D thru 4D texture coordinates */
+#define D3DWRAPCOORD_0   0x00000001L    // same as D3DWRAP_U
+#define D3DWRAPCOORD_1   0x00000002L    // same as D3DWRAP_V
+#define D3DWRAPCOORD_2   0x00000004L
+#define D3DWRAPCOORD_3   0x00000008L
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+#define D3DRENDERSTATE_STIPPLEPATTERN(y) (D3DRENDERSTATE_STIPPLEPATTERN00 + (y))
+
+typedef struct _D3DSTATE {
+    union {
+#if(DIRECT3D_VERSION < 0x0800)
+    D3DTRANSFORMSTATETYPE   dtstTransformStateType;
+#endif //(DIRECT3D_VERSION < 0x0800)
+    D3DLIGHTSTATETYPE   dlstLightStateType;
+    D3DRENDERSTATETYPE  drstRenderStateType;
+    };
+    union {
+    DWORD           dwArg[1];
+    D3DVALUE        dvArg[1];
+    };
+} D3DSTATE, *LPD3DSTATE;
+
+
+/*
+ * Operation used to load matrices
+ * hDstMat = hSrcMat
+ */
+typedef struct _D3DMATRIXLOAD {
+    D3DMATRIXHANDLE hDestMatrix;   /* Destination matrix */
+    D3DMATRIXHANDLE hSrcMatrix;   /* Source matrix */
+} D3DMATRIXLOAD, *LPD3DMATRIXLOAD;
+
+/*
+ * Operation used to multiply matrices
+ * hDstMat = hSrcMat1 * hSrcMat2
+ */
+typedef struct _D3DMATRIXMULTIPLY {
+    D3DMATRIXHANDLE hDestMatrix;   /* Destination matrix */
+    D3DMATRIXHANDLE hSrcMatrix1;  /* First source matrix */
+    D3DMATRIXHANDLE hSrcMatrix2;  /* Second source matrix */
+} D3DMATRIXMULTIPLY, *LPD3DMATRIXMULTIPLY;
+
+/*
+ * Operation used to transform and light vertices.
+ */
+typedef struct _D3DPROCESSVERTICES {
+    DWORD        dwFlags;    /* Do we transform or light or just copy? */
+    WORD         wStart;     /* Index to first vertex in source */
+    WORD         wDest;      /* Index to first vertex in local buffer */
+    DWORD        dwCount;    /* Number of vertices to be processed */
+    DWORD    dwReserved; /* Must be zero */
+} D3DPROCESSVERTICES, *LPD3DPROCESSVERTICES;
+
+#define D3DPROCESSVERTICES_TRANSFORMLIGHT   0x00000000L
+#define D3DPROCESSVERTICES_TRANSFORM        0x00000001L
+#define D3DPROCESSVERTICES_COPY         0x00000002L
+#define D3DPROCESSVERTICES_OPMASK       0x00000007L
+
+#define D3DPROCESSVERTICES_UPDATEEXTENTS    0x00000008L
+#define D3DPROCESSVERTICES_NOCOLOR      0x00000010L
+
+
+#if(DIRECT3D_VERSION >= 0x0600)
+
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+/*
+ * State enumerants for per-stage texture processing.
+ */
+typedef enum _D3DTEXTURESTAGESTATETYPE
+{
+    D3DTSS_COLOROP        =  1, /* D3DTEXTUREOP - per-stage blending controls for color channels */
+    D3DTSS_COLORARG1      =  2, /* D3DTA_* (texture arg) */
+    D3DTSS_COLORARG2      =  3, /* D3DTA_* (texture arg) */
+    D3DTSS_ALPHAOP        =  4, /* D3DTEXTUREOP - per-stage blending controls for alpha channel */
+    D3DTSS_ALPHAARG1      =  5, /* D3DTA_* (texture arg) */
+    D3DTSS_ALPHAARG2      =  6, /* D3DTA_* (texture arg) */
+    D3DTSS_BUMPENVMAT00   =  7, /* D3DVALUE (bump mapping matrix) */
+    D3DTSS_BUMPENVMAT01   =  8, /* D3DVALUE (bump mapping matrix) */
+    D3DTSS_BUMPENVMAT10   =  9, /* D3DVALUE (bump mapping matrix) */
+    D3DTSS_BUMPENVMAT11   = 10, /* D3DVALUE (bump mapping matrix) */
+    D3DTSS_TEXCOORDINDEX  = 11, /* identifies which set of texture coordinates index this texture */
+    D3DTSS_ADDRESS        = 12, /* D3DTEXTUREADDRESS for both coordinates */
+    D3DTSS_ADDRESSU       = 13, /* D3DTEXTUREADDRESS for U coordinate */
+    D3DTSS_ADDRESSV       = 14, /* D3DTEXTUREADDRESS for V coordinate */
+    D3DTSS_BORDERCOLOR    = 15, /* D3DCOLOR */
+    D3DTSS_MAGFILTER      = 16, /* D3DTEXTUREMAGFILTER filter to use for magnification */
+    D3DTSS_MINFILTER      = 17, /* D3DTEXTUREMINFILTER filter to use for minification */
+    D3DTSS_MIPFILTER      = 18, /* D3DTEXTUREMIPFILTER filter to use between mipmaps during minification */
+    D3DTSS_MIPMAPLODBIAS  = 19, /* D3DVALUE Mipmap LOD bias */
+    D3DTSS_MAXMIPLEVEL    = 20, /* DWORD 0..(n-1) LOD index of largest map to use (0 == largest) */
+    D3DTSS_MAXANISOTROPY  = 21, /* DWORD maximum anisotropy */
+    D3DTSS_BUMPENVLSCALE  = 22, /* D3DVALUE scale for bump map luminance */
+    D3DTSS_BUMPENVLOFFSET = 23, /* D3DVALUE offset for bump map luminance */
+#if(DIRECT3D_VERSION >= 0x0700)
+    D3DTSS_TEXTURETRANSFORMFLAGS = 24, /* D3DTEXTURETRANSFORMFLAGS controls texture transform */
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+    D3DTSS_FORCEuint   = 0x7fffffff, /* force 32-bit size enum */
+} D3DTEXTURESTAGESTATETYPE;
+
+#if(DIRECT3D_VERSION >= 0x0700)
+// Values, used with D3DTSS_TEXCOORDINDEX, to specify that the vertex data(position
+// and normal in the camera space) should be taken as texture coordinates
+// Low 16 bits are used to specify texture coordinate index, to take the WRAP mode from
+//
+#define D3DTSS_TCI_PASSTHRU                             0x00000000
+#define D3DTSS_TCI_CAMERASPACENORMAL                    0x00010000
+#define D3DTSS_TCI_CAMERASPACEPOSITION                  0x00020000
+#define D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR          0x00030000
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+/*
+ * Enumerations for COLOROP and ALPHAOP texture blending operations set in
+ * texture processing stage controls in D3DRENDERSTATE.
+ */
+typedef enum _D3DTEXTUREOP
+{
+// Control
+    D3DTOP_DISABLE    = 1,      // disables stage
+    D3DTOP_SELECTARG1 = 2,      // the default
+    D3DTOP_SELECTARG2 = 3,
+
+// Modulate
+    D3DTOP_MODULATE   = 4,      // multiply args together
+    D3DTOP_MODULATE2X = 5,      // multiply and  1 bit
+    D3DTOP_MODULATE4X = 6,      // multiply and  2 bits
+
+// Add
+    D3DTOP_ADD          =  7,   // add arguments together
+    D3DTOP_ADDSIGNED    =  8,   // add with -0.5 bias
+    D3DTOP_ADDSIGNED2X  =  9,   // as above but left  1 bit
+    D3DTOP_SUBTRACT     = 10,   // Arg1 - Arg2, with no saturation
+    D3DTOP_ADDSMOOTH    = 11,   // add 2 args, subtract product
+                                // Arg1 + Arg2 - Arg1*Arg2
+                                // = Arg1 + (1-Arg1)*Arg2
+
+// Linear alpha blend: Arg1*(Alpha) + Arg2*(1-Alpha)
+    D3DTOP_BLENDDIFFUSEALPHA    = 12, // iterated alpha
+    D3DTOP_BLENDTEXTUREALPHA    = 13, // texture alpha
+    D3DTOP_BLENDFACTORALPHA     = 14, // alpha from D3DRENDERSTATE_TEXTUREFACTOR
+    // Linear alpha blend with pre-multiplied arg1 input: Arg1 + Arg2*(1-Alpha)
+    D3DTOP_BLENDTEXTUREALPHAPM  = 15, // texture alpha
+    D3DTOP_BLENDCURRENTALPHA    = 16, // by alpha of current color
+
+// Specular mapping
+    D3DTOP_PREMODULATE            = 17,     // modulate with next texture before use
+    D3DTOP_MODULATEALPHA_ADDCOLOR = 18,     // Arg1.RGB + Arg1.A*Arg2.RGB
+                                            // COLOROP only
+    D3DTOP_MODULATECOLOR_ADDALPHA = 19,     // Arg1.RGB*Arg2.RGB + Arg1.A
+                                            // COLOROP only
+    D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20,  // (1-Arg1.A)*Arg2.RGB + Arg1.RGB
+                                            // COLOROP only
+    D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21,  // (1-Arg1.RGB)*Arg2.RGB + Arg1.A
+                                            // COLOROP only
+
+// Bump mapping
+    D3DTOP_BUMPENVMAP           = 22, // per pixel env map perturbation
+    D3DTOP_BUMPENVMAPLUMINANCE  = 23, // with luminance channel
+    // This can do either diffuse or specular bump mapping with correct input.
+    // Performs the function (Arg1.R*Arg2.R + Arg1.G*Arg2.G + Arg1.B*Arg2.B)
+    // where each component has been scaled and offset to make it signed.
+    // The result is replicated into all four (including alpha) channels.
+    // This is a valid COLOROP only.
+    D3DTOP_DOTPRODUCT3          = 24,
+
+    D3DTOP_FORCEuint = 0x7fffffff,
+} D3DTEXTUREOP;
+
+/*
+ * Values for COLORARG1,2 and ALPHAARG1,2 texture blending operations
+ * set in texture processing stage controls in D3DRENDERSTATE.
+ */
+#define D3DTA_SELECTMASK        0x0000000f  // mask for arg selector
+#define D3DTA_DIFFUSE           0x00000000  // select diffuse color
+#define D3DTA_CURRENT           0x00000001  // select result of previous stage
+#define D3DTA_TEXTURE           0x00000002  // select texture color
+#define D3DTA_TFACTOR           0x00000003  // select RENDERSTATE_TEXTUREFACTOR
+#if(DIRECT3D_VERSION >= 0x0700)
+#define D3DTA_SPECULAR          0x00000004  // select specular color
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+#define D3DTA_COMPLEMENT        0x00000010  // take 1.0 - x
+#define D3DTA_ALPHAREPLICATE    0x00000020  // replicate alpha to color components
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+/*
+ *  IDirect3DTexture2 State Filter Types
+ */
+typedef enum _D3DTEXTUREMAGFILTER
+{
+    D3DTFG_POINT        = 1,    // nearest
+    D3DTFG_LINEAR       = 2,    // linear interpolation
+    D3DTFG_FLATCUBIC    = 3,    // cubic
+    D3DTFG_GAUSSIANCUBIC = 4,   // different cubic kernel
+    D3DTFG_ANISOTROPIC  = 5,    //
+#if(DIRECT3D_VERSION >= 0x0700)
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+    D3DTFG_FORCEuint  = 0x7fffffff,   // force 32-bit size enum
+} D3DTEXTUREMAGFILTER;
+
+typedef enum _D3DTEXTUREMINFILTER
+{
+    D3DTFN_POINT        = 1,    // nearest
+    D3DTFN_LINEAR       = 2,    // linear interpolation
+    D3DTFN_ANISOTROPIC  = 3,    //
+    D3DTFN_FORCEuint  = 0x7fffffff,   // force 32-bit size enum
+} D3DTEXTUREMINFILTER;
+
+typedef enum _D3DTEXTUREMIPFILTER
+{
+    D3DTFP_NONE         = 1,    // mipmapping disabled (use MAG filter)
+    D3DTFP_POINT        = 2,    // nearest
+    D3DTFP_LINEAR       = 3,    // linear interpolation
+    D3DTFP_FORCEuint  = 0x7fffffff,   // force 32-bit size enum
+} D3DTEXTUREMIPFILTER;
+
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+/*
+ * Triangle flags
+ */
+
+/*
+ * Tri strip and fan flags.
+ * START loads all three vertices
+ * EVEN and ODD load just v3 with even or odd culling
+ * START_FLAT contains a count from 0 to 29 that allows the
+ * whole strip or fan to be culled in one hit.
+ * e.g. for a quad len = 1
+ */
+#define D3DTRIFLAG_START            0x00000000L
+#define D3DTRIFLAG_STARTFLAT(len) (len)     /* 0 < len < 30 */
+#define D3DTRIFLAG_ODD              0x0000001eL
+#define D3DTRIFLAG_EVEN             0x0000001fL
+
+/*
+ * Triangle edge flags
+ * enable edges for wireframe or antialiasing
+ */
+#define D3DTRIFLAG_EDGEENABLE1          0x00000100L /* v0-v1 edge */
+#define D3DTRIFLAG_EDGEENABLE2          0x00000200L /* v1-v2 edge */
+#define D3DTRIFLAG_EDGEENABLE3          0x00000400L /* v2-v0 edge */
+#define D3DTRIFLAG_EDGEENABLETRIANGLE \
+        (D3DTRIFLAG_EDGEENABLE1 | D3DTRIFLAG_EDGEENABLE2 | D3DTRIFLAG_EDGEENABLE3)
+
+/*
+ * Primitive structures and related defines.  Vertex offsets are to types
+ * RenderVertexD3D3, D3DLVERTEX, or D3DTLVERTEX.
+ */
+
+/*
+ * Triangle list primitive structure
+ */
+typedef struct _D3DTRIANGLE {
+    union {
+    WORD    v1;            /* Vertex indices */
+    WORD    wV1;
+    };
+    union {
+    WORD    v2;
+    WORD    wV2;
+    };
+    union {
+    WORD    v3;
+    WORD    wV3;
+    };
+    WORD        wFlags;       /* Edge (and other) flags */
+} D3DTRIANGLE, *LPD3DTRIANGLE;
+
+/*
+ * Line list structure.
+ * The instruction count defines the number of line segments.
+ */
+typedef struct _D3DLINE {
+    union {
+    WORD    v1;            /* Vertex indices */
+    WORD    wV1;
+    };
+    union {
+    WORD    v2;
+    WORD    wV2;
+    };
+} D3DLINE, *LPD3DLINE;
+
+/*
+ * Span structure
+ * Spans join a list of points with the same y value.
+ * If the y value changes, a new span is started.
+ */
+typedef struct _D3DSPAN {
+    WORD    wCount; /* Number of spans */
+    WORD    wFirst; /* Index to first vertex */
+} D3DSPAN, *LPD3DSPAN;
+
+/*
+ * Point structure
+ */
+typedef struct _D3DPOINT {
+    WORD    wCount;     /* number of points     */
+    WORD    wFirst;     /* index to first vertex    */
+} D3DPOINT, *LPD3DPOINT;
+
+
+/*
+ * Forward branch structure.
+ * Mask is logically anded with the driver status mask
+ * if the result equals 'value', the branch is taken.
+ */
+typedef struct _D3DBRANCH {
+    DWORD   dwMask;     /* Bitmask against D3D status */
+    DWORD   dwValue;
+    BOOL    bNegate;        /* TRUE to negate comparison */
+    DWORD   dwOffset;   /* How far to branch forward (0 for exit)*/
+} D3DBRANCH, *LPD3DBRANCH;
+
+/*
+ * Status used for set status instruction.
+ * The D3D status is initialised on device creation
+ * and is modified by all execute calls.
+ */
+typedef struct _D3DSTATUS {
+    DWORD       dwFlags;    /* Do we set extents or status */
+    DWORD   dwStatus;   /* D3D status */
+    D3DRECT drExtent;
+} D3DSTATUS, *LPD3DSTATUS;
+
+#define D3DSETSTATUS_STATUS     0x00000001L
+#define D3DSETSTATUS_EXTENTS        0x00000002L
+#define D3DSETSTATUS_ALL    (D3DSETSTATUS_STATUS | D3DSETSTATUS_EXTENTS)
+
+#if(DIRECT3D_VERSION >= 0x0500)
+typedef struct _D3DCLIPSTATUS {
+    DWORD dwFlags; /* Do we set 2d extents, 3D extents or status */
+    DWORD dwStatus; /* Clip status */
+    float minx, maxx; /* X extents */
+    float miny, maxy; /* Y extents */
+    float minz, maxz; /* Z extents */
+} D3DCLIPSTATUS, *LPD3DCLIPSTATUS;
+
+#define D3DCLIPSTATUS_STATUS        0x00000001L
+#define D3DCLIPSTATUS_EXTENTS2      0x00000002L
+#define D3DCLIPSTATUS_EXTENTS3      0x00000004L
+
+#endif /* DIRECT3D_VERSION >= 0x0500 */
+/*
+ * Statistics structure
+ */
+typedef struct _D3DSTATS {
+    DWORD        dwSize;
+    DWORD        dwTrianglesDrawn;
+    DWORD        dwLinesDrawn;
+    DWORD        dwPointsDrawn;
+    DWORD        dwSpansDrawn;
+    DWORD        dwVerticesProcessed;
+} D3DSTATS, *LPD3DSTATS;
+
+/*
+ * Execute options.
+ * When calling using D3DEXECUTE_UNCLIPPED all the primitives
+ * inside the buffer must be contained within the OldViewport.
+ */
+#define D3DEXECUTE_CLIPPED       0x00000001l
+#define D3DEXECUTE_UNCLIPPED     0x00000002l
+
+typedef struct _D3DEXECUTEDATA {
+    DWORD       dwSize;
+    DWORD       dwVertexOffset;
+    DWORD       dwVertexCount;
+    DWORD       dwInstructionOffset;
+    DWORD       dwInstructionLength;
+    DWORD       dwHVertexOffset;
+    D3DSTATUS   dsStatus;   /* Status after execute */
+} D3DEXECUTEDATA, *LPD3DEXECUTEDATA;
+
+/*
+ * Palette flags.
+ * This are or'ed with the peFlags in the PALETTEENTRYs passed to DirectDraw.
+ */
+#define D3DPAL_FREE 0x00    /* Renderer may use this entry freely */
+#define D3DPAL_READONLY 0x40    /* Renderer may not set this entry */
+#define D3DPAL_RESERVED 0x80    /* Renderer may not use this entry */
+
+
+#if(DIRECT3D_VERSION >= 0x0600)
+
+typedef struct _D3DVERTEXBUFFERDESC {
+    DWORD dwSize;
+    DWORD dwCaps;
+    DWORD dwFVF;
+    DWORD dwNumVertices;
+} D3DVERTEXBUFFERDESC, *LPD3DVERTEXBUFFERDESC;
+
+#define D3DVBCAPS_SYSTEMMEMORY      0x00000800l
+#define D3DVBCAPS_WRITEONLY         0x00010000l
+#define D3DVBCAPS_OPTIMIZED         0x80000000l
+#define D3DVBCAPS_DONOTCLIP         0x00000001l
+
+/* Vertex Operations for ProcessVertices */
+#define D3DVOP_LIGHT       (1 << 10)
+#define D3DVOP_TRANSFORM   (1 << 0)
+#define D3DVOP_CLIP        (1 << 2)
+#define D3DVOP_EXTENTS     (1 << 3)
+
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+/* The maximum number of vertices user can pass to any d3d
+   drawing function or to create vertex buffer with
+*/
+#define D3DMAXNUMVERTICES    ((1<<16) - 1)
+/* The maximum number of primitives user can pass to any d3d
+   drawing function.
+*/
+#define D3DMAXNUMPRIMITIVES  ((1<<16) - 1)
+
+#if(DIRECT3D_VERSION >= 0x0700)
+
+/* Bits for dwFlags in ProcessVertices call */
+#define D3DPV_DONOTCOPYDATA (1 << 0)
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+//-------------------------------------------------------------------
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+// Flexible vertex format bits
+//
+#define D3DFVF_RESERVED0        0x001
+#define D3DFVF_POSITION_MASK    0x00E
+#define D3DFVF_XYZ              0x002
+#define D3DFVF_XYZRHW           0x004
+#if(DIRECT3D_VERSION >= 0x0700)
+#define D3DFVF_XYZB1            0x006
+#define D3DFVF_XYZB2            0x008
+#define D3DFVF_XYZB3            0x00a
+#define D3DFVF_XYZB4            0x00c
+#define D3DFVF_XYZB5            0x00e
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+#define D3DFVF_NORMAL           0x010
+#define D3DFVF_RESERVED1        0x020
+#define D3DFVF_DIFFUSE          0x040
+#define D3DFVF_SPECULAR         0x080
+
+#define D3DFVF_TEXCOUNT_MASK    0xf00
+#define D3DFVF_TEXCOUNT_SHIFT   8
+#define D3DFVF_TEX0             0x000
+#define D3DFVF_TEX1             0x100
+#define D3DFVF_TEX2             0x200
+#define D3DFVF_TEX3             0x300
+#define D3DFVF_TEX4             0x400
+#define D3DFVF_TEX5             0x500
+#define D3DFVF_TEX6             0x600
+#define D3DFVF_TEX7             0x700
+#define D3DFVF_TEX8             0x800
+
+#define D3DFVF_RESERVED2        0xf000  // 4 reserved bits
+
+#else
+#define D3DFVF_RESERVED1        0x020
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+#define D3DFVF_VERTEX ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 )
+#define D3DFVF_LVERTEX ( D3DFVF_XYZ | D3DFVF_RESERVED1 | D3DFVF_DIFFUSE | \
+                         D3DFVF_SPECULAR | D3DFVF_TEX1 )
+#define D3DFVF_TLVERTEX ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | \
+                          D3DFVF_TEX1 )
+
+
+typedef struct _D3DDP_PTRSTRIDE
+{
+    LPVOID lpvData;
+    DWORD  dwStride;
+} D3DDP_PTRSTRIDE;
+
+#define D3DDP_MAXTEXCOORD 8
+
+typedef struct _D3DDRAWPRIMITIVESTRIDEDDATA
+{
+    D3DDP_PTRSTRIDE position;
+    D3DDP_PTRSTRIDE normal;
+    D3DDP_PTRSTRIDE diffuse;
+    D3DDP_PTRSTRIDE specular;
+    D3DDP_PTRSTRIDE textureCoords[D3DDP_MAXTEXCOORD];
+} D3DDRAWPRIMITIVESTRIDEDDATA, *LPD3DDRAWPRIMITIVESTRIDEDDATA;
+//---------------------------------------------------------------------
+// ComputeSphereVisibility return values
+//
+#define D3DVIS_INSIDE_FRUSTUM       0
+#define D3DVIS_INTERSECT_FRUSTUM    1
+#define D3DVIS_OUTSIDE_FRUSTUM      2
+#define D3DVIS_INSIDE_LEFT          0
+#define D3DVIS_INTERSECT_LEFT       (1 << 2)
+#define D3DVIS_OUTSIDE_LEFT         (2 << 2)
+#define D3DVIS_INSIDE_RIGHT         0
+#define D3DVIS_INTERSECT_RIGHT      (1 << 4)
+#define D3DVIS_OUTSIDE_RIGHT        (2 << 4)
+#define D3DVIS_INSIDE_TOP           0
+#define D3DVIS_INTERSECT_TOP        (1 << 6)
+#define D3DVIS_OUTSIDE_TOP          (2 << 6)
+#define D3DVIS_INSIDE_BOTTOM        0
+#define D3DVIS_INTERSECT_BOTTOM     (1 << 8)
+#define D3DVIS_OUTSIDE_BOTTOM       (2 << 8)
+#define D3DVIS_INSIDE_NEAR          0
+#define D3DVIS_INTERSECT_NEAR       (1 << 10)
+#define D3DVIS_OUTSIDE_NEAR         (2 << 10)
+#define D3DVIS_INSIDE_FAR           0
+#define D3DVIS_INTERSECT_FAR        (1 << 12)
+#define D3DVIS_OUTSIDE_FAR          (2 << 12)
+
+#define D3DVIS_MASK_FRUSTUM         (3 << 0)
+#define D3DVIS_MASK_LEFT            (3 << 2)
+#define D3DVIS_MASK_RIGHT           (3 << 4)
+#define D3DVIS_MASK_TOP             (3 << 6)
+#define D3DVIS_MASK_BOTTOM          (3 << 8)
+#define D3DVIS_MASK_NEAR            (3 << 10)
+#define D3DVIS_MASK_FAR             (3 << 12)
+
+#endif /* DIRECT3D_VERSION >= 0x0600 */
+
+#if(DIRECT3D_VERSION < 0x0800)
+
+#if(DIRECT3D_VERSION >= 0x0700)
+
+// To be used with GetInfo()
+#define D3DDEVINFOID_TEXTUREMANAGER    1
+#define D3DDEVINFOID_D3DTEXTUREMANAGER 2
+#define D3DDEVINFOID_TEXTURING         3
+
+typedef enum _D3DSTATEBLOCKTYPE
+{
+    D3DSBT_ALL           = 1, // capture all state
+    D3DSBT_PIXELSTATE    = 2, // capture pixel state
+    D3DSBT_VERTEXSTATE   = 3, // capture vertex state
+    D3DSBT_FORCEuint   = 0xffffffff
+} D3DSTATEBLOCKTYPE;
+
+// The D3DVERTEXBLENDFLAGS type is used with D3DRENDERSTATE_VERTEXBLEND state.
+//
+typedef enum _D3DVERTEXBLENDFLAGS
+{
+    D3DVBLEND_DISABLE  = 0, // Disable vertex blending
+    D3DVBLEND_1WEIGHT  = 1, // blend between 2 matrices
+    D3DVBLEND_2WEIGHTS = 2, // blend between 3 matrices
+    D3DVBLEND_3WEIGHTS = 3, // blend between 4 matrices
+} D3DVERTEXBLENDFLAGS;
+
+typedef enum _D3DTEXTURETRANSFORMFLAGS {
+    D3DTTFF_DISABLE         = 0,    // texture coordinates are passed directly
+    D3DTTFF_COUNT1          = 1,    // rasterizer should expect 1-D texture coords
+    D3DTTFF_COUNT2          = 2,    // rasterizer should expect 2-D texture coords
+    D3DTTFF_COUNT3          = 3,    // rasterizer should expect 3-D texture coords
+    D3DTTFF_COUNT4          = 4,    // rasterizer should expect 4-D texture coords
+    D3DTTFF_PROJECTED       = 256,  // texcoords to be divided by COUNTth element
+    D3DTTFF_FORCEuint     = 0x7fffffff,
+} D3DTEXTURETRANSFORMFLAGS;
+
+// Macros to set texture coordinate format bits in the FVF id
+
+#define D3DFVF_TEXTUREFORMAT2 0         // Two floating point values
+#define D3DFVF_TEXTUREFORMAT1 3         // One floating point value
+#define D3DFVF_TEXTUREFORMAT3 1         // Three floating point values
+#define D3DFVF_TEXTUREFORMAT4 2         // Four floating point values
+
+#define D3DFVF_TEXCOORDSIZE3(CoordIndex) (D3DFVF_TEXTUREFORMAT3 << (CoordIndex*2 + 16))
+#define D3DFVF_TEXCOORDSIZE2(CoordIndex) (D3DFVF_TEXTUREFORMAT2)
+#define D3DFVF_TEXCOORDSIZE4(CoordIndex) (D3DFVF_TEXTUREFORMAT4 << (CoordIndex*2 + 16))
+#define D3DFVF_TEXCOORDSIZE1(CoordIndex) (D3DFVF_TEXTUREFORMAT1 << (CoordIndex*2 + 16))
+
+
+#endif /* DIRECT3D_VERSION >= 0x0700 */
+
+#else
+//
+// legacy vertex blend names
+//
+typedef enum _D3DVERTEXBLENDFLAGS D3DVERTEXBLENDFLAGS;
+#define D3DVBLEND_DISABLE  (D3DVERTEXBLENDFLAGS)0
+#define D3DVBLEND_1WEIGHT  (D3DVERTEXBLENDFLAGS)1
+#define D3DVBLEND_2WEIGHTS (D3DVERTEXBLENDFLAGS)2
+#define D3DVBLEND_3WEIGHTS (D3DVERTEXBLENDFLAGS)3
+
+#endif //(DIRECT3D_VERSION < 0x0800)
+
+#pragma pack()
+#pragma warning(default:4201)
+
+#endif /* _D3DTYPES_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/d3dvec.inl	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,255 @@
+
+/****************************************************************** 
+ *                                                                *
+ *   D3DVec.inl                                                   *
+ *                                                                *
+ *   Float-valued 3D vector class for Direct3D.                   *
+ *                                                                *
+ *   Copyright (c) Microsoft Corp. All rights reserved.           *
+ *                                                                *
+ ******************************************************************/
+
+#include <math.h>
+
+// =====================================
+// Constructors
+// =====================================
+
+inline
+_D3DVECTOR::_D3DVECTOR(D3DVALUE f)
+{
+    x = y = z = f;
+}
+
+inline
+_D3DVECTOR::_D3DVECTOR(D3DVALUE _x, D3DVALUE _y, D3DVALUE _z)
+{
+    x = _x; y = _y; z = _z;
+}
+
+inline
+_D3DVECTOR::_D3DVECTOR(const D3DVALUE f[3])
+{
+    x = f[0]; y = f[1]; z = f[2];
+}
+
+// =====================================
+// Access grants
+// =====================================
+
+inline const D3DVALUE&
+_D3DVECTOR::operator[](int i) const
+{
+    return (&x)[i];
+}
+
+inline D3DVALUE&
+_D3DVECTOR::operator[](int i)
+{
+    return (&x)[i];
+}
+
+
+// =====================================
+// Assignment operators
+// =====================================
+
+inline _D3DVECTOR&
+_D3DVECTOR::operator += (const _D3DVECTOR& v)
+{
+   x += v.x;   y += v.y;   z += v.z;
+   return *_this;
+}
+
+inline _D3DVECTOR&
+_D3DVECTOR::operator -= (const _D3DVECTOR& v)
+{
+   x -= v.x;   y -= v.y;   z -= v.z;
+   return *_this;
+}
+
+inline _D3DVECTOR&
+_D3DVECTOR::operator *= (const _D3DVECTOR& v)
+{
+   x *= v.x;   y *= v.y;   z *= v.z;
+   return *_this;
+}
+
+inline _D3DVECTOR&
+_D3DVECTOR::operator /= (const _D3DVECTOR& v)
+{
+   x /= v.x;   y /= v.y;   z /= v.z;
+   return *_this;
+}
+
+inline _D3DVECTOR&
+_D3DVECTOR::operator *= (D3DVALUE s)
+{
+   x *= s;   y *= s;   z *= s;
+   return *_this;
+}
+
+inline _D3DVECTOR&
+_D3DVECTOR::operator /= (D3DVALUE s)
+{
+   x /= s;   y /= s;   z /= s;
+   return *_this;
+}
+
+inline _D3DVECTOR
+operator + (const _D3DVECTOR& v)
+{
+   return v;
+}
+
+inline _D3DVECTOR
+operator - (const _D3DVECTOR& v)
+{
+   return _D3DVECTOR(-v.x, -v.y, -v.z);
+}
+
+inline _D3DVECTOR
+operator + (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return _D3DVECTOR(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z);
+}
+
+inline _D3DVECTOR
+operator - (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return _D3DVECTOR(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z);
+}
+
+inline _D3DVECTOR
+operator * (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return _D3DVECTOR(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z);
+}
+
+inline _D3DVECTOR
+operator / (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return _D3DVECTOR(v1.x/v2.x, v1.y/v2.y, v1.z/v2.z);
+}
+
+inline int
+operator < (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return v1[0] < v2[0] && v1[1] < v2[1] && v1[2] < v2[2];
+}
+
+inline int
+operator <= (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return v1[0] <= v2[0] && v1[1] <= v2[1] && v1[2] <= v2[2];
+}
+
+inline _D3DVECTOR
+operator * (const _D3DVECTOR& v, D3DVALUE s)
+{
+   return _D3DVECTOR(s*v.x, s*v.y, s*v.z);
+}
+
+inline _D3DVECTOR
+operator * (D3DVALUE s, const _D3DVECTOR& v)
+{
+   return _D3DVECTOR(s*v.x, s*v.y, s*v.z);
+}
+
+inline _D3DVECTOR
+operator / (const _D3DVECTOR& v, D3DVALUE s)
+{
+   return _D3DVECTOR(v.x/s, v.y/s, v.z/s);
+}
+
+inline int
+operator == (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return v1.x==v2.x && v1.y==v2.y && v1.z == v2.z;
+}
+
+inline D3DVALUE
+Magnitude (const _D3DVECTOR& v)
+{
+   return (D3DVALUE) sqrt(SquareMagnitude(v));
+}
+
+inline D3DVALUE
+SquareMagnitude (const _D3DVECTOR& v)
+{
+   return v.x*v.x + v.y*v.y + v.z*v.z;
+}
+
+inline _D3DVECTOR
+Normalize (const _D3DVECTOR& v)
+{
+   return v / Magnitude(v);
+}
+
+inline D3DVALUE
+Min (const _D3DVECTOR& v)
+{
+   D3DVALUE ret = v.x;
+   if (v.y < ret) ret = v.y;
+   if (v.z < ret) ret = v.z;
+   return ret;
+}
+
+inline D3DVALUE
+Max (const _D3DVECTOR& v)
+{
+   D3DVALUE ret = v.x;
+   if (ret < v.y) ret = v.y;
+   if (ret < v.z) ret = v.z;
+   return ret;
+}
+
+inline _D3DVECTOR
+Minimize (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return _D3DVECTOR( v1[0] < v2[0] ? v1[0] : v2[0],
+                   v1[1] < v2[1] ? v1[1] : v2[1],
+                   v1[2] < v2[2] ? v1[2] : v2[2]);
+}
+
+inline _D3DVECTOR
+Maximize (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return _D3DVECTOR( v1[0] > v2[0] ? v1[0] : v2[0],
+                   v1[1] > v2[1] ? v1[1] : v2[1],
+                   v1[2] > v2[2] ? v1[2] : v2[2]);
+}
+
+inline D3DVALUE
+DotProduct (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+   return v1.x*v2.x + v1.y * v2.y + v1.z*v2.z;
+}
+
+inline _D3DVECTOR
+CrossProduct (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
+{
+	_D3DVECTOR result;
+
+	result[0] = v1[1] * v2[2] - v1[2] * v2[1];
+	result[1] = v1[2] * v2[0] - v1[0] * v2[2];
+	result[2] = v1[0] * v2[1] - v1[1] * v2[0];
+
+	return result;
+}
+
+inline _D3DMATRIX
+operator* (const _D3DMATRIX& a, const _D3DMATRIX& b)
+{
+    _D3DMATRIX ret;
+    for (int i=0; i<4; i++) {
+        for (int j=0; j<4; j++) {
+            ret(i, j) = 0.0f;
+            for (int k=0; k<4; k++) {
+                ret(i, j) += a(i, k) * b(k, j);
+            }
+        }
+    }
+    return ret;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/ddraw.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,5792 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       ddraw.h
+ *  Content:    DirectDraw include file
+ *
+ ***************************************************************************/
+
+#ifndef __DDRAW_INCLUDED__
+#define __DDRAW_INCLUDED__
+
+//Disable the nameless union warning when building internally
+#undef ENABLE_NAMELESS_UNION_PRAGMA
+#ifdef DIRECTX_REDIST
+#define ENABLE_NAMELESS_UNION_PRAGMA
+#endif
+
+#ifdef ENABLE_NAMELESS_UNION_PRAGMA
+#pragma warning(disable:4201)
+#endif
+
+/*
+ * If you wish an application built against the newest version of DirectDraw
+ * to run against an older DirectDraw run time then define DIRECTDRAW_VERSION
+ * to be the earlies version of DirectDraw you wish to run against. For,
+ * example if you wish an application to run against a DX 3 runtime define
+ * DIRECTDRAW_VERSION to be 0x0300.
+ */
+#ifndef   DIRECTDRAW_VERSION
+#define   DIRECTDRAW_VERSION 0x0700
+#endif /* DIRECTDRAW_VERSION */
+
+#if defined( _WIN32 )  && !defined( _NO_COM )
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#else
+#define IUnknown            void
+#if !defined( NT_BUILD_ENVIRONMENT ) && !defined(WINNT)
+        #define CO_E_NOTINITIALIZED 0x800401F0L
+#endif
+#endif
+
+#define _FACDD  0x876
+#define MAKE_DDHRESULT( code )  MAKE_HRESULT( 1, _FACDD, code )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// For compilers that don't support nameless unions, do a
+//
+// #define NONAMELESSUNION
+//
+// before #include <ddraw.h>
+//
+#ifndef DUMMYUNIONNAMEN
+#if defined(__cplusplus) || !defined(NONAMELESSUNION)
+#define DUMMYUNIONNAMEN(n)
+#else
+#define DUMMYUNIONNAMEN(n)      u##n
+#endif
+#endif
+
+#ifndef MAKEFOURCC
+    #define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
+                ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) |   \
+                ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
+#endif //defined(MAKEFOURCC)
+
+/*
+ * FOURCC codes for DX compressed-texture pixel formats
+ */
+#define FOURCC_DXT1  (MAKEFOURCC('D','X','T','1'))
+#define FOURCC_DXT2  (MAKEFOURCC('D','X','T','2'))
+#define FOURCC_DXT3  (MAKEFOURCC('D','X','T','3'))
+#define FOURCC_DXT4  (MAKEFOURCC('D','X','T','4'))
+#define FOURCC_DXT5  (MAKEFOURCC('D','X','T','5'))
+
+/*
+ * GUIDS used by DirectDraw objects
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+
+DEFINE_GUID( CLSID_DirectDraw,                  0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 );
+DEFINE_GUID( CLSID_DirectDraw7,                 0x3c305196,0x50db,0x11d3,0x9c,0xfe,0x00,0xc0,0x4f,0xd9,0x30,0xc5 );
+DEFINE_GUID( CLSID_DirectDrawClipper,           0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDraw,                   0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDraw2,                  0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDraw4,                  0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 );
+DEFINE_GUID( IID_IDirectDraw7,                  0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b );
+DEFINE_GUID( IID_IDirectDrawSurface,            0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawSurface2,           0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
+DEFINE_GUID( IID_IDirectDrawSurface3,           0xDA044E00,0x69B2,0x11D0,0xA1,0xD5,0x00,0xAA,0x00,0xB8,0xDF,0xBB );
+DEFINE_GUID( IID_IDirectDrawSurface4,           0x0B2B8630,0xAD35,0x11D0,0x8E,0xA6,0x00,0x60,0x97,0x97,0xEA,0x5B );
+DEFINE_GUID( IID_IDirectDrawSurface7,           0x06675a80,0x3b9b,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b );
+DEFINE_GUID( IID_IDirectDrawPalette,            0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawClipper,            0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawColorControl,       0x4B9F0EE0,0x0D7E,0x11D0,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8 );
+DEFINE_GUID( IID_IDirectDrawGammaControl,       0x69C11C3E,0xB46B,0x11D1,0xAD,0x7A,0x00,0xC0,0x4F,0xC2,0x9B,0x4E );
+
+#endif
+
+/*============================================================================
+ *
+ * DirectDraw Structures
+ *
+ * Various structures used to invoke DirectDraw.
+ *
+ *==========================================================================*/
+
+struct IDirectDraw;
+struct IDirectDrawSurface;
+struct IDirectDrawPalette;
+struct IDirectDrawClipper;
+
+typedef struct IDirectDraw              FAR *LPDIRECTDRAW;
+typedef struct IDirectDraw2             FAR *LPDIRECTDRAW2;
+typedef struct IDirectDraw4             FAR *LPDIRECTDRAW4;
+typedef struct IDirectDraw7             FAR *LPDIRECTDRAW7;
+typedef struct IDirectDrawSurface       FAR *LPDIRECTDRAWSURFACE;
+typedef struct IDirectDrawSurface2      FAR *LPDIRECTDRAWSURFACE2;
+typedef struct IDirectDrawSurface3      FAR *LPDIRECTDRAWSURFACE3;
+typedef struct IDirectDrawSurface4      FAR *LPDIRECTDRAWSURFACE4;
+typedef struct IDirectDrawSurface7      FAR *LPDIRECTDRAWSURFACE7;
+typedef struct IDirectDrawPalette               FAR *LPDIRECTDRAWPALETTE;
+typedef struct IDirectDrawClipper               FAR *LPDIRECTDRAWCLIPPER;
+typedef struct IDirectDrawColorControl          FAR *LPDIRECTDRAWCOLORCONTROL;
+typedef struct IDirectDrawGammaControl          FAR *LPDIRECTDRAWGAMMACONTROL;
+
+typedef struct _DDFXROP                 FAR *LPDDFXROP;
+typedef struct _DDSURFACEDESC           FAR *LPDDSURFACEDESC;
+typedef struct _DDSURFACEDESC2          FAR *LPDDSURFACEDESC2;
+typedef struct _DDCOLORCONTROL          FAR *LPDDCOLORCONTROL;
+
+/*
+ * API's
+ */
+#if (defined (WIN32) || defined( _WIN32 ) ) && !defined( _NO_COM )
+//#if defined( _WIN32 ) && !defined( _NO_ENUM )
+    typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID);
+    typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID);
+    extern HRESULT WINAPI DirectDrawEnumerateW( LPDDENUMCALLBACKW lpCallback, LPVOID lpContext );
+    extern HRESULT WINAPI DirectDrawEnumerateA( LPDDENUMCALLBACKA lpCallback, LPVOID lpContext );
+    /*
+     * Protect against old SDKs
+     */
+    #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500)
+        #define HMONITOR_DECLARED
+        DECLARE_HANDLE(HMONITOR);
+    #endif
+    typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKEXA)(GUID FAR *, LPSTR, LPSTR, LPVOID, HMONITOR);
+    typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKEXW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID, HMONITOR);
+    extern HRESULT WINAPI DirectDrawEnumerateExW( LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags);
+    extern HRESULT WINAPI DirectDrawEnumerateExA( LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags);
+    typedef HRESULT (WINAPI * LPDIRECTDRAWENUMERATEEXA)( LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags);
+    typedef HRESULT (WINAPI * LPDIRECTDRAWENUMERATEEXW)( LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags);
+
+    #ifdef UNICODE
+        typedef LPDDENUMCALLBACKW           LPDDENUMCALLBACK;
+        #define DirectDrawEnumerate         DirectDrawEnumerateW
+        typedef LPDDENUMCALLBACKEXW         LPDDENUMCALLBACKEX;
+        typedef LPDIRECTDRAWENUMERATEEXW        LPDIRECTDRAWENUMERATEEX;
+        #define DirectDrawEnumerateEx       DirectDrawEnumerateExW
+    #else
+        typedef LPDDENUMCALLBACKA           LPDDENUMCALLBACK;
+        #define DirectDrawEnumerate         DirectDrawEnumerateA
+        typedef LPDDENUMCALLBACKEXA         LPDDENUMCALLBACKEX;
+        typedef LPDIRECTDRAWENUMERATEEXA        LPDIRECTDRAWENUMERATEEX;
+        #define DirectDrawEnumerateEx       DirectDrawEnumerateExA
+    #endif
+    extern HRESULT WINAPI DirectDrawCreate( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
+    extern HRESULT WINAPI DirectDrawCreateEx( GUID FAR * lpGuid, LPVOID  *lplpDD, REFIID  iid,IUnknown FAR *pUnkOuter );
+    extern HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter );
+#endif
+/*
+ * Flags for DirectDrawEnumerateEx
+ * DirectDrawEnumerateEx supercedes DirectDrawEnumerate. You must use GetProcAddress to
+ * obtain a function pointer (of type LPDIRECTDRAWENUMERATEEX) to DirectDrawEnumerateEx.
+ * By default, only the primary display device is enumerated.
+ * DirectDrawEnumerate is equivalent to DirectDrawEnumerate(,,DDENUM_NONDISPLAYDEVICES)
+ */
+
+/*
+ * This flag causes enumeration of any GDI display devices which are part of
+ * the Windows Desktop
+ */
+#define DDENUM_ATTACHEDSECONDARYDEVICES     0x00000001L
+
+/*
+ * This flag causes enumeration of any GDI display devices which are not
+ * part of the Windows Desktop
+ */
+#define DDENUM_DETACHEDSECONDARYDEVICES     0x00000002L
+
+/*
+ * This flag causes enumeration of non-display devices
+ */
+#define DDENUM_NONDISPLAYDEVICES            0x00000004L
+
+
+#define REGSTR_KEY_DDHW_DESCRIPTION     "Description"
+#define REGSTR_KEY_DDHW_DRIVERNAME      "DriverName"
+#define REGSTR_PATH_DDHW                "Hardware\\DirectDrawDrivers"
+
+#define DDCREATE_HARDWAREONLY           0x00000001l
+#define DDCREATE_EMULATIONONLY          0x00000002l
+
+#if defined(WINNT) || !defined(WIN32)
+typedef long HRESULT;
+#endif
+
+//#ifndef WINNT
+typedef HRESULT (FAR PASCAL * LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID);
+typedef HRESULT (FAR PASCAL * LPDDENUMMODESCALLBACK2)(LPDDSURFACEDESC2, LPVOID);
+typedef HRESULT (FAR PASCAL * LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID);
+typedef HRESULT (FAR PASCAL * LPDDENUMSURFACESCALLBACK2)(LPDIRECTDRAWSURFACE4, LPDDSURFACEDESC2, LPVOID);
+typedef HRESULT (FAR PASCAL * LPDDENUMSURFACESCALLBACK7)(LPDIRECTDRAWSURFACE7, LPDDSURFACEDESC2, LPVOID);
+//#endif
+
+/*
+ * Generic pixel format with 8-bit RGB and alpha components
+ */
+typedef struct _DDARGB
+{
+    BYTE blue;
+    BYTE green;
+    BYTE red;
+    BYTE alpha;
+} DDARGB;
+
+typedef DDARGB FAR *LPDDARGB;
+
+/*
+ * This version of the structure remains for backwards source compatibility.
+ * The DDARGB structure is the one that should be used for all DirectDraw APIs.
+ */
+typedef struct _DDRGBA
+{
+    BYTE red;
+    BYTE green;
+    BYTE blue;
+    BYTE alpha;
+} DDRGBA;
+
+typedef DDRGBA FAR *LPDDRGBA;
+
+
+/*
+ * DDCOLORKEY
+ */
+typedef struct _DDCOLORKEY
+{
+    DWORD       dwColorSpaceLowValue;   // low boundary of color space that is to
+                                        // be treated as Color Key, inclusive
+    DWORD       dwColorSpaceHighValue;  // high boundary of color space that is
+                                        // to be treated as Color Key, inclusive
+} DDCOLORKEY;
+
+typedef DDCOLORKEY FAR* LPDDCOLORKEY;
+
+/*
+ * DDBLTFX
+ * Used to pass override information to the DIRECTDRAWSURFACE callback Blt.
+ */
+typedef struct _DDBLTFX
+{
+    DWORD       dwSize;                         // size of structure
+    DWORD       dwDDFX;                         // FX operations
+    DWORD       dwROP;                          // Win32 raster operations
+    DWORD       dwDDROP;                        // Raster operations new for DirectDraw
+    DWORD       dwRotationAngle;                // Rotation angle for blt
+    DWORD       dwZBufferOpCode;                // ZBuffer compares
+    DWORD       dwZBufferLow;                   // Low limit of Z buffer
+    DWORD       dwZBufferHigh;                  // High limit of Z buffer
+    DWORD       dwZBufferBaseDest;              // Destination base value
+    DWORD       dwZDestConstBitDepth;           // Bit depth used to specify Z constant for destination
+    union
+    {
+        DWORD   dwZDestConst;                   // Constant to use as Z buffer for dest
+        LPDIRECTDRAWSURFACE lpDDSZBufferDest;   // Surface to use as Z buffer for dest
+    } DUMMYUNIONNAMEN(1);
+    DWORD       dwZSrcConstBitDepth;            // Bit depth used to specify Z constant for source
+    union
+    {
+        DWORD   dwZSrcConst;                    // Constant to use as Z buffer for src
+        LPDIRECTDRAWSURFACE lpDDSZBufferSrc;    // Surface to use as Z buffer for src
+    } DUMMYUNIONNAMEN(2);
+    DWORD       dwAlphaEdgeBlendBitDepth;       // Bit depth used to specify constant for alpha edge blend
+    DWORD       dwAlphaEdgeBlend;               // Alpha for edge blending
+    DWORD       dwReserved;
+    DWORD       dwAlphaDestConstBitDepth;       // Bit depth used to specify alpha constant for destination
+    union
+    {
+        DWORD   dwAlphaDestConst;               // Constant to use as Alpha Channel
+        LPDIRECTDRAWSURFACE lpDDSAlphaDest;     // Surface to use as Alpha Channel
+    } DUMMYUNIONNAMEN(3);
+    DWORD       dwAlphaSrcConstBitDepth;        // Bit depth used to specify alpha constant for source
+    union
+    {
+        DWORD   dwAlphaSrcConst;                // Constant to use as Alpha Channel
+        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      // Surface to use as Alpha Channel
+    } DUMMYUNIONNAMEN(4);
+    union
+    {
+        DWORD   dwFillColor;                    // color in RGB or Palettized
+        DWORD   dwFillDepth;                    // depth value for z-buffer
+        DWORD   dwFillPixel;                    // pixel value for RGBA or RGBZ
+        LPDIRECTDRAWSURFACE lpDDSPattern;       // Surface to use as pattern
+    } DUMMYUNIONNAMEN(5);
+    DDCOLORKEY  ddckDestColorkey;               // DestColorkey override
+    DDCOLORKEY  ddckSrcColorkey;                // SrcColorkey override
+} DDBLTFX;
+
+typedef DDBLTFX FAR* LPDDBLTFX;
+
+
+
+/*
+ * DDSCAPS
+ */
+typedef struct _DDSCAPS
+{
+    DWORD       dwCaps;         // capabilities of surface wanted
+} DDSCAPS;
+
+typedef DDSCAPS FAR* LPDDSCAPS;
+
+
+/*
+ * DDOSCAPS
+ */
+typedef struct _DDOSCAPS
+{
+    DWORD       dwCaps;         // capabilities of surface wanted
+} DDOSCAPS;
+
+typedef DDOSCAPS FAR* LPDDOSCAPS;
+
+/*
+ * This structure is used internally by DirectDraw.
+ */
+typedef struct _DDSCAPSEX
+{
+    DWORD       dwCaps2;
+    DWORD       dwCaps3;
+    union
+    {
+        DWORD       dwCaps4;
+        DWORD       dwVolumeDepth;
+    } DUMMYUNIONNAMEN(1);
+} DDSCAPSEX, FAR * LPDDSCAPSEX;
+
+/*
+ * DDSCAPS2
+ */
+typedef struct _DDSCAPS2
+{
+    DWORD       dwCaps;         // capabilities of surface wanted
+    DWORD       dwCaps2;
+    DWORD       dwCaps3;
+    union
+    {
+        DWORD       dwCaps4;
+        DWORD       dwVolumeDepth;
+    } DUMMYUNIONNAMEN(1);
+} DDSCAPS2;
+
+typedef DDSCAPS2 FAR* LPDDSCAPS2;
+
+/*
+ * DDCAPS
+ */
+#define DD_ROP_SPACE            (256/32)        // space required to store ROP array
+/*
+ * NOTE: Our choosen structure number scheme is to append a single digit to
+ * the end of the structure giving the version that structure is associated
+ * with.
+ */
+
+/*
+ * This structure represents the DDCAPS structure released in DirectDraw 1.0.  It is used internally
+ * by DirectDraw to interpret caps passed into ddraw by drivers written prior to the release of DirectDraw 2.0.
+ * New applications should use the DDCAPS structure defined below.
+ */
+typedef struct _DDCAPS_DX1
+{
+    DWORD       dwSize;                 // size of the DDDRIVERCAPS structure
+    DWORD       dwCaps;                 // driver specific capabilities
+    DWORD       dwCaps2;                // more driver specific capabilites
+    DWORD       dwCKeyCaps;             // color key capabilities of the surface
+    DWORD       dwFXCaps;               // driver specific stretching and effects capabilites
+    DWORD       dwFXAlphaCaps;          // alpha driver specific capabilities
+    DWORD       dwPalCaps;              // palette capabilities
+    DWORD       dwSVCaps;               // stereo vision capabilities
+    DWORD       dwAlphaBltConstBitDepths;       // DDBD_2,4,8
+    DWORD       dwAlphaBltPixelBitDepths;       // DDBD_1,2,4,8
+    DWORD       dwAlphaBltSurfaceBitDepths;     // DDBD_1,2,4,8
+    DWORD       dwAlphaOverlayConstBitDepths;   // DDBD_2,4,8
+    DWORD       dwAlphaOverlayPixelBitDepths;   // DDBD_1,2,4,8
+    DWORD       dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8
+    DWORD       dwZBufferBitDepths;             // DDBD_8,16,24,32
+    DWORD       dwVidMemTotal;          // total amount of video memory
+    DWORD       dwVidMemFree;           // amount of free video memory
+    DWORD       dwMaxVisibleOverlays;   // maximum number of visible overlays
+    DWORD       dwCurrVisibleOverlays;  // current number of visible overlays
+    DWORD       dwNumFourCCCodes;       // number of four cc codes
+    DWORD       dwAlignBoundarySrc;     // source rectangle alignment
+    DWORD       dwAlignSizeSrc;         // source rectangle byte size
+    DWORD       dwAlignBoundaryDest;    // dest rectangle alignment
+    DWORD       dwAlignSizeDest;        // dest rectangle byte size
+    DWORD       dwAlignStrideAlign;     // stride alignment
+    DWORD       dwRops[DD_ROP_SPACE];   // ROPS supported
+    DDSCAPS     ddsCaps;                // DDSCAPS structure has all the general capabilities
+    DWORD       dwMinOverlayStretch;    // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxOverlayStretch;    // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMinLiveVideoStretch;  // OBSOLETE! This field remains for compatability reasons only
+    DWORD       dwMaxLiveVideoStretch;  // OBSOLETE! This field remains for compatability reasons only
+    DWORD       dwMinHwCodecStretch;    // OBSOLETE! This field remains for compatability reasons only
+    DWORD       dwMaxHwCodecStretch;    // OBSOLETE! This field remains for compatability reasons only
+    DWORD       dwReserved1;            // reserved
+    DWORD       dwReserved2;            // reserved
+    DWORD       dwReserved3;            // reserved
+} DDCAPS_DX1;
+
+typedef DDCAPS_DX1 FAR* LPDDCAPS_DX1;
+
+/*
+ * This structure is the DDCAPS structure as it was in version 2 and 3 of Direct X.
+ * It is present for back compatability.
+ */
+typedef struct _DDCAPS_DX3
+{
+    DWORD       dwSize;                 // size of the DDDRIVERCAPS structure
+    DWORD       dwCaps;                 // driver specific capabilities
+    DWORD       dwCaps2;                // more driver specific capabilites
+    DWORD       dwCKeyCaps;             // color key capabilities of the surface
+    DWORD       dwFXCaps;               // driver specific stretching and effects capabilites
+    DWORD       dwFXAlphaCaps;          // alpha driver specific capabilities
+    DWORD       dwPalCaps;              // palette capabilities
+    DWORD       dwSVCaps;               // stereo vision capabilities
+    DWORD       dwAlphaBltConstBitDepths;       // DDBD_2,4,8
+    DWORD       dwAlphaBltPixelBitDepths;       // DDBD_1,2,4,8
+    DWORD       dwAlphaBltSurfaceBitDepths;     // DDBD_1,2,4,8
+    DWORD       dwAlphaOverlayConstBitDepths;   // DDBD_2,4,8
+    DWORD       dwAlphaOverlayPixelBitDepths;   // DDBD_1,2,4,8
+    DWORD       dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8
+    DWORD       dwZBufferBitDepths;             // DDBD_8,16,24,32
+    DWORD       dwVidMemTotal;          // total amount of video memory
+    DWORD       dwVidMemFree;           // amount of free video memory
+    DWORD       dwMaxVisibleOverlays;   // maximum number of visible overlays
+    DWORD       dwCurrVisibleOverlays;  // current number of visible overlays
+    DWORD       dwNumFourCCCodes;       // number of four cc codes
+    DWORD       dwAlignBoundarySrc;     // source rectangle alignment
+    DWORD       dwAlignSizeSrc;         // source rectangle byte size
+    DWORD       dwAlignBoundaryDest;    // dest rectangle alignment
+    DWORD       dwAlignSizeDest;        // dest rectangle byte size
+    DWORD       dwAlignStrideAlign;     // stride alignment
+    DWORD       dwRops[DD_ROP_SPACE];   // ROPS supported
+    DDSCAPS     ddsCaps;                // DDSCAPS structure has all the general capabilities
+    DWORD       dwMinOverlayStretch;    // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxOverlayStretch;    // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMinLiveVideoStretch;  // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxLiveVideoStretch;  // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMinHwCodecStretch;    // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxHwCodecStretch;    // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwReserved1;            // reserved
+    DWORD       dwReserved2;            // reserved
+    DWORD       dwReserved3;            // reserved
+    DWORD       dwSVBCaps;              // driver specific capabilities for System->Vmem blts
+    DWORD       dwSVBCKeyCaps;          // driver color key capabilities for System->Vmem blts
+    DWORD       dwSVBFXCaps;            // driver FX capabilities for System->Vmem blts
+    DWORD       dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts
+    DWORD       dwVSBCaps;              // driver specific capabilities for Vmem->System blts
+    DWORD       dwVSBCKeyCaps;          // driver color key capabilities for Vmem->System blts
+    DWORD       dwVSBFXCaps;            // driver FX capabilities for Vmem->System blts
+    DWORD       dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts
+    DWORD       dwSSBCaps;              // driver specific capabilities for System->System blts
+    DWORD       dwSSBCKeyCaps;          // driver color key capabilities for System->System blts
+    DWORD       dwSSBFXCaps;            // driver FX capabilities for System->System blts
+    DWORD       dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts
+    DWORD       dwReserved4;            // reserved
+    DWORD       dwReserved5;            // reserved
+    DWORD       dwReserved6;            // reserved
+} DDCAPS_DX3;
+typedef DDCAPS_DX3 FAR* LPDDCAPS_DX3;
+
+/*
+ * This structure is the DDCAPS structure as it was in version 5 of Direct X.
+ * It is present for back compatability.
+ */
+typedef struct _DDCAPS_DX5
+{
+/*  0*/ DWORD   dwSize;                 // size of the DDDRIVERCAPS structure
+/*  4*/ DWORD   dwCaps;                 // driver specific capabilities
+/*  8*/ DWORD   dwCaps2;                // more driver specific capabilites
+/*  c*/ DWORD   dwCKeyCaps;             // color key capabilities of the surface
+/* 10*/ DWORD   dwFXCaps;               // driver specific stretching and effects capabilites
+/* 14*/ DWORD   dwFXAlphaCaps;          // alpha driver specific capabilities
+/* 18*/ DWORD   dwPalCaps;              // palette capabilities
+/* 1c*/ DWORD   dwSVCaps;               // stereo vision capabilities
+/* 20*/ DWORD   dwAlphaBltConstBitDepths;       // DDBD_2,4,8
+/* 24*/ DWORD   dwAlphaBltPixelBitDepths;       // DDBD_1,2,4,8
+/* 28*/ DWORD   dwAlphaBltSurfaceBitDepths;     // DDBD_1,2,4,8
+/* 2c*/ DWORD   dwAlphaOverlayConstBitDepths;   // DDBD_2,4,8
+/* 30*/ DWORD   dwAlphaOverlayPixelBitDepths;   // DDBD_1,2,4,8
+/* 34*/ DWORD   dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8
+/* 38*/ DWORD   dwZBufferBitDepths;             // DDBD_8,16,24,32
+/* 3c*/ DWORD   dwVidMemTotal;          // total amount of video memory
+/* 40*/ DWORD   dwVidMemFree;           // amount of free video memory
+/* 44*/ DWORD   dwMaxVisibleOverlays;   // maximum number of visible overlays
+/* 48*/ DWORD   dwCurrVisibleOverlays;  // current number of visible overlays
+/* 4c*/ DWORD   dwNumFourCCCodes;       // number of four cc codes
+/* 50*/ DWORD   dwAlignBoundarySrc;     // source rectangle alignment
+/* 54*/ DWORD   dwAlignSizeSrc;         // source rectangle byte size
+/* 58*/ DWORD   dwAlignBoundaryDest;    // dest rectangle alignment
+/* 5c*/ DWORD   dwAlignSizeDest;        // dest rectangle byte size
+/* 60*/ DWORD   dwAlignStrideAlign;     // stride alignment
+/* 64*/ DWORD   dwRops[DD_ROP_SPACE];   // ROPS supported
+/* 84*/ DDSCAPS ddsCaps;                // DDSCAPS structure has all the general capabilities
+/* 88*/ DWORD   dwMinOverlayStretch;    // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 8c*/ DWORD   dwMaxOverlayStretch;    // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 90*/ DWORD   dwMinLiveVideoStretch;  // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 94*/ DWORD   dwMaxLiveVideoStretch;  // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 98*/ DWORD   dwMinHwCodecStretch;    // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 9c*/ DWORD   dwMaxHwCodecStretch;    // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* a0*/ DWORD   dwReserved1;            // reserved
+/* a4*/ DWORD   dwReserved2;            // reserved
+/* a8*/ DWORD   dwReserved3;            // reserved
+/* ac*/ DWORD   dwSVBCaps;              // driver specific capabilities for System->Vmem blts
+/* b0*/ DWORD   dwSVBCKeyCaps;          // driver color key capabilities for System->Vmem blts
+/* b4*/ DWORD   dwSVBFXCaps;            // driver FX capabilities for System->Vmem blts
+/* b8*/ DWORD   dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts
+/* d8*/ DWORD   dwVSBCaps;              // driver specific capabilities for Vmem->System blts
+/* dc*/ DWORD   dwVSBCKeyCaps;          // driver color key capabilities for Vmem->System blts
+/* e0*/ DWORD   dwVSBFXCaps;            // driver FX capabilities for Vmem->System blts
+/* e4*/ DWORD   dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts
+/*104*/ DWORD   dwSSBCaps;              // driver specific capabilities for System->System blts
+/*108*/ DWORD   dwSSBCKeyCaps;          // driver color key capabilities for System->System blts
+/*10c*/ DWORD   dwSSBFXCaps;            // driver FX capabilities for System->System blts
+/*110*/ DWORD   dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts
+// Members added for DX5:
+/*130*/ DWORD   dwMaxVideoPorts;        // maximum number of usable video ports
+/*134*/ DWORD   dwCurrVideoPorts;       // current number of video ports used
+/*138*/ DWORD   dwSVBCaps2;             // more driver specific capabilities for System->Vmem blts
+/*13c*/ DWORD   dwNLVBCaps;               // driver specific capabilities for non-local->local vidmem blts
+/*140*/ DWORD   dwNLVBCaps2;              // more driver specific capabilities non-local->local vidmem blts
+/*144*/ DWORD   dwNLVBCKeyCaps;           // driver color key capabilities for non-local->local vidmem blts
+/*148*/ DWORD   dwNLVBFXCaps;             // driver FX capabilities for non-local->local blts
+/*14c*/ DWORD   dwNLVBRops[DD_ROP_SPACE]; // ROPS supported for non-local->local blts
+} DDCAPS_DX5;
+typedef DDCAPS_DX5 FAR* LPDDCAPS_DX5;
+
+typedef struct _DDCAPS_DX6
+{
+/*  0*/ DWORD   dwSize;                 // size of the DDDRIVERCAPS structure
+/*  4*/ DWORD   dwCaps;                 // driver specific capabilities
+/*  8*/ DWORD   dwCaps2;                // more driver specific capabilites
+/*  c*/ DWORD   dwCKeyCaps;             // color key capabilities of the surface
+/* 10*/ DWORD   dwFXCaps;               // driver specific stretching and effects capabilites
+/* 14*/ DWORD   dwFXAlphaCaps;          // alpha caps
+/* 18*/ DWORD   dwPalCaps;              // palette capabilities
+/* 1c*/ DWORD   dwSVCaps;               // stereo vision capabilities
+/* 20*/ DWORD   dwAlphaBltConstBitDepths;       // DDBD_2,4,8
+/* 24*/ DWORD   dwAlphaBltPixelBitDepths;       // DDBD_1,2,4,8
+/* 28*/ DWORD   dwAlphaBltSurfaceBitDepths;     // DDBD_1,2,4,8
+/* 2c*/ DWORD   dwAlphaOverlayConstBitDepths;   // DDBD_2,4,8
+/* 30*/ DWORD   dwAlphaOverlayPixelBitDepths;   // DDBD_1,2,4,8
+/* 34*/ DWORD   dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8
+/* 38*/ DWORD   dwZBufferBitDepths;             // DDBD_8,16,24,32
+/* 3c*/ DWORD   dwVidMemTotal;          // total amount of video memory
+/* 40*/ DWORD   dwVidMemFree;           // amount of free video memory
+/* 44*/ DWORD   dwMaxVisibleOverlays;   // maximum number of visible overlays
+/* 48*/ DWORD   dwCurrVisibleOverlays;  // current number of visible overlays
+/* 4c*/ DWORD   dwNumFourCCCodes;       // number of four cc codes
+/* 50*/ DWORD   dwAlignBoundarySrc;     // source rectangle alignment
+/* 54*/ DWORD   dwAlignSizeSrc;         // source rectangle byte size
+/* 58*/ DWORD   dwAlignBoundaryDest;    // dest rectangle alignment
+/* 5c*/ DWORD   dwAlignSizeDest;        // dest rectangle byte size
+/* 60*/ DWORD   dwAlignStrideAlign;     // stride alignment
+/* 64*/ DWORD   dwRops[DD_ROP_SPACE];   // ROPS supported
+/* 84*/ DDSCAPS ddsOldCaps;             // Was DDSCAPS  ddsCaps. ddsCaps is of type DDSCAPS2 for DX6
+/* 88*/ DWORD   dwMinOverlayStretch;    // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 8c*/ DWORD   dwMaxOverlayStretch;    // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 90*/ DWORD   dwMinLiveVideoStretch;  // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 94*/ DWORD   dwMaxLiveVideoStretch;  // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 98*/ DWORD   dwMinHwCodecStretch;    // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 9c*/ DWORD   dwMaxHwCodecStretch;    // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* a0*/ DWORD   dwReserved1;            // reserved
+/* a4*/ DWORD   dwReserved2;            // reserved
+/* a8*/ DWORD   dwReserved3;            // reserved
+/* ac*/ DWORD   dwSVBCaps;              // driver specific capabilities for System->Vmem blts
+/* b0*/ DWORD   dwSVBCKeyCaps;          // driver color key capabilities for System->Vmem blts
+/* b4*/ DWORD   dwSVBFXCaps;            // driver FX capabilities for System->Vmem blts
+/* b8*/ DWORD   dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts
+/* d8*/ DWORD   dwVSBCaps;              // driver specific capabilities for Vmem->System blts
+/* dc*/ DWORD   dwVSBCKeyCaps;          // driver color key capabilities for Vmem->System blts
+/* e0*/ DWORD   dwVSBFXCaps;            // driver FX capabilities for Vmem->System blts
+/* e4*/ DWORD   dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts
+/*104*/ DWORD   dwSSBCaps;              // driver specific capabilities for System->System blts
+/*108*/ DWORD   dwSSBCKeyCaps;          // driver color key capabilities for System->System blts
+/*10c*/ DWORD   dwSSBFXCaps;            // driver FX capabilities for System->System blts
+/*110*/ DWORD   dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts
+/*130*/ DWORD   dwMaxVideoPorts;        // maximum number of usable video ports
+/*134*/ DWORD   dwCurrVideoPorts;       // current number of video ports used
+/*138*/ DWORD   dwSVBCaps2;             // more driver specific capabilities for System->Vmem blts
+/*13c*/ DWORD   dwNLVBCaps;               // driver specific capabilities for non-local->local vidmem blts
+/*140*/ DWORD   dwNLVBCaps2;              // more driver specific capabilities non-local->local vidmem blts
+/*144*/ DWORD   dwNLVBCKeyCaps;           // driver color key capabilities for non-local->local vidmem blts
+/*148*/ DWORD   dwNLVBFXCaps;             // driver FX capabilities for non-local->local blts
+/*14c*/ DWORD   dwNLVBRops[DD_ROP_SPACE]; // ROPS supported for non-local->local blts
+// Members added for DX6 release
+/*16c*/ DDSCAPS2 ddsCaps;               // Surface Caps
+} DDCAPS_DX6;
+typedef DDCAPS_DX6 FAR* LPDDCAPS_DX6;
+
+typedef struct _DDCAPS_DX7
+{
+/*  0*/ DWORD   dwSize;                 // size of the DDDRIVERCAPS structure
+/*  4*/ DWORD   dwCaps;                 // driver specific capabilities
+/*  8*/ DWORD   dwCaps2;                // more driver specific capabilites
+/*  c*/ DWORD   dwCKeyCaps;             // color key capabilities of the surface
+/* 10*/ DWORD   dwFXCaps;               // driver specific stretching and effects capabilites
+/* 14*/ DWORD   dwFXAlphaCaps;          // alpha driver specific capabilities
+/* 18*/ DWORD   dwPalCaps;              // palette capabilities
+/* 1c*/ DWORD   dwSVCaps;               // stereo vision capabilities
+/* 20*/ DWORD   dwAlphaBltConstBitDepths;       // DDBD_2,4,8
+/* 24*/ DWORD   dwAlphaBltPixelBitDepths;       // DDBD_1,2,4,8
+/* 28*/ DWORD   dwAlphaBltSurfaceBitDepths;     // DDBD_1,2,4,8
+/* 2c*/ DWORD   dwAlphaOverlayConstBitDepths;   // DDBD_2,4,8
+/* 30*/ DWORD   dwAlphaOverlayPixelBitDepths;   // DDBD_1,2,4,8
+/* 34*/ DWORD   dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8
+/* 38*/ DWORD   dwZBufferBitDepths;             // DDBD_8,16,24,32
+/* 3c*/ DWORD   dwVidMemTotal;          // total amount of video memory
+/* 40*/ DWORD   dwVidMemFree;           // amount of free video memory
+/* 44*/ DWORD   dwMaxVisibleOverlays;   // maximum number of visible overlays
+/* 48*/ DWORD   dwCurrVisibleOverlays;  // current number of visible overlays
+/* 4c*/ DWORD   dwNumFourCCCodes;       // number of four cc codes
+/* 50*/ DWORD   dwAlignBoundarySrc;     // source rectangle alignment
+/* 54*/ DWORD   dwAlignSizeSrc;         // source rectangle byte size
+/* 58*/ DWORD   dwAlignBoundaryDest;    // dest rectangle alignment
+/* 5c*/ DWORD   dwAlignSizeDest;        // dest rectangle byte size
+/* 60*/ DWORD   dwAlignStrideAlign;     // stride alignment
+/* 64*/ DWORD   dwRops[DD_ROP_SPACE];   // ROPS supported
+/* 84*/ DDSCAPS ddsOldCaps;             // Was DDSCAPS  ddsCaps. ddsCaps is of type DDSCAPS2 for DX6
+/* 88*/ DWORD   dwMinOverlayStretch;    // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 8c*/ DWORD   dwMaxOverlayStretch;    // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 90*/ DWORD   dwMinLiveVideoStretch;  // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 94*/ DWORD   dwMaxLiveVideoStretch;  // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 98*/ DWORD   dwMinHwCodecStretch;    // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* 9c*/ DWORD   dwMaxHwCodecStretch;    // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+/* a0*/ DWORD   dwReserved1;            // reserved
+/* a4*/ DWORD   dwReserved2;            // reserved
+/* a8*/ DWORD   dwReserved3;            // reserved
+/* ac*/ DWORD   dwSVBCaps;              // driver specific capabilities for System->Vmem blts
+/* b0*/ DWORD   dwSVBCKeyCaps;          // driver color key capabilities for System->Vmem blts
+/* b4*/ DWORD   dwSVBFXCaps;            // driver FX capabilities for System->Vmem blts
+/* b8*/ DWORD   dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts
+/* d8*/ DWORD   dwVSBCaps;              // driver specific capabilities for Vmem->System blts
+/* dc*/ DWORD   dwVSBCKeyCaps;          // driver color key capabilities for Vmem->System blts
+/* e0*/ DWORD   dwVSBFXCaps;            // driver FX capabilities for Vmem->System blts
+/* e4*/ DWORD   dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts
+/*104*/ DWORD   dwSSBCaps;              // driver specific capabilities for System->System blts
+/*108*/ DWORD   dwSSBCKeyCaps;          // driver color key capabilities for System->System blts
+/*10c*/ DWORD   dwSSBFXCaps;            // driver FX capabilities for System->System blts
+/*110*/ DWORD   dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts
+/*130*/ DWORD   dwMaxVideoPorts;        // maximum number of usable video ports
+/*134*/ DWORD   dwCurrVideoPorts;       // current number of video ports used
+/*138*/ DWORD   dwSVBCaps2;             // more driver specific capabilities for System->Vmem blts
+/*13c*/ DWORD   dwNLVBCaps;               // driver specific capabilities for non-local->local vidmem blts
+/*140*/ DWORD   dwNLVBCaps2;              // more driver specific capabilities non-local->local vidmem blts
+/*144*/ DWORD   dwNLVBCKeyCaps;           // driver color key capabilities for non-local->local vidmem blts
+/*148*/ DWORD   dwNLVBFXCaps;             // driver FX capabilities for non-local->local blts
+/*14c*/ DWORD   dwNLVBRops[DD_ROP_SPACE]; // ROPS supported for non-local->local blts
+// Members added for DX6 release
+/*16c*/ DDSCAPS2 ddsCaps;               // Surface Caps
+} DDCAPS_DX7;
+typedef DDCAPS_DX7 FAR* LPDDCAPS_DX7;
+
+
+#if DIRECTDRAW_VERSION <= 0x300
+    typedef DDCAPS_DX3 DDCAPS;
+#elif DIRECTDRAW_VERSION <= 0x500
+    typedef DDCAPS_DX5 DDCAPS;
+#elif DIRECTDRAW_VERSION <= 0x600
+    typedef DDCAPS_DX6 DDCAPS;
+#else
+    typedef DDCAPS_DX7 DDCAPS;
+#endif
+
+typedef DDCAPS FAR* LPDDCAPS;
+
+
+
+/*
+ * DDPIXELFORMAT
+ */
+typedef struct _DDPIXELFORMAT
+{
+    DWORD       dwSize;                 // size of structure
+    DWORD       dwFlags;                // pixel format flags
+    DWORD       dwFourCC;               // (FOURCC code)
+    union
+    {
+        DWORD   dwRGBBitCount;          // how many bits per pixel
+        DWORD   dwYUVBitCount;          // how many bits per pixel
+        DWORD   dwZBufferBitDepth;      // how many total bits/pixel in z buffer (including any stencil bits)
+        DWORD   dwAlphaBitDepth;        // how many bits for alpha channels
+        DWORD   dwLuminanceBitCount;    // how many bits per pixel
+        DWORD   dwBumpBitCount;         // how many bits per "buxel", total
+        DWORD   dwPrivateFormatBitCount;// Bits per pixel of private driver formats. Only valid in texture
+                                        // format list and if DDPF_D3DFORMAT is set
+    } DUMMYUNIONNAMEN(1);
+    union
+    {
+        DWORD   dwRBitMask;             // mask for red bit
+        DWORD   dwYBitMask;             // mask for Y bits
+        DWORD   dwStencilBitDepth;      // how many stencil bits (note: dwZBufferBitDepth-dwStencilBitDepth is total Z-only bits)
+        DWORD   dwLuminanceBitMask;     // mask for luminance bits
+        DWORD   dwBumpDuBitMask;        // mask for bump map U delta bits
+        DWORD   dwOperations;           // DDPF_D3DFORMAT Operations
+    } DUMMYUNIONNAMEN(2);
+    union
+    {
+        DWORD   dwGBitMask;             // mask for green bits
+        DWORD   dwUBitMask;             // mask for U bits
+        DWORD   dwZBitMask;             // mask for Z bits
+        DWORD   dwBumpDvBitMask;        // mask for bump map V delta bits
+        struct
+        {
+            WORD    wFlipMSTypes;       // Multisample methods supported via flip for this D3DFORMAT
+            WORD    wBltMSTypes;        // Multisample methods supported via blt for this D3DFORMAT
+        } MultiSampleCaps;
+
+    } DUMMYUNIONNAMEN(3);
+    union
+    {
+        DWORD   dwBBitMask;             // mask for blue bits
+        DWORD   dwVBitMask;             // mask for V bits
+        DWORD   dwStencilBitMask;       // mask for stencil bits
+        DWORD   dwBumpLuminanceBitMask; // mask for luminance in bump map
+    } DUMMYUNIONNAMEN(4);
+    union
+    {
+        DWORD   dwRGBAlphaBitMask;      // mask for alpha channel
+        DWORD   dwYUVAlphaBitMask;      // mask for alpha channel
+        DWORD   dwLuminanceAlphaBitMask;// mask for alpha channel
+        DWORD   dwRGBZBitMask;          // mask for Z channel
+        DWORD   dwYUVZBitMask;          // mask for Z channel
+    } DUMMYUNIONNAMEN(5);
+} DDPIXELFORMAT;
+
+typedef DDPIXELFORMAT FAR* LPDDPIXELFORMAT;
+
+/*
+ * DDOVERLAYFX
+ */
+typedef struct _DDOVERLAYFX
+{
+    DWORD       dwSize;                         // size of structure
+    DWORD       dwAlphaEdgeBlendBitDepth;       // Bit depth used to specify constant for alpha edge blend
+    DWORD       dwAlphaEdgeBlend;               // Constant to use as alpha for edge blend
+    DWORD       dwReserved;
+    DWORD       dwAlphaDestConstBitDepth;       // Bit depth used to specify alpha constant for destination
+    union
+    {
+        DWORD   dwAlphaDestConst;               // Constant to use as alpha channel for dest
+        LPDIRECTDRAWSURFACE lpDDSAlphaDest;     // Surface to use as alpha channel for dest
+    } DUMMYUNIONNAMEN(1);
+    DWORD       dwAlphaSrcConstBitDepth;        // Bit depth used to specify alpha constant for source
+    union
+    {
+        DWORD   dwAlphaSrcConst;                // Constant to use as alpha channel for src
+        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      // Surface to use as alpha channel for src
+    } DUMMYUNIONNAMEN(2);
+    DDCOLORKEY  dckDestColorkey;                // DestColorkey override
+    DDCOLORKEY  dckSrcColorkey;                 // DestColorkey override
+    DWORD       dwDDFX;                         // Overlay FX
+    DWORD       dwFlags;                        // flags
+} DDOVERLAYFX;
+
+typedef DDOVERLAYFX FAR *LPDDOVERLAYFX;
+
+
+/*
+ * DDBLTBATCH: BltBatch entry structure
+ */
+typedef struct _DDBLTBATCH
+{
+    LPRECT              lprDest;
+    LPDIRECTDRAWSURFACE lpDDSSrc;
+    LPRECT              lprSrc;
+    DWORD               dwFlags;
+    LPDDBLTFX           lpDDBltFx;
+} DDBLTBATCH;
+
+typedef DDBLTBATCH FAR * LPDDBLTBATCH;
+
+
+/*
+ * DDGAMMARAMP
+ */
+typedef struct _DDGAMMARAMP
+{
+    WORD                red[256];
+    WORD                green[256];
+    WORD                blue[256];
+} DDGAMMARAMP;
+typedef DDGAMMARAMP FAR * LPDDGAMMARAMP;
+
+/*
+ *  This is the structure within which DirectDraw returns data about the current graphics driver and chipset
+ */
+
+#define MAX_DDDEVICEID_STRING           512
+
+typedef struct tagDDDEVICEIDENTIFIER
+{
+    /*
+     * These elements are for presentation to the user only. They should not be used to identify particular
+     * drivers, since this is unreliable and many different strings may be associated with the same
+     * device, and the same driver from different vendors.
+     */
+    char    szDriver[MAX_DDDEVICEID_STRING];
+    char    szDescription[MAX_DDDEVICEID_STRING];
+
+    /*
+     * This element is the version of the DirectDraw/3D driver. It is legal to do <, > comparisons
+     * on the whole 64 bits. Caution should be exercised if you use this element to identify problematic
+     * drivers. It is recommended that guidDeviceIdentifier is used for this purpose.
+     *
+     * This version has the form:
+     *  wProduct = HIWORD(liDriverVersion.HighPart)
+     *  wVersion = LOWORD(liDriverVersion.HighPart)
+     *  wSubVersion = HIWORD(liDriverVersion.LowPart)
+     *  wBuild = LOWORD(liDriverVersion.LowPart)
+     */
+#ifdef _WIN32
+    LARGE_INTEGER liDriverVersion;      /* Defined for applications and other 32 bit components */
+#else
+    DWORD   dwDriverVersionLowPart;     /* Defined for 16 bit driver components */
+    DWORD   dwDriverVersionHighPart;
+#endif
+
+
+    /*
+     * These elements can be used to identify particular chipsets. Use with extreme caution.
+     *   dwVendorId     Identifies the manufacturer. May be zero if unknown.
+     *   dwDeviceId     Identifies the type of chipset. May be zero if unknown.
+     *   dwSubSysId     Identifies the subsystem, typically this means the particular board. May be zero if unknown.
+     *   dwRevision     Identifies the revision level of the chipset. May be zero if unknown.
+     */
+    DWORD   dwVendorId;
+    DWORD   dwDeviceId;
+    DWORD   dwSubSysId;
+    DWORD   dwRevision;
+
+    /*
+     * This element can be used to check changes in driver/chipset. This GUID is a unique identifier for the
+     * driver/chipset pair. Use this element if you wish to track changes to the driver/chipset in order to
+     * reprofile the graphics subsystem.
+     * This element can also be used to identify particular problematic drivers.
+     */
+    GUID    guidDeviceIdentifier;
+} DDDEVICEIDENTIFIER, * LPDDDEVICEIDENTIFIER;
+
+typedef struct tagDDDEVICEIDENTIFIER2
+{
+    /*
+     * These elements are for presentation to the user only. They should not be used to identify particular
+     * drivers, since this is unreliable and many different strings may be associated with the same
+     * device, and the same driver from different vendors.
+     */
+    char    szDriver[MAX_DDDEVICEID_STRING];
+    char    szDescription[MAX_DDDEVICEID_STRING];
+
+    /*
+     * This element is the version of the DirectDraw/3D driver. It is legal to do <, > comparisons
+     * on the whole 64 bits. Caution should be exercised if you use this element to identify problematic
+     * drivers. It is recommended that guidDeviceIdentifier is used for this purpose.
+     *
+     * This version has the form:
+     *  wProduct = HIWORD(liDriverVersion.HighPart)
+     *  wVersion = LOWORD(liDriverVersion.HighPart)
+     *  wSubVersion = HIWORD(liDriverVersion.LowPart)
+     *  wBuild = LOWORD(liDriverVersion.LowPart)
+     */
+#ifdef _WIN32
+    LARGE_INTEGER liDriverVersion;      /* Defined for applications and other 32 bit components */
+#else
+    DWORD   dwDriverVersionLowPart;     /* Defined for 16 bit driver components */
+    DWORD   dwDriverVersionHighPart;
+#endif
+
+
+    /*
+     * These elements can be used to identify particular chipsets. Use with extreme caution.
+     *   dwVendorId     Identifies the manufacturer. May be zero if unknown.
+     *   dwDeviceId     Identifies the type of chipset. May be zero if unknown.
+     *   dwSubSysId     Identifies the subsystem, typically this means the particular board. May be zero if unknown.
+     *   dwRevision     Identifies the revision level of the chipset. May be zero if unknown.
+     */
+    DWORD   dwVendorId;
+    DWORD   dwDeviceId;
+    DWORD   dwSubSysId;
+    DWORD   dwRevision;
+
+    /*
+     * This element can be used to check changes in driver/chipset. This GUID is a unique identifier for the
+     * driver/chipset pair. Use this element if you wish to track changes to the driver/chipset in order to
+     * reprofile the graphics subsystem.
+     * This element can also be used to identify particular problematic drivers.
+     */
+    GUID    guidDeviceIdentifier;
+
+    /*
+     * This element is used to determine the Windows Hardware Quality Lab (WHQL)
+     * certification level for this driver/device pair.
+     */
+    DWORD   dwWHQLLevel;
+
+} DDDEVICEIDENTIFIER2, * LPDDDEVICEIDENTIFIER2;
+
+/*
+ * Flags for the IDirectDraw4::GetDeviceIdentifier method
+ */
+
+/*
+ * This flag causes GetDeviceIdentifier to return information about the host (typically 2D) adapter in a system equipped
+ * with a stacked secondary 3D adapter. Such an adapter appears to the application as if it were part of the
+ * host adapter, but is typically physcially located on a separate card. The stacked secondary's information is
+ * returned when GetDeviceIdentifier's dwFlags field is zero, since this most accurately reflects the qualities
+ * of the DirectDraw object involved.
+ */
+#define DDGDI_GETHOSTIDENTIFIER         0x00000001L
+
+/*
+ * Macros for interpretting DDEVICEIDENTIFIER2.dwWHQLLevel
+ */
+#define GET_WHQL_YEAR( dwWHQLLevel ) \
+    ( (dwWHQLLevel) / 0x10000 )
+#define GET_WHQL_MONTH( dwWHQLLevel ) \
+    ( ( (dwWHQLLevel) / 0x100 ) & 0x00ff )
+#define GET_WHQL_DAY( dwWHQLLevel ) \
+    ( (dwWHQLLevel) & 0xff )
+
+
+/*
+ * callbacks
+ */
+typedef DWORD   (FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper, HWND hWnd, DWORD code, LPVOID lpContext );
+#ifdef STREAMING
+typedef DWORD   (FAR PASCAL *LPSURFACESTREAMINGCALLBACK)(DWORD);
+#endif
+
+
+/*
+ * INTERACES FOLLOW:
+ *      IDirectDraw
+ *      IDirectDrawClipper
+ *      IDirectDrawPalette
+ *      IDirectDrawSurface
+ */
+
+/*
+ * IDirectDraw
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDraw
+DECLARE_INTERFACE_( IDirectDraw, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDraw_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDraw_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirectDraw_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirectDraw_Compact(p)                      (p)->lpVtbl->Compact(p)
+#define IDirectDraw_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
+#define IDirectDraw_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
+#define IDirectDraw_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
+#define IDirectDraw_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
+#define IDirectDraw_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
+#define IDirectDraw_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
+#define IDirectDraw_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
+#define IDirectDraw_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirectDraw_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
+#define IDirectDraw_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
+#define IDirectDraw_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
+#define IDirectDraw_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
+#define IDirectDraw_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
+#define IDirectDraw_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
+#define IDirectDraw_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirectDraw_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
+#define IDirectDraw_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
+#define IDirectDraw_SetDisplayMode(p, a, b, c)      (p)->lpVtbl->SetDisplayMode(p, a, b, c)
+#define IDirectDraw_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)
+#else
+#define IDirectDraw_QueryInterface(p, a, b)         (p)->QueryInterface(a, b)
+#define IDirectDraw_AddRef(p)                       (p)->AddRef()
+#define IDirectDraw_Release(p)                      (p)->Release()
+#define IDirectDraw_Compact(p)                      (p)->Compact()
+#define IDirectDraw_CreateClipper(p, a, b, c)       (p)->CreateClipper(a, b, c)
+#define IDirectDraw_CreatePalette(p, a, b, c, d)    (p)->CreatePalette(a, b, c, d)
+#define IDirectDraw_CreateSurface(p, a, b, c)       (p)->CreateSurface(a, b, c)
+#define IDirectDraw_DuplicateSurface(p, a, b)       (p)->DuplicateSurface(a, b)
+#define IDirectDraw_EnumDisplayModes(p, a, b, c, d) (p)->EnumDisplayModes(a, b, c, d)
+#define IDirectDraw_EnumSurfaces(p, a, b, c, d)     (p)->EnumSurfaces(a, b, c, d)
+#define IDirectDraw_FlipToGDISurface(p)             (p)->FlipToGDISurface()
+#define IDirectDraw_GetCaps(p, a, b)                (p)->GetCaps(a, b)
+#define IDirectDraw_GetDisplayMode(p, a)            (p)->GetDisplayMode(a)
+#define IDirectDraw_GetFourCCCodes(p, a, b)         (p)->GetFourCCCodes(a, b)
+#define IDirectDraw_GetGDISurface(p, a)             (p)->GetGDISurface(a)
+#define IDirectDraw_GetMonitorFrequency(p, a)       (p)->GetMonitorFrequency(a)
+#define IDirectDraw_GetScanLine(p, a)               (p)->GetScanLine(a)
+#define IDirectDraw_GetVerticalBlankStatus(p, a)    (p)->GetVerticalBlankStatus(a)
+#define IDirectDraw_Initialize(p, a)                (p)->Initialize(a)
+#define IDirectDraw_RestoreDisplayMode(p)           (p)->RestoreDisplayMode()
+#define IDirectDraw_SetCooperativeLevel(p, a, b)    (p)->SetCooperativeLevel(a, b)
+#define IDirectDraw_SetDisplayMode(p, a, b, c)      (p)->SetDisplayMode(a, b, c)
+#define IDirectDraw_WaitForVerticalBlank(p, a, b)   (p)->WaitForVerticalBlank(a, b)
+#endif
+
+#endif
+
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDraw2
+DECLARE_INTERFACE_( IDirectDraw2, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE;
+};
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDraw2_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDraw2_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirectDraw2_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirectDraw2_Compact(p)                      (p)->lpVtbl->Compact(p)
+#define IDirectDraw2_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
+#define IDirectDraw2_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
+#define IDirectDraw2_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
+#define IDirectDraw2_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
+#define IDirectDraw2_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
+#define IDirectDraw2_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
+#define IDirectDraw2_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
+#define IDirectDraw2_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirectDraw2_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
+#define IDirectDraw2_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
+#define IDirectDraw2_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
+#define IDirectDraw2_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
+#define IDirectDraw2_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
+#define IDirectDraw2_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
+#define IDirectDraw2_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirectDraw2_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
+#define IDirectDraw2_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
+#define IDirectDraw2_SetDisplayMode(p, a, b, c, d, e) (p)->lpVtbl->SetDisplayMode(p, a, b, c, d, e)
+#define IDirectDraw2_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)
+#define IDirectDraw2_GetAvailableVidMem(p, a, b, c)  (p)->lpVtbl->GetAvailableVidMem(p, a, b, c)
+#else
+#define IDirectDraw2_QueryInterface(p, a, b)         (p)->QueryInterface(a, b)
+#define IDirectDraw2_AddRef(p)                       (p)->AddRef()
+#define IDirectDraw2_Release(p)                      (p)->Release()
+#define IDirectDraw2_Compact(p)                      (p)->Compact()
+#define IDirectDraw2_CreateClipper(p, a, b, c)       (p)->CreateClipper(a, b, c)
+#define IDirectDraw2_CreatePalette(p, a, b, c, d)    (p)->CreatePalette(a, b, c, d)
+#define IDirectDraw2_CreateSurface(p, a, b, c)       (p)->CreateSurface(a, b, c)
+#define IDirectDraw2_DuplicateSurface(p, a, b)       (p)->DuplicateSurface(a, b)
+#define IDirectDraw2_EnumDisplayModes(p, a, b, c, d) (p)->EnumDisplayModes(a, b, c, d)
+#define IDirectDraw2_EnumSurfaces(p, a, b, c, d)     (p)->EnumSurfaces(a, b, c, d)
+#define IDirectDraw2_FlipToGDISurface(p)             (p)->FlipToGDISurface()
+#define IDirectDraw2_GetCaps(p, a, b)                (p)->GetCaps(a, b)
+#define IDirectDraw2_GetDisplayMode(p, a)            (p)->GetDisplayMode(a)
+#define IDirectDraw2_GetFourCCCodes(p, a, b)         (p)->GetFourCCCodes(a, b)
+#define IDirectDraw2_GetGDISurface(p, a)             (p)->GetGDISurface(a)
+#define IDirectDraw2_GetMonitorFrequency(p, a)       (p)->GetMonitorFrequency(a)
+#define IDirectDraw2_GetScanLine(p, a)               (p)->GetScanLine(a)
+#define IDirectDraw2_GetVerticalBlankStatus(p, a)    (p)->GetVerticalBlankStatus(a)
+#define IDirectDraw2_Initialize(p, a)                (p)->Initialize(a)
+#define IDirectDraw2_RestoreDisplayMode(p)           (p)->RestoreDisplayMode()
+#define IDirectDraw2_SetCooperativeLevel(p, a, b)    (p)->SetCooperativeLevel(a, b)
+#define IDirectDraw2_SetDisplayMode(p, a, b, c, d, e) (p)->SetDisplayMode(a, b, c, d, e)
+#define IDirectDraw2_WaitForVerticalBlank(p, a, b)   (p)->WaitForVerticalBlank(a, b)
+#define IDirectDraw2_GetAvailableVidMem(p, a, b, c)  (p)->GetAvailableVidMem(a, b, c)
+#endif
+
+#endif
+
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDraw4
+DECLARE_INTERFACE_( IDirectDraw4, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC2, LPDIRECTDRAWSURFACE4 FAR *, IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE4, LPDIRECTDRAWSURFACE4 FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC2, LPVOID, LPDDENUMMODESCALLBACK2 ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC2, LPVOID,LPDDENUMSURFACESCALLBACK2 ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC2) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE4 FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS2, LPDWORD, LPDWORD) PURE;
+    /*** Added in the V4 Interface ***/
+    STDMETHOD(GetSurfaceFromDC) (THIS_ HDC, LPDIRECTDRAWSURFACE4 *) PURE;
+    STDMETHOD(RestoreAllSurfaces)(THIS) PURE;
+    STDMETHOD(TestCooperativeLevel)(THIS) PURE;
+    STDMETHOD(GetDeviceIdentifier)(THIS_ LPDDDEVICEIDENTIFIER, DWORD ) PURE;
+};
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDraw4_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDraw4_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirectDraw4_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirectDraw4_Compact(p)                      (p)->lpVtbl->Compact(p)
+#define IDirectDraw4_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
+#define IDirectDraw4_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
+#define IDirectDraw4_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
+#define IDirectDraw4_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
+#define IDirectDraw4_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
+#define IDirectDraw4_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
+#define IDirectDraw4_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
+#define IDirectDraw4_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirectDraw4_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
+#define IDirectDraw4_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
+#define IDirectDraw4_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
+#define IDirectDraw4_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
+#define IDirectDraw4_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
+#define IDirectDraw4_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
+#define IDirectDraw4_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirectDraw4_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
+#define IDirectDraw4_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
+#define IDirectDraw4_SetDisplayMode(p, a, b, c, d, e) (p)->lpVtbl->SetDisplayMode(p, a, b, c, d, e)
+#define IDirectDraw4_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)
+#define IDirectDraw4_GetAvailableVidMem(p, a, b, c)  (p)->lpVtbl->GetAvailableVidMem(p, a, b, c)
+#define IDirectDraw4_GetSurfaceFromDC(p, a, b)       (p)->lpVtbl->GetSurfaceFromDC(p, a, b)
+#define IDirectDraw4_RestoreAllSurfaces(p)           (p)->lpVtbl->RestoreAllSurfaces(p)
+#define IDirectDraw4_TestCooperativeLevel(p)         (p)->lpVtbl->TestCooperativeLevel(p)
+#define IDirectDraw4_GetDeviceIdentifier(p,a,b)      (p)->lpVtbl->GetDeviceIdentifier(p,a,b)
+#else
+#define IDirectDraw4_QueryInterface(p, a, b)         (p)->QueryInterface(a, b)
+#define IDirectDraw4_AddRef(p)                       (p)->AddRef()
+#define IDirectDraw4_Release(p)                      (p)->Release()
+#define IDirectDraw4_Compact(p)                      (p)->Compact()
+#define IDirectDraw4_CreateClipper(p, a, b, c)       (p)->CreateClipper(a, b, c)
+#define IDirectDraw4_CreatePalette(p, a, b, c, d)    (p)->CreatePalette(a, b, c, d)
+#define IDirectDraw4_CreateSurface(p, a, b, c)       (p)->CreateSurface(a, b, c)
+#define IDirectDraw4_DuplicateSurface(p, a, b)       (p)->DuplicateSurface(a, b)
+#define IDirectDraw4_EnumDisplayModes(p, a, b, c, d) (p)->EnumDisplayModes(a, b, c, d)
+#define IDirectDraw4_EnumSurfaces(p, a, b, c, d)     (p)->EnumSurfaces(a, b, c, d)
+#define IDirectDraw4_FlipToGDISurface(p)             (p)->FlipToGDISurface()
+#define IDirectDraw4_GetCaps(p, a, b)                (p)->GetCaps(a, b)
+#define IDirectDraw4_GetDisplayMode(p, a)            (p)->GetDisplayMode(a)
+#define IDirectDraw4_GetFourCCCodes(p, a, b)         (p)->GetFourCCCodes(a, b)
+#define IDirectDraw4_GetGDISurface(p, a)             (p)->GetGDISurface(a)
+#define IDirectDraw4_GetMonitorFrequency(p, a)       (p)->GetMonitorFrequency(a)
+#define IDirectDraw4_GetScanLine(p, a)               (p)->GetScanLine(a)
+#define IDirectDraw4_GetVerticalBlankStatus(p, a)    (p)->GetVerticalBlankStatus(a)
+#define IDirectDraw4_Initialize(p, a)                (p)->Initialize(a)
+#define IDirectDraw4_RestoreDisplayMode(p)           (p)->RestoreDisplayMode()
+#define IDirectDraw4_SetCooperativeLevel(p, a, b)    (p)->SetCooperativeLevel(a, b)
+#define IDirectDraw4_SetDisplayMode(p, a, b, c, d, e) (p)->SetDisplayMode(a, b, c, d, e)
+#define IDirectDraw4_WaitForVerticalBlank(p, a, b)   (p)->WaitForVerticalBlank(a, b)
+#define IDirectDraw4_GetAvailableVidMem(p, a, b, c)  (p)->GetAvailableVidMem(a, b, c)
+#define IDirectDraw4_GetSurfaceFromDC(p, a, b)       (p)->GetSurfaceFromDC(a, b)
+#define IDirectDraw4_RestoreAllSurfaces(p)           (p)->RestoreAllSurfaces()
+#define IDirectDraw4_TestCooperativeLevel(p)         (p)->TestCooperativeLevel()
+#define IDirectDraw4_GetDeviceIdentifier(p,a,b)      (p)->GetDeviceIdentifier(a,b)
+#endif
+
+#endif
+
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDraw7
+DECLARE_INTERFACE_( IDirectDraw7, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC2, LPDIRECTDRAWSURFACE7 FAR *, IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE7, LPDIRECTDRAWSURFACE7 FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC2, LPVOID, LPDDENUMMODESCALLBACK2 ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC2, LPVOID,LPDDENUMSURFACESCALLBACK7 ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC2) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE7 FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS2, LPDWORD, LPDWORD) PURE;
+    /*** Added in the V4 Interface ***/
+    STDMETHOD(GetSurfaceFromDC) (THIS_ HDC, LPDIRECTDRAWSURFACE7 *) PURE;
+    STDMETHOD(RestoreAllSurfaces)(THIS) PURE;
+    STDMETHOD(TestCooperativeLevel)(THIS) PURE;
+    STDMETHOD(GetDeviceIdentifier)(THIS_ LPDDDEVICEIDENTIFIER2, DWORD ) PURE;
+    STDMETHOD(StartModeTest)(THIS_ LPSIZE, DWORD, DWORD ) PURE;
+    STDMETHOD(EvaluateMode)(THIS_ DWORD, DWORD * ) PURE;
+};
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDraw7_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDraw7_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirectDraw7_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirectDraw7_Compact(p)                      (p)->lpVtbl->Compact(p)
+#define IDirectDraw7_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
+#define IDirectDraw7_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
+#define IDirectDraw7_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
+#define IDirectDraw7_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
+#define IDirectDraw7_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
+#define IDirectDraw7_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
+#define IDirectDraw7_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
+#define IDirectDraw7_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirectDraw7_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
+#define IDirectDraw7_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
+#define IDirectDraw7_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
+#define IDirectDraw7_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
+#define IDirectDraw7_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
+#define IDirectDraw7_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
+#define IDirectDraw7_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirectDraw7_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
+#define IDirectDraw7_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
+#define IDirectDraw7_SetDisplayMode(p, a, b, c, d, e) (p)->lpVtbl->SetDisplayMode(p, a, b, c, d, e)
+#define IDirectDraw7_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)
+#define IDirectDraw7_GetAvailableVidMem(p, a, b, c)  (p)->lpVtbl->GetAvailableVidMem(p, a, b, c)
+#define IDirectDraw7_GetSurfaceFromDC(p, a, b)       (p)->lpVtbl->GetSurfaceFromDC(p, a, b)
+#define IDirectDraw7_RestoreAllSurfaces(p)           (p)->lpVtbl->RestoreAllSurfaces(p)
+#define IDirectDraw7_TestCooperativeLevel(p)         (p)->lpVtbl->TestCooperativeLevel(p)
+#define IDirectDraw7_GetDeviceIdentifier(p,a,b)      (p)->lpVtbl->GetDeviceIdentifier(p,a,b)
+#define IDirectDraw7_StartModeTest(p,a,b,c)        (p)->lpVtbl->StartModeTest(p,a,b,c)
+#define IDirectDraw7_EvaluateMode(p,a,b)           (p)->lpVtbl->EvaluateMode(p,a,b)
+#else
+#define IDirectDraw7_QueryInterface(p, a, b)         (p)->QueryInterface(a, b)
+#define IDirectDraw7_AddRef(p)                       (p)->AddRef()
+#define IDirectDraw7_Release(p)                      (p)->Release()
+#define IDirectDraw7_Compact(p)                      (p)->Compact()
+#define IDirectDraw7_CreateClipper(p, a, b, c)       (p)->CreateClipper(a, b, c)
+#define IDirectDraw7_CreatePalette(p, a, b, c, d)    (p)->CreatePalette(a, b, c, d)
+#define IDirectDraw7_CreateSurface(p, a, b, c)       (p)->CreateSurface(a, b, c)
+#define IDirectDraw7_DuplicateSurface(p, a, b)       (p)->DuplicateSurface(a, b)
+#define IDirectDraw7_EnumDisplayModes(p, a, b, c, d) (p)->EnumDisplayModes(a, b, c, d)
+#define IDirectDraw7_EnumSurfaces(p, a, b, c, d)     (p)->EnumSurfaces(a, b, c, d)
+#define IDirectDraw7_FlipToGDISurface(p)             (p)->FlipToGDISurface()
+#define IDirectDraw7_GetCaps(p, a, b)                (p)->GetCaps(a, b)
+#define IDirectDraw7_GetDisplayMode(p, a)            (p)->GetDisplayMode(a)
+#define IDirectDraw7_GetFourCCCodes(p, a, b)         (p)->GetFourCCCodes(a, b)
+#define IDirectDraw7_GetGDISurface(p, a)             (p)->GetGDISurface(a)
+#define IDirectDraw7_GetMonitorFrequency(p, a)       (p)->GetMonitorFrequency(a)
+#define IDirectDraw7_GetScanLine(p, a)               (p)->GetScanLine(a)
+#define IDirectDraw7_GetVerticalBlankStatus(p, a)    (p)->GetVerticalBlankStatus(a)
+#define IDirectDraw7_Initialize(p, a)                (p)->Initialize(a)
+#define IDirectDraw7_RestoreDisplayMode(p)           (p)->RestoreDisplayMode()
+#define IDirectDraw7_SetCooperativeLevel(p, a, b)    (p)->SetCooperativeLevel(a, b)
+#define IDirectDraw7_SetDisplayMode(p, a, b, c, d, e) (p)->SetDisplayMode(a, b, c, d, e)
+#define IDirectDraw7_WaitForVerticalBlank(p, a, b)   (p)->WaitForVerticalBlank(a, b)
+#define IDirectDraw7_GetAvailableVidMem(p, a, b, c)  (p)->GetAvailableVidMem(a, b, c)
+#define IDirectDraw7_GetSurfaceFromDC(p, a, b)       (p)->GetSurfaceFromDC(a, b)
+#define IDirectDraw7_RestoreAllSurfaces(p)           (p)->RestoreAllSurfaces()
+#define IDirectDraw7_TestCooperativeLevel(p)         (p)->TestCooperativeLevel()
+#define IDirectDraw7_GetDeviceIdentifier(p,a,b)      (p)->GetDeviceIdentifier(a,b)
+#define IDirectDraw7_StartModeTest(p,a,b,c)        (p)->lpVtbl->StartModeTest(a,b,c)
+#define IDirectDraw7_EvaluateMode(p,a,b)           (p)->lpVtbl->EvaluateMode(a,b)
+#endif
+
+#endif
+
+
+/*
+ * IDirectDrawPalette
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawPalette
+DECLARE_INTERFACE_( IDirectDrawPalette, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawPalette methods ***/
+    STDMETHOD(GetCaps)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE;
+    STDMETHOD(SetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawPalette_QueryInterface(p, a, b)      (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDrawPalette_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawPalette_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawPalette_GetCaps(p, a)                (p)->lpVtbl->GetCaps(p, a)
+#define IDirectDrawPalette_GetEntries(p, a, b, c, d)    (p)->lpVtbl->GetEntries(p, a, b, c, d)
+#define IDirectDrawPalette_Initialize(p, a, b, c)       (p)->lpVtbl->Initialize(p, a, b, c)
+#define IDirectDrawPalette_SetEntries(p, a, b, c, d)    (p)->lpVtbl->SetEntries(p, a, b, c, d)
+#else
+#define IDirectDrawPalette_QueryInterface(p, a, b)      (p)->QueryInterface(a, b)
+#define IDirectDrawPalette_AddRef(p)                    (p)->AddRef()
+#define IDirectDrawPalette_Release(p)                   (p)->Release()
+#define IDirectDrawPalette_GetCaps(p, a)                (p)->GetCaps(a)
+#define IDirectDrawPalette_GetEntries(p, a, b, c, d)    (p)->GetEntries(a, b, c, d)
+#define IDirectDrawPalette_Initialize(p, a, b, c)       (p)->Initialize(a, b, c)
+#define IDirectDrawPalette_SetEntries(p, a, b, c, d)    (p)->SetEntries(a, b, c, d)
+#endif
+
+#endif
+
+
+/*
+ * IDirectDrawClipper
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawClipper
+DECLARE_INTERFACE_( IDirectDrawClipper, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawClipper methods ***/
+    STDMETHOD(GetClipList)(THIS_ LPRECT, LPRGNDATA, LPDWORD) PURE;
+    STDMETHOD(GetHWnd)(THIS_ HWND FAR *) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD) PURE;
+    STDMETHOD(IsClipListChanged)(THIS_ BOOL FAR *) PURE;
+    STDMETHOD(SetClipList)(THIS_ LPRGNDATA,DWORD) PURE;
+    STDMETHOD(SetHWnd)(THIS_ DWORD, HWND ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawClipper_QueryInterface(p, a, b)  (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDrawClipper_AddRef(p)                (p)->lpVtbl->AddRef(p)
+#define IDirectDrawClipper_Release(p)               (p)->lpVtbl->Release(p)
+#define IDirectDrawClipper_GetClipList(p, a, b, c)  (p)->lpVtbl->GetClipList(p, a, b, c)
+#define IDirectDrawClipper_GetHWnd(p, a)            (p)->lpVtbl->GetHWnd(p, a)
+#define IDirectDrawClipper_Initialize(p, a, b)      (p)->lpVtbl->Initialize(p, a, b)
+#define IDirectDrawClipper_IsClipListChanged(p, a)  (p)->lpVtbl->IsClipListChanged(p, a)
+#define IDirectDrawClipper_SetClipList(p, a, b)     (p)->lpVtbl->SetClipList(p, a, b)
+#define IDirectDrawClipper_SetHWnd(p, a, b)         (p)->lpVtbl->SetHWnd(p, a, b)
+#else
+#define IDirectDrawClipper_QueryInterface(p, a, b)  (p)->QueryInterface(a, b)
+#define IDirectDrawClipper_AddRef(p)                (p)->AddRef()
+#define IDirectDrawClipper_Release(p)               (p)->Release()
+#define IDirectDrawClipper_GetClipList(p, a, b, c)  (p)->GetClipList(a, b, c)
+#define IDirectDrawClipper_GetHWnd(p, a)            (p)->GetHWnd(a)
+#define IDirectDrawClipper_Initialize(p, a, b)      (p)->Initialize(a, b)
+#define IDirectDrawClipper_IsClipListChanged(p, a)  (p)->IsClipListChanged(a)
+#define IDirectDrawClipper_SetClipList(p, a, b)     (p)->SetClipList(a, b)
+#define IDirectDrawClipper_SetHWnd(p, a, b)         (p)->SetHWnd(a, b)
+#endif
+
+#endif
+
+/*
+ * IDirectDrawSurface and related interfaces
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface
+DECLARE_INTERFACE_( IDirectDrawSurface, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#else
+#define IDirectDrawSurface_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirectDrawSurface_AddRef(p)                    (p)->AddRef()
+#define IDirectDrawSurface_Release(p)                   (p)->Release()
+#define IDirectDrawSurface_AddAttachedSurface(p,a)      (p)->AddAttachedSurface(a)
+#define IDirectDrawSurface_AddOverlayDirtyRect(p,a)     (p)->AddOverlayDirtyRect(a)
+#define IDirectDrawSurface_Blt(p,a,b,c,d,e)             (p)->Blt(a,b,c,d,e)
+#define IDirectDrawSurface_BltBatch(p,a,b,c)            (p)->BltBatch(a,b,c)
+#define IDirectDrawSurface_BltFast(p,a,b,c,d,e)         (p)->BltFast(a,b,c,d,e)
+#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b)
+#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b)  (p)->EnumAttachedSurfaces(a,b)
+#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c)  (p)->EnumOverlayZOrders(a,b,c)
+#define IDirectDrawSurface_Flip(p,a,b)                  (p)->Flip(a,b)
+#define IDirectDrawSurface_GetAttachedSurface(p,a,b)    (p)->GetAttachedSurface(a,b)
+#define IDirectDrawSurface_GetBltStatus(p,a)            (p)->GetBltStatus(a)
+#define IDirectDrawSurface_GetCaps(p,b)                 (p)->GetCaps(b)
+#define IDirectDrawSurface_GetClipper(p,a)              (p)->GetClipper(a)
+#define IDirectDrawSurface_GetColorKey(p,a,b)           (p)->GetColorKey(a,b)
+#define IDirectDrawSurface_GetDC(p,a)                   (p)->GetDC(a)
+#define IDirectDrawSurface_GetFlipStatus(p,a)           (p)->GetFlipStatus(a)
+#define IDirectDrawSurface_GetOverlayPosition(p,a,b)    (p)->GetOverlayPosition(a,b)
+#define IDirectDrawSurface_GetPalette(p,a)              (p)->GetPalette(a)
+#define IDirectDrawSurface_GetPixelFormat(p,a)          (p)->GetPixelFormat(a)
+#define IDirectDrawSurface_GetSurfaceDesc(p,a)          (p)->GetSurfaceDesc(a)
+#define IDirectDrawSurface_Initialize(p,a,b)            (p)->Initialize(a,b)
+#define IDirectDrawSurface_IsLost(p)                    (p)->IsLost()
+#define IDirectDrawSurface_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirectDrawSurface_ReleaseDC(p,a)               (p)->ReleaseDC(a)
+#define IDirectDrawSurface_Restore(p)                   (p)->Restore()
+#define IDirectDrawSurface_SetClipper(p,a)              (p)->SetClipper(a)
+#define IDirectDrawSurface_SetColorKey(p,a,b)           (p)->SetColorKey(a,b)
+#define IDirectDrawSurface_SetOverlayPosition(p,a,b)    (p)->SetOverlayPosition(a,b)
+#define IDirectDrawSurface_SetPalette(p,a)              (p)->SetPalette(a)
+#define IDirectDrawSurface_Unlock(p,b)                  (p)->Unlock(b)
+#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e)   (p)->UpdateOverlay(a,b,c,d,e)
+#define IDirectDrawSurface_UpdateOverlayDisplay(p,a)    (p)->UpdateOverlayDisplay(a)
+#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b)   (p)->UpdateOverlayZOrder(a,b)
+#endif
+
+/*
+ * IDirectDrawSurface2 and related interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface2
+DECLARE_INTERFACE_( IDirectDrawSurface2, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE2) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE2, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE2, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE2) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE2, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE2 FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE2,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE2) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE;
+    STDMETHOD(PageLock)(THIS_ DWORD) PURE;
+    STDMETHOD(PageUnlock)(THIS_ DWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface2_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface2_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface2_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface2_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface2_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface2_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface2_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface2_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface2_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface2_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface2_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface2_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface2_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface2_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface2_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface2_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface2_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface2_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface2_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface2_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface2_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface2_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface2_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface2_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface2_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface2_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface2_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface2_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#define IDirectDrawSurface2_GetDDInterface(p,a)          (p)->lpVtbl->GetDDInterface(p,a)
+#define IDirectDrawSurface2_PageLock(p,a)                (p)->lpVtbl->PageLock(p,a)
+#define IDirectDrawSurface2_PageUnlock(p,a)              (p)->lpVtbl->PageUnlock(p,a)
+#else
+#define IDirectDrawSurface2_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirectDrawSurface2_AddRef(p)                    (p)->AddRef()
+#define IDirectDrawSurface2_Release(p)                   (p)->Release()
+#define IDirectDrawSurface2_AddAttachedSurface(p,a)      (p)->AddAttachedSurface(a)
+#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a)     (p)->AddOverlayDirtyRect(a)
+#define IDirectDrawSurface2_Blt(p,a,b,c,d,e)             (p)->Blt(a,b,c,d,e)
+#define IDirectDrawSurface2_BltBatch(p,a,b,c)            (p)->BltBatch(a,b,c)
+#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e)         (p)->BltFast(a,b,c,d,e)
+#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b)
+#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b)  (p)->EnumAttachedSurfaces(a,b)
+#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c)  (p)->EnumOverlayZOrders(a,b,c)
+#define IDirectDrawSurface2_Flip(p,a,b)                  (p)->Flip(a,b)
+#define IDirectDrawSurface2_GetAttachedSurface(p,a,b)    (p)->GetAttachedSurface(a,b)
+#define IDirectDrawSurface2_GetBltStatus(p,a)            (p)->GetBltStatus(a)
+#define IDirectDrawSurface2_GetCaps(p,b)                 (p)->GetCaps(b)
+#define IDirectDrawSurface2_GetClipper(p,a)              (p)->GetClipper(a)
+#define IDirectDrawSurface2_GetColorKey(p,a,b)           (p)->GetColorKey(a,b)
+#define IDirectDrawSurface2_GetDC(p,a)                   (p)->GetDC(a)
+#define IDirectDrawSurface2_GetFlipStatus(p,a)           (p)->GetFlipStatus(a)
+#define IDirectDrawSurface2_GetOverlayPosition(p,a,b)    (p)->GetOverlayPosition(a,b)
+#define IDirectDrawSurface2_GetPalette(p,a)              (p)->GetPalette(a)
+#define IDirectDrawSurface2_GetPixelFormat(p,a)          (p)->GetPixelFormat(a)
+#define IDirectDrawSurface2_GetSurfaceDesc(p,a)          (p)->GetSurfaceDesc(a)
+#define IDirectDrawSurface2_Initialize(p,a,b)            (p)->Initialize(a,b)
+#define IDirectDrawSurface2_IsLost(p)                    (p)->IsLost()
+#define IDirectDrawSurface2_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirectDrawSurface2_ReleaseDC(p,a)               (p)->ReleaseDC(a)
+#define IDirectDrawSurface2_Restore(p)                   (p)->Restore()
+#define IDirectDrawSurface2_SetClipper(p,a)              (p)->SetClipper(a)
+#define IDirectDrawSurface2_SetColorKey(p,a,b)           (p)->SetColorKey(a,b)
+#define IDirectDrawSurface2_SetOverlayPosition(p,a,b)    (p)->SetOverlayPosition(a,b)
+#define IDirectDrawSurface2_SetPalette(p,a)              (p)->SetPalette(a)
+#define IDirectDrawSurface2_Unlock(p,b)                  (p)->Unlock(b)
+#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e)   (p)->UpdateOverlay(a,b,c,d,e)
+#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a)    (p)->UpdateOverlayDisplay(a)
+#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b)   (p)->UpdateOverlayZOrder(a,b)
+#define IDirectDrawSurface2_GetDDInterface(p,a)          (p)->GetDDInterface(a)
+#define IDirectDrawSurface2_PageLock(p,a)                (p)->PageLock(a)
+#define IDirectDrawSurface2_PageUnlock(p,a)              (p)->PageUnlock(a)
+#endif
+
+/*
+ * IDirectDrawSurface3 and related interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface3
+DECLARE_INTERFACE_( IDirectDrawSurface3, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE3) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE3, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE3, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE3) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE3, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE3 FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE3,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE3) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE;
+    STDMETHOD(PageLock)(THIS_ DWORD) PURE;
+    STDMETHOD(PageUnlock)(THIS_ DWORD) PURE;
+    /*** Added in the V3 interface ***/
+    STDMETHOD(SetSurfaceDesc)(THIS_ LPDDSURFACEDESC, DWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface3_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface3_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface3_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface3_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface3_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface3_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface3_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface3_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface3_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface3_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface3_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface3_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface3_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface3_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface3_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface3_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface3_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface3_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface3_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface3_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface3_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface3_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface3_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface3_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface3_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface3_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface3_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface3_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface3_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface3_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface3_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface3_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface3_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface3_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface3_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface3_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#define IDirectDrawSurface3_GetDDInterface(p,a)          (p)->lpVtbl->GetDDInterface(p,a)
+#define IDirectDrawSurface3_PageLock(p,a)                (p)->lpVtbl->PageLock(p,a)
+#define IDirectDrawSurface3_PageUnlock(p,a)              (p)->lpVtbl->PageUnlock(p,a)
+#define IDirectDrawSurface3_SetSurfaceDesc(p,a,b)        (p)->lpVtbl->SetSurfaceDesc(p,a,b)
+#else
+#define IDirectDrawSurface3_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirectDrawSurface3_AddRef(p)                    (p)->AddRef()
+#define IDirectDrawSurface3_Release(p)                   (p)->Release()
+#define IDirectDrawSurface3_AddAttachedSurface(p,a)      (p)->AddAttachedSurface(a)
+#define IDirectDrawSurface3_AddOverlayDirtyRect(p,a)     (p)->AddOverlayDirtyRect(a)
+#define IDirectDrawSurface3_Blt(p,a,b,c,d,e)             (p)->Blt(a,b,c,d,e)
+#define IDirectDrawSurface3_BltBatch(p,a,b,c)            (p)->BltBatch(a,b,c)
+#define IDirectDrawSurface3_BltFast(p,a,b,c,d,e)         (p)->BltFast(a,b,c,d,e)
+#define IDirectDrawSurface3_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b)
+#define IDirectDrawSurface3_EnumAttachedSurfaces(p,a,b)  (p)->EnumAttachedSurfaces(a,b)
+#define IDirectDrawSurface3_EnumOverlayZOrders(p,a,b,c)  (p)->EnumOverlayZOrders(a,b,c)
+#define IDirectDrawSurface3_Flip(p,a,b)                  (p)->Flip(a,b)
+#define IDirectDrawSurface3_GetAttachedSurface(p,a,b)    (p)->GetAttachedSurface(a,b)
+#define IDirectDrawSurface3_GetBltStatus(p,a)            (p)->GetBltStatus(a)
+#define IDirectDrawSurface3_GetCaps(p,b)                 (p)->GetCaps(b)
+#define IDirectDrawSurface3_GetClipper(p,a)              (p)->GetClipper(a)
+#define IDirectDrawSurface3_GetColorKey(p,a,b)           (p)->GetColorKey(a,b)
+#define IDirectDrawSurface3_GetDC(p,a)                   (p)->GetDC(a)
+#define IDirectDrawSurface3_GetFlipStatus(p,a)           (p)->GetFlipStatus(a)
+#define IDirectDrawSurface3_GetOverlayPosition(p,a,b)    (p)->GetOverlayPosition(a,b)
+#define IDirectDrawSurface3_GetPalette(p,a)              (p)->GetPalette(a)
+#define IDirectDrawSurface3_GetPixelFormat(p,a)          (p)->GetPixelFormat(a)
+#define IDirectDrawSurface3_GetSurfaceDesc(p,a)          (p)->GetSurfaceDesc(a)
+#define IDirectDrawSurface3_Initialize(p,a,b)            (p)->Initialize(a,b)
+#define IDirectDrawSurface3_IsLost(p)                    (p)->IsLost()
+#define IDirectDrawSurface3_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirectDrawSurface3_ReleaseDC(p,a)               (p)->ReleaseDC(a)
+#define IDirectDrawSurface3_Restore(p)                   (p)->Restore()
+#define IDirectDrawSurface3_SetClipper(p,a)              (p)->SetClipper(a)
+#define IDirectDrawSurface3_SetColorKey(p,a,b)           (p)->SetColorKey(a,b)
+#define IDirectDrawSurface3_SetOverlayPosition(p,a,b)    (p)->SetOverlayPosition(a,b)
+#define IDirectDrawSurface3_SetPalette(p,a)              (p)->SetPalette(a)
+#define IDirectDrawSurface3_Unlock(p,b)                  (p)->Unlock(b)
+#define IDirectDrawSurface3_UpdateOverlay(p,a,b,c,d,e)   (p)->UpdateOverlay(a,b,c,d,e)
+#define IDirectDrawSurface3_UpdateOverlayDisplay(p,a)    (p)->UpdateOverlayDisplay(a)
+#define IDirectDrawSurface3_UpdateOverlayZOrder(p,a,b)   (p)->UpdateOverlayZOrder(a,b)
+#define IDirectDrawSurface3_GetDDInterface(p,a)          (p)->GetDDInterface(a)
+#define IDirectDrawSurface3_PageLock(p,a)                (p)->PageLock(a)
+#define IDirectDrawSurface3_PageUnlock(p,a)              (p)->PageUnlock(a)
+#define IDirectDrawSurface3_SetSurfaceDesc(p,a,b)        (p)->SetSurfaceDesc(a,b)
+#endif
+
+/*
+ * IDirectDrawSurface4 and related interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface4
+DECLARE_INTERFACE_( IDirectDrawSurface4, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE4) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE4, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE4, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE4) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK2) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK2) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE4, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS2, LPDIRECTDRAWSURFACE4 FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS2) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC2) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC2) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC2,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPRECT) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE4,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE4) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE;
+    STDMETHOD(PageLock)(THIS_ DWORD) PURE;
+    STDMETHOD(PageUnlock)(THIS_ DWORD) PURE;
+    /*** Added in the v3 interface ***/
+    STDMETHOD(SetSurfaceDesc)(THIS_ LPDDSURFACEDESC2, DWORD) PURE;
+    /*** Added in the v4 interface ***/
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID, LPVOID, DWORD, DWORD) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID, LPVOID, LPDWORD) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID) PURE;
+    STDMETHOD(GetUniquenessValue)(THIS_ LPDWORD) PURE;
+    STDMETHOD(ChangeUniquenessValue)(THIS) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface4_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface4_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface4_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface4_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface4_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface4_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface4_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface4_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface4_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface4_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface4_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface4_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface4_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface4_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface4_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface4_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface4_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface4_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface4_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface4_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface4_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface4_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface4_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface4_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface4_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface4_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface4_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface4_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface4_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface4_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface4_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface4_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface4_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface4_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface4_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface4_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#define IDirectDrawSurface4_GetDDInterface(p,a)          (p)->lpVtbl->GetDDInterface(p,a)
+#define IDirectDrawSurface4_PageLock(p,a)                (p)->lpVtbl->PageLock(p,a)
+#define IDirectDrawSurface4_PageUnlock(p,a)              (p)->lpVtbl->PageUnlock(p,a)
+#define IDirectDrawSurface4_SetSurfaceDesc(p,a,b)        (p)->lpVtbl->SetSurfaceDesc(p,a,b)
+#define IDirectDrawSurface4_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirectDrawSurface4_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirectDrawSurface4_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirectDrawSurface4_GetUniquenessValue(p, a)     (p)->lpVtbl->GetUniquenessValue(p, a)
+#define IDirectDrawSurface4_ChangeUniquenessValue(p)     (p)->lpVtbl->ChangeUniquenessValue(p)
+#else
+#define IDirectDrawSurface4_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirectDrawSurface4_AddRef(p)                    (p)->AddRef()
+#define IDirectDrawSurface4_Release(p)                   (p)->Release()
+#define IDirectDrawSurface4_AddAttachedSurface(p,a)      (p)->AddAttachedSurface(a)
+#define IDirectDrawSurface4_AddOverlayDirtyRect(p,a)     (p)->AddOverlayDirtyRect(a)
+#define IDirectDrawSurface4_Blt(p,a,b,c,d,e)             (p)->Blt(a,b,c,d,e)
+#define IDirectDrawSurface4_BltBatch(p,a,b,c)            (p)->BltBatch(a,b,c)
+#define IDirectDrawSurface4_BltFast(p,a,b,c,d,e)         (p)->BltFast(a,b,c,d,e)
+#define IDirectDrawSurface4_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b)
+#define IDirectDrawSurface4_EnumAttachedSurfaces(p,a,b)  (p)->EnumAttachedSurfaces(a,b)
+#define IDirectDrawSurface4_EnumOverlayZOrders(p,a,b,c)  (p)->EnumOverlayZOrders(a,b,c)
+#define IDirectDrawSurface4_Flip(p,a,b)                  (p)->Flip(a,b)
+#define IDirectDrawSurface4_GetAttachedSurface(p,a,b)    (p)->GetAttachedSurface(a,b)
+#define IDirectDrawSurface4_GetBltStatus(p,a)            (p)->GetBltStatus(a)
+#define IDirectDrawSurface4_GetCaps(p,b)                 (p)->GetCaps(b)
+#define IDirectDrawSurface4_GetClipper(p,a)              (p)->GetClipper(a)
+#define IDirectDrawSurface4_GetColorKey(p,a,b)           (p)->GetColorKey(a,b)
+#define IDirectDrawSurface4_GetDC(p,a)                   (p)->GetDC(a)
+#define IDirectDrawSurface4_GetFlipStatus(p,a)           (p)->GetFlipStatus(a)
+#define IDirectDrawSurface4_GetOverlayPosition(p,a,b)    (p)->GetOverlayPosition(a,b)
+#define IDirectDrawSurface4_GetPalette(p,a)              (p)->GetPalette(a)
+#define IDirectDrawSurface4_GetPixelFormat(p,a)          (p)->GetPixelFormat(a)
+#define IDirectDrawSurface4_GetSurfaceDesc(p,a)          (p)->GetSurfaceDesc(a)
+#define IDirectDrawSurface4_Initialize(p,a,b)            (p)->Initialize(a,b)
+#define IDirectDrawSurface4_IsLost(p)                    (p)->IsLost()
+#define IDirectDrawSurface4_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirectDrawSurface4_ReleaseDC(p,a)               (p)->ReleaseDC(a)
+#define IDirectDrawSurface4_Restore(p)                   (p)->Restore()
+#define IDirectDrawSurface4_SetClipper(p,a)              (p)->SetClipper(a)
+#define IDirectDrawSurface4_SetColorKey(p,a,b)           (p)->SetColorKey(a,b)
+#define IDirectDrawSurface4_SetOverlayPosition(p,a,b)    (p)->SetOverlayPosition(a,b)
+#define IDirectDrawSurface4_SetPalette(p,a)              (p)->SetPalette(a)
+#define IDirectDrawSurface4_Unlock(p,b)                  (p)->Unlock(b)
+#define IDirectDrawSurface4_UpdateOverlay(p,a,b,c,d,e)   (p)->UpdateOverlay(a,b,c,d,e)
+#define IDirectDrawSurface4_UpdateOverlayDisplay(p,a)    (p)->UpdateOverlayDisplay(a)
+#define IDirectDrawSurface4_UpdateOverlayZOrder(p,a,b)   (p)->UpdateOverlayZOrder(a,b)
+#define IDirectDrawSurface4_GetDDInterface(p,a)          (p)->GetDDInterface(a)
+#define IDirectDrawSurface4_PageLock(p,a)                (p)->PageLock(a)
+#define IDirectDrawSurface4_PageUnlock(p,a)              (p)->PageUnlock(a)
+#define IDirectDrawSurface4_SetSurfaceDesc(p,a,b)        (p)->SetSurfaceDesc(a,b)
+#define IDirectDrawSurface4_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirectDrawSurface4_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirectDrawSurface4_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirectDrawSurface4_GetUniquenessValue(p, a)     (p)->GetUniquenessValue(a)
+#define IDirectDrawSurface4_ChangeUniquenessValue(p)     (p)->ChangeUniquenessValue()
+#endif
+
+/*
+ * IDirectDrawSurface7 and related interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface7
+DECLARE_INTERFACE_( IDirectDrawSurface7, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE7) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE7, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE7, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE7) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK7) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK7) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE7, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS2, LPDIRECTDRAWSURFACE7 FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS2) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC2) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC2) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC2,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPRECT) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE7,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE7) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE;
+    STDMETHOD(PageLock)(THIS_ DWORD) PURE;
+    STDMETHOD(PageUnlock)(THIS_ DWORD) PURE;
+    /*** Added in the v3 interface ***/
+    STDMETHOD(SetSurfaceDesc)(THIS_ LPDDSURFACEDESC2, DWORD) PURE;
+    /*** Added in the v4 interface ***/
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID, LPVOID, DWORD, DWORD) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID, LPVOID, LPDWORD) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID) PURE;
+    STDMETHOD(GetUniquenessValue)(THIS_ LPDWORD) PURE;
+    STDMETHOD(ChangeUniquenessValue)(THIS) PURE;
+    /*** Moved Texture7 methods here ***/
+    STDMETHOD(SetPriority)(THIS_ DWORD) PURE;
+    STDMETHOD(GetPriority)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SetLOD)(THIS_ DWORD) PURE;
+    STDMETHOD(GetLOD)(THIS_ LPDWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface7_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface7_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface7_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface7_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface7_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface7_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface7_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface7_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface7_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface7_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface7_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface7_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface7_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface7_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface7_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface7_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface7_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface7_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface7_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface7_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface7_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface7_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface7_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface7_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface7_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface7_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface7_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface7_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface7_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface7_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface7_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface7_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface7_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface7_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface7_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface7_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#define IDirectDrawSurface7_GetDDInterface(p,a)          (p)->lpVtbl->GetDDInterface(p,a)
+#define IDirectDrawSurface7_PageLock(p,a)                (p)->lpVtbl->PageLock(p,a)
+#define IDirectDrawSurface7_PageUnlock(p,a)              (p)->lpVtbl->PageUnlock(p,a)
+#define IDirectDrawSurface7_SetSurfaceDesc(p,a,b)        (p)->lpVtbl->SetSurfaceDesc(p,a,b)
+#define IDirectDrawSurface7_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirectDrawSurface7_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirectDrawSurface7_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirectDrawSurface7_GetUniquenessValue(p, a)     (p)->lpVtbl->GetUniquenessValue(p, a)
+#define IDirectDrawSurface7_ChangeUniquenessValue(p)     (p)->lpVtbl->ChangeUniquenessValue(p)
+#define IDirectDrawSurface7_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirectDrawSurface7_GetPriority(p,a)             (p)->lpVtbl->GetPriority(p,a)
+#define IDirectDrawSurface7_SetLOD(p,a)                  (p)->lpVtbl->SetLOD(p,a)
+#define IDirectDrawSurface7_GetLOD(p,a)                  (p)->lpVtbl->GetLOD(p,a)
+#else
+#define IDirectDrawSurface7_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirectDrawSurface7_AddRef(p)                    (p)->AddRef()
+#define IDirectDrawSurface7_Release(p)                   (p)->Release()
+#define IDirectDrawSurface7_AddAttachedSurface(p,a)      (p)->AddAttachedSurface(a)
+#define IDirectDrawSurface7_AddOverlayDirtyRect(p,a)     (p)->AddOverlayDirtyRect(a)
+#define IDirectDrawSurface7_Blt(p,a,b,c,d,e)             (p)->Blt(a,b,c,d,e)
+#define IDirectDrawSurface7_BltBatch(p,a,b,c)            (p)->BltBatch(a,b,c)
+#define IDirectDrawSurface7_BltFast(p,a,b,c,d,e)         (p)->BltFast(a,b,c,d,e)
+#define IDirectDrawSurface7_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b)
+#define IDirectDrawSurface7_EnumAttachedSurfaces(p,a,b)  (p)->EnumAttachedSurfaces(a,b)
+#define IDirectDrawSurface7_EnumOverlayZOrders(p,a,b,c)  (p)->EnumOverlayZOrders(a,b,c)
+#define IDirectDrawSurface7_Flip(p,a,b)                  (p)->Flip(a,b)
+#define IDirectDrawSurface7_GetAttachedSurface(p,a,b)    (p)->GetAttachedSurface(a,b)
+#define IDirectDrawSurface7_GetBltStatus(p,a)            (p)->GetBltStatus(a)
+#define IDirectDrawSurface7_GetCaps(p,b)                 (p)->GetCaps(b)
+#define IDirectDrawSurface7_GetClipper(p,a)              (p)->GetClipper(a)
+#define IDirectDrawSurface7_GetColorKey(p,a,b)           (p)->GetColorKey(a,b)
+#define IDirectDrawSurface7_GetDC(p,a)                   (p)->GetDC(a)
+#define IDirectDrawSurface7_GetFlipStatus(p,a)           (p)->GetFlipStatus(a)
+#define IDirectDrawSurface7_GetOverlayPosition(p,a,b)    (p)->GetOverlayPosition(a,b)
+#define IDirectDrawSurface7_GetPalette(p,a)              (p)->GetPalette(a)
+#define IDirectDrawSurface7_GetPixelFormat(p,a)          (p)->GetPixelFormat(a)
+#define IDirectDrawSurface7_GetSurfaceDesc(p,a)          (p)->GetSurfaceDesc(a)
+#define IDirectDrawSurface7_Initialize(p,a,b)            (p)->Initialize(a,b)
+#define IDirectDrawSurface7_IsLost(p)                    (p)->IsLost()
+#define IDirectDrawSurface7_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirectDrawSurface7_ReleaseDC(p,a)               (p)->ReleaseDC(a)
+#define IDirectDrawSurface7_Restore(p)                   (p)->Restore()
+#define IDirectDrawSurface7_SetClipper(p,a)              (p)->SetClipper(a)
+#define IDirectDrawSurface7_SetColorKey(p,a,b)           (p)->SetColorKey(a,b)
+#define IDirectDrawSurface7_SetOverlayPosition(p,a,b)    (p)->SetOverlayPosition(a,b)
+#define IDirectDrawSurface7_SetPalette(p,a)              (p)->SetPalette(a)
+#define IDirectDrawSurface7_Unlock(p,b)                  (p)->Unlock(b)
+#define IDirectDrawSurface7_UpdateOverlay(p,a,b,c,d,e)   (p)->UpdateOverlay(a,b,c,d,e)
+#define IDirectDrawSurface7_UpdateOverlayDisplay(p,a)    (p)->UpdateOverlayDisplay(a)
+#define IDirectDrawSurface7_UpdateOverlayZOrder(p,a,b)   (p)->UpdateOverlayZOrder(a,b)
+#define IDirectDrawSurface7_GetDDInterface(p,a)          (p)->GetDDInterface(a)
+#define IDirectDrawSurface7_PageLock(p,a)                (p)->PageLock(a)
+#define IDirectDrawSurface7_PageUnlock(p,a)              (p)->PageUnlock(a)
+#define IDirectDrawSurface7_SetSurfaceDesc(p,a,b)        (p)->SetSurfaceDesc(a,b)
+#define IDirectDrawSurface7_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirectDrawSurface7_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirectDrawSurface7_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirectDrawSurface7_GetUniquenessValue(p, a)     (p)->GetUniquenessValue(a)
+#define IDirectDrawSurface7_ChangeUniquenessValue(p)     (p)->ChangeUniquenessValue()
+#define IDirectDrawSurface7_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirectDrawSurface7_GetPriority(p,a)             (p)->GetPriority(a)
+#define IDirectDrawSurface7_SetLOD(p,a)                  (p)->SetLOD(a)
+#define IDirectDrawSurface7_GetLOD(p,a)                  (p)->GetLOD(a)
+#endif
+
+
+/*
+ * IDirectDrawColorControl
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawColorControl
+DECLARE_INTERFACE_( IDirectDrawColorControl, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawColorControl methods ***/
+    STDMETHOD(GetColorControls)(THIS_ LPDDCOLORCONTROL) PURE;
+    STDMETHOD(SetColorControls)(THIS_ LPDDCOLORCONTROL) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawColorControl_QueryInterface(p, a, b)  (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDrawColorControl_AddRef(p)                (p)->lpVtbl->AddRef(p)
+#define IDirectDrawColorControl_Release(p)               (p)->lpVtbl->Release(p)
+#define IDirectDrawColorControl_GetColorControls(p, a)   (p)->lpVtbl->GetColorControls(p, a)
+#define IDirectDrawColorControl_SetColorControls(p, a)   (p)->lpVtbl->SetColorControls(p, a)
+#else
+#define IDirectDrawColorControl_QueryInterface(p, a, b)  (p)->QueryInterface(a, b)
+#define IDirectDrawColorControl_AddRef(p)                (p)->AddRef()
+#define IDirectDrawColorControl_Release(p)               (p)->Release()
+#define IDirectDrawColorControl_GetColorControls(p, a)   (p)->GetColorControls(a)
+#define IDirectDrawColorControl_SetColorControls(p, a)   (p)->SetColorControls(a)
+#endif
+
+#endif
+
+
+/*
+ * IDirectDrawGammaControl
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawGammaControl
+DECLARE_INTERFACE_( IDirectDrawGammaControl, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawGammaControl methods ***/
+    STDMETHOD(GetGammaRamp)(THIS_ DWORD, LPDDGAMMARAMP) PURE;
+    STDMETHOD(SetGammaRamp)(THIS_ DWORD, LPDDGAMMARAMP) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawGammaControl_QueryInterface(p, a, b)  (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDrawGammaControl_AddRef(p)                (p)->lpVtbl->AddRef(p)
+#define IDirectDrawGammaControl_Release(p)               (p)->lpVtbl->Release(p)
+#define IDirectDrawGammaControl_GetGammaRamp(p, a, b)    (p)->lpVtbl->GetGammaRamp(p, a, b)
+#define IDirectDrawGammaControl_SetGammaRamp(p, a, b)    (p)->lpVtbl->SetGammaRamp(p, a, b)
+#else
+#define IDirectDrawGammaControl_QueryInterface(p, a, b)  (p)->QueryInterface(a, b)
+#define IDirectDrawGammaControl_AddRef(p)                (p)->AddRef()
+#define IDirectDrawGammaControl_Release(p)               (p)->Release()
+#define IDirectDrawGammaControl_GetGammaRamp(p, a, b)    (p)->GetGammaRamp(a, b)
+#define IDirectDrawGammaControl_SetGammaRamp(p, a, b)    (p)->SetGammaRamp(a, b)
+#endif
+
+#endif
+
+
+
+#endif
+
+
+/*
+ * DDSURFACEDESC
+ */
+typedef struct _DDSURFACEDESC
+{
+    DWORD               dwSize;                 // size of the DDSURFACEDESC structure
+    DWORD               dwFlags;                // determines what fields are valid
+    DWORD               dwHeight;               // height of surface to be created
+    DWORD               dwWidth;                // width of input surface
+    union
+    {
+        LONG            lPitch;                 // distance to start of next line (return value only)
+        DWORD           dwLinearSize;           // Formless late-allocated optimized surface size
+    } DUMMYUNIONNAMEN(1);
+    DWORD               dwBackBufferCount;      // number of back buffers requested
+    union
+    {
+        DWORD           dwMipMapCount;          // number of mip-map levels requested
+        DWORD           dwZBufferBitDepth;      // depth of Z buffer requested
+        DWORD           dwRefreshRate;          // refresh rate (used when display mode is described)
+    } DUMMYUNIONNAMEN(2);
+    DWORD               dwAlphaBitDepth;        // depth of alpha buffer requested
+    DWORD               dwReserved;             // reserved
+    LPVOID              lpSurface;              // pointer to the associated surface memory
+    DDCOLORKEY          ddckCKDestOverlay;      // color key for destination overlay use
+    DDCOLORKEY          ddckCKDestBlt;          // color key for destination blt use
+    DDCOLORKEY          ddckCKSrcOverlay;       // color key for source overlay use
+    DDCOLORKEY          ddckCKSrcBlt;           // color key for source blt use
+    DDPIXELFORMAT       ddpfPixelFormat;        // pixel format description of the surface
+    DDSCAPS             ddsCaps;                // direct draw surface capabilities
+} DDSURFACEDESC;
+
+/*
+ * DDSURFACEDESC2
+ */
+typedef struct _DDSURFACEDESC2
+{
+    DWORD               dwSize;                 // size of the DDSURFACEDESC structure
+    DWORD               dwFlags;                // determines what fields are valid
+    DWORD               dwHeight;               // height of surface to be created
+    DWORD               dwWidth;                // width of input surface
+    union
+    {
+        LONG            lPitch;                 // distance to start of next line (return value only)
+        DWORD           dwLinearSize;           // Formless late-allocated optimized surface size
+    } DUMMYUNIONNAMEN(1);
+    union
+    {
+        DWORD           dwBackBufferCount;      // number of back buffers requested
+        DWORD           dwDepth;                // the depth if this is a volume texture 
+    } DUMMYUNIONNAMEN(5);
+    union
+    {
+        DWORD           dwMipMapCount;          // number of mip-map levels requestde
+                                                // dwZBufferBitDepth removed, use ddpfPixelFormat one instead
+        DWORD           dwRefreshRate;          // refresh rate (used when display mode is described)
+        DWORD           dwSrcVBHandle;          // The source used in VB::Optimize
+    } DUMMYUNIONNAMEN(2);
+    DWORD               dwAlphaBitDepth;        // depth of alpha buffer requested
+    DWORD               dwReserved;             // reserved
+    LPVOID              lpSurface;              // pointer to the associated surface memory
+    union
+    {
+        DDCOLORKEY      ddckCKDestOverlay;      // color key for destination overlay use
+        DWORD           dwEmptyFaceColor;       // Physical color for empty cubemap faces
+    } DUMMYUNIONNAMEN(3);
+    DDCOLORKEY          ddckCKDestBlt;          // color key for destination blt use
+    DDCOLORKEY          ddckCKSrcOverlay;       // color key for source overlay use
+    DDCOLORKEY          ddckCKSrcBlt;           // color key for source blt use
+    union
+    {
+        DDPIXELFORMAT   ddpfPixelFormat;        // pixel format description of the surface
+        DWORD           dwFVF;                  // vertex format description of vertex buffers
+    } DUMMYUNIONNAMEN(4);
+    DDSCAPS2            ddsCaps;                // direct draw surface capabilities
+    DWORD               dwTextureStage;         // stage in multitexture cascade
+} DDSURFACEDESC2;
+
+/*
+ * ddsCaps field is valid.
+ */
+#define DDSD_CAPS               0x00000001l     // default
+
+/*
+ * dwHeight field is valid.
+ */
+#define DDSD_HEIGHT             0x00000002l
+
+/*
+ * dwWidth field is valid.
+ */
+#define DDSD_WIDTH              0x00000004l
+
+/*
+ * lPitch is valid.
+ */
+#define DDSD_PITCH              0x00000008l
+
+/*
+ * dwBackBufferCount is valid.
+ */
+#define DDSD_BACKBUFFERCOUNT    0x00000020l
+
+/*
+ * dwZBufferBitDepth is valid.  (shouldnt be used in DDSURFACEDESC2)
+ */
+#define DDSD_ZBUFFERBITDEPTH    0x00000040l
+
+/*
+ * dwAlphaBitDepth is valid.
+ */
+#define DDSD_ALPHABITDEPTH      0x00000080l
+
+
+/*
+ * lpSurface is valid.
+ */
+#define DDSD_LPSURFACE          0x00000800l
+
+/*
+ * ddpfPixelFormat is valid.
+ */
+#define DDSD_PIXELFORMAT        0x00001000l
+
+/*
+ * ddckCKDestOverlay is valid.
+ */
+#define DDSD_CKDESTOVERLAY      0x00002000l
+
+/*
+ * ddckCKDestBlt is valid.
+ */
+#define DDSD_CKDESTBLT          0x00004000l
+
+/*
+ * ddckCKSrcOverlay is valid.
+ */
+#define DDSD_CKSRCOVERLAY       0x00008000l
+
+/*
+ * ddckCKSrcBlt is valid.
+ */
+#define DDSD_CKSRCBLT           0x00010000l
+
+/*
+ * dwMipMapCount is valid.
+ */
+#define DDSD_MIPMAPCOUNT        0x00020000l
+
+ /*
+  * dwRefreshRate is valid
+  */
+#define DDSD_REFRESHRATE        0x00040000l
+
+/*
+ * dwLinearSize is valid
+ */
+#define DDSD_LINEARSIZE         0x00080000l
+
+/*
+ * dwTextureStage is valid
+ */
+#define DDSD_TEXTURESTAGE       0x00100000l
+/*
+ * dwFVF is valid
+ */
+#define DDSD_FVF                0x00200000l
+/*
+ * dwSrcVBHandle is valid
+ */
+#define DDSD_SRCVBHANDLE        0x00400000l
+
+/*
+ * dwDepth is valid
+ */
+#define DDSD_DEPTH              0x00800000l
+
+/*
+ * All input fields are valid.
+ */
+#define DDSD_ALL                0x00fff9eel
+
+/*
+ * DDOPTSURFACEDESC
+ */
+typedef struct _DDOPTSURFACEDESC
+{
+    DWORD       dwSize;             // size of the DDOPTSURFACEDESC structure
+    DWORD       dwFlags;            // determines what fields are valid
+    DDSCAPS2    ddSCaps;            // Common caps like: Memory type
+    DDOSCAPS    ddOSCaps;           // Common caps like: Memory type
+    GUID        guid;               // Compression technique GUID
+    DWORD       dwCompressionRatio; // Compression ratio
+} DDOPTSURFACEDESC;
+
+/*
+ * guid field is valid.
+ */
+#define DDOSD_GUID                  0x00000001l
+
+/*
+ * dwCompressionRatio field is valid.
+ */
+#define DDOSD_COMPRESSION_RATIO     0x00000002l
+
+/*
+ * ddSCaps field is valid.
+ */
+#define DDOSD_SCAPS                 0x00000004l
+
+/*
+ * ddOSCaps field is valid.
+ */
+#define DDOSD_OSCAPS                0x00000008l
+
+/*
+ * All input fields are valid.
+ */
+#define DDOSD_ALL                   0x0000000fl
+
+/*
+ * The surface's optimized pixelformat is compressed
+ */
+#define DDOSDCAPS_OPTCOMPRESSED                 0x00000001l
+
+/*
+ * The surface's optimized pixelformat is reordered
+ */
+#define DDOSDCAPS_OPTREORDERED                  0x00000002l
+
+/*
+ * The opt surface is a monolithic mipmap
+ */
+#define DDOSDCAPS_MONOLITHICMIPMAP              0x00000004l
+
+/*
+ * The valid Surf caps:
+ * #define DDSCAPS_SYSTEMMEMORY                 0x00000800l
+ * #define DDSCAPS_VIDEOMEMORY          0x00004000l
+ * #define DDSCAPS_LOCALVIDMEM          0x10000000l
+ * #define DDSCAPS_NONLOCALVIDMEM       0x20000000l
+ */
+#define DDOSDCAPS_VALIDSCAPS            0x30004800l
+
+/*
+ * The valid OptSurf caps
+ */
+#define DDOSDCAPS_VALIDOSCAPS           0x00000007l
+
+
+/*
+ * DDCOLORCONTROL
+ */
+typedef struct _DDCOLORCONTROL
+{
+    DWORD               dwSize;
+    DWORD               dwFlags;
+    LONG                lBrightness;
+    LONG                lContrast;
+    LONG                lHue;
+    LONG                lSaturation;
+    LONG                lSharpness;
+    LONG                lGamma;
+    LONG                lColorEnable;
+    DWORD               dwReserved1;
+} DDCOLORCONTROL;
+
+
+/*
+ * lBrightness field is valid.
+ */
+#define DDCOLOR_BRIGHTNESS              0x00000001l
+
+/*
+ * lContrast field is valid.
+ */
+#define DDCOLOR_CONTRAST                0x00000002l
+
+/*
+ * lHue field is valid.
+ */
+#define DDCOLOR_HUE                     0x00000004l
+
+/*
+ * lSaturation field is valid.
+ */
+#define DDCOLOR_SATURATION              0x00000008l
+
+/*
+ * lSharpness field is valid.
+ */
+#define DDCOLOR_SHARPNESS               0x00000010l
+
+/*
+ * lGamma field is valid.
+ */
+#define DDCOLOR_GAMMA                   0x00000020l
+
+/*
+ * lColorEnable field is valid.
+ */
+#define DDCOLOR_COLORENABLE             0x00000040l
+
+
+
+/*============================================================================
+ *
+ * Direct Draw Capability Flags
+ *
+ * These flags are used to describe the capabilities of a given Surface.
+ * All flags are bit flags.
+ *
+ *==========================================================================*/
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * This bit is reserved. It should not be specified.
+ */
+#define DDSCAPS_RESERVED1                       0x00000001l
+
+/*
+ * Indicates that this surface contains alpha-only information.
+ * (To determine if a surface is RGBA/YUVA, the pixel format must be
+ * interrogated.)
+ */
+#define DDSCAPS_ALPHA                           0x00000002l
+
+/*
+ * Indicates that this surface is a backbuffer.  It is generally
+ * set by CreateSurface when the DDSCAPS_FLIP capability bit is set.
+ * It indicates that this surface is THE back buffer of a surface
+ * flipping structure.  DirectDraw supports N surfaces in a
+ * surface flipping structure.  Only the surface that immediately
+ * precedeces the DDSCAPS_FRONTBUFFER has this capability bit set.
+ * The other surfaces are identified as back buffers by the presence
+ * of the DDSCAPS_FLIP capability, their attachment order, and the
+ * absence of the DDSCAPS_FRONTBUFFER and DDSCAPS_BACKBUFFER
+ * capabilities.  The bit is sent to CreateSurface when a standalone
+ * back buffer is being created.  This surface could be attached to
+ * a front buffer and/or back buffers to form a flipping surface
+ * structure after the CreateSurface call.  See AddAttachments for
+ * a detailed description of the behaviors in this case.
+ */
+#define DDSCAPS_BACKBUFFER                      0x00000004l
+
+/*
+ * Indicates a complex surface structure is being described.  A
+ * complex surface structure results in the creation of more than
+ * one surface.  The additional surfaces are attached to the root
+ * surface.  The complex structure can only be destroyed by
+ * destroying the root.
+ */
+#define DDSCAPS_COMPLEX                         0x00000008l
+
+/*
+ * Indicates that this surface is a part of a surface flipping structure.
+ * When it is passed to CreateSurface the DDSCAPS_FRONTBUFFER and
+ * DDSCAP_BACKBUFFER bits are not set.  They are set by CreateSurface
+ * on the resulting creations.  The dwBackBufferCount field in the
+ * DDSURFACEDESC structure must be set to at least 1 in order for
+ * the CreateSurface call to succeed.  The DDSCAPS_COMPLEX capability
+ * must always be set with creating multiple surfaces through CreateSurface.
+ */
+#define DDSCAPS_FLIP                            0x00000010l
+
+/*
+ * Indicates that this surface is THE front buffer of a surface flipping
+ * structure.  It is generally set by CreateSurface when the DDSCAPS_FLIP
+ * capability bit is set.
+ * If this capability is sent to CreateSurface then a standalonw front buffer
+ * is created.  This surface will not have the DDSCAPS_FLIP capability.
+ * It can be attached to other back buffers to form a flipping structure.
+ * See AddAttachments for a detailed description of the behaviors in this
+ * case.
+ */
+#define DDSCAPS_FRONTBUFFER                     0x00000020l
+
+/*
+ * Indicates that this surface is any offscreen surface that is not an overlay,
+ * texture, zbuffer, front buffer, back buffer, or alpha surface.  It is used
+ * to identify plain vanilla surfaces.
+ */
+#define DDSCAPS_OFFSCREENPLAIN                  0x00000040l
+
+/*
+ * Indicates that this surface is an overlay.  It may or may not be directly visible
+ * depending on whether or not it is currently being overlayed onto the primary
+ * surface.  DDSCAPS_VISIBLE can be used to determine whether or not it is being
+ * overlayed at the moment.
+ */
+#define DDSCAPS_OVERLAY                         0x00000080l
+
+/*
+ * Indicates that unique DirectDrawPalette objects can be created and
+ * attached to this surface.
+ */
+#define DDSCAPS_PALETTE                         0x00000100l
+
+/*
+ * Indicates that this surface is the primary surface.  The primary
+ * surface represents what the user is seeing at the moment.
+ */
+#define DDSCAPS_PRIMARYSURFACE                  0x00000200l
+
+
+/*
+ * This flag used to be DDSCAPS_PRIMARYSURFACELEFT, which is now
+ * obsolete.
+ */
+#define DDSCAPS_RESERVED3               0x00000400l
+#define DDSCAPS_PRIMARYSURFACELEFT              0x00000000l
+
+/*
+ * Indicates that this surface memory was allocated in system memory
+ */
+#define DDSCAPS_SYSTEMMEMORY                    0x00000800l
+
+/*
+ * Indicates that this surface can be used as a 3D texture.  It does not
+ * indicate whether or not the surface is being used for that purpose.
+ */
+#define DDSCAPS_TEXTURE                         0x00001000l
+
+/*
+ * Indicates that a surface may be a destination for 3D rendering.  This
+ * bit must be set in order to query for a Direct3D Device Interface
+ * from this surface.
+ */
+#define DDSCAPS_3DDEVICE                        0x00002000l
+
+/*
+ * Indicates that this surface exists in video memory.
+ */
+#define DDSCAPS_VIDEOMEMORY                     0x00004000l
+
+/*
+ * Indicates that changes made to this surface are immediately visible.
+ * It is always set for the primary surface and is set for overlays while
+ * they are being overlayed and texture maps while they are being textured.
+ */
+#define DDSCAPS_VISIBLE                         0x00008000l
+
+/*
+ * Indicates that only writes are permitted to the surface.  Read accesses
+ * from the surface may or may not generate a protection fault, but the
+ * results of a read from this surface will not be meaningful.  READ ONLY.
+ */
+#define DDSCAPS_WRITEONLY                       0x00010000l
+
+/*
+ * Indicates that this surface is a z buffer. A z buffer does not contain
+ * displayable information.  Instead it contains bit depth information that is
+ * used to determine which pixels are visible and which are obscured.
+ */
+#define DDSCAPS_ZBUFFER                         0x00020000l
+
+/*
+ * Indicates surface will have a DC associated long term
+ */
+#define DDSCAPS_OWNDC                           0x00040000l
+
+/*
+ * Indicates surface should be able to receive live video
+ */
+#define DDSCAPS_LIVEVIDEO                       0x00080000l
+
+/*
+ * Indicates surface should be able to have a stream decompressed
+ * to it by the hardware.
+ */
+#define DDSCAPS_HWCODEC                         0x00100000l
+
+/*
+ * Surface is a ModeX surface.
+ *
+ */
+#define DDSCAPS_MODEX                           0x00200000l
+
+/*
+ * Indicates surface is one level of a mip-map. This surface will
+ * be attached to other DDSCAPS_MIPMAP surfaces to form the mip-map.
+ * This can be done explicitly, by creating a number of surfaces and
+ * attaching them with AddAttachedSurface or by implicitly by CreateSurface.
+ * If this bit is set then DDSCAPS_TEXTURE must also be set.
+ */
+#define DDSCAPS_MIPMAP                          0x00400000l
+
+/*
+ * This bit is reserved. It should not be specified.
+ */
+#define DDSCAPS_RESERVED2                       0x00800000l
+
+
+/*
+ * Indicates that memory for the surface is not allocated until the surface
+ * is loaded (via the Direct3D texture Load() function).
+ */
+#define DDSCAPS_ALLOCONLOAD                     0x04000000l
+
+/*
+ * Indicates that the surface will recieve data from a video port.
+ */
+#define DDSCAPS_VIDEOPORT                       0x08000000l
+
+/*
+ * Indicates that a video memory surface is resident in true, local video
+ * memory rather than non-local video memory. If this flag is specified then
+ * so must DDSCAPS_VIDEOMEMORY. This flag is mutually exclusive with
+ * DDSCAPS_NONLOCALVIDMEM.
+ */
+#define DDSCAPS_LOCALVIDMEM                     0x10000000l
+
+/*
+ * Indicates that a video memory surface is resident in non-local video
+ * memory rather than true, local video memory. If this flag is specified
+ * then so must DDSCAPS_VIDEOMEMORY. This flag is mutually exclusive with
+ * DDSCAPS_LOCALVIDMEM.
+ */
+#define DDSCAPS_NONLOCALVIDMEM                  0x20000000l
+
+/*
+ * Indicates that this surface is a standard VGA mode surface, and not a
+ * ModeX surface. (This flag will never be set in combination with the
+ * DDSCAPS_MODEX flag).
+ */
+#define DDSCAPS_STANDARDVGAMODE                 0x40000000l
+
+/*
+ * Indicates that this surface will be an optimized surface. This flag is
+ * currently only valid in conjunction with the DDSCAPS_TEXTURE flag. The surface
+ * will be created without any underlying video memory until loaded.
+ */
+#define DDSCAPS_OPTIMIZED                       0x80000000l
+
+
+
+/*
+ * This bit is reserved
+ */
+#define DDSCAPS2_RESERVED4                      0x00000002L
+#define DDSCAPS2_HARDWAREDEINTERLACE            0x00000000L
+
+/*
+ * Indicates to the driver that this surface will be locked very frequently
+ * (for procedural textures, dynamic lightmaps, etc). Surfaces with this cap
+ * set must also have DDSCAPS_TEXTURE. This cap cannot be used with
+ * DDSCAPS2_HINTSTATIC and DDSCAPS2_OPAQUE.
+ */
+#define DDSCAPS2_HINTDYNAMIC                    0x00000004L
+
+/*
+ * Indicates to the driver that this surface can be re-ordered/retiled on
+ * load. This operation will not change the size of the texture. It is
+ * relatively fast and symmetrical, since the application may lock these
+ * bits (although it will take a performance hit when doing so). Surfaces
+ * with this cap set must also have DDSCAPS_TEXTURE. This cap cannot be
+ * used with DDSCAPS2_HINTDYNAMIC and DDSCAPS2_OPAQUE.
+ */
+#define DDSCAPS2_HINTSTATIC                     0x00000008L
+
+/*
+ * Indicates that the client would like this texture surface to be managed by the
+ * DirectDraw/Direct3D runtime. Surfaces with this cap set must also have
+ * DDSCAPS_TEXTURE set.
+ */
+#define DDSCAPS2_TEXTUREMANAGE                  0x00000010L
+
+/*
+ * These bits are reserved for internal use */
+#define DDSCAPS2_RESERVED1                      0x00000020L
+#define DDSCAPS2_RESERVED2                      0x00000040L
+
+/*
+ * Indicates to the driver that this surface will never be locked again.
+ * The driver is free to optimize this surface via retiling and actual compression.
+ * All calls to Lock() or Blts from this surface will fail. Surfaces with this
+ * cap set must also have DDSCAPS_TEXTURE. This cap cannot be used with
+ * DDSCAPS2_HINTDYNAMIC and DDSCAPS2_HINTSTATIC.
+ */
+#define DDSCAPS2_OPAQUE                         0x00000080L
+
+/*
+ * Applications should set this bit at CreateSurface time to indicate that they
+ * intend to use antialiasing. Only valid if DDSCAPS_3DDEVICE is also set.
+ */
+#define DDSCAPS2_HINTANTIALIASING               0x00000100L
+
+
+/*
+ * This flag is used at CreateSurface time to indicate that this set of
+ * surfaces is a cubic environment map
+ */
+#define DDSCAPS2_CUBEMAP                        0x00000200L
+
+/*
+ * These flags preform two functions:
+ * - At CreateSurface time, they define which of the six cube faces are
+ *   required by the application.
+ * - After creation, each face in the cubemap will have exactly one of these
+ *   bits set.
+ */
+#define DDSCAPS2_CUBEMAP_POSITIVEX              0x00000400L
+#define DDSCAPS2_CUBEMAP_NEGATIVEX              0x00000800L
+#define DDSCAPS2_CUBEMAP_POSITIVEY              0x00001000L
+#define DDSCAPS2_CUBEMAP_NEGATIVEY              0x00002000L
+#define DDSCAPS2_CUBEMAP_POSITIVEZ              0x00004000L
+#define DDSCAPS2_CUBEMAP_NEGATIVEZ              0x00008000L
+
+/*
+ * This macro may be used to specify all faces of a cube map at CreateSurface time
+ */
+#define DDSCAPS2_CUBEMAP_ALLFACES ( DDSCAPS2_CUBEMAP_POSITIVEX |\
+                                    DDSCAPS2_CUBEMAP_NEGATIVEX |\
+                                    DDSCAPS2_CUBEMAP_POSITIVEY |\
+                                    DDSCAPS2_CUBEMAP_NEGATIVEY |\
+                                    DDSCAPS2_CUBEMAP_POSITIVEZ |\
+                                    DDSCAPS2_CUBEMAP_NEGATIVEZ )
+
+
+/*
+ * This flag is an additional flag which is present on mipmap sublevels from DX7 onwards
+ * It enables easier use of GetAttachedSurface rather than EnumAttachedSurfaces for surface
+ * constructs such as Cube Maps, wherein there are more than one mipmap surface attached
+ * to the root surface.
+ * This caps bit is ignored by CreateSurface
+ */
+#define DDSCAPS2_MIPMAPSUBLEVEL                 0x00010000L
+
+/* This flag indicates that the texture should be managed by D3D only */
+#define DDSCAPS2_D3DTEXTUREMANAGE               0x00020000L
+
+/* This flag indicates that the managed surface can be safely lost */
+#define DDSCAPS2_DONOTPERSIST                   0x00040000L
+
+/* indicates that this surface is part of a stereo flipping chain */
+#define DDSCAPS2_STEREOSURFACELEFT              0x00080000L
+
+
+/*
+ * Indicates that the surface is a volume.
+ * Can be combined with DDSCAPS_MIPMAP to indicate a multi-level volume
+ */
+#define DDSCAPS2_VOLUME                         0x00200000L
+
+/*
+ * Indicates that the surface may be locked multiple times by the application.
+ * This cap cannot be used with DDSCAPS2_OPAQUE.
+ */
+#define DDSCAPS2_NOTUSERLOCKABLE                0x00400000L
+
+/*
+ * Indicates that the vertex buffer data can be used to render points and
+ * point sprites.
+ */
+#define DDSCAPS2_POINTS                         0x00800000L
+
+/*
+ * Indicates that the vertex buffer data can be used to render rt pactches.
+ */
+#define DDSCAPS2_RTPATCHES                      0x01000000L
+
+/*
+ * Indicates that the vertex buffer data can be used to render n patches.
+ */
+#define DDSCAPS2_NPATCHES                       0x02000000L
+
+/*
+ * This bit is reserved for internal use 
+ */
+#define DDSCAPS2_RESERVED3                      0x04000000L
+
+
+/*
+ * Indicates that the contents of the backbuffer do not have to be preserved
+ * the contents of the backbuffer after they are presented.
+ */
+#define DDSCAPS2_DISCARDBACKBUFFER              0x10000000L
+
+/*
+ * Indicates that all surfaces in this creation chain should be given an alpha channel.
+ * This flag will be set on primary surface chains that may have no explicit pixel format
+ * (and thus take on the format of the current display mode).
+ * The driver should infer that all these surfaces have a format having an alpha channel.
+ * (e.g. assume D3DFMT_A8R8G8B8 if the display mode is x888.)
+ */
+#define DDSCAPS2_ENABLEALPHACHANNEL             0x20000000L
+
+/*
+ * Indicates that all surfaces in this creation chain is extended primary surface format.
+ * This flag will be set on extended primary surface chains that always have explicit pixel
+ * format and the pixel format is typically GDI (Graphics Device Interface) couldn't handle,
+ * thus only used with fullscreen application. (e.g. D3DFMT_A2R10G10B10 format)
+ */
+#define DDSCAPS2_EXTENDEDFORMATPRIMARY          0x40000000L
+
+/*
+ * Indicates that all surfaces in this creation chain is additional primary surface.
+ * This flag will be set on primary surface chains which must present on the adapter
+ * id provided on dwCaps4. Typically this will be used to create secondary primary surface
+ * on DualView display adapter.
+ */
+#define DDSCAPS2_ADDITIONALPRIMARY              0x80000000L
+
+/*
+ * This is a mask that indicates the set of bits that may be set
+ * at createsurface time to indicate number of samples per pixel
+ * when multisampling
+ */
+#define DDSCAPS3_MULTISAMPLE_MASK               0x0000001FL
+
+/*
+ * This is a mask that indicates the set of bits that may be set
+ * at createsurface time to indicate the quality level of rendering
+ * for the current number of samples per pixel
+ */
+#define DDSCAPS3_MULTISAMPLE_QUALITY_MASK       0x000000E0L
+#define DDSCAPS3_MULTISAMPLE_QUALITY_SHIFT      5
+
+/*
+ * This bit is reserved for internal use 
+ */
+#define DDSCAPS3_RESERVED1                      0x00000100L
+
+/*
+ * This bit is reserved for internal use 
+ */
+#define DDSCAPS3_RESERVED2                      0x00000200L
+
+/*
+ * This indicates whether this surface has light-weight miplevels
+ */
+#define DDSCAPS3_LIGHTWEIGHTMIPMAP              0x00000400L
+
+/*
+ * This indicates that the mipsublevels for this surface are auto-generated
+ */
+#define DDSCAPS3_AUTOGENMIPMAP                  0x00000800L
+
+/*
+ * This indicates that the mipsublevels for this surface are auto-generated
+ */
+#define DDSCAPS3_DMAP                           0x00001000L
+
+
+ /****************************************************************************
+ *
+ * DIRECTDRAW DRIVER CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Display hardware has 3D acceleration.
+ */
+#define DDCAPS_3D                       0x00000001l
+
+/*
+ * Indicates that DirectDraw will support only dest rectangles that are aligned
+ * on DIRECTDRAWCAPS.dwAlignBoundaryDest boundaries of the surface, respectively.
+ * READ ONLY.
+ */
+#define DDCAPS_ALIGNBOUNDARYDEST        0x00000002l
+
+/*
+ * Indicates that DirectDraw will support only source rectangles  whose sizes in
+ * BYTEs are DIRECTDRAWCAPS.dwAlignSizeDest multiples, respectively.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSIZEDEST            0x00000004l
+/*
+ * Indicates that DirectDraw will support only source rectangles that are aligned
+ * on DIRECTDRAWCAPS.dwAlignBoundarySrc boundaries of the surface, respectively.
+ * READ ONLY.
+ */
+#define DDCAPS_ALIGNBOUNDARYSRC         0x00000008l
+
+/*
+ * Indicates that DirectDraw will support only source rectangles  whose sizes in
+ * BYTEs are DIRECTDRAWCAPS.dwAlignSizeSrc multiples, respectively.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSIZESRC             0x00000010l
+
+/*
+ * Indicates that DirectDraw will create video memory surfaces that have a stride
+ * alignment equal to DIRECTDRAWCAPS.dwAlignStride.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSTRIDE              0x00000020l
+
+/*
+ * Display hardware is capable of blt operations.
+ */
+#define DDCAPS_BLT                      0x00000040l
+
+/*
+ * Display hardware is capable of asynchronous blt operations.
+ */
+#define DDCAPS_BLTQUEUE                 0x00000080l
+
+/*
+ * Display hardware is capable of color space conversions during the blt operation.
+ */
+#define DDCAPS_BLTFOURCC                0x00000100l
+
+/*
+ * Display hardware is capable of stretching during blt operations.
+ */
+#define DDCAPS_BLTSTRETCH               0x00000200l
+
+/*
+ * Display hardware is shared with GDI.
+ */
+#define DDCAPS_GDI                      0x00000400l
+
+/*
+ * Display hardware can overlay.
+ */
+#define DDCAPS_OVERLAY                  0x00000800l
+
+/*
+ * Set if display hardware supports overlays but can not clip them.
+ */
+#define DDCAPS_OVERLAYCANTCLIP          0x00001000l
+
+/*
+ * Indicates that overlay hardware is capable of color space conversions during
+ * the overlay operation.
+ */
+#define DDCAPS_OVERLAYFOURCC            0x00002000l
+
+/*
+ * Indicates that stretching can be done by the overlay hardware.
+ */
+#define DDCAPS_OVERLAYSTRETCH           0x00004000l
+
+/*
+ * Indicates that unique DirectDrawPalettes can be created for DirectDrawSurfaces
+ * other than the primary surface.
+ */
+#define DDCAPS_PALETTE                  0x00008000l
+
+/*
+ * Indicates that palette changes can be syncd with the veritcal refresh.
+ */
+#define DDCAPS_PALETTEVSYNC             0x00010000l
+
+/*
+ * Display hardware can return the current scan line.
+ */
+#define DDCAPS_READSCANLINE             0x00020000l
+
+
+/*
+ * This flag used to bo DDCAPS_STEREOVIEW, which is now obsolete
+ */
+#define DDCAPS_RESERVED1                0x00040000l
+
+/*
+ * Display hardware is capable of generating a vertical blank interrupt.
+ */
+#define DDCAPS_VBI                      0x00080000l
+
+/*
+ * Supports the use of z buffers with blt operations.
+ */
+#define DDCAPS_ZBLTS                    0x00100000l
+
+/*
+ * Supports Z Ordering of overlays.
+ */
+#define DDCAPS_ZOVERLAYS                0x00200000l
+
+/*
+ * Supports color key
+ */
+#define DDCAPS_COLORKEY                 0x00400000l
+
+/*
+ * Supports alpha surfaces
+ */
+#define DDCAPS_ALPHA                    0x00800000l
+
+/*
+ * colorkey is hardware assisted(DDCAPS_COLORKEY will also be set)
+ */
+#define DDCAPS_COLORKEYHWASSIST         0x01000000l
+
+/*
+ * no hardware support at all
+ */
+#define DDCAPS_NOHARDWARE               0x02000000l
+
+/*
+ * Display hardware is capable of color fill with bltter
+ */
+#define DDCAPS_BLTCOLORFILL             0x04000000l
+
+/*
+ * Display hardware is bank switched, and potentially very slow at
+ * random access to VRAM.
+ */
+#define DDCAPS_BANKSWITCHED             0x08000000l
+
+/*
+ * Display hardware is capable of depth filling Z-buffers with bltter
+ */
+#define DDCAPS_BLTDEPTHFILL             0x10000000l
+
+/*
+ * Display hardware is capable of clipping while bltting.
+ */
+#define DDCAPS_CANCLIP                  0x20000000l
+
+/*
+ * Display hardware is capable of clipping while stretch bltting.
+ */
+#define DDCAPS_CANCLIPSTRETCHED         0x40000000l
+
+/*
+ * Display hardware is capable of bltting to or from system memory
+ */
+#define DDCAPS_CANBLTSYSMEM             0x80000000l
+
+
+ /****************************************************************************
+ *
+ * MORE DIRECTDRAW DRIVER CAPABILITY FLAGS (dwCaps2)
+ *
+ ****************************************************************************/
+
+/*
+ * Display hardware is certified
+ */
+#define DDCAPS2_CERTIFIED              0x00000001l
+
+/*
+ * Driver cannot interleave 2D operations (lock and blt) to surfaces with
+ * Direct3D rendering operations between calls to BeginScene() and EndScene()
+ */
+#define DDCAPS2_NO2DDURING3DSCENE       0x00000002l
+
+/*
+ * Display hardware contains a video port
+ */
+#define DDCAPS2_VIDEOPORT               0x00000004l
+
+/*
+ * The overlay can be automatically flipped according to the video port
+ * VSYNCs, providing automatic doubled buffered display of video port
+ * data using an overlay
+ */
+#define DDCAPS2_AUTOFLIPOVERLAY         0x00000008l
+
+/*
+ * Overlay can display each field of interlaced data individually while
+ * it is interleaved in memory without causing jittery artifacts.
+ */
+#define DDCAPS2_CANBOBINTERLEAVED       0x00000010l
+
+/*
+ * Overlay can display each field of interlaced data individually while
+ * it is not interleaved in memory without causing jittery artifacts.
+ */
+#define DDCAPS2_CANBOBNONINTERLEAVED    0x00000020l
+
+/*
+ * The overlay surface contains color controls (brightness, sharpness, etc.)
+ */
+#define DDCAPS2_COLORCONTROLOVERLAY     0x00000040l
+
+/*
+ * The primary surface contains color controls (gamma, etc.)
+ */
+#define DDCAPS2_COLORCONTROLPRIMARY     0x00000080l
+
+/*
+ * RGBZ -> RGB supported for 16:16 RGB:Z
+ */
+#define DDCAPS2_CANDROPZ16BIT           0x00000100l
+
+/*
+ * Driver supports non-local video memory.
+ */
+#define DDCAPS2_NONLOCALVIDMEM          0x00000200l
+
+/*
+ * Dirver supports non-local video memory but has different capabilities for
+ * non-local video memory surfaces. If this bit is set then so must
+ * DDCAPS2_NONLOCALVIDMEM.
+ */
+#define DDCAPS2_NONLOCALVIDMEMCAPS      0x00000400l
+
+/*
+ * Driver neither requires nor prefers surfaces to be pagelocked when performing
+ * blts involving system memory surfaces
+ */
+#define DDCAPS2_NOPAGELOCKREQUIRED      0x00000800l
+
+/*
+ * Driver can create surfaces which are wider than the primary surface
+ */
+#define DDCAPS2_WIDESURFACES            0x00001000l
+
+/*
+ * Driver supports bob without using a video port by handling the
+ * DDFLIP_ODD and DDFLIP_EVEN flags specified in Flip.
+ */
+#define DDCAPS2_CANFLIPODDEVEN          0x00002000l
+
+/*
+ * Driver supports bob using hardware
+ */
+#define DDCAPS2_CANBOBHARDWARE          0x00004000l
+
+/*
+ * Driver supports bltting any FOURCC surface to another surface of the same FOURCC
+ */
+#define DDCAPS2_COPYFOURCC              0x00008000l
+
+
+/*
+ * Driver supports loadable gamma ramps for the primary surface
+ */
+#define DDCAPS2_PRIMARYGAMMA            0x00020000l
+
+/*
+ * Driver can render in windowed mode.
+ */
+#define DDCAPS2_CANRENDERWINDOWED       0x00080000l
+
+/*
+ * A calibrator is available to adjust the gamma ramp according to the
+ * physical display properties so that the result will be identical on
+ * all calibrated systems.
+ */
+#define DDCAPS2_CANCALIBRATEGAMMA       0x00100000l
+
+/*
+ * Indicates that the driver will respond to DDFLIP_INTERVALn flags
+ */
+#define DDCAPS2_FLIPINTERVAL            0x00200000l
+
+/*
+ * Indicates that the driver will respond to DDFLIP_NOVSYNC
+ */
+#define DDCAPS2_FLIPNOVSYNC             0x00400000l
+
+/*
+ * Driver supports management of video memory, if this flag is ON,
+ * driver manages the texture if requested with DDSCAPS2_TEXTUREMANAGE on
+ * DirectX manages the texture if this flag is OFF and surface has DDSCAPS2_TEXTUREMANAGE on
+ */
+#define DDCAPS2_CANMANAGETEXTURE        0x00800000l
+
+/*
+ * The Direct3D texture manager uses this cap to decide whether to put managed
+ * surfaces in non-local video memory. If the cap is set, the texture manager will
+ * put managed surfaces in non-local vidmem. Drivers that cannot texture from
+ * local vidmem SHOULD NOT set this cap.
+ */
+#define DDCAPS2_TEXMANINNONLOCALVIDMEM  0x01000000l
+
+/*
+ * Indicates that the driver supports DX7 type of stereo in at least one mode (which may
+ * not necessarily be the current mode). Applications should use IDirectDraw7 (or higher)
+ * ::EnumDisplayModes and check the DDSURFACEDESC.ddsCaps.dwCaps2 field for the presence of
+ * DDSCAPS2_STEREOSURFACELEFT to check if a particular mode supports stereo. The application
+ * can also use IDirectDraw7(or higher)::GetDisplayMode to check the current mode.
+ */
+#define DDCAPS2_STEREO                  0x02000000L
+
+/*
+ * This caps bit is intended for internal DirectDraw use.
+ * -It is only valid if DDCAPS2_NONLOCALVIDMEMCAPS is set.
+ * -If this bit is set, then DDCAPS_CANBLTSYSMEM MUST be set by the driver (and
+ *  all the assoicated system memory blt caps must be correct).
+ * -It implies that the system->video blt caps in DDCAPS also apply to system to
+ *  nonlocal blts. I.e. the dwSVBCaps, dwSVBCKeyCaps, dwSVBFXCaps and dwSVBRops
+ *  members of DDCAPS (DDCORECAPS) are filled in correctly.
+ * -Any blt from system to nonlocal memory that matches these caps bits will
+ *  be passed to the driver.
+ *
+ * NOTE: This is intended to enable the driver itself to do efficient reordering
+ * of textures. This is NOT meant to imply that hardware can write into AGP memory.
+ * This operation is not currently supported.
+ */
+#define DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL   0x04000000L
+
+/*
+ * was DDCAPS2_PUREHAL
+ */
+#define DDCAPS2_RESERVED1                     0x08000000L
+
+/*
+ * Driver supports management of video memory, if this flag is ON,
+ * driver manages the resource if requested with DDSCAPS2_TEXTUREMANAGE on
+ * DirectX manages the resource if this flag is OFF and surface has DDSCAPS2_TEXTUREMANAGE on
+ */
+#define DDCAPS2_CANMANAGERESOURCE             0x10000000L
+
+/*
+ * Driver supports dynamic textures. This will allow the application to set
+ * D3DUSAGE_DYNAMIC (DDSCAPS2_HINTDYNAMIC for drivers) at texture create time.
+ * Video memory dynamic textures WILL be lockable by applications. It is
+ * expected that these locks will be very efficient (which implies that the
+ * driver should always maintain a linear copy, a pointer to which can be
+ * quickly handed out to the application).
+ */
+#define DDCAPS2_DYNAMICTEXTURES               0x20000000L
+
+/*
+ * Driver supports auto-generation of mipmaps.
+ */
+#define DDCAPS2_CANAUTOGENMIPMAP              0x40000000L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW FX ALPHA CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Supports alpha blending around the edge of a source color keyed surface.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAEDGEBLEND         0x00000001l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value becomes
+ * more opaque as the alpha value increases.  (0 is transparent.)
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAPIXELS            0x00000002l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value
+ * becomes more transparent as the alpha value increases.  (0 is opaque.)
+ * This flag can only be set if DDCAPS_ALPHA is set.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAPIXELSNEG         0x00000004l
+
+/*
+ * Supports alpha only surfaces.  The bit depth of an alpha only surface can be
+ * 1,2,4, or 8.  The alpha value becomes more opaque as the alpha value increases.
+ * (0 is transparent.)
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHASURFACES          0x00000008l
+
+/*
+ * The depth of the alpha channel data can range can be 1,2,4, or 8.
+ * The NEG suffix indicates that this alpha channel becomes more transparent
+ * as the alpha value increases. (0 is opaque.)  This flag can only be set if
+ * DDCAPS_ALPHA is set.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHASURFACESNEG       0x00000010l
+
+/*
+ * Supports alpha blending around the edge of a source color keyed surface.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND     0x00000020l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value becomes
+ * more opaque as the alpha value increases.  (0 is transparent.)
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAPIXELS        0x00000040l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value
+ * becomes more transparent as the alpha value increases.  (0 is opaque.)
+ * This flag can only be set if DDCAPS_ALPHA is set.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG     0x00000080l
+
+/*
+ * Supports alpha only surfaces.  The bit depth of an alpha only surface can be
+ * 1,2,4, or 8.  The alpha value becomes more opaque as the alpha value increases.
+ * (0 is transparent.)
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHASURFACES      0x00000100l
+
+/*
+ * The depth of the alpha channel data can range can be 1,2,4, or 8.
+ * The NEG suffix indicates that this alpha channel becomes more transparent
+ * as the alpha value increases. (0 is opaque.)  This flag can only be set if
+ * DDCAPS_ALPHA is set.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHASURFACESNEG   0x00000200l
+
+#if DIRECTDRAW_VERSION < 0x0600
+#endif  //DIRECTDRAW_VERSION
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW FX CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Uses arithmetic operations to stretch and shrink surfaces during blt
+ * rather than pixel doubling techniques.  Along the Y axis.
+ */
+#define DDFXCAPS_BLTARITHSTRETCHY       0x00000020l
+
+/*
+ * Uses arithmetic operations to stretch during blt
+ * rather than pixel doubling techniques.  Along the Y axis. Only
+ * works for x1, x2, etc.
+ */
+#define DDFXCAPS_BLTARITHSTRETCHYN      0x00000010l
+
+/*
+ * Supports mirroring left to right in blt.
+ */
+#define DDFXCAPS_BLTMIRRORLEFTRIGHT     0x00000040l
+
+/*
+ * Supports mirroring top to bottom in blt.
+ */
+#define DDFXCAPS_BLTMIRRORUPDOWN        0x00000080l
+
+/*
+ * Supports arbitrary rotation for blts.
+ */
+#define DDFXCAPS_BLTROTATION            0x00000100l
+
+/*
+ * Supports 90 degree rotations for blts.
+ */
+#define DDFXCAPS_BLTROTATION90          0x00000200l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSHRINKX             0x00000400l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSHRINKXN            0x00000800l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * y axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSHRINKY             0x00001000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the y axis (vertical direction) for blts.
+ */
+#define DDFXCAPS_BLTSHRINKYN            0x00002000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSTRETCHX            0x00004000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSTRETCHXN           0x00008000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * y axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSTRETCHY            0x00010000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the y axis (vertical direction) for blts.
+ */
+#define DDFXCAPS_BLTSTRETCHYN           0x00020000l
+
+/*
+ * Uses arithmetic operations to stretch and shrink surfaces during
+ * overlay rather than pixel doubling techniques.  Along the Y axis
+ * for overlays.
+ */
+#define DDFXCAPS_OVERLAYARITHSTRETCHY   0x00040000l
+
+/*
+ * Uses arithmetic operations to stretch surfaces during
+ * overlay rather than pixel doubling techniques.  Along the Y axis
+ * for overlays. Only works for x1, x2, etc.
+ */
+#define DDFXCAPS_OVERLAYARITHSTRETCHYN  0x00000008l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSHRINKX         0x00080000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSHRINKXN        0x00100000l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * y axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSHRINKY         0x00200000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the y axis (vertical direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSHRINKYN        0x00400000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSTRETCHX        0x00800000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSTRETCHXN       0x01000000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * y axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSTRETCHY        0x02000000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the y axis (vertical direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSTRETCHYN       0x04000000l
+
+/*
+ * DirectDraw supports mirroring of overlays across the vertical axis
+ */
+#define DDFXCAPS_OVERLAYMIRRORLEFTRIGHT 0x08000000l
+
+/*
+ * DirectDraw supports mirroring of overlays across the horizontal axis
+ */
+#define DDFXCAPS_OVERLAYMIRRORUPDOWN    0x10000000l
+
+/*
+ * DirectDraw supports deinterlacing of overlay surfaces
+ */
+#define DDFXCAPS_OVERLAYDEINTERLACE		0x20000000l
+
+/*
+ * Driver can do alpha blending for blits.
+ */
+#define DDFXCAPS_BLTALPHA               0x00000001l
+
+
+/*
+ * Driver can do surface-reconstruction filtering for warped blits.
+ */
+#define DDFXCAPS_BLTFILTER              DDFXCAPS_BLTARITHSTRETCHY
+
+/*
+ * Driver can do alpha blending for overlays.
+ */
+#define DDFXCAPS_OVERLAYALPHA           0x00000004l
+
+
+/*
+ * Driver can do surface-reconstruction filtering for warped overlays.
+ */
+#define DDFXCAPS_OVERLAYFILTER          DDFXCAPS_OVERLAYARITHSTRETCHY
+
+/****************************************************************************
+ *
+ * DIRECTDRAW STEREO VIEW CAPABILITIES
+ *
+ ****************************************************************************/
+
+/*
+ * This flag used to be DDSVCAPS_ENIGMA, which is now obsolete
+ */
+
+#define DDSVCAPS_RESERVED1              0x00000001l
+
+/*
+ * This flag used to be DDSVCAPS_FLICKER, which is now obsolete
+ */
+#define DDSVCAPS_RESERVED2              0x00000002l
+
+/*
+ * This flag used to be DDSVCAPS_REDBLUE, which is now obsolete
+ */
+#define DDSVCAPS_RESERVED3              0x00000004l
+
+/*
+ * This flag used to be DDSVCAPS_SPLIT, which is now obsolete
+ */
+#define DDSVCAPS_RESERVED4              0x00000008l
+
+/*
+ * The stereo view is accomplished with switching technology
+ */
+
+#define DDSVCAPS_STEREOSEQUENTIAL       0x00000010L
+
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE CAPABILITIES
+ *
+ ****************************************************************************/
+
+/*
+ * Index is 4 bits.  There are sixteen color entries in the palette table.
+ */
+#define DDPCAPS_4BIT                    0x00000001l
+
+/*
+ * Index is onto a 8 bit color index.  This field is only valid with the
+ * DDPCAPS_1BIT, DDPCAPS_2BIT or DDPCAPS_4BIT capability and the target
+ * surface is in 8bpp. Each color entry is one byte long and is an index
+ * into destination surface's 8bpp palette.
+ */
+#define DDPCAPS_8BITENTRIES             0x00000002l
+
+/*
+ * Index is 8 bits.  There are 256 color entries in the palette table.
+ */
+#define DDPCAPS_8BIT                    0x00000004l
+
+/*
+ * Indicates that this DIRECTDRAWPALETTE should use the palette color array
+ * passed into the lpDDColorArray parameter to initialize the DIRECTDRAWPALETTE
+ * object.
+ * This flag is obsolete. DirectDraw always initializes the color array from
+ * the lpDDColorArray parameter. The definition remains for source-level
+ * compatibility.
+ */
+#define DDPCAPS_INITIALIZE              0x00000000l
+
+/*
+ * This palette is the one attached to the primary surface.  Changing this
+ * table has immediate effect on the display unless DDPSETPAL_VSYNC is specified
+ * and supported.
+ */
+#define DDPCAPS_PRIMARYSURFACE          0x00000010l
+
+/*
+ * This palette is the one attached to the primary surface left.  Changing
+ * this table has immediate effect on the display for the left eye unless
+ * DDPSETPAL_VSYNC is specified and supported.
+ */
+#define DDPCAPS_PRIMARYSURFACELEFT      0x00000020l
+
+/*
+ * This palette can have all 256 entries defined
+ */
+#define DDPCAPS_ALLOW256                0x00000040l
+
+/*
+ * This palette can have modifications to it synced with the monitors
+ * refresh rate.
+ */
+#define DDPCAPS_VSYNC                   0x00000080l
+
+/*
+ * Index is 1 bit.  There are two color entries in the palette table.
+ */
+#define DDPCAPS_1BIT                    0x00000100l
+
+/*
+ * Index is 2 bit.  There are four color entries in the palette table.
+ */
+#define DDPCAPS_2BIT                    0x00000200l
+
+/*
+ * The peFlags member of PALETTEENTRY denotes an 8 bit alpha value
+ */
+#define DDPCAPS_ALPHA                   0x00000400l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE SETENTRY CONSTANTS
+ *
+ ****************************************************************************/
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE GETENTRY CONSTANTS
+ *
+ ****************************************************************************/
+
+/* 0 is the only legal value */
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE SETPRIVATEDATA CONSTANTS
+ *
+ ****************************************************************************/
+
+/*
+ * The passed pointer is an IUnknown ptr. The cbData argument to SetPrivateData
+ * must be set to sizeof(IUnknown*). DirectDraw will call AddRef through this
+ * pointer and Release when the private data is destroyed. This includes when
+ * the surface or palette is destroyed before such priovate data is destroyed.
+ */
+#define DDSPD_IUNKNOWNPOINTER           0x00000001L
+
+/*
+ * Private data is only valid for the current state of the object,
+ * as determined by the uniqueness value.
+ */
+#define DDSPD_VOLATILE                  0x00000002L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE SETPALETTE CONSTANTS
+ *
+ ****************************************************************************/
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW BITDEPTH CONSTANTS
+ *
+ * NOTE:  These are only used to indicate supported bit depths.   These
+ * are flags only, they are not to be used as an actual bit depth.   The
+ * absolute numbers 1, 2, 4, 8, 16, 24 and 32 are used to indicate actual
+ * bit depths in a surface or for changing the display mode.
+ *
+ ****************************************************************************/
+
+/*
+ * 1 bit per pixel.
+ */
+#define DDBD_1                  0x00004000l
+
+/*
+ * 2 bits per pixel.
+ */
+#define DDBD_2                  0x00002000l
+
+/*
+ * 4 bits per pixel.
+ */
+#define DDBD_4                  0x00001000l
+
+/*
+ * 8 bits per pixel.
+ */
+#define DDBD_8                  0x00000800l
+
+/*
+ * 16 bits per pixel.
+ */
+#define DDBD_16                 0x00000400l
+
+/*
+ * 24 bits per pixel.
+ */
+#define DDBD_24                 0X00000200l
+
+/*
+ * 32 bits per pixel.
+ */
+#define DDBD_32                 0x00000100l
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE SET/GET COLOR KEY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Set if the structure contains a color space.  Not set if the structure
+ * contains a single color key.
+ */
+#define DDCKEY_COLORSPACE       0x00000001l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a destination color key for blt operations.
+ */
+#define DDCKEY_DESTBLT          0x00000002l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a destination color key for overlay operations.
+ */
+#define DDCKEY_DESTOVERLAY      0x00000004l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a source color key for blt operations.
+ */
+#define DDCKEY_SRCBLT           0x00000008l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a source color key for overlay operations.
+ */
+#define DDCKEY_SRCOVERLAY       0x00000010l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW COLOR KEY CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Supports transparent blting using a color key to identify the replaceable
+ * bits of the destination surface for RGB colors.
+ */
+#define DDCKEYCAPS_DESTBLT                      0x00000001l
+
+/*
+ * Supports transparent blting using a color space to identify the replaceable
+ * bits of the destination surface for RGB colors.
+ */
+#define DDCKEYCAPS_DESTBLTCLRSPACE              0x00000002l
+
+/*
+ * Supports transparent blting using a color space to identify the replaceable
+ * bits of the destination surface for YUV colors.
+ */
+#define DDCKEYCAPS_DESTBLTCLRSPACEYUV           0x00000004l
+
+/*
+ * Supports transparent blting using a color key to identify the replaceable
+ * bits of the destination surface for YUV colors.
+ */
+#define DDCKEYCAPS_DESTBLTYUV                   0x00000008l
+
+/*
+ * Supports overlaying using colorkeying of the replaceable bits of the surface
+ * being overlayed for RGB colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAY                  0x00000010l
+
+/*
+ * Supports a color space as the color key for the destination for RGB colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYCLRSPACE          0x00000020l
+
+/*
+ * Supports a color space as the color key for the destination for YUV colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV       0x00000040l
+
+/*
+ * Supports only one active destination color key value for visible overlay
+ * surfaces.
+ */
+#define DDCKEYCAPS_DESTOVERLAYONEACTIVE         0x00000080l
+
+/*
+ * Supports overlaying using colorkeying of the replaceable bits of the
+ * surface being overlayed for YUV colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYYUV               0x00000100l
+
+/*
+ * Supports transparent blting using the color key for the source with
+ * this surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCBLT                       0x00000200l
+
+/*
+ * Supports transparent blting using a color space for the source with
+ * this surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCBLTCLRSPACE               0x00000400l
+
+/*
+ * Supports transparent blting using a color space for the source with
+ * this surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCBLTCLRSPACEYUV            0x00000800l
+
+/*
+ * Supports transparent blting using the color key for the source with
+ * this surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCBLTYUV                    0x00001000l
+
+/*
+ * Supports overlays using the color key for the source with this
+ * overlay surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAY                   0x00002000l
+
+/*
+ * Supports overlays using a color space as the source color key for
+ * the overlay surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYCLRSPACE           0x00004000l
+
+/*
+ * Supports overlays using a color space as the source color key for
+ * the overlay surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV        0x00008000l
+
+/*
+ * Supports only one active source color key value for visible
+ * overlay surfaces.
+ */
+#define DDCKEYCAPS_SRCOVERLAYONEACTIVE          0x00010000l
+
+/*
+ * Supports overlays using the color key for the source with this
+ * overlay surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYYUV                0x00020000l
+
+/*
+ * there are no bandwidth trade-offs for using colorkey with an overlay
+ */
+#define DDCKEYCAPS_NOCOSTOVERLAY                0x00040000l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW PIXELFORMAT FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * The surface has alpha channel information in the pixel format.
+ */
+#define DDPF_ALPHAPIXELS                        0x00000001l
+
+/*
+ * The pixel format contains alpha only information
+ */
+#define DDPF_ALPHA                              0x00000002l
+
+/*
+ * The FourCC code is valid.
+ */
+#define DDPF_FOURCC                             0x00000004l
+
+/*
+ * The surface is 4-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED4                    0x00000008l
+
+/*
+ * The surface is indexed into a palette which stores indices
+ * into the destination surface's 8-bit palette.
+ */
+#define DDPF_PALETTEINDEXEDTO8                  0x00000010l
+
+/*
+ * The surface is 8-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED8                    0x00000020l
+
+/*
+ * The RGB data in the pixel format structure is valid.
+ */
+#define DDPF_RGB                                0x00000040l
+
+/*
+ * The surface will accept pixel data in the format specified
+ * and compress it during the write.
+ */
+#define DDPF_COMPRESSED                         0x00000080l
+
+/*
+ * The surface will accept RGB data and translate it during
+ * the write to YUV data.  The format of the data to be written
+ * will be contained in the pixel format structure.  The DDPF_RGB
+ * flag will be set.
+ */
+#define DDPF_RGBTOYUV                           0x00000100l
+
+/*
+ * pixel format is YUV - YUV data in pixel format struct is valid
+ */
+#define DDPF_YUV                                0x00000200l
+
+/*
+ * pixel format is a z buffer only surface
+ */
+#define DDPF_ZBUFFER                            0x00000400l
+
+/*
+ * The surface is 1-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED1                    0x00000800l
+
+/*
+ * The surface is 2-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED2                    0x00001000l
+
+/*
+ * The surface contains Z information in the pixels
+ */
+#define DDPF_ZPIXELS                            0x00002000l
+
+/*
+ * The surface contains stencil information along with Z
+ */
+#define DDPF_STENCILBUFFER                      0x00004000l
+
+/*
+ * Premultiplied alpha format -- the color components have been
+ * premultiplied by the alpha component.
+ */
+#define DDPF_ALPHAPREMULT                       0x00008000l
+
+
+/*
+ * Luminance data in the pixel format is valid.
+ * Use this flag for luminance-only or luminance+alpha surfaces,
+ * the bit depth is then ddpf.dwLuminanceBitCount.
+ */
+#define DDPF_LUMINANCE                          0x00020000l
+
+/*
+ * Luminance data in the pixel format is valid.
+ * Use this flag when hanging luminance off bumpmap surfaces,
+ * the bit mask for the luminance portion of the pixel is then
+ * ddpf.dwBumpLuminanceBitMask
+ */
+#define DDPF_BUMPLUMINANCE                      0x00040000l
+
+/*
+ * Bump map dUdV data in the pixel format is valid.
+ */
+#define DDPF_BUMPDUDV                           0x00080000l
+
+
+/*===========================================================================
+ *
+ *
+ * DIRECTDRAW CALLBACK FLAGS
+ *
+ *
+ *==========================================================================*/
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMSURFACES FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate all of the surfaces that meet the search criterion.
+ */
+#define DDENUMSURFACES_ALL                      0x00000001l
+
+/*
+ * A search hit is a surface that matches the surface description.
+ */
+#define DDENUMSURFACES_MATCH                    0x00000002l
+
+/*
+ * A search hit is a surface that does not match the surface description.
+ */
+#define DDENUMSURFACES_NOMATCH                  0x00000004l
+
+/*
+ * Enumerate the first surface that can be created which meets the search criterion.
+ */
+#define DDENUMSURFACES_CANBECREATED             0x00000008l
+
+/*
+ * Enumerate the surfaces that already exist that meet the search criterion.
+ */
+#define DDENUMSURFACES_DOESEXIST                0x00000010l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW SETDISPLAYMODE FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * The desired mode is a standard VGA mode
+ */
+#define DDSDM_STANDARDVGAMODE                   0x00000001l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMDISPLAYMODES FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate Modes with different refresh rates.  EnumDisplayModes guarantees
+ * that a particular mode will be enumerated only once.  This flag specifies whether
+ * the refresh rate is taken into account when determining if a mode is unique.
+ */
+#define DDEDM_REFRESHRATES                      0x00000001l
+
+/*
+ * Enumerate VGA modes. Specify this flag if you wish to enumerate supported VGA
+ * modes such as mode 0x13 in addition to the usual ModeX modes (which are always
+ * enumerated if the application has previously called SetCooperativeLevel with the
+ * DDSCL_ALLOWMODEX flag set).
+ */
+#define DDEDM_STANDARDVGAMODES                  0x00000002L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW SETCOOPERATIVELEVEL FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Exclusive mode owner will be responsible for the entire primary surface.
+ * GDI can be ignored. used with DD
+ */
+#define DDSCL_FULLSCREEN                        0x00000001l
+
+/*
+ * allow CTRL_ALT_DEL to work while in fullscreen exclusive mode
+ */
+#define DDSCL_ALLOWREBOOT                       0x00000002l
+
+/*
+ * prevents DDRAW from modifying the application window.
+ * prevents DDRAW from minimize/restore the application window on activation.
+ */
+#define DDSCL_NOWINDOWCHANGES                   0x00000004l
+
+/*
+ * app wants to work as a regular Windows application
+ */
+#define DDSCL_NORMAL                            0x00000008l
+
+/*
+ * app wants exclusive access
+ */
+#define DDSCL_EXCLUSIVE                         0x00000010l
+
+
+/*
+ * app can deal with non-windows display modes
+ */
+#define DDSCL_ALLOWMODEX                        0x00000040l
+
+/*
+ * this window will receive the focus messages
+ */
+#define DDSCL_SETFOCUSWINDOW                    0x00000080l
+
+/*
+ * this window is associated with the DDRAW object and will
+ * cover the screen in fullscreen mode
+ */
+#define DDSCL_SETDEVICEWINDOW                   0x00000100l
+
+/*
+ * app wants DDRAW to create a window to be associated with the
+ * DDRAW object
+ */
+#define DDSCL_CREATEDEVICEWINDOW                0x00000200l
+
+/*
+ * App explicitly asks DDRAW/D3D to be multithread safe. This makes D3D
+ * take the global crtisec more frequently.
+ */
+#define DDSCL_MULTITHREADED                     0x00000400l
+
+/*
+ * App specifies that it would like to keep the FPU set up for optimal Direct3D
+ * performance (single precision and exceptions disabled) so Direct3D
+ * does not need to explicitly set the FPU each time. This is assumed by
+ * default in DirectX 7. See also DDSCL_FPUPRESERVE
+ */
+#define DDSCL_FPUSETUP                          0x00000800l
+
+/*
+ * App specifies that it needs either double precision FPU or FPU exceptions
+ * enabled. This makes Direct3D explicitly set the FPU state eah time it is
+ * called. Setting the flag will reduce Direct3D performance. The flag is
+ * assumed by default in DirectX 6 and earlier. See also DDSCL_FPUSETUP
+ */
+#define DDSCL_FPUPRESERVE                          0x00001000l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW BLT FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the destination surface as the alpha channel for this blt.
+ */
+#define DDBLT_ALPHADEST                         0x00000001l
+
+/*
+ * Use the dwConstAlphaDest field in the DDBLTFX structure as the alpha channel
+ * for the destination surface for this blt.
+ */
+#define DDBLT_ALPHADESTCONSTOVERRIDE            0x00000002l
+
+/*
+ * The NEG suffix indicates that the destination surface becomes more
+ * transparent as the alpha value increases. (0 is opaque)
+ */
+#define DDBLT_ALPHADESTNEG                      0x00000004l
+
+/*
+ * Use the lpDDSAlphaDest field in the DDBLTFX structure as the alpha
+ * channel for the destination for this blt.
+ */
+#define DDBLT_ALPHADESTSURFACEOVERRIDE          0x00000008l
+
+/*
+ * Use the dwAlphaEdgeBlend field in the DDBLTFX structure as the alpha channel
+ * for the edges of the image that border the color key colors.
+ */
+#define DDBLT_ALPHAEDGEBLEND                    0x00000010l
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the source surface as the alpha channel for this blt.
+ */
+#define DDBLT_ALPHASRC                          0x00000020l
+
+/*
+ * Use the dwConstAlphaSrc field in the DDBLTFX structure as the alpha channel
+ * for the source for this blt.
+ */
+#define DDBLT_ALPHASRCCONSTOVERRIDE             0x00000040l
+
+/*
+ * The NEG suffix indicates that the source surface becomes more transparent
+ * as the alpha value increases. (0 is opaque)
+ */
+#define DDBLT_ALPHASRCNEG                       0x00000080l
+
+/*
+ * Use the lpDDSAlphaSrc field in the DDBLTFX structure as the alpha channel
+ * for the source for this blt.
+ */
+#define DDBLT_ALPHASRCSURFACEOVERRIDE           0x00000100l
+
+/*
+ * Do this blt asynchronously through the FIFO in the order received.  If
+ * there is no room in the hardware FIFO fail the call.
+ */
+#define DDBLT_ASYNC                             0x00000200l
+
+/*
+ * Uses the dwFillColor field in the DDBLTFX structure as the RGB color
+ * to fill the destination rectangle on the destination surface with.
+ */
+#define DDBLT_COLORFILL                         0x00000400l
+
+/*
+ * Uses the dwDDFX field in the DDBLTFX structure to specify the effects
+ * to use for the blt.
+ */
+#define DDBLT_DDFX                              0x00000800l
+
+/*
+ * Uses the dwDDROPS field in the DDBLTFX structure to specify the ROPS
+ * that are not part of the Win32 API.
+ */
+#define DDBLT_DDROPS                            0x00001000l
+
+/*
+ * Use the color key associated with the destination surface.
+ */
+#define DDBLT_KEYDEST                           0x00002000l
+
+/*
+ * Use the dckDestColorkey field in the DDBLTFX structure as the color key
+ * for the destination surface.
+ */
+#define DDBLT_KEYDESTOVERRIDE                   0x00004000l
+
+/*
+ * Use the color key associated with the source surface.
+ */
+#define DDBLT_KEYSRC                            0x00008000l
+
+/*
+ * Use the dckSrcColorkey field in the DDBLTFX structure as the color key
+ * for the source surface.
+ */
+#define DDBLT_KEYSRCOVERRIDE                    0x00010000l
+
+/*
+ * Use the dwROP field in the DDBLTFX structure for the raster operation
+ * for this blt.  These ROPs are the same as the ones defined in the Win32 API.
+ */
+#define DDBLT_ROP                               0x00020000l
+
+/*
+ * Use the dwRotationAngle field in the DDBLTFX structure as the angle
+ * (specified in 1/100th of a degree) to rotate the surface.
+ */
+#define DDBLT_ROTATIONANGLE                     0x00040000l
+
+/*
+ * Z-buffered blt using the z-buffers attached to the source and destination
+ * surfaces and the dwZBufferOpCode field in the DDBLTFX structure as the
+ * z-buffer opcode.
+ */
+#define DDBLT_ZBUFFER                           0x00080000l
+
+/*
+ * Z-buffered blt using the dwConstDest Zfield and the dwZBufferOpCode field
+ * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively
+ * for the destination.
+ */
+#define DDBLT_ZBUFFERDESTCONSTOVERRIDE          0x00100000l
+
+/*
+ * Z-buffered blt using the lpDDSDestZBuffer field and the dwZBufferOpCode
+ * field in the DDBLTFX structure as the z-buffer and z-buffer opcode
+ * respectively for the destination.
+ */
+#define DDBLT_ZBUFFERDESTOVERRIDE               0x00200000l
+
+/*
+ * Z-buffered blt using the dwConstSrcZ field and the dwZBufferOpCode field
+ * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively
+ * for the source.
+ */
+#define DDBLT_ZBUFFERSRCCONSTOVERRIDE           0x00400000l
+
+/*
+ * Z-buffered blt using the lpDDSSrcZBuffer field and the dwZBufferOpCode
+ * field in the DDBLTFX structure as the z-buffer and z-buffer opcode
+ * respectively for the source.
+ */
+#define DDBLT_ZBUFFERSRCOVERRIDE                0x00800000l
+
+/*
+ * wait until the device is ready to handle the blt
+ * this will cause blt to not return DDERR_WASSTILLDRAWING
+ */
+#define DDBLT_WAIT                              0x01000000l
+
+/*
+ * Uses the dwFillDepth field in the DDBLTFX structure as the depth value
+ * to fill the destination rectangle on the destination Z-buffer surface
+ * with.
+ */
+#define DDBLT_DEPTHFILL                         0x02000000l
+
+
+/*
+ * Return immediately (with DDERR_WASSTILLDRAWING) if the device is not
+ * ready to schedule the blt at the time Blt() is called.
+ */
+#define DDBLT_DONOTWAIT                         0x08000000l
+
+/*
+ * These flags indicate a presentation blt (i.e. a blt
+ * that moves surface contents from an offscreen back buffer to the primary
+ * surface). The driver is not allowed to "queue"  more than three such blts.
+ * The "end" of the presentation blt is indicated, since the
+ * blt may be clipped, in which case the runtime will call the driver with 
+ * several blts. All blts (even if not clipped) are tagged with DDBLT_PRESENTATION
+ * and the last (even if not clipped) additionally with DDBLT_LAST_PRESENTATION.
+ * Thus the true rule is that the driver must not schedule a DDBLT_PRESENTATION
+ * blt if there are 3 or more DDBLT_PRESENTLAST blts in the hardware pipe.
+ * If there are such blts in the pipe, the driver should return DDERR_WASSTILLDRAWING
+ * until the oldest queued DDBLT_LAST_PRESENTATION blts has been retired (i.e. the
+ * pixels have been actually written to the primary surface). Once the oldest blt
+ * has been retired, the driver is free to schedule the current blt.
+ * The goal is to provide a mechanism whereby the device's hardware queue never
+ * gets more than 3 frames ahead of the frames being generated by the application.
+ * When excessive queueing occurs, applications become unusable because the application
+ * visibly lags user input, and such problems make windowed interactive applications impossible.
+ * Some drivers may not have sufficient knowledge of their hardware's FIFO to know
+ * when a certain blt has been retired. Such drivers should code cautiously, and 
+ * simply not allow any frames to be queued at all. DDBLT_LAST_PRESENTATION should cause
+ * such drivers to return DDERR_WASSTILLDRAWING until the accelerator is completely
+ * finished- exactly as if the application had called Lock on the source surface
+ * before calling Blt. 
+ * In other words, the driver is allowed and encouraged to 
+ * generate as much latency as it can, but never more than 3 frames worth.
+ * Implementation detail: Drivers should count blts against the SOURCE surface, not
+ * against the primary surface. This enables multiple parallel windowed application
+ * to function more optimally.
+ * This flag is passed only to DX8 or higher drivers.
+ *
+ * APPLICATIONS DO NOT SET THESE FLAGS. THEY ARE SET BY THE DIRECTDRAW RUNTIME.
+ * 
+ */
+#define DDBLT_PRESENTATION                      0x10000000l
+#define DDBLT_LAST_PRESENTATION                 0x20000000l
+
+/*
+ * If DDBLT_EXTENDED_FLAGS is set, then the driver should re-interpret
+ * other flags according to the definitions that follow.
+ * For example, bit 0 (0x00000001L) means DDBLT_ALPHADEST, unless
+ * DDBLT_EXTENDED_FLAGS is also set, in which case bit 0 means
+ * DDBLT_EXTENDED_LINEAR_CONTENT.
+ * Only DirectX9 and higher drivers will be given extended blt flags.
+ * Only flags explicitly mentioned here should be re-interpreted.
+ * All other flags retain their original meanings.
+ *
+ * List of re-interpreted flags:
+ *
+ * Bit Hex value   New meaning                                  old meaning
+ * ---------------------------------------------------------------
+ *  2  0x00000004  DDBLT_EXTENDED_LINEAR_CONTENT                DDBLT_ALPHADESTNEG
+ *  4  0x00000010  DDBLT_EXTENDED_PRESENTATION_STRETCHFACTOR    DDBLT_ALPHAEDGEBLEND
+ *
+ *
+ * NOTE: APPLICATIONS SHOULD NOT SET THIS FLAG. THIS FLAG IS INTENDED
+ * FOR USE BY THE DIRECT3D RUNTIME.
+ */
+#define DDBLT_EXTENDED_FLAGS                    0x40000000l
+
+/*
+ * EXTENDED FLAG. SEE DEFINITION OF DDBLT_EXTENDED_FLAGS.
+ * This flag indidcates that the source surface contains content in a
+ * linear color space. The driver may perform gamma correction to the
+ * desktop color space (i.e. sRGB, gamma 2.2) as part of this blt.
+ * If the device can perform such a conversion as part of the copy,
+ * the driver should also set D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION
+ *
+ * NOTE: APPLICATIONS SHOULD NOT SET THIS FLAG. THIS FLAG IS INTENDED
+ * FOR USE BY THE DIRECT3D RUNTIME. Use IDirect3DSwapChain9::Present
+ * and specify D3DPRESENT_LINEAR_CONTENT in order to use this functionality.
+ */ 
+#define DDBLT_EXTENDED_LINEAR_CONTENT           0x00000004l
+
+
+/****************************************************************************
+ *
+ * BLTFAST FLAGS
+ *
+ ****************************************************************************/
+
+#define DDBLTFAST_NOCOLORKEY                    0x00000000
+#define DDBLTFAST_SRCCOLORKEY                   0x00000001
+#define DDBLTFAST_DESTCOLORKEY                  0x00000002
+#define DDBLTFAST_WAIT                          0x00000010
+#define DDBLTFAST_DONOTWAIT                     0x00000020
+
+/****************************************************************************
+ *
+ * FLIP FLAGS
+ *
+ ****************************************************************************/
+
+#define DDFLIP_WAIT                          0x00000001L
+
+/*
+ * Indicates that the target surface contains the even field of video data.
+ * This flag is only valid with an overlay surface.
+ */
+#define DDFLIP_EVEN                          0x00000002L
+
+/*
+ * Indicates that the target surface contains the odd field of video data.
+ * This flag is only valid with an overlay surface.
+ */
+#define DDFLIP_ODD                           0x00000004L
+
+/*
+ * Causes DirectDraw to perform the physical flip immediately and return
+ * to the application. Typically, what was the front buffer but is now the back
+ * buffer will still be visible (depending on timing) until the next vertical
+ * retrace. Subsequent operations involving the two flipped surfaces will
+ * not check to see if the physical flip has finished (i.e. will not return
+ * DDERR_WASSTILLDRAWING for that reason (but may for other reasons)).
+ * This allows an application to perform Flips at a higher frequency than the
+ * monitor refresh rate, but may introduce visible artifacts.
+ * Only effective if DDCAPS2_FLIPNOVSYNC is set. If that bit is not set,
+ * DDFLIP_NOVSYNC has no effect.
+ */
+#define DDFLIP_NOVSYNC                       0x00000008L
+
+
+/*
+ * Flip Interval Flags. These flags indicate how many vertical retraces to wait between
+ * each flip. The default is one. DirectDraw will return DDERR_WASSTILLDRAWING for each
+ * surface involved in the flip until the specified number of vertical retraces has
+ * ocurred. Only effective if DDCAPS2_FLIPINTERVAL is set. If that bit is not set,
+ * DDFLIP_INTERVALn has no effect.
+ */
+
+/*
+ * DirectDraw will flip on every other vertical sync
+ */
+#define DDFLIP_INTERVAL2                     0x02000000L
+
+
+/*
+ * DirectDraw will flip on every third vertical sync
+ */
+#define DDFLIP_INTERVAL3                     0x03000000L
+
+
+/*
+ * DirectDraw will flip on every fourth vertical sync
+ */
+#define DDFLIP_INTERVAL4                     0x04000000L
+
+/*
+ * DirectDraw will flip and display a main stereo surface
+ */
+#define DDFLIP_STEREO                        0x00000010L
+
+/*
+ * On IDirectDrawSurface7 and higher interfaces, the default is DDFLIP_WAIT. If you wish
+ * to override the default and use time when the accelerator is busy (as denoted by
+ * the DDERR_WASSTILLDRAWING return code) then use DDFLIP_DONOTWAIT.
+ */
+#define DDFLIP_DONOTWAIT                     0x00000020L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW SURFACE OVERLAY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the destination surface as the alpha channel for the
+ * destination overlay.
+ */
+#define DDOVER_ALPHADEST                        0x00000001l
+
+/*
+ * Use the dwConstAlphaDest field in the DDOVERLAYFX structure as the
+ * destination alpha channel for this overlay.
+ */
+#define DDOVER_ALPHADESTCONSTOVERRIDE           0x00000002l
+
+/*
+ * The NEG suffix indicates that the destination surface becomes more
+ * transparent as the alpha value increases.
+ */
+#define DDOVER_ALPHADESTNEG                     0x00000004l
+
+/*
+ * Use the lpDDSAlphaDest field in the DDOVERLAYFX structure as the alpha
+ * channel destination for this overlay.
+ */
+#define DDOVER_ALPHADESTSURFACEOVERRIDE         0x00000008l
+
+/*
+ * Use the dwAlphaEdgeBlend field in the DDOVERLAYFX structure as the alpha
+ * channel for the edges of the image that border the color key colors.
+ */
+#define DDOVER_ALPHAEDGEBLEND                   0x00000010l
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the source surface as the source alpha channel for this overlay.
+ */
+#define DDOVER_ALPHASRC                         0x00000020l
+
+/*
+ * Use the dwConstAlphaSrc field in the DDOVERLAYFX structure as the source
+ * alpha channel for this overlay.
+ */
+#define DDOVER_ALPHASRCCONSTOVERRIDE            0x00000040l
+
+/*
+ * The NEG suffix indicates that the source surface becomes more transparent
+ * as the alpha value increases.
+ */
+#define DDOVER_ALPHASRCNEG                      0x00000080l
+
+/*
+ * Use the lpDDSAlphaSrc field in the DDOVERLAYFX structure as the alpha channel
+ * source for this overlay.
+ */
+#define DDOVER_ALPHASRCSURFACEOVERRIDE          0x00000100l
+
+/*
+ * Turn this overlay off.
+ */
+#define DDOVER_HIDE                             0x00000200l
+
+/*
+ * Use the color key associated with the destination surface.
+ */
+#define DDOVER_KEYDEST                          0x00000400l
+
+/*
+ * Use the dckDestColorkey field in the DDOVERLAYFX structure as the color key
+ * for the destination surface
+ */
+#define DDOVER_KEYDESTOVERRIDE                  0x00000800l
+
+/*
+ * Use the color key associated with the source surface.
+ */
+#define DDOVER_KEYSRC                           0x00001000l
+
+/*
+ * Use the dckSrcColorkey field in the DDOVERLAYFX structure as the color key
+ * for the source surface.
+ */
+#define DDOVER_KEYSRCOVERRIDE                   0x00002000l
+
+/*
+ * Turn this overlay on.
+ */
+#define DDOVER_SHOW                             0x00004000l
+
+/*
+ * Add a dirty rect to an emulated overlayed surface.
+ */
+#define DDOVER_ADDDIRTYRECT                     0x00008000l
+
+/*
+ * Redraw all dirty rects on an emulated overlayed surface.
+ */
+#define DDOVER_REFRESHDIRTYRECTS                0x00010000l
+
+/*
+ * Redraw the entire surface on an emulated overlayed surface.
+ */
+#define DDOVER_REFRESHALL                      0x00020000l
+
+
+/*
+ * Use the overlay FX flags to define special overlay FX
+ */
+#define DDOVER_DDFX                             0x00080000l
+
+/*
+ * Autoflip the overlay when ever the video port autoflips
+ */
+#define DDOVER_AUTOFLIP                         0x00100000l
+
+/*
+ * Display each field of video port data individually without
+ * causing any jittery artifacts
+ */
+#define DDOVER_BOB                              0x00200000l
+
+/*
+ * Indicates that bob/weave decisions should not be overridden by other
+ * interfaces.
+ */
+#define DDOVER_OVERRIDEBOBWEAVE                 0x00400000l
+
+/*
+ * Indicates that the surface memory is composed of interleaved fields.
+ */
+#define DDOVER_INTERLEAVED                      0x00800000l
+
+/*
+ * Indicates that bob will be performed using hardware rather than
+ * software or emulated.
+ */
+#define DDOVER_BOBHARDWARE                      0x01000000l
+
+/*
+ * Indicates that overlay FX structure contains valid ARGB scaling factors.
+ */
+#define DDOVER_ARGBSCALEFACTORS                 0x02000000l
+
+/*
+ * Indicates that ARGB scaling factors can be degraded to fit driver capabilities.
+ */
+#define DDOVER_DEGRADEARGBSCALING               0x04000000l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE LOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * The default.  Set to indicate that Lock should return a valid memory pointer
+ * to the top of the specified rectangle.  If no rectangle is specified then a
+ * pointer to the top of the surface is returned.
+ */
+#define DDLOCK_SURFACEMEMORYPTR                 0x00000000L     // default
+
+/*
+ * Set to indicate that Lock should wait until it can obtain a valid memory
+ * pointer before returning.  If this bit is set, Lock will never return
+ * DDERR_WASSTILLDRAWING.
+ */
+#define DDLOCK_WAIT                             0x00000001L
+
+/*
+ * Set if an event handle is being passed to Lock.  Lock will trigger the event
+ * when it can return the surface memory pointer requested.
+ */
+#define DDLOCK_EVENT                            0x00000002L
+
+/*
+ * Indicates that the surface being locked will only be read from.
+ */
+#define DDLOCK_READONLY                         0x00000010L
+
+/*
+ * Indicates that the surface being locked will only be written to
+ */
+#define DDLOCK_WRITEONLY                        0x00000020L
+
+
+/*
+ * Indicates that a system wide lock should not be taken when this surface
+ * is locked. This has several advantages (cursor responsiveness, ability
+ * to call more Windows functions, easier debugging) when locking video
+ * memory surfaces. However, an application specifying this flag must
+ * comply with a number of conditions documented in the help file.
+ * Furthermore, this flag cannot be specified when locking the primary.
+ */
+#define DDLOCK_NOSYSLOCK                        0x00000800L
+
+/*
+ * Used only with Direct3D Vertex Buffer Locks. Indicates that no vertices
+ * that were referred to in Draw*PrimtiveVB calls since the start of the
+ * frame (or the last lock without this flag) will be modified during the
+ * lock. This can be useful when one is only appending data to the vertex
+ * buffer
+ */
+#define DDLOCK_NOOVERWRITE                      0x00001000L
+
+/*
+ * Indicates that no assumptions will be made about the contents of the
+ * surface or vertex buffer during this lock.
+ * This enables two things:
+ * -    Direct3D or the driver may provide an alternative memory
+ *      area as the vertex buffer. This is useful when one plans to clear the
+ *      contents of the vertex buffer and fill in new data.
+ * -    Drivers sometimes store surface data in a re-ordered format.
+ *      When the application locks the surface, the driver is forced to un-re-order
+ *      the surface data before allowing the application to see the surface contents.
+ *      This flag is a hint to the driver that it can skip the un-re-ordering process
+ *      since the application plans to overwrite every single pixel in the surface
+ *      or locked rectangle (and so erase any un-re-ordered pixels anyway).
+ *      Applications should always set this flag when they intend to overwrite the entire
+ *      surface or locked rectangle.
+ */
+#define DDLOCK_DISCARDCONTENTS                  0x00002000L
+ /*
+  * DDLOCK_OKTOSWAP is an older, less informative name for DDLOCK_DISCARDCONTENTS
+  */
+#define DDLOCK_OKTOSWAP                         0x00002000L
+
+/*
+ * On IDirectDrawSurface7 and higher interfaces, the default is DDLOCK_WAIT. If you wish
+ * to override the default and use time when the accelerator is busy (as denoted by
+ * the DDERR_WASSTILLDRAWING return code) then use DDLOCK_DONOTWAIT.
+ */
+#define DDLOCK_DONOTWAIT                        0x00004000L
+
+/*
+ * This indicates volume texture lock with front and back specified.
+ */
+#define DDLOCK_HASVOLUMETEXTUREBOXRECT          0x00008000L
+
+/*
+ * This indicates that the driver should not update dirty rect information for this lock.
+ */
+#define DDLOCK_NODIRTYUPDATE                    0x00010000L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE PAGELOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * No flags defined at present
+ */
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE PAGEUNLOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * No flags defined at present
+ */
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE BLT FX FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * If stretching, use arithmetic stretching along the Y axis for this blt.
+ */
+#define DDBLTFX_ARITHSTRETCHY                   0x00000001l
+
+/*
+ * Do this blt mirroring the surface left to right.  Spin the
+ * surface around its y-axis.
+ */
+#define DDBLTFX_MIRRORLEFTRIGHT                 0x00000002l
+
+/*
+ * Do this blt mirroring the surface up and down.  Spin the surface
+ * around its x-axis.
+ */
+#define DDBLTFX_MIRRORUPDOWN                    0x00000004l
+
+/*
+ * Schedule this blt to avoid tearing.
+ */
+#define DDBLTFX_NOTEARING                       0x00000008l
+
+/*
+ * Do this blt rotating the surface one hundred and eighty degrees.
+ */
+#define DDBLTFX_ROTATE180                       0x00000010l
+
+/*
+ * Do this blt rotating the surface two hundred and seventy degrees.
+ */
+#define DDBLTFX_ROTATE270                       0x00000020l
+
+/*
+ * Do this blt rotating the surface ninety degrees.
+ */
+#define DDBLTFX_ROTATE90                        0x00000040l
+
+/*
+ * Do this z blt using dwZBufferLow and dwZBufferHigh as  range values
+ * specified to limit the bits copied from the source surface.
+ */
+#define DDBLTFX_ZBUFFERRANGE                    0x00000080l
+
+/*
+ * Do this z blt adding the dwZBufferBaseDest to each of the sources z values
+ * before comparing it with the desting z values.
+ */
+#define DDBLTFX_ZBUFFERBASEDEST                 0x00000100l
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE OVERLAY FX FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * If stretching, use arithmetic stretching along the Y axis for this overlay.
+ */
+#define DDOVERFX_ARITHSTRETCHY                  0x00000001l
+
+/*
+ * Mirror the overlay across the vertical axis
+ */
+#define DDOVERFX_MIRRORLEFTRIGHT                0x00000002l
+
+/*
+ * Mirror the overlay across the horizontal axis
+ */
+#define DDOVERFX_MIRRORUPDOWN                   0x00000004l
+
+/*
+ * Deinterlace the overlay, if possible
+ */
+#define DDOVERFX_DEINTERLACE                    0x00000008l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW WAITFORVERTICALBLANK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * return when the vertical blank interval begins
+ */
+#define DDWAITVB_BLOCKBEGIN                     0x00000001l
+
+/*
+ * set up an event to trigger when the vertical blank begins
+ */
+#define DDWAITVB_BLOCKBEGINEVENT                0x00000002l
+
+/*
+ * return when the vertical blank interval ends and display begins
+ */
+#define DDWAITVB_BLOCKEND                       0x00000004l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW GETFLIPSTATUS FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * is it OK to flip now?
+ */
+#define DDGFS_CANFLIP                   0x00000001l
+
+/*
+ * is the last flip finished?
+ */
+#define DDGFS_ISFLIPDONE                0x00000002l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW GETBLTSTATUS FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * is it OK to blt now?
+ */
+#define DDGBS_CANBLT                    0x00000001l
+
+/*
+ * is the blt to the surface finished?
+ */
+#define DDGBS_ISBLTDONE                 0x00000002l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMOVERLAYZORDER FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate overlays back to front.
+ */
+#define DDENUMOVERLAYZ_BACKTOFRONT      0x00000000l
+
+/*
+ * Enumerate overlays front to back
+ */
+#define DDENUMOVERLAYZ_FRONTTOBACK      0x00000001l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW UPDATEOVERLAYZORDER FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Send overlay to front
+ */
+#define DDOVERZ_SENDTOFRONT             0x00000000l
+
+/*
+ * Send overlay to back
+ */
+#define DDOVERZ_SENDTOBACK              0x00000001l
+
+/*
+ * Move Overlay forward
+ */
+#define DDOVERZ_MOVEFORWARD             0x00000002l
+
+/*
+ * Move Overlay backward
+ */
+#define DDOVERZ_MOVEBACKWARD            0x00000003l
+
+/*
+ * Move Overlay in front of relative surface
+ */
+#define DDOVERZ_INSERTINFRONTOF         0x00000004l
+
+/*
+ * Move Overlay in back of relative surface
+ */
+#define DDOVERZ_INSERTINBACKOF          0x00000005l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW SETGAMMARAMP FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Request calibrator to adjust the gamma ramp according to the physical
+ * properties of the display so that the result should appear identical
+ * on all systems.
+ */
+#define DDSGR_CALIBRATE                        0x00000001L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW STARTMODETEST FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Indicates that the mode being tested has passed
+ */
+#define DDSMT_ISTESTREQUIRED                   0x00000001L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW EVALUATEMODE FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Indicates that the mode being tested has passed
+ */
+#define DDEM_MODEPASSED                        0x00000001L
+
+/*
+ * Indicates that the mode being tested has failed
+ */
+#define DDEM_MODEFAILED                        0x00000002L
+
+
+/*===========================================================================
+ *
+ *
+ * DIRECTDRAW RETURN CODES
+ *
+ * The return values from DirectDraw Commands and Surface that return an HRESULT
+ * are codes from DirectDraw concerning the results of the action
+ * requested by DirectDraw.
+ *
+ *==========================================================================*/
+
+/*
+ * Status is OK
+ *
+ * Issued by: DirectDraw Commands and all callbacks
+ */
+#define DD_OK                                   S_OK
+#define DD_FALSE                                S_FALSE
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMCALLBACK RETURN VALUES
+ *
+ * EnumCallback returns are used to control the flow of the DIRECTDRAW and
+ * DIRECTDRAWSURFACE object enumerations.   They can only be returned by
+ * enumeration callback routines.
+ *
+ ****************************************************************************/
+
+/*
+ * stop the enumeration
+ */
+#define DDENUMRET_CANCEL                        0
+
+/*
+ * continue the enumeration
+ */
+#define DDENUMRET_OK                            1
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ERRORS
+ *
+ * Errors are represented by negative values and cannot be combined.
+ *
+ ****************************************************************************/
+
+/*
+ * This object is already initialized
+ */
+#define DDERR_ALREADYINITIALIZED                MAKE_DDHRESULT( 5 )
+
+/*
+ * This surface can not be attached to the requested surface.
+ */
+#define DDERR_CANNOTATTACHSURFACE               MAKE_DDHRESULT( 10 )
+
+/*
+ * This surface can not be detached from the requested surface.
+ */
+#define DDERR_CANNOTDETACHSURFACE               MAKE_DDHRESULT( 20 )
+
+/*
+ * Support is currently not available.
+ */
+#define DDERR_CURRENTLYNOTAVAIL                 MAKE_DDHRESULT( 40 )
+
+/*
+ * An exception was encountered while performing the requested operation
+ */
+#define DDERR_EXCEPTION                         MAKE_DDHRESULT( 55 )
+
+/*
+ * Generic failure.
+ */
+#define DDERR_GENERIC                           E_FAIL
+
+/*
+ * Height of rectangle provided is not a multiple of reqd alignment
+ */
+#define DDERR_HEIGHTALIGN                       MAKE_DDHRESULT( 90 )
+
+/*
+ * Unable to match primary surface creation request with existing
+ * primary surface.
+ */
+#define DDERR_INCOMPATIBLEPRIMARY               MAKE_DDHRESULT( 95 )
+
+/*
+ * One or more of the caps bits passed to the callback are incorrect.
+ */
+#define DDERR_INVALIDCAPS                       MAKE_DDHRESULT( 100 )
+
+/*
+ * DirectDraw does not support provided Cliplist.
+ */
+#define DDERR_INVALIDCLIPLIST                   MAKE_DDHRESULT( 110 )
+
+/*
+ * DirectDraw does not support the requested mode
+ */
+#define DDERR_INVALIDMODE                       MAKE_DDHRESULT( 120 )
+
+/*
+ * DirectDraw received a pointer that was an invalid DIRECTDRAW object.
+ */
+#define DDERR_INVALIDOBJECT                     MAKE_DDHRESULT( 130 )
+
+/*
+ * One or more of the parameters passed to the callback function are
+ * incorrect.
+ */
+#define DDERR_INVALIDPARAMS                     E_INVALIDARG
+
+/*
+ * pixel format was invalid as specified
+ */
+#define DDERR_INVALIDPIXELFORMAT                MAKE_DDHRESULT( 145 )
+
+/*
+ * Rectangle provided was invalid.
+ */
+#define DDERR_INVALIDRECT                       MAKE_DDHRESULT( 150 )
+
+/*
+ * Operation could not be carried out because one or more surfaces are locked
+ */
+#define DDERR_LOCKEDSURFACES                    MAKE_DDHRESULT( 160 )
+
+/*
+ * There is no 3D present.
+ */
+#define DDERR_NO3D                              MAKE_DDHRESULT( 170 )
+
+/*
+ * Operation could not be carried out because there is no alpha accleration
+ * hardware present or available.
+ */
+#define DDERR_NOALPHAHW                         MAKE_DDHRESULT( 180 )
+
+/*
+ * Operation could not be carried out because there is no stereo
+ * hardware present or available.
+ */
+#define DDERR_NOSTEREOHARDWARE          MAKE_DDHRESULT( 181 )
+
+/*
+ * Operation could not be carried out because there is no hardware
+ * present which supports stereo surfaces
+ */
+#define DDERR_NOSURFACELEFT                             MAKE_DDHRESULT( 182 )
+
+
+
+/*
+ * no clip list available
+ */
+#define DDERR_NOCLIPLIST                        MAKE_DDHRESULT( 205 )
+
+/*
+ * Operation could not be carried out because there is no color conversion
+ * hardware present or available.
+ */
+#define DDERR_NOCOLORCONVHW                     MAKE_DDHRESULT( 210 )
+
+/*
+ * Create function called without DirectDraw object method SetCooperativeLevel
+ * being called.
+ */
+#define DDERR_NOCOOPERATIVELEVELSET             MAKE_DDHRESULT( 212 )
+
+/*
+ * Surface doesn't currently have a color key
+ */
+#define DDERR_NOCOLORKEY                        MAKE_DDHRESULT( 215 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * of the dest color key.
+ */
+#define DDERR_NOCOLORKEYHW                      MAKE_DDHRESULT( 220 )
+
+/*
+ * No DirectDraw support possible with current display driver
+ */
+#define DDERR_NODIRECTDRAWSUPPORT               MAKE_DDHRESULT( 222 )
+
+/*
+ * Operation requires the application to have exclusive mode but the
+ * application does not have exclusive mode.
+ */
+#define DDERR_NOEXCLUSIVEMODE                   MAKE_DDHRESULT( 225 )
+
+/*
+ * Flipping visible surfaces is not supported.
+ */
+#define DDERR_NOFLIPHW                          MAKE_DDHRESULT( 230 )
+
+/*
+ * There is no GDI present.
+ */
+#define DDERR_NOGDI                             MAKE_DDHRESULT( 240 )
+
+/*
+ * Operation could not be carried out because there is no hardware present
+ * or available.
+ */
+#define DDERR_NOMIRRORHW                        MAKE_DDHRESULT( 250 )
+
+/*
+ * Requested item was not found
+ */
+#define DDERR_NOTFOUND                          MAKE_DDHRESULT( 255 )
+
+/*
+ * Operation could not be carried out because there is no overlay hardware
+ * present or available.
+ */
+#define DDERR_NOOVERLAYHW                       MAKE_DDHRESULT( 260 )
+
+/*
+ * Operation could not be carried out because the source and destination
+ * rectangles are on the same surface and overlap each other.
+ */
+#define DDERR_OVERLAPPINGRECTS                  MAKE_DDHRESULT( 270 )
+
+/*
+ * Operation could not be carried out because there is no appropriate raster
+ * op hardware present or available.
+ */
+#define DDERR_NORASTEROPHW                      MAKE_DDHRESULT( 280 )
+
+/*
+ * Operation could not be carried out because there is no rotation hardware
+ * present or available.
+ */
+#define DDERR_NOROTATIONHW                      MAKE_DDHRESULT( 290 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for stretching
+ */
+#define DDERR_NOSTRETCHHW                       MAKE_DDHRESULT( 310 )
+
+/*
+ * DirectDrawSurface is not in 4 bit color palette and the requested operation
+ * requires 4 bit color palette.
+ */
+#define DDERR_NOT4BITCOLOR                      MAKE_DDHRESULT( 316 )
+
+/*
+ * DirectDrawSurface is not in 4 bit color index palette and the requested
+ * operation requires 4 bit color index palette.
+ */
+#define DDERR_NOT4BITCOLORINDEX                 MAKE_DDHRESULT( 317 )
+
+/*
+ * DirectDraw Surface is not in 8 bit color mode and the requested operation
+ * requires 8 bit color.
+ */
+#define DDERR_NOT8BITCOLOR                      MAKE_DDHRESULT( 320 )
+
+/*
+ * Operation could not be carried out because there is no texture mapping
+ * hardware present or available.
+ */
+#define DDERR_NOTEXTUREHW                       MAKE_DDHRESULT( 330 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for vertical blank synchronized operations.
+ */
+#define DDERR_NOVSYNCHW                         MAKE_DDHRESULT( 335 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for zbuffer blting.
+ */
+#define DDERR_NOZBUFFERHW                       MAKE_DDHRESULT( 340 )
+
+/*
+ * Overlay surfaces could not be z layered based on their BltOrder because
+ * the hardware does not support z layering of overlays.
+ */
+#define DDERR_NOZOVERLAYHW                      MAKE_DDHRESULT( 350 )
+
+/*
+ * The hardware needed for the requested operation has already been
+ * allocated.
+ */
+#define DDERR_OUTOFCAPS                         MAKE_DDHRESULT( 360 )
+
+/*
+ * DirectDraw does not have enough memory to perform the operation.
+ */
+#define DDERR_OUTOFMEMORY                       E_OUTOFMEMORY
+
+/*
+ * DirectDraw does not have enough memory to perform the operation.
+ */
+#define DDERR_OUTOFVIDEOMEMORY                  MAKE_DDHRESULT( 380 )
+
+/*
+ * hardware does not support clipped overlays
+ */
+#define DDERR_OVERLAYCANTCLIP                   MAKE_DDHRESULT( 382 )
+
+/*
+ * Can only have ony color key active at one time for overlays
+ */
+#define DDERR_OVERLAYCOLORKEYONLYONEACTIVE      MAKE_DDHRESULT( 384 )
+
+/*
+ * Access to this palette is being refused because the palette is already
+ * locked by another thread.
+ */
+#define DDERR_PALETTEBUSY                       MAKE_DDHRESULT( 387 )
+
+/*
+ * No src color key specified for this operation.
+ */
+#define DDERR_COLORKEYNOTSET                    MAKE_DDHRESULT( 400 )
+
+/*
+ * This surface is already attached to the surface it is being attached to.
+ */
+#define DDERR_SURFACEALREADYATTACHED            MAKE_DDHRESULT( 410 )
+
+/*
+ * This surface is already a dependency of the surface it is being made a
+ * dependency of.
+ */
+#define DDERR_SURFACEALREADYDEPENDENT           MAKE_DDHRESULT( 420 )
+
+/*
+ * Access to this surface is being refused because the surface is already
+ * locked by another thread.
+ */
+#define DDERR_SURFACEBUSY                       MAKE_DDHRESULT( 430 )
+
+/*
+ * Access to this surface is being refused because no driver exists
+ * which can supply a pointer to the surface.
+ * This is most likely to happen when attempting to lock the primary
+ * surface when no DCI provider is present.
+ * Will also happen on attempts to lock an optimized surface.
+ */
+#define DDERR_CANTLOCKSURFACE                   MAKE_DDHRESULT( 435 )
+
+/*
+ * Access to Surface refused because Surface is obscured.
+ */
+#define DDERR_SURFACEISOBSCURED                 MAKE_DDHRESULT( 440 )
+
+/*
+ * Access to this surface is being refused because the surface is gone.
+ * The DIRECTDRAWSURFACE object representing this surface should
+ * have Restore called on it.
+ */
+#define DDERR_SURFACELOST                       MAKE_DDHRESULT( 450 )
+
+/*
+ * The requested surface is not attached.
+ */
+#define DDERR_SURFACENOTATTACHED                MAKE_DDHRESULT( 460 )
+
+/*
+ * Height requested by DirectDraw is too large.
+ */
+#define DDERR_TOOBIGHEIGHT                      MAKE_DDHRESULT( 470 )
+
+/*
+ * Size requested by DirectDraw is too large --  The individual height and
+ * width are OK.
+ */
+#define DDERR_TOOBIGSIZE                        MAKE_DDHRESULT( 480 )
+
+/*
+ * Width requested by DirectDraw is too large.
+ */
+#define DDERR_TOOBIGWIDTH                       MAKE_DDHRESULT( 490 )
+
+/*
+ * Action not supported.
+ */
+#define DDERR_UNSUPPORTED                       E_NOTIMPL
+
+/*
+ * Pixel format requested is unsupported by DirectDraw
+ */
+#define DDERR_UNSUPPORTEDFORMAT                 MAKE_DDHRESULT( 510 )
+
+/*
+ * Bitmask in the pixel format requested is unsupported by DirectDraw
+ */
+#define DDERR_UNSUPPORTEDMASK                   MAKE_DDHRESULT( 520 )
+
+/*
+ * The specified stream contains invalid data
+ */
+#define DDERR_INVALIDSTREAM                     MAKE_DDHRESULT( 521 )
+
+/*
+ * vertical blank is in progress
+ */
+#define DDERR_VERTICALBLANKINPROGRESS           MAKE_DDHRESULT( 537 )
+
+/*
+ * Informs DirectDraw that the previous Blt which is transfering information
+ * to or from this Surface is incomplete.
+ */
+#define DDERR_WASSTILLDRAWING                   MAKE_DDHRESULT( 540 )
+
+
+/*
+ * The specified surface type requires specification of the COMPLEX flag
+ */
+#define DDERR_DDSCAPSCOMPLEXREQUIRED            MAKE_DDHRESULT( 542 )
+
+
+/*
+ * Rectangle provided was not horizontally aligned on reqd. boundary
+ */
+#define DDERR_XALIGN                            MAKE_DDHRESULT( 560 )
+
+/*
+ * The GUID passed to DirectDrawCreate is not a valid DirectDraw driver
+ * identifier.
+ */
+#define DDERR_INVALIDDIRECTDRAWGUID             MAKE_DDHRESULT( 561 )
+
+/*
+ * A DirectDraw object representing this driver has already been created
+ * for this process.
+ */
+#define DDERR_DIRECTDRAWALREADYCREATED          MAKE_DDHRESULT( 562 )
+
+/*
+ * A hardware only DirectDraw object creation was attempted but the driver
+ * did not support any hardware.
+ */
+#define DDERR_NODIRECTDRAWHW                    MAKE_DDHRESULT( 563 )
+
+/*
+ * this process already has created a primary surface
+ */
+#define DDERR_PRIMARYSURFACEALREADYEXISTS       MAKE_DDHRESULT( 564 )
+
+/*
+ * software emulation not available.
+ */
+#define DDERR_NOEMULATION                       MAKE_DDHRESULT( 565 )
+
+/*
+ * region passed to Clipper::GetClipList is too small.
+ */
+#define DDERR_REGIONTOOSMALL                    MAKE_DDHRESULT( 566 )
+
+/*
+ * an attempt was made to set a clip list for a clipper objec that
+ * is already monitoring an hwnd.
+ */
+#define DDERR_CLIPPERISUSINGHWND                MAKE_DDHRESULT( 567 )
+
+/*
+ * No clipper object attached to surface object
+ */
+#define DDERR_NOCLIPPERATTACHED                 MAKE_DDHRESULT( 568 )
+
+/*
+ * Clipper notification requires an HWND or
+ * no HWND has previously been set as the CooperativeLevel HWND.
+ */
+#define DDERR_NOHWND                            MAKE_DDHRESULT( 569 )
+
+/*
+ * HWND used by DirectDraw CooperativeLevel has been subclassed,
+ * this prevents DirectDraw from restoring state.
+ */
+#define DDERR_HWNDSUBCLASSED                    MAKE_DDHRESULT( 570 )
+
+/*
+ * The CooperativeLevel HWND has already been set.
+ * It can not be reset while the process has surfaces or palettes created.
+ */
+#define DDERR_HWNDALREADYSET                    MAKE_DDHRESULT( 571 )
+
+/*
+ * No palette object attached to this surface.
+ */
+#define DDERR_NOPALETTEATTACHED                 MAKE_DDHRESULT( 572 )
+
+/*
+ * No hardware support for 16 or 256 color palettes.
+ */
+#define DDERR_NOPALETTEHW                       MAKE_DDHRESULT( 573 )
+
+/*
+ * If a clipper object is attached to the source surface passed into a
+ * BltFast call.
+ */
+#define DDERR_BLTFASTCANTCLIP                   MAKE_DDHRESULT( 574 )
+
+/*
+ * No blter.
+ */
+#define DDERR_NOBLTHW                           MAKE_DDHRESULT( 575 )
+
+/*
+ * No DirectDraw ROP hardware.
+ */
+#define DDERR_NODDROPSHW                        MAKE_DDHRESULT( 576 )
+
+/*
+ * returned when GetOverlayPosition is called on a hidden overlay
+ */
+#define DDERR_OVERLAYNOTVISIBLE                 MAKE_DDHRESULT( 577 )
+
+/*
+ * returned when GetOverlayPosition is called on a overlay that UpdateOverlay
+ * has never been called on to establish a destionation.
+ */
+#define DDERR_NOOVERLAYDEST                     MAKE_DDHRESULT( 578 )
+
+/*
+ * returned when the position of the overlay on the destionation is no longer
+ * legal for that destionation.
+ */
+#define DDERR_INVALIDPOSITION                   MAKE_DDHRESULT( 579 )
+
+/*
+ * returned when an overlay member is called for a non-overlay surface
+ */
+#define DDERR_NOTAOVERLAYSURFACE                MAKE_DDHRESULT( 580 )
+
+/*
+ * An attempt was made to set the cooperative level when it was already
+ * set to exclusive.
+ */
+#define DDERR_EXCLUSIVEMODEALREADYSET           MAKE_DDHRESULT( 581 )
+
+/*
+ * An attempt has been made to flip a surface that is not flippable.
+ */
+#define DDERR_NOTFLIPPABLE                      MAKE_DDHRESULT( 582 )
+
+/*
+ * Can't duplicate primary & 3D surfaces, or surfaces that are implicitly
+ * created.
+ */
+#define DDERR_CANTDUPLICATE                     MAKE_DDHRESULT( 583 )
+
+/*
+ * Surface was not locked.  An attempt to unlock a surface that was not
+ * locked at all, or by this process, has been attempted.
+ */
+#define DDERR_NOTLOCKED                         MAKE_DDHRESULT( 584 )
+
+/*
+ * Windows can not create any more DCs, or a DC was requested for a paltte-indexed
+ * surface when the surface had no palette AND the display mode was not palette-indexed
+ * (in this case DirectDraw cannot select a proper palette into the DC)
+ */
+#define DDERR_CANTCREATEDC                      MAKE_DDHRESULT( 585 )
+
+/*
+ * No DC was ever created for this surface.
+ */
+#define DDERR_NODC                              MAKE_DDHRESULT( 586 )
+
+/*
+ * This surface can not be restored because it was created in a different
+ * mode.
+ */
+#define DDERR_WRONGMODE                         MAKE_DDHRESULT( 587 )
+
+/*
+ * This surface can not be restored because it is an implicitly created
+ * surface.
+ */
+#define DDERR_IMPLICITLYCREATED                 MAKE_DDHRESULT( 588 )
+
+/*
+ * The surface being used is not a palette-based surface
+ */
+#define DDERR_NOTPALETTIZED                     MAKE_DDHRESULT( 589 )
+
+
+/*
+ * The display is currently in an unsupported mode
+ */
+#define DDERR_UNSUPPORTEDMODE                   MAKE_DDHRESULT( 590 )
+
+/*
+ * Operation could not be carried out because there is no mip-map
+ * texture mapping hardware present or available.
+ */
+#define DDERR_NOMIPMAPHW                        MAKE_DDHRESULT( 591 )
+
+/*
+ * The requested action could not be performed because the surface was of
+ * the wrong type.
+ */
+#define DDERR_INVALIDSURFACETYPE                MAKE_DDHRESULT( 592 )
+
+
+/*
+ * Device does not support optimized surfaces, therefore no video memory optimized surfaces
+ */
+#define DDERR_NOOPTIMIZEHW                      MAKE_DDHRESULT( 600 )
+
+/*
+ * Surface is an optimized surface, but has not yet been allocated any memory
+ */
+#define DDERR_NOTLOADED                         MAKE_DDHRESULT( 601 )
+
+/*
+ * Attempt was made to create or set a device window without first setting
+ * the focus window
+ */
+#define DDERR_NOFOCUSWINDOW                     MAKE_DDHRESULT( 602 )
+
+/*
+ * Attempt was made to set a palette on a mipmap sublevel
+ */
+#define DDERR_NOTONMIPMAPSUBLEVEL               MAKE_DDHRESULT( 603 )
+
+/*
+ * A DC has already been returned for this surface. Only one DC can be
+ * retrieved per surface.
+ */
+#define DDERR_DCALREADYCREATED                  MAKE_DDHRESULT( 620 )
+
+/*
+ * An attempt was made to allocate non-local video memory from a device
+ * that does not support non-local video memory.
+ */
+#define DDERR_NONONLOCALVIDMEM                  MAKE_DDHRESULT( 630 )
+
+/*
+ * The attempt to page lock a surface failed.
+ */
+#define DDERR_CANTPAGELOCK                      MAKE_DDHRESULT( 640 )
+
+
+/*
+ * The attempt to page unlock a surface failed.
+ */
+#define DDERR_CANTPAGEUNLOCK                    MAKE_DDHRESULT( 660 )
+
+/*
+ * An attempt was made to page unlock a surface with no outstanding page locks.
+ */
+#define DDERR_NOTPAGELOCKED                     MAKE_DDHRESULT( 680 )
+
+/*
+ * There is more data available than the specified buffer size could hold
+ */
+#define DDERR_MOREDATA                          MAKE_DDHRESULT( 690 )
+
+/*
+ * The data has expired and is therefore no longer valid.
+ */
+#define DDERR_EXPIRED                           MAKE_DDHRESULT( 691 )
+
+/*
+ * The mode test has finished executing.
+ */
+#define DDERR_TESTFINISHED                      MAKE_DDHRESULT( 692 )
+
+/*
+ * The mode test has switched to a new mode.
+ */
+#define DDERR_NEWMODE                           MAKE_DDHRESULT( 693 )
+
+/*
+ * D3D has not yet been initialized.
+ */
+#define DDERR_D3DNOTINITIALIZED                 MAKE_DDHRESULT( 694 )
+
+/*
+ * The video port is not active
+ */
+#define DDERR_VIDEONOTACTIVE                    MAKE_DDHRESULT( 695 )
+
+/*
+ * The monitor does not have EDID data.
+ */
+#define DDERR_NOMONITORINFORMATION              MAKE_DDHRESULT( 696 )
+
+/*
+ * The driver does not enumerate display mode refresh rates.
+ */
+#define DDERR_NODRIVERSUPPORT                   MAKE_DDHRESULT( 697 )
+
+/*
+ * Surfaces created by one direct draw device cannot be used directly by
+ * another direct draw device.
+ */
+#define DDERR_DEVICEDOESNTOWNSURFACE            MAKE_DDHRESULT( 699 )
+
+
+
+/*
+ * An attempt was made to invoke an interface member of a DirectDraw object
+ * created by CoCreateInstance() before it was initialized.
+ */
+#define DDERR_NOTINITIALIZED                    CO_E_NOTINITIALIZED
+
+
+/* Alpha bit depth constants */
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#ifdef ENABLE_NAMELESS_UNION_PRAGMA
+#pragma warning(default:4201)
+#endif
+
+#endif //__DDRAW_INCLUDED__
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dinput.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,4417 @@
+/****************************************************************************
+ *
+ *  Copyright (C) 1996-2000 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dinput.h
+ *  Content:    DirectInput include file
+ *
+ ****************************************************************************/
+
+#ifndef __DINPUT_INCLUDED__
+#define __DINPUT_INCLUDED__
+
+#ifndef DIJ_RINGZERO
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#endif
+
+#endif /* DIJ_RINGZERO */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+
+
+/*
+ *  To build applications for older versions of DirectInput
+ *
+ *  #define DIRECTINPUT_VERSION [ 0x0300 | 0x0500 | 0x0700 ]
+ *
+ *  before #include <dinput.h>.  By default, #include <dinput.h>
+ *  will produce a DirectX 8-compatible header file.
+ *
+ */
+
+#define DIRECTINPUT_HEADER_VERSION  0x0800
+#ifndef DIRECTINPUT_VERSION
+#define DIRECTINPUT_VERSION         DIRECTINPUT_HEADER_VERSION
+#pragma message(__FILE__ ": DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800")
+#endif
+
+#ifndef DIJ_RINGZERO
+
+/****************************************************************************
+ *
+ *      Class IDs
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(CLSID_DirectInput,       0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(CLSID_DirectInputDevice, 0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(CLSID_DirectInput8,      0x25E609E4,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(CLSID_DirectInputDevice8,0x25E609E5,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Interfaces
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(IID_IDirectInputA,     0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputW,     0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInput2A,    0x5944E662,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInput2W,    0x5944E663,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInput7A,    0x9A4CB684,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE);
+DEFINE_GUID(IID_IDirectInput7W,    0x9A4CB685,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE);
+DEFINE_GUID(IID_IDirectInput8A,    0xBF798030,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00);
+DEFINE_GUID(IID_IDirectInput8W,    0xBF798031,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00);
+DEFINE_GUID(IID_IDirectInputDeviceA, 0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputDeviceW, 0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputDevice2A,0x5944E682,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputDevice2W,0x5944E683,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputDevice7A,0x57D7C6BC,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE);
+DEFINE_GUID(IID_IDirectInputDevice7W,0x57D7C6BD,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE);
+DEFINE_GUID(IID_IDirectInputDevice8A,0x54D41080,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79);
+DEFINE_GUID(IID_IDirectInputDevice8W,0x54D41081,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79);
+DEFINE_GUID(IID_IDirectInputEffect,  0xE7E1F7C0,0x88D2,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+
+/****************************************************************************
+ *
+ *      Predefined object types
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(GUID_XAxis,   0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_YAxis,   0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_ZAxis,   0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_RxAxis,  0xA36D02F4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_RyAxis,  0xA36D02F5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_RzAxis,  0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_Slider,  0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(GUID_Button,  0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_Key,     0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(GUID_POV,     0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(GUID_Unknown, 0xA36D02F3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Predefined product GUIDs
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(GUID_SysMouse,   0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_SysKeyboard,0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_Joystick   ,0x6F1D2B70,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_SysMouseEm, 0x6F1D2B80,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_SysMouseEm2,0x6F1D2B81,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_SysKeyboardEm, 0x6F1D2B82,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_SysKeyboardEm2,0x6F1D2B83,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Predefined force feedback effects
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(GUID_ConstantForce, 0x13541C20,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_RampForce,     0x13541C21,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_Square,        0x13541C22,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_Sine,          0x13541C23,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_Triangle,      0x13541C24,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_SawtoothUp,    0x13541C25,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_SawtoothDown,  0x13541C26,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_Spring,        0x13541C27,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_Damper,        0x13541C28,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_Inertia,       0x13541C29,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_Friction,      0x13541C2A,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(GUID_CustomForce,   0x13541C2B,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+
+#endif /* DIJ_RINGZERO */
+
+/****************************************************************************
+ *
+ *      Interfaces and Structures...
+ *
+ ****************************************************************************/
+
+#if(DIRECTINPUT_VERSION >= 0x0500)
+
+/****************************************************************************
+ *
+ *      IDirectInputEffect
+ *
+ ****************************************************************************/
+
+#define DIEFT_ALL                   0x00000000
+
+#define DIEFT_CONSTANTFORCE         0x00000001
+#define DIEFT_RAMPFORCE             0x00000002
+#define DIEFT_PERIODIC              0x00000003
+#define DIEFT_CONDITION             0x00000004
+#define DIEFT_CUSTOMFORCE           0x00000005
+#define DIEFT_HARDWARE              0x000000FF
+#define DIEFT_FFATTACK              0x00000200
+#define DIEFT_FFFADE                0x00000400
+#define DIEFT_SATURATION            0x00000800
+#define DIEFT_POSNEGCOEFFICIENTS    0x00001000
+#define DIEFT_POSNEGSATURATION      0x00002000
+#define DIEFT_DEADBAND              0x00004000
+#define DIEFT_STARTDELAY            0x00008000
+#define DIEFT_GETTYPE(n)            LOBYTE(n)
+
+#define DI_DEGREES                  100
+#define DI_FFNOMINALMAX             10000
+#define DI_SECONDS                  1000000
+
+typedef struct DICONSTANTFORCE {
+    LONG  lMagnitude;
+} DICONSTANTFORCE, *LPDICONSTANTFORCE;
+typedef const DICONSTANTFORCE *LPCDICONSTANTFORCE;
+
+typedef struct DIRAMPFORCE {
+    LONG  lStart;
+    LONG  lEnd;
+} DIRAMPFORCE, *LPDIRAMPFORCE;
+typedef const DIRAMPFORCE *LPCDIRAMPFORCE;
+
+typedef struct DIPERIODIC {
+    DWORD dwMagnitude;
+    LONG  lOffset;
+    DWORD dwPhase;
+    DWORD dwPeriod;
+} DIPERIODIC, *LPDIPERIODIC;
+typedef const DIPERIODIC *LPCDIPERIODIC;
+
+typedef struct DICONDITION {
+    LONG  lOffset;
+    LONG  lPositiveCoefficient;
+    LONG  lNegativeCoefficient;
+    DWORD dwPositiveSaturation;
+    DWORD dwNegativeSaturation;
+    LONG  lDeadBand;
+} DICONDITION, *LPDICONDITION;
+typedef const DICONDITION *LPCDICONDITION;
+
+typedef struct DICUSTOMFORCE {
+    DWORD cChannels;
+    DWORD dwSamplePeriod;
+    DWORD cSamples;
+    LPLONG rglForceData;
+} DICUSTOMFORCE, *LPDICUSTOMFORCE;
+typedef const DICUSTOMFORCE *LPCDICUSTOMFORCE;
+
+
+typedef struct DIENVELOPE {
+    DWORD dwSize;                   /* sizeof(DIENVELOPE)   */
+    DWORD dwAttackLevel;
+    DWORD dwAttackTime;             /* Microseconds         */
+    DWORD dwFadeLevel;
+    DWORD dwFadeTime;               /* Microseconds         */
+} DIENVELOPE, *LPDIENVELOPE;
+typedef const DIENVELOPE *LPCDIENVELOPE;
+
+
+/* This structure is defined for DirectX 5.0 compatibility */
+typedef struct DIEFFECT_DX5 {
+    DWORD dwSize;                   /* sizeof(DIEFFECT_DX5) */
+    DWORD dwFlags;                  /* DIEFF_*              */
+    DWORD dwDuration;               /* Microseconds         */
+    DWORD dwSamplePeriod;           /* Microseconds         */
+    DWORD dwGain;
+    DWORD dwTriggerButton;          /* or DIEB_NOTRIGGER    */
+    DWORD dwTriggerRepeatInterval;  /* Microseconds         */
+    DWORD cAxes;                    /* Number of axes       */
+    LPDWORD rgdwAxes;               /* Array of axes        */
+    LPLONG rglDirection;            /* Array of directions  */
+    LPDIENVELOPE lpEnvelope;        /* Optional             */
+    DWORD cbTypeSpecificParams;     /* Size of params       */
+    LPVOID lpvTypeSpecificParams;   /* Pointer to params    */
+} DIEFFECT_DX5, *LPDIEFFECT_DX5;
+typedef const DIEFFECT_DX5 *LPCDIEFFECT_DX5;
+
+typedef struct DIEFFECT {
+    DWORD dwSize;                   /* sizeof(DIEFFECT)     */
+    DWORD dwFlags;                  /* DIEFF_*              */
+    DWORD dwDuration;               /* Microseconds         */
+    DWORD dwSamplePeriod;           /* Microseconds         */
+    DWORD dwGain;
+    DWORD dwTriggerButton;          /* or DIEB_NOTRIGGER    */
+    DWORD dwTriggerRepeatInterval;  /* Microseconds         */
+    DWORD cAxes;                    /* Number of axes       */
+    LPDWORD rgdwAxes;               /* Array of axes        */
+    LPLONG rglDirection;            /* Array of directions  */
+    LPDIENVELOPE lpEnvelope;        /* Optional             */
+    DWORD cbTypeSpecificParams;     /* Size of params       */
+    LPVOID lpvTypeSpecificParams;   /* Pointer to params    */
+#if(DIRECTINPUT_VERSION >= 0x0600)
+    DWORD  dwStartDelay;            /* Microseconds         */
+#endif /* DIRECTINPUT_VERSION >= 0x0600 */
+} DIEFFECT, *LPDIEFFECT;
+typedef DIEFFECT DIEFFECT_DX6;
+typedef LPDIEFFECT LPDIEFFECT_DX6;
+typedef const DIEFFECT *LPCDIEFFECT;
+
+
+#if(DIRECTINPUT_VERSION >= 0x0700)
+#ifndef DIJ_RINGZERO
+typedef struct DIFILEEFFECT{
+    DWORD       dwSize;
+    GUID        GuidEffect;
+    LPCDIEFFECT lpDiEffect;
+    CHAR        szFriendlyName[MAX_PATH];
+}DIFILEEFFECT, *LPDIFILEEFFECT;
+typedef const DIFILEEFFECT *LPCDIFILEEFFECT;
+typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSINFILECALLBACK)(LPCDIFILEEFFECT , LPVOID);
+#endif /* DIJ_RINGZERO */
+#endif /* DIRECTINPUT_VERSION >= 0x0700 */
+
+#define DIEFF_OBJECTIDS             0x00000001
+#define DIEFF_OBJECTOFFSETS         0x00000002
+#define DIEFF_CARTESIAN             0x00000010
+#define DIEFF_POLAR                 0x00000020
+#define DIEFF_SPHERICAL             0x00000040
+
+#define DIEP_DURATION               0x00000001
+#define DIEP_SAMPLEPERIOD           0x00000002
+#define DIEP_GAIN                   0x00000004
+#define DIEP_TRIGGERBUTTON          0x00000008
+#define DIEP_TRIGGERREPEATINTERVAL  0x00000010
+#define DIEP_AXES                   0x00000020
+#define DIEP_DIRECTION              0x00000040
+#define DIEP_ENVELOPE               0x00000080
+#define DIEP_TYPESPECIFICPARAMS     0x00000100
+#if(DIRECTINPUT_VERSION >= 0x0600)
+#define DIEP_STARTDELAY             0x00000200
+#define DIEP_ALLPARAMS_DX5          0x000001FF
+#define DIEP_ALLPARAMS              0x000003FF
+#else /* DIRECTINPUT_VERSION < 0x0600 */
+#define DIEP_ALLPARAMS              0x000001FF
+#endif /* DIRECTINPUT_VERSION < 0x0600 */
+#define DIEP_START                  0x20000000
+#define DIEP_NORESTART              0x40000000
+#define DIEP_NODOWNLOAD             0x80000000
+#define DIEB_NOTRIGGER              0xFFFFFFFF
+
+#define DIES_SOLO                   0x00000001
+#define DIES_NODOWNLOAD             0x80000000
+
+#define DIEGES_PLAYING              0x00000001
+#define DIEGES_EMULATED             0x00000002
+
+typedef struct DIEFFESCAPE {
+    DWORD   dwSize;
+    DWORD   dwCommand;
+    LPVOID  lpvInBuffer;
+    DWORD   cbInBuffer;
+    LPVOID  lpvOutBuffer;
+    DWORD   cbOutBuffer;
+} DIEFFESCAPE, *LPDIEFFESCAPE;
+
+#ifndef DIJ_RINGZERO
+
+#undef INTERFACE
+#define INTERFACE IDirectInputEffect
+
+DECLARE_INTERFACE_(IDirectInputEffect, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputEffect methods ***/
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+    STDMETHOD(GetEffectGuid)(THIS_ LPGUID) PURE;
+    STDMETHOD(GetParameters)(THIS_ LPDIEFFECT,DWORD) PURE;
+    STDMETHOD(SetParameters)(THIS_ LPCDIEFFECT,DWORD) PURE;
+    STDMETHOD(Start)(THIS_ DWORD,DWORD) PURE;
+    STDMETHOD(Stop)(THIS) PURE;
+    STDMETHOD(GetEffectStatus)(THIS_ LPDWORD) PURE;
+    STDMETHOD(Download)(THIS) PURE;
+    STDMETHOD(Unload)(THIS) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+};
+
+typedef struct IDirectInputEffect *LPDIRECTINPUTEFFECT;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputEffect_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputEffect_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputEffect_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputEffect_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#define IDirectInputEffect_GetEffectGuid(p,a) (p)->lpVtbl->GetEffectGuid(p,a)
+#define IDirectInputEffect_GetParameters(p,a,b) (p)->lpVtbl->GetParameters(p,a,b)
+#define IDirectInputEffect_SetParameters(p,a,b) (p)->lpVtbl->SetParameters(p,a,b)
+#define IDirectInputEffect_Start(p,a,b) (p)->lpVtbl->Start(p,a,b)
+#define IDirectInputEffect_Stop(p) (p)->lpVtbl->Stop(p)
+#define IDirectInputEffect_GetEffectStatus(p,a) (p)->lpVtbl->GetEffectStatus(p,a)
+#define IDirectInputEffect_Download(p) (p)->lpVtbl->Download(p)
+#define IDirectInputEffect_Unload(p) (p)->lpVtbl->Unload(p)
+#define IDirectInputEffect_Escape(p,a) (p)->lpVtbl->Escape(p,a)
+#else
+#define IDirectInputEffect_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputEffect_AddRef(p) (p)->AddRef()
+#define IDirectInputEffect_Release(p) (p)->Release()
+#define IDirectInputEffect_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+#define IDirectInputEffect_GetEffectGuid(p,a) (p)->GetEffectGuid(a)
+#define IDirectInputEffect_GetParameters(p,a,b) (p)->GetParameters(a,b)
+#define IDirectInputEffect_SetParameters(p,a,b) (p)->SetParameters(a,b)
+#define IDirectInputEffect_Start(p,a,b) (p)->Start(a,b)
+#define IDirectInputEffect_Stop(p) (p)->Stop()
+#define IDirectInputEffect_GetEffectStatus(p,a) (p)->GetEffectStatus(a)
+#define IDirectInputEffect_Download(p) (p)->Download()
+#define IDirectInputEffect_Unload(p) (p)->Unload()
+#define IDirectInputEffect_Escape(p,a) (p)->Escape(a)
+#endif
+
+#endif /* DIJ_RINGZERO */
+
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+
+/****************************************************************************
+ *
+ *      IDirectInputDevice
+ *
+ ****************************************************************************/
+
+#if DIRECTINPUT_VERSION <= 0x700
+#define DIDEVTYPE_DEVICE        1
+#define DIDEVTYPE_MOUSE         2
+#define DIDEVTYPE_KEYBOARD      3
+#define DIDEVTYPE_JOYSTICK      4
+
+#else
+#define DI8DEVCLASS_ALL             0
+#define DI8DEVCLASS_DEVICE          1
+#define DI8DEVCLASS_POINTER         2
+#define DI8DEVCLASS_KEYBOARD        3
+#define DI8DEVCLASS_GAMECTRL        4
+
+#define DI8DEVTYPE_DEVICE           0x11
+#define DI8DEVTYPE_MOUSE            0x12
+#define DI8DEVTYPE_KEYBOARD         0x13
+#define DI8DEVTYPE_JOYSTICK         0x14
+#define DI8DEVTYPE_GAMEPAD          0x15
+#define DI8DEVTYPE_DRIVING          0x16
+#define DI8DEVTYPE_FLIGHT           0x17
+#define DI8DEVTYPE_1STPERSON        0x18
+#define DI8DEVTYPE_DEVICECTRL       0x19
+#define DI8DEVTYPE_SCREENPOINTER    0x1A
+#define DI8DEVTYPE_REMOTE           0x1B
+#define DI8DEVTYPE_SUPPLEMENTAL     0x1C
+#endif /* DIRECTINPUT_VERSION <= 0x700 */
+
+#define DIDEVTYPE_HID           0x00010000
+
+#if DIRECTINPUT_VERSION <= 0x700
+#define DIDEVTYPEMOUSE_UNKNOWN          1
+#define DIDEVTYPEMOUSE_TRADITIONAL      2
+#define DIDEVTYPEMOUSE_FINGERSTICK      3
+#define DIDEVTYPEMOUSE_TOUCHPAD         4
+#define DIDEVTYPEMOUSE_TRACKBALL        5
+
+#define DIDEVTYPEKEYBOARD_UNKNOWN       0
+#define DIDEVTYPEKEYBOARD_PCXT          1
+#define DIDEVTYPEKEYBOARD_OLIVETTI      2
+#define DIDEVTYPEKEYBOARD_PCAT          3
+#define DIDEVTYPEKEYBOARD_PCENH         4
+#define DIDEVTYPEKEYBOARD_NOKIA1050     5
+#define DIDEVTYPEKEYBOARD_NOKIA9140     6
+#define DIDEVTYPEKEYBOARD_NEC98         7
+#define DIDEVTYPEKEYBOARD_NEC98LAPTOP   8
+#define DIDEVTYPEKEYBOARD_NEC98106      9
+#define DIDEVTYPEKEYBOARD_JAPAN106     10
+#define DIDEVTYPEKEYBOARD_JAPANAX      11
+#define DIDEVTYPEKEYBOARD_J3100        12
+
+#define DIDEVTYPEJOYSTICK_UNKNOWN       1
+#define DIDEVTYPEJOYSTICK_TRADITIONAL   2
+#define DIDEVTYPEJOYSTICK_FLIGHTSTICK   3
+#define DIDEVTYPEJOYSTICK_GAMEPAD       4
+#define DIDEVTYPEJOYSTICK_RUDDER        5
+#define DIDEVTYPEJOYSTICK_WHEEL         6
+#define DIDEVTYPEJOYSTICK_HEADTRACKER   7
+
+#else
+#define DI8DEVTYPEMOUSE_UNKNOWN                     1
+#define DI8DEVTYPEMOUSE_TRADITIONAL                 2
+#define DI8DEVTYPEMOUSE_FINGERSTICK                 3
+#define DI8DEVTYPEMOUSE_TOUCHPAD                    4
+#define DI8DEVTYPEMOUSE_TRACKBALL                   5
+#define DI8DEVTYPEMOUSE_ABSOLUTE                    6
+
+#define DI8DEVTYPEKEYBOARD_UNKNOWN                  0
+#define DI8DEVTYPEKEYBOARD_PCXT                     1
+#define DI8DEVTYPEKEYBOARD_OLIVETTI                 2
+#define DI8DEVTYPEKEYBOARD_PCAT                     3
+#define DI8DEVTYPEKEYBOARD_PCENH                    4
+#define DI8DEVTYPEKEYBOARD_NOKIA1050                5
+#define DI8DEVTYPEKEYBOARD_NOKIA9140                6
+#define DI8DEVTYPEKEYBOARD_NEC98                    7
+#define DI8DEVTYPEKEYBOARD_NEC98LAPTOP              8
+#define DI8DEVTYPEKEYBOARD_NEC98106                 9
+#define DI8DEVTYPEKEYBOARD_JAPAN106                10
+#define DI8DEVTYPEKEYBOARD_JAPANAX                 11
+#define DI8DEVTYPEKEYBOARD_J3100                   12
+
+#define DI8DEVTYPE_LIMITEDGAMESUBTYPE               1
+
+#define DI8DEVTYPEJOYSTICK_LIMITED                  DI8DEVTYPE_LIMITEDGAMESUBTYPE
+#define DI8DEVTYPEJOYSTICK_STANDARD                 2
+
+#define DI8DEVTYPEGAMEPAD_LIMITED                   DI8DEVTYPE_LIMITEDGAMESUBTYPE
+#define DI8DEVTYPEGAMEPAD_STANDARD                  2
+#define DI8DEVTYPEGAMEPAD_TILT                      3
+
+#define DI8DEVTYPEDRIVING_LIMITED                   DI8DEVTYPE_LIMITEDGAMESUBTYPE
+#define DI8DEVTYPEDRIVING_COMBINEDPEDALS            2
+#define DI8DEVTYPEDRIVING_DUALPEDALS                3
+#define DI8DEVTYPEDRIVING_THREEPEDALS               4
+#define DI8DEVTYPEDRIVING_HANDHELD                  5
+
+#define DI8DEVTYPEFLIGHT_LIMITED                    DI8DEVTYPE_LIMITEDGAMESUBTYPE
+#define DI8DEVTYPEFLIGHT_STICK                      2
+#define DI8DEVTYPEFLIGHT_YOKE                       3
+#define DI8DEVTYPEFLIGHT_RC                         4
+
+#define DI8DEVTYPE1STPERSON_LIMITED                 DI8DEVTYPE_LIMITEDGAMESUBTYPE
+#define DI8DEVTYPE1STPERSON_UNKNOWN                 2
+#define DI8DEVTYPE1STPERSON_SIXDOF                  3
+#define DI8DEVTYPE1STPERSON_SHOOTER                 4
+
+#define DI8DEVTYPESCREENPTR_UNKNOWN                 2
+#define DI8DEVTYPESCREENPTR_LIGHTGUN                3
+#define DI8DEVTYPESCREENPTR_LIGHTPEN                4
+#define DI8DEVTYPESCREENPTR_TOUCH                   5
+
+#define DI8DEVTYPEREMOTE_UNKNOWN                    2
+
+#define DI8DEVTYPEDEVICECTRL_UNKNOWN                2
+#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION         3
+#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION_HARDWIRED 4
+
+#define DI8DEVTYPESUPPLEMENTAL_UNKNOWN              2
+#define DI8DEVTYPESUPPLEMENTAL_2NDHANDCONTROLLER    3
+#define DI8DEVTYPESUPPLEMENTAL_HEADTRACKER          4
+#define DI8DEVTYPESUPPLEMENTAL_HANDTRACKER          5
+#define DI8DEVTYPESUPPLEMENTAL_SHIFTSTICKGATE       6
+#define DI8DEVTYPESUPPLEMENTAL_SHIFTER              7
+#define DI8DEVTYPESUPPLEMENTAL_THROTTLE             8
+#define DI8DEVTYPESUPPLEMENTAL_SPLITTHROTTLE        9
+#define DI8DEVTYPESUPPLEMENTAL_COMBINEDPEDALS      10
+#define DI8DEVTYPESUPPLEMENTAL_DUALPEDALS          11
+#define DI8DEVTYPESUPPLEMENTAL_THREEPEDALS         12
+#define DI8DEVTYPESUPPLEMENTAL_RUDDERPEDALS        13
+#endif /* DIRECTINPUT_VERSION <= 0x700 */
+
+#define GET_DIDEVICE_TYPE(dwDevType)    LOBYTE(dwDevType)
+#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType)
+
+#if(DIRECTINPUT_VERSION >= 0x0500)
+/* This structure is defined for DirectX 3.0 compatibility */
+typedef struct DIDEVCAPS_DX3 {
+    DWORD   dwSize;
+    DWORD   dwFlags;
+    DWORD   dwDevType;
+    DWORD   dwAxes;
+    DWORD   dwButtons;
+    DWORD   dwPOVs;
+} DIDEVCAPS_DX3, *LPDIDEVCAPS_DX3;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+
+typedef struct DIDEVCAPS {
+    DWORD   dwSize;
+    DWORD   dwFlags;
+    DWORD   dwDevType;
+    DWORD   dwAxes;
+    DWORD   dwButtons;
+    DWORD   dwPOVs;
+#if(DIRECTINPUT_VERSION >= 0x0500)
+    DWORD   dwFFSamplePeriod;
+    DWORD   dwFFMinTimeResolution;
+    DWORD   dwFirmwareRevision;
+    DWORD   dwHardwareRevision;
+    DWORD   dwFFDriverVersion;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+} DIDEVCAPS, *LPDIDEVCAPS;
+
+#define DIDC_ATTACHED           0x00000001
+#define DIDC_POLLEDDEVICE       0x00000002
+#define DIDC_EMULATED           0x00000004
+#define DIDC_POLLEDDATAFORMAT   0x00000008
+#if(DIRECTINPUT_VERSION >= 0x0500)
+#define DIDC_FORCEFEEDBACK      0x00000100
+#define DIDC_FFATTACK           0x00000200
+#define DIDC_FFFADE             0x00000400
+#define DIDC_SATURATION         0x00000800
+#define DIDC_POSNEGCOEFFICIENTS 0x00001000
+#define DIDC_POSNEGSATURATION   0x00002000
+#define DIDC_DEADBAND           0x00004000
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+#define DIDC_STARTDELAY         0x00008000
+#if(DIRECTINPUT_VERSION >= 0x050a)
+#define DIDC_ALIAS              0x00010000
+#define DIDC_PHANTOM            0x00020000
+#endif /* DIRECTINPUT_VERSION >= 0x050a */
+#if(DIRECTINPUT_VERSION >= 0x0800)
+#define DIDC_HIDDEN             0x00040000
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+#define DIDFT_ALL           0x00000000
+
+#define DIDFT_RELAXIS       0x00000001
+#define DIDFT_ABSAXIS       0x00000002
+#define DIDFT_AXIS          0x00000003
+
+#define DIDFT_PSHBUTTON     0x00000004
+#define DIDFT_TGLBUTTON     0x00000008
+#define DIDFT_BUTTON        0x0000000C
+
+#define DIDFT_POV           0x00000010
+#define DIDFT_COLLECTION    0x00000040
+#define DIDFT_NODATA        0x00000080
+
+#define DIDFT_ANYINSTANCE   0x00FFFF00
+#define DIDFT_INSTANCEMASK  DIDFT_ANYINSTANCE
+#define DIDFT_MAKEINSTANCE(n) ((WORD)(n) << 8)
+#define DIDFT_GETTYPE(n)     LOBYTE(n)
+#define DIDFT_GETINSTANCE(n) LOWORD((n) >> 8)
+#define DIDFT_FFACTUATOR        0x01000000
+#define DIDFT_FFEFFECTTRIGGER   0x02000000
+#if(DIRECTINPUT_VERSION >= 0x050a)
+#define DIDFT_OUTPUT            0x10000000
+#define DIDFT_VENDORDEFINED     0x04000000
+#define DIDFT_ALIAS             0x08000000
+#endif /* DIRECTINPUT_VERSION >= 0x050a */
+#ifndef DIDFT_OPTIONAL
+#define DIDFT_OPTIONAL          0x80000000
+#endif
+
+#define DIDFT_ENUMCOLLECTION(n) ((WORD)(n) << 8)
+#define DIDFT_NOCOLLECTION      0x00FFFF00
+
+#ifndef DIJ_RINGZERO
+
+typedef struct _DIOBJECTDATAFORMAT {
+    const GUID *pguid;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT;
+typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT;
+
+typedef struct _DIDATAFORMAT {
+    DWORD   dwSize;
+    DWORD   dwObjSize;
+    DWORD   dwFlags;
+    DWORD   dwDataSize;
+    DWORD   dwNumObjs;
+    LPDIOBJECTDATAFORMAT rgodf;
+} DIDATAFORMAT, *LPDIDATAFORMAT;
+typedef const DIDATAFORMAT *LPCDIDATAFORMAT;
+
+#define DIDF_ABSAXIS            0x00000001
+#define DIDF_RELAXIS            0x00000002
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern const DIDATAFORMAT c_dfDIMouse;
+
+#if(DIRECTINPUT_VERSION >= 0x0700)
+extern const DIDATAFORMAT c_dfDIMouse2;
+#endif /* DIRECTINPUT_VERSION >= 0x0700 */
+
+extern const DIDATAFORMAT c_dfDIKeyboard;
+
+#if(DIRECTINPUT_VERSION >= 0x0500)
+extern const DIDATAFORMAT c_dfDIJoystick;
+extern const DIDATAFORMAT c_dfDIJoystick2;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+
+#ifdef __cplusplus
+};
+#endif
+
+
+#if DIRECTINPUT_VERSION > 0x0700
+
+typedef struct _DIACTIONA {
+                UINT_PTR    uAppData;
+                DWORD       dwSemantic;
+    OPTIONAL    DWORD       dwFlags;
+    OPTIONAL    union {
+                    LPCSTR      lptszActionName;
+                    UINT        uResIdString;
+                };
+    OPTIONAL    GUID        guidInstance;
+    OPTIONAL    DWORD       dwObjID;
+    OPTIONAL    DWORD       dwHow;
+} DIACTIONA, *LPDIACTIONA ;
+typedef struct _DIACTIONW {
+                UINT_PTR    uAppData;
+                DWORD       dwSemantic;
+    OPTIONAL    DWORD       dwFlags;
+    OPTIONAL    union {
+                    LPCWSTR     lptszActionName;
+                    UINT        uResIdString;
+                };
+    OPTIONAL    GUID        guidInstance;
+    OPTIONAL    DWORD       dwObjID;
+    OPTIONAL    DWORD       dwHow;
+} DIACTIONW, *LPDIACTIONW ;
+#ifdef UNICODE
+typedef DIACTIONW DIACTION;
+typedef LPDIACTIONW LPDIACTION;
+#else
+typedef DIACTIONA DIACTION;
+typedef LPDIACTIONA LPDIACTION;
+#endif // UNICODE
+
+typedef const DIACTIONA *LPCDIACTIONA;
+typedef const DIACTIONW *LPCDIACTIONW;
+#ifdef UNICODE
+typedef DIACTIONW DIACTION;
+typedef LPCDIACTIONW LPCDIACTION;
+#else
+typedef DIACTIONA DIACTION;
+typedef LPCDIACTIONA LPCDIACTION;
+#endif // UNICODE
+typedef const DIACTION *LPCDIACTION;
+
+
+#define DIA_FORCEFEEDBACK       0x00000001
+#define DIA_APPMAPPED           0x00000002
+#define DIA_APPNOMAP            0x00000004
+#define DIA_NORANGE             0x00000008
+#define DIA_APPFIXED            0x00000010
+
+#define DIAH_UNMAPPED           0x00000000
+#define DIAH_USERCONFIG         0x00000001
+#define DIAH_APPREQUESTED       0x00000002
+#define DIAH_HWAPP              0x00000004
+#define DIAH_HWDEFAULT          0x00000008
+#define DIAH_DEFAULT            0x00000020
+#define DIAH_ERROR              0x80000000
+
+typedef struct _DIACTIONFORMATA {
+                DWORD       dwSize;
+                DWORD       dwActionSize;
+                DWORD       dwDataSize;
+                DWORD       dwNumActions;
+                LPDIACTIONA rgoAction;
+                GUID        guidActionMap;
+                DWORD       dwGenre;
+                DWORD       dwBufferSize;
+    OPTIONAL    LONG        lAxisMin;
+    OPTIONAL    LONG        lAxisMax;
+    OPTIONAL    HINSTANCE   hInstString;
+                FILETIME    ftTimeStamp;
+                DWORD       dwCRC;
+                CHAR        tszActionMap[MAX_PATH];
+} DIACTIONFORMATA, *LPDIACTIONFORMATA;
+typedef struct _DIACTIONFORMATW {
+                DWORD       dwSize;
+                DWORD       dwActionSize;
+                DWORD       dwDataSize;
+                DWORD       dwNumActions;
+                LPDIACTIONW rgoAction;
+                GUID        guidActionMap;
+                DWORD       dwGenre;
+                DWORD       dwBufferSize;
+    OPTIONAL    LONG        lAxisMin;
+    OPTIONAL    LONG        lAxisMax;
+    OPTIONAL    HINSTANCE   hInstString;
+                FILETIME    ftTimeStamp;
+                DWORD       dwCRC;
+                WCHAR       tszActionMap[MAX_PATH];
+} DIACTIONFORMATW, *LPDIACTIONFORMATW;
+#ifdef UNICODE
+typedef DIACTIONFORMATW DIACTIONFORMAT;
+typedef LPDIACTIONFORMATW LPDIACTIONFORMAT;
+#else
+typedef DIACTIONFORMATA DIACTIONFORMAT;
+typedef LPDIACTIONFORMATA LPDIACTIONFORMAT;
+#endif // UNICODE
+typedef const DIACTIONFORMATA *LPCDIACTIONFORMATA;
+typedef const DIACTIONFORMATW *LPCDIACTIONFORMATW;
+#ifdef UNICODE
+typedef DIACTIONFORMATW DIACTIONFORMAT;
+typedef LPCDIACTIONFORMATW LPCDIACTIONFORMAT;
+#else
+typedef DIACTIONFORMATA DIACTIONFORMAT;
+typedef LPCDIACTIONFORMATA LPCDIACTIONFORMAT;
+#endif // UNICODE
+typedef const DIACTIONFORMAT *LPCDIACTIONFORMAT;
+
+#define DIAFTS_NEWDEVICELOW     0xFFFFFFFF
+#define DIAFTS_NEWDEVICEHIGH    0xFFFFFFFF
+#define DIAFTS_UNUSEDDEVICELOW  0x00000000
+#define DIAFTS_UNUSEDDEVICEHIGH 0x00000000
+
+#define DIDBAM_DEFAULT          0x00000000
+#define DIDBAM_PRESERVE         0x00000001
+#define DIDBAM_INITIALIZE       0x00000002
+#define DIDBAM_HWDEFAULTS       0x00000004
+
+#define DIDSAM_DEFAULT          0x00000000
+#define DIDSAM_NOUSER           0x00000001
+#define DIDSAM_FORCESAVE        0x00000002
+
+#define DICD_DEFAULT            0x00000000
+#define DICD_EDIT               0x00000001
+
+/*
+ * The following definition is normally defined in d3dtypes.h
+ */
+#ifndef D3DCOLOR_DEFINED
+typedef DWORD D3DCOLOR;
+#define D3DCOLOR_DEFINED
+#endif
+
+typedef struct _DICOLORSET{
+    DWORD dwSize;
+    D3DCOLOR cTextFore;
+    D3DCOLOR cTextHighlight;
+    D3DCOLOR cCalloutLine;
+    D3DCOLOR cCalloutHighlight;
+    D3DCOLOR cBorder;
+    D3DCOLOR cControlFill;
+    D3DCOLOR cHighlightFill;
+    D3DCOLOR cAreaFill;
+} DICOLORSET, *LPDICOLORSET;
+typedef const DICOLORSET *LPCDICOLORSET;
+
+
+typedef struct _DICONFIGUREDEVICESPARAMSA{
+     DWORD             dwSize;
+     DWORD             dwcUsers;
+     LPSTR             lptszUserNames;
+     DWORD             dwcFormats;
+     LPDIACTIONFORMATA lprgFormats;
+     HWND              hwnd;
+     DICOLORSET        dics;
+     IUnknown FAR *    lpUnkDDSTarget;
+} DICONFIGUREDEVICESPARAMSA, *LPDICONFIGUREDEVICESPARAMSA;
+typedef struct _DICONFIGUREDEVICESPARAMSW{
+     DWORD             dwSize;
+     DWORD             dwcUsers;
+     LPWSTR            lptszUserNames;
+     DWORD             dwcFormats;
+     LPDIACTIONFORMATW lprgFormats;
+     HWND              hwnd;
+     DICOLORSET        dics;
+     IUnknown FAR *    lpUnkDDSTarget;
+} DICONFIGUREDEVICESPARAMSW, *LPDICONFIGUREDEVICESPARAMSW;
+#ifdef UNICODE
+typedef DICONFIGUREDEVICESPARAMSW DICONFIGUREDEVICESPARAMS;
+typedef LPDICONFIGUREDEVICESPARAMSW LPDICONFIGUREDEVICESPARAMS;
+#else
+typedef DICONFIGUREDEVICESPARAMSA DICONFIGUREDEVICESPARAMS;
+typedef LPDICONFIGUREDEVICESPARAMSA LPDICONFIGUREDEVICESPARAMS;
+#endif // UNICODE
+typedef const DICONFIGUREDEVICESPARAMSA *LPCDICONFIGUREDEVICESPARAMSA;
+typedef const DICONFIGUREDEVICESPARAMSW *LPCDICONFIGUREDEVICESPARAMSW;
+#ifdef UNICODE
+typedef DICONFIGUREDEVICESPARAMSW DICONFIGUREDEVICESPARAMS;
+typedef LPCDICONFIGUREDEVICESPARAMSW LPCDICONFIGUREDEVICESPARAMS;
+#else
+typedef DICONFIGUREDEVICESPARAMSA DICONFIGUREDEVICESPARAMS;
+typedef LPCDICONFIGUREDEVICESPARAMSA LPCDICONFIGUREDEVICESPARAMS;
+#endif // UNICODE
+typedef const DICONFIGUREDEVICESPARAMS *LPCDICONFIGUREDEVICESPARAMS;
+
+
+#define DIDIFT_CONFIGURATION    0x00000001
+#define DIDIFT_OVERLAY          0x00000002
+
+#define DIDAL_CENTERED      0x00000000
+#define DIDAL_LEFTALIGNED   0x00000001
+#define DIDAL_RIGHTALIGNED  0x00000002
+#define DIDAL_MIDDLE        0x00000000
+#define DIDAL_TOPALIGNED    0x00000004
+#define DIDAL_BOTTOMALIGNED 0x00000008
+
+typedef struct _DIDEVICEIMAGEINFOA {
+    CHAR        tszImagePath[MAX_PATH];
+    DWORD       dwFlags; 
+    // These are valid if DIDIFT_OVERLAY is present in dwFlags.
+    DWORD       dwViewID;      
+    RECT        rcOverlay;             
+    DWORD       dwObjID;
+    DWORD       dwcValidPts;
+    POINT       rgptCalloutLine[5];  
+    RECT        rcCalloutRect;  
+    DWORD       dwTextAlign;     
+} DIDEVICEIMAGEINFOA, *LPDIDEVICEIMAGEINFOA;
+typedef struct _DIDEVICEIMAGEINFOW {
+    WCHAR       tszImagePath[MAX_PATH];
+    DWORD       dwFlags; 
+    // These are valid if DIDIFT_OVERLAY is present in dwFlags.
+    DWORD       dwViewID;      
+    RECT        rcOverlay;             
+    DWORD       dwObjID;
+    DWORD       dwcValidPts;
+    POINT       rgptCalloutLine[5];  
+    RECT        rcCalloutRect;  
+    DWORD       dwTextAlign;     
+} DIDEVICEIMAGEINFOW, *LPDIDEVICEIMAGEINFOW;
+#ifdef UNICODE
+typedef DIDEVICEIMAGEINFOW DIDEVICEIMAGEINFO;
+typedef LPDIDEVICEIMAGEINFOW LPDIDEVICEIMAGEINFO;
+#else
+typedef DIDEVICEIMAGEINFOA DIDEVICEIMAGEINFO;
+typedef LPDIDEVICEIMAGEINFOA LPDIDEVICEIMAGEINFO;
+#endif // UNICODE
+typedef const DIDEVICEIMAGEINFOA *LPCDIDEVICEIMAGEINFOA;
+typedef const DIDEVICEIMAGEINFOW *LPCDIDEVICEIMAGEINFOW;
+#ifdef UNICODE
+typedef DIDEVICEIMAGEINFOW DIDEVICEIMAGEINFO;
+typedef LPCDIDEVICEIMAGEINFOW LPCDIDEVICEIMAGEINFO;
+#else
+typedef DIDEVICEIMAGEINFOA DIDEVICEIMAGEINFO;
+typedef LPCDIDEVICEIMAGEINFOA LPCDIDEVICEIMAGEINFO;
+#endif // UNICODE
+typedef const DIDEVICEIMAGEINFO *LPCDIDEVICEIMAGEINFO;
+
+typedef struct _DIDEVICEIMAGEINFOHEADERA {
+    DWORD       dwSize;
+    DWORD       dwSizeImageInfo;
+    DWORD       dwcViews;
+    DWORD       dwcButtons;
+    DWORD       dwcAxes;
+    DWORD       dwcPOVs;
+    DWORD       dwBufferSize;
+    DWORD       dwBufferUsed;
+    LPDIDEVICEIMAGEINFOA lprgImageInfoArray;
+} DIDEVICEIMAGEINFOHEADERA, *LPDIDEVICEIMAGEINFOHEADERA;
+typedef struct _DIDEVICEIMAGEINFOHEADERW {
+    DWORD       dwSize;
+    DWORD       dwSizeImageInfo;
+    DWORD       dwcViews;
+    DWORD       dwcButtons;
+    DWORD       dwcAxes;
+    DWORD       dwcPOVs;
+    DWORD       dwBufferSize;
+    DWORD       dwBufferUsed;
+    LPDIDEVICEIMAGEINFOW lprgImageInfoArray;
+} DIDEVICEIMAGEINFOHEADERW, *LPDIDEVICEIMAGEINFOHEADERW;
+#ifdef UNICODE
+typedef DIDEVICEIMAGEINFOHEADERW DIDEVICEIMAGEINFOHEADER;
+typedef LPDIDEVICEIMAGEINFOHEADERW LPDIDEVICEIMAGEINFOHEADER;
+#else
+typedef DIDEVICEIMAGEINFOHEADERA DIDEVICEIMAGEINFOHEADER;
+typedef LPDIDEVICEIMAGEINFOHEADERA LPDIDEVICEIMAGEINFOHEADER;
+#endif // UNICODE
+typedef const DIDEVICEIMAGEINFOHEADERA *LPCDIDEVICEIMAGEINFOHEADERA;
+typedef const DIDEVICEIMAGEINFOHEADERW *LPCDIDEVICEIMAGEINFOHEADERW;
+#ifdef UNICODE
+typedef DIDEVICEIMAGEINFOHEADERW DIDEVICEIMAGEINFOHEADER;
+typedef LPCDIDEVICEIMAGEINFOHEADERW LPCDIDEVICEIMAGEINFOHEADER;
+#else
+typedef DIDEVICEIMAGEINFOHEADERA DIDEVICEIMAGEINFOHEADER;
+typedef LPCDIDEVICEIMAGEINFOHEADERA LPCDIDEVICEIMAGEINFOHEADER;
+#endif // UNICODE
+typedef const DIDEVICEIMAGEINFOHEADER *LPCDIDEVICEIMAGEINFOHEADER;
+
+#endif /* DIRECTINPUT_VERSION > 0x0700 */
+
+#if(DIRECTINPUT_VERSION >= 0x0500)
+/* These structures are defined for DirectX 3.0 compatibility */
+
+typedef struct DIDEVICEOBJECTINSTANCE_DX3A {
+    DWORD   dwSize;
+    GUID    guidType;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+    CHAR    tszName[MAX_PATH];
+} DIDEVICEOBJECTINSTANCE_DX3A, *LPDIDEVICEOBJECTINSTANCE_DX3A;
+typedef struct DIDEVICEOBJECTINSTANCE_DX3W {
+    DWORD   dwSize;
+    GUID    guidType;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+    WCHAR   tszName[MAX_PATH];
+} DIDEVICEOBJECTINSTANCE_DX3W, *LPDIDEVICEOBJECTINSTANCE_DX3W;
+#ifdef UNICODE
+typedef DIDEVICEOBJECTINSTANCE_DX3W DIDEVICEOBJECTINSTANCE_DX3;
+typedef LPDIDEVICEOBJECTINSTANCE_DX3W LPDIDEVICEOBJECTINSTANCE_DX3;
+#else
+typedef DIDEVICEOBJECTINSTANCE_DX3A DIDEVICEOBJECTINSTANCE_DX3;
+typedef LPDIDEVICEOBJECTINSTANCE_DX3A LPDIDEVICEOBJECTINSTANCE_DX3;
+#endif // UNICODE
+typedef const DIDEVICEOBJECTINSTANCE_DX3A *LPCDIDEVICEOBJECTINSTANCE_DX3A;
+typedef const DIDEVICEOBJECTINSTANCE_DX3W *LPCDIDEVICEOBJECTINSTANCE_DX3W;
+typedef const DIDEVICEOBJECTINSTANCE_DX3  *LPCDIDEVICEOBJECTINSTANCE_DX3;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+
+typedef struct DIDEVICEOBJECTINSTANCEA {
+    DWORD   dwSize;
+    GUID    guidType;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+    CHAR    tszName[MAX_PATH];
+#if(DIRECTINPUT_VERSION >= 0x0500)
+    DWORD   dwFFMaxForce;
+    DWORD   dwFFForceResolution;
+    WORD    wCollectionNumber;
+    WORD    wDesignatorIndex;
+    WORD    wUsagePage;
+    WORD    wUsage;
+    DWORD   dwDimension;
+    WORD    wExponent;
+    WORD    wReportId;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA;
+typedef struct DIDEVICEOBJECTINSTANCEW {
+    DWORD   dwSize;
+    GUID    guidType;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+    WCHAR   tszName[MAX_PATH];
+#if(DIRECTINPUT_VERSION >= 0x0500)
+    DWORD   dwFFMaxForce;
+    DWORD   dwFFForceResolution;
+    WORD    wCollectionNumber;
+    WORD    wDesignatorIndex;
+    WORD    wUsagePage;
+    WORD    wUsage;
+    DWORD   dwDimension;
+    WORD    wExponent;
+    WORD    wReportId;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW;
+#ifdef UNICODE
+typedef DIDEVICEOBJECTINSTANCEW DIDEVICEOBJECTINSTANCE;
+typedef LPDIDEVICEOBJECTINSTANCEW LPDIDEVICEOBJECTINSTANCE;
+#else
+typedef DIDEVICEOBJECTINSTANCEA DIDEVICEOBJECTINSTANCE;
+typedef LPDIDEVICEOBJECTINSTANCEA LPDIDEVICEOBJECTINSTANCE;
+#endif // UNICODE
+typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA;
+typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW;
+typedef const DIDEVICEOBJECTINSTANCE  *LPCDIDEVICEOBJECTINSTANCE;
+
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA, LPVOID);
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW, LPVOID);
+#ifdef UNICODE
+#define LPDIENUMDEVICEOBJECTSCALLBACK  LPDIENUMDEVICEOBJECTSCALLBACKW
+#else
+#define LPDIENUMDEVICEOBJECTSCALLBACK  LPDIENUMDEVICEOBJECTSCALLBACKA
+#endif // !UNICODE
+
+#if(DIRECTINPUT_VERSION >= 0x0500)
+#define DIDOI_FFACTUATOR        0x00000001
+#define DIDOI_FFEFFECTTRIGGER   0x00000002
+#define DIDOI_POLLED            0x00008000
+#define DIDOI_ASPECTPOSITION    0x00000100
+#define DIDOI_ASPECTVELOCITY    0x00000200
+#define DIDOI_ASPECTACCEL       0x00000300
+#define DIDOI_ASPECTFORCE       0x00000400
+#define DIDOI_ASPECTMASK        0x00000F00
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+#if(DIRECTINPUT_VERSION >= 0x050a)
+#define DIDOI_GUIDISUSAGE       0x00010000
+#endif /* DIRECTINPUT_VERSION >= 0x050a */
+
+typedef struct DIPROPHEADER {
+    DWORD   dwSize;
+    DWORD   dwHeaderSize;
+    DWORD   dwObj;
+    DWORD   dwHow;
+} DIPROPHEADER, *LPDIPROPHEADER;
+typedef const DIPROPHEADER *LPCDIPROPHEADER;
+
+#define DIPH_DEVICE             0
+#define DIPH_BYOFFSET           1
+#define DIPH_BYID               2
+#if(DIRECTINPUT_VERSION >= 0x050a)
+#define DIPH_BYUSAGE            3
+#endif /* DIRECTINPUT_VERSION >= 0x050a */
+
+#if(DIRECTINPUT_VERSION >= 0x050a)
+#define DIMAKEUSAGEDWORD(UsagePage, Usage) \
+                                (DWORD)MAKELONG(Usage, UsagePage)
+#endif /* DIRECTINPUT_VERSION >= 0x050a */
+
+typedef struct DIPROPDWORD {
+    DIPROPHEADER diph;
+    DWORD   dwData;
+} DIPROPDWORD, *LPDIPROPDWORD;
+typedef const DIPROPDWORD *LPCDIPROPDWORD;
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+typedef struct DIPROPPOINTER {
+    DIPROPHEADER diph;
+    UINT_PTR uData;
+} DIPROPPOINTER, *LPDIPROPPOINTER;
+typedef const DIPROPPOINTER *LPCDIPROPPOINTER;
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+typedef struct DIPROPRANGE {
+    DIPROPHEADER diph;
+    LONG    lMin;
+    LONG    lMax;
+} DIPROPRANGE, *LPDIPROPRANGE;
+typedef const DIPROPRANGE *LPCDIPROPRANGE;
+
+#define DIPROPRANGE_NOMIN       ((LONG)0x80000000)
+#define DIPROPRANGE_NOMAX       ((LONG)0x7FFFFFFF)
+
+#if(DIRECTINPUT_VERSION >= 0x050a)
+typedef struct DIPROPCAL {
+    DIPROPHEADER diph;
+    LONG    lMin;
+    LONG    lCenter;
+    LONG    lMax;
+} DIPROPCAL, *LPDIPROPCAL;
+typedef const DIPROPCAL *LPCDIPROPCAL;
+
+typedef struct DIPROPCALPOV {
+    DIPROPHEADER diph;
+    LONG   lMin[5];
+    LONG   lMax[5];
+} DIPROPCALPOV, *LPDIPROPCALPOV;
+typedef const DIPROPCALPOV *LPCDIPROPCALPOV;
+
+typedef struct DIPROPGUIDANDPATH {
+    DIPROPHEADER diph;
+    GUID    guidClass;
+    WCHAR   wszPath[MAX_PATH];
+} DIPROPGUIDANDPATH, *LPDIPROPGUIDANDPATH;
+typedef const DIPROPGUIDANDPATH *LPCDIPROPGUIDANDPATH;
+
+typedef struct DIPROPSTRING {
+    DIPROPHEADER diph;
+    WCHAR   wsz[MAX_PATH];
+} DIPROPSTRING, *LPDIPROPSTRING;
+typedef const DIPROPSTRING *LPCDIPROPSTRING;
+
+#endif /* DIRECTINPUT_VERSION >= 0x050a */
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+#define MAXCPOINTSNUM          8
+
+typedef struct _CPOINT
+{
+    LONG  lP;     // raw value
+    DWORD dwLog;  // logical_value / max_logical_value * 10000
+} CPOINT, *PCPOINT;
+
+typedef struct DIPROPCPOINTS {
+    DIPROPHEADER diph;
+    DWORD  dwCPointsNum;
+    CPOINT cp[MAXCPOINTSNUM];
+} DIPROPCPOINTS, *LPDIPROPCPOINTS;
+typedef const DIPROPCPOINTS *LPCDIPROPCPOINTS;
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+
+#ifdef __cplusplus
+#define MAKEDIPROP(prop)    (*(const GUID *)(prop))
+#else
+#define MAKEDIPROP(prop)    ((REFGUID)(prop))
+#endif
+
+#define DIPROP_BUFFERSIZE       MAKEDIPROP(1)
+
+#define DIPROP_AXISMODE         MAKEDIPROP(2)
+
+#define DIPROPAXISMODE_ABS      0
+#define DIPROPAXISMODE_REL      1
+
+#define DIPROP_GRANULARITY      MAKEDIPROP(3)
+
+#define DIPROP_RANGE            MAKEDIPROP(4)
+
+#define DIPROP_DEADZONE         MAKEDIPROP(5)
+
+#define DIPROP_SATURATION       MAKEDIPROP(6)
+
+#define DIPROP_FFGAIN           MAKEDIPROP(7)
+
+#define DIPROP_FFLOAD           MAKEDIPROP(8)
+
+#define DIPROP_AUTOCENTER       MAKEDIPROP(9)
+
+#define DIPROPAUTOCENTER_OFF    0
+#define DIPROPAUTOCENTER_ON     1
+
+#define DIPROP_CALIBRATIONMODE  MAKEDIPROP(10)
+
+#define DIPROPCALIBRATIONMODE_COOKED    0
+#define DIPROPCALIBRATIONMODE_RAW       1
+
+#if(DIRECTINPUT_VERSION >= 0x050a)
+#define DIPROP_CALIBRATION      MAKEDIPROP(11)
+
+#define DIPROP_GUIDANDPATH      MAKEDIPROP(12)
+
+#define DIPROP_INSTANCENAME     MAKEDIPROP(13)
+
+#define DIPROP_PRODUCTNAME      MAKEDIPROP(14)
+#endif /* DIRECTINPUT_VERSION >= 0x050a */
+
+#if(DIRECTINPUT_VERSION >= 0x05b2)
+#define DIPROP_JOYSTICKID       MAKEDIPROP(15)
+
+#define DIPROP_GETPORTDISPLAYNAME       MAKEDIPROP(16)
+
+#endif /* DIRECTINPUT_VERSION >= 0x05b2 */
+
+#if(DIRECTINPUT_VERSION >= 0x0700)
+#define DIPROP_PHYSICALRANGE            MAKEDIPROP(18)
+
+#define DIPROP_LOGICALRANGE             MAKEDIPROP(19)
+#endif /* DIRECTINPUT_VERSION >= 0x0700 */
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+#define DIPROP_KEYNAME                     MAKEDIPROP(20)
+
+#define DIPROP_CPOINTS                 MAKEDIPROP(21)
+
+#define DIPROP_APPDATA       MAKEDIPROP(22)
+
+#define DIPROP_SCANCODE      MAKEDIPROP(23)
+
+#define DIPROP_VIDPID           MAKEDIPROP(24)
+
+#define DIPROP_USERNAME         MAKEDIPROP(25)
+
+#define DIPROP_TYPENAME         MAKEDIPROP(26)
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+
+typedef struct DIDEVICEOBJECTDATA_DX3 {
+    DWORD       dwOfs;
+    DWORD       dwData;
+    DWORD       dwTimeStamp;
+    DWORD       dwSequence;
+} DIDEVICEOBJECTDATA_DX3, *LPDIDEVICEOBJECTDATA_DX3;
+typedef const DIDEVICEOBJECTDATA_DX3 *LPCDIDEVICEOBJECTDATA_DX;
+
+typedef struct DIDEVICEOBJECTDATA {
+    DWORD       dwOfs;
+    DWORD       dwData;
+    DWORD       dwTimeStamp;
+    DWORD       dwSequence;
+#if(DIRECTINPUT_VERSION >= 0x0800)
+    UINT_PTR    uAppData;
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA;
+typedef const DIDEVICEOBJECTDATA *LPCDIDEVICEOBJECTDATA;
+
+#define DIGDD_PEEK          0x00000001
+
+#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \
+                        ((int)((dwSequence1) - (dwSequence2)) cmp 0)
+#define DISCL_EXCLUSIVE     0x00000001
+#define DISCL_NONEXCLUSIVE  0x00000002
+#define DISCL_FOREGROUND    0x00000004
+#define DISCL_BACKGROUND    0x00000008
+#define DISCL_NOWINKEY      0x00000010
+
+#if(DIRECTINPUT_VERSION >= 0x0500)
+/* These structures are defined for DirectX 3.0 compatibility */
+
+typedef struct DIDEVICEINSTANCE_DX3A {
+    DWORD   dwSize;
+    GUID    guidInstance;
+    GUID    guidProduct;
+    DWORD   dwDevType;
+    CHAR    tszInstanceName[MAX_PATH];
+    CHAR    tszProductName[MAX_PATH];
+} DIDEVICEINSTANCE_DX3A, *LPDIDEVICEINSTANCE_DX3A;
+typedef struct DIDEVICEINSTANCE_DX3W {
+    DWORD   dwSize;
+    GUID    guidInstance;
+    GUID    guidProduct;
+    DWORD   dwDevType;
+    WCHAR   tszInstanceName[MAX_PATH];
+    WCHAR   tszProductName[MAX_PATH];
+} DIDEVICEINSTANCE_DX3W, *LPDIDEVICEINSTANCE_DX3W;
+#ifdef UNICODE
+typedef DIDEVICEINSTANCE_DX3W DIDEVICEINSTANCE_DX3;
+typedef LPDIDEVICEINSTANCE_DX3W LPDIDEVICEINSTANCE_DX3;
+#else
+typedef DIDEVICEINSTANCE_DX3A DIDEVICEINSTANCE_DX3;
+typedef LPDIDEVICEINSTANCE_DX3A LPDIDEVICEINSTANCE_DX3;
+#endif // UNICODE
+typedef const DIDEVICEINSTANCE_DX3A *LPCDIDEVICEINSTANCE_DX3A;
+typedef const DIDEVICEINSTANCE_DX3W *LPCDIDEVICEINSTANCE_DX3W;
+typedef const DIDEVICEINSTANCE_DX3  *LPCDIDEVICEINSTANCE_DX3;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+
+typedef struct DIDEVICEINSTANCEA {
+    DWORD   dwSize;
+    GUID    guidInstance;
+    GUID    guidProduct;
+    DWORD   dwDevType;
+    CHAR    tszInstanceName[MAX_PATH];
+    CHAR    tszProductName[MAX_PATH];
+#if(DIRECTINPUT_VERSION >= 0x0500)
+    GUID    guidFFDriver;
+    WORD    wUsagePage;
+    WORD    wUsage;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA;
+typedef struct DIDEVICEINSTANCEW {
+    DWORD   dwSize;
+    GUID    guidInstance;
+    GUID    guidProduct;
+    DWORD   dwDevType;
+    WCHAR   tszInstanceName[MAX_PATH];
+    WCHAR   tszProductName[MAX_PATH];
+#if(DIRECTINPUT_VERSION >= 0x0500)
+    GUID    guidFFDriver;
+    WORD    wUsagePage;
+    WORD    wUsage;
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW;
+#ifdef UNICODE
+typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE;
+typedef LPDIDEVICEINSTANCEW LPDIDEVICEINSTANCE;
+#else
+typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE;
+typedef LPDIDEVICEINSTANCEA LPDIDEVICEINSTANCE;
+#endif // UNICODE
+
+typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA;
+typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW;
+#ifdef UNICODE
+typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE;
+typedef LPCDIDEVICEINSTANCEW LPCDIDEVICEINSTANCE;
+#else
+typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE;
+typedef LPCDIDEVICEINSTANCEA LPCDIDEVICEINSTANCE;
+#endif // UNICODE
+typedef const DIDEVICEINSTANCE  *LPCDIDEVICEINSTANCE;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDeviceW
+
+DECLARE_INTERFACE_(IDirectInputDeviceW, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDeviceW methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+};
+
+typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDeviceA
+
+DECLARE_INTERFACE_(IDirectInputDeviceA, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDeviceA methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+};
+
+typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA;
+
+#ifdef UNICODE
+#define IID_IDirectInputDevice IID_IDirectInputDeviceW
+#define IDirectInputDevice IDirectInputDeviceW
+#define IDirectInputDeviceVtbl IDirectInputDeviceWVtbl
+#else
+#define IID_IDirectInputDevice IID_IDirectInputDeviceA
+#define IDirectInputDevice IDirectInputDeviceA
+#define IDirectInputDeviceVtbl IDirectInputDeviceAVtbl
+#endif
+typedef struct IDirectInputDevice *LPDIRECTINPUTDEVICE;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p)
+#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#else
+#define IDirectInputDevice_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputDevice_AddRef(p) (p)->AddRef()
+#define IDirectInputDevice_Release(p) (p)->Release()
+#define IDirectInputDevice_GetCapabilities(p,a) (p)->GetCapabilities(a)
+#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c)
+#define IDirectInputDevice_GetProperty(p,a,b) (p)->GetProperty(a,b)
+#define IDirectInputDevice_SetProperty(p,a,b) (p)->SetProperty(a,b)
+#define IDirectInputDevice_Acquire(p) (p)->Acquire()
+#define IDirectInputDevice_Unacquire(p) (p)->Unacquire()
+#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b)
+#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d)
+#define IDirectInputDevice_SetDataFormat(p,a) (p)->SetDataFormat(a)
+#define IDirectInputDevice_SetEventNotification(p,a) (p)->SetEventNotification(a)
+#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c)
+#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a)
+#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+#define IDirectInputDevice_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+#endif
+
+#endif /* DIJ_RINGZERO */
+
+
+#if(DIRECTINPUT_VERSION >= 0x0500)
+
+#define DISFFC_RESET            0x00000001
+#define DISFFC_STOPALL          0x00000002
+#define DISFFC_PAUSE            0x00000004
+#define DISFFC_CONTINUE         0x00000008
+#define DISFFC_SETACTUATORSON   0x00000010
+#define DISFFC_SETACTUATORSOFF  0x00000020
+
+#define DIGFFS_EMPTY            0x00000001
+#define DIGFFS_STOPPED          0x00000002
+#define DIGFFS_PAUSED           0x00000004
+#define DIGFFS_ACTUATORSON      0x00000010
+#define DIGFFS_ACTUATORSOFF     0x00000020
+#define DIGFFS_POWERON          0x00000040
+#define DIGFFS_POWEROFF         0x00000080
+#define DIGFFS_SAFETYSWITCHON   0x00000100
+#define DIGFFS_SAFETYSWITCHOFF  0x00000200
+#define DIGFFS_USERFFSWITCHON   0x00000400
+#define DIGFFS_USERFFSWITCHOFF  0x00000800
+#define DIGFFS_DEVICELOST       0x80000000
+
+#ifndef DIJ_RINGZERO
+
+typedef struct DIEFFECTINFOA {
+    DWORD   dwSize;
+    GUID    guid;
+    DWORD   dwEffType;
+    DWORD   dwStaticParams;
+    DWORD   dwDynamicParams;
+    CHAR    tszName[MAX_PATH];
+} DIEFFECTINFOA, *LPDIEFFECTINFOA;
+typedef struct DIEFFECTINFOW {
+    DWORD   dwSize;
+    GUID    guid;
+    DWORD   dwEffType;
+    DWORD   dwStaticParams;
+    DWORD   dwDynamicParams;
+    WCHAR   tszName[MAX_PATH];
+} DIEFFECTINFOW, *LPDIEFFECTINFOW;
+#ifdef UNICODE
+typedef DIEFFECTINFOW DIEFFECTINFO;
+typedef LPDIEFFECTINFOW LPDIEFFECTINFO;
+#else
+typedef DIEFFECTINFOA DIEFFECTINFO;
+typedef LPDIEFFECTINFOA LPDIEFFECTINFO;
+#endif // UNICODE
+typedef const DIEFFECTINFOA *LPCDIEFFECTINFOA;
+typedef const DIEFFECTINFOW *LPCDIEFFECTINFOW;
+typedef const DIEFFECTINFO  *LPCDIEFFECTINFO;
+
+#define DISDD_CONTINUE          0x00000001
+
+typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSCALLBACKA)(LPCDIEFFECTINFOA, LPVOID);
+typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSCALLBACKW)(LPCDIEFFECTINFOW, LPVOID);
+#ifdef UNICODE
+#define LPDIENUMEFFECTSCALLBACK  LPDIENUMEFFECTSCALLBACKW
+#else
+#define LPDIENUMEFFECTSCALLBACK  LPDIENUMEFFECTSCALLBACKA
+#endif // !UNICODE
+typedef BOOL (FAR PASCAL * LPDIENUMCREATEDEFFECTOBJECTSCALLBACK)(LPDIRECTINPUTEFFECT, LPVOID);
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDevice2W
+
+DECLARE_INTERFACE_(IDirectInputDevice2W, IDirectInputDeviceW)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDeviceW methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+
+    /*** IDirectInputDevice2W methods ***/
+    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
+    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+    STDMETHOD(Poll)(THIS) PURE;
+    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+};
+
+typedef struct IDirectInputDevice2W *LPDIRECTINPUTDEVICE2W;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDevice2A
+
+DECLARE_INTERFACE_(IDirectInputDevice2A, IDirectInputDeviceA)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDeviceA methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+
+    /*** IDirectInputDevice2A methods ***/
+    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
+    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+    STDMETHOD(Poll)(THIS) PURE;
+    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+};
+
+typedef struct IDirectInputDevice2A *LPDIRECTINPUTDEVICE2A;
+
+#ifdef UNICODE
+#define IID_IDirectInputDevice2 IID_IDirectInputDevice2W
+#define IDirectInputDevice2 IDirectInputDevice2W
+#define IDirectInputDevice2Vtbl IDirectInputDevice2WVtbl
+#else
+#define IID_IDirectInputDevice2 IID_IDirectInputDevice2A
+#define IDirectInputDevice2 IDirectInputDevice2A
+#define IDirectInputDevice2Vtbl IDirectInputDevice2AVtbl
+#endif
+typedef struct IDirectInputDevice2 *LPDIRECTINPUTDEVICE2;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputDevice2_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputDevice2_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputDevice2_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+#define IDirectInputDevice2_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+#define IDirectInputDevice2_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+#define IDirectInputDevice2_Acquire(p) (p)->lpVtbl->Acquire(p)
+#define IDirectInputDevice2_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+#define IDirectInputDevice2_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+#define IDirectInputDevice2_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d)
+#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c)
+#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b)
+#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a)
+#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a)
+#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c)
+#define IDirectInputDevice2_Escape(p,a) (p)->lpVtbl->Escape(p,a)
+#define IDirectInputDevice2_Poll(p) (p)->lpVtbl->Poll(p)
+#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d)
+#else
+#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputDevice2_AddRef(p) (p)->AddRef()
+#define IDirectInputDevice2_Release(p) (p)->Release()
+#define IDirectInputDevice2_GetCapabilities(p,a) (p)->GetCapabilities(a)
+#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c)
+#define IDirectInputDevice2_GetProperty(p,a,b) (p)->GetProperty(a,b)
+#define IDirectInputDevice2_SetProperty(p,a,b) (p)->SetProperty(a,b)
+#define IDirectInputDevice2_Acquire(p) (p)->Acquire()
+#define IDirectInputDevice2_Unacquire(p) (p)->Unacquire()
+#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b)
+#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d)
+#define IDirectInputDevice2_SetDataFormat(p,a) (p)->SetDataFormat(a)
+#define IDirectInputDevice2_SetEventNotification(p,a) (p)->SetEventNotification(a)
+#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c)
+#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a)
+#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d)
+#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c)
+#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b)
+#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a)
+#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a)
+#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c)
+#define IDirectInputDevice2_Escape(p,a) (p)->Escape(a)
+#define IDirectInputDevice2_Poll(p) (p)->Poll()
+#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d)
+#endif
+
+#endif /* DIJ_RINGZERO */
+
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+
+#if(DIRECTINPUT_VERSION >= 0x0700)
+#define DIFEF_DEFAULT               0x00000000
+#define DIFEF_INCLUDENONSTANDARD    0x00000001
+#define DIFEF_MODIFYIFNEEDED            0x00000010
+
+#ifndef DIJ_RINGZERO
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDevice7W
+
+DECLARE_INTERFACE_(IDirectInputDevice7W, IDirectInputDevice2W)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDevice2W methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
+    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+    STDMETHOD(Poll)(THIS) PURE;
+    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+
+    /*** IDirectInputDevice7W methods ***/
+    STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE;
+};
+
+typedef struct IDirectInputDevice7W *LPDIRECTINPUTDEVICE7W;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDevice7A
+
+DECLARE_INTERFACE_(IDirectInputDevice7A, IDirectInputDevice2A)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDevice2A methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
+    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+    STDMETHOD(Poll)(THIS) PURE;
+    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+
+    /*** IDirectInputDevice7A methods ***/
+    STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE;
+};
+
+typedef struct IDirectInputDevice7A *LPDIRECTINPUTDEVICE7A;
+
+#ifdef UNICODE
+#define IID_IDirectInputDevice7 IID_IDirectInputDevice7W
+#define IDirectInputDevice7 IDirectInputDevice7W
+#define IDirectInputDevice7Vtbl IDirectInputDevice7WVtbl
+#else
+#define IID_IDirectInputDevice7 IID_IDirectInputDevice7A
+#define IDirectInputDevice7 IDirectInputDevice7A
+#define IDirectInputDevice7Vtbl IDirectInputDevice7AVtbl
+#endif
+typedef struct IDirectInputDevice7 *LPDIRECTINPUTDEVICE7;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputDevice7_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputDevice7_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputDevice7_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+#define IDirectInputDevice7_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+#define IDirectInputDevice7_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+#define IDirectInputDevice7_Acquire(p) (p)->lpVtbl->Acquire(p)
+#define IDirectInputDevice7_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+#define IDirectInputDevice7_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+#define IDirectInputDevice7_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d)
+#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c)
+#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b)
+#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a)
+#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a)
+#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c)
+#define IDirectInputDevice7_Escape(p,a) (p)->lpVtbl->Escape(p,a)
+#define IDirectInputDevice7_Poll(p) (p)->lpVtbl->Poll(p)
+#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d)
+#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d)
+#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d)
+#else
+#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputDevice7_AddRef(p) (p)->AddRef()
+#define IDirectInputDevice7_Release(p) (p)->Release()
+#define IDirectInputDevice7_GetCapabilities(p,a) (p)->GetCapabilities(a)
+#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c)
+#define IDirectInputDevice7_GetProperty(p,a,b) (p)->GetProperty(a,b)
+#define IDirectInputDevice7_SetProperty(p,a,b) (p)->SetProperty(a,b)
+#define IDirectInputDevice7_Acquire(p) (p)->Acquire()
+#define IDirectInputDevice7_Unacquire(p) (p)->Unacquire()
+#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b)
+#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d)
+#define IDirectInputDevice7_SetDataFormat(p,a) (p)->SetDataFormat(a)
+#define IDirectInputDevice7_SetEventNotification(p,a) (p)->SetEventNotification(a)
+#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c)
+#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a)
+#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d)
+#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c)
+#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b)
+#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a)
+#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a)
+#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c)
+#define IDirectInputDevice7_Escape(p,a) (p)->Escape(a)
+#define IDirectInputDevice7_Poll(p) (p)->Poll()
+#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d)
+#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d)
+#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d)
+#endif
+
+#endif /* DIJ_RINGZERO */
+
+#endif /* DIRECTINPUT_VERSION >= 0x0700 */
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+
+#ifndef DIJ_RINGZERO
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDevice8W
+
+DECLARE_INTERFACE_(IDirectInputDevice8W, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDevice8W methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
+    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+    STDMETHOD(Poll)(THIS) PURE;
+    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE;
+    STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATW,LPCWSTR,DWORD) PURE;
+    STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATW,LPCWSTR,DWORD) PURE;
+    STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERW) PURE;
+};
+
+typedef struct IDirectInputDevice8W *LPDIRECTINPUTDEVICE8W;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDevice8A
+
+DECLARE_INTERFACE_(IDirectInputDevice8A, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDevice8A methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
+    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+    STDMETHOD(Poll)(THIS) PURE;
+    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE;
+    STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATA,LPCSTR,DWORD) PURE;
+    STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATA,LPCSTR,DWORD) PURE;
+    STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERA) PURE;
+};
+
+typedef struct IDirectInputDevice8A *LPDIRECTINPUTDEVICE8A;
+
+#ifdef UNICODE
+#define IID_IDirectInputDevice8 IID_IDirectInputDevice8W
+#define IDirectInputDevice8 IDirectInputDevice8W
+#define IDirectInputDevice8Vtbl IDirectInputDevice8WVtbl
+#else
+#define IID_IDirectInputDevice8 IID_IDirectInputDevice8A
+#define IDirectInputDevice8 IDirectInputDevice8A
+#define IDirectInputDevice8Vtbl IDirectInputDevice8AVtbl
+#endif
+typedef struct IDirectInputDevice8 *LPDIRECTINPUTDEVICE8;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputDevice8_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputDevice8_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputDevice8_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+#define IDirectInputDevice8_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+#define IDirectInputDevice8_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+#define IDirectInputDevice8_Acquire(p) (p)->lpVtbl->Acquire(p)
+#define IDirectInputDevice8_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+#define IDirectInputDevice8_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+#define IDirectInputDevice8_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d)
+#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c)
+#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b)
+#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a)
+#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a)
+#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c)
+#define IDirectInputDevice8_Escape(p,a) (p)->lpVtbl->Escape(p,a)
+#define IDirectInputDevice8_Poll(p) (p)->lpVtbl->Poll(p)
+#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d)
+#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d)
+#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d)
+#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->lpVtbl->BuildActionMap(p,a,b,c)
+#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->lpVtbl->SetActionMap(p,a,b,c)
+#define IDirectInputDevice8_GetImageInfo(p,a) (p)->lpVtbl->GetImageInfo(p,a)
+#else
+#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputDevice8_AddRef(p) (p)->AddRef()
+#define IDirectInputDevice8_Release(p) (p)->Release()
+#define IDirectInputDevice8_GetCapabilities(p,a) (p)->GetCapabilities(a)
+#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c)
+#define IDirectInputDevice8_GetProperty(p,a,b) (p)->GetProperty(a,b)
+#define IDirectInputDevice8_SetProperty(p,a,b) (p)->SetProperty(a,b)
+#define IDirectInputDevice8_Acquire(p) (p)->Acquire()
+#define IDirectInputDevice8_Unacquire(p) (p)->Unacquire()
+#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b)
+#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d)
+#define IDirectInputDevice8_SetDataFormat(p,a) (p)->SetDataFormat(a)
+#define IDirectInputDevice8_SetEventNotification(p,a) (p)->SetEventNotification(a)
+#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c)
+#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a)
+#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d)
+#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c)
+#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b)
+#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a)
+#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a)
+#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c)
+#define IDirectInputDevice8_Escape(p,a) (p)->Escape(a)
+#define IDirectInputDevice8_Poll(p) (p)->Poll()
+#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d)
+#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d)
+#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d)
+#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->BuildActionMap(a,b,c)
+#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->SetActionMap(a,b,c)
+#define IDirectInputDevice8_GetImageInfo(p,a) (p)->GetImageInfo(a)
+#endif
+
+#endif /* DIJ_RINGZERO */
+
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+/****************************************************************************
+ *
+ *      Mouse
+ *
+ ****************************************************************************/
+
+#ifndef DIJ_RINGZERO
+
+typedef struct _DIMOUSESTATE {
+    LONG    lX;
+    LONG    lY;
+    LONG    lZ;
+    BYTE    rgbButtons[4];
+} DIMOUSESTATE, *LPDIMOUSESTATE;
+
+#if DIRECTINPUT_VERSION >= 0x0700
+typedef struct _DIMOUSESTATE2 {
+    LONG    lX;
+    LONG    lY;
+    LONG    lZ;
+    BYTE    rgbButtons[8];
+} DIMOUSESTATE2, *LPDIMOUSESTATE2;
+#endif
+
+
+#define DIMOFS_X        FIELD_OFFSET(DIMOUSESTATE, lX)
+#define DIMOFS_Y        FIELD_OFFSET(DIMOUSESTATE, lY)
+#define DIMOFS_Z        FIELD_OFFSET(DIMOUSESTATE, lZ)
+#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0)
+#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1)
+#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2)
+#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3)
+#if (DIRECTINPUT_VERSION >= 0x0700)
+#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4)
+#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5)
+#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6)
+#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7)
+#endif
+#endif /* DIJ_RINGZERO */
+
+/****************************************************************************
+ *
+ *      Keyboard
+ *
+ ****************************************************************************/
+
+#ifndef DIJ_RINGZERO
+
+/****************************************************************************
+ *
+ *      DirectInput keyboard scan codes
+ *
+ ****************************************************************************/
+#define DIK_ESCAPE          0x01
+#define DIK_1               0x02
+#define DIK_2               0x03
+#define DIK_3               0x04
+#define DIK_4               0x05
+#define DIK_5               0x06
+#define DIK_6               0x07
+#define DIK_7               0x08
+#define DIK_8               0x09
+#define DIK_9               0x0A
+#define DIK_0               0x0B
+#define DIK_MINUS           0x0C    /* - on main keyboard */
+#define DIK_EQUALS          0x0D
+#define DIK_BACK            0x0E    /* backspace */
+#define DIK_TAB             0x0F
+#define DIK_Q               0x10
+#define DIK_W               0x11
+#define DIK_E               0x12
+#define DIK_R               0x13
+#define DIK_T               0x14
+#define DIK_Y               0x15
+#define DIK_U               0x16
+#define DIK_I               0x17
+#define DIK_O               0x18
+#define DIK_P               0x19
+#define DIK_LBRACKET        0x1A
+#define DIK_RBRACKET        0x1B
+#define DIK_RETURN          0x1C    /* Enter on main keyboard */
+#define DIK_LCONTROL        0x1D
+#define DIK_A               0x1E
+#define DIK_S               0x1F
+#define DIK_D               0x20
+#define DIK_F               0x21
+#define DIK_G               0x22
+#define DIK_H               0x23
+#define DIK_J               0x24
+#define DIK_K               0x25
+#define DIK_L               0x26
+#define DIK_SEMICOLON       0x27
+#define DIK_APOSTROPHE      0x28
+#define DIK_GRAVE           0x29    /* accent grave */
+#define DIK_LSHIFT          0x2A
+#define DIK_BACKSLASH       0x2B
+#define DIK_Z               0x2C
+#define DIK_X               0x2D
+#define DIK_C               0x2E
+#define DIK_V               0x2F
+#define DIK_B               0x30
+#define DIK_N               0x31
+#define DIK_M               0x32
+#define DIK_COMMA           0x33
+#define DIK_PERIOD          0x34    /* . on main keyboard */
+#define DIK_SLASH           0x35    /* / on main keyboard */
+#define DIK_RSHIFT          0x36
+#define DIK_MULTIPLY        0x37    /* * on numeric keypad */
+#define DIK_LMENU           0x38    /* left Alt */
+#define DIK_SPACE           0x39
+#define DIK_CAPITAL         0x3A
+#define DIK_F1              0x3B
+#define DIK_F2              0x3C
+#define DIK_F3              0x3D
+#define DIK_F4              0x3E
+#define DIK_F5              0x3F
+#define DIK_F6              0x40
+#define DIK_F7              0x41
+#define DIK_F8              0x42
+#define DIK_F9              0x43
+#define DIK_F10             0x44
+#define DIK_NUMLOCK         0x45
+#define DIK_SCROLL          0x46    /* Scroll Lock */
+#define DIK_NUMPAD7         0x47
+#define DIK_NUMPAD8         0x48
+#define DIK_NUMPAD9         0x49
+#define DIK_SUBTRACT        0x4A    /* - on numeric keypad */
+#define DIK_NUMPAD4         0x4B
+#define DIK_NUMPAD5         0x4C
+#define DIK_NUMPAD6         0x4D
+#define DIK_ADD             0x4E    /* + on numeric keypad */
+#define DIK_NUMPAD1         0x4F
+#define DIK_NUMPAD2         0x50
+#define DIK_NUMPAD3         0x51
+#define DIK_NUMPAD0         0x52
+#define DIK_DECIMAL         0x53    /* . on numeric keypad */
+#define DIK_OEM_102         0x56    /* <> or \| on RT 102-key keyboard (Non-U.S.) */
+#define DIK_F11             0x57
+#define DIK_F12             0x58
+#define DIK_F13             0x64    /*                     (NEC PC98) */
+#define DIK_F14             0x65    /*                     (NEC PC98) */
+#define DIK_F15             0x66    /*                     (NEC PC98) */
+#define DIK_KANA            0x70    /* (Japanese keyboard)            */
+#define DIK_ABNT_C1         0x73    /* /? on Brazilian keyboard */
+#define DIK_CONVERT         0x79    /* (Japanese keyboard)            */
+#define DIK_NOCONVERT       0x7B    /* (Japanese keyboard)            */
+#define DIK_YEN             0x7D    /* (Japanese keyboard)            */
+#define DIK_ABNT_C2         0x7E    /* Numpad . on Brazilian keyboard */
+#define DIK_NUMPADEQUALS    0x8D    /* = on numeric keypad (NEC PC98) */
+#define DIK_PREVTRACK       0x90    /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */
+#define DIK_AT              0x91    /*                     (NEC PC98) */
+#define DIK_COLON           0x92    /*                     (NEC PC98) */
+#define DIK_UNDERLINE       0x93    /*                     (NEC PC98) */
+#define DIK_KANJI           0x94    /* (Japanese keyboard)            */
+#define DIK_STOP            0x95    /*                     (NEC PC98) */
+#define DIK_AX              0x96    /*                     (Japan AX) */
+#define DIK_UNLABELED       0x97    /*                        (J3100) */
+#define DIK_NEXTTRACK       0x99    /* Next Track */
+#define DIK_NUMPADENTER     0x9C    /* Enter on numeric keypad */
+#define DIK_RCONTROL        0x9D
+#define DIK_MUTE            0xA0    /* Mute */
+#define DIK_CALCULATOR      0xA1    /* Calculator */
+#define DIK_PLAYPAUSE       0xA2    /* Play / Pause */
+#define DIK_MEDIASTOP       0xA4    /* Media Stop */
+#define DIK_VOLUMEDOWN      0xAE    /* Volume - */
+#define DIK_VOLUMEUP        0xB0    /* Volume + */
+#define DIK_WEBHOME         0xB2    /* Web home */
+#define DIK_NUMPADCOMMA     0xB3    /* , on numeric keypad (NEC PC98) */
+#define DIK_DIVIDE          0xB5    /* / on numeric keypad */
+#define DIK_SYSRQ           0xB7
+#define DIK_RMENU           0xB8    /* right Alt */
+#define DIK_PAUSE           0xC5    /* Pause */
+#define DIK_HOME            0xC7    /* Home on arrow keypad */
+#define DIK_UP              0xC8    /* UpArrow on arrow keypad */
+#define DIK_PRIOR           0xC9    /* PgUp on arrow keypad */
+#define DIK_LEFT            0xCB    /* LeftArrow on arrow keypad */
+#define DIK_RIGHT           0xCD    /* RightArrow on arrow keypad */
+#define DIK_END             0xCF    /* End on arrow keypad */
+#define DIK_DOWN            0xD0    /* DownArrow on arrow keypad */
+#define DIK_NEXT            0xD1    /* PgDn on arrow keypad */
+#define DIK_INSERT          0xD2    /* Insert on arrow keypad */
+#define DIK_DELETE          0xD3    /* Delete on arrow keypad */
+#define DIK_LWIN            0xDB    /* Left Windows key */
+#define DIK_RWIN            0xDC    /* Right Windows key */
+#define DIK_APPS            0xDD    /* AppMenu key */
+#define DIK_POWER           0xDE    /* System Power */
+#define DIK_SLEEP           0xDF    /* System Sleep */
+#define DIK_WAKE            0xE3    /* System Wake */
+#define DIK_WEBSEARCH       0xE5    /* Web Search */
+#define DIK_WEBFAVORITES    0xE6    /* Web Favorites */
+#define DIK_WEBREFRESH      0xE7    /* Web Refresh */
+#define DIK_WEBSTOP         0xE8    /* Web Stop */
+#define DIK_WEBFORWARD      0xE9    /* Web Forward */
+#define DIK_WEBBACK         0xEA    /* Web Back */
+#define DIK_MYCOMPUTER      0xEB    /* My Computer */
+#define DIK_MAIL            0xEC    /* Mail */
+#define DIK_MEDIASELECT     0xED    /* Media Select */
+
+/*
+ *  Alternate names for keys, to facilitate transition from DOS.
+ */
+#define DIK_BACKSPACE       DIK_BACK            /* backspace */
+#define DIK_NUMPADSTAR      DIK_MULTIPLY        /* * on numeric keypad */
+#define DIK_LALT            DIK_LMENU           /* left Alt */
+#define DIK_CAPSLOCK        DIK_CAPITAL         /* CapsLock */
+#define DIK_NUMPADMINUS     DIK_SUBTRACT        /* - on numeric keypad */
+#define DIK_NUMPADPLUS      DIK_ADD             /* + on numeric keypad */
+#define DIK_NUMPADPERIOD    DIK_DECIMAL         /* . on numeric keypad */
+#define DIK_NUMPADSLASH     DIK_DIVIDE          /* / on numeric keypad */
+#define DIK_RALT            DIK_RMENU           /* right Alt */
+#define DIK_UPARROW         DIK_UP              /* UpArrow on arrow keypad */
+#define DIK_PGUP            DIK_PRIOR           /* PgUp on arrow keypad */
+#define DIK_LEFTARROW       DIK_LEFT            /* LeftArrow on arrow keypad */
+#define DIK_RIGHTARROW      DIK_RIGHT           /* RightArrow on arrow keypad */
+#define DIK_DOWNARROW       DIK_DOWN            /* DownArrow on arrow keypad */
+#define DIK_PGDN            DIK_NEXT            /* PgDn on arrow keypad */
+
+/*
+ *  Alternate names for keys originally not used on US keyboards.
+ */
+#define DIK_CIRCUMFLEX      DIK_PREVTRACK       /* Japanese keyboard */
+
+#endif /* DIJ_RINGZERO */
+
+/****************************************************************************
+ *
+ *      Joystick
+ *
+ ****************************************************************************/
+
+#ifndef DIJ_RINGZERO
+
+typedef struct DIJOYSTATE {
+    LONG    lX;                     /* x-axis position              */
+    LONG    lY;                     /* y-axis position              */
+    LONG    lZ;                     /* z-axis position              */
+    LONG    lRx;                    /* x-axis rotation              */
+    LONG    lRy;                    /* y-axis rotation              */
+    LONG    lRz;                    /* z-axis rotation              */
+    LONG    rglSlider[2];           /* extra axes positions         */
+    DWORD   rgdwPOV[4];             /* POV directions               */
+    BYTE    rgbButtons[32];         /* 32 buttons                   */
+} DIJOYSTATE, *LPDIJOYSTATE;
+
+typedef struct DIJOYSTATE2 {
+    LONG    lX;                     /* x-axis position              */
+    LONG    lY;                     /* y-axis position              */
+    LONG    lZ;                     /* z-axis position              */
+    LONG    lRx;                    /* x-axis rotation              */
+    LONG    lRy;                    /* y-axis rotation              */
+    LONG    lRz;                    /* z-axis rotation              */
+    LONG    rglSlider[2];           /* extra axes positions         */
+    DWORD   rgdwPOV[4];             /* POV directions               */
+    BYTE    rgbButtons[128];        /* 128 buttons                  */
+    LONG    lVX;                    /* x-axis velocity              */
+    LONG    lVY;                    /* y-axis velocity              */
+    LONG    lVZ;                    /* z-axis velocity              */
+    LONG    lVRx;                   /* x-axis angular velocity      */
+    LONG    lVRy;                   /* y-axis angular velocity      */
+    LONG    lVRz;                   /* z-axis angular velocity      */
+    LONG    rglVSlider[2];          /* extra axes velocities        */
+    LONG    lAX;                    /* x-axis acceleration          */
+    LONG    lAY;                    /* y-axis acceleration          */
+    LONG    lAZ;                    /* z-axis acceleration          */
+    LONG    lARx;                   /* x-axis angular acceleration  */
+    LONG    lARy;                   /* y-axis angular acceleration  */
+    LONG    lARz;                   /* z-axis angular acceleration  */
+    LONG    rglASlider[2];          /* extra axes accelerations     */
+    LONG    lFX;                    /* x-axis force                 */
+    LONG    lFY;                    /* y-axis force                 */
+    LONG    lFZ;                    /* z-axis force                 */
+    LONG    lFRx;                   /* x-axis torque                */
+    LONG    lFRy;                   /* y-axis torque                */
+    LONG    lFRz;                   /* z-axis torque                */
+    LONG    rglFSlider[2];          /* extra axes forces            */
+} DIJOYSTATE2, *LPDIJOYSTATE2;
+
+#define DIJOFS_X            FIELD_OFFSET(DIJOYSTATE, lX)
+#define DIJOFS_Y            FIELD_OFFSET(DIJOYSTATE, lY)
+#define DIJOFS_Z            FIELD_OFFSET(DIJOYSTATE, lZ)
+#define DIJOFS_RX           FIELD_OFFSET(DIJOYSTATE, lRx)
+#define DIJOFS_RY           FIELD_OFFSET(DIJOYSTATE, lRy)
+#define DIJOFS_RZ           FIELD_OFFSET(DIJOYSTATE, lRz)
+#define DIJOFS_SLIDER(n)   (FIELD_OFFSET(DIJOYSTATE, rglSlider) + \
+                                                        (n) * sizeof(LONG))
+#define DIJOFS_POV(n)      (FIELD_OFFSET(DIJOYSTATE, rgdwPOV) + \
+                                                        (n) * sizeof(DWORD))
+#define DIJOFS_BUTTON(n)   (FIELD_OFFSET(DIJOYSTATE, rgbButtons) + (n))
+#define DIJOFS_BUTTON0      DIJOFS_BUTTON(0)
+#define DIJOFS_BUTTON1      DIJOFS_BUTTON(1)
+#define DIJOFS_BUTTON2      DIJOFS_BUTTON(2)
+#define DIJOFS_BUTTON3      DIJOFS_BUTTON(3)
+#define DIJOFS_BUTTON4      DIJOFS_BUTTON(4)
+#define DIJOFS_BUTTON5      DIJOFS_BUTTON(5)
+#define DIJOFS_BUTTON6      DIJOFS_BUTTON(6)
+#define DIJOFS_BUTTON7      DIJOFS_BUTTON(7)
+#define DIJOFS_BUTTON8      DIJOFS_BUTTON(8)
+#define DIJOFS_BUTTON9      DIJOFS_BUTTON(9)
+#define DIJOFS_BUTTON10     DIJOFS_BUTTON(10)
+#define DIJOFS_BUTTON11     DIJOFS_BUTTON(11)
+#define DIJOFS_BUTTON12     DIJOFS_BUTTON(12)
+#define DIJOFS_BUTTON13     DIJOFS_BUTTON(13)
+#define DIJOFS_BUTTON14     DIJOFS_BUTTON(14)
+#define DIJOFS_BUTTON15     DIJOFS_BUTTON(15)
+#define DIJOFS_BUTTON16     DIJOFS_BUTTON(16)
+#define DIJOFS_BUTTON17     DIJOFS_BUTTON(17)
+#define DIJOFS_BUTTON18     DIJOFS_BUTTON(18)
+#define DIJOFS_BUTTON19     DIJOFS_BUTTON(19)
+#define DIJOFS_BUTTON20     DIJOFS_BUTTON(20)
+#define DIJOFS_BUTTON21     DIJOFS_BUTTON(21)
+#define DIJOFS_BUTTON22     DIJOFS_BUTTON(22)
+#define DIJOFS_BUTTON23     DIJOFS_BUTTON(23)
+#define DIJOFS_BUTTON24     DIJOFS_BUTTON(24)
+#define DIJOFS_BUTTON25     DIJOFS_BUTTON(25)
+#define DIJOFS_BUTTON26     DIJOFS_BUTTON(26)
+#define DIJOFS_BUTTON27     DIJOFS_BUTTON(27)
+#define DIJOFS_BUTTON28     DIJOFS_BUTTON(28)
+#define DIJOFS_BUTTON29     DIJOFS_BUTTON(29)
+#define DIJOFS_BUTTON30     DIJOFS_BUTTON(30)
+#define DIJOFS_BUTTON31     DIJOFS_BUTTON(31)
+
+
+#endif /* DIJ_RINGZERO */
+
+/****************************************************************************
+ *
+ *  IDirectInput
+ *
+ ****************************************************************************/
+
+#ifndef DIJ_RINGZERO
+
+#define DIENUM_STOP             0
+#define DIENUM_CONTINUE         1
+
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA, LPVOID);
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW, LPVOID);
+#ifdef UNICODE
+#define LPDIENUMDEVICESCALLBACK  LPDIENUMDEVICESCALLBACKW
+#else
+#define LPDIENUMDEVICESCALLBACK  LPDIENUMDEVICESCALLBACKA
+#endif // !UNICODE
+typedef BOOL (FAR PASCAL * LPDICONFIGUREDEVICESCALLBACK)(IUnknown FAR *, LPVOID);
+
+#define DIEDFL_ALLDEVICES       0x00000000
+#define DIEDFL_ATTACHEDONLY     0x00000001
+#if(DIRECTINPUT_VERSION >= 0x0500)
+#define DIEDFL_FORCEFEEDBACK    0x00000100
+#endif /* DIRECTINPUT_VERSION >= 0x0500 */
+#if(DIRECTINPUT_VERSION >= 0x050a)
+#define DIEDFL_INCLUDEALIASES   0x00010000
+#define DIEDFL_INCLUDEPHANTOMS  0x00020000
+#endif /* DIRECTINPUT_VERSION >= 0x050a */
+#if(DIRECTINPUT_VERSION >= 0x0800)
+#define DIEDFL_INCLUDEHIDDEN    0x00040000
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICESBYSEMANTICSCBA)(LPCDIDEVICEINSTANCEA, LPDIRECTINPUTDEVICE8A, DWORD, DWORD, LPVOID);
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICESBYSEMANTICSCBW)(LPCDIDEVICEINSTANCEW, LPDIRECTINPUTDEVICE8W, DWORD, DWORD, LPVOID);
+#ifdef UNICODE
+#define LPDIENUMDEVICESBYSEMANTICSCB  LPDIENUMDEVICESBYSEMANTICSCBW
+#else
+#define LPDIENUMDEVICESBYSEMANTICSCB  LPDIENUMDEVICESBYSEMANTICSCBA
+#endif // !UNICODE
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+#define DIEDBS_MAPPEDPRI1         0x00000001
+#define DIEDBS_MAPPEDPRI2         0x00000002
+#define DIEDBS_RECENTDEVICE       0x00000010
+#define DIEDBS_NEWDEVICE          0x00000020
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+#define DIEDBSFL_ATTACHEDONLY       0x00000000
+#define DIEDBSFL_THISUSER           0x00000010
+#define DIEDBSFL_FORCEFEEDBACK      DIEDFL_FORCEFEEDBACK
+#define DIEDBSFL_AVAILABLEDEVICES   0x00001000
+#define DIEDBSFL_MULTIMICEKEYBOARDS 0x00002000
+#define DIEDBSFL_NONGAMINGDEVICES   0x00004000
+#define DIEDBSFL_VALID              0x00007110
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+#undef INTERFACE
+#define INTERFACE IDirectInputW
+
+DECLARE_INTERFACE_(IDirectInputW, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputW methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+};
+
+typedef struct IDirectInputW *LPDIRECTINPUTW;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputA
+
+DECLARE_INTERFACE_(IDirectInputA, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputA methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+};
+
+typedef struct IDirectInputA *LPDIRECTINPUTA;
+
+#ifdef UNICODE
+#define IID_IDirectInput IID_IDirectInputW
+#define IDirectInput IDirectInputW
+#define IDirectInputVtbl IDirectInputWVtbl
+#else
+#define IID_IDirectInput IID_IDirectInputA
+#define IDirectInput IDirectInputA
+#define IDirectInputVtbl IDirectInputAVtbl
+#endif
+typedef struct IDirectInput *LPDIRECTINPUT;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInput_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+#else
+#define IDirectInput_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInput_AddRef(p) (p)->AddRef()
+#define IDirectInput_Release(p) (p)->Release()
+#define IDirectInput_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d)
+#define IDirectInput_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a)
+#define IDirectInput_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+#define IDirectInput_Initialize(p,a,b) (p)->Initialize(a,b)
+#endif
+
+#undef INTERFACE
+#define INTERFACE IDirectInput2W
+
+DECLARE_INTERFACE_(IDirectInput2W, IDirectInputW)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputW methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+
+    /*** IDirectInput2W methods ***/
+    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE;
+};
+
+typedef struct IDirectInput2W *LPDIRECTINPUT2W;
+
+#undef INTERFACE
+#define INTERFACE IDirectInput2A
+
+DECLARE_INTERFACE_(IDirectInput2A, IDirectInputA)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputA methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+
+    /*** IDirectInput2A methods ***/
+    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE;
+};
+
+typedef struct IDirectInput2A *LPDIRECTINPUT2A;
+
+#ifdef UNICODE
+#define IID_IDirectInput2 IID_IDirectInput2W
+#define IDirectInput2 IDirectInput2W
+#define IDirectInput2Vtbl IDirectInput2WVtbl
+#else
+#define IID_IDirectInput2 IID_IDirectInput2A
+#define IDirectInput2 IDirectInput2A
+#define IDirectInput2Vtbl IDirectInput2AVtbl
+#endif
+typedef struct IDirectInput2 *LPDIRECTINPUT2;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInput2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInput2_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInput2_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInput2_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+#define IDirectInput2_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+#define IDirectInput2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInput2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectInput2_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c)
+#else
+#define IDirectInput2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInput2_AddRef(p) (p)->AddRef()
+#define IDirectInput2_Release(p) (p)->Release()
+#define IDirectInput2_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d)
+#define IDirectInput2_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a)
+#define IDirectInput2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+#define IDirectInput2_Initialize(p,a,b) (p)->Initialize(a,b)
+#define IDirectInput2_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c)
+#endif
+
+
+#undef INTERFACE
+#define INTERFACE IDirectInput7W
+
+DECLARE_INTERFACE_(IDirectInput7W, IDirectInput2W)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInput2W methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE;
+
+    /*** IDirectInput7W methods ***/
+    STDMETHOD(CreateDeviceEx)(THIS_ REFGUID,REFIID,LPVOID *,LPUNKNOWN) PURE;
+};
+
+typedef struct IDirectInput7W *LPDIRECTINPUT7W;
+
+#undef INTERFACE
+#define INTERFACE IDirectInput7A
+
+DECLARE_INTERFACE_(IDirectInput7A, IDirectInput2A)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInput2A methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE;
+
+    /*** IDirectInput7A methods ***/
+    STDMETHOD(CreateDeviceEx)(THIS_ REFGUID,REFIID,LPVOID *,LPUNKNOWN) PURE;
+};
+
+typedef struct IDirectInput7A *LPDIRECTINPUT7A;
+
+#ifdef UNICODE
+#define IID_IDirectInput7 IID_IDirectInput7W
+#define IDirectInput7 IDirectInput7W
+#define IDirectInput7Vtbl IDirectInput7WVtbl
+#else
+#define IID_IDirectInput7 IID_IDirectInput7A
+#define IDirectInput7 IDirectInput7A
+#define IDirectInput7Vtbl IDirectInput7AVtbl
+#endif
+typedef struct IDirectInput7 *LPDIRECTINPUT7;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInput7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInput7_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInput7_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInput7_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+#define IDirectInput7_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+#define IDirectInput7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInput7_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectInput7_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c)
+#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d)
+#else
+#define IDirectInput7_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInput7_AddRef(p) (p)->AddRef()
+#define IDirectInput7_Release(p) (p)->Release()
+#define IDirectInput7_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d)
+#define IDirectInput7_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a)
+#define IDirectInput7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+#define IDirectInput7_Initialize(p,a,b) (p)->Initialize(a,b)
+#define IDirectInput7_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c)
+#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->CreateDeviceEx(a,b,c,d)
+#endif
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+#undef INTERFACE
+#define INTERFACE IDirectInput8W
+
+DECLARE_INTERFACE_(IDirectInput8W, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInput8W methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICE8W *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE;
+    STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCWSTR,LPDIACTIONFORMATW,LPDIENUMDEVICESBYSEMANTICSCBW,LPVOID,DWORD) PURE;
+    STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK,LPDICONFIGUREDEVICESPARAMSW,DWORD,LPVOID) PURE;
+};
+
+typedef struct IDirectInput8W *LPDIRECTINPUT8W;
+
+#undef INTERFACE
+#define INTERFACE IDirectInput8A
+
+DECLARE_INTERFACE_(IDirectInput8A, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInput8A methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICE8A *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE;
+    STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCSTR,LPDIACTIONFORMATA,LPDIENUMDEVICESBYSEMANTICSCBA,LPVOID,DWORD) PURE;
+    STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK,LPDICONFIGUREDEVICESPARAMSA,DWORD,LPVOID) PURE;
+};
+
+typedef struct IDirectInput8A *LPDIRECTINPUT8A;
+
+#ifdef UNICODE
+#define IID_IDirectInput8 IID_IDirectInput8W
+#define IDirectInput8 IDirectInput8W
+#define IDirectInput8Vtbl IDirectInput8WVtbl
+#else
+#define IID_IDirectInput8 IID_IDirectInput8A
+#define IDirectInput8 IDirectInput8A
+#define IDirectInput8Vtbl IDirectInput8AVtbl
+#endif
+typedef struct IDirectInput8 *LPDIRECTINPUT8;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInput8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInput8_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInput8_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInput8_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+#define IDirectInput8_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+#define IDirectInput8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInput8_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectInput8_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c)
+#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->lpVtbl->EnumDevicesBySemantics(p,a,b,c,d,e)
+#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->lpVtbl->ConfigureDevices(p,a,b,c,d)
+#else
+#define IDirectInput8_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInput8_AddRef(p) (p)->AddRef()
+#define IDirectInput8_Release(p) (p)->Release()
+#define IDirectInput8_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d)
+#define IDirectInput8_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a)
+#define IDirectInput8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+#define IDirectInput8_Initialize(p,a,b) (p)->Initialize(a,b)
+#define IDirectInput8_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c)
+#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->EnumDevicesBySemantics(a,b,c,d,e)
+#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->ConfigureDevices(a,b,c,d)
+#endif
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+#if DIRECTINPUT_VERSION > 0x0700
+
+extern HRESULT WINAPI DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
+
+#else
+extern HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter);
+extern HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter);
+#ifdef UNICODE
+#define DirectInputCreate  DirectInputCreateW
+#else
+#define DirectInputCreate  DirectInputCreateA
+#endif // !UNICODE
+
+extern HRESULT WINAPI DirectInputCreateEx(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
+
+#endif /* DIRECTINPUT_VERSION > 0x700 */
+
+#endif /* DIJ_RINGZERO */
+
+
+/****************************************************************************
+ *
+ *  Return Codes
+ *
+ ****************************************************************************/
+
+/*
+ *  The operation completed successfully.
+ */
+#define DI_OK                           S_OK
+
+/*
+ *  The device exists but is not currently attached.
+ */
+#define DI_NOTATTACHED                  S_FALSE
+
+/*
+ *  The device buffer overflowed.  Some input was lost.
+ */
+#define DI_BUFFEROVERFLOW               S_FALSE
+
+/*
+ *  The change in device properties had no effect.
+ */
+#define DI_PROPNOEFFECT                 S_FALSE
+
+/*
+ *  The operation had no effect.
+ */
+#define DI_NOEFFECT                     S_FALSE
+
+/*
+ *  The device is a polled device.  As a result, device buffering
+ *  will not collect any data and event notifications will not be
+ *  signalled until GetDeviceState is called.
+ */
+#define DI_POLLEDDEVICE                 ((HRESULT)0x00000002L)
+
+/*
+ *  The parameters of the effect were successfully updated by
+ *  IDirectInputEffect::SetParameters, but the effect was not
+ *  downloaded because the device is not exclusively acquired
+ *  or because the DIEP_NODOWNLOAD flag was passed.
+ */
+#define DI_DOWNLOADSKIPPED              ((HRESULT)0x00000003L)
+
+/*
+ *  The parameters of the effect were successfully updated by
+ *  IDirectInputEffect::SetParameters, but in order to change
+ *  the parameters, the effect needed to be restarted.
+ */
+#define DI_EFFECTRESTARTED              ((HRESULT)0x00000004L)
+
+/*
+ *  The parameters of the effect were successfully updated by
+ *  IDirectInputEffect::SetParameters, but some of them were
+ *  beyond the capabilities of the device and were truncated.
+ */
+#define DI_TRUNCATED                    ((HRESULT)0x00000008L)
+
+/*
+ *  The settings have been successfully applied but could not be 
+ *  persisted. 
+ */
+#define DI_SETTINGSNOTSAVED				((HRESULT)0x0000000BL)
+
+/*
+ *  Equal to DI_EFFECTRESTARTED | DI_TRUNCATED.
+ */
+#define DI_TRUNCATEDANDRESTARTED        ((HRESULT)0x0000000CL)
+
+/*
+ *  A SUCCESS code indicating that settings cannot be modified.
+ */
+#define DI_WRITEPROTECT                 ((HRESULT)0x00000013L)
+
+/*
+ *  The application requires a newer version of DirectInput.
+ */
+#define DIERR_OLDDIRECTINPUTVERSION     \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION)
+
+/*
+ *  The application was written for an unsupported prerelease version
+ *  of DirectInput.
+ */
+#define DIERR_BETADIRECTINPUTVERSION    \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP)
+
+/*
+ *  The object could not be created due to an incompatible driver version
+ *  or mismatched or incomplete driver components.
+ */
+#define DIERR_BADDRIVERVER              \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL)
+
+/*
+ * The device or device instance or effect is not registered with DirectInput.
+ */
+#define DIERR_DEVICENOTREG              REGDB_E_CLASSNOTREG
+
+/*
+ * The requested object does not exist.
+ */
+#define DIERR_NOTFOUND                  \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND)
+
+/*
+ * The requested object does not exist.
+ */
+#define DIERR_OBJECTNOTFOUND            \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND)
+
+/*
+ * An invalid parameter was passed to the returning function,
+ * or the object was not in a state that admitted the function
+ * to be called.
+ */
+#define DIERR_INVALIDPARAM              E_INVALIDARG
+
+/*
+ * The specified interface is not supported by the object
+ */
+#define DIERR_NOINTERFACE               E_NOINTERFACE
+
+/*
+ * An undetermined error occured inside the DInput subsystem
+ */
+#define DIERR_GENERIC                   E_FAIL
+
+/*
+ * The DInput subsystem couldn't allocate sufficient memory to complete the
+ * caller's request.
+ */
+#define DIERR_OUTOFMEMORY               E_OUTOFMEMORY
+
+/*
+ * The function called is not supported at this time
+ */
+#define DIERR_UNSUPPORTED               E_NOTIMPL
+
+/*
+ * This object has not been initialized
+ */
+#define DIERR_NOTINITIALIZED            \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY)
+
+/*
+ * This object is already initialized
+ */
+#define DIERR_ALREADYINITIALIZED        \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED)
+
+/*
+ * This object does not support aggregation
+ */
+#define DIERR_NOAGGREGATION             CLASS_E_NOAGGREGATION
+
+/*
+ * Another app has a higher priority level, preventing this call from
+ * succeeding.
+ */
+#define DIERR_OTHERAPPHASPRIO           E_ACCESSDENIED
+
+/*
+ * Access to the device has been lost.  It must be re-acquired.
+ */
+#define DIERR_INPUTLOST                 \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT)
+
+/*
+ * The operation cannot be performed while the device is acquired.
+ */
+#define DIERR_ACQUIRED                  \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY)
+
+/*
+ * The operation cannot be performed unless the device is acquired.
+ */
+#define DIERR_NOTACQUIRED               \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS)
+
+/*
+ * The specified property cannot be changed.
+ */
+#define DIERR_READONLY                  E_ACCESSDENIED
+
+/*
+ * The device already has an event notification associated with it.
+ */
+#define DIERR_HANDLEEXISTS              E_ACCESSDENIED
+
+/*
+ * Data is not yet available.
+ */
+#ifndef E_PENDING
+#define E_PENDING                       0x8000000AL
+#endif
+
+/*
+ * Unable to IDirectInputJoyConfig_Acquire because the user
+ * does not have sufficient privileges to change the joystick
+ * configuration.
+ */
+#define DIERR_INSUFFICIENTPRIVS         0x80040200L
+
+/*
+ * The device is full.
+ */
+#define DIERR_DEVICEFULL                0x80040201L
+
+/*
+ * Not all the requested information fit into the buffer.
+ */
+#define DIERR_MOREDATA                  0x80040202L
+
+/*
+ * The effect is not downloaded.
+ */
+#define DIERR_NOTDOWNLOADED             0x80040203L
+
+/*
+ *  The device cannot be reinitialized because there are still effects
+ *  attached to it.
+ */
+#define DIERR_HASEFFECTS                0x80040204L
+
+/*
+ *  The operation cannot be performed unless the device is acquired
+ *  in DISCL_EXCLUSIVE mode.
+ */
+#define DIERR_NOTEXCLUSIVEACQUIRED      0x80040205L
+
+/*
+ *  The effect could not be downloaded because essential information
+ *  is missing.  For example, no axes have been associated with the
+ *  effect, or no type-specific information has been created.
+ */
+#define DIERR_INCOMPLETEEFFECT          0x80040206L
+
+/*
+ *  Attempted to read buffered device data from a device that is
+ *  not buffered.
+ */
+#define DIERR_NOTBUFFERED               0x80040207L
+
+/*
+ *  An attempt was made to modify parameters of an effect while it is
+ *  playing.  Not all hardware devices support altering the parameters
+ *  of an effect while it is playing.
+ */
+#define DIERR_EFFECTPLAYING             0x80040208L
+
+/*
+ *  The operation could not be completed because the device is not
+ *  plugged in.
+ */
+#define DIERR_UNPLUGGED                 0x80040209L
+
+/*
+ *  SendDeviceData failed because more information was requested
+ *  to be sent than can be sent to the device.  Some devices have
+ *  restrictions on how much data can be sent to them.  (For example,
+ *  there might be a limit on the number of buttons that can be
+ *  pressed at once.)
+ */
+#define DIERR_REPORTFULL                0x8004020AL
+
+
+/*
+ *  A mapper file function failed because reading or writing the user or IHV 
+ *  settings file failed.
+ */
+#define DIERR_MAPFILEFAIL               0x8004020BL
+
+
+/*--- DINPUT Mapper Definitions: New for Dx8         ---*/
+
+
+/*--- Keyboard
+      Physical Keyboard Device       ---*/
+
+#define DIKEYBOARD_ESCAPE                       0x81000401
+#define DIKEYBOARD_1                            0x81000402
+#define DIKEYBOARD_2                            0x81000403
+#define DIKEYBOARD_3                            0x81000404
+#define DIKEYBOARD_4                            0x81000405
+#define DIKEYBOARD_5                            0x81000406
+#define DIKEYBOARD_6                            0x81000407
+#define DIKEYBOARD_7                            0x81000408
+#define DIKEYBOARD_8                            0x81000409
+#define DIKEYBOARD_9                            0x8100040A
+#define DIKEYBOARD_0                            0x8100040B
+#define DIKEYBOARD_MINUS                        0x8100040C    /* - on main keyboard */
+#define DIKEYBOARD_EQUALS                       0x8100040D
+#define DIKEYBOARD_BACK                         0x8100040E    /* backspace */
+#define DIKEYBOARD_TAB                          0x8100040F
+#define DIKEYBOARD_Q                            0x81000410
+#define DIKEYBOARD_W                            0x81000411
+#define DIKEYBOARD_E                            0x81000412
+#define DIKEYBOARD_R                            0x81000413
+#define DIKEYBOARD_T                            0x81000414
+#define DIKEYBOARD_Y                            0x81000415
+#define DIKEYBOARD_U                            0x81000416
+#define DIKEYBOARD_I                            0x81000417
+#define DIKEYBOARD_O                            0x81000418
+#define DIKEYBOARD_P                            0x81000419
+#define DIKEYBOARD_LBRACKET                     0x8100041A
+#define DIKEYBOARD_RBRACKET                     0x8100041B
+#define DIKEYBOARD_RETURN                       0x8100041C    /* Enter on main keyboard */
+#define DIKEYBOARD_LCONTROL                     0x8100041D
+#define DIKEYBOARD_A                            0x8100041E
+#define DIKEYBOARD_S                            0x8100041F
+#define DIKEYBOARD_D                            0x81000420
+#define DIKEYBOARD_F                            0x81000421
+#define DIKEYBOARD_G                            0x81000422
+#define DIKEYBOARD_H                            0x81000423
+#define DIKEYBOARD_J                            0x81000424
+#define DIKEYBOARD_K                            0x81000425
+#define DIKEYBOARD_L                            0x81000426
+#define DIKEYBOARD_SEMICOLON                    0x81000427
+#define DIKEYBOARD_APOSTROPHE                   0x81000428
+#define DIKEYBOARD_GRAVE                        0x81000429    /* accent grave */
+#define DIKEYBOARD_LSHIFT                       0x8100042A
+#define DIKEYBOARD_BACKSLASH                    0x8100042B
+#define DIKEYBOARD_Z                            0x8100042C
+#define DIKEYBOARD_X                            0x8100042D
+#define DIKEYBOARD_C                            0x8100042E
+#define DIKEYBOARD_V                            0x8100042F
+#define DIKEYBOARD_B                            0x81000430
+#define DIKEYBOARD_N                            0x81000431
+#define DIKEYBOARD_M                            0x81000432
+#define DIKEYBOARD_COMMA                        0x81000433
+#define DIKEYBOARD_PERIOD                       0x81000434    /* . on main keyboard */
+#define DIKEYBOARD_SLASH                        0x81000435    /* / on main keyboard */
+#define DIKEYBOARD_RSHIFT                       0x81000436
+#define DIKEYBOARD_MULTIPLY                     0x81000437    /* * on numeric keypad */
+#define DIKEYBOARD_LMENU                        0x81000438    /* left Alt */
+#define DIKEYBOARD_SPACE                        0x81000439
+#define DIKEYBOARD_CAPITAL                      0x8100043A
+#define DIKEYBOARD_F1                           0x8100043B
+#define DIKEYBOARD_F2                           0x8100043C
+#define DIKEYBOARD_F3                           0x8100043D
+#define DIKEYBOARD_F4                           0x8100043E
+#define DIKEYBOARD_F5                           0x8100043F
+#define DIKEYBOARD_F6                           0x81000440
+#define DIKEYBOARD_F7                           0x81000441
+#define DIKEYBOARD_F8                           0x81000442
+#define DIKEYBOARD_F9                           0x81000443
+#define DIKEYBOARD_F10                          0x81000444
+#define DIKEYBOARD_NUMLOCK                      0x81000445
+#define DIKEYBOARD_SCROLL                       0x81000446    /* Scroll Lock */
+#define DIKEYBOARD_NUMPAD7                      0x81000447
+#define DIKEYBOARD_NUMPAD8                      0x81000448
+#define DIKEYBOARD_NUMPAD9                      0x81000449
+#define DIKEYBOARD_SUBTRACT                     0x8100044A    /* - on numeric keypad */
+#define DIKEYBOARD_NUMPAD4                      0x8100044B
+#define DIKEYBOARD_NUMPAD5                      0x8100044C
+#define DIKEYBOARD_NUMPAD6                      0x8100044D
+#define DIKEYBOARD_ADD                          0x8100044E    /* + on numeric keypad */
+#define DIKEYBOARD_NUMPAD1                      0x8100044F
+#define DIKEYBOARD_NUMPAD2                      0x81000450
+#define DIKEYBOARD_NUMPAD3                      0x81000451
+#define DIKEYBOARD_NUMPAD0                      0x81000452
+#define DIKEYBOARD_DECIMAL                      0x81000453    /* . on numeric keypad */
+#define DIKEYBOARD_OEM_102                      0x81000456    /* <> or \| on RT 102-key keyboard (Non-U.S.) */
+#define DIKEYBOARD_F11                          0x81000457
+#define DIKEYBOARD_F12                          0x81000458
+#define DIKEYBOARD_F13                          0x81000464    /*                     (NEC PC98) */
+#define DIKEYBOARD_F14                          0x81000465    /*                     (NEC PC98) */
+#define DIKEYBOARD_F15                          0x81000466    /*                     (NEC PC98) */
+#define DIKEYBOARD_KANA                         0x81000470    /* (Japanese keyboard)            */
+#define DIKEYBOARD_ABNT_C1                      0x81000473    /* /? on Brazilian keyboard */
+#define DIKEYBOARD_CONVERT                      0x81000479    /* (Japanese keyboard)            */
+#define DIKEYBOARD_NOCONVERT                    0x8100047B    /* (Japanese keyboard)            */
+#define DIKEYBOARD_YEN                          0x8100047D    /* (Japanese keyboard)            */
+#define DIKEYBOARD_ABNT_C2                      0x8100047E    /* Numpad . on Brazilian keyboard */
+#define DIKEYBOARD_NUMPADEQUALS                 0x8100048D    /* = on numeric keypad (NEC PC98) */
+#define DIKEYBOARD_PREVTRACK                    0x81000490    /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */
+#define DIKEYBOARD_AT                           0x81000491    /*                     (NEC PC98) */
+#define DIKEYBOARD_COLON                        0x81000492    /*                     (NEC PC98) */
+#define DIKEYBOARD_UNDERLINE                    0x81000493    /*                     (NEC PC98) */
+#define DIKEYBOARD_KANJI                        0x81000494    /* (Japanese keyboard)            */
+#define DIKEYBOARD_STOP                         0x81000495    /*                     (NEC PC98) */
+#define DIKEYBOARD_AX                           0x81000496    /*                     (Japan AX) */
+#define DIKEYBOARD_UNLABELED                    0x81000497    /*                        (J3100) */
+#define DIKEYBOARD_NEXTTRACK                    0x81000499    /* Next Track */
+#define DIKEYBOARD_NUMPADENTER                  0x8100049C    /* Enter on numeric keypad */
+#define DIKEYBOARD_RCONTROL                     0x8100049D
+#define DIKEYBOARD_MUTE                         0x810004A0    /* Mute */
+#define DIKEYBOARD_CALCULATOR                   0x810004A1    /* Calculator */
+#define DIKEYBOARD_PLAYPAUSE                    0x810004A2    /* Play / Pause */
+#define DIKEYBOARD_MEDIASTOP                    0x810004A4    /* Media Stop */
+#define DIKEYBOARD_VOLUMEDOWN                   0x810004AE    /* Volume - */
+#define DIKEYBOARD_VOLUMEUP                     0x810004B0    /* Volume + */
+#define DIKEYBOARD_WEBHOME                      0x810004B2    /* Web home */
+#define DIKEYBOARD_NUMPADCOMMA                  0x810004B3    /* , on numeric keypad (NEC PC98) */
+#define DIKEYBOARD_DIVIDE                       0x810004B5    /* / on numeric keypad */
+#define DIKEYBOARD_SYSRQ                        0x810004B7
+#define DIKEYBOARD_RMENU                        0x810004B8    /* right Alt */
+#define DIKEYBOARD_PAUSE                        0x810004C5    /* Pause */
+#define DIKEYBOARD_HOME                         0x810004C7    /* Home on arrow keypad */
+#define DIKEYBOARD_UP                           0x810004C8    /* UpArrow on arrow keypad */
+#define DIKEYBOARD_PRIOR                        0x810004C9    /* PgUp on arrow keypad */
+#define DIKEYBOARD_LEFT                         0x810004CB    /* LeftArrow on arrow keypad */
+#define DIKEYBOARD_RIGHT                        0x810004CD    /* RightArrow on arrow keypad */
+#define DIKEYBOARD_END                          0x810004CF    /* End on arrow keypad */
+#define DIKEYBOARD_DOWN                         0x810004D0    /* DownArrow on arrow keypad */
+#define DIKEYBOARD_NEXT                         0x810004D1    /* PgDn on arrow keypad */
+#define DIKEYBOARD_INSERT                       0x810004D2    /* Insert on arrow keypad */
+#define DIKEYBOARD_DELETE                       0x810004D3    /* Delete on arrow keypad */
+#define DIKEYBOARD_LWIN                         0x810004DB    /* Left Windows key */
+#define DIKEYBOARD_RWIN                         0x810004DC    /* Right Windows key */
+#define DIKEYBOARD_APPS                         0x810004DD    /* AppMenu key */
+#define DIKEYBOARD_POWER                        0x810004DE    /* System Power */
+#define DIKEYBOARD_SLEEP                        0x810004DF    /* System Sleep */
+#define DIKEYBOARD_WAKE                         0x810004E3    /* System Wake */
+#define DIKEYBOARD_WEBSEARCH                    0x810004E5    /* Web Search */
+#define DIKEYBOARD_WEBFAVORITES                 0x810004E6    /* Web Favorites */
+#define DIKEYBOARD_WEBREFRESH                   0x810004E7    /* Web Refresh */
+#define DIKEYBOARD_WEBSTOP                      0x810004E8    /* Web Stop */
+#define DIKEYBOARD_WEBFORWARD                   0x810004E9    /* Web Forward */
+#define DIKEYBOARD_WEBBACK                      0x810004EA    /* Web Back */
+#define DIKEYBOARD_MYCOMPUTER                   0x810004EB    /* My Computer */
+#define DIKEYBOARD_MAIL                         0x810004EC    /* Mail */
+#define DIKEYBOARD_MEDIASELECT                  0x810004ED    /* Media Select */
+  
+
+/*--- MOUSE
+      Physical Mouse Device             ---*/
+
+#define DIMOUSE_XAXISAB                         (0x82000200 |DIMOFS_X ) /* X Axis-absolute: Some mice natively report absolute coordinates  */ 
+#define DIMOUSE_YAXISAB                         (0x82000200 |DIMOFS_Y ) /* Y Axis-absolute: Some mice natively report absolute coordinates */
+#define DIMOUSE_XAXIS                           (0x82000300 |DIMOFS_X ) /* X Axis */
+#define DIMOUSE_YAXIS                           (0x82000300 |DIMOFS_Y ) /* Y Axis */
+#define DIMOUSE_WHEEL                           (0x82000300 |DIMOFS_Z ) /* Z Axis */
+#define DIMOUSE_BUTTON0                         (0x82000400 |DIMOFS_BUTTON0) /* Button 0 */
+#define DIMOUSE_BUTTON1                         (0x82000400 |DIMOFS_BUTTON1) /* Button 1 */
+#define DIMOUSE_BUTTON2                         (0x82000400 |DIMOFS_BUTTON2) /* Button 2 */
+#define DIMOUSE_BUTTON3                         (0x82000400 |DIMOFS_BUTTON3) /* Button 3 */
+#define DIMOUSE_BUTTON4                         (0x82000400 |DIMOFS_BUTTON4) /* Button 4 */
+#define DIMOUSE_BUTTON5                         (0x82000400 |DIMOFS_BUTTON5) /* Button 5 */
+#define DIMOUSE_BUTTON6                         (0x82000400 |DIMOFS_BUTTON6) /* Button 6 */
+#define DIMOUSE_BUTTON7                         (0x82000400 |DIMOFS_BUTTON7) /* Button 7 */
+
+
+/*--- VOICE
+      Physical Dplay Voice Device       ---*/
+
+#define DIVOICE_CHANNEL1                        0x83000401
+#define DIVOICE_CHANNEL2                        0x83000402
+#define DIVOICE_CHANNEL3                        0x83000403
+#define DIVOICE_CHANNEL4                        0x83000404
+#define DIVOICE_CHANNEL5                        0x83000405
+#define DIVOICE_CHANNEL6                        0x83000406
+#define DIVOICE_CHANNEL7                        0x83000407
+#define DIVOICE_CHANNEL8                        0x83000408
+#define DIVOICE_TEAM                            0x83000409
+#define DIVOICE_ALL                             0x8300040A
+#define DIVOICE_RECORDMUTE                      0x8300040B
+#define DIVOICE_PLAYBACKMUTE                    0x8300040C
+#define DIVOICE_TRANSMIT                        0x8300040D
+
+#define DIVOICE_VOICECOMMAND                    0x83000410
+
+
+/*--- Driving Simulator - Racing
+      Vehicle control is primary objective  ---*/
+#define DIVIRTUAL_DRIVING_RACE                  0x01000000
+#define DIAXIS_DRIVINGR_STEER                   0x01008A01 /* Steering */
+#define DIAXIS_DRIVINGR_ACCELERATE              0x01039202 /* Accelerate */
+#define DIAXIS_DRIVINGR_BRAKE                   0x01041203 /* Brake-Axis */
+#define DIBUTTON_DRIVINGR_SHIFTUP               0x01000C01 /* Shift to next higher gear */
+#define DIBUTTON_DRIVINGR_SHIFTDOWN             0x01000C02 /* Shift to next lower gear */
+#define DIBUTTON_DRIVINGR_VIEW                  0x01001C03 /* Cycle through view options */
+#define DIBUTTON_DRIVINGR_MENU                  0x010004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIAXIS_DRIVINGR_ACCEL_AND_BRAKE         0x01014A04 /* Some devices combine accelerate and brake in a single axis */
+#define DIHATSWITCH_DRIVINGR_GLANCE             0x01004601 /* Look around */
+#define DIBUTTON_DRIVINGR_BRAKE                 0x01004C04 /* Brake-button */
+#define DIBUTTON_DRIVINGR_DASHBOARD             0x01004405 /* Select next dashboard option */
+#define DIBUTTON_DRIVINGR_AIDS                  0x01004406 /* Driver correction aids */
+#define DIBUTTON_DRIVINGR_MAP                   0x01004407 /* Display Driving Map */
+#define DIBUTTON_DRIVINGR_BOOST                 0x01004408 /* Turbo Boost */
+#define DIBUTTON_DRIVINGR_PIT                   0x01004409 /* Pit stop notification */
+#define DIBUTTON_DRIVINGR_ACCELERATE_LINK       0x0103D4E0 /* Fallback Accelerate button */
+#define DIBUTTON_DRIVINGR_STEER_LEFT_LINK       0x0100CCE4 /* Fallback Steer Left button */
+#define DIBUTTON_DRIVINGR_STEER_RIGHT_LINK      0x0100CCEC /* Fallback Steer Right button */
+#define DIBUTTON_DRIVINGR_GLANCE_LEFT_LINK      0x0107C4E4 /* Fallback Glance Left button */
+#define DIBUTTON_DRIVINGR_GLANCE_RIGHT_LINK     0x0107C4EC /* Fallback Glance Right button */
+#define DIBUTTON_DRIVINGR_DEVICE                0x010044FE /* Show input device and controls */
+#define DIBUTTON_DRIVINGR_PAUSE                 0x010044FC /* Start / Pause / Restart game */
+
+/*--- Driving Simulator - Combat
+      Combat from within a vehicle is primary objective  ---*/
+#define DIVIRTUAL_DRIVING_COMBAT                0x02000000
+#define DIAXIS_DRIVINGC_STEER                   0x02008A01 /* Steering  */
+#define DIAXIS_DRIVINGC_ACCELERATE              0x02039202 /* Accelerate */
+#define DIAXIS_DRIVINGC_BRAKE                   0x02041203 /* Brake-axis */
+#define DIBUTTON_DRIVINGC_FIRE                  0x02000C01 /* Fire */
+#define DIBUTTON_DRIVINGC_WEAPONS               0x02000C02 /* Select next weapon */
+#define DIBUTTON_DRIVINGC_TARGET                0x02000C03 /* Select next available target */
+#define DIBUTTON_DRIVINGC_MENU                  0x020004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIAXIS_DRIVINGC_ACCEL_AND_BRAKE         0x02014A04 /* Some devices combine accelerate and brake in a single axis */
+#define DIHATSWITCH_DRIVINGC_GLANCE             0x02004601 /* Look around */
+#define DIBUTTON_DRIVINGC_SHIFTUP               0x02004C04 /* Shift to next higher gear */
+#define DIBUTTON_DRIVINGC_SHIFTDOWN             0x02004C05 /* Shift to next lower gear */
+#define DIBUTTON_DRIVINGC_DASHBOARD             0x02004406 /* Select next dashboard option */
+#define DIBUTTON_DRIVINGC_AIDS                  0x02004407 /* Driver correction aids */
+#define DIBUTTON_DRIVINGC_BRAKE                 0x02004C08 /* Brake-button */
+#define DIBUTTON_DRIVINGC_FIRESECONDARY         0x02004C09 /* Alternative fire button */
+#define DIBUTTON_DRIVINGC_ACCELERATE_LINK       0x0203D4E0 /* Fallback Accelerate button */
+#define DIBUTTON_DRIVINGC_STEER_LEFT_LINK       0x0200CCE4 /* Fallback Steer Left button */
+#define DIBUTTON_DRIVINGC_STEER_RIGHT_LINK      0x0200CCEC /* Fallback Steer Right button */
+#define DIBUTTON_DRIVINGC_GLANCE_LEFT_LINK      0x0207C4E4 /* Fallback Glance Left button */
+#define DIBUTTON_DRIVINGC_GLANCE_RIGHT_LINK     0x0207C4EC /* Fallback Glance Right button */
+#define DIBUTTON_DRIVINGC_DEVICE                0x020044FE /* Show input device and controls */
+#define DIBUTTON_DRIVINGC_PAUSE                 0x020044FC /* Start / Pause / Restart game */
+
+/*--- Driving Simulator - Tank
+      Combat from withing a tank is primary objective  ---*/
+#define DIVIRTUAL_DRIVING_TANK                  0x03000000
+#define DIAXIS_DRIVINGT_STEER                   0x03008A01 /* Turn tank left / right */
+#define DIAXIS_DRIVINGT_BARREL                  0x03010202 /* Raise / lower barrel */
+#define DIAXIS_DRIVINGT_ACCELERATE              0x03039203 /* Accelerate */
+#define DIAXIS_DRIVINGT_ROTATE                  0x03020204 /* Turn barrel left / right */
+#define DIBUTTON_DRIVINGT_FIRE                  0x03000C01 /* Fire */
+#define DIBUTTON_DRIVINGT_WEAPONS               0x03000C02 /* Select next weapon */
+#define DIBUTTON_DRIVINGT_TARGET                0x03000C03 /* Selects next available target */
+#define DIBUTTON_DRIVINGT_MENU                  0x030004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_DRIVINGT_GLANCE             0x03004601 /* Look around */
+#define DIAXIS_DRIVINGT_BRAKE                   0x03045205 /* Brake-axis */
+#define DIAXIS_DRIVINGT_ACCEL_AND_BRAKE         0x03014A06 /* Some devices combine accelerate and brake in a single axis */
+#define DIBUTTON_DRIVINGT_VIEW                  0x03005C04 /* Cycle through view options */
+#define DIBUTTON_DRIVINGT_DASHBOARD             0x03005C05 /* Select next dashboard option */
+#define DIBUTTON_DRIVINGT_BRAKE                 0x03004C06 /* Brake-button */
+#define DIBUTTON_DRIVINGT_FIRESECONDARY         0x03004C07 /* Alternative fire button */
+#define DIBUTTON_DRIVINGT_ACCELERATE_LINK       0x0303D4E0 /* Fallback Accelerate button */
+#define DIBUTTON_DRIVINGT_STEER_LEFT_LINK       0x0300CCE4 /* Fallback Steer Left button */
+#define DIBUTTON_DRIVINGT_STEER_RIGHT_LINK      0x0300CCEC /* Fallback Steer Right button */
+#define DIBUTTON_DRIVINGT_BARREL_UP_LINK        0x030144E0 /* Fallback Barrel up button */
+#define DIBUTTON_DRIVINGT_BARREL_DOWN_LINK      0x030144E8 /* Fallback Barrel down button */
+#define DIBUTTON_DRIVINGT_ROTATE_LEFT_LINK      0x030244E4 /* Fallback Rotate left button */
+#define DIBUTTON_DRIVINGT_ROTATE_RIGHT_LINK     0x030244EC /* Fallback Rotate right button */
+#define DIBUTTON_DRIVINGT_GLANCE_LEFT_LINK      0x0307C4E4 /* Fallback Glance Left button */
+#define DIBUTTON_DRIVINGT_GLANCE_RIGHT_LINK     0x0307C4EC /* Fallback Glance Right button */
+#define DIBUTTON_DRIVINGT_DEVICE                0x030044FE /* Show input device and controls */
+#define DIBUTTON_DRIVINGT_PAUSE                 0x030044FC /* Start / Pause / Restart game */
+
+/*--- Flight Simulator - Civilian 
+      Plane control is the primary objective  ---*/
+#define DIVIRTUAL_FLYING_CIVILIAN               0x04000000
+#define DIAXIS_FLYINGC_BANK                     0x04008A01 /* Roll ship left / right */
+#define DIAXIS_FLYINGC_PITCH                    0x04010A02 /* Nose up / down */
+#define DIAXIS_FLYINGC_THROTTLE                 0x04039203 /* Throttle */
+#define DIBUTTON_FLYINGC_VIEW                   0x04002401 /* Cycle through view options */
+#define DIBUTTON_FLYINGC_DISPLAY                0x04002402 /* Select next dashboard / heads up display option */
+#define DIBUTTON_FLYINGC_GEAR                   0x04002C03 /* Gear up / down */
+#define DIBUTTON_FLYINGC_MENU                   0x040004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_FLYINGC_GLANCE              0x04004601 /* Look around */
+#define DIAXIS_FLYINGC_BRAKE                    0x04046A04 /* Apply Brake */
+#define DIAXIS_FLYINGC_RUDDER                   0x04025205 /* Yaw ship left/right */
+#define DIAXIS_FLYINGC_FLAPS                    0x04055A06 /* Flaps */
+#define DIBUTTON_FLYINGC_FLAPSUP                0x04006404 /* Increment stepping up until fully retracted */
+#define DIBUTTON_FLYINGC_FLAPSDOWN              0x04006405 /* Decrement stepping down until fully extended */
+#define DIBUTTON_FLYINGC_BRAKE_LINK             0x04046CE0 /* Fallback brake button */
+#define DIBUTTON_FLYINGC_FASTER_LINK            0x0403D4E0 /* Fallback throttle up button */
+#define DIBUTTON_FLYINGC_SLOWER_LINK            0x0403D4E8 /* Fallback throttle down button */
+#define DIBUTTON_FLYINGC_GLANCE_LEFT_LINK       0x0407C4E4 /* Fallback Glance Left button */
+#define DIBUTTON_FLYINGC_GLANCE_RIGHT_LINK      0x0407C4EC /* Fallback Glance Right button */
+#define DIBUTTON_FLYINGC_GLANCE_UP_LINK         0x0407C4E0 /* Fallback Glance Up button */
+#define DIBUTTON_FLYINGC_GLANCE_DOWN_LINK       0x0407C4E8 /* Fallback Glance Down button */
+#define DIBUTTON_FLYINGC_DEVICE                 0x040044FE /* Show input device and controls */
+#define DIBUTTON_FLYINGC_PAUSE                  0x040044FC /* Start / Pause / Restart game */
+
+/*--- Flight Simulator - Military 
+      Aerial combat is the primary objective  ---*/
+#define DIVIRTUAL_FLYING_MILITARY               0x05000000
+#define DIAXIS_FLYINGM_BANK                     0x05008A01 /* Bank - Roll ship left / right */
+#define DIAXIS_FLYINGM_PITCH                    0x05010A02 /* Pitch - Nose up / down */
+#define DIAXIS_FLYINGM_THROTTLE                 0x05039203 /* Throttle - faster / slower */
+#define DIBUTTON_FLYINGM_FIRE                   0x05000C01 /* Fire */
+#define DIBUTTON_FLYINGM_WEAPONS                0x05000C02 /* Select next weapon */
+#define DIBUTTON_FLYINGM_TARGET                 0x05000C03 /* Selects next available target */
+#define DIBUTTON_FLYINGM_MENU                   0x050004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_FLYINGM_GLANCE              0x05004601 /* Look around */
+#define DIBUTTON_FLYINGM_COUNTER                0x05005C04 /* Activate counter measures */
+#define DIAXIS_FLYINGM_RUDDER                   0x05024A04 /* Rudder - Yaw ship left/right */
+#define DIAXIS_FLYINGM_BRAKE                    0x05046205 /* Brake-axis */
+#define DIBUTTON_FLYINGM_VIEW                   0x05006405 /* Cycle through view options */
+#define DIBUTTON_FLYINGM_DISPLAY                0x05006406 /* Select next dashboard option */
+#define DIAXIS_FLYINGM_FLAPS                    0x05055206 /* Flaps */
+#define DIBUTTON_FLYINGM_FLAPSUP                0x05005407 /* Increment stepping up until fully retracted */
+#define DIBUTTON_FLYINGM_FLAPSDOWN              0x05005408 /* Decrement stepping down until fully extended */
+#define DIBUTTON_FLYINGM_FIRESECONDARY          0x05004C09 /* Alternative fire button */
+#define DIBUTTON_FLYINGM_GEAR                   0x0500640A /* Gear up / down */
+#define DIBUTTON_FLYINGM_BRAKE_LINK             0x050464E0 /* Fallback brake button */
+#define DIBUTTON_FLYINGM_FASTER_LINK            0x0503D4E0 /* Fallback throttle up button */
+#define DIBUTTON_FLYINGM_SLOWER_LINK            0x0503D4E8 /* Fallback throttle down button */
+#define DIBUTTON_FLYINGM_GLANCE_LEFT_LINK       0x0507C4E4 /* Fallback Glance Left button */
+#define DIBUTTON_FLYINGM_GLANCE_RIGHT_LINK      0x0507C4EC /* Fallback Glance Right button */
+#define DIBUTTON_FLYINGM_GLANCE_UP_LINK         0x0507C4E0 /* Fallback Glance Up button */
+#define DIBUTTON_FLYINGM_GLANCE_DOWN_LINK       0x0507C4E8 /* Fallback Glance Down button */
+#define DIBUTTON_FLYINGM_DEVICE                 0x050044FE /* Show input device and controls */
+#define DIBUTTON_FLYINGM_PAUSE                  0x050044FC /* Start / Pause / Restart game */
+
+/*--- Flight Simulator - Combat Helicopter
+      Combat from helicopter is primary objective  ---*/
+#define DIVIRTUAL_FLYING_HELICOPTER             0x06000000
+#define DIAXIS_FLYINGH_BANK                     0x06008A01 /* Bank - Roll ship left / right */
+#define DIAXIS_FLYINGH_PITCH                    0x06010A02 /* Pitch - Nose up / down */
+#define DIAXIS_FLYINGH_COLLECTIVE               0x06018A03 /* Collective - Blade pitch/power */
+#define DIBUTTON_FLYINGH_FIRE                   0x06001401 /* Fire */
+#define DIBUTTON_FLYINGH_WEAPONS                0x06001402 /* Select next weapon */
+#define DIBUTTON_FLYINGH_TARGET                 0x06001403 /* Selects next available target */
+#define DIBUTTON_FLYINGH_MENU                   0x060004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_FLYINGH_GLANCE              0x06004601 /* Look around */
+#define DIAXIS_FLYINGH_TORQUE                   0x06025A04 /* Torque - Rotate ship around left / right axis */
+#define DIAXIS_FLYINGH_THROTTLE                 0x0603DA05 /* Throttle */
+#define DIBUTTON_FLYINGH_COUNTER                0x06005404 /* Activate counter measures */
+#define DIBUTTON_FLYINGH_VIEW                   0x06006405 /* Cycle through view options */
+#define DIBUTTON_FLYINGH_GEAR                   0x06006406 /* Gear up / down */
+#define DIBUTTON_FLYINGH_FIRESECONDARY          0x06004C07 /* Alternative fire button */
+#define DIBUTTON_FLYINGH_FASTER_LINK            0x0603DCE0 /* Fallback throttle up button */
+#define DIBUTTON_FLYINGH_SLOWER_LINK            0x0603DCE8 /* Fallback throttle down button */
+#define DIBUTTON_FLYINGH_GLANCE_LEFT_LINK       0x0607C4E4 /* Fallback Glance Left button */
+#define DIBUTTON_FLYINGH_GLANCE_RIGHT_LINK      0x0607C4EC /* Fallback Glance Right button */
+#define DIBUTTON_FLYINGH_GLANCE_UP_LINK         0x0607C4E0 /* Fallback Glance Up button */
+#define DIBUTTON_FLYINGH_GLANCE_DOWN_LINK       0x0607C4E8 /* Fallback Glance Down button */
+#define DIBUTTON_FLYINGH_DEVICE                 0x060044FE /* Show input device and controls */
+#define DIBUTTON_FLYINGH_PAUSE                  0x060044FC /* Start / Pause / Restart game */
+
+/*--- Space Simulator - Combat
+      Space Simulator with weapons  ---*/
+#define DIVIRTUAL_SPACESIM                      0x07000000
+#define DIAXIS_SPACESIM_LATERAL                 0x07008201 /* Move ship left / right */
+#define DIAXIS_SPACESIM_MOVE                    0x07010202 /* Move ship forward/backward */
+#define DIAXIS_SPACESIM_THROTTLE                0x07038203 /* Throttle - Engine speed */
+#define DIBUTTON_SPACESIM_FIRE                  0x07000401 /* Fire */
+#define DIBUTTON_SPACESIM_WEAPONS               0x07000402 /* Select next weapon */
+#define DIBUTTON_SPACESIM_TARGET                0x07000403 /* Selects next available target */
+#define DIBUTTON_SPACESIM_MENU                  0x070004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_SPACESIM_GLANCE             0x07004601 /* Look around */
+#define DIAXIS_SPACESIM_CLIMB                   0x0701C204 /* Climb - Pitch ship up/down */
+#define DIAXIS_SPACESIM_ROTATE                  0x07024205 /* Rotate - Turn ship left/right */
+#define DIBUTTON_SPACESIM_VIEW                  0x07004404 /* Cycle through view options */
+#define DIBUTTON_SPACESIM_DISPLAY               0x07004405 /* Select next dashboard / heads up display option */
+#define DIBUTTON_SPACESIM_RAISE                 0x07004406 /* Raise ship while maintaining current pitch */
+#define DIBUTTON_SPACESIM_LOWER                 0x07004407 /* Lower ship while maintaining current pitch */
+#define DIBUTTON_SPACESIM_GEAR                  0x07004408 /* Gear up / down */
+#define DIBUTTON_SPACESIM_FIRESECONDARY         0x07004409 /* Alternative fire button */
+#define DIBUTTON_SPACESIM_LEFT_LINK             0x0700C4E4 /* Fallback move left button */
+#define DIBUTTON_SPACESIM_RIGHT_LINK            0x0700C4EC /* Fallback move right button */
+#define DIBUTTON_SPACESIM_FORWARD_LINK          0x070144E0 /* Fallback move forward button */
+#define DIBUTTON_SPACESIM_BACKWARD_LINK         0x070144E8 /* Fallback move backwards button */
+#define DIBUTTON_SPACESIM_FASTER_LINK           0x0703C4E0 /* Fallback throttle up button */
+#define DIBUTTON_SPACESIM_SLOWER_LINK           0x0703C4E8 /* Fallback throttle down button */
+#define DIBUTTON_SPACESIM_TURN_LEFT_LINK        0x070244E4 /* Fallback turn left button */
+#define DIBUTTON_SPACESIM_TURN_RIGHT_LINK       0x070244EC /* Fallback turn right button */
+#define DIBUTTON_SPACESIM_GLANCE_LEFT_LINK      0x0707C4E4 /* Fallback Glance Left button */
+#define DIBUTTON_SPACESIM_GLANCE_RIGHT_LINK     0x0707C4EC /* Fallback Glance Right button */
+#define DIBUTTON_SPACESIM_GLANCE_UP_LINK        0x0707C4E0 /* Fallback Glance Up button */
+#define DIBUTTON_SPACESIM_GLANCE_DOWN_LINK      0x0707C4E8 /* Fallback Glance Down button */
+#define DIBUTTON_SPACESIM_DEVICE                0x070044FE /* Show input device and controls */
+#define DIBUTTON_SPACESIM_PAUSE                 0x070044FC /* Start / Pause / Restart game */
+
+/*--- Fighting - First Person 
+      Hand to Hand combat is primary objective  ---*/
+#define DIVIRTUAL_FIGHTING_HAND2HAND            0x08000000
+#define DIAXIS_FIGHTINGH_LATERAL                0x08008201 /* Sidestep left/right */
+#define DIAXIS_FIGHTINGH_MOVE                   0x08010202 /* Move forward/backward */
+#define DIBUTTON_FIGHTINGH_PUNCH                0x08000401 /* Punch */
+#define DIBUTTON_FIGHTINGH_KICK                 0x08000402 /* Kick */
+#define DIBUTTON_FIGHTINGH_BLOCK                0x08000403 /* Block */
+#define DIBUTTON_FIGHTINGH_CROUCH               0x08000404 /* Crouch */
+#define DIBUTTON_FIGHTINGH_JUMP                 0x08000405 /* Jump */
+#define DIBUTTON_FIGHTINGH_SPECIAL1             0x08000406 /* Apply first special move */
+#define DIBUTTON_FIGHTINGH_SPECIAL2             0x08000407 /* Apply second special move */
+#define DIBUTTON_FIGHTINGH_MENU                 0x080004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_FIGHTINGH_SELECT               0x08004408 /* Select special move */
+#define DIHATSWITCH_FIGHTINGH_SLIDE             0x08004601 /* Look around */
+#define DIBUTTON_FIGHTINGH_DISPLAY              0x08004409 /* Shows next on-screen display option */
+#define DIAXIS_FIGHTINGH_ROTATE                 0x08024203 /* Rotate - Turn body left/right */
+#define DIBUTTON_FIGHTINGH_DODGE                0x0800440A /* Dodge */
+#define DIBUTTON_FIGHTINGH_LEFT_LINK            0x0800C4E4 /* Fallback left sidestep button */
+#define DIBUTTON_FIGHTINGH_RIGHT_LINK           0x0800C4EC /* Fallback right sidestep button */
+#define DIBUTTON_FIGHTINGH_FORWARD_LINK         0x080144E0 /* Fallback forward button */
+#define DIBUTTON_FIGHTINGH_BACKWARD_LINK        0x080144E8 /* Fallback backward button */
+#define DIBUTTON_FIGHTINGH_DEVICE               0x080044FE /* Show input device and controls */
+#define DIBUTTON_FIGHTINGH_PAUSE                0x080044FC /* Start / Pause / Restart game */
+
+/*--- Fighting - First Person Shooting
+      Navigation and combat are primary objectives  ---*/
+#define DIVIRTUAL_FIGHTING_FPS                  0x09000000
+#define DIAXIS_FPS_ROTATE                       0x09008201 /* Rotate character left/right */
+#define DIAXIS_FPS_MOVE                         0x09010202 /* Move forward/backward */
+#define DIBUTTON_FPS_FIRE                       0x09000401 /* Fire */
+#define DIBUTTON_FPS_WEAPONS                    0x09000402 /* Select next weapon */
+#define DIBUTTON_FPS_APPLY                      0x09000403 /* Use item */
+#define DIBUTTON_FPS_SELECT                     0x09000404 /* Select next inventory item */
+#define DIBUTTON_FPS_CROUCH                     0x09000405 /* Crouch/ climb down/ swim down */
+#define DIBUTTON_FPS_JUMP                       0x09000406 /* Jump/ climb up/ swim up */
+#define DIAXIS_FPS_LOOKUPDOWN                   0x09018203 /* Look up / down  */
+#define DIBUTTON_FPS_STRAFE                     0x09000407 /* Enable strafing while active */
+#define DIBUTTON_FPS_MENU                       0x090004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_FPS_GLANCE                  0x09004601 /* Look around */
+#define DIBUTTON_FPS_DISPLAY                    0x09004408 /* Shows next on-screen display option/ map */
+#define DIAXIS_FPS_SIDESTEP                     0x09024204 /* Sidestep */
+#define DIBUTTON_FPS_DODGE                      0x09004409 /* Dodge */
+#define DIBUTTON_FPS_GLANCEL                    0x0900440A /* Glance Left */
+#define DIBUTTON_FPS_GLANCER                    0x0900440B /* Glance Right */
+#define DIBUTTON_FPS_FIRESECONDARY              0x0900440C /* Alternative fire button */
+#define DIBUTTON_FPS_ROTATE_LEFT_LINK           0x0900C4E4 /* Fallback rotate left button */
+#define DIBUTTON_FPS_ROTATE_RIGHT_LINK          0x0900C4EC /* Fallback rotate right button */
+#define DIBUTTON_FPS_FORWARD_LINK               0x090144E0 /* Fallback forward button */
+#define DIBUTTON_FPS_BACKWARD_LINK              0x090144E8 /* Fallback backward button */
+#define DIBUTTON_FPS_GLANCE_UP_LINK             0x0901C4E0 /* Fallback look up button */
+#define DIBUTTON_FPS_GLANCE_DOWN_LINK           0x0901C4E8 /* Fallback look down button */
+#define DIBUTTON_FPS_STEP_LEFT_LINK             0x090244E4 /* Fallback step left button */
+#define DIBUTTON_FPS_STEP_RIGHT_LINK            0x090244EC /* Fallback step right button */
+#define DIBUTTON_FPS_DEVICE                     0x090044FE /* Show input device and controls */
+#define DIBUTTON_FPS_PAUSE                      0x090044FC /* Start / Pause / Restart game */
+
+/*--- Fighting - Third Person action
+      Perspective of Camera is behind the main character  ---*/
+#define DIVIRTUAL_FIGHTING_THIRDPERSON          0x0A000000
+#define DIAXIS_TPS_TURN                         0x0A020201 /* Turn left/right */
+#define DIAXIS_TPS_MOVE                         0x0A010202 /* Move forward/backward */
+#define DIBUTTON_TPS_RUN                        0x0A000401 /* Run or walk toggle switch */
+#define DIBUTTON_TPS_ACTION                     0x0A000402 /* Action Button */
+#define DIBUTTON_TPS_SELECT                     0x0A000403 /* Select next weapon */
+#define DIBUTTON_TPS_USE                        0x0A000404 /* Use inventory item currently selected */
+#define DIBUTTON_TPS_JUMP                       0x0A000405 /* Character Jumps */
+#define DIBUTTON_TPS_MENU                       0x0A0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_TPS_GLANCE                  0x0A004601 /* Look around */
+#define DIBUTTON_TPS_VIEW                       0x0A004406 /* Select Camera view */
+#define DIBUTTON_TPS_STEPLEFT                   0x0A004407 /* Character takes a left step */
+#define DIBUTTON_TPS_STEPRIGHT                  0x0A004408 /* Character takes a right step */
+#define DIAXIS_TPS_STEP                         0x0A00C203 /* Character steps left/right */
+#define DIBUTTON_TPS_DODGE                      0x0A004409 /* Character dodges or ducks */
+#define DIBUTTON_TPS_INVENTORY                  0x0A00440A /* Cycle through inventory */
+#define DIBUTTON_TPS_TURN_LEFT_LINK             0x0A0244E4 /* Fallback turn left button */
+#define DIBUTTON_TPS_TURN_RIGHT_LINK            0x0A0244EC /* Fallback turn right button */
+#define DIBUTTON_TPS_FORWARD_LINK               0x0A0144E0 /* Fallback forward button */
+#define DIBUTTON_TPS_BACKWARD_LINK              0x0A0144E8 /* Fallback backward button */
+#define DIBUTTON_TPS_GLANCE_UP_LINK             0x0A07C4E0 /* Fallback look up button */
+#define DIBUTTON_TPS_GLANCE_DOWN_LINK           0x0A07C4E8 /* Fallback look down button */
+#define DIBUTTON_TPS_GLANCE_LEFT_LINK           0x0A07C4E4 /* Fallback glance up button */
+#define DIBUTTON_TPS_GLANCE_RIGHT_LINK          0x0A07C4EC /* Fallback glance right button */
+#define DIBUTTON_TPS_DEVICE                     0x0A0044FE /* Show input device and controls */
+#define DIBUTTON_TPS_PAUSE                      0x0A0044FC /* Start / Pause / Restart game */
+
+/*--- Strategy - Role Playing
+      Navigation and problem solving are primary actions  ---*/
+#define DIVIRTUAL_STRATEGY_ROLEPLAYING          0x0B000000
+#define DIAXIS_STRATEGYR_LATERAL                0x0B008201 /* sidestep - left/right */
+#define DIAXIS_STRATEGYR_MOVE                   0x0B010202 /* move forward/backward */
+#define DIBUTTON_STRATEGYR_GET                  0x0B000401 /* Acquire item */
+#define DIBUTTON_STRATEGYR_APPLY                0x0B000402 /* Use selected item */
+#define DIBUTTON_STRATEGYR_SELECT               0x0B000403 /* Select nextitem */
+#define DIBUTTON_STRATEGYR_ATTACK               0x0B000404 /* Attack */
+#define DIBUTTON_STRATEGYR_CAST                 0x0B000405 /* Cast Spell */
+#define DIBUTTON_STRATEGYR_CROUCH               0x0B000406 /* Crouch */
+#define DIBUTTON_STRATEGYR_JUMP                 0x0B000407 /* Jump */
+#define DIBUTTON_STRATEGYR_MENU                 0x0B0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_STRATEGYR_GLANCE            0x0B004601 /* Look around */
+#define DIBUTTON_STRATEGYR_MAP                  0x0B004408 /* Cycle through map options */
+#define DIBUTTON_STRATEGYR_DISPLAY              0x0B004409 /* Shows next on-screen display option */
+#define DIAXIS_STRATEGYR_ROTATE                 0x0B024203 /* Turn body left/right */
+#define DIBUTTON_STRATEGYR_LEFT_LINK            0x0B00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_STRATEGYR_RIGHT_LINK           0x0B00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_STRATEGYR_FORWARD_LINK         0x0B0144E0 /* Fallback move forward button */
+#define DIBUTTON_STRATEGYR_BACK_LINK            0x0B0144E8 /* Fallback move backward button */
+#define DIBUTTON_STRATEGYR_ROTATE_LEFT_LINK     0x0B0244E4 /* Fallback turn body left button */
+#define DIBUTTON_STRATEGYR_ROTATE_RIGHT_LINK    0x0B0244EC /* Fallback turn body right button */
+#define DIBUTTON_STRATEGYR_DEVICE               0x0B0044FE /* Show input device and controls */
+#define DIBUTTON_STRATEGYR_PAUSE                0x0B0044FC /* Start / Pause / Restart game */
+
+/*--- Strategy - Turn based
+      Navigation and problem solving are primary actions  ---*/
+#define DIVIRTUAL_STRATEGY_TURN                 0x0C000000
+#define DIAXIS_STRATEGYT_LATERAL                0x0C008201 /* Sidestep left/right */
+#define DIAXIS_STRATEGYT_MOVE                   0x0C010202 /* Move forward/backwards */
+#define DIBUTTON_STRATEGYT_SELECT               0x0C000401 /* Select unit or object */
+#define DIBUTTON_STRATEGYT_INSTRUCT             0x0C000402 /* Cycle through instructions */
+#define DIBUTTON_STRATEGYT_APPLY                0x0C000403 /* Apply selected instruction */
+#define DIBUTTON_STRATEGYT_TEAM                 0x0C000404 /* Select next team / cycle through all */
+#define DIBUTTON_STRATEGYT_TURN                 0x0C000405 /* Indicate turn over */
+#define DIBUTTON_STRATEGYT_MENU                 0x0C0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_STRATEGYT_ZOOM                 0x0C004406 /* Zoom - in / out */
+#define DIBUTTON_STRATEGYT_MAP                  0x0C004407 /* cycle through map options */
+#define DIBUTTON_STRATEGYT_DISPLAY              0x0C004408 /* shows next on-screen display options */
+#define DIBUTTON_STRATEGYT_LEFT_LINK            0x0C00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_STRATEGYT_RIGHT_LINK           0x0C00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_STRATEGYT_FORWARD_LINK         0x0C0144E0 /* Fallback move forward button */
+#define DIBUTTON_STRATEGYT_BACK_LINK            0x0C0144E8 /* Fallback move back button */
+#define DIBUTTON_STRATEGYT_DEVICE               0x0C0044FE /* Show input device and controls */
+#define DIBUTTON_STRATEGYT_PAUSE                0x0C0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Hunting
+      Hunting                ---*/
+#define DIVIRTUAL_SPORTS_HUNTING                0x0D000000
+#define DIAXIS_HUNTING_LATERAL                  0x0D008201 /* sidestep left/right */
+#define DIAXIS_HUNTING_MOVE                     0x0D010202 /* move forward/backwards */
+#define DIBUTTON_HUNTING_FIRE                   0x0D000401 /* Fire selected weapon */
+#define DIBUTTON_HUNTING_AIM                    0x0D000402 /* Select aim/move */
+#define DIBUTTON_HUNTING_WEAPON                 0x0D000403 /* Select next weapon */
+#define DIBUTTON_HUNTING_BINOCULAR              0x0D000404 /* Look through Binoculars */
+#define DIBUTTON_HUNTING_CALL                   0x0D000405 /* Make animal call */
+#define DIBUTTON_HUNTING_MAP                    0x0D000406 /* View Map */
+#define DIBUTTON_HUNTING_SPECIAL                0x0D000407 /* Special game operation */
+#define DIBUTTON_HUNTING_MENU                   0x0D0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_HUNTING_GLANCE              0x0D004601 /* Look around */
+#define DIBUTTON_HUNTING_DISPLAY                0x0D004408 /* show next on-screen display option */
+#define DIAXIS_HUNTING_ROTATE                   0x0D024203 /* Turn body left/right */
+#define DIBUTTON_HUNTING_CROUCH                 0x0D004409 /* Crouch/ Climb / Swim down */
+#define DIBUTTON_HUNTING_JUMP                   0x0D00440A /* Jump/ Climb up / Swim up */
+#define DIBUTTON_HUNTING_FIRESECONDARY          0x0D00440B /* Alternative fire button */
+#define DIBUTTON_HUNTING_LEFT_LINK              0x0D00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_HUNTING_RIGHT_LINK             0x0D00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_HUNTING_FORWARD_LINK           0x0D0144E0 /* Fallback move forward button */
+#define DIBUTTON_HUNTING_BACK_LINK              0x0D0144E8 /* Fallback move back button */
+#define DIBUTTON_HUNTING_ROTATE_LEFT_LINK       0x0D0244E4 /* Fallback turn body left button */
+#define DIBUTTON_HUNTING_ROTATE_RIGHT_LINK      0x0D0244EC /* Fallback turn body right button */
+#define DIBUTTON_HUNTING_DEVICE                 0x0D0044FE /* Show input device and controls */
+#define DIBUTTON_HUNTING_PAUSE                  0x0D0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Fishing
+      Catching Fish is primary objective   ---*/
+#define DIVIRTUAL_SPORTS_FISHING                0x0E000000
+#define DIAXIS_FISHING_LATERAL                  0x0E008201 /* sidestep left/right */
+#define DIAXIS_FISHING_MOVE                     0x0E010202 /* move forward/backwards */
+#define DIBUTTON_FISHING_CAST                   0x0E000401 /* Cast line */
+#define DIBUTTON_FISHING_TYPE                   0x0E000402 /* Select cast type */
+#define DIBUTTON_FISHING_BINOCULAR              0x0E000403 /* Look through Binocular */
+#define DIBUTTON_FISHING_BAIT                   0x0E000404 /* Select type of Bait */
+#define DIBUTTON_FISHING_MAP                    0x0E000405 /* View Map */
+#define DIBUTTON_FISHING_MENU                   0x0E0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_FISHING_GLANCE              0x0E004601 /* Look around */
+#define DIBUTTON_FISHING_DISPLAY                0x0E004406 /* Show next on-screen display option */
+#define DIAXIS_FISHING_ROTATE                   0x0E024203 /* Turn character left / right */
+#define DIBUTTON_FISHING_CROUCH                 0x0E004407 /* Crouch/ Climb / Swim down */
+#define DIBUTTON_FISHING_JUMP                   0x0E004408 /* Jump/ Climb up / Swim up */
+#define DIBUTTON_FISHING_LEFT_LINK              0x0E00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_FISHING_RIGHT_LINK             0x0E00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_FISHING_FORWARD_LINK           0x0E0144E0 /* Fallback move forward button */
+#define DIBUTTON_FISHING_BACK_LINK              0x0E0144E8 /* Fallback move back button */
+#define DIBUTTON_FISHING_ROTATE_LEFT_LINK       0x0E0244E4 /* Fallback turn body left button */
+#define DIBUTTON_FISHING_ROTATE_RIGHT_LINK      0x0E0244EC /* Fallback turn body right button */
+#define DIBUTTON_FISHING_DEVICE                 0x0E0044FE /* Show input device and controls */
+#define DIBUTTON_FISHING_PAUSE                  0x0E0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Baseball - Batting
+      Batter control is primary objective  ---*/
+#define DIVIRTUAL_SPORTS_BASEBALL_BAT           0x0F000000
+#define DIAXIS_BASEBALLB_LATERAL                0x0F008201 /* Aim left / right */
+#define DIAXIS_BASEBALLB_MOVE                   0x0F010202 /* Aim up / down */
+#define DIBUTTON_BASEBALLB_SELECT               0x0F000401 /* cycle through swing options */
+#define DIBUTTON_BASEBALLB_NORMAL               0x0F000402 /* normal swing */
+#define DIBUTTON_BASEBALLB_POWER                0x0F000403 /* swing for the fence */
+#define DIBUTTON_BASEBALLB_BUNT                 0x0F000404 /* bunt */
+#define DIBUTTON_BASEBALLB_STEAL                0x0F000405 /* Base runner attempts to steal a base */
+#define DIBUTTON_BASEBALLB_BURST                0x0F000406 /* Base runner invokes burst of speed */
+#define DIBUTTON_BASEBALLB_SLIDE                0x0F000407 /* Base runner slides into base */
+#define DIBUTTON_BASEBALLB_CONTACT              0x0F000408 /* Contact swing */
+#define DIBUTTON_BASEBALLB_MENU                 0x0F0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_BASEBALLB_NOSTEAL              0x0F004409 /* Base runner goes back to a base */
+#define DIBUTTON_BASEBALLB_BOX                  0x0F00440A /* Enter or exit batting box */
+#define DIBUTTON_BASEBALLB_LEFT_LINK            0x0F00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_BASEBALLB_RIGHT_LINK           0x0F00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_BASEBALLB_FORWARD_LINK         0x0F0144E0 /* Fallback move forward button */
+#define DIBUTTON_BASEBALLB_BACK_LINK            0x0F0144E8 /* Fallback move back button */
+#define DIBUTTON_BASEBALLB_DEVICE               0x0F0044FE /* Show input device and controls */
+#define DIBUTTON_BASEBALLB_PAUSE                0x0F0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Baseball - Pitching
+      Pitcher control is primary objective   ---*/
+#define DIVIRTUAL_SPORTS_BASEBALL_PITCH         0x10000000
+#define DIAXIS_BASEBALLP_LATERAL                0x10008201 /* Aim left / right */
+#define DIAXIS_BASEBALLP_MOVE                   0x10010202 /* Aim up / down */
+#define DIBUTTON_BASEBALLP_SELECT               0x10000401 /* cycle through pitch selections */
+#define DIBUTTON_BASEBALLP_PITCH                0x10000402 /* throw pitch */
+#define DIBUTTON_BASEBALLP_BASE                 0x10000403 /* select base to throw to */
+#define DIBUTTON_BASEBALLP_THROW                0x10000404 /* throw to base */
+#define DIBUTTON_BASEBALLP_FAKE                 0x10000405 /* Fake a throw to a base */
+#define DIBUTTON_BASEBALLP_MENU                 0x100004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_BASEBALLP_WALK                 0x10004406 /* Throw intentional walk / pitch out */
+#define DIBUTTON_BASEBALLP_LOOK                 0x10004407 /* Look at runners on bases */
+#define DIBUTTON_BASEBALLP_LEFT_LINK            0x1000C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_BASEBALLP_RIGHT_LINK           0x1000C4EC /* Fallback sidestep right button */
+#define DIBUTTON_BASEBALLP_FORWARD_LINK         0x100144E0 /* Fallback move forward button */
+#define DIBUTTON_BASEBALLP_BACK_LINK            0x100144E8 /* Fallback move back button */
+#define DIBUTTON_BASEBALLP_DEVICE               0x100044FE /* Show input device and controls */
+#define DIBUTTON_BASEBALLP_PAUSE                0x100044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Baseball - Fielding
+      Fielder control is primary objective  ---*/
+#define DIVIRTUAL_SPORTS_BASEBALL_FIELD         0x11000000
+#define DIAXIS_BASEBALLF_LATERAL                0x11008201 /* Aim left / right */
+#define DIAXIS_BASEBALLF_MOVE                   0x11010202 /* Aim up / down */
+#define DIBUTTON_BASEBALLF_NEAREST              0x11000401 /* Switch to fielder nearest to the ball */
+#define DIBUTTON_BASEBALLF_THROW1               0x11000402 /* Make conservative throw */
+#define DIBUTTON_BASEBALLF_THROW2               0x11000403 /* Make aggressive throw */
+#define DIBUTTON_BASEBALLF_BURST                0x11000404 /* Invoke burst of speed */
+#define DIBUTTON_BASEBALLF_JUMP                 0x11000405 /* Jump to catch ball */
+#define DIBUTTON_BASEBALLF_DIVE                 0x11000406 /* Dive to catch ball */
+#define DIBUTTON_BASEBALLF_MENU                 0x110004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_BASEBALLF_SHIFTIN              0x11004407 /* Shift the infield positioning */
+#define DIBUTTON_BASEBALLF_SHIFTOUT             0x11004408 /* Shift the outfield positioning */
+#define DIBUTTON_BASEBALLF_AIM_LEFT_LINK        0x1100C4E4 /* Fallback aim left button */
+#define DIBUTTON_BASEBALLF_AIM_RIGHT_LINK       0x1100C4EC /* Fallback aim right button */
+#define DIBUTTON_BASEBALLF_FORWARD_LINK         0x110144E0 /* Fallback move forward button */
+#define DIBUTTON_BASEBALLF_BACK_LINK            0x110144E8 /* Fallback move back button */
+#define DIBUTTON_BASEBALLF_DEVICE               0x110044FE /* Show input device and controls */
+#define DIBUTTON_BASEBALLF_PAUSE                0x110044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Basketball - Offense
+      Offense  ---*/
+#define DIVIRTUAL_SPORTS_BASKETBALL_OFFENSE     0x12000000
+#define DIAXIS_BBALLO_LATERAL                   0x12008201 /* left / right */
+#define DIAXIS_BBALLO_MOVE                      0x12010202 /* up / down */
+#define DIBUTTON_BBALLO_SHOOT                   0x12000401 /* shoot basket */
+#define DIBUTTON_BBALLO_DUNK                    0x12000402 /* dunk basket */
+#define DIBUTTON_BBALLO_PASS                    0x12000403 /* throw pass */
+#define DIBUTTON_BBALLO_FAKE                    0x12000404 /* fake shot or pass */
+#define DIBUTTON_BBALLO_SPECIAL                 0x12000405 /* apply special move */
+#define DIBUTTON_BBALLO_PLAYER                  0x12000406 /* select next player */
+#define DIBUTTON_BBALLO_BURST                   0x12000407 /* invoke burst */
+#define DIBUTTON_BBALLO_CALL                    0x12000408 /* call for ball / pass to me */
+#define DIBUTTON_BBALLO_MENU                    0x120004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_BBALLO_GLANCE               0x12004601 /* scroll view */
+#define DIBUTTON_BBALLO_SCREEN                  0x12004409 /* Call for screen */
+#define DIBUTTON_BBALLO_PLAY                    0x1200440A /* Call for specific offensive play */
+#define DIBUTTON_BBALLO_JAB                     0x1200440B /* Initiate fake drive to basket */
+#define DIBUTTON_BBALLO_POST                    0x1200440C /* Perform post move */
+#define DIBUTTON_BBALLO_TIMEOUT                 0x1200440D /* Time Out */
+#define DIBUTTON_BBALLO_SUBSTITUTE              0x1200440E /* substitute one player for another */
+#define DIBUTTON_BBALLO_LEFT_LINK               0x1200C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_BBALLO_RIGHT_LINK              0x1200C4EC /* Fallback sidestep right button */
+#define DIBUTTON_BBALLO_FORWARD_LINK            0x120144E0 /* Fallback move forward button */
+#define DIBUTTON_BBALLO_BACK_LINK               0x120144E8 /* Fallback move back button */
+#define DIBUTTON_BBALLO_DEVICE                  0x120044FE /* Show input device and controls */
+#define DIBUTTON_BBALLO_PAUSE                   0x120044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Basketball - Defense
+      Defense  ---*/
+#define DIVIRTUAL_SPORTS_BASKETBALL_DEFENSE     0x13000000
+#define DIAXIS_BBALLD_LATERAL                   0x13008201 /* left / right */
+#define DIAXIS_BBALLD_MOVE                      0x13010202 /* up / down */
+#define DIBUTTON_BBALLD_JUMP                    0x13000401 /* jump to block shot */
+#define DIBUTTON_BBALLD_STEAL                   0x13000402 /* attempt to steal ball */
+#define DIBUTTON_BBALLD_FAKE                    0x13000403 /* fake block or steal */
+#define DIBUTTON_BBALLD_SPECIAL                 0x13000404 /* apply special move */
+#define DIBUTTON_BBALLD_PLAYER                  0x13000405 /* select next player */
+#define DIBUTTON_BBALLD_BURST                   0x13000406 /* invoke burst */
+#define DIBUTTON_BBALLD_PLAY                    0x13000407 /* call for specific defensive play */
+#define DIBUTTON_BBALLD_MENU                    0x130004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_BBALLD_GLANCE               0x13004601 /* scroll view */
+#define DIBUTTON_BBALLD_TIMEOUT                 0x13004408 /* Time Out */
+#define DIBUTTON_BBALLD_SUBSTITUTE              0x13004409 /* substitute one player for another */
+#define DIBUTTON_BBALLD_LEFT_LINK               0x1300C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_BBALLD_RIGHT_LINK              0x1300C4EC /* Fallback sidestep right button */
+#define DIBUTTON_BBALLD_FORWARD_LINK            0x130144E0 /* Fallback move forward button */
+#define DIBUTTON_BBALLD_BACK_LINK               0x130144E8 /* Fallback move back button */
+#define DIBUTTON_BBALLD_DEVICE                  0x130044FE /* Show input device and controls */
+#define DIBUTTON_BBALLD_PAUSE                   0x130044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Football - Play
+      Play selection  ---*/
+#define DIVIRTUAL_SPORTS_FOOTBALL_FIELD         0x14000000
+#define DIBUTTON_FOOTBALLP_PLAY                 0x14000401 /* cycle through available plays */
+#define DIBUTTON_FOOTBALLP_SELECT               0x14000402 /* select play */
+#define DIBUTTON_FOOTBALLP_HELP                 0x14000403 /* Bring up pop-up help */
+#define DIBUTTON_FOOTBALLP_MENU                 0x140004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_FOOTBALLP_DEVICE               0x140044FE /* Show input device and controls */
+#define DIBUTTON_FOOTBALLP_PAUSE                0x140044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Football - QB
+      Offense: Quarterback / Kicker  ---*/
+#define DIVIRTUAL_SPORTS_FOOTBALL_QBCK          0x15000000
+#define DIAXIS_FOOTBALLQ_LATERAL                0x15008201 /* Move / Aim: left / right */
+#define DIAXIS_FOOTBALLQ_MOVE                   0x15010202 /* Move / Aim: up / down */
+#define DIBUTTON_FOOTBALLQ_SELECT               0x15000401 /* Select */
+#define DIBUTTON_FOOTBALLQ_SNAP                 0x15000402 /* snap ball - start play */
+#define DIBUTTON_FOOTBALLQ_JUMP                 0x15000403 /* jump over defender */
+#define DIBUTTON_FOOTBALLQ_SLIDE                0x15000404 /* Dive/Slide */
+#define DIBUTTON_FOOTBALLQ_PASS                 0x15000405 /* throws pass to receiver */
+#define DIBUTTON_FOOTBALLQ_FAKE                 0x15000406 /* pump fake pass or fake kick */
+#define DIBUTTON_FOOTBALLQ_MENU                 0x150004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_FOOTBALLQ_FAKESNAP             0x15004407 /* Fake snap  */
+#define DIBUTTON_FOOTBALLQ_MOTION               0x15004408 /* Send receivers in motion */
+#define DIBUTTON_FOOTBALLQ_AUDIBLE              0x15004409 /* Change offensive play at line of scrimmage */
+#define DIBUTTON_FOOTBALLQ_LEFT_LINK            0x1500C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_FOOTBALLQ_RIGHT_LINK           0x1500C4EC /* Fallback sidestep right button */
+#define DIBUTTON_FOOTBALLQ_FORWARD_LINK         0x150144E0 /* Fallback move forward button */
+#define DIBUTTON_FOOTBALLQ_BACK_LINK            0x150144E8 /* Fallback move back button */
+#define DIBUTTON_FOOTBALLQ_DEVICE               0x150044FE /* Show input device and controls */
+#define DIBUTTON_FOOTBALLQ_PAUSE                0x150044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Football - Offense
+      Offense - Runner  ---*/
+#define DIVIRTUAL_SPORTS_FOOTBALL_OFFENSE       0x16000000
+#define DIAXIS_FOOTBALLO_LATERAL                0x16008201 /* Move / Aim: left / right */
+#define DIAXIS_FOOTBALLO_MOVE                   0x16010202 /* Move / Aim: up / down */
+#define DIBUTTON_FOOTBALLO_JUMP                 0x16000401 /* jump or hurdle over defender */
+#define DIBUTTON_FOOTBALLO_LEFTARM              0x16000402 /* holds out left arm */
+#define DIBUTTON_FOOTBALLO_RIGHTARM             0x16000403 /* holds out right arm */
+#define DIBUTTON_FOOTBALLO_THROW                0x16000404 /* throw pass or lateral ball to another runner */
+#define DIBUTTON_FOOTBALLO_SPIN                 0x16000405 /* Spin to avoid defenders */
+#define DIBUTTON_FOOTBALLO_MENU                 0x160004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_FOOTBALLO_JUKE                 0x16004406 /* Use special move to avoid defenders */
+#define DIBUTTON_FOOTBALLO_SHOULDER             0x16004407 /* Lower shoulder to run over defenders */
+#define DIBUTTON_FOOTBALLO_TURBO                0x16004408 /* Speed burst past defenders */
+#define DIBUTTON_FOOTBALLO_DIVE                 0x16004409 /* Dive over defenders */
+#define DIBUTTON_FOOTBALLO_ZOOM                 0x1600440A /* Zoom view in / out */
+#define DIBUTTON_FOOTBALLO_SUBSTITUTE           0x1600440B /* substitute one player for another */
+#define DIBUTTON_FOOTBALLO_LEFT_LINK            0x1600C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_FOOTBALLO_RIGHT_LINK           0x1600C4EC /* Fallback sidestep right button */
+#define DIBUTTON_FOOTBALLO_FORWARD_LINK         0x160144E0 /* Fallback move forward button */
+#define DIBUTTON_FOOTBALLO_BACK_LINK            0x160144E8 /* Fallback move back button */
+#define DIBUTTON_FOOTBALLO_DEVICE               0x160044FE /* Show input device and controls */
+#define DIBUTTON_FOOTBALLO_PAUSE                0x160044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Football - Defense
+      Defense     ---*/
+#define DIVIRTUAL_SPORTS_FOOTBALL_DEFENSE       0x17000000
+#define DIAXIS_FOOTBALLD_LATERAL                0x17008201 /* Move / Aim: left / right */
+#define DIAXIS_FOOTBALLD_MOVE                   0x17010202 /* Move / Aim: up / down */
+#define DIBUTTON_FOOTBALLD_PLAY                 0x17000401 /* cycle through available plays */
+#define DIBUTTON_FOOTBALLD_SELECT               0x17000402 /* select player closest to the ball */
+#define DIBUTTON_FOOTBALLD_JUMP                 0x17000403 /* jump to intercept or block */
+#define DIBUTTON_FOOTBALLD_TACKLE               0x17000404 /* tackler runner */
+#define DIBUTTON_FOOTBALLD_FAKE                 0x17000405 /* hold down to fake tackle or intercept */
+#define DIBUTTON_FOOTBALLD_SUPERTACKLE          0x17000406 /* Initiate special tackle */
+#define DIBUTTON_FOOTBALLD_MENU                 0x170004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_FOOTBALLD_SPIN                 0x17004407 /* Spin to beat offensive line */
+#define DIBUTTON_FOOTBALLD_SWIM                 0x17004408 /* Swim to beat the offensive line */
+#define DIBUTTON_FOOTBALLD_BULLRUSH             0x17004409 /* Bull rush the offensive line */
+#define DIBUTTON_FOOTBALLD_RIP                  0x1700440A /* Rip the offensive line */
+#define DIBUTTON_FOOTBALLD_AUDIBLE              0x1700440B /* Change defensive play at the line of scrimmage */
+#define DIBUTTON_FOOTBALLD_ZOOM                 0x1700440C /* Zoom view in / out */
+#define DIBUTTON_FOOTBALLD_SUBSTITUTE           0x1700440D /* substitute one player for another */
+#define DIBUTTON_FOOTBALLD_LEFT_LINK            0x1700C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_FOOTBALLD_RIGHT_LINK           0x1700C4EC /* Fallback sidestep right button */
+#define DIBUTTON_FOOTBALLD_FORWARD_LINK         0x170144E0 /* Fallback move forward button */
+#define DIBUTTON_FOOTBALLD_BACK_LINK            0x170144E8 /* Fallback move back button */
+#define DIBUTTON_FOOTBALLD_DEVICE               0x170044FE /* Show input device and controls */
+#define DIBUTTON_FOOTBALLD_PAUSE                0x170044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Golf
+                                ---*/
+#define DIVIRTUAL_SPORTS_GOLF                   0x18000000
+#define DIAXIS_GOLF_LATERAL                     0x18008201 /* Move / Aim: left / right */
+#define DIAXIS_GOLF_MOVE                        0x18010202 /* Move / Aim: up / down */
+#define DIBUTTON_GOLF_SWING                     0x18000401 /* swing club */
+#define DIBUTTON_GOLF_SELECT                    0x18000402 /* cycle between: club / swing strength / ball arc / ball spin */
+#define DIBUTTON_GOLF_UP                        0x18000403 /* increase selection */
+#define DIBUTTON_GOLF_DOWN                      0x18000404 /* decrease selection */
+#define DIBUTTON_GOLF_TERRAIN                   0x18000405 /* shows terrain detail */
+#define DIBUTTON_GOLF_FLYBY                     0x18000406 /* view the hole via a flyby */
+#define DIBUTTON_GOLF_MENU                      0x180004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_GOLF_SCROLL                 0x18004601 /* scroll view */
+#define DIBUTTON_GOLF_ZOOM                      0x18004407 /* Zoom view in / out */
+#define DIBUTTON_GOLF_TIMEOUT                   0x18004408 /* Call for time out */
+#define DIBUTTON_GOLF_SUBSTITUTE                0x18004409 /* substitute one player for another */
+#define DIBUTTON_GOLF_LEFT_LINK                 0x1800C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_GOLF_RIGHT_LINK                0x1800C4EC /* Fallback sidestep right button */
+#define DIBUTTON_GOLF_FORWARD_LINK              0x180144E0 /* Fallback move forward button */
+#define DIBUTTON_GOLF_BACK_LINK                 0x180144E8 /* Fallback move back button */
+#define DIBUTTON_GOLF_DEVICE                    0x180044FE /* Show input device and controls */
+#define DIBUTTON_GOLF_PAUSE                     0x180044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Hockey - Offense
+      Offense       ---*/
+#define DIVIRTUAL_SPORTS_HOCKEY_OFFENSE         0x19000000
+#define DIAXIS_HOCKEYO_LATERAL                  0x19008201 /* Move / Aim: left / right */
+#define DIAXIS_HOCKEYO_MOVE                     0x19010202 /* Move / Aim: up / down */
+#define DIBUTTON_HOCKEYO_SHOOT                  0x19000401 /* Shoot */
+#define DIBUTTON_HOCKEYO_PASS                   0x19000402 /* pass the puck */
+#define DIBUTTON_HOCKEYO_BURST                  0x19000403 /* invoke speed burst */
+#define DIBUTTON_HOCKEYO_SPECIAL                0x19000404 /* invoke special move */
+#define DIBUTTON_HOCKEYO_FAKE                   0x19000405 /* hold down to fake pass or kick */
+#define DIBUTTON_HOCKEYO_MENU                   0x190004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_HOCKEYO_SCROLL              0x19004601 /* scroll view */
+#define DIBUTTON_HOCKEYO_ZOOM                   0x19004406 /* Zoom view in / out */
+#define DIBUTTON_HOCKEYO_STRATEGY               0x19004407 /* Invoke coaching menu for strategy help */
+#define DIBUTTON_HOCKEYO_TIMEOUT                0x19004408 /* Call for time out */
+#define DIBUTTON_HOCKEYO_SUBSTITUTE             0x19004409 /* substitute one player for another */
+#define DIBUTTON_HOCKEYO_LEFT_LINK              0x1900C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_HOCKEYO_RIGHT_LINK             0x1900C4EC /* Fallback sidestep right button */
+#define DIBUTTON_HOCKEYO_FORWARD_LINK           0x190144E0 /* Fallback move forward button */
+#define DIBUTTON_HOCKEYO_BACK_LINK              0x190144E8 /* Fallback move back button */
+#define DIBUTTON_HOCKEYO_DEVICE                 0x190044FE /* Show input device and controls */
+#define DIBUTTON_HOCKEYO_PAUSE                  0x190044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Hockey - Defense
+      Defense       ---*/
+#define DIVIRTUAL_SPORTS_HOCKEY_DEFENSE         0x1A000000
+#define DIAXIS_HOCKEYD_LATERAL                  0x1A008201 /* Move / Aim: left / right */
+#define DIAXIS_HOCKEYD_MOVE                     0x1A010202 /* Move / Aim: up / down */
+#define DIBUTTON_HOCKEYD_PLAYER                 0x1A000401 /* control player closest to the puck */
+#define DIBUTTON_HOCKEYD_STEAL                  0x1A000402 /* attempt steal */
+#define DIBUTTON_HOCKEYD_BURST                  0x1A000403 /* speed burst or body check */
+#define DIBUTTON_HOCKEYD_BLOCK                  0x1A000404 /* block puck */
+#define DIBUTTON_HOCKEYD_FAKE                   0x1A000405 /* hold down to fake tackle or intercept */
+#define DIBUTTON_HOCKEYD_MENU                   0x1A0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_HOCKEYD_SCROLL              0x1A004601 /* scroll view */
+#define DIBUTTON_HOCKEYD_ZOOM                   0x1A004406 /* Zoom view in / out */
+#define DIBUTTON_HOCKEYD_STRATEGY               0x1A004407 /* Invoke coaching menu for strategy help */
+#define DIBUTTON_HOCKEYD_TIMEOUT                0x1A004408 /* Call for time out */
+#define DIBUTTON_HOCKEYD_SUBSTITUTE             0x1A004409 /* substitute one player for another */
+#define DIBUTTON_HOCKEYD_LEFT_LINK              0x1A00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_HOCKEYD_RIGHT_LINK             0x1A00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_HOCKEYD_FORWARD_LINK           0x1A0144E0 /* Fallback move forward button */
+#define DIBUTTON_HOCKEYD_BACK_LINK              0x1A0144E8 /* Fallback move back button */
+#define DIBUTTON_HOCKEYD_DEVICE                 0x1A0044FE /* Show input device and controls */
+#define DIBUTTON_HOCKEYD_PAUSE                  0x1A0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Hockey - Goalie
+      Goal tending  ---*/
+#define DIVIRTUAL_SPORTS_HOCKEY_GOALIE          0x1B000000
+#define DIAXIS_HOCKEYG_LATERAL                  0x1B008201 /* Move / Aim: left / right */
+#define DIAXIS_HOCKEYG_MOVE                     0x1B010202 /* Move / Aim: up / down */
+#define DIBUTTON_HOCKEYG_PASS                   0x1B000401 /* pass puck */
+#define DIBUTTON_HOCKEYG_POKE                   0x1B000402 /* poke / check / hack */
+#define DIBUTTON_HOCKEYG_STEAL                  0x1B000403 /* attempt steal */
+#define DIBUTTON_HOCKEYG_BLOCK                  0x1B000404 /* block puck */
+#define DIBUTTON_HOCKEYG_MENU                   0x1B0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_HOCKEYG_SCROLL              0x1B004601 /* scroll view */
+#define DIBUTTON_HOCKEYG_ZOOM                   0x1B004405 /* Zoom view in / out */
+#define DIBUTTON_HOCKEYG_STRATEGY               0x1B004406 /* Invoke coaching menu for strategy help */
+#define DIBUTTON_HOCKEYG_TIMEOUT                0x1B004407 /* Call for time out */
+#define DIBUTTON_HOCKEYG_SUBSTITUTE             0x1B004408 /* substitute one player for another */
+#define DIBUTTON_HOCKEYG_LEFT_LINK              0x1B00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_HOCKEYG_RIGHT_LINK             0x1B00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_HOCKEYG_FORWARD_LINK           0x1B0144E0 /* Fallback move forward button */
+#define DIBUTTON_HOCKEYG_BACK_LINK              0x1B0144E8 /* Fallback move back button */
+#define DIBUTTON_HOCKEYG_DEVICE                 0x1B0044FE /* Show input device and controls */
+#define DIBUTTON_HOCKEYG_PAUSE                  0x1B0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Mountain Biking
+                     ---*/
+#define DIVIRTUAL_SPORTS_BIKING_MOUNTAIN        0x1C000000
+#define DIAXIS_BIKINGM_TURN                     0x1C008201 /* left / right */
+#define DIAXIS_BIKINGM_PEDAL                    0x1C010202 /* Pedal faster / slower / brake */
+#define DIBUTTON_BIKINGM_JUMP                   0x1C000401 /* jump over obstacle */
+#define DIBUTTON_BIKINGM_CAMERA                 0x1C000402 /* switch Camera view */
+#define DIBUTTON_BIKINGM_SPECIAL1               0x1C000403 /* perform first special move */
+#define DIBUTTON_BIKINGM_SELECT                 0x1C000404 /* Select */
+#define DIBUTTON_BIKINGM_SPECIAL2               0x1C000405 /* perform second special move */
+#define DIBUTTON_BIKINGM_MENU                   0x1C0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_BIKINGM_SCROLL              0x1C004601 /* scroll view */
+#define DIBUTTON_BIKINGM_ZOOM                   0x1C004406 /* Zoom view in / out */
+#define DIAXIS_BIKINGM_BRAKE                    0x1C044203 /* Brake axis  */
+#define DIBUTTON_BIKINGM_LEFT_LINK              0x1C00C4E4 /* Fallback turn left button */
+#define DIBUTTON_BIKINGM_RIGHT_LINK             0x1C00C4EC /* Fallback turn right button */
+#define DIBUTTON_BIKINGM_FASTER_LINK            0x1C0144E0 /* Fallback pedal faster button */
+#define DIBUTTON_BIKINGM_SLOWER_LINK            0x1C0144E8 /* Fallback pedal slower button */
+#define DIBUTTON_BIKINGM_BRAKE_BUTTON_LINK      0x1C0444E8 /* Fallback brake button */
+#define DIBUTTON_BIKINGM_DEVICE                 0x1C0044FE /* Show input device and controls */
+#define DIBUTTON_BIKINGM_PAUSE                  0x1C0044FC /* Start / Pause / Restart game */
+
+/*--- Sports: Skiing / Snowboarding / Skateboarding
+        ---*/
+#define DIVIRTUAL_SPORTS_SKIING                 0x1D000000
+#define DIAXIS_SKIING_TURN                      0x1D008201 /* left / right */
+#define DIAXIS_SKIING_SPEED                     0x1D010202 /* faster / slower */
+#define DIBUTTON_SKIING_JUMP                    0x1D000401 /* Jump */
+#define DIBUTTON_SKIING_CROUCH                  0x1D000402 /* crouch down */
+#define DIBUTTON_SKIING_CAMERA                  0x1D000403 /* switch Camera view */
+#define DIBUTTON_SKIING_SPECIAL1                0x1D000404 /* perform first special move */
+#define DIBUTTON_SKIING_SELECT                  0x1D000405 /* Select */
+#define DIBUTTON_SKIING_SPECIAL2                0x1D000406 /* perform second special move */
+#define DIBUTTON_SKIING_MENU                    0x1D0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_SKIING_GLANCE               0x1D004601 /* scroll view */
+#define DIBUTTON_SKIING_ZOOM                    0x1D004407 /* Zoom view in / out */
+#define DIBUTTON_SKIING_LEFT_LINK               0x1D00C4E4 /* Fallback turn left button */
+#define DIBUTTON_SKIING_RIGHT_LINK              0x1D00C4EC /* Fallback turn right button */
+#define DIBUTTON_SKIING_FASTER_LINK             0x1D0144E0 /* Fallback increase speed button */
+#define DIBUTTON_SKIING_SLOWER_LINK             0x1D0144E8 /* Fallback decrease speed button */
+#define DIBUTTON_SKIING_DEVICE                  0x1D0044FE /* Show input device and controls */
+#define DIBUTTON_SKIING_PAUSE                   0x1D0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Soccer - Offense
+      Offense       ---*/
+#define DIVIRTUAL_SPORTS_SOCCER_OFFENSE         0x1E000000
+#define DIAXIS_SOCCERO_LATERAL                  0x1E008201 /* Move / Aim: left / right */
+#define DIAXIS_SOCCERO_MOVE                     0x1E010202 /* Move / Aim: up / down */
+#define DIAXIS_SOCCERO_BEND                     0x1E018203 /* Bend to soccer shot/pass */
+#define DIBUTTON_SOCCERO_SHOOT                  0x1E000401 /* Shoot the ball */
+#define DIBUTTON_SOCCERO_PASS                   0x1E000402 /* Pass  */
+#define DIBUTTON_SOCCERO_FAKE                   0x1E000403 /* Fake */
+#define DIBUTTON_SOCCERO_PLAYER                 0x1E000404 /* Select next player */
+#define DIBUTTON_SOCCERO_SPECIAL1               0x1E000405 /* Apply special move */
+#define DIBUTTON_SOCCERO_SELECT                 0x1E000406 /* Select special move */
+#define DIBUTTON_SOCCERO_MENU                   0x1E0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_SOCCERO_GLANCE              0x1E004601 /* scroll view */
+#define DIBUTTON_SOCCERO_SUBSTITUTE             0x1E004407 /* Substitute one player for another */
+#define DIBUTTON_SOCCERO_SHOOTLOW               0x1E004408 /* Shoot the ball low */
+#define DIBUTTON_SOCCERO_SHOOTHIGH              0x1E004409 /* Shoot the ball high */
+#define DIBUTTON_SOCCERO_PASSTHRU               0x1E00440A /* Make a thru pass */
+#define DIBUTTON_SOCCERO_SPRINT                 0x1E00440B /* Sprint / turbo boost */
+#define DIBUTTON_SOCCERO_CONTROL                0x1E00440C /* Obtain control of the ball */
+#define DIBUTTON_SOCCERO_HEAD                   0x1E00440D /* Attempt to head the ball */
+#define DIBUTTON_SOCCERO_LEFT_LINK              0x1E00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_SOCCERO_RIGHT_LINK             0x1E00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_SOCCERO_FORWARD_LINK           0x1E0144E0 /* Fallback move forward button */
+#define DIBUTTON_SOCCERO_BACK_LINK              0x1E0144E8 /* Fallback move back button */
+#define DIBUTTON_SOCCERO_DEVICE                 0x1E0044FE /* Show input device and controls */
+#define DIBUTTON_SOCCERO_PAUSE                  0x1E0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Soccer - Defense
+      Defense       ---*/
+#define DIVIRTUAL_SPORTS_SOCCER_DEFENSE         0x1F000000
+#define DIAXIS_SOCCERD_LATERAL                  0x1F008201 /* Move / Aim: left / right */
+#define DIAXIS_SOCCERD_MOVE                     0x1F010202 /* Move / Aim: up / down */
+#define DIBUTTON_SOCCERD_BLOCK                  0x1F000401 /* Attempt to block shot */
+#define DIBUTTON_SOCCERD_STEAL                  0x1F000402 /* Attempt to steal ball */
+#define DIBUTTON_SOCCERD_FAKE                   0x1F000403 /* Fake a block or a steal */
+#define DIBUTTON_SOCCERD_PLAYER                 0x1F000404 /* Select next player */
+#define DIBUTTON_SOCCERD_SPECIAL                0x1F000405 /* Apply special move */
+#define DIBUTTON_SOCCERD_SELECT                 0x1F000406 /* Select special move */
+#define DIBUTTON_SOCCERD_SLIDE                  0x1F000407 /* Attempt a slide tackle */
+#define DIBUTTON_SOCCERD_MENU                   0x1F0004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_SOCCERD_GLANCE              0x1F004601 /* scroll view */
+#define DIBUTTON_SOCCERD_FOUL                   0x1F004408 /* Initiate a foul / hard-foul */
+#define DIBUTTON_SOCCERD_HEAD                   0x1F004409 /* Attempt a Header */
+#define DIBUTTON_SOCCERD_CLEAR                  0x1F00440A /* Attempt to clear the ball down the field */
+#define DIBUTTON_SOCCERD_GOALIECHARGE           0x1F00440B /* Make the goalie charge out of the box */
+#define DIBUTTON_SOCCERD_SUBSTITUTE             0x1F00440C /* Substitute one player for another */
+#define DIBUTTON_SOCCERD_LEFT_LINK              0x1F00C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_SOCCERD_RIGHT_LINK             0x1F00C4EC /* Fallback sidestep right button */
+#define DIBUTTON_SOCCERD_FORWARD_LINK           0x1F0144E0 /* Fallback move forward button */
+#define DIBUTTON_SOCCERD_BACK_LINK              0x1F0144E8 /* Fallback move back button */
+#define DIBUTTON_SOCCERD_DEVICE                 0x1F0044FE /* Show input device and controls */
+#define DIBUTTON_SOCCERD_PAUSE                  0x1F0044FC /* Start / Pause / Restart game */
+
+/*--- Sports - Racquet
+      Tennis - Table-Tennis - Squash   ---*/
+#define DIVIRTUAL_SPORTS_RACQUET                0x20000000
+#define DIAXIS_RACQUET_LATERAL                  0x20008201 /* Move / Aim: left / right */
+#define DIAXIS_RACQUET_MOVE                     0x20010202 /* Move / Aim: up / down */
+#define DIBUTTON_RACQUET_SWING                  0x20000401 /* Swing racquet */
+#define DIBUTTON_RACQUET_BACKSWING              0x20000402 /* Swing backhand */
+#define DIBUTTON_RACQUET_SMASH                  0x20000403 /* Smash shot */
+#define DIBUTTON_RACQUET_SPECIAL                0x20000404 /* Special shot */
+#define DIBUTTON_RACQUET_SELECT                 0x20000405 /* Select special shot */
+#define DIBUTTON_RACQUET_MENU                   0x200004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_RACQUET_GLANCE              0x20004601 /* scroll view */
+#define DIBUTTON_RACQUET_TIMEOUT                0x20004406 /* Call for time out */
+#define DIBUTTON_RACQUET_SUBSTITUTE             0x20004407 /* Substitute one player for another */
+#define DIBUTTON_RACQUET_LEFT_LINK              0x2000C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_RACQUET_RIGHT_LINK             0x2000C4EC /* Fallback sidestep right button */
+#define DIBUTTON_RACQUET_FORWARD_LINK           0x200144E0 /* Fallback move forward button */
+#define DIBUTTON_RACQUET_BACK_LINK              0x200144E8 /* Fallback move back button */
+#define DIBUTTON_RACQUET_DEVICE                 0x200044FE /* Show input device and controls */
+#define DIBUTTON_RACQUET_PAUSE                  0x200044FC /* Start / Pause / Restart game */
+
+/*--- Arcade- 2D
+      Side to Side movement        ---*/
+#define DIVIRTUAL_ARCADE_SIDE2SIDE              0x21000000
+#define DIAXIS_ARCADES_LATERAL                  0x21008201 /* left / right */
+#define DIAXIS_ARCADES_MOVE                     0x21010202 /* up / down */
+#define DIBUTTON_ARCADES_THROW                  0x21000401 /* throw object */
+#define DIBUTTON_ARCADES_CARRY                  0x21000402 /* carry object */
+#define DIBUTTON_ARCADES_ATTACK                 0x21000403 /* attack */
+#define DIBUTTON_ARCADES_SPECIAL                0x21000404 /* apply special move */
+#define DIBUTTON_ARCADES_SELECT                 0x21000405 /* select special move */
+#define DIBUTTON_ARCADES_MENU                   0x210004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_ARCADES_VIEW                0x21004601 /* scroll view left / right / up / down */
+#define DIBUTTON_ARCADES_LEFT_LINK              0x2100C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_ARCADES_RIGHT_LINK             0x2100C4EC /* Fallback sidestep right button */
+#define DIBUTTON_ARCADES_FORWARD_LINK           0x210144E0 /* Fallback move forward button */
+#define DIBUTTON_ARCADES_BACK_LINK              0x210144E8 /* Fallback move back button */
+#define DIBUTTON_ARCADES_VIEW_UP_LINK           0x2107C4E0 /* Fallback scroll view up button */
+#define DIBUTTON_ARCADES_VIEW_DOWN_LINK         0x2107C4E8 /* Fallback scroll view down button */
+#define DIBUTTON_ARCADES_VIEW_LEFT_LINK         0x2107C4E4 /* Fallback scroll view left button */
+#define DIBUTTON_ARCADES_VIEW_RIGHT_LINK        0x2107C4EC /* Fallback scroll view right button */
+#define DIBUTTON_ARCADES_DEVICE                 0x210044FE /* Show input device and controls */
+#define DIBUTTON_ARCADES_PAUSE                  0x210044FC /* Start / Pause / Restart game */
+
+/*--- Arcade - Platform Game
+      Character moves around on screen  ---*/
+#define DIVIRTUAL_ARCADE_PLATFORM               0x22000000
+#define DIAXIS_ARCADEP_LATERAL                  0x22008201 /* Left / right */
+#define DIAXIS_ARCADEP_MOVE                     0x22010202 /* Up / down */
+#define DIBUTTON_ARCADEP_JUMP                   0x22000401 /* Jump */
+#define DIBUTTON_ARCADEP_FIRE                   0x22000402 /* Fire */
+#define DIBUTTON_ARCADEP_CROUCH                 0x22000403 /* Crouch */
+#define DIBUTTON_ARCADEP_SPECIAL                0x22000404 /* Apply special move */
+#define DIBUTTON_ARCADEP_SELECT                 0x22000405 /* Select special move */
+#define DIBUTTON_ARCADEP_MENU                   0x220004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_ARCADEP_VIEW                0x22004601 /* Scroll view */
+#define DIBUTTON_ARCADEP_FIRESECONDARY          0x22004406 /* Alternative fire button */
+#define DIBUTTON_ARCADEP_LEFT_LINK              0x2200C4E4 /* Fallback sidestep left button */
+#define DIBUTTON_ARCADEP_RIGHT_LINK             0x2200C4EC /* Fallback sidestep right button */
+#define DIBUTTON_ARCADEP_FORWARD_LINK           0x220144E0 /* Fallback move forward button */
+#define DIBUTTON_ARCADEP_BACK_LINK              0x220144E8 /* Fallback move back button */
+#define DIBUTTON_ARCADEP_VIEW_UP_LINK           0x2207C4E0 /* Fallback scroll view up button */
+#define DIBUTTON_ARCADEP_VIEW_DOWN_LINK         0x2207C4E8 /* Fallback scroll view down button */
+#define DIBUTTON_ARCADEP_VIEW_LEFT_LINK         0x2207C4E4 /* Fallback scroll view left button */
+#define DIBUTTON_ARCADEP_VIEW_RIGHT_LINK        0x2207C4EC /* Fallback scroll view right button */
+#define DIBUTTON_ARCADEP_DEVICE                 0x220044FE /* Show input device and controls */
+#define DIBUTTON_ARCADEP_PAUSE                  0x220044FC /* Start / Pause / Restart game */
+
+/*--- CAD - 2D Object Control
+      Controls to select and move objects in 2D  ---*/
+#define DIVIRTUAL_CAD_2DCONTROL                 0x23000000
+#define DIAXIS_2DCONTROL_LATERAL                0x23008201 /* Move view left / right */
+#define DIAXIS_2DCONTROL_MOVE                   0x23010202 /* Move view up / down */
+#define DIAXIS_2DCONTROL_INOUT                  0x23018203 /* Zoom - in / out */
+#define DIBUTTON_2DCONTROL_SELECT               0x23000401 /* Select Object */
+#define DIBUTTON_2DCONTROL_SPECIAL1             0x23000402 /* Do first special operation */
+#define DIBUTTON_2DCONTROL_SPECIAL              0x23000403 /* Select special operation */
+#define DIBUTTON_2DCONTROL_SPECIAL2             0x23000404 /* Do second special operation */
+#define DIBUTTON_2DCONTROL_MENU                 0x230004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_2DCONTROL_HATSWITCH         0x23004601 /* Hat switch */
+#define DIAXIS_2DCONTROL_ROTATEZ                0x23024204 /* Rotate view clockwise / counterclockwise */
+#define DIBUTTON_2DCONTROL_DISPLAY              0x23004405 /* Shows next on-screen display options */
+#define DIBUTTON_2DCONTROL_DEVICE               0x230044FE /* Show input device and controls */
+#define DIBUTTON_2DCONTROL_PAUSE                0x230044FC /* Start / Pause / Restart game */
+
+/*--- CAD - 3D object control
+      Controls to select and move objects within a 3D environment  ---*/
+#define DIVIRTUAL_CAD_3DCONTROL                 0x24000000
+#define DIAXIS_3DCONTROL_LATERAL                0x24008201 /* Move view left / right */
+#define DIAXIS_3DCONTROL_MOVE                   0x24010202 /* Move view up / down */
+#define DIAXIS_3DCONTROL_INOUT                  0x24018203 /* Zoom - in / out */
+#define DIBUTTON_3DCONTROL_SELECT               0x24000401 /* Select Object */
+#define DIBUTTON_3DCONTROL_SPECIAL1             0x24000402 /* Do first special operation */
+#define DIBUTTON_3DCONTROL_SPECIAL              0x24000403 /* Select special operation */
+#define DIBUTTON_3DCONTROL_SPECIAL2             0x24000404 /* Do second special operation */
+#define DIBUTTON_3DCONTROL_MENU                 0x240004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_3DCONTROL_HATSWITCH         0x24004601 /* Hat switch */
+#define DIAXIS_3DCONTROL_ROTATEX                0x24034204 /* Rotate view forward or up / backward or down */
+#define DIAXIS_3DCONTROL_ROTATEY                0x2402C205 /* Rotate view clockwise / counterclockwise */
+#define DIAXIS_3DCONTROL_ROTATEZ                0x24024206 /* Rotate view left / right */
+#define DIBUTTON_3DCONTROL_DISPLAY              0x24004405 /* Show next on-screen display options */
+#define DIBUTTON_3DCONTROL_DEVICE               0x240044FE /* Show input device and controls */
+#define DIBUTTON_3DCONTROL_PAUSE                0x240044FC /* Start / Pause / Restart game */
+
+/*--- CAD - 3D Navigation - Fly through
+      Controls for 3D modeling  ---*/
+#define DIVIRTUAL_CAD_FLYBY                     0x25000000
+#define DIAXIS_CADF_LATERAL                     0x25008201 /* move view left / right */
+#define DIAXIS_CADF_MOVE                        0x25010202 /* move view up / down */
+#define DIAXIS_CADF_INOUT                       0x25018203 /* in / out */
+#define DIBUTTON_CADF_SELECT                    0x25000401 /* Select Object */
+#define DIBUTTON_CADF_SPECIAL1                  0x25000402 /* do first special operation */
+#define DIBUTTON_CADF_SPECIAL                   0x25000403 /* Select special operation */
+#define DIBUTTON_CADF_SPECIAL2                  0x25000404 /* do second special operation */
+#define DIBUTTON_CADF_MENU                      0x250004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_CADF_HATSWITCH              0x25004601 /* Hat switch */
+#define DIAXIS_CADF_ROTATEX                     0x25034204 /* Rotate view forward or up / backward or down */
+#define DIAXIS_CADF_ROTATEY                     0x2502C205 /* Rotate view clockwise / counterclockwise */
+#define DIAXIS_CADF_ROTATEZ                     0x25024206 /* Rotate view left / right */
+#define DIBUTTON_CADF_DISPLAY                   0x25004405 /* shows next on-screen display options */
+#define DIBUTTON_CADF_DEVICE                    0x250044FE /* Show input device and controls */
+#define DIBUTTON_CADF_PAUSE                     0x250044FC /* Start / Pause / Restart game */
+
+/*--- CAD - 3D Model Control
+      Controls for 3D modeling  ---*/
+#define DIVIRTUAL_CAD_MODEL                     0x26000000
+#define DIAXIS_CADM_LATERAL                     0x26008201 /* move view left / right */
+#define DIAXIS_CADM_MOVE                        0x26010202 /* move view up / down */
+#define DIAXIS_CADM_INOUT                       0x26018203 /* in / out */
+#define DIBUTTON_CADM_SELECT                    0x26000401 /* Select Object */
+#define DIBUTTON_CADM_SPECIAL1                  0x26000402 /* do first special operation */
+#define DIBUTTON_CADM_SPECIAL                   0x26000403 /* Select special operation */
+#define DIBUTTON_CADM_SPECIAL2                  0x26000404 /* do second special operation */
+#define DIBUTTON_CADM_MENU                      0x260004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIHATSWITCH_CADM_HATSWITCH              0x26004601 /* Hat switch */
+#define DIAXIS_CADM_ROTATEX                     0x26034204 /* Rotate view forward or up / backward or down */
+#define DIAXIS_CADM_ROTATEY                     0x2602C205 /* Rotate view clockwise / counterclockwise */
+#define DIAXIS_CADM_ROTATEZ                     0x26024206 /* Rotate view left / right */
+#define DIBUTTON_CADM_DISPLAY                   0x26004405 /* shows next on-screen display options */
+#define DIBUTTON_CADM_DEVICE                    0x260044FE /* Show input device and controls */
+#define DIBUTTON_CADM_PAUSE                     0x260044FC /* Start / Pause / Restart game */
+
+/*--- Control - Media Equipment
+      Remote        ---*/
+#define DIVIRTUAL_REMOTE_CONTROL                0x27000000
+#define DIAXIS_REMOTE_SLIDER                    0x27050201 /* Slider for adjustment: volume / color / bass / etc */
+#define DIBUTTON_REMOTE_MUTE                    0x27000401 /* Set volume on current device to zero */
+#define DIBUTTON_REMOTE_SELECT                  0x27000402 /* Next/previous: channel/ track / chapter / picture / station */
+#define DIBUTTON_REMOTE_PLAY                    0x27002403 /* Start or pause entertainment on current device */
+#define DIBUTTON_REMOTE_CUE                     0x27002404 /* Move through current media */
+#define DIBUTTON_REMOTE_REVIEW                  0x27002405 /* Move through current media */
+#define DIBUTTON_REMOTE_CHANGE                  0x27002406 /* Select next device */
+#define DIBUTTON_REMOTE_RECORD                  0x27002407 /* Start recording the current media */
+#define DIBUTTON_REMOTE_MENU                    0x270004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIAXIS_REMOTE_SLIDER2                   0x27054202 /* Slider for adjustment: volume */
+#define DIBUTTON_REMOTE_TV                      0x27005C08 /* Select TV */
+#define DIBUTTON_REMOTE_CABLE                   0x27005C09 /* Select cable box */
+#define DIBUTTON_REMOTE_CD                      0x27005C0A /* Select CD player */
+#define DIBUTTON_REMOTE_VCR                     0x27005C0B /* Select VCR */
+#define DIBUTTON_REMOTE_TUNER                   0x27005C0C /* Select tuner */
+#define DIBUTTON_REMOTE_DVD                     0x27005C0D /* Select DVD player */
+#define DIBUTTON_REMOTE_ADJUST                  0x27005C0E /* Enter device adjustment menu */
+#define DIBUTTON_REMOTE_DIGIT0                  0x2700540F /* Digit 0 */
+#define DIBUTTON_REMOTE_DIGIT1                  0x27005410 /* Digit 1 */
+#define DIBUTTON_REMOTE_DIGIT2                  0x27005411 /* Digit 2 */
+#define DIBUTTON_REMOTE_DIGIT3                  0x27005412 /* Digit 3 */
+#define DIBUTTON_REMOTE_DIGIT4                  0x27005413 /* Digit 4 */
+#define DIBUTTON_REMOTE_DIGIT5                  0x27005414 /* Digit 5 */
+#define DIBUTTON_REMOTE_DIGIT6                  0x27005415 /* Digit 6 */
+#define DIBUTTON_REMOTE_DIGIT7                  0x27005416 /* Digit 7 */
+#define DIBUTTON_REMOTE_DIGIT8                  0x27005417 /* Digit 8 */
+#define DIBUTTON_REMOTE_DIGIT9                  0x27005418 /* Digit 9 */
+#define DIBUTTON_REMOTE_DEVICE                  0x270044FE /* Show input device and controls */
+#define DIBUTTON_REMOTE_PAUSE                   0x270044FC /* Start / Pause / Restart game */
+
+/*--- Control- Web
+      Help or Browser            ---*/
+#define DIVIRTUAL_BROWSER_CONTROL               0x28000000
+#define DIAXIS_BROWSER_LATERAL                  0x28008201 /* Move on screen pointer */
+#define DIAXIS_BROWSER_MOVE                     0x28010202 /* Move on screen pointer */
+#define DIBUTTON_BROWSER_SELECT                 0x28000401 /* Select current item */
+#define DIAXIS_BROWSER_VIEW                     0x28018203 /* Move view up/down */
+#define DIBUTTON_BROWSER_REFRESH                0x28000402 /* Refresh */
+#define DIBUTTON_BROWSER_MENU                   0x280004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_BROWSER_SEARCH                 0x28004403 /* Use search tool */
+#define DIBUTTON_BROWSER_STOP                   0x28004404 /* Cease current update */
+#define DIBUTTON_BROWSER_HOME                   0x28004405 /* Go directly to "home" location */
+#define DIBUTTON_BROWSER_FAVORITES              0x28004406 /* Mark current site as favorite */
+#define DIBUTTON_BROWSER_NEXT                   0x28004407 /* Select Next page */
+#define DIBUTTON_BROWSER_PREVIOUS               0x28004408 /* Select Previous page */
+#define DIBUTTON_BROWSER_HISTORY                0x28004409 /* Show/Hide History */
+#define DIBUTTON_BROWSER_PRINT                  0x2800440A /* Print current page */
+#define DIBUTTON_BROWSER_DEVICE                 0x280044FE /* Show input device and controls */
+#define DIBUTTON_BROWSER_PAUSE                  0x280044FC /* Start / Pause / Restart game */
+
+/*--- Driving Simulator - Giant Walking Robot
+      Walking tank with weapons  ---*/
+#define DIVIRTUAL_DRIVING_MECHA                 0x29000000
+#define DIAXIS_MECHA_STEER                      0x29008201 /* Turns mecha left/right */
+#define DIAXIS_MECHA_TORSO                      0x29010202 /* Tilts torso forward/backward */
+#define DIAXIS_MECHA_ROTATE                     0x29020203 /* Turns torso left/right */
+#define DIAXIS_MECHA_THROTTLE                   0x29038204 /* Engine Speed */
+#define DIBUTTON_MECHA_FIRE                     0x29000401 /* Fire */
+#define DIBUTTON_MECHA_WEAPONS                  0x29000402 /* Select next weapon group */
+#define DIBUTTON_MECHA_TARGET                   0x29000403 /* Select closest enemy available target */
+#define DIBUTTON_MECHA_REVERSE                  0x29000404 /* Toggles throttle in/out of reverse */
+#define DIBUTTON_MECHA_ZOOM                     0x29000405 /* Zoom in/out targeting reticule */
+#define DIBUTTON_MECHA_JUMP                     0x29000406 /* Fires jump jets */
+#define DIBUTTON_MECHA_MENU                     0x290004FD /* Show menu options */
+/*--- Priority 2 controls                            ---*/
+
+#define DIBUTTON_MECHA_CENTER                   0x29004407 /* Center torso to legs */
+#define DIHATSWITCH_MECHA_GLANCE                0x29004601 /* Look around */
+#define DIBUTTON_MECHA_VIEW                     0x29004408 /* Cycle through view options */
+#define DIBUTTON_MECHA_FIRESECONDARY            0x29004409 /* Alternative fire button */
+#define DIBUTTON_MECHA_LEFT_LINK                0x2900C4E4 /* Fallback steer left button */
+#define DIBUTTON_MECHA_RIGHT_LINK               0x2900C4EC /* Fallback steer right button */
+#define DIBUTTON_MECHA_FORWARD_LINK             0x290144E0 /* Fallback tilt torso forward button */
+#define DIBUTTON_MECHA_BACK_LINK                0x290144E8 /* Fallback tilt toroso backward button */
+#define DIBUTTON_MECHA_ROTATE_LEFT_LINK         0x290244E4 /* Fallback rotate toroso right button */
+#define DIBUTTON_MECHA_ROTATE_RIGHT_LINK        0x290244EC /* Fallback rotate torso left button */
+#define DIBUTTON_MECHA_FASTER_LINK              0x2903C4E0 /* Fallback increase engine speed */
+#define DIBUTTON_MECHA_SLOWER_LINK              0x2903C4E8 /* Fallback decrease engine speed */
+#define DIBUTTON_MECHA_DEVICE                   0x290044FE /* Show input device and controls */
+#define DIBUTTON_MECHA_PAUSE                    0x290044FC /* Start / Pause / Restart game */
+
+/*
+ *  "ANY" semantics can be used as a last resort to get mappings for actions 
+ *  that match nothing in the chosen virtual genre.  These semantics will be 
+ *  mapped at a lower priority that virtual genre semantics.  Also, hardware 
+ *  vendors will not be able to provide sensible mappings for these unless 
+ *  they provide application specific mappings.
+ */
+#define DIAXIS_ANY_X_1                          0xFF00C201 
+#define DIAXIS_ANY_X_2                          0xFF00C202 
+#define DIAXIS_ANY_Y_1                          0xFF014201 
+#define DIAXIS_ANY_Y_2                          0xFF014202 
+#define DIAXIS_ANY_Z_1                          0xFF01C201 
+#define DIAXIS_ANY_Z_2                          0xFF01C202 
+#define DIAXIS_ANY_R_1                          0xFF024201 
+#define DIAXIS_ANY_R_2                          0xFF024202 
+#define DIAXIS_ANY_U_1                          0xFF02C201 
+#define DIAXIS_ANY_U_2                          0xFF02C202 
+#define DIAXIS_ANY_V_1                          0xFF034201 
+#define DIAXIS_ANY_V_2                          0xFF034202 
+#define DIAXIS_ANY_A_1                          0xFF03C201 
+#define DIAXIS_ANY_A_2                          0xFF03C202 
+#define DIAXIS_ANY_B_1                          0xFF044201 
+#define DIAXIS_ANY_B_2                          0xFF044202 
+#define DIAXIS_ANY_C_1                          0xFF04C201 
+#define DIAXIS_ANY_C_2                          0xFF04C202 
+#define DIAXIS_ANY_S_1                          0xFF054201 
+#define DIAXIS_ANY_S_2                          0xFF054202 
+
+#define DIAXIS_ANY_1                            0xFF004201 
+#define DIAXIS_ANY_2                            0xFF004202 
+#define DIAXIS_ANY_3                            0xFF004203 
+#define DIAXIS_ANY_4                            0xFF004204 
+
+#define DIPOV_ANY_1                             0xFF004601 
+#define DIPOV_ANY_2                             0xFF004602 
+#define DIPOV_ANY_3                             0xFF004603 
+#define DIPOV_ANY_4                             0xFF004604 
+
+#define DIBUTTON_ANY(instance)                  ( 0xFF004400 | instance )
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __DINPUT_INCLUDED__ */
+
+/****************************************************************************
+ *
+ *  Definitions for non-IDirectInput (VJoyD) features defined more recently
+ *  than the current sdk files
+ *
+ ****************************************************************************/
+
+#ifdef _INC_MMSYSTEM
+#ifndef MMNOJOY
+
+#ifndef __VJOYDX_INCLUDED__
+#define __VJOYDX_INCLUDED__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Flag to indicate that the dwReserved2 field of the JOYINFOEX structure
+ * contains mini-driver specific data to be passed by VJoyD to the mini-
+ * driver instead of doing a poll.
+ */
+#define JOY_PASSDRIVERDATA          0x10000000l
+
+/*
+ * Informs the joystick driver that the configuration has been changed
+ * and should be reloaded from the registery.
+ * dwFlags is reserved and should be set to zero
+ */
+WINMMAPI MMRESULT WINAPI joyConfigChanged( DWORD dwFlags );
+
+#ifndef DIJ_RINGZERO
+/*
+ * Invoke the joystick control panel directly, using the passed window handle 
+ * as the parent of the dialog.  This API is only supported for compatibility 
+ * purposes; new applications should use the RunControlPanel method of a 
+ * device interface for a game controller.
+ * The API is called by using the function pointer returned by
+ * GetProcAddress( hCPL, TEXT("ShowJoyCPL") ) where hCPL is a HMODULE returned 
+ * by LoadLibrary( TEXT("joy.cpl") ).  The typedef is provided to allow 
+ * declaration and casting of an appropriately typed variable.
+ */
+void WINAPI ShowJoyCPL( HWND hWnd );
+typedef void (WINAPI* LPFNSHOWJOYCPL)( HWND hWnd );
+#endif /* DIJ_RINGZERO */
+
+
+/*
+ * Hardware Setting indicating that the device is a headtracker
+ */
+#define JOY_HWS_ISHEADTRACKER       0x02000000l
+
+/*
+ * Hardware Setting indicating that the VxD is used to replace
+ * the standard analog polling
+ */
+#define JOY_HWS_ISGAMEPORTDRIVER    0x04000000l
+
+/*
+ * Hardware Setting indicating that the driver needs a standard
+ * gameport in order to communicate with the device.
+ */
+#define JOY_HWS_ISANALOGPORTDRIVER  0x08000000l
+
+/*
+ * Hardware Setting indicating that VJoyD should not load this
+ * driver, it will be loaded externally and will register with
+ * VJoyD of it's own accord.
+ */
+#define JOY_HWS_AUTOLOAD            0x10000000l
+
+/*
+ * Hardware Setting indicating that the driver acquires any
+ * resources needed without needing a devnode through VJoyD.
+ */
+#define JOY_HWS_NODEVNODE           0x20000000l
+
+
+/*
+ * Hardware Setting indicating that the device is a gameport bus
+ */
+#define JOY_HWS_ISGAMEPORTBUS       0x80000000l
+#define JOY_HWS_GAMEPORTBUSBUSY     0x00000001l
+
+/*
+ * Usage Setting indicating that the settings are volatile and
+ * should be removed if still present on a reboot.
+ */
+#define JOY_US_VOLATILE             0x00000008L
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __VJOYDX_INCLUDED__ */
+
+#endif  /* not MMNOJOY */
+#endif  /* _INC_MMSYSTEM */
+
+/****************************************************************************
+ *
+ *  Definitions for non-IDirectInput (VJoyD) features defined more recently
+ *  than the current ddk files
+ *
+ ****************************************************************************/
+
+#ifndef DIJ_RINGZERO
+
+#ifdef _INC_MMDDK
+#ifndef MMNOJOYDEV
+
+#ifndef __VJOYDXD_INCLUDED__
+#define __VJOYDXD_INCLUDED__
+/*
+ * Poll type in which the do_other field of the JOYOEMPOLLDATA
+ * structure contains mini-driver specific data passed from an app.
+ */
+#define JOY_OEMPOLL_PASSDRIVERDATA  7
+
+#endif  /* __VJOYDXD_INCLUDED__ */
+
+#endif  /* not MMNOJOYDEV */
+#endif  /* _INC_MMDDK */
+
+#endif /* DIJ_RINGZERO */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dinputd.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,755 @@
+/****************************************************************************
+ *
+ *  Copyright (C) 1995-2000 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dinputd.h
+ *  Content:    DirectInput include file for device driver implementors
+ *
+ ****************************************************************************/
+#ifndef __DINPUTD_INCLUDED__
+#define __DINPUTD_INCLUDED__
+
+#ifndef DIRECTINPUT_VERSION
+#define DIRECTINPUT_VERSION         0x0800
+#pragma message(__FILE__ ": DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800")
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ *
+ *      Interfaces
+ *
+ ****************************************************************************/
+
+#ifndef DIJ_RINGZERO
+
+DEFINE_GUID(IID_IDirectInputEffectDriver,   0x02538130,0x898F,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
+DEFINE_GUID(IID_IDirectInputJoyConfig,      0x1DE12AB1,0xC9F5,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputPIDDriver,      0xEEC6993A,0xB3FD,0x11D2,0xA9,0x16,0x00,0xC0,0x4F,0xB9,0x86,0x38);
+
+DEFINE_GUID(IID_IDirectInputJoyConfig8,     0xeb0d7dfa,0x1990,0x4f27,0xb4,0xd6,0xed,0xf2,0xee,0xc4,0xa4,0x4c);
+
+#endif /* DIJ_RINGZERO */
+
+
+/****************************************************************************
+ *
+ *      IDirectInputEffectDriver
+ *
+ ****************************************************************************/
+
+typedef struct DIOBJECTATTRIBUTES {
+    DWORD   dwFlags;
+    WORD    wUsagePage;
+    WORD    wUsage;
+} DIOBJECTATTRIBUTES, *LPDIOBJECTATTRIBUTES;
+typedef const DIOBJECTATTRIBUTES *LPCDIOBJECTATTRIBUTES;
+
+typedef struct DIFFOBJECTATTRIBUTES {
+    DWORD   dwFFMaxForce;
+    DWORD   dwFFForceResolution;
+} DIFFOBJECTATTRIBUTES, *LPDIFFOBJECTATTRIBUTES;
+typedef const DIFFOBJECTATTRIBUTES *LPCDIFFOBJECTATTRIBUTES;
+
+typedef struct DIOBJECTCALIBRATION {
+    LONG    lMin;
+    LONG    lCenter;
+    LONG    lMax;
+} DIOBJECTCALIBRATION, *LPDIOBJECTCALIBRATION;
+typedef const DIOBJECTCALIBRATION *LPCDIOBJECTCALIBRATION;
+
+typedef struct DIPOVCALIBRATION {
+    LONG    lMin[5];
+    LONG    lMax[5];
+} DIPOVCALIBRATION, *LPDIPOVCALIBRATION;
+typedef const DIPOVCALIBRATION *LPCDIPOVCALIBRATION;
+
+typedef struct DIEFFECTATTRIBUTES {
+    DWORD   dwEffectId;
+    DWORD   dwEffType;
+    DWORD   dwStaticParams;
+    DWORD   dwDynamicParams;
+    DWORD   dwCoords;
+} DIEFFECTATTRIBUTES, *LPDIEFFECTATTRIBUTES;
+typedef const DIEFFECTATTRIBUTES *LPCDIEFFECTATTRIBUTES;
+
+typedef struct DIFFDEVICEATTRIBUTES {
+    DWORD   dwFlags;
+    DWORD   dwFFSamplePeriod;
+    DWORD   dwFFMinTimeResolution;
+} DIFFDEVICEATTRIBUTES, *LPDIFFDEVICEATTRIBUTES;
+typedef const DIFFDEVICEATTRIBUTES *LPCDIFFDEVICEATTRIBUTES;
+
+typedef struct DIDRIVERVERSIONS {
+    DWORD   dwSize;
+    DWORD   dwFirmwareRevision;
+    DWORD   dwHardwareRevision;
+    DWORD   dwFFDriverVersion;
+} DIDRIVERVERSIONS, *LPDIDRIVERVERSIONS;
+typedef const DIDRIVERVERSIONS *LPCDIDRIVERVERSIONS;
+
+typedef struct DIDEVICESTATE {
+    DWORD   dwSize;
+    DWORD   dwState;
+    DWORD   dwLoad;
+} DIDEVICESTATE, *LPDIDEVICESTATE;
+
+#define DEV_STS_EFFECT_RUNNING  DIEGES_PLAYING
+
+#ifndef DIJ_RINGZERO
+
+typedef struct DIHIDFFINITINFO {
+    DWORD   dwSize;
+    LPWSTR  pwszDeviceInterface;
+    GUID    GuidInstance;
+} DIHIDFFINITINFO, *LPDIHIDFFINITINFO;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputEffectDriver
+
+DECLARE_INTERFACE_(IDirectInputEffectDriver, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputEffectDriver methods ***/
+    STDMETHOD(DeviceID)(THIS_ DWORD,DWORD,DWORD,DWORD,LPVOID) PURE;
+    STDMETHOD(GetVersions)(THIS_ LPDIDRIVERVERSIONS) PURE;
+    STDMETHOD(Escape)(THIS_ DWORD,DWORD,LPDIEFFESCAPE) PURE;
+    STDMETHOD(SetGain)(THIS_ DWORD,DWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD,DWORD) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ DWORD,LPDIDEVICESTATE) PURE;
+    STDMETHOD(DownloadEffect)(THIS_ DWORD,DWORD,LPDWORD,LPCDIEFFECT,DWORD) PURE;
+    STDMETHOD(DestroyEffect)(THIS_ DWORD,DWORD) PURE;
+    STDMETHOD(StartEffect)(THIS_ DWORD,DWORD,DWORD,DWORD) PURE;
+    STDMETHOD(StopEffect)(THIS_ DWORD,DWORD) PURE;
+    STDMETHOD(GetEffectStatus)(THIS_ DWORD,DWORD,LPDWORD) PURE;
+};
+
+typedef struct IDirectInputEffectDriver *LPDIRECTINPUTEFFECTDRIVER;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputEffectDriver_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputEffectDriver_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputEffectDriver_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputEffectDriver_DeviceID(p,a,b,c,d,e) (p)->lpVtbl->DeviceID(p,a,b,c,d,e)
+#define IDirectInputEffectDriver_GetVersions(p,a) (p)->lpVtbl->GetVersions(p,a)
+#define IDirectInputEffectDriver_Escape(p,a,b,c) (p)->lpVtbl->Escape(p,a,b,c)
+#define IDirectInputEffectDriver_SetGain(p,a,b) (p)->lpVtbl->SetGain(p,a,b)
+#define IDirectInputEffectDriver_SendForceFeedbackCommand(p,a,b) (p)->lpVtbl->SendForceFeedbackCommand(p,a,b)
+#define IDirectInputEffectDriver_GetForceFeedbackState(p,a,b) (p)->lpVtbl->GetForceFeedbackState(p,a,b)
+#define IDirectInputEffectDriver_DownloadEffect(p,a,b,c,d,e) (p)->lpVtbl->DownloadEffect(p,a,b,c,d,e)
+#define IDirectInputEffectDriver_DestroyEffect(p,a,b) (p)->lpVtbl->DestroyEffect(p,a,b)
+#define IDirectInputEffectDriver_StartEffect(p,a,b,c,d) (p)->lpVtbl->StartEffect(p,a,b,c,d)
+#define IDirectInputEffectDriver_StopEffect(p,a,b) (p)->lpVtbl->StopEffect(p,a,b)
+#define IDirectInputEffectDriver_GetEffectStatus(p,a,b,c) (p)->lpVtbl->GetEffectStatus(p,a,b,c)
+#else
+#define IDirectInputEffectDriver_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputEffectDriver_AddRef(p) (p)->AddRef()
+#define IDirectInputEffectDriver_Release(p) (p)->Release()
+#define IDirectInputEffectDriver_DeviceID(p,a,b,c,d,e) (p)->DeviceID(a,b,c,d,e)
+#define IDirectInputEffectDriver_GetVersions(p,a) (p)->GetVersions(a)
+#define IDirectInputEffectDriver_Escape(p,a,b,c) (p)->Escape(a,b,c)
+#define IDirectInputEffectDriver_SetGain(p,a,b) (p)->SetGain(a,b)
+#define IDirectInputEffectDriver_SendForceFeedbackCommand(p,a,b) (p)->SendForceFeedbackCommand(a,b)
+#define IDirectInputEffectDriver_GetForceFeedbackState(p,a,b) (p)->GetForceFeedbackState(a,b)
+#define IDirectInputEffectDriver_DownloadEffect(p,a,b,c,d,e) (p)->DownloadEffect(a,b,c,d,e)
+#define IDirectInputEffectDriver_DestroyEffect(p,a,b) (p)->DestroyEffect(a,b)
+#define IDirectInputEffectDriver_StartEffect(p,a,b,c,d) (p)->StartEffect(a,b,c,d)
+#define IDirectInputEffectDriver_StopEffect(p,a,b) (p)->StopEffect(a,b)
+#define IDirectInputEffectDriver_GetEffectStatus(p,a,b,c) (p)->GetEffectStatus(a,b,c)
+#endif
+
+
+#endif /* DIJ_RINGZERO */
+
+
+/****************************************************************************
+ *
+ *      IDirectInputJoyConfig
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ *      Definitions copied from the DDK
+ *
+ ****************************************************************************/
+
+#ifndef JOY_HW_NONE
+
+/* pre-defined joystick types */
+#define JOY_HW_NONE                     0
+#define JOY_HW_CUSTOM                   1
+#define JOY_HW_2A_2B_GENERIC            2
+#define JOY_HW_2A_4B_GENERIC            3
+#define JOY_HW_2B_GAMEPAD               4
+#define JOY_HW_2B_FLIGHTYOKE            5
+#define JOY_HW_2B_FLIGHTYOKETHROTTLE    6
+#define JOY_HW_3A_2B_GENERIC            7
+#define JOY_HW_3A_4B_GENERIC            8
+#define JOY_HW_4B_GAMEPAD               9
+#define JOY_HW_4B_FLIGHTYOKE            10
+#define JOY_HW_4B_FLIGHTYOKETHROTTLE    11
+#define JOY_HW_TWO_2A_2B_WITH_Y         12
+#define JOY_HW_LASTENTRY                13
+
+
+/* calibration flags */
+#define JOY_ISCAL_XY            0x00000001l     /* XY are calibrated */
+#define JOY_ISCAL_Z             0x00000002l     /* Z is calibrated */
+#define JOY_ISCAL_R             0x00000004l     /* R is calibrated */
+#define JOY_ISCAL_U             0x00000008l     /* U is calibrated */
+#define JOY_ISCAL_V             0x00000010l     /* V is calibrated */
+#define JOY_ISCAL_POV           0x00000020l     /* POV is calibrated */
+
+/* point of view constants */
+#define JOY_POV_NUMDIRS          4
+#define JOY_POVVAL_FORWARD       0
+#define JOY_POVVAL_BACKWARD      1
+#define JOY_POVVAL_LEFT          2
+#define JOY_POVVAL_RIGHT         3
+
+/* Specific settings for joystick hardware */
+#define JOY_HWS_HASZ            0x00000001l     /* has Z info? */
+#define JOY_HWS_HASPOV          0x00000002l     /* point of view hat present */
+#define JOY_HWS_POVISBUTTONCOMBOS 0x00000004l   /* pov done through combo of buttons */
+#define JOY_HWS_POVISPOLL       0x00000008l     /* pov done through polling */
+#define JOY_HWS_ISYOKE          0x00000010l     /* joystick is a flight yoke */
+#define JOY_HWS_ISGAMEPAD       0x00000020l     /* joystick is a game pad */
+#define JOY_HWS_ISCARCTRL       0x00000040l     /* joystick is a car controller */
+/* X defaults to J1 X axis */
+#define JOY_HWS_XISJ1Y          0x00000080l     /* X is on J1 Y axis */
+#define JOY_HWS_XISJ2X          0x00000100l     /* X is on J2 X axis */
+#define JOY_HWS_XISJ2Y          0x00000200l     /* X is on J2 Y axis */
+/* Y defaults to J1 Y axis */
+#define JOY_HWS_YISJ1X          0x00000400l     /* Y is on J1 X axis */
+#define JOY_HWS_YISJ2X          0x00000800l     /* Y is on J2 X axis */
+#define JOY_HWS_YISJ2Y          0x00001000l     /* Y is on J2 Y axis */
+/* Z defaults to J2 Y axis */
+#define JOY_HWS_ZISJ1X          0x00002000l     /* Z is on J1 X axis */
+#define JOY_HWS_ZISJ1Y          0x00004000l     /* Z is on J1 Y axis */
+#define JOY_HWS_ZISJ2X          0x00008000l     /* Z is on J2 X axis */
+/* POV defaults to J2 Y axis, if it is not button based */
+#define JOY_HWS_POVISJ1X        0x00010000l     /* pov done through J1 X axis */
+#define JOY_HWS_POVISJ1Y        0x00020000l     /* pov done through J1 Y axis */
+#define JOY_HWS_POVISJ2X        0x00040000l     /* pov done through J2 X axis */
+/* R defaults to J2 X axis */
+#define JOY_HWS_HASR            0x00080000l     /* has R (4th axis) info */
+#define JOY_HWS_RISJ1X          0x00100000l     /* R done through J1 X axis */
+#define JOY_HWS_RISJ1Y          0x00200000l     /* R done through J1 Y axis */
+#define JOY_HWS_RISJ2Y          0x00400000l     /* R done through J2 X axis */
+/* U & V for future hardware */
+#define JOY_HWS_HASU            0x00800000l     /* has U (5th axis) info */
+#define JOY_HWS_HASV            0x01000000l     /* has V (6th axis) info */
+
+/* Usage settings */
+#define JOY_US_HASRUDDER        0x00000001l     /* joystick configured with rudder */
+#define JOY_US_PRESENT          0x00000002l     /* is joystick actually present? */
+#define JOY_US_ISOEM            0x00000004l     /* joystick is an OEM defined type */
+
+/* reserved for future use -> as link to next possible dword */
+#define JOY_US_RESERVED         0x80000000l     /* reserved */
+
+
+/* Settings for TypeInfo Flags1 */
+#define JOYTYPE_ZEROGAMEENUMOEMDATA     0x00000001l /* Zero GameEnum's OEM data field */
+#define JOYTYPE_NOAUTODETECTGAMEPORT    0x00000002l /* Device does not support Autodetect gameport*/
+#define JOYTYPE_NOHIDDIRECT             0x00000004l /* Do not use HID directly for this device */
+#define JOYTYPE_ANALOGCOMPAT            0x00000008l /* Expose the analog compatible ID */
+#define JOYTYPE_DEFAULTPROPSHEET        0x80000000l /* CPL overrides custom property sheet */
+
+/* Settings for TypeInfo Flags2 */
+#define JOYTYPE_DEVICEHIDE              0x00010000l /* Hide unclassified devices */
+#define JOYTYPE_MOUSEHIDE               0x00020000l /* Hide mice */
+#define JOYTYPE_KEYBHIDE                0x00040000l /* Hide keyboards */
+#define JOYTYPE_GAMEHIDE                0x00080000l /* Hide game controllers */
+#define JOYTYPE_HIDEACTIVE              0x00100000l /* Hide flags are active */
+#define JOYTYPE_INFOMASK                0x00E00000l /* Mask for type specific info */
+#define JOYTYPE_INFODEFAULT             0x00000000l /* Use default axis mappings */
+#define JOYTYPE_INFOYYPEDALS            0x00200000l /* Use Y as a combined pedals axis */
+#define JOYTYPE_INFOZYPEDALS            0x00400000l /* Use Z for accelerate, Y for brake */
+#define JOYTYPE_INFOYRPEDALS            0x00600000l /* Use Y for accelerate, R for brake */
+#define JOYTYPE_INFOZRPEDALS            0x00800000l /* Use Z for accelerate, R for brake */
+#define JOYTYPE_INFOZISSLIDER           0x00200000l /* Use Z as a slider */
+#define JOYTYPE_INFOZISZ                0x00400000l /* Use Z as Z axis */
+#define JOYTYPE_ENABLEINPUTREPORT       0x01000000l /* Enable initial input reports */
+
+/* struct for storing x,y, z, and rudder values */
+typedef struct joypos_tag {
+    DWORD       dwX;
+    DWORD       dwY;
+    DWORD       dwZ;
+    DWORD       dwR;
+    DWORD       dwU;
+    DWORD       dwV;
+} JOYPOS, FAR *LPJOYPOS;
+
+/* struct for storing ranges */
+typedef struct joyrange_tag {
+    JOYPOS      jpMin;
+    JOYPOS      jpMax;
+    JOYPOS      jpCenter;
+} JOYRANGE,FAR *LPJOYRANGE;
+
+/*
+ *  dwTimeout - value at which to timeout joystick polling
+ *  jrvRanges - range of values app wants returned for axes
+ *  jpDeadZone - area around center to be considered
+ *               as "dead". specified as a percentage
+ *               (0-100). Only X & Y handled by system driver
+ */
+typedef struct joyreguservalues_tag {
+    DWORD       dwTimeOut;
+    JOYRANGE    jrvRanges;
+    JOYPOS      jpDeadZone;
+} JOYREGUSERVALUES, FAR *LPJOYREGUSERVALUES;
+
+typedef struct joyreghwsettings_tag {
+    DWORD       dwFlags;
+    DWORD       dwNumButtons;
+} JOYREGHWSETTINGS, FAR *LPJOYHWSETTINGS;
+
+/* range of values returned by the hardware (filled in by calibration) */
+/*
+ *  jrvHardware - values returned by hardware
+ *  dwPOVValues - POV values returned by hardware
+ *  dwCalFlags  - what has been calibrated
+ */
+typedef struct joyreghwvalues_tag {
+    JOYRANGE    jrvHardware;
+    DWORD       dwPOVValues[JOY_POV_NUMDIRS];
+    DWORD       dwCalFlags;
+} JOYREGHWVALUES, FAR *LPJOYREGHWVALUES;
+
+/* hardware configuration */
+/*
+ *  hws             - hardware settings
+ *  dwUsageSettings - usage settings
+ *  hwv             - values returned by hardware
+ *  dwType          - type of joystick
+ *  dwReserved      - reserved for OEM drivers
+ */
+typedef struct joyreghwconfig_tag {
+    JOYREGHWSETTINGS    hws;
+    DWORD               dwUsageSettings;
+    JOYREGHWVALUES      hwv;
+    DWORD               dwType;
+    DWORD               dwReserved;
+} JOYREGHWCONFIG, FAR *LPJOYREGHWCONFIG;
+
+/* joystick calibration info structure */
+typedef struct joycalibrate_tag {
+    UINT    wXbase;
+    UINT    wXdelta;
+    UINT    wYbase;
+    UINT    wYdelta;
+    UINT    wZbase;
+    UINT    wZdelta;
+} JOYCALIBRATE;
+typedef JOYCALIBRATE FAR *LPJOYCALIBRATE;
+
+#endif
+
+#ifndef DIJ_RINGZERO
+
+#define MAX_JOYSTRING 256
+typedef BOOL (FAR PASCAL * LPDIJOYTYPECALLBACK)(LPCWSTR, LPVOID);
+
+#ifndef MAX_JOYSTICKOEMVXDNAME
+#define MAX_JOYSTICKOEMVXDNAME 260
+#endif
+
+#define DITC_REGHWSETTINGS          0x00000001
+#define DITC_CLSIDCONFIG            0x00000002
+#define DITC_DISPLAYNAME            0x00000004
+#define DITC_CALLOUT                0x00000008
+#define DITC_HARDWAREID             0x00000010
+#define DITC_FLAGS1                 0x00000020
+#define DITC_FLAGS2                 0x00000040
+#define DITC_MAPFILE                0x00000080
+
+
+
+/* This structure is defined for DirectX 5.0 compatibility */
+
+typedef struct DIJOYTYPEINFO_DX5 {
+    DWORD dwSize;
+    JOYREGHWSETTINGS hws;
+    CLSID clsidConfig;
+    WCHAR wszDisplayName[MAX_JOYSTRING];
+    WCHAR wszCallout[MAX_JOYSTICKOEMVXDNAME];
+} DIJOYTYPEINFO_DX5, *LPDIJOYTYPEINFO_DX5;
+typedef const DIJOYTYPEINFO_DX5 *LPCDIJOYTYPEINFO_DX5;
+
+/* This structure is defined for DirectX 6.1 compatibility */
+typedef struct DIJOYTYPEINFO_DX6 {
+    DWORD dwSize;
+    JOYREGHWSETTINGS hws;
+    CLSID clsidConfig;
+    WCHAR wszDisplayName[MAX_JOYSTRING];
+    WCHAR wszCallout[MAX_JOYSTICKOEMVXDNAME];
+    WCHAR wszHardwareId[MAX_JOYSTRING];
+    DWORD dwFlags1;
+} DIJOYTYPEINFO_DX6, *LPDIJOYTYPEINFO_DX6;
+typedef const DIJOYTYPEINFO_DX6 *LPCDIJOYTYPEINFO_DX6;
+
+typedef struct DIJOYTYPEINFO {
+    DWORD dwSize;
+    JOYREGHWSETTINGS hws;
+    CLSID clsidConfig;
+    WCHAR wszDisplayName[MAX_JOYSTRING];
+    WCHAR wszCallout[MAX_JOYSTICKOEMVXDNAME];
+#if(DIRECTINPUT_VERSION >= 0x05b2)
+    WCHAR wszHardwareId[MAX_JOYSTRING];
+    DWORD dwFlags1;
+#if(DIRECTINPUT_VERSION >= 0x0800)
+    DWORD dwFlags2;
+    WCHAR wszMapFile[MAX_JOYSTRING];
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+#endif /* DIRECTINPUT_VERSION >= 0x05b2 */
+} DIJOYTYPEINFO, *LPDIJOYTYPEINFO;
+typedef const DIJOYTYPEINFO *LPCDIJOYTYPEINFO;
+#define DIJC_GUIDINSTANCE           0x00000001
+#define DIJC_REGHWCONFIGTYPE        0x00000002
+#define DIJC_GAIN                   0x00000004
+#define DIJC_CALLOUT                0x00000008
+#define DIJC_WDMGAMEPORT            0x00000010
+
+/* This structure is defined for DirectX 5.0 compatibility */
+
+typedef struct DIJOYCONFIG_DX5 {
+    DWORD dwSize;
+    GUID guidInstance;
+    JOYREGHWCONFIG hwc;
+    DWORD dwGain;
+    WCHAR wszType[MAX_JOYSTRING];
+    WCHAR wszCallout[MAX_JOYSTRING];
+} DIJOYCONFIG_DX5, *LPDIJOYCONFIG_DX5;
+typedef const DIJOYCONFIG_DX5 *LPCDIJOYCONFIG_DX5;
+
+typedef struct DIJOYCONFIG {
+    DWORD dwSize;
+    GUID guidInstance;
+    JOYREGHWCONFIG hwc;
+    DWORD dwGain;
+    WCHAR wszType[MAX_JOYSTRING];
+    WCHAR wszCallout[MAX_JOYSTRING];
+#if(DIRECTINPUT_VERSION >= 0x05b2)
+    GUID  guidGameport;
+#endif /* DIRECTINPUT_VERSION >= 0x05b2 */
+    } DIJOYCONFIG, *LPDIJOYCONFIG;
+typedef const DIJOYCONFIG *LPCDIJOYCONFIG;
+
+
+#define DIJU_USERVALUES             0x00000001
+#define DIJU_GLOBALDRIVER           0x00000002
+#define DIJU_GAMEPORTEMULATOR       0x00000004
+
+typedef struct DIJOYUSERVALUES {
+    DWORD dwSize;
+    JOYREGUSERVALUES ruv;
+    WCHAR wszGlobalDriver[MAX_JOYSTRING];
+    WCHAR wszGameportEmulator[MAX_JOYSTRING];
+} DIJOYUSERVALUES, *LPDIJOYUSERVALUES;
+typedef const DIJOYUSERVALUES *LPCDIJOYUSERVALUES;
+
+DEFINE_GUID(GUID_KeyboardClass, 0x4D36E96B,0xE325,0x11CE,0xBF,0xC1,0x08,0x00,0x2B,0xE1,0x03,0x18);
+DEFINE_GUID(GUID_MediaClass,    0x4D36E96C,0xE325,0x11CE,0xBF,0xC1,0x08,0x00,0x2B,0xE1,0x03,0x18);
+DEFINE_GUID(GUID_MouseClass,    0x4D36E96F,0xE325,0x11CE,0xBF,0xC1,0x08,0x00,0x2B,0xE1,0x03,0x18);
+DEFINE_GUID(GUID_HIDClass,      0x745A17A0,0x74D3,0x11D0,0xB6,0xFE,0x00,0xA0,0xC9,0x0F,0x57,0xDA);
+
+#undef INTERFACE
+#define INTERFACE IDirectInputJoyConfig
+
+DECLARE_INTERFACE_(IDirectInputJoyConfig, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputJoyConfig methods ***/
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(SendNotify)(THIS) PURE;
+    STDMETHOD(EnumTypes)(THIS_ LPDIJOYTYPECALLBACK,LPVOID) PURE;
+    STDMETHOD(GetTypeInfo)(THIS_ LPCWSTR,LPDIJOYTYPEINFO,DWORD) PURE;
+    STDMETHOD(SetTypeInfo)(THIS_ LPCWSTR,LPCDIJOYTYPEINFO,DWORD) PURE;
+    STDMETHOD(DeleteType)(THIS_ LPCWSTR) PURE;
+    STDMETHOD(GetConfig)(THIS_ UINT,LPDIJOYCONFIG,DWORD) PURE;
+    STDMETHOD(SetConfig)(THIS_ UINT,LPCDIJOYCONFIG,DWORD) PURE;
+    STDMETHOD(DeleteConfig)(THIS_ UINT) PURE;
+    STDMETHOD(GetUserValues)(THIS_ LPDIJOYUSERVALUES,DWORD) PURE;
+    STDMETHOD(SetUserValues)(THIS_ LPCDIJOYUSERVALUES,DWORD) PURE;
+    STDMETHOD(AddNewHardware)(THIS_ HWND,REFGUID) PURE;
+    STDMETHOD(OpenTypeKey)(THIS_ LPCWSTR,DWORD,PHKEY) PURE;
+    STDMETHOD(OpenConfigKey)(THIS_ UINT,DWORD,PHKEY) PURE;
+};
+
+typedef struct IDirectInputJoyConfig *LPDIRECTINPUTJOYCONFIG;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputJoyConfig_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputJoyConfig_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputJoyConfig_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputJoyConfig_Acquire(p) (p)->lpVtbl->Acquire(p)
+#define IDirectInputJoyConfig_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+#define IDirectInputJoyConfig_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectInputJoyConfig_SendNotify(p) (p)->lpVtbl->SendNotify(p)
+#define IDirectInputJoyConfig_EnumTypes(p,a,b) (p)->lpVtbl->EnumTypes(p,a,b)
+#define IDirectInputJoyConfig_GetTypeInfo(p,a,b,c) (p)->lpVtbl->GetTypeInfo(p,a,b,c)
+#define IDirectInputJoyConfig_SetTypeInfo(p,a,b,c) (p)->lpVtbl->SetTypeInfo(p,a,b,c)
+#define IDirectInputJoyConfig_DeleteType(p,a) (p)->lpVtbl->DeleteType(p,a)
+#define IDirectInputJoyConfig_GetConfig(p,a,b,c) (p)->lpVtbl->GetConfig(p,a,b,c)
+#define IDirectInputJoyConfig_SetConfig(p,a,b,c) (p)->lpVtbl->SetConfig(p,a,b,c)
+#define IDirectInputJoyConfig_DeleteConfig(p,a) (p)->lpVtbl->DeleteConfig(p,a)
+#define IDirectInputJoyConfig_GetUserValues(p,a,b) (p)->lpVtbl->GetUserValues(p,a,b)
+#define IDirectInputJoyConfig_SetUserValues(p,a,b) (p)->lpVtbl->SetUserValues(p,a,b)
+#define IDirectInputJoyConfig_AddNewHardware(p,a,b) (p)->lpVtbl->AddNewHardware(p,a,b)
+#define IDirectInputJoyConfig_OpenTypeKey(p,a,b,c) (p)->lpVtbl->OpenTypeKey(p,a,b,c)
+#define IDirectInputJoyConfig_OpenConfigKey(p,a,b,c) (p)->lpVtbl->OpenConfigKey(p,a,b,c)
+#else
+#define IDirectInputJoyConfig_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputJoyConfig_AddRef(p) (p)->AddRef()
+#define IDirectInputJoyConfig_Release(p) (p)->Release()
+#define IDirectInputJoyConfig_Acquire(p) (p)->Acquire()
+#define IDirectInputJoyConfig_Unacquire(p) (p)->Unacquire()
+#define IDirectInputJoyConfig_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+#define IDirectInputJoyConfig_SendNotify(p) (p)->SendNotify()
+#define IDirectInputJoyConfig_EnumTypes(p,a,b) (p)->EnumTypes(a,b)
+#define IDirectInputJoyConfig_GetTypeInfo(p,a,b,c) (p)->GetTypeInfo(a,b,c)
+#define IDirectInputJoyConfig_SetTypeInfo(p,a,b,c) (p)->SetTypeInfo(a,b,c)
+#define IDirectInputJoyConfig_DeleteType(p,a) (p)->DeleteType(a)
+#define IDirectInputJoyConfig_GetConfig(p,a,b,c) (p)->GetConfig(a,b,c)
+#define IDirectInputJoyConfig_SetConfig(p,a,b,c) (p)->SetConfig(a,b,c)
+#define IDirectInputJoyConfig_DeleteConfig(p,a) (p)->DeleteConfig(a)
+#define IDirectInputJoyConfig_GetUserValues(p,a,b) (p)->GetUserValues(a,b)
+#define IDirectInputJoyConfig_SetUserValues(p,a,b) (p)->SetUserValues(a,b)
+#define IDirectInputJoyConfig_AddNewHardware(p,a,b) (p)->AddNewHardware(a,b)
+#define IDirectInputJoyConfig_OpenTypeKey(p,a,b,c) (p)->OpenTypeKey(a,b,c)
+#define IDirectInputJoyConfig_OpenConfigKey(p,a,b,c) (p)->OpenConfigKey(a,b,c)
+#endif
+
+#endif /* DIJ_RINGZERO */
+
+#if(DIRECTINPUT_VERSION >= 0x0800)
+
+#ifndef DIJ_RINGZERO
+
+#undef INTERFACE
+#define INTERFACE IDirectInputJoyConfig8
+
+DECLARE_INTERFACE_(IDirectInputJoyConfig8, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputJoyConfig8 methods ***/
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(SendNotify)(THIS) PURE;
+    STDMETHOD(EnumTypes)(THIS_ LPDIJOYTYPECALLBACK,LPVOID) PURE;
+    STDMETHOD(GetTypeInfo)(THIS_ LPCWSTR,LPDIJOYTYPEINFO,DWORD) PURE;
+    STDMETHOD(SetTypeInfo)(THIS_ LPCWSTR,LPCDIJOYTYPEINFO,DWORD,LPWSTR) PURE;
+    STDMETHOD(DeleteType)(THIS_ LPCWSTR) PURE;
+    STDMETHOD(GetConfig)(THIS_ UINT,LPDIJOYCONFIG,DWORD) PURE;
+    STDMETHOD(SetConfig)(THIS_ UINT,LPCDIJOYCONFIG,DWORD) PURE;
+    STDMETHOD(DeleteConfig)(THIS_ UINT) PURE;
+    STDMETHOD(GetUserValues)(THIS_ LPDIJOYUSERVALUES,DWORD) PURE;
+    STDMETHOD(SetUserValues)(THIS_ LPCDIJOYUSERVALUES,DWORD) PURE;
+    STDMETHOD(AddNewHardware)(THIS_ HWND,REFGUID) PURE;
+    STDMETHOD(OpenTypeKey)(THIS_ LPCWSTR,DWORD,PHKEY) PURE;
+    STDMETHOD(OpenAppStatusKey)(THIS_ PHKEY) PURE;
+};
+
+typedef struct IDirectInputJoyConfig8 *LPDIRECTINPUTJOYCONFIG8;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputJoyConfig8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputJoyConfig8_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputJoyConfig8_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputJoyConfig8_Acquire(p) (p)->lpVtbl->Acquire(p)
+#define IDirectInputJoyConfig8_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+#define IDirectInputJoyConfig8_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectInputJoyConfig8_SendNotify(p) (p)->lpVtbl->SendNotify(p)
+#define IDirectInputJoyConfig8_EnumTypes(p,a,b) (p)->lpVtbl->EnumTypes(p,a,b)
+#define IDirectInputJoyConfig8_GetTypeInfo(p,a,b,c) (p)->lpVtbl->GetTypeInfo(p,a,b,c)
+#define IDirectInputJoyConfig8_SetTypeInfo(p,a,b,c,d) (p)->lpVtbl->SetTypeInfo(p,a,b,c,d)
+#define IDirectInputJoyConfig8_DeleteType(p,a) (p)->lpVtbl->DeleteType(p,a)
+#define IDirectInputJoyConfig8_GetConfig(p,a,b,c) (p)->lpVtbl->GetConfig(p,a,b,c)
+#define IDirectInputJoyConfig8_SetConfig(p,a,b,c) (p)->lpVtbl->SetConfig(p,a,b,c)
+#define IDirectInputJoyConfig8_DeleteConfig(p,a) (p)->lpVtbl->DeleteConfig(p,a)
+#define IDirectInputJoyConfig8_GetUserValues(p,a,b) (p)->lpVtbl->GetUserValues(p,a,b)
+#define IDirectInputJoyConfig8_SetUserValues(p,a,b) (p)->lpVtbl->SetUserValues(p,a,b)
+#define IDirectInputJoyConfig8_AddNewHardware(p,a,b) (p)->lpVtbl->AddNewHardware(p,a,b)
+#define IDirectInputJoyConfig8_OpenTypeKey(p,a,b,c) (p)->lpVtbl->OpenTypeKey(p,a,b,c)
+#define IDirectInputJoyConfig8_OpenAppStatusKey(p,a) (p)->lpVtbl->OpenAppStatusKey(p,a)
+#else
+#define IDirectInputJoyConfig8_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputJoyConfig8_AddRef(p) (p)->AddRef()
+#define IDirectInputJoyConfig8_Release(p) (p)->Release()
+#define IDirectInputJoyConfig8_Acquire(p) (p)->Acquire()
+#define IDirectInputJoyConfig8_Unacquire(p) (p)->Unacquire()
+#define IDirectInputJoyConfig8_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+#define IDirectInputJoyConfig8_SendNotify(p) (p)->SendNotify()
+#define IDirectInputJoyConfig8_EnumTypes(p,a,b) (p)->EnumTypes(a,b)
+#define IDirectInputJoyConfig8_GetTypeInfo(p,a,b,c) (p)->GetTypeInfo(a,b,c)
+#define IDirectInputJoyConfig8_SetTypeInfo(p,a,b,c,d) (p)->SetTypeInfo(a,b,c,d)
+#define IDirectInputJoyConfig8_DeleteType(p,a) (p)->DeleteType(a)
+#define IDirectInputJoyConfig8_GetConfig(p,a,b,c) (p)->GetConfig(a,b,c)
+#define IDirectInputJoyConfig8_SetConfig(p,a,b,c) (p)->SetConfig(a,b,c)
+#define IDirectInputJoyConfig8_DeleteConfig(p,a) (p)->DeleteConfig(a)
+#define IDirectInputJoyConfig8_GetUserValues(p,a,b) (p)->GetUserValues(a,b)
+#define IDirectInputJoyConfig8_SetUserValues(p,a,b) (p)->SetUserValues(a,b)
+#define IDirectInputJoyConfig8_AddNewHardware(p,a,b) (p)->AddNewHardware(a,b)
+#define IDirectInputJoyConfig8_OpenTypeKey(p,a,b,c) (p)->OpenTypeKey(a,b,c)
+#define IDirectInputJoyConfig8_OpenAppStatusKey(p,a) (p)->OpenAppStatusKey(a)
+#endif
+
+#endif /* DIJ_RINGZERO */
+
+/****************************************************************************
+ *
+ *  Notification Messages
+ *
+ ****************************************************************************/
+
+/* RegisterWindowMessage with this to get DirectInput notification messages */
+#define DIRECTINPUT_NOTIFICATION_MSGSTRINGA  "DIRECTINPUT_NOTIFICATION_MSGSTRING"
+#define DIRECTINPUT_NOTIFICATION_MSGSTRINGW  L"DIRECTINPUT_NOTIFICATION_MSGSTRING"
+
+#ifdef UNICODE
+#define DIRECTINPUT_NOTIFICATION_MSGSTRING  DIRECTINPUT_NOTIFICATION_MSGSTRINGW
+#else
+#define DIRECTINPUT_NOTIFICATION_MSGSTRING  DIRECTINPUT_NOTIFICATION_MSGSTRINGA
+#endif
+
+#define DIMSGWP_NEWAPPSTART         0x00000001
+#define DIMSGWP_DX8APPSTART         0x00000002
+#define DIMSGWP_DX8MAPPERAPPSTART   0x00000003
+
+#endif /* DIRECTINPUT_VERSION >= 0x0800 */
+
+#define DIAPPIDFLAG_NOTIME         0x00000001
+#define DIAPPIDFLAG_NOSIZE         0x00000002
+
+#define DIRECTINPUT_REGSTR_VAL_APPIDFLAGA   "AppIdFlag"
+#define DIRECTINPUT_REGSTR_KEY_LASTAPPA     "MostRecentApplication"
+#define DIRECTINPUT_REGSTR_KEY_LASTMAPAPPA  "MostRecentMapperApplication"
+#define DIRECTINPUT_REGSTR_VAL_VERSIONA     "Version"
+#define DIRECTINPUT_REGSTR_VAL_NAMEA        "Name"
+#define DIRECTINPUT_REGSTR_VAL_IDA          "Id"
+#define DIRECTINPUT_REGSTR_VAL_MAPPERA      "UsesMapper"
+#define DIRECTINPUT_REGSTR_VAL_LASTSTARTA   "MostRecentStart"
+
+#define DIRECTINPUT_REGSTR_VAL_APPIDFLAGW   L"AppIdFlag"
+#define DIRECTINPUT_REGSTR_KEY_LASTAPPW     L"MostRecentApplication"
+#define DIRECTINPUT_REGSTR_KEY_LASTMAPAPPW  L"MostRecentMapperApplication"
+#define DIRECTINPUT_REGSTR_VAL_VERSIONW     L"Version"
+#define DIRECTINPUT_REGSTR_VAL_NAMEW        L"Name"
+#define DIRECTINPUT_REGSTR_VAL_IDW          L"Id"
+#define DIRECTINPUT_REGSTR_VAL_MAPPERW      L"UsesMapper"
+#define DIRECTINPUT_REGSTR_VAL_LASTSTARTW   L"MostRecentStart"
+
+#ifdef UNICODE
+#define DIRECTINPUT_REGSTR_VAL_APPIDFLAG    DIRECTINPUT_REGSTR_VAL_APPIDFLAGW
+#define DIRECTINPUT_REGSTR_KEY_LASTAPP      DIRECTINPUT_REGSTR_KEY_LASTAPPW
+#define DIRECTINPUT_REGSTR_KEY_LASTMAPAPP   DIRECTINPUT_REGSTR_KEY_LASTMAPAPPW
+#define DIRECTINPUT_REGSTR_VAL_VERSION      DIRECTINPUT_REGSTR_VAL_VERSIONW
+#define DIRECTINPUT_REGSTR_VAL_NAME         DIRECTINPUT_REGSTR_VAL_NAMEW
+#define DIRECTINPUT_REGSTR_VAL_ID           DIRECTINPUT_REGSTR_VAL_IDW
+#define DIRECTINPUT_REGSTR_VAL_MAPPER       DIRECTINPUT_REGSTR_VAL_MAPPERW
+#define DIRECTINPUT_REGSTR_VAL_LASTSTART    DIRECTINPUT_REGSTR_VAL_LASTSTARTW
+#else
+#define DIRECTINPUT_REGSTR_VAL_APPIDFLAG    DIRECTINPUT_REGSTR_VAL_APPIDFLAGA
+#define DIRECTINPUT_REGSTR_KEY_LASTAPP      DIRECTINPUT_REGSTR_KEY_LASTAPPA
+#define DIRECTINPUT_REGSTR_KEY_LASTMAPAPP   DIRECTINPUT_REGSTR_KEY_LASTMAPAPPA
+#define DIRECTINPUT_REGSTR_VAL_VERSION      DIRECTINPUT_REGSTR_VAL_VERSIONA
+#define DIRECTINPUT_REGSTR_VAL_NAME         DIRECTINPUT_REGSTR_VAL_NAMEA
+#define DIRECTINPUT_REGSTR_VAL_ID           DIRECTINPUT_REGSTR_VAL_IDA
+#define DIRECTINPUT_REGSTR_VAL_MAPPER       DIRECTINPUT_REGSTR_VAL_MAPPERA
+#define DIRECTINPUT_REGSTR_VAL_LASTSTART    DIRECTINPUT_REGSTR_VAL_LASTSTARTA
+#endif
+
+
+/****************************************************************************
+ *
+ *  Return Codes
+ *
+ ****************************************************************************/
+
+#define DIERR_NOMOREITEMS               \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NO_MORE_ITEMS)
+
+/*
+ *  Device driver-specific codes.
+ */
+
+#define DIERR_DRIVERFIRST               0x80040300L
+#define DIERR_DRIVERLAST                0x800403FFL
+
+/*
+ *  Unless the specific driver has been precisely identified, no meaning 
+ *  should be attributed to these values other than that the driver 
+ *  originated the error.  However, to illustrate the types of error that 
+ *  may be causing the failure, the PID force feedback driver distributed 
+ *  with DirectX 7 could return the following errors:
+ *
+ *  DIERR_DRIVERFIRST + 1   
+ *      The requested usage was not found.
+ *  DIERR_DRIVERFIRST + 2   
+ *      The parameter block couldn't be	downloaded to the device.
+ *  DIERR_DRIVERFIRST + 3   
+ *      PID initialization failed.
+ *  DIERR_DRIVERFIRST + 4   
+ *      The provided values couldn't be scaled.
+ */
+
+
+/*
+ *  Device installer errors.
+ */
+
+/*
+ *  Registry entry or DLL for class installer invalid
+ *  or class installer not found.
+ */
+#define DIERR_INVALIDCLASSINSTALLER     0x80040400L
+
+/*
+ *  The user cancelled the install operation.
+ */
+#define DIERR_CANCELLED                 0x80040401L
+
+/*
+ *  The INF file for the selected device could not be
+ *  found or is invalid or is damaged.
+ */
+#define DIERR_BADINF                    0x80040402L
+
+/****************************************************************************
+ *
+ *  Map files
+ *
+ ****************************************************************************/
+
+/*
+ *  Delete particular data from default map file.
+ */
+#define DIDIFT_DELETE                   0x01000000
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __DINPUTD_INCLUDED__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmdls.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,199 @@
+/************************************************************************
+*                                                                       *
+*   dmdls.h -- DLS download definitions for DirectMusic API's           *
+*                                                                       *
+*   Copyright (c) Microsoft Corporation.  All rights reserved.          *
+*                                                                       *
+************************************************************************/
+
+#ifndef _DMDLS_
+#define _DMDLS_
+
+#include "dls1.h"
+
+typedef long PCENT;     /* Pitch cents */
+typedef long GCENT;     /* Gain cents */
+typedef long TCENT;     /* Time cents */
+typedef long PERCENT;   /* Per.. cent! */
+
+typedef LONGLONG REFERENCE_TIME;
+typedef REFERENCE_TIME *LPREFERENCE_TIME;
+
+#ifndef MAKE_FOURCC
+#define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
+                ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) |   \
+                ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
+
+
+typedef DWORD           FOURCC;         /* a four character code */
+#endif
+
+typedef struct _DMUS_DOWNLOADINFO
+{
+    DWORD dwDLType;                     /* Instrument or Wave */
+    DWORD dwDLId;                       /* Unique identifier to tag this download. */
+    DWORD dwNumOffsetTableEntries;      /* Number of index in the offset address table. */
+    DWORD cbSize;                       /* Total size of this memory chunk. */
+} DMUS_DOWNLOADINFO;
+
+#define DMUS_DOWNLOADINFO_INSTRUMENT        1
+#define DMUS_DOWNLOADINFO_WAVE              2
+#define DMUS_DOWNLOADINFO_INSTRUMENT2       3   /* New version for better DLS2 support. */
+
+/* Support for oneshot and streaming wave data 
+ */
+#define DMUS_DOWNLOADINFO_WAVEARTICULATION  4   /* Wave articulation data */
+#define DMUS_DOWNLOADINFO_STREAMINGWAVE     5   /* One chunk of a streaming */
+#define DMUS_DOWNLOADINFO_ONESHOTWAVE       6
+
+#define DMUS_DEFAULT_SIZE_OFFSETTABLE   1
+
+/* Flags for DMUS_INSTRUMENT's ulFlags member */
+ 
+#define DMUS_INSTRUMENT_GM_INSTRUMENT   (1 << 0)
+
+typedef struct _DMUS_OFFSETTABLE
+{
+    ULONG ulOffsetTable[DMUS_DEFAULT_SIZE_OFFSETTABLE];
+} DMUS_OFFSETTABLE;
+
+typedef struct _DMUS_INSTRUMENT
+{
+    ULONG           ulPatch;
+    ULONG           ulFirstRegionIdx;             
+    ULONG           ulGlobalArtIdx;         /* If zero the instrument does not have an articulation */
+    ULONG           ulFirstExtCkIdx;        /* If zero no 3rd party entenstion chunks associated with the instrument */
+    ULONG           ulCopyrightIdx;         /* If zero no Copyright information associated with the instrument */
+    ULONG           ulFlags;                        
+} DMUS_INSTRUMENT;
+
+typedef struct _DMUS_REGION
+{
+    RGNRANGE        RangeKey;
+    RGNRANGE        RangeVelocity;
+    USHORT          fusOptions;
+    USHORT          usKeyGroup;
+    ULONG           ulRegionArtIdx;         /* If zero the region does not have an articulation */
+    ULONG           ulNextRegionIdx;        /* If zero no more regions */
+    ULONG           ulFirstExtCkIdx;        /* If zero no 3rd party entenstion chunks associated with the region */
+    WAVELINK        WaveLink;
+    WSMPL           WSMP;                   /*  If WSMP.cSampleLoops > 1 then a WLOOP is included */
+    WLOOP           WLOOP[1];
+} DMUS_REGION;
+
+typedef struct _DMUS_LFOPARAMS
+{
+    PCENT       pcFrequency;
+    TCENT       tcDelay;
+    GCENT       gcVolumeScale;
+    PCENT       pcPitchScale;
+    GCENT       gcMWToVolume;
+    PCENT       pcMWToPitch;
+} DMUS_LFOPARAMS;
+
+typedef struct _DMUS_VEGPARAMS
+{
+    TCENT       tcAttack;
+    TCENT       tcDecay;
+    PERCENT     ptSustain;
+    TCENT       tcRelease;
+    TCENT       tcVel2Attack;
+    TCENT       tcKey2Decay;
+} DMUS_VEGPARAMS;
+
+typedef struct _DMUS_PEGPARAMS
+{
+    TCENT       tcAttack;
+    TCENT       tcDecay;
+    PERCENT     ptSustain;
+    TCENT       tcRelease;
+    TCENT       tcVel2Attack;
+    TCENT       tcKey2Decay;
+    PCENT       pcRange;
+} DMUS_PEGPARAMS;
+
+typedef struct _DMUS_MSCPARAMS
+{
+    PERCENT     ptDefaultPan;
+} DMUS_MSCPARAMS;
+
+typedef struct _DMUS_ARTICPARAMS
+{
+    DMUS_LFOPARAMS   LFO;
+    DMUS_VEGPARAMS   VolEG;
+    DMUS_PEGPARAMS   PitchEG;
+    DMUS_MSCPARAMS   Misc;
+} DMUS_ARTICPARAMS;
+
+typedef struct _DMUS_ARTICULATION           /* Articulation chunk for DMUS_DOWNLOADINFO_INSTRUMENT format. */
+{
+    ULONG           ulArt1Idx;              /* DLS Level 1 articulation chunk */
+    ULONG           ulFirstExtCkIdx;        /* 3rd party extenstion chunks associated with the articulation */
+} DMUS_ARTICULATION;
+
+typedef struct _DMUS_ARTICULATION2          /* Articulation chunk for DMUS_DOWNLOADINFO_INSTRUMENT2 format. */
+{
+    ULONG           ulArtIdx;               /* DLS Level 1/2 articulation chunk */
+    ULONG           ulFirstExtCkIdx;        /* 3rd party extenstion chunks associated with the articulation */
+    ULONG           ulNextArtIdx;           /* Additional articulation chunks */
+} DMUS_ARTICULATION2;
+
+#define DMUS_MIN_DATA_SIZE 4       
+/*  The actual number is determined by cbSize of struct _DMUS_EXTENSIONCHUNK */
+
+typedef struct _DMUS_EXTENSIONCHUNK
+{
+    ULONG           cbSize;                      /*  Size of extension chunk  */
+    ULONG           ulNextExtCkIdx;              /*  If zero no more 3rd party entenstion chunks */
+    FOURCC          ExtCkID;                                      
+    BYTE            byExtCk[DMUS_MIN_DATA_SIZE]; /*  The actual number that follows is determined by cbSize */
+} DMUS_EXTENSIONCHUNK;
+
+/*  The actual number is determined by cbSize of struct _DMUS_COPYRIGHT */
+
+typedef struct _DMUS_COPYRIGHT
+{
+    ULONG           cbSize;                             /*  Size of copyright information */
+    BYTE            byCopyright[DMUS_MIN_DATA_SIZE];    /*  The actual number that follows is determined by cbSize */
+} DMUS_COPYRIGHT;
+
+typedef struct _DMUS_WAVEDATA
+{
+    ULONG           cbSize;
+    BYTE            byData[DMUS_MIN_DATA_SIZE]; 
+} DMUS_WAVEDATA;
+
+typedef struct _DMUS_WAVE
+{
+    ULONG           ulFirstExtCkIdx;    /* If zero no 3rd party entenstion chunks associated with the wave */
+    ULONG           ulCopyrightIdx;     /* If zero no Copyright information associated with the wave */
+    ULONG           ulWaveDataIdx;      /* Location of actual wave data. */
+    WAVEFORMATEX    WaveformatEx;       
+} DMUS_WAVE;
+
+typedef struct _DMUS_NOTERANGE *LPDMUS_NOTERANGE;
+typedef struct _DMUS_NOTERANGE
+{
+    DWORD           dwLowNote;  /* Sets the low note for the range of MIDI note events to which the instrument responds.*/
+    DWORD           dwHighNote; /* Sets the high note for the range of MIDI note events to which the instrument responds.*/
+} DMUS_NOTERANGE;
+
+typedef struct _DMUS_WAVEARTDL
+{
+    ULONG               ulDownloadIdIdx;    /* Download ID's of each buffer */
+    ULONG               ulBus;              /* Playback bus */
+    ULONG               ulBuffers;          /* Buffers */
+    ULONG               ulMasterDLId;       /* Download ID of master voice of slave group */
+    USHORT              usOptions;          /* Same as DLS2 region options */
+}   DMUS_WAVEARTDL,
+    *LPDMUS_WAVEARTDL;
+
+typedef struct _DMUS_WAVEDL
+{
+    ULONG               cbWaveData;         /* Bytes of wave data */
+}   DMUS_WAVEDL,
+    *LPDMUS_WAVEDL;
+
+#endif 
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmerror.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,843 @@
+/************************************************************************
+*                                                                       *
+*   dmerror.h -- Error codes returned by DirectMusic API's              *
+*                                                                       *
+*   Copyright (c) Microsoft Corporation.  All rights reserved.          *
+*                                                                       *
+************************************************************************/
+
+#ifndef _DMERROR_
+#define _DMERROR_
+
+#define FACILITY_DIRECTMUSIC      0x878       /* Shared with DirectSound */
+#define DMUS_ERRBASE              0x1000      /* Make error codes human readable in hex */
+
+#ifndef MAKE_HRESULT
+#define MAKE_HRESULT(sev,fac,code) \
+    ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+#endif
+    
+#define MAKE_DMHRESULTSUCCESS(code)     MAKE_HRESULT(0, FACILITY_DIRECTMUSIC, (DMUS_ERRBASE + (code)))
+#define MAKE_DMHRESULTERROR(code)       MAKE_HRESULT(1, FACILITY_DIRECTMUSIC, (DMUS_ERRBASE + (code)))
+
+/* DMUS_S_PARTIALLOAD
+ *
+ * The object could only load partially. This can happen if some components are
+ * not registered properly, such as embedded tracks and tools. This can also happen
+ * if some content is missing. For example, if a segment uses a DLS collection that
+ * is not in the loader's current search directory.
+ */
+#define DMUS_S_PARTIALLOAD              MAKE_DMHRESULTSUCCESS(0x091)
+
+/* DMUS_S_PARTIALDOWNLOAD
+ *
+ * Return value from IDirectMusicBand::Download() which indicates that
+ * some of the instruments safely downloaded, but others failed. This usually
+ * occurs when some instruments are on PChannels not supported by the performance
+ * or port.
+ */
+#define DMUS_S_PARTIALDOWNLOAD          MAKE_DMHRESULTSUCCESS(0x092)
+
+/* DMUS_S_REQUEUE
+ *
+ * Return value from IDirectMusicTool::ProcessPMsg() which indicates to the
+ * performance that it should cue the PMsg again automatically.
+ */
+#define DMUS_S_REQUEUE                  MAKE_DMHRESULTSUCCESS(0x200)
+
+/* DMUS_S_FREE
+ *
+ * Return value from IDirectMusicTool::ProcessPMsg() which indicates to the
+ * performance that it should free the PMsg automatically.
+ */
+#define DMUS_S_FREE                     MAKE_DMHRESULTSUCCESS(0x201)
+
+/* DMUS_S_END
+ *
+ * Return value from IDirectMusicTrack::Play() which indicates to the
+ * segment that the track has no more data after mtEnd.
+ */
+#define DMUS_S_END                      MAKE_DMHRESULTSUCCESS(0x202)
+
+/* DMUS_S_STRING_TRUNCATED
+ *
+ * Returned string has been truncated to fit the buffer size.
+ */
+#define DMUS_S_STRING_TRUNCATED         MAKE_DMHRESULTSUCCESS(0x210)
+
+/* DMUS_S_LAST_TOOL
+ *
+ * Returned from IDirectMusicGraph::StampPMsg(), this indicates that the PMsg
+ * is already stamped with the last tool in the graph. The returned PMsg's
+ * tool pointer is now NULL.
+ */
+#define DMUS_S_LAST_TOOL                MAKE_DMHRESULTSUCCESS(0x211)
+
+/* DMUS_S_OVER_CHORD
+ *
+ * Returned from IDirectMusicPerformance::MusicToMIDI(), this indicates 
+ * that no note has been calculated because the music value has the note 
+ * at a position higher than the top note of the chord. This applies only
+ * to DMUS_PLAYMODE_NORMALCHORD play mode. This success code indicates
+ * that the caller should not do anything with the note. It is not meant
+ * to be played against this chord.
+ */
+#define DMUS_S_OVER_CHORD               MAKE_DMHRESULTSUCCESS(0x212)
+
+/* DMUS_S_UP_OCTAVE
+ *
+ * Returned from IDirectMusicPerformance::MIDIToMusic(),  and
+ * IDirectMusicPerformance::MusicToMIDI(), this indicates 
+ * that the note conversion generated a note value that is below 0, 
+ * so it has been bumped up one or more octaves to be in the proper
+ * MIDI range of 0 through 127. 
+ * Note that this is valid for MIDIToMusic() when using play modes
+ * DMUS_PLAYMODE_FIXEDTOCHORD and DMUS_PLAYMODE_FIXEDTOKEY, both of
+ * which store MIDI values in wMusicValue. With MusicToMIDI(), it is
+ * valid for all play modes.
+ * Ofcourse, DMUS_PLAYMODE_FIXED will never return this success code.
+ */
+#define DMUS_S_UP_OCTAVE                MAKE_DMHRESULTSUCCESS(0x213)
+
+/* DMUS_S_DOWN_OCTAVE
+ *
+ * Returned from IDirectMusicPerformance::MIDIToMusic(),  and
+ * IDirectMusicPerformance::MusicToMIDI(), this indicates 
+ * that the note conversion generated a note value that is above 127, 
+ * so it has been bumped down one or more octaves to be in the proper
+ * MIDI range of 0 through 127. 
+ * Note that this is valid for MIDIToMusic() when using play modes
+ * DMUS_PLAYMODE_FIXEDTOCHORD and DMUS_PLAYMODE_FIXEDTOKEY, both of
+ * which store MIDI values in wMusicValue. With MusicToMIDI(), it is
+ * valid for all play modes.
+ * Ofcourse, DMUS_PLAYMODE_FIXED will never return this success code.
+ */
+#define DMUS_S_DOWN_OCTAVE              MAKE_DMHRESULTSUCCESS(0x214)
+
+/* DMUS_S_NOBUFFERCONTROL
+ *
+ * Although the audio output from the port will be routed to the
+ * same device as the given DirectSound buffer, buffer controls
+ * such as pan and volume will not affect the output.
+ *
+ */
+#define DMUS_S_NOBUFFERCONTROL          MAKE_DMHRESULTSUCCESS(0x215)
+
+/* DMUS_S_GARBAGE_COLLECTED
+ *
+ * The requested operation was not performed because during CollectGarbage
+ * the loader determined that the object had been released.
+ */
+#define DMUS_S_GARBAGE_COLLECTED        MAKE_DMHRESULTSUCCESS(0x216)
+
+/* DMUS_E_DRIVER_FAILED
+ *
+ * An unexpected error was returned from a device driver, indicating
+ * possible failure of the driver or hardware.
+ */
+#define DMUS_E_DRIVER_FAILED            MAKE_DMHRESULTERROR(0x0101)
+
+/* DMUS_E_PORTS_OPEN
+ *
+ * The requested operation cannot be performed while there are 
+ * instantiated ports in any process in the system.
+ */
+#define DMUS_E_PORTS_OPEN               MAKE_DMHRESULTERROR(0x0102)
+
+/* DMUS_E_DEVICE_IN_USE
+ *
+ * The requested device is already in use (possibly by a non-DirectMusic
+ * client) and cannot be opened again.
+ */
+#define DMUS_E_DEVICE_IN_USE            MAKE_DMHRESULTERROR(0x0103)
+
+/* DMUS_E_INSUFFICIENTBUFFER
+ *
+ * Buffer is not large enough for requested operation.
+ */
+#define DMUS_E_INSUFFICIENTBUFFER       MAKE_DMHRESULTERROR(0x0104)
+
+/* DMUS_E_BUFFERNOTSET
+ *
+ * No buffer was prepared for the download data.
+ */
+#define DMUS_E_BUFFERNOTSET             MAKE_DMHRESULTERROR(0x0105)
+
+/* DMUS_E_BUFFERNOTAVAILABLE
+ *
+ * Download failed due to inability to access or create download buffer.
+ */
+#define DMUS_E_BUFFERNOTAVAILABLE       MAKE_DMHRESULTERROR(0x0106)
+
+/* DMUS_E_NOTADLSCOL
+ *
+ * Error parsing DLS collection. File is corrupt.
+ */
+#define DMUS_E_NOTADLSCOL               MAKE_DMHRESULTERROR(0x0108)
+
+/* DMUS_E_INVALIDOFFSET
+ *
+ * Wave chunks in DLS collection file are at incorrect offsets.
+ */
+#define DMUS_E_INVALIDOFFSET            MAKE_DMHRESULTERROR(0x0109)
+
+/* DMUS_E_ALREADY_LOADED
+ *
+ * Second attempt to load a DLS collection that is currently open. 
+ */
+#define DMUS_E_ALREADY_LOADED           MAKE_DMHRESULTERROR(0x0111)
+
+/* DMUS_E_INVALIDPOS
+ *
+ * Error reading wave data from DLS collection. Indicates bad file.
+ */
+#define DMUS_E_INVALIDPOS               MAKE_DMHRESULTERROR(0x0113)
+
+/* DMUS_E_INVALIDPATCH
+ *
+ * There is no instrument in the collection that matches patch number.
+ */
+#define DMUS_E_INVALIDPATCH             MAKE_DMHRESULTERROR(0x0114)
+
+/* DMUS_E_CANNOTSEEK
+ *
+ * The IStream* doesn't support Seek().
+ */
+#define DMUS_E_CANNOTSEEK               MAKE_DMHRESULTERROR(0x0115)
+
+/* DMUS_E_CANNOTWRITE
+ *
+ * The IStream* doesn't support Write().
+ */
+#define DMUS_E_CANNOTWRITE              MAKE_DMHRESULTERROR(0x0116)
+
+/* DMUS_E_CHUNKNOTFOUND
+ *
+ * The RIFF parser doesn't contain a required chunk while parsing file.
+ */
+#define DMUS_E_CHUNKNOTFOUND            MAKE_DMHRESULTERROR(0x0117)
+
+/* DMUS_E_INVALID_DOWNLOADID
+ *
+ * Invalid download id was used in the process of creating a download buffer.
+ */
+#define DMUS_E_INVALID_DOWNLOADID       MAKE_DMHRESULTERROR(0x0119)
+
+/* DMUS_E_NOT_DOWNLOADED_TO_PORT
+ *
+ * Tried to unload an object that was not downloaded or previously unloaded.
+ */
+#define DMUS_E_NOT_DOWNLOADED_TO_PORT   MAKE_DMHRESULTERROR(0x0120)
+
+/* DMUS_E_ALREADY_DOWNLOADED
+ *
+ * Buffer was already downloaded to synth.
+ */
+#define DMUS_E_ALREADY_DOWNLOADED       MAKE_DMHRESULTERROR(0x0121)
+
+/* DMUS_E_UNKNOWN_PROPERTY
+ *
+ * The specified property item was not recognized by the target object.
+ */
+#define DMUS_E_UNKNOWN_PROPERTY         MAKE_DMHRESULTERROR(0x0122)
+
+/* DMUS_E_SET_UNSUPPORTED
+ *
+ * The specified property item may not be set on the target object.
+ */
+#define DMUS_E_SET_UNSUPPORTED          MAKE_DMHRESULTERROR(0x0123)
+
+/* DMUS_E_GET_UNSUPPORTED
+ *
+ * The specified property item may not be retrieved from the target object.
+ */ 
+#define DMUS_E_GET_UNSUPPORTED          MAKE_DMHRESULTERROR(0x0124)
+
+/* DMUS_E_NOTMONO
+ *
+ * Wave chunk has more than one interleaved channel. DLS format requires MONO.
+ */
+#define DMUS_E_NOTMONO                  MAKE_DMHRESULTERROR(0x0125)
+
+/* DMUS_E_BADARTICULATION
+ *
+ * Invalid articulation chunk in DLS collection.
+ */
+#define DMUS_E_BADARTICULATION          MAKE_DMHRESULTERROR(0x0126)
+
+/* DMUS_E_BADINSTRUMENT
+ *
+ * Invalid instrument chunk in DLS collection.
+ */
+#define DMUS_E_BADINSTRUMENT            MAKE_DMHRESULTERROR(0x0127)
+
+/* DMUS_E_BADWAVELINK
+ *
+ * Wavelink chunk in DLS collection points to invalid wave.
+ */
+#define DMUS_E_BADWAVELINK              MAKE_DMHRESULTERROR(0x0128)
+
+/* DMUS_E_NOARTICULATION
+ *
+ * Articulation missing from instrument in DLS collection.
+ */
+#define DMUS_E_NOARTICULATION           MAKE_DMHRESULTERROR(0x0129)
+
+/* DMUS_E_NOTPCM
+ *
+ * Downoaded DLS wave is not in PCM format. 
+*/
+#define DMUS_E_NOTPCM                   MAKE_DMHRESULTERROR(0x012A)
+
+/* DMUS_E_BADWAVE
+ *
+ * Bad wave chunk in DLS collection
+ */
+#define DMUS_E_BADWAVE                  MAKE_DMHRESULTERROR(0x012B)
+
+/* DMUS_E_BADOFFSETTABLE
+ *
+ * Offset Table for download buffer has errors. 
+ */
+#define DMUS_E_BADOFFSETTABLE           MAKE_DMHRESULTERROR(0x012C)
+
+/* DMUS_E_UNKNOWNDOWNLOAD
+ *
+ * Attempted to download unknown data type.
+ */
+#define DMUS_E_UNKNOWNDOWNLOAD          MAKE_DMHRESULTERROR(0x012D)
+
+/* DMUS_E_NOSYNTHSINK
+ *
+ * The operation could not be completed because no sink was connected to
+ * the synthesizer.
+ */
+#define DMUS_E_NOSYNTHSINK              MAKE_DMHRESULTERROR(0x012E)
+
+/* DMUS_E_ALREADYOPEN
+ *
+ * An attempt was made to open the software synthesizer while it was already 
+ * open.
+ * ASSERT?
+ */
+#define DMUS_E_ALREADYOPEN              MAKE_DMHRESULTERROR(0x012F)
+
+/* DMUS_E_ALREADYCLOSE
+ *
+ * An attempt was made to close the software synthesizer while it was already 
+ * open.
+ * ASSERT?
+ */
+#define DMUS_E_ALREADYCLOSED            MAKE_DMHRESULTERROR(0x0130)
+
+/* DMUS_E_SYNTHNOTCONFIGURED
+ *
+ * The operation could not be completed because the software synth has not 
+ * yet been fully configured.
+ * ASSERT?
+ */
+#define DMUS_E_SYNTHNOTCONFIGURED       MAKE_DMHRESULTERROR(0x0131)
+
+/* DMUS_E_SYNTHACTIVE
+ *
+ * The operation cannot be carried out while the synthesizer is active.
+ */
+#define DMUS_E_SYNTHACTIVE              MAKE_DMHRESULTERROR(0x0132)
+
+/* DMUS_E_CANNOTREAD
+ *
+ * An error occurred while attempting to read from the IStream* object.
+ */
+#define DMUS_E_CANNOTREAD               MAKE_DMHRESULTERROR(0x0133)
+
+/* DMUS_E_DMUSIC_RELEASED
+ *
+ * The operation cannot be performed because the final instance of the
+ * DirectMusic object was released. Ports cannot be used after final 
+ * release of the DirectMusic object.
+ */
+#define DMUS_E_DMUSIC_RELEASED          MAKE_DMHRESULTERROR(0x0134)
+
+/* DMUS_E_BUFFER_EMPTY
+ *
+ * There was no data in the referenced buffer.
+ */
+#define DMUS_E_BUFFER_EMPTY             MAKE_DMHRESULTERROR(0x0135)
+
+/* DMUS_E_BUFFER_FULL
+ *
+ * There is insufficient space to insert the given event into the buffer.
+ */
+#define DMUS_E_BUFFER_FULL              MAKE_DMHRESULTERROR(0x0136)
+
+/* DMUS_E_PORT_NOT_CAPTURE
+ *
+ * The given operation could not be carried out because the port is a
+ * capture port.
+ */
+#define DMUS_E_PORT_NOT_CAPTURE         MAKE_DMHRESULTERROR(0x0137)
+
+/* DMUS_E_PORT_NOT_RENDER
+ *
+ * The given operation could not be carried out because the port is a
+ * render port.
+ */
+#define DMUS_E_PORT_NOT_RENDER          MAKE_DMHRESULTERROR(0x0138)
+
+/* DMUS_E_DSOUND_NOT_SET
+ *
+ * The port could not be created because no DirectSound has been specified.
+ * Specify a DirectSound interface via the IDirectMusic::SetDirectSound
+ * method; pass NULL to have DirectMusic manage usage of DirectSound.
+ */
+#define DMUS_E_DSOUND_NOT_SET           MAKE_DMHRESULTERROR(0x0139)
+
+/* DMUS_E_ALREADY_ACTIVATED
+ *
+ * The operation cannot be carried out while the port is active.
+ */
+#define DMUS_E_ALREADY_ACTIVATED        MAKE_DMHRESULTERROR(0x013A)
+
+/* DMUS_E_INVALIDBUFFER
+ *
+ * Invalid DirectSound buffer was handed to port. 
+ */
+#define DMUS_E_INVALIDBUFFER            MAKE_DMHRESULTERROR(0x013B)
+
+/* DMUS_E_WAVEFORMATNOTSUPPORTED
+ *
+ * Invalid buffer format was handed to the synth sink.
+ */
+#define DMUS_E_WAVEFORMATNOTSUPPORTED   MAKE_DMHRESULTERROR(0x013C)
+
+/* DMUS_E_SYNTHINACTIVE
+ *
+ * The operation cannot be carried out while the synthesizer is inactive.
+ */
+#define DMUS_E_SYNTHINACTIVE            MAKE_DMHRESULTERROR(0x013D)
+
+/* DMUS_E_DSOUND_ALREADY_SET
+ *
+ * IDirectMusic::SetDirectSound has already been called. It may not be
+ * changed while in use.
+ */
+#define DMUS_E_DSOUND_ALREADY_SET       MAKE_DMHRESULTERROR(0x013E)
+
+/* DMUS_E_INVALID_EVENT
+ *
+ * The given event is invalid (either it is not a valid MIDI message
+ * or it makes use of running status). The event cannot be packed
+ * into the buffer.
+ */
+#define DMUS_E_INVALID_EVENT            MAKE_DMHRESULTERROR(0x013F)
+
+/* DMUS_E_UNSUPPORTED_STREAM
+ *
+ * The IStream* object does not contain data supported by the loading object.
+ */
+#define DMUS_E_UNSUPPORTED_STREAM       MAKE_DMHRESULTERROR(0x0150)
+
+/* DMUS_E_ALREADY_INITED
+ *
+ * The object has already been initialized.
+ */
+#define DMUS_E_ALREADY_INITED           MAKE_DMHRESULTERROR(0x0151)
+
+/* DMUS_E_INVALID_BAND
+ *
+ * The file does not contain a valid band.
+ */
+#define DMUS_E_INVALID_BAND             MAKE_DMHRESULTERROR(0x0152)
+
+/* DMUS_E_TRACK_HDR_NOT_FIRST_CK
+ *
+ * The IStream* object's data does not have a track header as the first chunk,
+ * and therefore can not be read by the segment object.
+ */
+#define DMUS_E_TRACK_HDR_NOT_FIRST_CK   MAKE_DMHRESULTERROR(0x0155)
+
+/* DMUS_E_TOOL_HDR_NOT_FIRST_CK
+ *
+ * The IStream* object's data does not have a tool header as the first chunk,
+ * and therefore can not be read by the graph object.
+ */
+#define DMUS_E_TOOL_HDR_NOT_FIRST_CK    MAKE_DMHRESULTERROR(0x0156)
+
+/* DMUS_E_INVALID_TRACK_HDR
+ *
+ * The IStream* object's data contains an invalid track header (ckid is 0 and
+ * fccType is NULL,) and therefore can not be read by the segment object.
+ */
+#define DMUS_E_INVALID_TRACK_HDR        MAKE_DMHRESULTERROR(0x0157)
+
+/* DMUS_E_INVALID_TOOL_HDR
+ *
+ * The IStream* object's data contains an invalid tool header (ckid is 0 and
+ * fccType is NULL,) and therefore can not be read by the graph object.
+ */
+#define DMUS_E_INVALID_TOOL_HDR         MAKE_DMHRESULTERROR(0x0158)
+
+/* DMUS_E_ALL_TOOLS_FAILED
+ *
+ * The graph object was unable to load all tools from the IStream* object data.
+ * This may be due to errors in the stream, or the tools being incorrectly
+ * registered on the client.
+ */
+#define DMUS_E_ALL_TOOLS_FAILED         MAKE_DMHRESULTERROR(0x0159)
+
+/* DMUS_E_ALL_TRACKS_FAILED
+ *
+ * The segment object was unable to load all tracks from the IStream* object data.
+ * This may be due to errors in the stream, or the tracks being incorrectly
+ * registered on the client.
+ */
+#define DMUS_E_ALL_TRACKS_FAILED        MAKE_DMHRESULTERROR(0x0160)
+
+/* DMUS_E_NOT_FOUND
+ *
+ * The requested item was not contained by the object.
+ */
+#define DMUS_E_NOT_FOUND                MAKE_DMHRESULTERROR(0x0161)
+
+/* DMUS_E_NOT_INIT
+ *
+ * A required object is not initialized or failed to initialize.
+ */
+#define DMUS_E_NOT_INIT                 MAKE_DMHRESULTERROR(0x0162)
+
+/* DMUS_E_TYPE_DISABLED
+ *
+ * The requested parameter type is currently disabled. Parameter types may
+ * be enabled and disabled by certain calls to SetParam().
+ */
+#define DMUS_E_TYPE_DISABLED            MAKE_DMHRESULTERROR(0x0163)
+
+/* DMUS_E_TYPE_UNSUPPORTED
+ *
+ * The requested parameter type is not supported on the object.
+ */
+#define DMUS_E_TYPE_UNSUPPORTED         MAKE_DMHRESULTERROR(0x0164)
+
+/* DMUS_E_TIME_PAST
+ *
+ * The time is in the past, and the operation can not succeed.
+ */
+#define DMUS_E_TIME_PAST                MAKE_DMHRESULTERROR(0x0165)
+
+/* DMUS_E_TRACK_NOT_FOUND
+ *
+ * The requested track is not contained by the segment.
+ */
+#define DMUS_E_TRACK_NOT_FOUND			MAKE_DMHRESULTERROR(0x0166)
+
+/* DMUS_E_TRACK_NO_CLOCKTIME_SUPPORT
+ *
+ * The track does not support Timer time playback or getparam.
+ */
+#define DMUS_E_TRACK_NO_CLOCKTIME_SUPPORT   MAKE_DMHRESULTERROR(0x0167)
+ 
+/* DMUS_E_NO_MASTER_CLOCK
+ *
+ * There is no master Timer in the performance. Be sure to call
+ * IDirectMusicPerformance::Init().
+ */
+#define DMUS_E_NO_MASTER_CLOCK          MAKE_DMHRESULTERROR(0x0170)
+
+/* DMUS_E_LOADER_NOCLASSID
+ *
+ * The class id field is required and missing in the DMUS_OBJECTDESC.
+ */
+#define DMUS_E_LOADER_NOCLASSID         MAKE_DMHRESULTERROR(0x0180)
+
+/* DMUS_E_LOADER_BADPATH
+ *
+ * The requested file path is invalid.
+ */
+#define DMUS_E_LOADER_BADPATH           MAKE_DMHRESULTERROR(0x0181)
+
+/* DMUS_E_LOADER_FAILEDOPEN
+ *
+ * File open failed - either file doesn't exist or is locked.
+ */
+#define DMUS_E_LOADER_FAILEDOPEN        MAKE_DMHRESULTERROR(0x0182)
+
+/* DMUS_E_LOADER_FORMATNOTSUPPORTED
+ *
+ * Search data type is not supported.
+ */
+#define DMUS_E_LOADER_FORMATNOTSUPPORTED    MAKE_DMHRESULTERROR(0x0183)
+
+/* DMUS_E_LOADER_FAILEDCREATE
+ *
+ * Unable to find or create object.
+ */
+#define DMUS_E_LOADER_FAILEDCREATE      MAKE_DMHRESULTERROR(0x0184)
+
+/* DMUS_E_LOADER_OBJECTNOTFOUND
+ *
+ * Object was not found.
+ */
+#define DMUS_E_LOADER_OBJECTNOTFOUND    MAKE_DMHRESULTERROR(0x0185)
+
+/* DMUS_E_LOADER_NOFILENAME
+ *
+ * The file name is missing from the DMUS_OBJECTDESC.
+ */
+#define DMUS_E_LOADER_NOFILENAME	    MAKE_DMHRESULTERROR(0x0186)
+
+/* DMUS_E_INVALIDFILE
+ *
+ * The file requested is not a valid file.
+ */
+#define DMUS_E_INVALIDFILE              MAKE_DMHRESULTERROR(0x0200)
+
+/* DMUS_E_ALREADY_EXISTS
+ *
+ * The tool is already contained in the graph. Create a new instance.
+ */
+#define DMUS_E_ALREADY_EXISTS           MAKE_DMHRESULTERROR(0x0201)
+
+/* DMUS_E_OUT_OF_RANGE
+ *
+ * Value is out of range, for instance the requested length is longer than
+ * the segment.
+ */
+#define DMUS_E_OUT_OF_RANGE             MAKE_DMHRESULTERROR(0x0202)
+
+/* DMUS_E_SEGMENT_INIT_FAILED
+ *
+ * Segment initialization failed, most likely due to a critical memory situation.
+ */
+#define DMUS_E_SEGMENT_INIT_FAILED      MAKE_DMHRESULTERROR(0x0203)
+
+/* DMUS_E_ALREADY_SENT
+ *
+ * The DMUS_PMSG has already been sent to the performance object via
+ * IDirectMusicPerformance::SendPMsg().
+ */
+#define DMUS_E_ALREADY_SENT             MAKE_DMHRESULTERROR(0x0204)
+
+/* DMUS_E_CANNOT_FREE
+ *
+ * The DMUS_PMSG was either not allocated by the performance via
+ * IDirectMusicPerformance::AllocPMsg(), or it was already freed via
+ * IDirectMusicPerformance::FreePMsg().
+ */
+#define DMUS_E_CANNOT_FREE              MAKE_DMHRESULTERROR(0x0205)
+
+/* DMUS_E_CANNOT_OPEN_PORT
+ *
+ * The default system port could not be opened.
+ */
+#define DMUS_E_CANNOT_OPEN_PORT         MAKE_DMHRESULTERROR(0x0206)
+
+/* DMUS_E_CANNOT_CONVERT
+ *
+ * A call to MIDIToMusic() or MusicToMIDI() resulted in an error because
+ * the requested conversion could not happen. This usually occurs when the
+ * provided DMUS_CHORD_KEY structure has an invalid chord or scale pattern.
+ */
+#define DMUS_E_CANNOT_CONVERT           MAKE_DMHRESULTERROR(0x0207)
+/* misspelling in previous versions of DirectX preserved for backward compatibility */
+#define DMUS_E_CONNOT_CONVERT           DMUS_E_CANNOT_CONVERT
+
+/* DMUS_E_DESCEND_CHUNK_FAIL
+ * 
+ * DMUS_E_DESCEND_CHUNK_FAIL is returned when the end of the file 
+ * was reached before the desired chunk was found.
+ */
+#define DMUS_E_DESCEND_CHUNK_FAIL       MAKE_DMHRESULTERROR(0x0210)
+
+/* DMUS_E_NOT_LOADED
+ *
+ * An attempt to use this object failed because it first needs to
+ * be loaded.
+ */
+#define DMUS_E_NOT_LOADED               MAKE_DMHRESULTERROR(0x0211)
+
+/* DMUS_E_SCRIPT_LANGUAGE_INCOMPATIBLE
+ *
+ * The activeX scripting engine for the script's language is not compatible with
+ * DirectMusic.
+ *
+ */
+#define DMUS_E_SCRIPT_LANGUAGE_INCOMPATIBLE  MAKE_DMHRESULTERROR(0x0213)
+
+/* DMUS_E_SCRIPT_UNSUPPORTED_VARTYPE
+ *
+ * A varient was used that had a type that is not supported by DirectMusic.
+ *
+ */
+#define DMUS_E_SCRIPT_UNSUPPORTED_VARTYPE    MAKE_DMHRESULTERROR(0x0214)
+
+/* DMUS_E_SCRIPT_ERROR_IN_SCRIPT
+ *
+ * An error was encountered while parsing or executing the script.
+ * The pErrorInfo parameter (if supplied) was filled with information about the error.
+ */
+#define DMUS_E_SCRIPT_ERROR_IN_SCRIPT        MAKE_DMHRESULTERROR(0x0215)
+
+/* DMUS_E_SCRIPT_CANTLOAD_OLEAUT32
+ *
+ * Loading of oleaut32.dll failed.  VBScript and other activeX scripting languages
+ * require use of oleaut32.dll.  On platforms where oleaut32.dll is not present, only
+ * the DirectMusicScript language, which doesn't require oleaut32.dll can be used.
+ */
+#define DMUS_E_SCRIPT_CANTLOAD_OLEAUT32      MAKE_DMHRESULTERROR(0x0216)
+
+/* DMUS_E_SCRIPT_LOADSCRIPT_ERROR
+ *
+ * An error occured while parsing a script loaded using LoadScript.  The script that
+ * was loaded contains an error.
+ */
+#define DMUS_E_SCRIPT_LOADSCRIPT_ERROR       MAKE_DMHRESULTERROR(0x0217)
+
+/* DMUS_E_SCRIPT_INVALID_FILE
+ *
+ * The script file is invalid.
+ */
+#define DMUS_E_SCRIPT_INVALID_FILE           MAKE_DMHRESULTERROR(0x0218)
+
+/* DMUS_E_INVALID_SCRIPTTRACK
+ *
+ * The file contains an invalid script track.
+ */
+#define DMUS_E_INVALID_SCRIPTTRACK           MAKE_DMHRESULTERROR(0x0219)
+
+/* DMUS_E_SCRIPT_VARIABLE_NOT_FOUND
+ *
+ * The script does not contain a variable with the specified name.
+ */
+#define DMUS_E_SCRIPT_VARIABLE_NOT_FOUND     MAKE_DMHRESULTERROR(0x021A)
+
+/* DMUS_E_SCRIPT_ROUTINE_NOT_FOUND
+ *
+ * The script does not contain a routine with the specified name.
+ */
+#define DMUS_E_SCRIPT_ROUTINE_NOT_FOUND      MAKE_DMHRESULTERROR(0x021B)
+
+/* DMUS_E_SCRIPT_CONTENT_READONLY
+ *
+ * Scripts variables for content referenced or embedded in a script cannot be set.
+ */
+#define DMUS_E_SCRIPT_CONTENT_READONLY       MAKE_DMHRESULTERROR(0x021C)
+
+/* DMUS_E_SCRIPT_NOT_A_REFERENCE
+ *
+ * Attempt was made to set a script's variable by reference to a value that was
+ * not an object type.
+ */
+#define DMUS_E_SCRIPT_NOT_A_REFERENCE        MAKE_DMHRESULTERROR(0x021D)
+
+/* DMUS_E_SCRIPT_VALUE_NOT_SUPPORTED
+ *
+ * Attempt was made to set a script's variable by value to an object that does
+ * not support a default value property.
+ */
+#define DMUS_E_SCRIPT_VALUE_NOT_SUPPORTED    MAKE_DMHRESULTERROR(0x021E)
+
+/* DMUS_E_INVALID_SEGMENTTRIGGERTRACK
+ *
+ * The file contains an invalid segment trigger track.
+ */
+#define DMUS_E_INVALID_SEGMENTTRIGGERTRACK   MAKE_DMHRESULTERROR(0x0220)
+
+/* DMUS_E_INVALID_LYRICSTRACK
+ *
+ * The file contains an invalid lyrics track.
+ */
+#define DMUS_E_INVALID_LYRICSTRACK           MAKE_DMHRESULTERROR(0x0221)
+
+/* DMUS_E_INVALID_PARAMCONTROLTRACK
+ *
+ * The file contains an invalid parameter control track.
+ */
+#define DMUS_E_INVALID_PARAMCONTROLTRACK     MAKE_DMHRESULTERROR(0x0222)
+
+/* DMUS_E_AUDIOVBSCRIPT_SYNTAXERROR
+ *
+ * A script written in AudioVBScript could not be read because it contained a statement that
+ * is not allowed by the AudioVBScript language.
+ */
+#define DMUS_E_AUDIOVBSCRIPT_SYNTAXERROR     MAKE_DMHRESULTERROR(0x0223)
+
+/* DMUS_E_AUDIOVBSCRIPT_RUNTIMEERROR
+ *
+ * A script routine written in AudioVBScript failed because an invalid operation occurred.  For example,
+ * adding the number 3 to a segment object would produce this error.  So would attempting to call a routine
+ * that doesn't exist.
+ */
+#define DMUS_E_AUDIOVBSCRIPT_RUNTIMEERROR     MAKE_DMHRESULTERROR(0x0224)
+
+/* DMUS_E_AUDIOVBSCRIPT_OPERATIONFAILURE
+ *
+ * A script routine written in AudioVBScript failed because a function outside of a script failed to complete.
+ * For example, a call to PlaySegment that fails to play because of low memory would return this error.
+ */
+#define DMUS_E_AUDIOVBSCRIPT_OPERATIONFAILURE     MAKE_DMHRESULTERROR(0x0225)
+
+/* DMUS_E_AUDIOPATHS_NOT_VALID
+ *
+ * The Performance has set up some PChannels using the AssignPChannel command, which 
+ * makes it not capable of supporting audio paths.
+ */
+#define DMUS_E_AUDIOPATHS_NOT_VALID     MAKE_DMHRESULTERROR(0x0226)
+
+/* DMUS_E_AUDIOPATHS_IN_USE
+ *
+ * This is the inverse of the previous error. 
+ * The Performance has set up some audio paths, which makes is incompatible
+ * with the calls to allocate pchannels, etc. 
+ */
+#define DMUS_E_AUDIOPATHS_IN_USE     MAKE_DMHRESULTERROR(0x0227)
+
+/* DMUS_E_NO_AUDIOPATH_CONFIG
+ *
+ * A segment was asked for its embedded audio path configuration,
+ * but there isn't any. 
+ */
+#define DMUS_E_NO_AUDIOPATH_CONFIG     MAKE_DMHRESULTERROR(0x0228)
+
+/* DMUS_E_AUDIOPATH_INACTIVE
+ *
+ * An audiopath is inactive, perhaps because closedown was called.
+ */
+#define DMUS_E_AUDIOPATH_INACTIVE     MAKE_DMHRESULTERROR(0x0229)
+
+/* DMUS_E_AUDIOPATH_NOBUFFER
+ *
+ * An audiopath failed to create because a requested buffer could not be created.
+ */
+#define DMUS_E_AUDIOPATH_NOBUFFER     MAKE_DMHRESULTERROR(0x022A)
+
+/* DMUS_E_AUDIOPATH_NOPORT
+ *
+ * An audiopath could not be used for playback because it lacked port assignments.
+ */
+#define DMUS_E_AUDIOPATH_NOPORT     MAKE_DMHRESULTERROR(0x022B)
+
+/* DMUS_E_NO_AUDIOPATH
+ *
+ * Attempt was made to play segment in audiopath mode and there was no audiopath.
+ */
+#define DMUS_E_NO_AUDIOPATH     MAKE_DMHRESULTERROR(0x022C)
+
+/* DMUS_E_INVALIDCHUNK
+ *
+ * Invalid data was found in a RIFF file chunk.
+ */
+#define DMUS_E_INVALIDCHUNK     MAKE_DMHRESULTERROR(0x022D)
+
+/* DMUS_E_AUDIOPATH_NOGLOBALFXBUFFER
+ *
+ * Attempt was made to create an audiopath that sends to a global effects buffer which did not exist.
+ */
+#define DMUS_E_AUDIOPATH_NOGLOBALFXBUFFER     MAKE_DMHRESULTERROR(0x022E)
+
+/* DMUS_E_INVALID_CONTAINER_OBJECT
+ *
+ * The file does not contain a valid container object.
+ */
+#define DMUS_E_INVALID_CONTAINER_OBJECT    MAKE_DMHRESULTERROR(0x022F)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmksctrl.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,166 @@
+/************************************************************************
+*                                                                       *
+*   dmksctrl.h -- Definition of IKsControl                              *
+*                                                                       *
+*   Copyright (c) Microsoft Corporation.  All rights reserved.          *
+*                                                                       *
+*   This header file contains the definition of IKsControl, which       *
+*   duplicates definitions from ks.h and ksproxy.h. Your code should    *
+*   include ks.h and ksproxy.h directly if you have them (they are      *
+*   provided in the Windows 98 DDK and will be in the Windows NT 5      *
+*   SDK).                                                               *
+*                                                                       *
+************************************************************************/
+
+#ifndef _DMKSCTRL_
+#define _DMKSCTRL_
+
+#if _MSC_VER >= 1200
+#pragma warning(push)
+#endif
+#pragma warning(disable:4201)   /* Disable warnings on anonymous unions */
+
+#include <pshpack8.h>
+
+#include <objbase.h>
+
+#if !defined(_NTRTL_)
+    #ifndef DEFINE_GUIDEX
+        #define DEFINE_GUIDEX(name) EXTERN_C const CDECL GUID name
+    #endif /* !defined(DEFINE_GUIDEX) */
+
+    #ifndef STATICGUIDOF
+        #define STATICGUIDOF(guid) STATIC_##guid
+    #endif /* !defined(STATICGUIDOF) */
+#endif /* !defined(_NTRTL_) */
+
+#ifndef STATIC_IID_IKsControl
+#define STATIC_IID_IKsControl\
+    0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96
+#endif /* STATIC_IID_IKsControl */
+
+/* 
+ * Warning: This will prevent the rest of ks.h from being pulled in if ks.h is 
+ * included after dmksctrl.h. Make sure you do not include both headers in
+ * the same source file.
+ */
+#ifndef _KS_
+#define _KS_
+
+#if (defined(_MSC_EXTENSIONS) || defined(__cplusplus)) && !defined(CINTERFACE)
+typedef struct {
+    union {
+        struct {
+            GUID    Set;
+            ULONG   Id;
+            ULONG   Flags;
+        };
+        LONGLONG    Alignment;
+    };
+} KSIDENTIFIER, *PKSIDENTIFIER;
+#else
+typedef struct {
+    union {
+        struct {
+            GUID    Set;
+            ULONG   Id;
+            ULONG   Flags;
+        } Data;
+        LONGLONG    Alignment;
+    };
+} KSIDENTIFIER, *PKSIDENTIFIER;
+#endif
+
+typedef KSIDENTIFIER KSPROPERTY, *PKSPROPERTY, KSMETHOD, *PKSMETHOD, KSEVENT, *PKSEVENT;
+
+#define KSMETHOD_TYPE_NONE                  0x00000000
+#define KSMETHOD_TYPE_READ                  0x00000001
+#define KSMETHOD_TYPE_WRITE                 0x00000002
+#define KSMETHOD_TYPE_MODIFY                0x00000003
+#define KSMETHOD_TYPE_SOURCE                0x00000004
+
+#define KSMETHOD_TYPE_SEND                  0x00000001
+#define KSMETHOD_TYPE_SETSUPPORT            0x00000100
+#define KSMETHOD_TYPE_BASICSUPPORT          0x00000200
+
+#define KSPROPERTY_TYPE_GET                 0x00000001
+#define KSPROPERTY_TYPE_SET                 0x00000002
+#define KSPROPERTY_TYPE_SETSUPPORT          0x00000100
+#define KSPROPERTY_TYPE_BASICSUPPORT        0x00000200
+#define KSPROPERTY_TYPE_RELATIONS           0x00000400
+#define KSPROPERTY_TYPE_SERIALIZESET        0x00000800
+#define KSPROPERTY_TYPE_UNSERIALIZESET      0x00001000
+#define KSPROPERTY_TYPE_SERIALIZERAW        0x00002000
+#define KSPROPERTY_TYPE_UNSERIALIZERAW      0x00004000
+#define KSPROPERTY_TYPE_SERIALIZESIZE       0x00008000
+#define KSPROPERTY_TYPE_DEFAULTVALUES       0x00010000
+
+#define KSPROPERTY_TYPE_TOPOLOGY            0x10000000
+#endif  /* _KS_ */
+
+#ifndef _IKsControl_
+#define _IKsControl_
+
+#ifdef DECLARE_INTERFACE_
+
+
+#undef INTERFACE
+#define INTERFACE IKsControl
+DECLARE_INTERFACE_(IKsControl, IUnknown)
+{
+     /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*IKsControl*/
+    STDMETHOD(KsProperty)(
+        THIS_
+        IN PKSPROPERTY Property,
+        IN ULONG PropertyLength,
+        IN OUT LPVOID PropertyData,
+        IN ULONG DataLength,
+        OUT ULONG* BytesReturned
+    ) PURE;
+    STDMETHOD(KsMethod)(
+        THIS_
+        IN PKSMETHOD Method,
+        IN ULONG MethodLength,
+        IN OUT LPVOID MethodData,
+        IN ULONG DataLength,
+        OUT ULONG* BytesReturned
+    ) PURE;
+    STDMETHOD(KsEvent)(
+        THIS_
+        IN PKSEVENT Event OPTIONAL,
+        IN ULONG EventLength,
+        IN OUT LPVOID EventData,
+        IN ULONG DataLength,
+        OUT ULONG* BytesReturned
+    ) PURE;
+};
+
+#endif /* DECLARE_INTERFACE_ */
+#endif /* _IKsControl_ */
+
+#include <poppack.h>
+
+DEFINE_GUID(IID_IKsControl, 0x28F54685, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96);
+
+/* These formats are in ksmedia.h
+ */
+#ifndef _KSMEDIA_
+
+DEFINE_GUID(KSDATAFORMAT_SUBTYPE_MIDI, 0x1D262760L, 0xE957, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00);
+DEFINE_GUID(KSDATAFORMAT_SUBTYPE_DIRECTMUSIC, 0x1a82f8bc,  0x3f8b, 0x11d2, 0xb7, 0x74, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1);
+
+#endif
+
+#if _MSC_VER >= 1200
+#pragma warning(pop)
+#endif
+
+#endif /* _DMKSCTRL */
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmplugin.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,280 @@
+/************************************************************************
+*                                                                       *
+*   dmplugin.h -- This module contains the API for plugins for the      *
+*                 DirectMusic performance layer                         *
+*                                                                       *
+*   Copyright (c) Microsoft Corporation.  All rights reserved.          *
+*                                                                       *
+************************************************************************/
+
+#ifndef _DMPLUGIN_
+#define _DMPLUGIN_
+
+#include <windows.h>
+
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+
+#include <mmsystem.h>
+#include <dmusici.h>
+
+#include <pshpack8.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+interface IDirectMusicTrack;
+interface IDirectMusicTool;
+interface IDirectMusicTool8;
+interface IDirectMusicTrack8;
+interface IDirectMusicPerformance;
+interface IDirectMusicPerformance8;
+interface IDirectMusicSegment;
+interface IDirectMusicSegment8;
+interface IDirectMusicSegmentState;
+interface IDirectMusicSegmentState8;
+interface IDirectMusicGraph;
+#ifndef __cplusplus 
+typedef interface IDirectMusicTrack IDirectMusicTrack;
+typedef interface IDirectMusicTool IDirectMusicTool;
+typedef interface IDirectMusicTool8 IDirectMusicTool8;
+typedef interface IDirectMusicTrack8 IDirectMusicTrack8;
+typedef interface IDirectMusicPerformance IDirectMusicPerformance;
+typedef interface IDirectMusicPerformance8 IDirectMusicPerformance8;
+typedef interface IDirectMusicSegment IDirectMusicSegment;
+typedef interface IDirectMusicSegment8 IDirectMusicSegment8;
+typedef interface IDirectMusicSegmentState IDirectMusicSegmentState;
+typedef interface IDirectMusicSegmentState8 IDirectMusicSegmentState8;
+typedef interface IDirectMusicGraph IDirectMusicGraph;
+#endif
+
+typedef struct _DMUS_PMSG DMUS_PMSG;
+typedef long              MUSIC_TIME;
+
+/* Registry location for tools */
+#define DMUS_REGSTR_PATH_TOOLS  "Software\\Microsoft\\DirectMusic\\Tools"
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicTool */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicTool
+DECLARE_INTERFACE_(IDirectMusicTool, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicTool */
+    STDMETHOD(Init)                 (THIS_ IDirectMusicGraph* pGraph) PURE;
+    STDMETHOD(GetMsgDeliveryType)   (THIS_ DWORD* pdwDeliveryType ) PURE;
+    STDMETHOD(GetMediaTypeArraySize)(THIS_ DWORD* pdwNumElements ) PURE;
+    STDMETHOD(GetMediaTypes)        (THIS_ DWORD** padwMediaTypes, 
+                                           DWORD dwNumElements) PURE;
+    STDMETHOD(ProcessPMsg)          (THIS_ IDirectMusicPerformance* pPerf, 
+                                           DMUS_PMSG* pPMSG) PURE;
+    STDMETHOD(Flush)                (THIS_ IDirectMusicPerformance* pPerf, 
+                                           DMUS_PMSG* pPMSG, 
+                                           REFERENCE_TIME rtTime) PURE;
+};
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicTool8 */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicTool8
+DECLARE_INTERFACE_(IDirectMusicTool8, IDirectMusicTool)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicTool */
+    STDMETHOD(Init)                 (THIS_ IDirectMusicGraph* pGraph) PURE;
+    STDMETHOD(GetMsgDeliveryType)   (THIS_ DWORD* pdwDeliveryType ) PURE;
+    STDMETHOD(GetMediaTypeArraySize)(THIS_ DWORD* pdwNumElements ) PURE;
+    STDMETHOD(GetMediaTypes)        (THIS_ DWORD** padwMediaTypes, 
+                                           DWORD dwNumElements) PURE;
+    STDMETHOD(ProcessPMsg)          (THIS_ IDirectMusicPerformance* pPerf, 
+                                           DMUS_PMSG* pPMSG) PURE;
+    STDMETHOD(Flush)                (THIS_ IDirectMusicPerformance* pPerf, 
+                                           DMUS_PMSG* pPMSG, 
+                                           REFERENCE_TIME rtTime) PURE;
+    /*  IDirectMusicTool8 */
+    STDMETHOD(Clone)                (THIS_ IDirectMusicTool ** ppTool) PURE;
+};
+
+ 
+/* The following flags are sent in the IDirectMusicTrack::Play() method */
+/* inside the dwFlags parameter */
+typedef enum enumDMUS_TRACKF_FLAGS
+{
+    DMUS_TRACKF_SEEK            = 1,      /* set on a seek */
+    DMUS_TRACKF_LOOP            = 2,      /* set on a loop (repeat) */
+    DMUS_TRACKF_START           = 4,      /* set on first call to Play */
+    DMUS_TRACKF_FLUSH           = 8,      /* set when this call is in response to a flush on the perfomance */
+    DMUS_TRACKF_DIRTY           = 0x10,   /* set when the track should consider any cached values from a previous call to GetParam to be invalidated */
+    /* The following flags are DX8 only. */
+    DMUS_TRACKF_NOTIFY_OFF      = 0x20,   /* tells track not to send notifications. */
+    DMUS_TRACKF_PLAY_OFF        = 0x40,   /* tells track not to play anything (but can still send notifications.) */
+    DMUS_TRACKF_LOOPEND         = 0x80,   /* set when the end of range is also a loop end. */
+    DMUS_TRACKF_STOP            = 0x100,  /* set when the end of range is also end of playing this segment. */
+    DMUS_TRACKF_RECOMPOSE       = 0x200,  /* set to indicate the track should compose. */
+    DMUS_TRACKF_CLOCK           = 0x400,  /* set when time parameters are in reference (Timer) time. Only valid for PlayEx(). */
+} DMUS_TRACKF_FLAGS;
+
+/* The following flags are sent in the IDirectMusicTrack8::GetParamEx() and SetParamEx() methods */
+/* inside the dwFlags parameter */
+#define DMUS_TRACK_PARAMF_CLOCK  0x01       /* set when the time is measured is in reference (Timer) time */
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicTrack */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicTrack
+DECLARE_INTERFACE_(IDirectMusicTrack, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)         (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)          (THIS) PURE;
+    STDMETHOD_(ULONG,Release)         (THIS) PURE;
+
+    /*  IDirectMusicTrack */
+    STDMETHOD(Init)                   (THIS_ IDirectMusicSegment* pSegment) PURE;
+    STDMETHOD(InitPlay)               (THIS_ IDirectMusicSegmentState* pSegmentState, 
+                                             IDirectMusicPerformance* pPerformance, 
+                                             void** ppStateData, 
+                                             DWORD dwVirtualTrackID,
+                                             DWORD dwFlags) PURE;
+    STDMETHOD(EndPlay)                (THIS_ void* pStateData) PURE;
+    STDMETHOD(Play)                   (THIS_ void* pStateData, 
+                                             MUSIC_TIME mtStart, 
+                                             MUSIC_TIME mtEnd, 
+                                             MUSIC_TIME mtOffset, 
+                                             DWORD dwFlags, 
+                                             IDirectMusicPerformance* pPerf, 
+                                             IDirectMusicSegmentState* pSegSt, 
+                                             DWORD dwVirtualID) PURE;
+    STDMETHOD(GetParam)               (THIS_ REFGUID rguidType, 
+                                             MUSIC_TIME mtTime, 
+                                             MUSIC_TIME* pmtNext, 
+                                             void* pParam) PURE; 
+    STDMETHOD(SetParam)               (THIS_ REFGUID rguidType, 
+                                             MUSIC_TIME mtTime, 
+                                             void* pParam) PURE;
+    STDMETHOD(IsParamSupported)       (THIS_ REFGUID rguidType) PURE;
+    STDMETHOD(AddNotificationType)    (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(RemoveNotificationType) (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(Clone)                  (THIS_ MUSIC_TIME mtStart, 
+                                             MUSIC_TIME mtEnd, 
+                                             IDirectMusicTrack** ppTrack) PURE;
+};
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicTrack8 */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicTrack8
+DECLARE_INTERFACE_(IDirectMusicTrack8, IDirectMusicTrack)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)         (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)          (THIS) PURE;
+    STDMETHOD_(ULONG,Release)         (THIS) PURE;
+
+    /*  IDirectMusicTrack */
+    STDMETHOD(Init)                   (THIS_ IDirectMusicSegment* pSegment) PURE;
+    STDMETHOD(InitPlay)               (THIS_ IDirectMusicSegmentState* pSegmentState, 
+                                             IDirectMusicPerformance* pPerformance, 
+                                             void** ppStateData, 
+                                             DWORD dwVirtualTrackID,
+                                             DWORD dwFlags) PURE;
+    STDMETHOD(EndPlay)                (THIS_ void* pStateData) PURE;
+    STDMETHOD(Play)                   (THIS_ void* pStateData, 
+                                             MUSIC_TIME mtStart, 
+                                             MUSIC_TIME mtEnd, 
+                                             MUSIC_TIME mtOffset, 
+                                             DWORD dwFlags, 
+                                             IDirectMusicPerformance* pPerf, 
+                                             IDirectMusicSegmentState* pSegSt, 
+                                             DWORD dwVirtualID) PURE;
+    STDMETHOD(GetParam)               (THIS_ REFGUID rguidType, 
+                                             MUSIC_TIME mtTime, 
+                                             MUSIC_TIME* pmtNext, 
+                                             void* pParam) PURE; 
+    STDMETHOD(SetParam)               (THIS_ REFGUID rguidType, 
+                                             MUSIC_TIME mtTime, 
+                                             void* pParam) PURE;
+    STDMETHOD(IsParamSupported)       (THIS_ REFGUID rguidType) PURE;
+    STDMETHOD(AddNotificationType)    (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(RemoveNotificationType) (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(Clone)                  (THIS_ MUSIC_TIME mtStart, 
+                                             MUSIC_TIME mtEnd, 
+                                             IDirectMusicTrack** ppTrack) PURE;
+    /* IDirectMusicTrack8 */
+    STDMETHOD(PlayEx)                 (THIS_ void* pStateData, 
+                                             REFERENCE_TIME rtStart, 
+                                             REFERENCE_TIME rtEnd, 
+                                             REFERENCE_TIME rtOffset, 
+                                             DWORD dwFlags, 
+                                             IDirectMusicPerformance* pPerf, 
+                                             IDirectMusicSegmentState* pSegSt, 
+                                             DWORD dwVirtualID) PURE; 
+    STDMETHOD(GetParamEx)             (THIS_ REFGUID rguidType,         /* Command type. */
+                                             REFERENCE_TIME rtTime,     /* Time, in ref time if dwFlags == DMUS_TRACK_PARAMF_CLOCK. Otherwise, music time. */
+                                             REFERENCE_TIME* prtNext,   /* Time of next parameter, relative to rtTime, in music or Timer time units. */
+                                             void* pParam,              /* Pointer to the parameter data. */
+                                             void * pStateData,         /* State data for track instance. */
+                                             DWORD dwFlags) PURE;       /* Control flags. */
+    STDMETHOD(SetParamEx)             (THIS_ REFGUID rguidType, 
+                                             REFERENCE_TIME rtTime, 
+                                             void* pParam,              /* Pointer to the parameter data. */
+                                             void * pStateData,         /* State data for track instance. */
+                                             DWORD dwFlags) PURE;       /* Control flags. */
+    STDMETHOD(Compose)                (THIS_ IUnknown* pContext,        /* Context for composition */
+                                             DWORD dwTrackGroup,
+                                             IDirectMusicTrack** ppResultTrack) PURE;
+    STDMETHOD(Join)                   (THIS_ IDirectMusicTrack* pNewTrack,
+                                             MUSIC_TIME mtJoin,
+                                             IUnknown* pContext,        /* Context for joining */
+                                             DWORD dwTrackGroup,
+                                             IDirectMusicTrack** ppResultTrack) PURE;
+};
+
+/* CLSID's */
+DEFINE_GUID(CLSID_DirectMusicTempoTrack,0xd2ac2885, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicSeqTrack,0xd2ac2886, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicSysExTrack,0xd2ac2887, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicTimeSigTrack,0xd2ac2888, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicChordTrack,0xd2ac288b, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicCommandTrack,0xd2ac288c, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicStyleTrack,0xd2ac288d, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicMotifTrack,0xd2ac288e, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicSignPostTrack,0xf17e8672, 0xc3b4, 0x11d1, 0x87, 0xb, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicBandTrack,0xd2ac2894, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicChordMapTrack,0xd2ac2896, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicMuteTrack,0xd2ac2898, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* New CLSID's for DX8 */
+DEFINE_GUID(CLSID_DirectMusicScriptTrack,0x4108fa85, 0x3586, 0x11d3, 0x8b, 0xd7, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xb6); /* {4108FA85-3586-11d3-8BD7-00600893B1B6} */
+DEFINE_GUID(CLSID_DirectMusicMarkerTrack,0x55a8fd00, 0x4288, 0x11d3, 0x9b, 0xd1, 0x8a, 0xd, 0x61, 0xc8, 0x88, 0x35);
+DEFINE_GUID(CLSID_DirectMusicSegmentTriggerTrack, 0xbae4d665, 0x4ea1, 0x11d3, 0x8b, 0xda, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xb6); /* {BAE4D665-4EA1-11d3-8BDA-00600893B1B6} */
+DEFINE_GUID(CLSID_DirectMusicLyricsTrack, 0x995c1cf5, 0x54ff, 0x11d3, 0x8b, 0xda, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xb6); /* {995C1CF5-54FF-11d3-8BDA-00600893B1B6} */
+DEFINE_GUID(CLSID_DirectMusicParamControlTrack, 0x4be0537b, 0x5c19, 0x11d3, 0x8b, 0xdc, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xb6); /* {4BE0537B-5C19-11d3-8BDC-00600893B1B6} */
+DEFINE_GUID(CLSID_DirectMusicWaveTrack,0xeed36461, 0x9ea5, 0x11d3, 0x9b, 0xd1, 0x0, 0x80, 0xc7, 0x15, 0xa, 0x74);
+
+/* IID's */
+DEFINE_GUID(IID_IDirectMusicTrack, 0xf96029a1, 0x4282, 0x11d2, 0x87, 0x17, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicTool,0xd2ac28ba, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Interface IDs for DX8 */
+/* changed interfaces (GUID only) */
+DEFINE_GUID(IID_IDirectMusicTool8, 0xe674303, 0x3b05, 0x11d3, 0x9b, 0xd1, 0xf9, 0xe7, 0xf0, 0xa0, 0x15, 0x36);
+DEFINE_GUID(IID_IDirectMusicTrack8, 0xe674304, 0x3b05, 0x11d3, 0x9b, 0xd1, 0xf9, 0xe7, 0xf0, 0xa0, 0x15, 0x36);
+
+#ifdef __cplusplus
+}; /* extern "C" */
+#endif
+
+#include <poppack.h>
+
+#endif /* #ifndef _DMPLUGIN_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmusbuff.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,41 @@
+/***************************************************************************
+*                                                                          *
+*   DMusBuff.h -- This module defines the buffer format for DirectMusic    *
+*                 Shared file between user mode and kernel mode components *
+*                                                                          *
+*   Copyright (c) 1998, Microsoft Corp. All rights reserved.               *
+*                                                                          *
+***************************************************************************/
+
+#ifndef _DMusBuff_
+#define _DMusBuff_
+
+/* Format of DirectMusic events in a buffer
+ *
+ * A buffer contains 1 or more events, each with the following header.
+ * Immediately following the header is the event data. The header+data
+ * size is rounded to the nearest quadword (8 bytes).
+ */
+ 
+#include <pshpack4.h>                       /* Do not pad at end - that's where the data is */ 
+typedef struct _DMUS_EVENTHEADER *LPDMUS_EVENTHEADER;
+typedef struct _DMUS_EVENTHEADER
+{
+    DWORD           cbEvent;                /* Unrounded bytes in event */
+    DWORD           dwChannelGroup;         /* Channel group of event */
+    REFERENCE_TIME  rtDelta;                /* Delta from start time of entire buffer */
+    DWORD           dwFlags;                /* Flags DMUS_EVENT_xxx */
+} DMUS_EVENTHEADER;
+#include <poppack.h>
+
+#define DMUS_EVENT_STRUCTURED   0x00000001  /* Unstructured data (SysEx, etc.) */
+
+/* The number of bytes to allocate for an event with 'cb' data bytes.
+ */ 
+#define QWORD_ALIGN(x) (((x) + 7) & ~7)
+#define DMUS_EVENT_SIZE(cb) QWORD_ALIGN(sizeof(DMUS_EVENTHEADER) + cb)
+
+
+#endif /* _DMusBuff_ */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmusicc.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,784 @@
+/************************************************************************
+*                                                                       *
+*   dmusicc.h -- This module defines the DirectMusic core API's         *
+*                                                                       *
+*   Copyright (c) Microsoft Corporation.  All rights reserved.          *
+*                                                                       *
+************************************************************************/
+
+#ifndef _DMUSICC_
+#define _DMUSICC_
+
+#include <windows.h>
+
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+
+#include <mmsystem.h>
+
+#include "dls1.h"
+#include "dmerror.h"
+#include "dmdls.h"
+#include "dsound.h"
+#include "dmusbuff.h"
+
+#include <pshpack8.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef ULONGLONG    SAMPLE_TIME;
+typedef ULONGLONG    SAMPLE_POSITION;
+typedef SAMPLE_TIME *LPSAMPLE_TIME;
+
+#define DMUS_MAX_DESCRIPTION 128
+#define DMUS_MAX_DRIVER 128
+
+typedef struct _DMUS_BUFFERDESC *LPDMUS_BUFFERDESC;
+typedef struct _DMUS_BUFFERDESC
+{
+    DWORD dwSize;
+    DWORD dwFlags;
+    GUID guidBufferFormat;
+    DWORD cbBuffer;
+} DMUS_BUFFERDESC;
+
+/* DMUS_EFFECT_ flags are used in the dwEffectFlags fields of both DMUS_PORTCAPS
+ * and DMUS_PORTPARAMS.
+ */
+#define DMUS_EFFECT_NONE             0x00000000
+#define DMUS_EFFECT_REVERB           0x00000001
+#define DMUS_EFFECT_CHORUS           0x00000002
+#define DMUS_EFFECT_DELAY            0x00000004
+
+/* For DMUS_PORTCAPS dwClass
+ */
+#define DMUS_PC_INPUTCLASS       (0)
+#define DMUS_PC_OUTPUTCLASS      (1)
+
+/* For DMUS_PORTCAPS dwFlags
+ */
+#define DMUS_PC_DLS              (0x00000001)   // Supports DLS downloading and DLS level 1.
+#define DMUS_PC_EXTERNAL         (0x00000002)   // External MIDI module.
+#define DMUS_PC_SOFTWARESYNTH    (0x00000004)   // Software synthesizer.
+#define DMUS_PC_MEMORYSIZEFIXED  (0x00000008)   // Memory size is fixed.
+#define DMUS_PC_GMINHARDWARE     (0x00000010)   // GM sound set is built in, no need to download.
+#define DMUS_PC_GSINHARDWARE     (0x00000020)   // GS sound set is built in.
+#define DMUS_PC_XGINHARDWARE     (0x00000040)   // XG sound set is built in.
+#define DMUS_PC_DIRECTSOUND      (0x00000080)   // Connects to DirectSound via a DirectSound buffer.
+#define DMUS_PC_SHAREABLE        (0x00000100)   // Synth can be actively shared by multiple apps at once.
+#define DMUS_PC_DLS2             (0x00000200)   // Supports DLS2 instruments.
+#define DMUS_PC_AUDIOPATH        (0x00000400)   // Multiple outputs can be connected to DirectSound for audiopaths.
+#define DMUS_PC_WAVE             (0x00000800)   // Supports streaming and one shot waves.
+
+#define DMUS_PC_SYSTEMMEMORY     (0x7FFFFFFF)   // Sample memory is system memory.
+
+
+typedef struct _DMUS_PORTCAPS
+{
+    DWORD   dwSize;
+    DWORD   dwFlags;
+    GUID    guidPort;
+    DWORD   dwClass;
+    DWORD   dwType;
+    DWORD   dwMemorySize;
+    DWORD   dwMaxChannelGroups;
+    DWORD   dwMaxVoices;
+    DWORD   dwMaxAudioChannels;
+    DWORD   dwEffectFlags;
+    WCHAR   wszDescription[DMUS_MAX_DESCRIPTION];
+} DMUS_PORTCAPS;
+
+typedef DMUS_PORTCAPS *LPDMUS_PORTCAPS;
+
+/* Values for DMUS_PORTCAPS dwType. This field indicates the underlying
+ * driver type of the port.
+ */
+#define DMUS_PORT_WINMM_DRIVER      (0)
+#define DMUS_PORT_USER_MODE_SYNTH   (1)
+#define DMUS_PORT_KERNEL_MODE       (2)
+
+/* These flags (set in dwValidParams) indicate which other members of the */
+/* DMUS_PORTPARAMS are valid. */
+/* */
+#define DMUS_PORTPARAMS_VOICES           0x00000001
+#define DMUS_PORTPARAMS_CHANNELGROUPS    0x00000002
+#define DMUS_PORTPARAMS_AUDIOCHANNELS    0x00000004
+#define DMUS_PORTPARAMS_SAMPLERATE       0x00000008
+#define DMUS_PORTPARAMS_EFFECTS          0x00000020
+#define DMUS_PORTPARAMS_SHARE            0x00000040
+#define DMUS_PORTPARAMS_FEATURES         0x00000080     /* DirectX 8.0 and above */
+
+typedef struct _DMUS_PORTPARAMS
+{
+    DWORD   dwSize;
+    DWORD   dwValidParams;
+    DWORD   dwVoices;
+    DWORD   dwChannelGroups;
+    DWORD   dwAudioChannels;
+    DWORD   dwSampleRate;
+    DWORD   dwEffectFlags;
+    BOOL    fShare;
+} DMUS_PORTPARAMS7;
+
+typedef struct _DMUS_PORTPARAMS8
+{
+    DWORD   dwSize;
+    DWORD   dwValidParams;
+    DWORD   dwVoices;
+    DWORD   dwChannelGroups;
+    DWORD   dwAudioChannels;
+    DWORD   dwSampleRate;
+    DWORD   dwEffectFlags;
+    BOOL    fShare;
+    DWORD   dwFeatures;
+} DMUS_PORTPARAMS8;
+
+#define DMUS_PORT_FEATURE_AUDIOPATH     0x00000001	/* Supports audiopath connection to DirectSound buffers. */
+#define DMUS_PORT_FEATURE_STREAMING     0x00000002	/* Supports streaming waves through the synth. */
+
+
+typedef DMUS_PORTPARAMS8 DMUS_PORTPARAMS;
+typedef DMUS_PORTPARAMS *LPDMUS_PORTPARAMS;
+
+typedef struct _DMUS_SYNTHSTATS *LPDMUS_SYNTHSTATS;
+typedef struct _DMUS_SYNTHSTATS8 *LPDMUS_SYNTHSTATS8;
+typedef struct _DMUS_SYNTHSTATS
+{
+    DWORD   dwSize;             /* Size in bytes of the structure */
+    DWORD   dwValidStats;       /* Flags indicating which fields below are valid. */
+    DWORD   dwVoices;           /* Average number of voices playing. */
+    DWORD   dwTotalCPU;         /* Total CPU usage as percent * 100. */
+    DWORD   dwCPUPerVoice;      /* CPU per voice as percent * 100. */
+    DWORD   dwLostNotes;        /* Number of notes lost in 1 second. */
+    DWORD   dwFreeMemory;       /* Free memory in bytes */
+    long    lPeakVolume;        /* Decibel level * 100. */
+} DMUS_SYNTHSTATS;
+
+typedef struct _DMUS_SYNTHSTATS8
+{
+    DWORD   dwSize;             /* Size in bytes of the structure */
+    DWORD   dwValidStats;       /* Flags indicating which fields below are valid. */
+    DWORD   dwVoices;           /* Average number of voices playing. */
+    DWORD   dwTotalCPU;         /* Total CPU usage as percent * 100. */
+    DWORD   dwCPUPerVoice;      /* CPU per voice as percent * 100. */
+    DWORD   dwLostNotes;        /* Number of notes lost in 1 second. */
+    DWORD   dwFreeMemory;       /* Free memory in bytes */
+    long    lPeakVolume;        /* Decibel level * 100. */
+	DWORD   dwSynthMemUse;		/* Memory used by synth wave data */
+} DMUS_SYNTHSTATS8;
+
+#define DMUS_SYNTHSTATS_VOICES          (1 << 0)
+#define DMUS_SYNTHSTATS_TOTAL_CPU       (1 << 1)
+#define DMUS_SYNTHSTATS_CPU_PER_VOICE   (1 << 2)
+#define DMUS_SYNTHSTATS_LOST_NOTES      (1 << 3)
+#define DMUS_SYNTHSTATS_PEAK_VOLUME     (1 << 4)
+#define DMUS_SYNTHSTATS_FREE_MEMORY     (1 << 5)
+
+#define DMUS_SYNTHSTATS_SYSTEMMEMORY    DMUS_PC_SYSTEMMEMORY
+
+typedef struct _DMUS_WAVES_REVERB_PARAMS
+{
+    float   fInGain;        /* Input gain in dB (to avoid output overflows) */
+    float   fReverbMix;     /* Reverb mix in dB. 0dB means 100% wet reverb (no direct signal)
+                            Negative values gives less wet signal.
+                            The coeficients are calculated so that the overall output level stays
+                            (approximately) constant regardless of the ammount of reverb mix. */
+    float   fReverbTime;    /* The reverb decay time, in milliseconds. */
+    float   fHighFreqRTRatio; /* The ratio of the high frequencies to the global reverb time.
+                            Unless very 'splashy-bright' reverbs are wanted, this should be set to
+                            a value < 1.0.
+                            For example if dRevTime==1000ms and dHighFreqRTRatio=0.1 than the
+                            decay time for high frequencies will be 100ms.*/
+
+} DMUS_WAVES_REVERB_PARAMS;
+
+/*  Note: Default values for Reverb are:
+    fInGain             = 0.0dB   (no change in level)
+    fReverbMix          = -10.0dB   (a reasonable reverb mix)
+    fReverbTime         = 1000.0ms (one second global reverb time)
+    fHighFreqRTRatio    = 0.001    (the ratio of the high frequencies to the global reverb time)
+*/
+
+typedef enum
+{
+    DMUS_CLOCK_SYSTEM = 0,
+    DMUS_CLOCK_WAVE = 1
+} DMUS_CLOCKTYPE;
+
+#define DMUS_CLOCKF_GLOBAL              0x00000001
+
+typedef struct _DMUS_CLOCKINFO7 *LPDMUS_CLOCKINFO7;
+typedef struct _DMUS_CLOCKINFO7
+{
+    DWORD           dwSize;
+    DMUS_CLOCKTYPE  ctType;
+    GUID            guidClock;          /* Identifies this time source */
+    WCHAR           wszDescription[DMUS_MAX_DESCRIPTION];
+} DMUS_CLOCKINFO7;
+
+typedef struct _DMUS_CLOCKINFO8 *LPDMUS_CLOCKINFO8;
+typedef struct _DMUS_CLOCKINFO8
+{
+    DWORD           dwSize;
+    DMUS_CLOCKTYPE  ctType;
+    GUID            guidClock;          /* Identifies this time source */
+    WCHAR           wszDescription[DMUS_MAX_DESCRIPTION];
+    DWORD           dwFlags;
+} DMUS_CLOCKINFO8;
+
+typedef DMUS_CLOCKINFO8 DMUS_CLOCKINFO;
+typedef DMUS_CLOCKINFO *LPDMUS_CLOCKINFO;
+
+/* Default bus identifiers
+ *
+ * The first 17 are direct mappings to the destinations defined in both
+ * the MMA DLS Level 2 specification and the Microsoft Multi-Channel audio
+ * specification.
+ */
+#define DSBUSID_FIRST_SPKR_LOC              0
+#define DSBUSID_FRONT_LEFT                  0
+#define DSBUSID_LEFT                        0   /* Front left is also just left */
+#define DSBUSID_FRONT_RIGHT                 1
+#define DSBUSID_RIGHT                       1   /* Ditto front right */
+#define DSBUSID_FRONT_CENTER                2
+#define DSBUSID_LOW_FREQUENCY               3
+#define DSBUSID_BACK_LEFT                   4
+#define DSBUSID_BACK_RIGHT                  5
+#define DSBUSID_FRONT_LEFT_OF_CENTER        6
+#define DSBUSID_FRONT_RIGHT_OF_CENTER       7
+#define DSBUSID_BACK_CENTER                 8
+#define DSBUSID_SIDE_LEFT                   9
+#define DSBUSID_SIDE_RIGHT                 10
+#define DSBUSID_TOP_CENTER                 11
+#define DSBUSID_TOP_FRONT_LEFT             12
+#define DSBUSID_TOP_FRONT_CENTER           13
+#define DSBUSID_TOP_FRONT_RIGHT            14
+#define DSBUSID_TOP_BACK_LEFT              15
+#define DSBUSID_TOP_BACK_CENTER            16
+#define DSBUSID_TOP_BACK_RIGHT             17
+#define DSBUSID_LAST_SPKR_LOC              17
+
+#define DSBUSID_IS_SPKR_LOC(id) ( ((id) >= DSBUSID_FIRST_SPKR_LOC) && ((id) <= DSBUSID_LAST_SPKR_LOC) )
+
+/* These bus identifiers are for the standard DLS effect sends
+ */
+#define DSBUSID_REVERB_SEND                64
+#define DSBUSID_CHORUS_SEND                65
+
+/* Dynamic bus identifiers start here. See the documentation for how
+ * synthesizers map the output of voices to static and dynamic
+ * bus identifiers.
+ */
+#define DSBUSID_DYNAMIC_0                 512
+
+/* Null bus, used to identify busses that have no function mapping.
+*/
+#define DSBUSID_NULL			   0xFFFFFFFF
+
+interface IDirectMusic;
+interface IDirectMusic8;
+interface IDirectMusicBuffer;
+interface IDirectMusicPort;
+interface IDirectMusicThru;
+interface IReferenceClock;
+
+#ifndef __cplusplus
+
+typedef interface IDirectMusic IDirectMusic;
+typedef interface IDirectMusic8 IDirectMusic8;
+typedef interface IDirectMusicPort IDirectMusicPort;
+typedef interface IDirectMusicBuffer IDirectMusicBuffer;
+typedef interface IDirectMusicThru IDirectMusicThru;
+typedef interface IReferenceClock IReferenceClock;
+
+#endif  /* C++ */
+
+typedef IDirectMusic *LPDIRECTMUSIC;
+typedef IDirectMusic8 *LPDIRECTMUSIC8;
+typedef IDirectMusicPort *LPDIRECTMUSICPORT;
+typedef IDirectMusicBuffer *LPDIRECTMUSICBUFFER;
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusic
+DECLARE_INTERFACE_(IDirectMusic, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusic */
+    STDMETHOD(EnumPort)             (THIS_ DWORD dwIndex,
+                                           LPDMUS_PORTCAPS pPortCaps) PURE;
+    STDMETHOD(CreateMusicBuffer)    (THIS_ LPDMUS_BUFFERDESC pBufferDesc,
+                                           LPDIRECTMUSICBUFFER *ppBuffer,
+                                           LPUNKNOWN pUnkOuter) PURE;
+    STDMETHOD(CreatePort)           (THIS_ REFCLSID rclsidPort,
+                                           LPDMUS_PORTPARAMS pPortParams,
+                                           LPDIRECTMUSICPORT *ppPort,
+                                           LPUNKNOWN pUnkOuter) PURE;
+    STDMETHOD(EnumMasterClock)      (THIS_ DWORD dwIndex,
+                                           LPDMUS_CLOCKINFO lpClockInfo) PURE;
+    STDMETHOD(GetMasterClock)       (THIS_ LPGUID pguidClock,
+                                           IReferenceClock **ppReferenceClock) PURE;
+    STDMETHOD(SetMasterClock)       (THIS_ REFGUID rguidClock) PURE;
+    STDMETHOD(Activate)             (THIS_ BOOL fEnable) PURE;
+    STDMETHOD(GetDefaultPort)       (THIS_ LPGUID pguidPort) PURE;
+    STDMETHOD(SetDirectSound)       (THIS_ LPDIRECTSOUND pDirectSound,
+                                           HWND hWnd) PURE;
+};
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusic8
+DECLARE_INTERFACE_(IDirectMusic8, IDirectMusic)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusic */
+    STDMETHOD(EnumPort)             (THIS_ DWORD dwIndex,
+                                           LPDMUS_PORTCAPS pPortCaps) PURE;
+    STDMETHOD(CreateMusicBuffer)    (THIS_ LPDMUS_BUFFERDESC pBufferDesc,
+                                           LPDIRECTMUSICBUFFER *ppBuffer,
+                                           LPUNKNOWN pUnkOuter) PURE;
+    STDMETHOD(CreatePort)           (THIS_ REFCLSID rclsidPort,
+                                           LPDMUS_PORTPARAMS pPortParams,
+                                           LPDIRECTMUSICPORT *ppPort,
+                                           LPUNKNOWN pUnkOuter) PURE;
+    STDMETHOD(EnumMasterClock)      (THIS_ DWORD dwIndex,
+                                           LPDMUS_CLOCKINFO lpClockInfo) PURE;
+    STDMETHOD(GetMasterClock)       (THIS_ LPGUID pguidClock,
+                                           IReferenceClock **ppReferenceClock) PURE;
+    STDMETHOD(SetMasterClock)       (THIS_ REFGUID rguidClock) PURE;
+    STDMETHOD(Activate)             (THIS_ BOOL fEnable) PURE;
+    STDMETHOD(GetDefaultPort)       (THIS_ LPGUID pguidPort) PURE;
+    STDMETHOD(SetDirectSound)       (THIS_ LPDIRECTSOUND pDirectSound,
+                                           HWND hWnd) PURE;
+    /*  IDirectMusic8 */
+    STDMETHOD(SetExternalMasterClock)
+                                    (THIS_ IReferenceClock *pClock) PURE;
+};
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicBuffer
+DECLARE_INTERFACE_(IDirectMusicBuffer, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicBuffer */
+    STDMETHOD(Flush)                (THIS) PURE;
+    STDMETHOD(TotalTime)            (THIS_ LPREFERENCE_TIME prtTime) PURE;
+
+    STDMETHOD(PackStructured)       (THIS_ REFERENCE_TIME rt,
+                                           DWORD dwChannelGroup,
+                                           DWORD dwChannelMessage) PURE;
+
+    STDMETHOD(PackUnstructured)     (THIS_ REFERENCE_TIME rt,
+                                           DWORD dwChannelGroup,
+                                           DWORD cb,
+                                           LPBYTE lpb) PURE;
+
+    STDMETHOD(ResetReadPtr)         (THIS) PURE;
+    STDMETHOD(GetNextEvent)         (THIS_ LPREFERENCE_TIME prt,
+                                           LPDWORD pdwChannelGroup,
+                                           LPDWORD pdwLength,
+                                           LPBYTE *ppData) PURE;
+
+    STDMETHOD(GetRawBufferPtr)      (THIS_ LPBYTE *ppData) PURE;
+    STDMETHOD(GetStartTime)         (THIS_ LPREFERENCE_TIME prt) PURE;
+    STDMETHOD(GetUsedBytes)         (THIS_ LPDWORD pcb) PURE;
+    STDMETHOD(GetMaxBytes)          (THIS_ LPDWORD pcb) PURE;
+    STDMETHOD(GetBufferFormat)      (THIS_ LPGUID pGuidFormat) PURE;
+
+    STDMETHOD(SetStartTime)         (THIS_ REFERENCE_TIME rt) PURE;
+    STDMETHOD(SetUsedBytes)         (THIS_ DWORD cb) PURE;
+};
+
+typedef IDirectMusicBuffer IDirectMusicBuffer8;
+typedef IDirectMusicBuffer8 *LPDIRECTMUSICBUFFER8;
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicInstrument
+DECLARE_INTERFACE_(IDirectMusicInstrument, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)           (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)            (THIS) PURE;
+    STDMETHOD_(ULONG,Release)           (THIS) PURE;
+
+    /* IDirectMusicInstrument */
+    STDMETHOD(GetPatch)                 (THIS_ DWORD* pdwPatch) PURE;
+    STDMETHOD(SetPatch)                 (THIS_ DWORD dwPatch) PURE;
+};
+
+typedef IDirectMusicInstrument IDirectMusicInstrument8;
+typedef IDirectMusicInstrument8 *LPDIRECTMUSICINSTRUMENT8;
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicDownloadedInstrument
+DECLARE_INTERFACE_(IDirectMusicDownloadedInstrument, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)           (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)            (THIS) PURE;
+    STDMETHOD_(ULONG,Release)           (THIS) PURE;
+
+    /* IDirectMusicDownloadedInstrument */
+    /* None at this time */
+};
+
+typedef IDirectMusicDownloadedInstrument IDirectMusicDownloadedInstrument8;
+typedef IDirectMusicDownloadedInstrument8 *LPDIRECTMUSICDOWNLOADEDINSTRUMENT8;
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicCollection
+DECLARE_INTERFACE_(IDirectMusicCollection, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)           (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)            (THIS) PURE;
+    STDMETHOD_(ULONG,Release)           (THIS) PURE;
+
+    /* IDirectMusicCollection */
+    STDMETHOD(GetInstrument)            (THIS_ DWORD dwPatch,
+                                               IDirectMusicInstrument** ppInstrument) PURE;
+    STDMETHOD(EnumInstrument)           (THIS_ DWORD dwIndex,
+                                               DWORD* pdwPatch,
+                                               LPWSTR pwszName,
+                                               DWORD dwNameLen) PURE;
+};
+
+typedef IDirectMusicCollection IDirectMusicCollection8;
+typedef IDirectMusicCollection8 *LPDIRECTMUSICCOLLECTION8;
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicDownload
+DECLARE_INTERFACE_(IDirectMusicDownload , IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicDownload */
+    STDMETHOD(GetBuffer)            (THIS_ void** ppvBuffer,
+                                           DWORD* pdwSize) PURE;
+};
+
+typedef IDirectMusicDownload IDirectMusicDownload8;
+typedef IDirectMusicDownload8 *LPDIRECTMUSICDOWNLOAD8;
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicPortDownload
+DECLARE_INTERFACE_(IDirectMusicPortDownload, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicPortDownload */
+    STDMETHOD(GetBuffer)            (THIS_ DWORD dwDLId,
+                                           IDirectMusicDownload** ppIDMDownload) PURE;
+    STDMETHOD(AllocateBuffer)       (THIS_ DWORD dwSize,
+                                           IDirectMusicDownload** ppIDMDownload) PURE;
+    STDMETHOD(GetDLId)              (THIS_ DWORD* pdwStartDLId,
+                                           DWORD dwCount) PURE;
+    STDMETHOD(GetAppend)            (THIS_ DWORD* pdwAppend) PURE;
+    STDMETHOD(Download)             (THIS_ IDirectMusicDownload* pIDMDownload) PURE;
+    STDMETHOD(Unload)               (THIS_ IDirectMusicDownload* pIDMDownload) PURE;
+};
+
+typedef IDirectMusicPortDownload IDirectMusicPortDownload8;
+typedef IDirectMusicPortDownload8 *LPDIRECTMUSICPORTDOWNLOAD8;
+
+/* Standard values for voice priorities. Numerically higher priorities are higher in priority.
+ * These priorities are used to set the voice priority for all voices on a channel. They are
+ * used in the dwPriority parameter of IDirectMusicPort::GetPriority and returned in the
+ * lpwPriority parameter of pdwPriority.
+ *
+ * These priorities are shared with DirectSound.
+ */
+
+#ifndef _DIRECTAUDIO_PRIORITIES_DEFINED_
+#define _DIRECTAUDIO_PRIORITIES_DEFINED_
+
+#define DAUD_CRITICAL_VOICE_PRIORITY    (0xF0000000)
+#define DAUD_HIGH_VOICE_PRIORITY        (0xC0000000)
+#define DAUD_STANDARD_VOICE_PRIORITY    (0x80000000)
+#define DAUD_LOW_VOICE_PRIORITY         (0x40000000)
+#define DAUD_PERSIST_VOICE_PRIORITY     (0x10000000)
+
+/* These are the default priorities assigned if not overridden. By default priorities are
+ * equal across channel groups (e.g. channel 5 on channel group 1 has the same priority as
+ * channel 5 on channel group 2).
+ *
+ * In accordance with DLS level 1, channel 10 has the highest priority, followed by 1 through 16
+ * except for 10.
+ */
+#define DAUD_CHAN1_VOICE_PRIORITY_OFFSET    (0x0000000E)
+#define DAUD_CHAN2_VOICE_PRIORITY_OFFSET    (0x0000000D)
+#define DAUD_CHAN3_VOICE_PRIORITY_OFFSET    (0x0000000C)
+#define DAUD_CHAN4_VOICE_PRIORITY_OFFSET    (0x0000000B)
+#define DAUD_CHAN5_VOICE_PRIORITY_OFFSET    (0x0000000A)
+#define DAUD_CHAN6_VOICE_PRIORITY_OFFSET    (0x00000009)
+#define DAUD_CHAN7_VOICE_PRIORITY_OFFSET    (0x00000008)
+#define DAUD_CHAN8_VOICE_PRIORITY_OFFSET    (0x00000007)
+#define DAUD_CHAN9_VOICE_PRIORITY_OFFSET    (0x00000006)
+#define DAUD_CHAN10_VOICE_PRIORITY_OFFSET   (0x0000000F)
+#define DAUD_CHAN11_VOICE_PRIORITY_OFFSET   (0x00000005)
+#define DAUD_CHAN12_VOICE_PRIORITY_OFFSET   (0x00000004)
+#define DAUD_CHAN13_VOICE_PRIORITY_OFFSET   (0x00000003)
+#define DAUD_CHAN14_VOICE_PRIORITY_OFFSET   (0x00000002)
+#define DAUD_CHAN15_VOICE_PRIORITY_OFFSET   (0x00000001)
+#define DAUD_CHAN16_VOICE_PRIORITY_OFFSET   (0x00000000)
+
+
+#define DAUD_CHAN1_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN1_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN2_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN2_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN3_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN3_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN4_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN4_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN5_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN5_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN6_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN6_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN7_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN7_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN8_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN8_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN9_DEF_VOICE_PRIORITY   (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN9_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN10_DEF_VOICE_PRIORITY  (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN10_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN11_DEF_VOICE_PRIORITY  (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN11_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN12_DEF_VOICE_PRIORITY  (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN12_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN13_DEF_VOICE_PRIORITY  (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN13_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN14_DEF_VOICE_PRIORITY  (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN14_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN15_DEF_VOICE_PRIORITY  (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN15_VOICE_PRIORITY_OFFSET)
+#define DAUD_CHAN16_DEF_VOICE_PRIORITY  (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN16_VOICE_PRIORITY_OFFSET)
+
+#endif  /* _DIRECTAUDIO_PRIORITIES_DEFINED_ */
+
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicPort
+DECLARE_INTERFACE_(IDirectMusicPort, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicPort */
+    /*  */
+    STDMETHOD(PlayBuffer)           (THIS_ LPDIRECTMUSICBUFFER pBuffer) PURE;
+    STDMETHOD(SetReadNotificationHandle) (THIS_ HANDLE hEvent) PURE;
+    STDMETHOD(Read)                 (THIS_ LPDIRECTMUSICBUFFER pBuffer) PURE;
+    STDMETHOD(DownloadInstrument)   (THIS_ IDirectMusicInstrument *pInstrument,
+                                     IDirectMusicDownloadedInstrument **ppDownloadedInstrument,
+                                     DMUS_NOTERANGE *pNoteRanges,
+                                     DWORD dwNumNoteRanges) PURE;
+    STDMETHOD(UnloadInstrument)     (THIS_ IDirectMusicDownloadedInstrument *pDownloadedInstrument) PURE;
+    STDMETHOD(GetLatencyClock)      (THIS_ IReferenceClock **ppClock) PURE;
+    STDMETHOD(GetRunningStats)      (THIS_ LPDMUS_SYNTHSTATS pStats) PURE;
+    STDMETHOD(Compact)              (THIS) PURE;
+    STDMETHOD(GetCaps)              (THIS_ LPDMUS_PORTCAPS pPortCaps) PURE;
+    STDMETHOD(DeviceIoControl)      (THIS_ DWORD dwIoControlCode,
+                                           LPVOID lpInBuffer,
+                                           DWORD nInBufferSize,
+                                           LPVOID lpOutBuffer,
+                                           DWORD nOutBufferSize,
+                                           LPDWORD lpBytesReturned,
+                                           LPOVERLAPPED lpOverlapped) PURE;
+    STDMETHOD(SetNumChannelGroups)  (THIS_ DWORD dwChannelGroups) PURE;
+    STDMETHOD(GetNumChannelGroups)  (THIS_ LPDWORD pdwChannelGroups) PURE;
+    STDMETHOD(Activate)             (THIS_ BOOL fActive) PURE;
+    STDMETHOD(SetChannelPriority)   (THIS_ DWORD dwChannelGroup, DWORD dwChannel, DWORD dwPriority) PURE;
+    STDMETHOD(GetChannelPriority)   (THIS_ DWORD dwChannelGroup, DWORD dwChannel, LPDWORD pdwPriority) PURE;
+    STDMETHOD(SetDirectSound)       (THIS_ LPDIRECTSOUND pDirectSound, LPDIRECTSOUNDBUFFER pDirectSoundBuffer) PURE;
+    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pWaveFormatEx, LPDWORD pdwWaveFormatExSize, LPDWORD pdwBufferSize) PURE;
+};
+
+typedef IDirectMusicPort IDirectMusicPort8;
+typedef IDirectMusicPort8 *LPDIRECTMUSICPORT8;
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicThru
+DECLARE_INTERFACE_(IDirectMusicThru, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicThru
+     */
+    STDMETHOD(ThruChannel)          (THIS_ DWORD dwSourceChannelGroup,
+                                           DWORD dwSourceChannel,
+                                           DWORD dwDestinationChannelGroup,
+                                           DWORD dwDestinationChannel,
+                                           LPDIRECTMUSICPORT pDestinationPort) PURE;
+};
+
+typedef IDirectMusicThru IDirectMusicThru8;
+typedef IDirectMusicThru8 *LPDIRECTMUSICTHRU8;
+
+#ifndef __IReferenceClock_INTERFACE_DEFINED__
+#define __IReferenceClock_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IReferenceClock,0x56a86897,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70);
+
+#undef  INTERFACE
+#define INTERFACE  IReferenceClock
+DECLARE_INTERFACE_(IReferenceClock, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)           (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)            (THIS) PURE;
+    STDMETHOD_(ULONG,Release)           (THIS) PURE;
+
+    /*  IReferenceClock */
+    /*  */
+
+    /*  get the time now */
+    STDMETHOD(GetTime)                  (THIS_ REFERENCE_TIME *pTime) PURE;
+
+    /*  ask for an async notification that a time has elapsed */
+    STDMETHOD(AdviseTime)               (THIS_ REFERENCE_TIME baseTime,         /*  base time */
+                                               REFERENCE_TIME streamTime,       /*  stream offset time */
+                                               HANDLE hEvent,                   /*  advise via this event */
+                                               DWORD * pdwAdviseCookie) PURE;   /*  where your cookie goes */
+
+    /*  ask for an async periodic notification that a time has elapsed */
+    STDMETHOD(AdvisePeriodic)           (THIS_ REFERENCE_TIME startTime,        /*  starting at this time */
+                                               REFERENCE_TIME periodTime,       /*  time between notifications */
+                                               HANDLE hSemaphore,               /*  advise via a semaphore */
+                                               DWORD * pdwAdviseCookie) PURE;   /*  where your cookie goes */
+
+    /*  cancel a request for notification */
+    STDMETHOD(Unadvise)                 (THIS_ DWORD dwAdviseCookie) PURE;
+};
+
+#endif /* __IReferenceClock_INTERFACE_DEFINED__ */
+
+DEFINE_GUID(CLSID_DirectMusic,0x636b9f10,0x0c7d,0x11d1,0x95,0xb2,0x00,0x20,0xaf,0xdc,0x74,0x21);
+DEFINE_GUID(CLSID_DirectMusicCollection,0x480ff4b0, 0x28b2, 0x11d1, 0xbe, 0xf7, 0x0, 0xc0, 0x4f, 0xbf, 0x8f, 0xef);
+DEFINE_GUID(CLSID_DirectMusicSynth,0x58C2B4D0,0x46E7,0x11D1,0x89,0xAC,0x00,0xA0,0xC9,0x05,0x41,0x29);
+
+DEFINE_GUID(IID_IDirectMusic,0x6536115a,0x7b2d,0x11d2,0xba,0x18,0x00,0x00,0xf8,0x75,0xac,0x12);
+DEFINE_GUID(IID_IDirectMusicBuffer,0xd2ac2878, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicPort, 0x08f2d8c9,0x37c2,0x11d2,0xb9,0xf9,0x00,0x00,0xf8,0x75,0xac,0x12);
+DEFINE_GUID(IID_IDirectMusicThru, 0xced153e7, 0x3606, 0x11d2, 0xb9, 0xf9, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(IID_IDirectMusicPortDownload,0xd2ac287a, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicDownload,0xd2ac287b, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicCollection,0xd2ac287c, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicInstrument,0xd2ac287d, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicDownloadedInstrument,0xd2ac287e, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+
+/* Alternate interface ID for IID_IDirectMusic, available in DX7 release and after. */
+DEFINE_GUID(IID_IDirectMusic2,0x6fc2cae1, 0xbc78, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+
+DEFINE_GUID(IID_IDirectMusic8,0x2d3629f7,0x813d,0x4939,0x85,0x08,0xf0,0x5c,0x6b,0x75,0xfd,0x97);
+
+#define IID_IDirectMusicThru8 IID_IDirectMusicThru
+#define IID_IDirectMusicPortDownload8 IID_IDirectMusicPortDownload
+#define IID_IDirectMusicDownload8 IID_IDirectMusicDownload
+#define IID_IDirectMusicCollection8 IID_IDirectMusicCollection
+#define IID_IDirectMusicInstrument8 IID_IDirectMusicInstrument
+#define IID_IDirectMusicDownloadedInstrument8 IID_IDirectMusicDownloadedInstrument
+#define IID_IDirectMusicPort8 IID_IDirectMusicPort
+
+
+/* Property Query GUID_DMUS_PROP_GM_Hardware - Local GM set, no need to download
+ * Property Query GUID_DMUS_PROP_GS_Hardware - Local GS set, no need to download
+ * Property Query GUID_DMUS_PROP_XG_Hardware - Local XG set, no need to download
+ * Property Query GUID_DMUS_PROP_DLS1        - Support DLS level 1
+ * Property Query GUID_DMUS_PROP_INSTRUMENT2 - Support new INSTRUMENT2 download format
+ * Property Query GUID_DMUS_PROP_XG_Capable  - Support minimum requirements of XG
+ * Property Query GUID_DMUS_PROP_GS_Capable  - Support minimum requirements of GS
+ * Property Query GUID_DMUS_PROP_SynthSink_DSOUND - Synthsink talks to DirectSound
+ * Property Query GUID_DMUS_PROP_SynthSink_WAVE - Synthsink talks to Wave device
+ *
+ * Item 0: Supported
+ * Returns a DWORD which is non-zero if the feature is supported
+ */
+DEFINE_GUID(GUID_DMUS_PROP_GM_Hardware, 0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(GUID_DMUS_PROP_GS_Hardware, 0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(GUID_DMUS_PROP_XG_Hardware, 0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(GUID_DMUS_PROP_XG_Capable,  0x6496aba1, 0x61b0, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_GUID(GUID_DMUS_PROP_GS_Capable,  0x6496aba2, 0x61b0, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_GUID(GUID_DMUS_PROP_DLS1,        0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(GUID_DMUS_PROP_DLS2,        0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_GUID(GUID_DMUS_PROP_INSTRUMENT2, 0x865fd372, 0x9f67, 0x11d2, 0x87, 0x2a, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_DMUS_PROP_SynthSink_DSOUND,0xaa97844, 0xc877, 0x11d1, 0x87, 0xc, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_DMUS_PROP_SynthSink_WAVE,0xaa97845, 0xc877, 0x11d1, 0x87, 0xc, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_DMUS_PROP_SampleMemorySize, 0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_GUID(GUID_DMUS_PROP_SamplePlaybackRate, 0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+
+/* Property Get/Set GUID_DMUS_PROP_WriteLatency
+ *
+ * Item 0: Synth buffer write latency, in milliseconds
+ * Get/Set SynthSink latency, the average time after the play head that the next buffer gets written.
+ */
+DEFINE_GUID(GUID_DMUS_PROP_WriteLatency,0x268a0fa0, 0x60f2, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+
+/* Property Get/Set GUID_DMUS_PROP_WritePeriod
+ *
+ * Item 0: Synth buffer write period, in milliseconds
+ * Get/Set SynthSink buffer write period, time span between successive writes.
+ */
+DEFINE_GUID(GUID_DMUS_PROP_WritePeriod,0x268a0fa1, 0x60f2, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+
+/* Property Get GUID_DMUS_PROP_MemorySize
+ *
+ * Item 0: Memory size
+ * Returns a DWORD containing the total number of bytes of sample RAM
+ */
+DEFINE_GUID(GUID_DMUS_PROP_MemorySize,  0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+
+/* Property Set GUID_DMUS_PROP_WavesReverb
+ *
+ * Item 0: DMUS_WAVES_REVERB structure
+ * Sets reverb parameters
+ */
+DEFINE_GUID(GUID_DMUS_PROP_WavesReverb,0x4cb5622, 0x32e5, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+
+/* Property Set GUID_DMUS_PROP_Effects
+ *
+ * Item 0: DWORD with effects flags.
+ * Get/Set effects bits, same as dwEffectFlags in DMUS_PORTPARAMS and DMUS_PORTCAPS:
+ * DMUS_EFFECT_NONE
+ * DMUS_EFFECT_REVERB
+ * DMUS_EFFECT_CHORUS
+ */
+DEFINE_GUID(GUID_DMUS_PROP_Effects, 0xcda8d611, 0x684a, 0x11d2, 0x87, 0x1e, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Property Set GUID_DMUS_PROP_LegacyCaps
+ *
+ * Item 0: The MIDINCAPS or MIDIOUTCAPS which describes the port's underlying WinMM device. This property is only supported
+ * by ports which wrap WinMM devices.
+ */
+
+DEFINE_GUID(GUID_DMUS_PROP_LegacyCaps,0xcfa7cdc2, 0x00a1, 0x11d2, 0xaa, 0xd5, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+
+/* Property Set GUID_DMUS_PROP_Volume
+ *
+ * Item 0: A long which contains an offset, in 1/100 dB, to be added to the final volume
+ *
+ */
+DEFINE_GUID(GUID_DMUS_PROP_Volume, 0xfedfae25L, 0xe46e, 0x11d1, 0xaa, 0xce, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+
+/* Min and Max values for setting volume with GUID_DMUS_PROP_Volume */
+
+#define DMUS_VOLUME_MAX     2000        /* +20 dB */
+#define DMUS_VOLUME_MIN   -20000        /* -200 dB */
+
+#ifdef __cplusplus
+}; /* extern "C" */
+#endif
+
+#include <poppack.h>
+
+#endif /* #ifndef _DMUSICC_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmusicf.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2199 @@
+/************************************************************************
+*                                                                       *
+*   dmusicf.h -- This module defines the DirectMusic file formats       *
+*                                                                       *
+*   Copyright (c) Microsoft Corporation.  All rights reserved.          *
+*                                                                       *
+************************************************************************/
+
+#ifndef _DMUSICF_
+#define _DMUSICF_
+
+
+#include <windows.h>
+
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+
+#include <mmsystem.h>
+
+#include <pshpack8.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+interface IDirectMusicCollection;
+#ifndef __cplusplus
+typedef interface IDirectMusicCollection IDirectMusicCollection;
+#endif
+
+/* Common chunks */
+
+#define DMUS_FOURCC_GUID_CHUNK        mmioFOURCC('g','u','i','d')
+#define DMUS_FOURCC_INFO_LIST         mmioFOURCC('I','N','F','O')
+#define DMUS_FOURCC_UNFO_LIST         mmioFOURCC('U','N','F','O')
+#define DMUS_FOURCC_UNAM_CHUNK        mmioFOURCC('U','N','A','M')
+#define DMUS_FOURCC_UART_CHUNK        mmioFOURCC('U','A','R','T')
+#define DMUS_FOURCC_UCOP_CHUNK        mmioFOURCC('U','C','O','P')
+#define DMUS_FOURCC_USBJ_CHUNK        mmioFOURCC('U','S','B','J')
+#define DMUS_FOURCC_UCMT_CHUNK        mmioFOURCC('U','C','M','T')
+#define DMUS_FOURCC_CATEGORY_CHUNK    mmioFOURCC('c','a','t','g')
+#define DMUS_FOURCC_VERSION_CHUNK     mmioFOURCC('v','e','r','s')
+
+/* The following structures are used by the Tracks, and are the packed structures */
+/* that are passed to the Tracks inside the IStream. */
+
+
+typedef struct _DMUS_IO_SEQ_ITEM
+{
+    MUSIC_TIME    mtTime;
+    MUSIC_TIME    mtDuration;
+    DWORD         dwPChannel;
+    short         nOffset;
+    BYTE          bStatus;
+    BYTE          bByte1;
+    BYTE          bByte2;
+} DMUS_IO_SEQ_ITEM;
+
+
+typedef struct _DMUS_IO_CURVE_ITEM
+{
+    MUSIC_TIME  mtStart;
+    MUSIC_TIME  mtDuration;
+    MUSIC_TIME  mtResetDuration;
+    DWORD       dwPChannel;
+    short       nOffset;
+    short       nStartValue;
+    short       nEndValue;
+    short       nResetValue;
+    BYTE        bType;
+    BYTE        bCurveShape;
+    BYTE        bCCData;
+    BYTE        bFlags;
+    /* Following was added for DirectX8. */
+    WORD        wParamType;      /* RPN or NRPN parameter number. */
+    WORD        wMergeIndex;     /* Allows multiple parameters to be merged (pitchbend, volume, and expression.) */
+} DMUS_IO_CURVE_ITEM;
+
+
+typedef struct _DMUS_IO_TEMPO_ITEM
+{
+    MUSIC_TIME    lTime;
+    double        dblTempo;
+} DMUS_IO_TEMPO_ITEM;
+
+
+typedef struct _DMUS_IO_SYSEX_ITEM
+{
+    MUSIC_TIME    mtTime;
+    DWORD         dwPChannel;
+    DWORD         dwSysExLength;
+} DMUS_IO_SYSEX_ITEM;
+
+typedef DMUS_CHORD_KEY DMUS_CHORD_PARAM; /* DMUS_CHORD_KEY defined in dmusici.h */
+
+typedef struct _DMUS_RHYTHM_PARAM
+{
+    DMUS_TIMESIGNATURE  TimeSig;
+    DWORD               dwRhythmPattern;
+} DMUS_RHYTHM_PARAM;
+
+typedef struct _DMUS_TEMPO_PARAM
+{
+    MUSIC_TIME  mtTime;
+    double      dblTempo;
+} DMUS_TEMPO_PARAM;
+
+
+typedef struct _DMUS_MUTE_PARAM
+{
+    DWORD   dwPChannel;
+    DWORD   dwPChannelMap;
+    BOOL    fMute;
+} DMUS_MUTE_PARAM;
+
+/* Style chunks */
+
+#define DMUS_FOURCC_STYLE_FORM            mmioFOURCC('D','M','S','T')
+#define DMUS_FOURCC_STYLE_CHUNK           mmioFOURCC('s','t','y','h')
+#define DMUS_FOURCC_PART_LIST             mmioFOURCC('p','a','r','t')
+#define DMUS_FOURCC_PART_CHUNK            mmioFOURCC('p','r','t','h')
+#define DMUS_FOURCC_NOTE_CHUNK            mmioFOURCC('n','o','t','e')
+#define DMUS_FOURCC_CURVE_CHUNK           mmioFOURCC('c','r','v','e')
+#define DMUS_FOURCC_MARKER_CHUNK          mmioFOURCC('m','r','k','r')
+#define DMUS_FOURCC_RESOLUTION_CHUNK      mmioFOURCC('r','s','l','n')
+#define DMUS_FOURCC_ANTICIPATION_CHUNK    mmioFOURCC('a','n','p','n')
+#define DMUS_FOURCC_PATTERN_LIST          mmioFOURCC('p','t','t','n')
+#define DMUS_FOURCC_PATTERN_CHUNK         mmioFOURCC('p','t','n','h')
+#define DMUS_FOURCC_RHYTHM_CHUNK          mmioFOURCC('r','h','t','m')
+#define DMUS_FOURCC_PARTREF_LIST          mmioFOURCC('p','r','e','f')
+#define DMUS_FOURCC_PARTREF_CHUNK         mmioFOURCC('p','r','f','c')
+#define DMUS_FOURCC_STYLE_PERS_REF_LIST   mmioFOURCC('p','r','r','f')
+#define DMUS_FOURCC_MOTIFSETTINGS_CHUNK   mmioFOURCC('m','t','f','s')
+
+/* Flags used by variations: these make up the DWORDs in dwVariationChoices.               */
+
+/* These flags determine the types of chords supported by a given variation in DirectMusic */
+/* mode.  The first seven flags (bits 1-7) are set if the variation supports major chords  */
+/* rooted in scale positions, so, e.g., if bits 1, 2, and 4 are set, the variation         */
+/* supports major chords rooted in the tonic, second, and fourth scale positions.  The     */
+/* next seven flags serve the same purpose, but for minor chords, and the following seven  */
+/* flags serve the same purpose for chords that are not major or minor (e.g., SUS 4        */
+/* chords).  Bits 22, 23, and 24 are set if the variation supports chords rooted in the    */
+/* scale, chords rooted sharp of scale tones, and chords rooted flat of scale tones,       */
+/* respectively.  For example, to support a C# minor chord in the scale of C Major,        */
+/* bits 8 (for tonic minor) and 24 (for sharp) need to be set.  Bits 25, 26, an 27 handle  */
+/* chords that are triads, 6th or 7th chords, and chords with extensions, respectively.    */
+/* bits 28 and 29 handle chords that are followed by tonic and dominant chords,            */
+/* respectively.                                                                           */
+#define DMUS_VARIATIONF_MAJOR        0x0000007F /* Seven positions in the scale - major chords. */
+#define DMUS_VARIATIONF_MINOR        0x00003F80 /* Seven positions in the scale - minor chords. */
+#define DMUS_VARIATIONF_OTHER        0x001FC000 /* Seven positions in the scale - other chords. */
+#define DMUS_VARIATIONF_ROOT_SCALE   0x00200000 /* Handles chord roots in the scale. */
+#define DMUS_VARIATIONF_ROOT_FLAT    0x00400000 /* Handles flat chord roots (based on scale notes). */
+#define DMUS_VARIATIONF_ROOT_SHARP   0x00800000 /* Handles sharp chord roots (based on scale notes). */
+#define DMUS_VARIATIONF_TYPE_TRIAD   0x01000000 /* Handles simple chords - triads. */
+#define DMUS_VARIATIONF_TYPE_6AND7   0x02000000 /* Handles simple chords - 6 and 7. */
+#define DMUS_VARIATIONF_TYPE_COMPLEX 0x04000000 /* Handles complex chords. */
+#define DMUS_VARIATIONF_DEST_TO1     0x08000000 /* Handles transitions to 1 chord. */
+#define DMUS_VARIATIONF_DEST_TO5     0x10000000 /* Handles transitions to 5 chord. */
+#define DMUS_VARIATIONF_DEST_OTHER   0x40000000 /* Handles transitions to chords other than 1 . */
+
+/* legacy mask for variation modes */
+#define DMUS_VARIATIONF_MODES        0xE0000000
+/* Bits 29 and 31 of the variation flags are the Mode bits.  If both are 0, it's IMA. */
+/* If bit 29 is 1, it's Direct Music. */
+#define DMUS_VARIATIONF_MODES_EX     (0x20000000 | 0x80000000)
+#define DMUS_VARIATIONF_IMA25_MODE   0x00000000
+#define DMUS_VARIATIONF_DMUS_MODE    0x20000000
+
+/* Set this if the part uses marker events */
+#define DMUS_PARTF_USE_MARKERS       0x1
+/* Set this if the part is allowed to switch only on chord-aligned markers */
+#define DMUS_PARTF_ALIGN_CHORDS      0x2
+
+/* These specify if the marker event signals whether to stop a variation or start a
+pattern/variation (or both), and whether new variations must align with a chord */
+#define DMUS_MARKERF_START            0x1
+#define DMUS_MARKERF_STOP             0x2
+#define DMUS_MARKERF_CHORD_ALIGN      0x4
+
+/* if this flag is set, variation settings in a playing pattern-based track's state data will
+persist in the track after it stops playing */
+#define DMUS_PATTERNF_PERSIST_CONTROL 0x1
+
+/* These specify possible values for DMUS_IO_PARTREF.bRandomVariation
+   all but DMUS_VARIATIONT_SEQUENTIAL and DMUS_VARIATIONT_RANDOM are DirectX8. */
+typedef enum enumDMUS_VARIATIONT_TYPES
+{
+    DMUS_VARIATIONT_SEQUENTIAL       = 0, /* Play sequential starting with variation 1. */
+    DMUS_VARIATIONT_RANDOM           = 1, /* Play randomly. */
+    DMUS_VARIATIONT_RANDOM_START     = 2, /* Play sequential starting with a random variation. */
+    DMUS_VARIATIONT_NO_REPEAT        = 3, /* Play randomly, but don't play the same variation twice. */
+    DMUS_VARIATIONT_RANDOM_ROW       = 4  /* Play randomly as a row: don't repeat any variation until all have played. */
+} DMUS_VARIATIONT_TYPES;
+
+/* These specify possible values for DMUS_IO_PATTERN.wEmbellishment (DirectX8) */
+typedef enum enumDMUS_EMBELLISHT_TYPES
+{
+    DMUS_EMBELLISHT_NORMAL          = 0,
+    DMUS_EMBELLISHT_FILL            = 1,
+    DMUS_EMBELLISHT_BREAK           = 2,
+    DMUS_EMBELLISHT_INTRO           = 4,
+    DMUS_EMBELLISHT_END             = 8,
+    DMUS_EMBELLISHT_MOTIF           = 16,
+    DMUS_EMBELLISHT_ALL             = 0xFFFF
+} DMUS_EMBELLISHT_TYPES;
+
+#pragma pack(2)
+
+typedef struct _DMUS_IO_TIMESIG
+{
+    /* Time signatures define how many beats per measure, which note receives */
+    /* the beat, and the grid resolution. */
+    BYTE    bBeatsPerMeasure;   /* beats per measure (top of time sig) */
+    BYTE    bBeat;              /* what note receives the beat (bottom of time sig.) */
+                                /* we can assume that 0 means 256th note */
+    WORD    wGridsPerBeat;      /* grids per beat */
+} DMUS_IO_TIMESIG;
+
+typedef struct _DMUS_IO_STYLE
+{
+    DMUS_IO_TIMESIG     timeSig;        /* Styles have a default Time Signature */
+    double              dblTempo;
+} DMUS_IO_STYLE;
+
+typedef struct _DMUS_IO_VERSION
+{
+    DWORD               dwVersionMS;        /* Version # high-order 32 bits */
+    DWORD               dwVersionLS;        /* Version # low-order 32 bits  */
+} DMUS_IO_VERSION;
+
+typedef struct _DMUS_IO_PATTERN
+{
+    DMUS_IO_TIMESIG     timeSig;           /* Patterns can override the Style's Time sig. */
+    BYTE                bGrooveBottom;     /* bottom of groove range */
+    BYTE                bGrooveTop;        /* top of groove range */
+    WORD                wEmbellishment;    /* Fill, Break, Intro, End, Normal, Motif */
+    WORD                wNbrMeasures;      /* length in measures */
+    BYTE                bDestGrooveBottom; /* bottom of groove range for next pattern */
+    BYTE                bDestGrooveTop;    /* top of groove range for next pattern */
+    DWORD               dwFlags;           /* various flags */
+} DMUS_IO_PATTERN;
+
+typedef struct _DMUS_IO_STYLEPART
+{
+    DMUS_IO_TIMESIG     timeSig;        /* can override pattern's */
+    DWORD               dwVariationChoices[32]; /* MOAW choice bitfield */
+    GUID                guidPartID;     /* identifies the part */
+    WORD                wNbrMeasures;   /* length of the Part */
+    BYTE                bPlayModeFlags; /* see PLAYMODE flags */
+    BYTE                bInvertUpper;   /* inversion upper limit */
+    BYTE                bInvertLower;   /* inversion lower limit */
+    BYTE                bPad[3];        /* for DWORD alignment */
+    DWORD               dwFlags;        /* various flags */
+} DMUS_IO_STYLEPART;
+
+typedef struct _DMUS_IO_PARTREF
+{
+    GUID    guidPartID;         /* unique ID for matching up with parts */
+    WORD    wLogicalPartID;     /* corresponds to port/device/midi channel OBSOLETE */
+    BYTE    bVariationLockID;   /* parts with the same ID lock variations. */
+                                /* high bit is used to identify master Part */
+    BYTE    bSubChordLevel;     /* tells which sub chord level this part wants */
+    BYTE    bPriority;          /* 256 priority levels. Parts with lower priority */
+                                /* aren't played first when a device runs out of */
+                                /* notes */
+    BYTE    bRandomVariation;   /* when set, matching variations play in random order */
+                                /* when clear, matching variations play sequentially */
+    WORD    wPad;               /* not used */
+    DWORD   dwPChannel;         /* replaces wLogicalPartID */
+} DMUS_IO_PARTREF;
+
+typedef struct _DMUS_IO_STYLENOTE
+{
+    MUSIC_TIME  mtGridStart;    /* when this note occurs */
+    DWORD       dwVariation;    /* variation bits */
+    MUSIC_TIME  mtDuration;     /* how long this note lasts */
+    short       nTimeOffset;    /* offset from mtGridStart */
+    WORD        wMusicValue;    /* Position in scale. */
+    BYTE        bVelocity;      /* Note velocity. */
+    BYTE        bTimeRange;     /* Range to randomize start time. */
+    BYTE        bDurRange;      /* Range to randomize duration. */
+    BYTE        bVelRange;      /* Range to randomize velocity. */
+    BYTE        bInversionID;   /* Identifies inversion group to which this note belongs */
+    BYTE        bPlayModeFlags; /* Can override part */
+    /* Following exists only under DirectX8 and on */
+    BYTE        bNoteFlags;     /* values from DMUS_NOTEF_FLAGS */
+} DMUS_IO_STYLENOTE;
+
+typedef struct _DMUS_IO_STYLECURVE
+{
+    MUSIC_TIME  mtGridStart;    /* when this curve occurs */
+    DWORD       dwVariation;    /* variation bits */
+    MUSIC_TIME  mtDuration;     /* how long this curve lasts */
+    MUSIC_TIME  mtResetDuration;/* how long after the end of the curve to reset the curve */
+    short       nTimeOffset;    /* offset from mtGridStart */
+    short       nStartValue;    /* curve's start value */
+    short       nEndValue;      /* curve's end value */
+    short       nResetValue;    /* the value to which to reset the curve */
+    BYTE        bEventType;     /* type of curve */
+    BYTE        bCurveShape;    /* shape of curve */
+    BYTE        bCCData;        /* CC# */
+    BYTE        bFlags;         /* Bit 1=TRUE means to send nResetValue. Otherwise, don't.
+                                   Other bits are reserved. */
+    /*  Following was added for DirectX8. */
+    WORD        wParamType;      /* RPN or NRPN parameter number. */
+    WORD        wMergeIndex;     /* Allows multiple parameters to be merged (pitchbend, volume, and expression.) */
+} DMUS_IO_STYLECURVE;
+
+typedef struct _DMUS_IO_STYLEMARKER
+{
+    MUSIC_TIME  mtGridStart;    /* when this marker occurs */
+    DWORD       dwVariation;    /* variation bits */
+    WORD        wMarkerFlags;   /* how the marker is used */
+} DMUS_IO_STYLEMARKER;
+
+typedef struct _DMUS_IO_STYLERESOLUTION
+{
+    DWORD    dwVariation;       /* variation bits */
+    WORD     wMusicValue;       /* Position in scale. */
+    BYTE     bInversionID;      /* Identifies inversion group to which this note belongs */
+    BYTE     bPlayModeFlags;    /* Can override part */
+} DMUS_IO_STYLERESOLUTION;
+
+typedef struct _DMUS_IO_STYLE_ANTICIPATION
+{
+    MUSIC_TIME    mtGridStart;   /* when this anticipation occurs */
+    DWORD         dwVariation;   /* variation bits */
+    short         nTimeOffset;   /* offset from mtGridStart */
+    BYTE          bTimeRange;    /* Range to randomize start time. */
+} DMUS_IO_STYLE_ANTICIPATION;
+
+typedef struct _DMUS_IO_MOTIFSETTINGS
+{
+    DWORD       dwRepeats;      /* Number of repeats. By default, 0. */
+    MUSIC_TIME  mtPlayStart;    /* Start of playback. By default, 0. */
+    MUSIC_TIME  mtLoopStart;    /* Start of looping portion. By default, 0. */
+    MUSIC_TIME  mtLoopEnd;      /* End of loop. Must be greater than mtLoopStart. Or, 0, indicating loop full motif.  */
+    DWORD       dwResolution;   /* Default resolution. */
+} DMUS_IO_MOTIFSETTINGS;
+
+#pragma pack()
+
+
+/*
+RIFF
+(
+    'DMST'          // Style
+    <styh-ck>       // Style header chunk
+    <guid-ck>       // Every Style has a GUID
+    [<UNFO-list>]   // Name, author, copyright info., comments
+    [<vers-ck>]     // version chunk
+    <part-list>...  // Array of parts in the Style, used by patterns
+    <pttn-list>...  // Array of patterns in the Style
+    <DMBD-form>...  // Array of bands in the Style
+    [<prrf-list>]...// Optional array of chord map references in the Style
+)
+
+    // <styh-ck>
+    styh
+    (
+        <DMUS_IO_STYLE>
+    )
+
+    // <guid-ck>
+    guid
+    (
+        <GUID>
+    )
+
+    // <vers-ck>
+    vers
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    // <part-list>
+    LIST
+    (
+        'part'
+        <prth-ck>       // Part header chunk
+        [<UNFO-list>]   // Name, author, copyright info., comments
+        [<note-ck>]     // Optional chunk containing an array of notes in Part
+        [<crve-ck>]     // Optional chunk containing an array of curves in Part
+        [<mrkr-ck>]     // Optional chunk containing an array of markers in Part
+        [<rsln-ck>]     // Optional chunk containing an array of variation resolutions in Part
+        [<anpn-ck>]     // Optional chunk containing an array of resolution anticipations in Part
+    )
+
+        // <orth-ck>
+        prth
+        (
+            <DMUS_IO_STYLEPART>
+        )
+
+        // <note-ck>
+        'note'
+        (
+            // sizeof DMUS_IO_STYLENOTE:DWORD
+            <DMUS_IO_STYLENOTE>...
+        )
+
+        // <crve-ck>
+        'crve'
+        (
+            // sizeof DMUS_IO_STYLECURVE:DWORD
+            <DMUS_IO_STYLECURVE>...
+        )
+
+        // <mrkr-ck>
+        'mrkr'
+        (
+            // sizeof DMUS_IO_STYLEMARKER:DWORD
+            <DMUS_IO_STYLEMARKER>...
+        )
+
+        // <rsln-ck>
+        'rsln'
+        (
+            // sizeof DMUS_IO_STYLERESOLUTION:DWORD
+            <DMUS_IO_STYLERESOLUTION>...
+        )
+
+        // <anpn-ck>
+        'anpn'
+        (
+            // sizeof DMUS_IO_STYLE_ANTICIPATION:DWORD
+            <DMUS_IO_STYLE_ANTICIPATION>...
+        )
+
+    // <pttn-list>
+    LIST
+    (
+        'pttn'
+        <ptnh-ck>       // Pattern header chunk
+        <rhtm-ck>       // Chunk containing an array of rhythms for chord matching
+        [<UNFO-list>]   // Name, author, copyright info., comments
+        [<mtfs-ck>]     // Motif settings chunk
+        [<DMBD-form>]   // Optional band to be associated with the pattern (for motifs)
+        <pref-list>...  // Array of part reference id's
+    )
+
+        // <ptnh-ck>
+        ptnh
+        (
+            <DMUS_IO_PATTERN>
+        )
+
+        // <rhtm-ck>
+        'rhtm'
+        (
+            // DWORD's representing rhythms for chord matching based on number
+            // of measures in the pattern
+        )
+
+
+        // pref-list
+        LIST
+        (
+            'pref'
+            <prfc-ck>   // part ref chunk
+        )
+
+        // <prfc-ck>
+        prfc
+        (
+            <DMUS_IO_PARTREF>
+        )
+
+        // <mtfs-ck>
+        mtfs
+        (
+            <DMUS_IO_MOTIFSETTINGS>
+        )
+
+    // <prrf-list>
+    LIST
+    (
+        'prrf'
+        <DMRF-list>... // Array of Chordmap references
+    )
+*/
+
+/* Pattern chunk, for use in Pattern tracks */
+
+#define DMUS_FOURCC_PATTERN_FORM        mmioFOURCC('D','M','P','T')
+
+/*
+RIFF
+(
+    'DMPT'          // Pattern
+    <styh-ck>       // Style header chunk
+    <pttn-list>     // The pattern, in single pattern format (includes DMUS_FOURCC_PART_LIST chunks)
+)
+*/
+
+
+/* Chord and command file formats */
+
+/* These specify possible values for DMUS_IO_COMMAND.bRepeatMode (DirectX8) */
+typedef enum enumDMUS_PATTERNT_TYPES
+{
+    DMUS_PATTERNT_RANDOM           = 0, /* Play randomly. (DirectX7 behavior) */
+    DMUS_PATTERNT_REPEAT           = 1, /* Repeat last pattern. */
+    DMUS_PATTERNT_SEQUENTIAL       = 2, /* Play sequential starting with first matching pattern. */
+    DMUS_PATTERNT_RANDOM_START     = 3, /* Play sequential starting with a random pattern. */
+    DMUS_PATTERNT_NO_REPEAT        = 4, /* Play randomly, but don't play the same pattern twice. */
+    DMUS_PATTERNT_RANDOM_ROW       = 5  /* Play randomly as a row: don't repeat any pattern until all have played. */
+} DMUS_PATTERNT_TYPES;
+
+
+#define DMUS_FOURCC_CHORDTRACK_LIST         mmioFOURCC('c','o','r','d')
+#define DMUS_FOURCC_CHORDTRACKHEADER_CHUNK  mmioFOURCC('c','r','d','h')
+#define DMUS_FOURCC_CHORDTRACKBODY_CHUNK    mmioFOURCC('c','r','d','b')
+
+#define DMUS_FOURCC_COMMANDTRACK_CHUNK      mmioFOURCC('c','m','n','d')
+
+typedef struct _DMUS_IO_CHORD
+{
+    WCHAR       wszName[16];    /* Name of the chord */
+    MUSIC_TIME  mtTime;         /* Time of this chord */
+    WORD        wMeasure;       /* Measure this falls on */
+    BYTE        bBeat;          /* Beat this falls on */
+    BYTE        bFlags;         /* Various flags */
+} DMUS_IO_CHORD;
+
+typedef struct _DMUS_IO_SUBCHORD
+{
+    DWORD   dwChordPattern;     /* Notes in the subchord */
+    DWORD   dwScalePattern;     /* Notes in the scale */
+    DWORD   dwInversionPoints;  /* Where inversions can occur */
+    DWORD   dwLevels;           /* Which levels are supported by this subchord */
+    BYTE    bChordRoot;         /* Root of the subchord */
+    BYTE    bScaleRoot;         /* Root of the scale */
+} DMUS_IO_SUBCHORD;
+
+typedef struct _DMUS_IO_COMMAND
+{
+    MUSIC_TIME  mtTime;         /* Time of this command */
+    WORD        wMeasure;       /* Measure this falls on */
+    BYTE        bBeat;          /* Beat this falls on */
+    BYTE        bCommand;       /* Command type (see #defines below) */
+    BYTE        bGrooveLevel;   /* Groove level (0 if command is not a groove) */
+    BYTE        bGrooveRange;   /* Groove range  */
+    BYTE        bRepeatMode;    /* Used to control selection of patterns with same groove level  */
+} DMUS_IO_COMMAND;
+
+
+/*
+
+    // <cord-list>
+    LIST
+    (
+        'cord'
+        <crdh-ck>
+        <crdb-ck>...    // Chord body chunks
+    )
+
+        // <crdh-ck>
+        crdh
+        (
+            // Scale: dword (upper 8 bits for root, lower 24 for scale)
+        )
+
+        // <crdb-ck>
+        crdb
+        (
+            // sizeof DMUS_IO_CHORD:dword
+            <DMUS_IO_CHORD>
+            // # of DMUS_IO_SUBCHORDS:dword
+            // sizeof DMUS_IO_SUBCHORDS:dword
+            // a number of <DMUS_IO_SUBCHORD>
+        )
+
+
+    // <cmnd-list>
+    'cmnd'
+    (
+        //sizeof DMUS_IO_COMMAND: DWORD
+        <DMUS_IO_COMMAND>...
+    )
+
+*/
+
+/*  File io for DirectMusic Tool and ToolGraph objects
+*/
+
+/* RIFF ids: */
+
+#define DMUS_FOURCC_TOOLGRAPH_FORM  mmioFOURCC('D','M','T','G')
+#define DMUS_FOURCC_TOOL_LIST       mmioFOURCC('t','o','l','l')
+#define DMUS_FOURCC_TOOL_FORM       mmioFOURCC('D','M','T','L')
+#define DMUS_FOURCC_TOOL_CHUNK      mmioFOURCC('t','o','l','h')
+
+/* io structures: */
+
+typedef struct _DMUS_IO_TOOL_HEADER
+{
+    GUID        guidClassID;    /* Class id of tool. */
+    long        lIndex;         /* Position in graph. */
+    DWORD       cPChannels;     /* Number of items in channels array. */
+    FOURCC      ckid;           /* chunk ID of tool's data chunk if 0 fccType valid. */
+    FOURCC      fccType;        /* list type if NULL ckid valid. */
+    DWORD       dwPChannels[1]; /* Array of PChannels, size determined by cPChannels. */
+} DMUS_IO_TOOL_HEADER;
+
+/*
+RIFF
+(
+    'DMTG'          // DirectMusic ToolGraph chunk
+    [<guid-ck>]     // GUID for ToolGraph
+    [<vers-ck>]     // Optional version info
+    [<UNFO-list>]   // Name, author, copyright info., comments
+    <toll-list>     // List of Tools
+)
+
+    // <guid-ck>
+    'guid'
+    (
+        <GUID>
+    )
+
+    // <vers-ck>
+    vers
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    // <toll-list>
+    LIST
+    (
+        'toll'          // Array of tools
+        <DMTL-form>...  // Each tool is encapsulated in a RIFF chunk
+    )
+
+// <DMTL-form>      Tools are embedded in a graph. Theoretically, they can be saved as individual files too.
+RIFF
+(
+    'DMTL'
+    <tolh-ck>
+    [<data>]        // Tool data. Must be a RIFF readable chunk.
+)
+
+    // <tolh-ck>            // Tool header chunk
+    (
+        'tolh'
+        <DMUS_IO_TOOL_HEADER>   // Tool header
+    )
+*/
+
+/*  The AudioPath file carries everything for describing a specific audio path,
+    including Tool Graph and Buffer Descriptor.
+    This can even be used for configuring a complete performance.
+*/
+
+#define DMUS_FOURCC_AUDIOPATH_FORM  mmioFOURCC('D','M','A','P')
+
+/*
+RIFF
+(
+    'DMAP'          // DirectMusic AudioPath chunk
+    [<guid-ck>]     // GUID for this Audio Path configuration
+    [<vers-ck>]     // Optional version info
+    [<UNFO-list>]   // Name, author, copyright info., comments
+    [<DMTG-form>]   // Optional ToolGraph
+    [<pcsl-list>]   // Optional list of port configurations
+    [<dbfl-list>]...// Optional array of DirectSound buffer descriptors
+)
+*/
+
+#define DMUS_FOURCC_PORTCONFIGS_LIST    mmioFOURCC('p','c','s','l')
+#define DMUS_FOURCC_PORTCONFIG_LIST     mmioFOURCC('p','c','f','l')
+#define DMUS_FOURCC_PORTCONFIG_ITEM     mmioFOURCC('p','c','f','h')
+#define DMUS_FOURCC_PORTPARAMS_ITEM     mmioFOURCC('p','p','r','h')
+#define DMUS_FOURCC_DSBUFFER_LIST       mmioFOURCC('d','b','f','l')
+#define DMUS_FOURCC_DSBUFFATTR_ITEM     mmioFOURCC('d','d','a','h')
+#define DMUS_FOURCC_PCHANNELS_LIST      mmioFOURCC('p','c','h','l')
+#define DMUS_FOURCC_PCHANNELS_ITEM      mmioFOURCC('p','c','h','h')
+
+typedef struct _DMUS_IO_PORTCONFIG_HEADER
+{
+    GUID    guidPort;           /* GUID of requested port. */
+    DWORD   dwPChannelBase;     /* PChannel that this should start on. */
+    DWORD   dwPChannelCount;    /* How many channels. */
+    DWORD   dwFlags;            /* Various flags. */
+} DMUS_IO_PORTCONFIG_HEADER;
+
+#define DMUS_PORTCONFIGF_DRUMSON10  1   /* This port configured for drums on channel 10. */
+#define DMUS_PORTCONFIGF_USEDEFAULT 2   /* Use the default port. */
+
+/* Each portconfig has one or more pchannel to buffer mappings. Each buffer
+   is identified by a guid. Each pchannel can map to one or more buffers.
+   This is defined with one or more DMUS_IO_PCHANNELTOBUFFER_HEADER
+   structures. Each defines a range of PChannels and the set of buffers
+   that they connect to.
+*/
+
+typedef struct _DMUS_IO_PCHANNELTOBUFFER_HEADER
+{
+    DWORD   dwPChannelBase;     /* PChannel that this should start on. */
+    DWORD   dwPChannelCount;    /* How many PChannels. */
+    DWORD   dwBufferCount;      /* How many buffers do these connect to. */
+    DWORD   dwFlags;            /* Various flags. Currently reserved for future use. Must be 0. */
+} DMUS_IO_PCHANNELTOBUFFER_HEADER;
+
+/* Each buffer is represented by an DSBC form. This is wrapped by the
+   DMUS_IO_BUFFER_ATTRIBUTES_HEADER which identifies how to use the
+   buffer. In particular, it indicates whether this gets dynamically duplicated
+   or all references to this should share the same instance.
+   To resolve references, the unique GUID of the buffer is also stored
+   in this structure.
+*/
+
+typedef struct _DMUS_IO_BUFFER_ATTRIBUTES_HEADER
+{
+    GUID    guidBufferID;       /* Each buffer config has a unique ID. */
+    DWORD   dwFlags;            /* Various flags. */
+} DMUS_IO_BUFFER_ATTRIBUTES_HEADER;
+
+/* DMUS_IO_BUFFER_ATTRIBUTES_HEADER.dwFlags: */
+#define DMUS_BUFFERF_SHARED     1   /* Share this with other audio paths, instead of creating unique copies. */
+#define DMUS_BUFFERF_DEFINED    2   /* Use one of the standard predefined buffers (see GUID_Buffer... in dmusici.h.) */
+#define DMUS_BUFFERF_MIXIN      8   /* This is a mixin buffer. */
+
+/*
+
+LIST
+(
+    'pcsl'          // Array of port configurations
+    <pcfl-list>...  // One or more port configurations, each in a list chunk
+)
+
+LIST
+(
+    'pcfl'          // List container for one port configuration.
+    <pcfh-ck>       // Portconfig header chunk.
+    <pprh-ck>       // Port params, to be used to create the port.
+    [<dbfl-list>]...// Optional array of DirectSound buffer descriptors
+    [<pchl-list>]   // Optional list of pchannel to buffer assignments
+
+)
+
+    // <pcfh-ck>            // Port config header chunk
+    (
+        'pcfh'
+        <DMUS_IO_PORTCONFIG_HEADER>   // Port config header
+    )
+
+    // <pprh-ck>            // Port params header chunk
+    (
+        'pprh'
+        <DMUS_PORTPARAMS8>   // Port params header
+    )
+
+LIST
+(
+    'pchl'          // List container for one or more pchannel to buffer assignments.
+    <pchh-ck>...    // One or more pchannel to buffer assignment headers and data.
+
+    // <pchh-ck>
+    (
+        'pchh'
+        <DMUS_IO_PCHANNELTOBUFFER_HEADER>   // Description of PChannels
+        <GUID>...                           // Array of GUIDs defining the buffers they all connect to.
+    )
+)
+
+LIST
+(
+    'dbfl'          // List container for one buffer and buffer attributes header.
+    <ddah-ck>       // Buffer attributes header.
+    [<DSBC-form>]   // Buffer configuration. Not required when header uses a predefined buffer type.
+
+    // <ddah-ck>
+    (
+        'ddah'
+        <DMUS_IO_BUFFER_ATTRIBUTES_HEADER>   // Buffer attributes.
+    )
+)
+*/
+
+/*  File io for DirectMusic Band Track object */
+
+
+/* RIFF ids: */
+#define DMUS_FOURCC_BANDTRACK_FORM  mmioFOURCC('D','M','B','T')
+#define DMUS_FOURCC_BANDTRACK_CHUNK mmioFOURCC('b','d','t','h')
+#define DMUS_FOURCC_BANDS_LIST      mmioFOURCC('l','b','d','l')
+#define DMUS_FOURCC_BAND_LIST       mmioFOURCC('l','b','n','d')
+#define DMUS_FOURCC_BANDITEM_CHUNK  mmioFOURCC('b','d','i','h')
+#define DMUS_FOURCC_BANDITEM_CHUNK2 mmioFOURCC('b','d','2','h')
+
+/* io structures */
+typedef struct _DMUS_IO_BAND_TRACK_HEADER
+{
+    BOOL bAutoDownload;     /* Determines if Auto-Download is enabled. */
+} DMUS_IO_BAND_TRACK_HEADER;
+
+typedef struct _DMUS_IO_BAND_ITEM_HEADER
+{
+    MUSIC_TIME lBandTime;   /* Position in track list. */
+} DMUS_IO_BAND_ITEM_HEADER;
+
+typedef struct _DMUS_IO_BAND_ITEM_HEADER2
+{
+    MUSIC_TIME lBandTimeLogical;   /* Position in track list. Time in the music with which band change is associated. */
+    MUSIC_TIME lBandTimePhysical;  /* Precise time band change will take effect. Should be close to logical time. */
+} DMUS_IO_BAND_ITEM_HEADER2;
+
+/*
+RIFF
+(
+    'DMBT'          // DirectMusic Band Track form-type
+    [<bdth-ck>]     // Band track header
+    [<guid-ck>]     // GUID for band track
+    [<vers-ck>]     // Optional version info
+    [<UNFO-list>]   // Name, author, copyright info., comments
+    <lbdl-list>     // List of Band items
+)
+
+    // <bnth-ck>
+    'bdth'
+    (
+        <DMUS_IO_BAND_TRACK_HEADER>
+    )
+
+    // <guid-ck>
+    'guid'
+    (
+        <GUID>
+    )
+
+    // <vers-ck>
+    vers
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    // <lbdl-list>
+    LIST
+    (
+        'lbdl'
+        <lbnd-list>...  // Array of bands, each encapsulated in a list chunk
+    )
+
+        // <lbnd-list>
+        LIST
+        (
+            'lbnd'
+            <bdih-ck> or <bd2h-ck>  // bdih is a legacy format.  bd2h is preferred for new content.
+            <DMBD-form> // Band
+        )
+
+            // <bdih-ck> or <bd2h-ck>       // band item header
+            (
+                <DMUS_IO_BAND_ITEM_HEADER> or <DMUS_IO_BAND_ITEM_HEADER2> // Band item header
+            )
+*/
+
+
+/*  File io for DirectMusic Band object
+*/
+
+/* RIFF ids: */
+
+#define DMUS_FOURCC_BAND_FORM           mmioFOURCC('D','M','B','D')
+#define DMUS_FOURCC_INSTRUMENTS_LIST    mmioFOURCC('l','b','i','l')
+#define DMUS_FOURCC_INSTRUMENT_LIST     mmioFOURCC('l','b','i','n')
+#define DMUS_FOURCC_INSTRUMENT_CHUNK    mmioFOURCC('b','i','n','s')
+
+/* Flags for DMUS_IO_INSTRUMENT
+ */
+#define DMUS_IO_INST_PATCH          (1 << 0)        /* dwPatch is valid. */
+#define DMUS_IO_INST_BANKSELECT     (1 << 1)        /* dwPatch contains a valid Bank Select MSB and LSB part */
+#define DMUS_IO_INST_ASSIGN_PATCH   (1 << 3)        /* dwAssignPatch is valid */
+#define DMUS_IO_INST_NOTERANGES     (1 << 4)        /* dwNoteRanges is valid */
+#define DMUS_IO_INST_PAN            (1 << 5)        /* bPan is valid */
+#define DMUS_IO_INST_VOLUME         (1 << 6 )       /* bVolume is valid */
+#define DMUS_IO_INST_TRANSPOSE      (1 << 7)        /* nTranspose is valid */
+#define DMUS_IO_INST_GM             (1 << 8)        /* Instrument is from GM collection */
+#define DMUS_IO_INST_GS             (1 << 9)        /* Instrument is from GS collection */
+#define DMUS_IO_INST_XG             (1 << 10)       /* Instrument is from XG collection */
+#define DMUS_IO_INST_CHANNEL_PRIORITY (1 << 11)     /* dwChannelPriority is valid */
+#define DMUS_IO_INST_USE_DEFAULT_GM_SET (1 << 12)   /* Always use the default GM set for this patch,  */
+                                                    /* don't rely on the synth caps stating GM or GS in hardware. */
+#define DMUS_IO_INST_PITCHBENDRANGE (1 << 13)     /* nPitchBendRange is valid */
+
+/* io structures */
+typedef struct _DMUS_IO_INSTRUMENT
+{
+    DWORD   dwPatch;            /* MSB, LSB and Program change to define instrument */
+    DWORD   dwAssignPatch;      /* MSB, LSB and Program change to assign to instrument when downloading */
+    DWORD   dwNoteRanges[4];    /* 128 bits; one for each MIDI note instrument needs to able to play */
+    DWORD   dwPChannel;         /* PChannel instrument plays on */
+    DWORD   dwFlags;            /* DMUS_IO_INST_ flags */
+    BYTE    bPan;               /* Pan for instrument */
+    BYTE    bVolume;            /* Volume for instrument */
+    short   nTranspose;         /* Number of semitones to transpose notes */
+    DWORD   dwChannelPriority;  /* Channel priority */
+    short   nPitchBendRange;    /* Number of semitones shifted by pitch bend */
+} DMUS_IO_INSTRUMENT;
+
+/*
+// <DMBD-form> bands can be embedded in other forms
+RIFF
+(
+    'DMBD'          // DirectMusic Band chunk
+    [<guid-ck>]     // GUID for band
+    [<vers-ck>]     // Optional version info
+    [<UNFO-list>]   // Name, author, copyright info., comments
+    <lbil-list>     // List of Instruments
+)
+
+    // <guid-ck>
+    'guid'
+    (
+        <GUID>
+    )
+
+    // <vers-ck>
+    vers
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    // <lbil-list>
+    LIST
+    (
+        'lbil'          // Array of instruments
+        <lbin-list>...  // Each instrument is encapsulated in a list
+    )
+
+        // <lbin-list>
+        LIST
+        (
+            'lbin'
+            <bins-ck>
+            [<DMRF-list>]       // Optional reference to DLS Collection file.
+        )
+
+            // <bins-ck>            // Instrument chunk
+            (
+                'bins'
+                <DMUS_IO_INSTRUMENT>    // Instrument header
+            )
+*/
+
+/* This RIFF id and io struct have been added to allow wave files (and the wave object) to
+   differentiate between streaming and one-shot waves, and to give a prefetch for streaming
+   waves  */
+
+#define DMUS_FOURCC_WAVEHEADER_CHUNK   mmioFOURCC('w','a','v','h')
+
+typedef struct _DMUS_IO_WAVE_HEADER
+{
+    REFERENCE_TIME  rtReadAhead;    /* How far ahead in the stream wave data will be read (in REFERENCE_TIME).  Ignored for one-shot waves.  */
+    DWORD           dwFlags;        /* Various flags, including whether this is a streaming wave and whether it can be invalidated. */
+} DMUS_IO_WAVE_HEADER;
+
+
+/*  File io for Wave track */
+
+/* RIFF ids: */
+
+#define DMUS_FOURCC_WAVETRACK_LIST      mmioFOURCC('w','a','v','t')
+#define DMUS_FOURCC_WAVETRACK_CHUNK     mmioFOURCC('w','a','t','h')
+#define DMUS_FOURCC_WAVEPART_LIST       mmioFOURCC('w','a','v','p')
+#define DMUS_FOURCC_WAVEPART_CHUNK      mmioFOURCC('w','a','p','h')
+#define DMUS_FOURCC_WAVEITEM_LIST       mmioFOURCC('w','a','v','i')
+#define DMUS_FOURCC_WAVE_LIST           mmioFOURCC('w','a','v','e')
+#define DMUS_FOURCC_WAVEITEM_CHUNK      mmioFOURCC('w','a','i','h')
+
+/* This flag is included in DMUS_IO_WAVE_TRACK_HEADER.dwFlags.  If set, the track will get its
+   variations from a pattern track, via GetParam(GUID_Variations). */
+#define DMUS_WAVETRACKF_SYNC_VAR   0x1
+/* This is also included in DMUS_IO_WAVE_TRACK_HEADER.dwFlags.  If set, variation control
+   information will persist from one playback instance to the next.*/
+#define DMUS_WAVETRACKF_PERSIST_CONTROL 0x2
+
+typedef struct _DMUS_IO_WAVE_TRACK_HEADER
+{
+    long        lVolume;        /* Gain, in 1/100th of dB, to be applied to all waves.  Note:  All gain values should be negative. */
+    DWORD       dwFlags;        /* Flags, including whether this track syncs to a pattern track for its variations. */
+} DMUS_IO_WAVE_TRACK_HEADER;
+
+typedef struct _DMUS_IO_WAVE_PART_HEADER
+{
+    long            lVolume;        /* Gain, in 1/100th of dB, to be applied to all waves in wave part.  Note:  All gain values should be negative. */
+    DWORD           dwVariations;   /* Variation mask for which of 32 variations */
+    DWORD           dwPChannel;     /* PChannel */
+    DWORD           dwLockToPart;   /* Part ID to lock to. */
+    DWORD           dwFlags;        /* Flags, including stuff for managing how variations are chosen (in low-order nibble) */
+    DWORD           dwIndex;        /* Index for distinguishing multiple parts on the same PChannel*/
+} DMUS_IO_WAVE_PART_HEADER;
+
+typedef struct _DMUS_IO_WAVE_ITEM_HEADER
+{
+    long            lVolume;        /* Gain, in 1/100th of dB.  Note:  All gain values should be negative. */
+    long            lPitch;         /* Pitch offset in 1/100th of a semitone. */
+    DWORD           dwVariations;   /* Variation flags for which of 32 variations this wave belongs to. */
+    REFERENCE_TIME  rtTime;         /* Start time, in REFERENCE_TIME, if Timer time track, or MUSIC_TIME for music time track. */
+    REFERENCE_TIME  rtStartOffset;  /* Distance into wave to start playback, in reference time units. */
+    REFERENCE_TIME  rtReserved;     /* Reserved field. */
+    REFERENCE_TIME  rtDuration;     /* Duration, in REFERENCE_TIME or MUSIC_TIME, depending on track timing format. */
+    MUSIC_TIME      mtLogicalTime;  /* If in music track format, this indicates the musical boundary where this belongs. Otherwise, ignored. */
+    DWORD           dwLoopStart;    /* Start point for a looping wave. */
+    DWORD           dwLoopEnd;      /* End point for a looping wave. */
+    DWORD           dwFlags;        /* Various flags, including whether this is a streaming wave and whether it can be invalidated. */
+    WORD            wVolumeRange;   /* Random range for volume. */
+    WORD            wPitchRange;    /* Random range for pitch. */
+} DMUS_IO_WAVE_ITEM_HEADER;
+
+/*
+LIST
+{
+    'wavt'          // Wave track chunk
+    <wath-ck>       // Wave track header
+    <wavp-list>...  // Array of Wave Parts
+}
+    // <wath-ck>
+    'wath'
+    {
+        <DMUS_IO_WAVE_TRACK_HEADER>
+    }
+
+    //  <wavp-list>
+    LIST
+    {
+        'wavp'
+        <waph-ck>       //  Wave Part Header
+        <wavi-list>     //  List of wave items
+    }
+
+        //  <waph-ck>
+        'waph'
+        {
+            <DMUS_IO_WAVE_PART_HEADER>
+        }
+
+        //  <wavi-list>
+        LIST
+        {
+            'wavi'
+            <wave-list>...  //  Array of waves; each wave is encapsulated in a list
+        }
+
+            //  <wave-list>
+            LIST
+            {
+                'wave'
+                <waih-ck>       //  Wave item header
+                <DMRF-list>     //  Reference to wave object
+            }
+
+                //  <waih-ck>
+                'waih'
+                {
+                    <DMUS_IO_WAVE_ITEM_HEADER>
+                }
+
+*/
+
+/*  File io for DirectMusic Container file. This embeds a set of related files. And,
+    in turn, it can be embedded within a segment or script file.
+*/
+
+#define DMUS_FOURCC_CONTAINER_FORM          mmioFOURCC('D','M','C','N')
+#define DMUS_FOURCC_CONTAINER_CHUNK         mmioFOURCC('c','o','n','h')
+#define DMUS_FOURCC_CONTAINED_ALIAS_CHUNK   mmioFOURCC('c','o','b','a')
+#define DMUS_FOURCC_CONTAINED_OBJECT_CHUNK  mmioFOURCC('c','o','b','h')
+#define DMUS_FOURCC_CONTAINED_OBJECTS_LIST  mmioFOURCC('c','o','s','l')
+#define DMUS_FOURCC_CONTAINED_OBJECT_LIST   mmioFOURCC('c','o','b','l')
+
+typedef struct _DMUS_IO_CONTAINER_HEADER
+{
+    DWORD       dwFlags;        /* Flags. */
+} DMUS_IO_CONTAINER_HEADER;
+
+#define DMUS_CONTAINER_NOLOADS  (1 << 1)   /* Contained items are not loaded when the container is loaded.
+                                              Entries will be created in the loader (via SetObject) but
+                                              the actual objects will not be created until they are
+                                              specifically loaded at a later time. */
+
+typedef struct _DMUS_IO_CONTAINED_OBJECT_HEADER
+{
+    GUID        guidClassID;    /* Class id of object. */
+    DWORD       dwFlags;        /* Flags, for example DMUS_CONTAINED_OBJF_KEEP. */
+    FOURCC      ckid;           /* chunk ID of track's data chunk if 0 fccType valid. */
+    FOURCC      fccType;        /* list type if NULL ckid valid */
+        /* Note that LIST:DMRF may be used for ckid and fccType in order to reference an
+           object instead of embedding it within the container. */
+} DMUS_IO_CONTAINED_OBJECT_HEADER;
+
+#define DMUS_CONTAINED_OBJF_KEEP    1   /* Keep the object cached in the loader after the container is released. */
+
+/*
+RIFF
+(
+    'DMCN'          // DirectMusic Container chunk
+    <conh-ck>       // Container header chunk
+    [<guid-ck>]     // GUID for container
+    [<vers-ck>]     // Optional version info
+    [<UNFO-list>]   // Name, author, copyright info., comments
+    <cosl-list>     // List of objects.
+)
+
+    // <conh-ck>
+    'conh'
+    (
+        <DMUS_IO_CONTAINER_HEADER>
+    )
+
+    // <guid-ck>
+    'guid'
+    (
+        <GUID>
+    )
+
+    // <vers-ck>
+    vers
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    LIST
+    (
+        'cosl'          // Array of embedded objects.
+        <cobl-list>...  // Each object is encapsulated in a LIST chunk
+    )
+
+    // <cobl-list>      // Encapsulates one object
+    LIST
+    (
+        'cobl'
+        [<coba-ck>]         // Alias.  An alternative name by which this object is known
+                            // within the container.
+        <cobh-ck>           // Required header, includes CLASS ID for object.
+        [<data>] or <DMRF>  // Object data of the type specified in <cobh-ck>.
+                            // If DMRF, it is a reference of where to find the object.
+                            // Otherwise, it could be any RIFF readable chunk in the
+                            //    exact same format as a file.  The object will load
+                            //    itself from this data.
+    )
+
+    // <coba-ck>
+    'coba'
+    (
+        // Alias, stored as NULL terminated string of WCHARs
+    )
+
+    // <cobh-ck>
+    'cobh'
+    (
+        <DMUS_IO_CONTAINED_OBJECT_HEADER>
+    )
+*/
+
+/*  File io for DirectMusic Segment object */
+
+/* RIFF ids: */
+
+#define DMUS_FOURCC_SEGMENT_FORM        mmioFOURCC('D','M','S','G')
+#define DMUS_FOURCC_SEGMENT_CHUNK       mmioFOURCC('s','e','g','h')
+#define DMUS_FOURCC_TRACK_LIST          mmioFOURCC('t','r','k','l')
+#define DMUS_FOURCC_TRACK_FORM          mmioFOURCC('D','M','T','K')
+#define DMUS_FOURCC_TRACK_CHUNK         mmioFOURCC('t','r','k','h')
+#define DMUS_FOURCC_TRACK_EXTRAS_CHUNK  mmioFOURCC('t','r','k','x')
+
+/* io structures:*/
+
+typedef struct _DMUS_IO_SEGMENT_HEADER
+{
+    DWORD       dwRepeats;      /* Number of repeats. By default, 0. */
+    MUSIC_TIME  mtLength;       /* Length, in music time. */
+    MUSIC_TIME  mtPlayStart;    /* Start of playback. By default, 0. */
+    MUSIC_TIME  mtLoopStart;    /* Start of looping portion. By default, 0. */
+    MUSIC_TIME  mtLoopEnd;      /* End of loop. Must be greater than dwPlayStart. Or, 0, indicating loop full segment. */
+    DWORD       dwResolution;   /* Default resolution. */
+    /* Following added for DirectX8: */
+    REFERENCE_TIME rtLength;    /* Length, in reference time (overrides music time length.) */
+    DWORD       dwFlags;
+    DWORD       dwReserved;     /* Reserved. */
+    /* Added for DirectX9: */
+    REFERENCE_TIME rtLoopStart; /* Timer time loop start. */
+    REFERENCE_TIME rtLoopEnd;   /* Timer time loop end. */
+    REFERENCE_TIME rtPlayStart; /* Start of playback in Timer time. */
+} DMUS_IO_SEGMENT_HEADER;
+
+#define DMUS_SEGIOF_REFLENGTH   1  /* Use the time in rtLength for the segment length. */
+#define DMUS_SEGIOF_CLOCKTIME   2  /* This is a Timer time segment. */
+
+typedef struct _DMUS_IO_TRACK_HEADER
+{
+    GUID        guidClassID;    /* Class id of track. */
+    DWORD       dwPosition;     /* Position in track list. */
+    DWORD       dwGroup;        /* Group bits for track. */
+    FOURCC      ckid;           /* chunk ID of track's data chunk. */
+    FOURCC      fccType;        /* list type if ckid is RIFF or LIST */
+} DMUS_IO_TRACK_HEADER;
+
+/*  Additional parameters for the track header chunk, introduced in DirectX8 and
+    on, are stored in a separate chunk. */
+
+typedef struct _DMUS_IO_TRACK_EXTRAS_HEADER
+{
+    DWORD       dwFlags;        /* DirectX8 Added flags for control tracks. */
+    DWORD       dwPriority;     /* Priority for composition. */
+} DMUS_IO_TRACK_EXTRAS_HEADER;
+
+/*
+RIFF
+(
+    'DMSG'          // DirectMusic Segment chunk
+    <segh-ck>       // Segment header chunk
+    [<guid-ck>]     // GUID for segment
+    [<vers-ck>]     // Optional version info
+    [<UNFO-list>]   // Name, author, copyright info., comments
+    [<DMCN-form>]   // Optional container of objects embedded in file. Must precede tracklist.
+    <trkl-list>     // List of Tracks
+    [<DMTG-form>]   // Optional ToolGraph
+    [<DMAP-form>]   // Optional Audio Path
+)
+
+    // <segh-ck>
+    'segh'
+    (
+        <DMUS_IO_SEGMENT_HEADER>
+    )
+
+    // <guid-ck>
+    'guid'
+    (
+        <GUID>
+    )
+
+    // <vers-ck>
+    vers
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    // <trkl-list>
+    LIST
+    (
+        'trkl'          // Array of tracks
+        <DMTK-form>...  // Each track is encapsulated in a RIFF chunk
+    )
+
+    // <DMTK-form>      // Tracks can be embedded in a segment or stored as separate files.
+    RIFF
+    (
+        'DMTK'
+        <trkh-ck>
+        [<trkx-ck>]     // Optional track flags.
+        [<guid-ck>]     // Optional GUID for track object instance (not to be confused with Class id in track header)
+        [<vers-ck>]     // Optional version info
+        [<UNFO-list>]   // Optional name, author, copyright info., comments
+        [<data>]        // Track data. Must be a RIFF readable chunk.
+    )
+
+    // <trkh-ck>            // Track header chunk
+    (
+        'trkh'
+        <DMUS_IO_TRACK_HEADER>  // Track header
+    )
+
+    // <trkx-ck>            // Track flags chunk
+    (
+        'trkx'
+        <DMUS_IO_TRACK_EXTRAS_HEADER>  // DirectX8 Track flags header
+    )
+*/
+
+/*  File io for DirectMusic reference chunk.
+    This is used to embed a reference to an object.
+*/
+
+/*  RIFF ids: */
+
+#define DMUS_FOURCC_REF_LIST        mmioFOURCC('D','M','R','F')
+#define DMUS_FOURCC_REF_CHUNK       mmioFOURCC('r','e','f','h')
+#define DMUS_FOURCC_DATE_CHUNK      mmioFOURCC('d','a','t','e')
+#define DMUS_FOURCC_NAME_CHUNK      mmioFOURCC('n','a','m','e')
+#define DMUS_FOURCC_FILE_CHUNK      mmioFOURCC('f','i','l','e')
+
+typedef struct _DMUS_IO_REFERENCE
+{
+    GUID    guidClassID;    /* Class id is always required. */
+    DWORD   dwValidData;    /* Flags. */
+} DMUS_IO_REFERENCE;
+
+/*
+LIST
+(
+    'DMRF'          // DirectMusic Reference chunk
+    <refh-ck>       // Reference header chunk
+    [<guid-ck>]     // Optional object GUID.
+    [<date-ck>]     // Optional file date.
+    [<name-ck>]     // Optional name.
+    [<file-ck>]     // Optional file name.
+    [<catg-ck>]     // Optional category name.
+    [<vers-ck>]     // Optional version info.
+)
+
+    // <refh-ck>
+    'refh'
+    (
+        <DMUS_IO_REFERENCE>
+    )
+
+    // <guid-ck>
+    'guid'
+    (
+        <GUID>
+    )
+
+    // <date-ck>
+    date
+    (
+        <FILETIME>
+    )
+
+    // <name-ck>
+    name
+    (
+        // Name, stored as NULL terminated string of WCHARs
+    )
+
+    // <file-ck>
+    file
+    (
+        // File name, stored as NULL terminated string of WCHARs
+    )
+
+    // <catg-ck>
+    catg
+    (
+        // Category name, stored as NULL terminated string of WCHARs
+    )
+
+    // <vers-ck>
+    vers
+    (
+        <DMUS_IO_VERSION>
+    )
+*/
+
+/* Chord Maps */
+
+/* runtime chunks */
+#define DMUS_FOURCC_CHORDMAP_FORM       mmioFOURCC('D','M','P','R')
+#define DMUS_FOURCC_IOCHORDMAP_CHUNK    mmioFOURCC('p','e','r','h')
+#define DMUS_FOURCC_SUBCHORD_CHUNK      mmioFOURCC('c','h','d','t')
+#define DMUS_FOURCC_CHORDENTRY_CHUNK    mmioFOURCC('c','h','e','h')
+#define DMUS_FOURCC_SUBCHORDID_CHUNK    mmioFOURCC('s','b','c','n')
+#define DMUS_FOURCC_IONEXTCHORD_CHUNK   mmioFOURCC('n','c','r','d')
+#define DMUS_FOURCC_NEXTCHORDSEQ_CHUNK  mmioFOURCC('n','c','s','q')
+#define DMUS_FOURCC_IOSIGNPOST_CHUNK    mmioFOURCC('s','p','s','h')
+#define DMUS_FOURCC_CHORDNAME_CHUNK     mmioFOURCC('I','N','A','M')
+
+/* runtime list chunks */
+#define DMUS_FOURCC_CHORDENTRY_LIST     mmioFOURCC('c','h','o','e')
+#define DMUS_FOURCC_CHORDMAP_LIST       mmioFOURCC('c','m','a','p')
+#define DMUS_FOURCC_CHORD_LIST          mmioFOURCC('c','h','r','d')
+#define DMUS_FOURCC_CHORDPALETTE_LIST   mmioFOURCC('c','h','p','l')
+#define DMUS_FOURCC_CADENCE_LIST        mmioFOURCC('c','a','d','e')
+#define DMUS_FOURCC_SIGNPOSTITEM_LIST   mmioFOURCC('s','p','s','t')
+
+#define DMUS_FOURCC_SIGNPOST_LIST       mmioFOURCC('s','p','s','q')
+
+/* values for dwChord field of DMUS_IO_PERS_SIGNPOST */
+/* DMUS_SIGNPOSTF_ flags are also used in templates (DMUS_IO_SIGNPOST) */
+#define DMUS_SIGNPOSTF_A        1
+#define DMUS_SIGNPOSTF_B        2
+#define DMUS_SIGNPOSTF_C        4
+#define DMUS_SIGNPOSTF_D        8
+#define DMUS_SIGNPOSTF_E        0x10
+#define DMUS_SIGNPOSTF_F        0x20
+#define DMUS_SIGNPOSTF_LETTER   (DMUS_SIGNPOSTF_A | DMUS_SIGNPOSTF_B | DMUS_SIGNPOSTF_C | DMUS_SIGNPOSTF_D | DMUS_SIGNPOSTF_E | DMUS_SIGNPOSTF_F)
+#define DMUS_SIGNPOSTF_1        0x100
+#define DMUS_SIGNPOSTF_2        0x200
+#define DMUS_SIGNPOSTF_3        0x400
+#define DMUS_SIGNPOSTF_4        0x800
+#define DMUS_SIGNPOSTF_5        0x1000
+#define DMUS_SIGNPOSTF_6        0x2000
+#define DMUS_SIGNPOSTF_7        0x4000
+#define DMUS_SIGNPOSTF_ROOT     (DMUS_SIGNPOSTF_1 | DMUS_SIGNPOSTF_2 | DMUS_SIGNPOSTF_3 | DMUS_SIGNPOSTF_4 | DMUS_SIGNPOSTF_5 | DMUS_SIGNPOSTF_6 | DMUS_SIGNPOSTF_7)
+#define DMUS_SIGNPOSTF_CADENCE  0x8000
+
+/* values for dwFlags field of DMUS_IO_CHORDMAP */
+#define DMUS_CHORDMAPF_VERSION8  1   /* Chordmap is version 8 or above. */
+
+/* values for dwChord field of DMUS_IO_PERS_SIGNPOST */
+#define DMUS_SPOSTCADENCEF_1  2   /* Use the first cadence chord. */
+#define DMUS_SPOSTCADENCEF_2  4   /* Use the second cadence chord. */
+
+/* run time data structs */
+typedef struct _DMUS_IO_CHORDMAP
+{
+    WCHAR   wszLoadName[20];
+    DWORD   dwScalePattern;
+    DWORD   dwFlags;           /* Various flags. Only lower 16 bits are significant. */
+} DMUS_IO_CHORDMAP;
+
+typedef struct _DMUS_IO_CHORDMAP_SUBCHORD
+{
+    DWORD   dwChordPattern;
+    DWORD   dwScalePattern;
+    DWORD   dwInvertPattern;
+    BYTE    bChordRoot;
+    BYTE    bScaleRoot;
+    WORD    wCFlags;
+    DWORD   dwLevels;   /* parts or which subchord levels this chord supports */
+} DMUS_IO_CHORDMAP_SUBCHORD;
+
+/* Legacy name... */
+typedef DMUS_IO_CHORDMAP_SUBCHORD DMUS_IO_PERS_SUBCHORD;
+
+typedef struct _DMUS_IO_CHORDENTRY
+{
+    DWORD   dwFlags;
+    WORD    wConnectionID;  /* replaces runtime "pointer to this" */
+} DMUS_IO_CHORDENTRY;
+
+typedef struct _DMUS_IO_NEXTCHORD
+{
+    DWORD   dwFlags;
+    WORD    nWeight;
+    WORD    wMinBeats;
+    WORD    wMaxBeats;
+    WORD    wConnectionID;  /* points to an ioChordEntry */
+} DMUS_IO_NEXTCHORD;
+
+typedef struct _DMUS_IO_CHORDMAP_SIGNPOST
+{
+    DWORD   dwChords;   /* 1bit per group */
+    DWORD   dwFlags;
+} DMUS_IO_CHORDMAP_SIGNPOST;
+
+/* Legacy name... */
+typedef DMUS_IO_CHORDMAP_SIGNPOST DMUS_IO_PERS_SIGNPOST;
+
+/*
+RIFF
+(
+    'DMPR'
+    <perh-ck>           // Chord map header chunk
+    [<guid-ck>]         // guid chunk
+    [<vers-ck>]         // version chunk (two DWORDS)
+    [<UNFO-list>]       // Unfo chunk
+    <chdt-ck>           // subchord database
+    <chpl-list>         // chord palette
+    <cmap-list>         // chord map
+    <spsq-list>         // signpost list
+ )
+
+<cmap-list> ::= LIST('cmap' <choe-list> )
+
+<choe-list> ::= LIST('choe'
+                                <cheh-ck>   // chord entry data
+                                <chrd-list> // chord definition
+                                <ncsq-ck>   // connecting(next) chords
+                     )
+
+<chrd-list> ::= LIST('chrd'
+                                <INAM-ck>   // name of chord in wide char format
+                                <sbcn-ck>   // list of subchords composing chord
+                    )
+
+<chpl-list> ::= LIST('chpl'
+                                <chrd-list> ... // chord definition
+                    )
+
+<spsq-list> ::== LIST('spsq' <spst-list> ... )
+
+<spst-list> ::= LIST('spst'
+                             <spsh-ck>
+                             <chrd-list>
+                             [<cade-list>]
+                    )
+
+<cade-list> ::= LIST('cade' <chrd-list> ...)
+
+<perh-ck> ::= perh(<DMUS_IO_CHORDMAP>)
+
+<chdt-ck> ::= chdt(<cbChordSize::WORD>
+                   <DMUS_IO_PERS_SUBCHORD> ... )
+
+<cheh-ck> ::= cheh(<DMUS_IO_CHORDENTRY>)
+
+<sbcn-ck> ::= sbcn(<cSubChordID:WORD> ...)
+
+<ncsq-ck> ::= ncsq(<wNextChordSize:WORD>
+                   <DMUS_IO_NEXTCHORD>...)
+
+<spsh-ck> ::= spsh(<DMUS_IO_PERS_SIGNPOST>)
+
+*/
+
+/*  File io for DirectMusic Script object */
+
+/* RIFF ids: */
+
+#define DMUS_FOURCC_SCRIPT_FORM             mmioFOURCC('D','M','S','C')
+#define DMUS_FOURCC_SCRIPT_CHUNK            mmioFOURCC('s','c','h','d')
+#define DMUS_FOURCC_SCRIPTVERSION_CHUNK     mmioFOURCC('s','c','v','e')
+#define DMUS_FOURCC_SCRIPTLANGUAGE_CHUNK    mmioFOURCC('s','c','l','a')
+#define DMUS_FOURCC_SCRIPTSOURCE_CHUNK      mmioFOURCC('s','c','s','r')
+
+/* io structures:*/
+
+typedef struct _DMUS_IO_SCRIPT_HEADER
+{
+    DWORD       dwFlags; /* DMUS_SCRIPTIOF_ flags */
+} DMUS_IO_SCRIPT_HEADER;
+
+#define DMUS_SCRIPTIOF_LOAD_ALL_CONTENT       (1 << 0)
+    /* If set, when the script loads it will also load all the content in its container. */
+#define DMUS_SCRIPTIOF_DOWNLOAD_ALL_SEGMENTS  (1 << 1)
+    /* If set and LOAD_ALL_CONTENT is also set, when the script initializes it will also download all the segments in its container.
+       If set and LOAD_ALL_CONTENT is not set, when the script calls segment.Load on a segment then the segment will also be downloaded.
+       If not set, the script must manually download and unload by calling segment.DownloadSoundData and segment.UnloadSoundData. */
+
+/*
+RIFF
+(
+    'DMSC'              // DirectMusic Script chunk
+    <schd-ck>           // Script header chunk
+    [<guid-ck>]         // GUID for script
+    [<vers-ck>]         // Optional version info
+    [<UNFO-list>]       // Name, author, copyright info., comments
+    <scve-ck>           // Version of DirectMusic this script was authored to run against
+    <DMCN-form>         // Container of content referenced by the script.
+    <scla-ck>           // ActiveX scripting language in which the script is written
+    <scsr-ck> or <DMRF> // The script's source code.
+                        // If scsr-ck, the source is embedding in the chunk.
+                        // If DMRF, it is a reference of where to find a text file with the source.
+                        //    Class id (guidClassID in DMUS_IO_REFERENCE) must be GUID_NULL because
+                        //    this text file is not a DirectMusic object in its own right.
+)
+
+    // <schd-ck>
+    'schd'
+    (
+        <DMUS_FOURCC_SCRIPT_CHUNK>
+    )
+
+    // <guid-ck>
+    'guid'
+    (
+        <GUID>
+    )
+
+    // <vers-ck>
+    vers
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    // <scve-ck>
+    scve
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    'scla'
+    (
+        // Language name, stored as NULL terminated string of WCHARs
+    )
+
+    'scsr'
+    (
+        // Source code, stored as NULL terminated string of WCHARs
+    )
+*/
+
+/* Signpost tracks */
+
+#define DMUS_FOURCC_SIGNPOST_TRACK_CHUNK     mmioFOURCC( 's', 'g', 'n', 'p' )
+
+
+typedef struct _DMUS_IO_SIGNPOST
+{
+    MUSIC_TIME  mtTime;
+    DWORD       dwChords;
+    WORD        wMeasure;
+} DMUS_IO_SIGNPOST;
+
+/*
+
+    // <sgnp-list>
+    'sgnp'
+    (
+        //sizeof DMUS_IO_SIGNPOST: DWORD
+        <DMUS_IO_SIGNPOST>...
+    )
+
+*/
+
+#define DMUS_FOURCC_MUTE_CHUNK  mmioFOURCC('m','u','t','e')
+
+typedef struct _DMUS_IO_MUTE
+{
+    MUSIC_TIME  mtTime;
+    DWORD       dwPChannel;
+    DWORD       dwPChannelMap;
+} DMUS_IO_MUTE;
+
+/*
+
+    // <mute-list>
+    'mute'
+    (
+        //sizeof DMUS_IO_MUTE:DWORD
+        <DMUS_IO_MUTE>...
+    )
+
+
+*/
+
+/* Used for both style and chord map tracks */
+
+#define DMUS_FOURCC_TIME_STAMP_CHUNK    mmioFOURCC('s', 't', 'm', 'p')
+
+/* Style tracks */
+
+#define DMUS_FOURCC_STYLE_TRACK_LIST    mmioFOURCC('s', 't', 't', 'r')
+#define DMUS_FOURCC_STYLE_REF_LIST      mmioFOURCC('s', 't', 'r', 'f')
+
+/*
+
+    // <sttr-list>
+    LIST('sttr'
+    (
+        <strf-list>...  // Array of Style references
+    )
+
+    // <strf-list>
+    LIST('strf'
+    (
+        <stmp-ck>
+        <DMRF>
+    )
+
+  // <stmp-ck>
+  'stmp'
+  (
+    // time:DWORD
+  )
+
+*/
+
+/* Chord map tracks */
+
+#define DMUS_FOURCC_PERS_TRACK_LIST mmioFOURCC('p', 'f', 't', 'r')
+#define DMUS_FOURCC_PERS_REF_LIST   mmioFOURCC('p', 'f', 'r', 'f')
+
+/*
+
+    // <pftr-list>
+    LIST('pftr'
+    (
+        <pfrf-list>...  // Array of Chord map references
+    )
+
+    // <pfrf-list>
+    LIST('pfrf'
+    (
+        <stmp-ck>
+        <DMRF>
+    )
+
+  // <stmp-ck>
+  'stmp'
+  (
+    // time:DWORD
+  )
+
+*/
+
+#define DMUS_FOURCC_TEMPO_TRACK     mmioFOURCC('t','e','t','r')
+
+/*
+    // tempo array
+    'tetr'
+    (
+        // sizeof DMUS_IO_TEMPO_ITEM: DWORD
+        <DMUS_IO_TEMPO_ITEM>...
+    )
+ */
+
+#define DMUS_FOURCC_SEQ_TRACK       mmioFOURCC('s','e','q','t')
+#define DMUS_FOURCC_SEQ_LIST        mmioFOURCC('e','v','t','l')
+#define DMUS_FOURCC_CURVE_LIST      mmioFOURCC('c','u','r','l')
+
+/*
+    // sequence track
+    'seqt'
+    (
+        // sequence array
+        'evtl'
+        (
+            // sizeof DMUS_IO_SEQ_ITEM: DWORD
+            <DMUS_IO_SEQ_ITEM>...
+        )
+        // curve array
+        'curl'
+        (
+            // sizeof DMUS_IO_CURVE_ITEM: DWORD
+            <DMUS_IO_CURVE_ITEM>...
+        )
+    )
+*/
+
+#define DMUS_FOURCC_SYSEX_TRACK     mmioFOURCC('s','y','e','x')
+
+/*
+    // sysex track
+    'syex'
+    (
+        {
+            <DMUS_IO_SYSEX_ITEM>
+            <BYTE>...    // Array of bytes, length defined in the DMUS_IO_SYSEXITEM structure
+        }...
+    )
+*/
+
+#define DMUS_FOURCC_TIMESIGNATURE_TRACK mmioFOURCC('t','i','m','s')
+
+typedef struct _DMUS_IO_TIMESIGNATURE_ITEM
+{
+    MUSIC_TIME    lTime;
+    BYTE          bBeatsPerMeasure;   /* beats per measure (top of time sig) */
+    BYTE          bBeat;              /* what note receives the beat (bottom of time sig.) */
+                                      /* we can assume that 0 means 256th note */
+    WORD          wGridsPerBeat;      /* grids per beat */
+} DMUS_IO_TIMESIGNATURE_ITEM;
+
+/*  DirectX6 time signature track
+
+    'tims'
+    (
+        // size of DMUS_IO_TIMESIGNATURE_ITEM : DWORD
+        <DMUS_IO_TIMESIGNATURE_ITEM>...
+    )
+*/
+
+/*  DirectX8 Time signature track. The track has been updated from DirectX7 to support a list of
+    RIFF chunks. This will allow the time signature track to expand in the future.
+*/
+
+#define DMUS_FOURCC_TIMESIGTRACK_LIST   mmioFOURCC('T','I','M','S')
+#define DMUS_FOURCC_TIMESIG_CHUNK       DMUS_FOURCC_TIMESIGNATURE_TRACK
+
+/*
+LIST
+(
+    'TIMS'          // Time Signature Track list-type
+    <tims-ck>       // Chunk containing an array of time signatures
+)
+
+    'tims'
+    (
+        // size of DMUS_IO_TIMESIGNATURE_ITEM : DWORD
+        <DMUS_IO_TIMESIGNATURE_ITEM>...
+    )
+
+*/
+
+/*  DirectX8 Marker track. This is used to store valid start points and other
+    flow control parameters that may come later. For example, if we want
+    to implement more sophisticated looping and branching constructs, they
+    would live in this track.
+*/
+
+#define DMUS_FOURCC_MARKERTRACK_LIST    mmioFOURCC('M','A','R','K')
+#define DMUS_FOURCC_VALIDSTART_CHUNK    mmioFOURCC('v','a','l','s')
+#define DMUS_FOURCC_PLAYMARKER_CHUNK    mmioFOURCC('p','l','a','y')
+
+/* io structures */
+typedef struct _DMUS_IO_VALID_START
+{
+    MUSIC_TIME mtTime;      /* Time of a legal start. */
+} DMUS_IO_VALID_START;
+
+typedef struct _DMUS_IO_PLAY_MARKER
+{
+    MUSIC_TIME mtTime;      /* Time of a next legal play point marker. */
+} DMUS_IO_PLAY_MARKER;
+
+/*
+LIST
+(
+    'MARK'          // Marker Track list-type
+    [<vals-ck>]     // Chunk containing an array of start points
+    [<play-ck>]     // Chunk containing an array of play start markers
+)
+
+    'vals'
+    (
+        // size of DMUS_IO_VALID_START : DWORD
+        <DMUS_IO_VALID_START>...
+    )
+
+    'play'
+    (
+        // size of DMUS_IO_PLAY_MARKER : DWORD
+        <DMUS_IO_PLAY_MARKER>...
+    )
+
+*/
+
+/* segment trigger tracks */
+
+/* RIFF ids: */
+#define DMUS_FOURCC_SEGTRACK_LIST                   mmioFOURCC('s','e','g','t')
+#define DMUS_FOURCC_SEGTRACK_CHUNK                  mmioFOURCC('s','g','t','h')
+#define DMUS_FOURCC_SEGMENTS_LIST                   mmioFOURCC('l','s','g','l')
+#define DMUS_FOURCC_SEGMENT_LIST                    mmioFOURCC('l','s','e','g')
+#define DMUS_FOURCC_SEGMENTITEM_CHUNK               mmioFOURCC('s','g','i','h')
+#define DMUS_FOURCC_SEGMENTITEMNAME_CHUNK           mmioFOURCC('s','n','a','m')
+
+/* io structures */
+typedef struct _DMUS_IO_SEGMENT_TRACK_HEADER
+{
+    DWORD dwFlags; /* Reserved leave as 0. */
+} DMUS_IO_SEGMENT_TRACK_HEADER;
+
+typedef struct _DMUS_IO_SEGMENT_ITEM_HEADER
+{
+    MUSIC_TIME      lTimeLogical;    /* Position in track list. Time in the music with which the event is associated. */
+    MUSIC_TIME      lTimePhysical;   /* Precise time event will be triggered. Should be close to logical time. */
+    DWORD           dwPlayFlags;     /* Flags for PlaySegment(). */
+    DWORD           dwFlags;         /* Flags. */
+} DMUS_IO_SEGMENT_ITEM_HEADER;
+
+/* values for dwflags field of DMUS_IO_SEGMENT_ITEM_HEADER */
+#define DMUS_SEGMENTTRACKF_MOTIF                 1        /* interpret DMRF as link to style, and use snam as the name of a motif within the style */
+
+/*
+LIST
+(
+    'segt'          // DirectMusic Segment Trigger Track form-type
+    [<sgth-ck>]     // Segment track header
+    <lsgl-list>     // List of Segment Lists
+)
+
+    // <sgth-ck>
+    'sgth'
+    (
+        <DMUS_IO_SEGMENT_TRACK_HEADER>
+    )
+
+    // <lsgl-list>
+    LIST
+    (
+        'lsgl'          // Array of segments
+        <lseg-list>...  // Each segment is encapsulated in a list (that way it can still be riff parsed.)
+    )
+
+        // <lseg-list>
+        LIST
+        (
+            'lseg'
+            <sgih-ck>
+            <DMRF-list>    // Link to a segment or style file.
+            [<snam-ck>]    // Name field.  Used with DMUS_SEGMENTTRACKF_MOTIF flag.
+        )
+
+            // <sgih-ck>            // segment item header
+            (
+                <DMUS_IO_SEGMENT_ITEM_HEADER>  // Segment item header
+            )
+
+            // <snam-ck>
+            (
+                // Name, stored as NULL terminated string of WCHARs
+            )
+*/
+
+/* Script track. */
+
+/* RIFF ids: */
+#define DMUS_FOURCC_SCRIPTTRACK_LIST                mmioFOURCC('s','c','r','t')
+#define DMUS_FOURCC_SCRIPTTRACKEVENTS_LIST          mmioFOURCC('s','c','r','l')
+#define DMUS_FOURCC_SCRIPTTRACKEVENT_LIST           mmioFOURCC('s','c','r','e')
+#define DMUS_FOURCC_SCRIPTTRACKEVENTHEADER_CHUNK    mmioFOURCC('s','c','r','h')
+#define DMUS_FOURCC_SCRIPTTRACKEVENTNAME_CHUNK      mmioFOURCC('s','c','r','n')
+
+/* Flags for DMUS_IO_SCRIPTTRACK_TIMING
+ */
+#define DMUS_IO_SCRIPTTRACKF_PREPARE (1 << 0)        /* Fire event in advance of time stamp, at Prepare time.  This is the default because it leaves the script time to change the music happening at the target time. */
+#define DMUS_IO_SCRIPTTRACKF_QUEUE   (1 << 1)        /* Fire event just before time stamp, at Queue time. */
+#define DMUS_IO_SCRIPTTRACKF_ATTIME  (1 << 2)        /* Fire event right at the time stamp. */
+
+typedef struct _DMUS_IO_SCRIPTTRACK_EVENTHEADER
+{
+    DWORD dwFlags;              /* various bits (see DMUS_IO_SCRIPTTRACKF_*) */
+    MUSIC_TIME lTimeLogical;    /* Position in track list. Time in the music with which the event is associated. */
+    MUSIC_TIME lTimePhysical;   /* Precise time event will be triggered. Should be close to logical time. */
+} DMUS_IO_SCRIPTTRACK_EVENTHEADER;
+
+/*
+    // Script Track
+
+    // <scrt-list>
+    LIST
+    (
+        <scrl-list>       // List of script events
+    )
+
+        // <scrl-list>
+        LIST
+        (
+            <scre-list>...    // Array of event descriptions
+        )
+
+            // <scre-list>
+            LIST
+            (
+                <scrh-ck>         // Event header chunk
+                <DMRF>
+                <scrn-ck>         // Routine name
+            )
+
+                'scrh'
+                (
+                    <DMUS_IO_SCRIPTTRACK_EVENTHEADER>
+                )
+
+                'scrn'
+                (
+                    // Name, stored as NULL terminated string of WCHARs
+                )
+*/
+
+/* Lyrics/Notification track. */
+
+/* RIFF ids: */
+#define DMUS_FOURCC_LYRICSTRACK_LIST                mmioFOURCC('l','y','r','t')
+#define DMUS_FOURCC_LYRICSTRACKEVENTS_LIST          mmioFOURCC('l','y','r','l')
+#define DMUS_FOURCC_LYRICSTRACKEVENT_LIST           mmioFOURCC('l','y','r','e')
+#define DMUS_FOURCC_LYRICSTRACKEVENTHEADER_CHUNK    mmioFOURCC('l','y','r','h')
+#define DMUS_FOURCC_LYRICSTRACKEVENTTEXT_CHUNK      mmioFOURCC('l','y','r','n')
+
+typedef struct _DMUS_IO_LYRICSTRACK_EVENTHEADER
+{
+    DWORD dwFlags;              /* Reserved leave as 0. */
+    DWORD dwTimingFlags;        /* Combination DMUS_PMSGF_TOOL_* flags.  Determines the precise timing of when the notification happens. Invalid with the flag DMUS_PMSGF_REFTIME, DMUS_PMSGF_MUSICTIME, DMUS_PMSGF_TOOL_FLUSH, or DMUS_PMSGF_LOCKTOREFTIME. */
+    MUSIC_TIME lTimeLogical;    /* Position in track list. Time in the music with which the event is associated. */
+    MUSIC_TIME lTimePhysical;   /* Precise time event will be triggered. Should be close to logical time. */
+} DMUS_IO_LYRICSTRACK_EVENTHEADER;
+
+/*
+    // Lyrics/Notification Track
+
+    // <lyrt-list>
+    LIST
+    (
+        <lyrl-list>       // List of notification events
+    )
+
+        // <lyrl-list>
+        LIST
+        (
+            <lyre-list>...    // Array of event descriptions
+        )
+
+            // <lyre-list>
+            LIST
+            (
+                <lyrh-ck>         // Event header chunk
+                <lyrn-ck>         // Notification text
+            )
+
+                'lyrh'
+                (
+                    <DMUS_IO_LYRICSTRACK_EVENTHEADER>
+                )
+
+                'lyrn'
+                (
+                    // Name, stored as NULL terminated string of WCHARs
+                )
+*/
+
+/* Parameter control track */
+
+/* RIFF ids: */
+#define DMUS_FOURCC_PARAMCONTROLTRACK_TRACK_LIST            mmioFOURCC('p','r','m','t')
+#define DMUS_FOURCC_PARAMCONTROLTRACK_OBJECT_LIST           mmioFOURCC('p','r','o','l')
+#define DMUS_FOURCC_PARAMCONTROLTRACK_OBJECT_CHUNK          mmioFOURCC('p','r','o','h')
+#define DMUS_FOURCC_PARAMCONTROLTRACK_PARAM_LIST            mmioFOURCC('p','r','p','l')
+#define DMUS_FOURCC_PARAMCONTROLTRACK_PARAM_CHUNK           mmioFOURCC('p','r','p','h')
+#define DMUS_FOURCC_PARAMCONTROLTRACK_CURVES_CHUNK          mmioFOURCC('p','r','c','c')
+
+typedef struct _DMUS_IO_PARAMCONTROLTRACK_OBJECTHEADER
+{
+    DWORD dwFlags;              /* Reserved.  Must be zero. */
+    GUID guidTimeFormat;        /* Time format to set the object to.  Must be GUID_TIME_REFERNCE or GUID_TIME_MUSIC from medparam.h. */
+    /* Path for finding the object. These fields correspond to the first five parameters of IDirectMusicSegmentState::GetObjectInPath. */
+    DWORD dwPChannel;
+    DWORD dwStage;
+    DWORD dwBuffer;
+    GUID guidObject;
+    DWORD dwIndex;
+} DMUS_IO_PARAMCONTROLTRACK_OBJECTHEADER;
+
+typedef struct _DMUS_IO_PARAMCONTROLTRACK_PARAMHEADER
+{
+    DWORD dwFlags;              /* Reserved.  Must be zero. */
+    DWORD dwIndex;              /* Index number of the parameter on the object */
+} DMUS_IO_PARAMCONTROLTRACK_PARAMHEADER;
+
+typedef struct _DMUS_IO_PARAMCONTROLTRACK_CURVEINFO
+{
+    MUSIC_TIME  mtStartTime;
+    MUSIC_TIME  mtEndTime;
+    float       fltStartValue;
+    float       fltEndValue;
+    DWORD       dwCurveType;   /* One of the items from the MP_CURVE_TYPE enum in medparam.h */
+    DWORD       dwFlags;       /* A combination of the MPF_ENVLP_* constants in medparam.h */
+} DMUS_IO_PARAMCONTROLTRACK_CURVEINFO;
+
+/*
+    // <prmt-list>
+    LIST
+    (
+        <prol-list>...   // one for each object
+    )
+
+        // <prol-list>
+        LIST
+        (
+            <proh-ck>       // object header chunk
+            <prpl-list>...  // one for each parameter
+        )
+
+            // <proh-ck>
+            proh
+            (
+                <DMUS_IO_PARAMCONTROLTRACK_OBJECTHEADER>
+            )
+
+            // <prpl-list>
+            LIST
+            (
+                <prph-ck>       // parameter header chunk
+                <prcc-ck>       // chunk containing an array of curves
+            )
+
+                // <prph-ck>
+                prph
+                (
+                    <DMUS_IO_PARAMCONTROLTRACK_PARAMHEADER>
+                )
+
+                // <prcc-ck>
+                prcc
+                (
+                    // sizeof DMUS_IO_PARAMCONTROLTRACK_CURVEINFO:DWORD
+                    <DMUS_IO_PARAMCONTROLTRACK_CURVEINFO>... // curves, sorted in order of mtTime
+                )
+*/
+
+#if (DIRECTSOUND_VERSION >= 0x0800)
+
+/* DirectSoundBufferConfig FX Map */
+
+/* RIFF ids: */
+
+#define DMUS_FOURCC_DSBC_FORM       mmioFOURCC('D','S','B','C')
+#define DMUS_FOURCC_DSBD_CHUNK      mmioFOURCC('d','s','b','d')
+#define DMUS_FOURCC_BSID_CHUNK      mmioFOURCC('b','s','i','d')
+#define DMUS_FOURCC_DS3D_CHUNK      mmioFOURCC('d','s','3','d')
+#define DMUS_FOURCC_DSBC_LIST       mmioFOURCC('f','x','l','s')
+#define DMUS_FOURCC_DSFX_FORM       mmioFOURCC('D','S','F','X')
+#define DMUS_FOURCC_DSFX_CHUNK      mmioFOURCC('f','x','h','r')
+#define DMUS_FOURCC_DSFX_DATA       mmioFOURCC('d','a','t','a')
+
+/* io structures */
+
+typedef struct _DSOUND_IO_DSBUFFERDESC
+{
+    DWORD dwFlags;        /* DirectSound buffer creation flags */
+    WORD nChannels;       /* No. of channels (rest of buffer format is determined by owning sink) */
+    LONG lVolume;         /* Initial pan; only used if CTRLVOLUME is specified */
+    LONG lPan;            /* Initial pan; only used if CTRLPAN is specified */
+    DWORD dwReserved;     /* Reserved - must be 0 */
+} DSOUND_IO_DSBUFFERDESC;
+
+typedef struct _DSOUND_IO_DSBUSID
+{
+    DWORD busid[1];       /* Array size determined from chunk size */
+} DSOUND_IO_DSBUSID;
+
+typedef struct _DSOUND_IO_3D
+{
+    GUID guid3DAlgorithm; /* GUID identifying the 3D algorithm to use (defined in dsound.h) */
+    DS3DBUFFER ds3d;      /* Initial 3D parameters */
+} DSOUND_IO_3D;
+
+typedef struct _DSOUND_IO_DXDMO_HEADER
+{
+    DWORD dwEffectFlags;  /* Effect creation flags - equivalent to DSEFFECTDESC::dwFlags */
+    GUID guidDSFXClass;   /* GUID identifying the effect to use - corresponds to a COM CLSID */
+    GUID guidReserved;    /* Reserved - must be the null GUID */
+    GUID guidSendBuffer;  /* GUID identifying the buffer to send to if this is a send effect */
+    DWORD dwReserved;     /* Reserved - must be 0 */
+} DSOUND_IO_DXDMO_HEADER;
+
+typedef struct _DSOUND_IO_DXDMO_DATA
+{
+    DWORD data[1];      /* Array size determined by the DMO involved */
+} DSOUND_IO_DXDMO_DATA;
+
+/*
+RIFF
+(
+    'DSBC'          // DirectSoundBufferConfig chunk
+    [<guid-ck>]     // GUID identifier for this DirectSoundBufferConfig
+    [<vers-ck>]     // Optional version info
+    [<UNFO-list>]   // Name, author, copyright info., comments
+    <dsbd-ck>       // DirectSound Buffer descriptor chunk
+    [<bsid-ck>]     // Optional bus id array
+    [<ds3d-ck>]     // Optional 3d Parameters
+    [<fxls-list>]   // Optional list of FX descriptors
+)
+
+    // <guid-ck>
+    'guid'
+    (
+        <GUID>
+    )
+
+    // <vers-ck>
+    'vers'
+    (
+        <DMUS_IO_VERSION>
+    )
+
+    // <dsbd-ck>
+    'dsbd'
+    (
+        <DSOUND_IO_DSBUFFERDESC>  // Creation parameters and initial settings for the buffer
+    )
+
+    // <bsid-ck>
+    'bsid'
+    (
+        <DSOUND_IO_DSBUSID>  // The size of DSOUND_IO_DSBUSID is determined by the chunk size
+    )
+
+    // <ds3d-ck>
+    'ds3d'
+    (
+        <DSOUND_IO_3D>  // Initial 3D buffer parameters: position, etc.
+    )
+
+    // <fx-list>
+    LIST
+    (
+        'fxls'          // Array of DMO creation parameter blocks
+        <DSFX-form>...  // Each DMO is encapsulated in a RIFF chunk
+    )
+
+// <DSFX-form>          // DMOs can be embedded in a buffer configuration or stored as separate files
+RIFF
+(
+    'DSFX'
+    <fxhr-ck>           // FX header chunk
+    [<data-ck>]         // FX initial settings chunk
+)
+
+    // <fxhr-ck>
+    'fxhr'
+    (
+        <DSOUND_IO_DXDMO_HEADER>
+    )
+
+    // <data-ck>
+    'data'
+    (
+        <DSOUND_IO_DXDMO_DATA>  // Opaque data block used by the DMO to load itself.
+        // For our standard included DMOs, this is simply the structure accepted by
+        // the DMO's SetAllParameters() method - e.g. struct DSFXChorus for Chorus.
+    )
+*/
+
+#endif
+
+#ifdef __cplusplus
+}; /* extern "C" */
+#endif
+
+#include <poppack.h>
+
+#endif /* #ifndef _DMUSICF_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmusici.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1883 @@
+/************************************************************************
+*                                                                       *
+*   dmusici.h -- This module contains the API for the                   *
+*                DirectMusic performance layer                          *
+*                                                                       *
+*   Copyright (c) Microsoft Corporation.  All rights reserved.          *
+*                                                                       *
+************************************************************************/
+
+#ifndef _DMUSICI_
+#define _DMUSICI_
+
+#include <windows.h>
+
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+
+#include <mmsystem.h>
+#include <dmusicc.h>
+/* plugin (track and tool) interfaces.  This #include will eventually go away. */
+#include <dmplugin.h>
+
+#include <pshpack8.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef WORD            TRANSITION_TYPE;
+typedef __int64         REFERENCE_TIME;
+typedef long            MUSIC_TIME;
+
+#define MT_MIN          0x80000000  /* Minimum music time value. */
+#define MT_MAX          0x7FFFFFFF  /* Maximum music time value. */
+
+#define DMUS_PPQ        768     /* parts per quarter note */
+
+interface IDirectMusicTrack;
+interface IDirectMusicPerformance;
+interface IDirectMusicPerformance8;
+interface IDirectMusicTool;
+interface IDirectMusicSegment;
+interface IDirectMusicSegment8;
+interface IDirectMusicSegmentState;
+interface IDirectMusicSegmentState8;
+interface IDirectMusicGraph;
+interface IDirectMusicBuffer;
+interface IDirectMusicInstrument;
+interface IDirectMusicDownloadedInstrument;
+interface IDirectMusicBand;
+interface IDirectMusicChordMap;
+interface IDirectMusicLoader;
+interface IDirectMusicLoader8;
+interface IDirectMusicScript;
+interface IDirectMusicObject;
+interface IDirectMusicStyle8;
+interface IDirectMusicPatternTrack;
+interface IDirectMusicContainer;
+interface IDirectMusicTool8;
+interface IDirectMusicTrack8;
+interface IDirectMusicAudioPath;
+#ifndef __cplusplus
+typedef interface IDirectMusicTrack IDirectMusicTrack;
+typedef interface IDirectMusicPerformance IDirectMusicPerformance;
+typedef interface IDirectMusicPerformance8 IDirectMusicPerformance8;
+typedef interface IDirectMusicTool IDirectMusicTool;
+typedef interface IDirectMusicSegment IDirectMusicSegment;
+typedef interface IDirectMusicSegment8 IDirectMusicSegment8;
+typedef interface IDirectMusicSegmentState IDirectMusicSegmentState;
+typedef interface IDirectMusicSegmentState8 IDirectMusicSegmentState8;
+typedef interface IDirectMusicGraph IDirectMusicGraph;
+typedef interface IDirectMusicBuffer IDirectMusicBuffer;
+typedef interface IDirectMusicInstrument IDirectMusicInstrument;
+typedef interface IDirectMusicDownloadedInstrument IDirectMusicDownloadedInstrument;
+typedef interface IDirectMusicBand IDirectMusicBand;
+typedef interface IDirectMusicChordMap IDirectMusicChordMap;
+typedef interface IDirectMusicObject IDirectMusicObject;
+typedef interface IDirectMusicLoader IDirectMusicLoader;
+typedef interface IDirectMusicLoader8 IDirectMusicLoader8;
+typedef interface IDirectMusicScript IDirectMusicScript;
+typedef interface IDirectMusicStyle8 IDirectMusicStyle8;
+typedef interface IDirectMusicPatternTrack IDirectMusicPatternTrack;
+typedef interface IDirectMusicContainer IDirectMusicContainer;
+typedef interface IDirectMusicTool8 IDirectMusicTool8;
+typedef interface IDirectMusicTrack8 IDirectMusicTrack8;
+typedef interface IDirectMusicAudioPath IDirectMusicAudioPath;
+#endif
+
+typedef enum enumDMUS_STYLET_TYPES
+{
+    DMUS_STYLET_PATTERN         = 0,
+    DMUS_STYLET_MOTIF           = 1,
+} DMUS_STYLET_TYPES;
+
+
+typedef enum enumDMUS_COMMANDT_TYPES
+{
+    DMUS_COMMANDT_GROOVE            = 0,
+    DMUS_COMMANDT_FILL              = 1,
+    DMUS_COMMANDT_INTRO             = 2,
+    DMUS_COMMANDT_BREAK             = 3,
+    DMUS_COMMANDT_END               = 4,
+    DMUS_COMMANDT_ENDANDINTRO       = 5
+} DMUS_COMMANDT_TYPES;
+
+typedef enum enumDMUS_SHAPET_TYPES
+{
+    DMUS_SHAPET_FALLING             = 0,
+    DMUS_SHAPET_LEVEL               = 1,
+    DMUS_SHAPET_LOOPABLE            = 2,
+    DMUS_SHAPET_LOUD                = 3,
+    DMUS_SHAPET_QUIET               = 4,
+    DMUS_SHAPET_PEAKING             = 5,
+    DMUS_SHAPET_RANDOM              = 6,
+    DMUS_SHAPET_RISING              = 7,
+    DMUS_SHAPET_SONG                = 8
+}   DMUS_SHAPET_TYPES;
+
+typedef enum enumDMUS_COMPOSEF_FLAGS
+{
+    DMUS_COMPOSEF_NONE              = 0,
+    DMUS_COMPOSEF_ALIGN             = 0x1,
+    DMUS_COMPOSEF_OVERLAP           = 0x2,
+    DMUS_COMPOSEF_IMMEDIATE         = 0x4,
+    DMUS_COMPOSEF_GRID              = 0x8,
+    DMUS_COMPOSEF_BEAT              = 0x10,
+    DMUS_COMPOSEF_MEASURE           = 0x20,
+    DMUS_COMPOSEF_AFTERPREPARETIME  = 0x40,
+    DMUS_COMPOSEF_VALID_START_BEAT  = 0x80,   /* In conjunction with DMUS_COMPOSEF_ALIGN, allows the switch to occur on any beat. */
+    DMUS_COMPOSEF_VALID_START_GRID  = 0x100,  /* In conjunction with DMUS_COMPOSEF_ALIGN, allows the switch to occur on any grid. */
+    DMUS_COMPOSEF_VALID_START_TICK  = 0x200,  /* In conjunction with DMUS_COMPOSEF_ALIGN, allows the switch to occur any time. */
+    DMUS_COMPOSEF_SEGMENTEND        = 0x400,  /* Play the transition at the end of the current segment. */
+    DMUS_COMPOSEF_MARKER            = 0x800,  /* Play the transition at the next marker in the current segment. */
+    DMUS_COMPOSEF_MODULATE          = 0x1000,
+    DMUS_COMPOSEF_LONG              = 0x2000,
+    DMUS_COMPOSEF_ENTIRE_TRANSITION = 0x4000,    /* play the entire transition pattern */
+    DMUS_COMPOSEF_1BAR_TRANSITION   = 0x8000,    /* play one bar of the transition pattern */
+    DMUS_COMPOSEF_ENTIRE_ADDITION   = 0x10000,   /* play the additional pattern in its entirety */
+    DMUS_COMPOSEF_1BAR_ADDITION     = 0x20000,   /* play one bar of the additional pattern */
+    DMUS_COMPOSEF_VALID_START_MEASURE = 0x40000, /* In conjunction with DMUS_COMPOSEF_ALIGN, allows the switch to occur on any bar. */
+    DMUS_COMPOSEF_DEFAULT           = 0x80000,   /* Use segment's default boundary */
+    DMUS_COMPOSEF_NOINVALIDATE      = 0x100000,  /* Play without invalidating the currently playing segment(s) */
+    DMUS_COMPOSEF_USE_AUDIOPATH     = 0x200000,  /* Uses the audio paths that are embedded in the segments */
+    DMUS_COMPOSEF_INVALIDATE_PRI    = 0x400000   /* Invalidate only the current primary seg state */
+}   DMUS_COMPOSEF_FLAGS;
+
+#define DMUS_PMSG_PART                                                                              \
+    DWORD               dwSize;                                                                     \
+    REFERENCE_TIME      rtTime;             /* real time (in 100 nanosecond increments) */          \
+    MUSIC_TIME          mtTime;             /* music time */                                        \
+    DWORD               dwFlags;            /* various bits (see DMUS_PMSGF_FLAGS enumeration) */    \
+    DWORD               dwPChannel;         /* Performance Channel. The Performance can */          \
+                                            /* use this to determine the port/channel. */           \
+    DWORD               dwVirtualTrackID;   /* virtual track ID */                                  \
+    IDirectMusicTool*   pTool;              /* tool interface pointer */                            \
+    IDirectMusicGraph*  pGraph;             /* tool graph interface pointer */                      \
+    DWORD               dwType;             /* PMSG type (see DMUS_PMSGT_TYPES defines) */              \
+    DWORD               dwVoiceID;          /* unique voice id which allows synthesizers to */      \
+                                            /* identify a specific event. For DirectX 6.0, */       \
+                                            /* this field should always be 0. */                    \
+    DWORD               dwGroupID;          /* Track group id */                                 \
+    IUnknown*           punkUser;           /* user com pointer, auto released upon PMSG free */
+
+/* every DMUS_PMSG is based off of this structure. The Performance needs
+   to access these members consistently in every PMSG that goes through it. */
+typedef struct _DMUS_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+} DMUS_PMSG;
+
+#define DMUS_PCHANNEL_BROADCAST_PERFORMANCE	0xFFFFFFFF  /* PMsg is sent on all PChannels of the performance. */
+#define DMUS_PCHANNEL_BROADCAST_AUDIOPATH   0xFFFFFFFE  /* PMsg is sent on all PChannels of the audio path. */
+#define DMUS_PCHANNEL_BROADCAST_SEGMENT	    0xFFFFFFFD  /* PMsg is sent on all PChannels of the segment. */
+#define DMUS_PCHANNEL_BROADCAST_GROUPS  	0xFFFFFFFC  /* A duplicate PMsg is for each Channels Groups in the performance. */
+
+/*  The DMUS_PATH constants are used in conjunction with GetObjectInPath to find a requested
+    interface at a particular stage in the audio path.
+*/
+#define DMUS_PATH_SEGMENT          0x1000      /* Get the segment itself (from a segment state.) */
+#define DMUS_PATH_SEGMENT_TRACK    0x1100      /* Look in Track List of Segment. */
+#define DMUS_PATH_SEGMENT_GRAPH    0x1200      /* Get the segment's tool graph. */
+#define DMUS_PATH_SEGMENT_TOOL     0x1300      /* Look in Tool Graph of Segment. */
+#define DMUS_PATH_AUDIOPATH        0x2000      /* Get the audiopath itself (from a segment state.) */
+#define DMUS_PATH_AUDIOPATH_GRAPH  0x2200      /* Get the audiopath's tool graph. */
+#define DMUS_PATH_AUDIOPATH_TOOL   0x2300      /* Look in Tool Graph of Audio Path. */
+#define DMUS_PATH_PERFORMANCE      0x3000      /* Access the performance. */
+#define DMUS_PATH_PERFORMANCE_GRAPH 0x3200     /* Get the performance's tool graph. */
+#define DMUS_PATH_PERFORMANCE_TOOL 0x3300      /* Look in Tool Graph of Performance. */
+#define DMUS_PATH_PORT             0x4000      /* Access the synth. */
+#define DMUS_PATH_BUFFER           0x6000      /* Look in DirectSoundBuffer. */
+#define DMUS_PATH_BUFFER_DMO       0x6100      /* Access a DMO in the buffer. */
+#define DMUS_PATH_MIXIN_BUFFER     0x7000      /* Look in a global mixin buffer. */
+#define DMUS_PATH_MIXIN_BUFFER_DMO 0x7100      /* Access a DMO in a global mixin buffer. */
+#define DMUS_PATH_PRIMARY_BUFFER   0x8000      /* Access the primary buffer. */
+
+/*  To ignore PChannels when calling GetObjectInPath(), use the DMUS_PCHANNEL_ALL constant. */
+#define DMUS_PCHANNEL_ALL           0xFFFFFFFB
+
+/*  The DMUS_APATH types are used in conjunction with CreateStandardAudioPath to
+    build default path types. _SHARED_ means the same buffer is shared across multiple
+    instantiations of the audiopath type. _DYNAMIC_ means a unique buffer is created
+    every time.
+*/
+
+#define DMUS_APATH_SHARED_STEREOPLUSREVERB   1       /* A standard music set up with stereo outs and reverb. */
+#define DMUS_APATH_DYNAMIC_3D                6       /* An audio path with one dynamic bus from the synth feeding to a dynamic 3d buffer. Does not send to env reverb. */
+#define DMUS_APATH_DYNAMIC_MONO              7       /* An audio path with one dynamic bus from the synth feeding to a dynamic mono buffer. */
+#define DMUS_APATH_DYNAMIC_STEREO            8       /* An audio path with two dynamic buses from the synth feeding to a dynamic stereo buffer. */
+
+typedef struct _DMUS_AUDIOPARAMS
+{
+    DWORD   dwSize;             /* Size of this structure. */
+    BOOL    fInitNow;           /* If true, the sink and synth are created immediately and results returned in this structure. */
+    DWORD 	dwValidData;        /* Flags indicating which fields below are valid. */
+    DWORD   dwFeatures;         /* Required DMUS_AUDIOF features. */
+    DWORD   dwVoices;           /* Required number of voices. */
+    DWORD   dwSampleRate;       /* Sample rate of synths and sink. */
+    CLSID   clsidDefaultSynth;  /* Class ID of default synthesizer. */
+} DMUS_AUDIOPARAMS;
+
+/* dwFeatures flags. These indicate which features are required for the audio environment. */
+#define DMUS_AUDIOF_3D          0x1   /* Require 3D buffers. */
+#define DMUS_AUDIOF_ENVIRON     0x2   /* Require environmental modeling. */
+#define DMUS_AUDIOF_EAX         0x4   /* Require use of EAX effects. */
+#define DMUS_AUDIOF_DMOS        0x8   /* Require use of additional DMOs. */
+#define DMUS_AUDIOF_STREAMING   0x10  /* Require support for streaming waves. */
+#define DMUS_AUDIOF_BUFFERS     0x20  /* Require support for multiple buffers (all above cases need this.) */
+#define DMUS_AUDIOF_ALL         0x3F  /* Requires everything. */
+
+/* dwValidData flags. These indicate which fields in DMUS_AUDIOPARAMS have been filled in. If fInitNow is set, these also return what was allocated. */
+#define DMUS_AUDIOPARAMS_FEATURES       0x00000001
+#define DMUS_AUDIOPARAMS_VOICES         0x00000002
+#define DMUS_AUDIOPARAMS_SAMPLERATE     0x00000004
+#define DMUS_AUDIOPARAMS_DEFAULTSYNTH   0x00000008
+
+/* DMUS_PMSGF_FLAGS fill the DMUS_PMSG's dwFlags member */
+typedef enum enumDMUS_PMSGF_FLAGS
+{
+    DMUS_PMSGF_REFTIME          = 1,      /* if rtTime is valid */
+    DMUS_PMSGF_MUSICTIME        = 2,      /* if mtTime is valid */
+    DMUS_PMSGF_TOOL_IMMEDIATE   = 4,      /* if PMSG should be processed immediately */
+    DMUS_PMSGF_TOOL_QUEUE       = 8,      /* if PMSG should be processed a little early, at Queue time */
+    DMUS_PMSGF_TOOL_ATTIME      = 0x10,   /* if PMSG should be processed at the time stamp */
+    DMUS_PMSGF_TOOL_FLUSH       = 0x20,   /* if PMSG is being flushed */
+    DMUS_PMSGF_LOCKTOREFTIME    = 0x40,   /* if rtTime can not be overriden by a tempo change. */
+    DMUS_PMSGF_DX8              = 0x80    /* if the message has DX8 or later extensions. */
+    /* The values of DMUS_TIME_RESOLVE_FLAGS may also be used inside the */
+    /* DMUS_PMSG's dwFlags member. */
+} DMUS_PMSGF_FLAGS;
+
+/* DMUS_PMSGT_TYPES fill the DMUS_PMSG's dwType member */
+typedef enum enumDMUS_PMSGT_TYPES
+{
+    DMUS_PMSGT_MIDI             = 0,      /* MIDI short message */
+    DMUS_PMSGT_NOTE             = 1,      /* Interactive Music Note */
+    DMUS_PMSGT_SYSEX            = 2,      /* MIDI long message (system exclusive message) */
+    DMUS_PMSGT_NOTIFICATION     = 3,      /* Notification message */
+    DMUS_PMSGT_TEMPO            = 4,      /* Tempo message */
+    DMUS_PMSGT_CURVE            = 5,      /* Control change / pitch bend, etc. curve */
+    DMUS_PMSGT_TIMESIG          = 6,      /* Time signature */
+    DMUS_PMSGT_PATCH            = 7,      /* Patch changes */
+    DMUS_PMSGT_TRANSPOSE        = 8,      /* Transposition messages */
+    DMUS_PMSGT_CHANNEL_PRIORITY = 9,      /* Channel priority */
+    DMUS_PMSGT_STOP             = 10,     /* Stop message */
+    DMUS_PMSGT_DIRTY            = 11,     /* Tells Tools that cache GetParam() info to refresh */
+    DMUS_PMSGT_WAVE             = 12,     /* Carries control information for playing a wave. */
+    DMUS_PMSGT_LYRIC            = 13,     /* Lyric message from lyric track. */
+    DMUS_PMSGT_SCRIPTLYRIC      = 14,     /* Lyric message sent by a script with the Trace function. */
+    DMUS_PMSGT_USER             = 255     /* User message */
+} DMUS_PMSGT_TYPES;
+
+/* DMUS_SEGF_FLAGS correspond to IDirectMusicPerformance::PlaySegment, and other API */
+typedef enum enumDMUS_SEGF_FLAGS
+{
+    DMUS_SEGF_REFTIME           = 1<<6,   /* 0x40 Time parameter is in reference time  */
+    DMUS_SEGF_SECONDARY         = 1<<7,   /* 0x80 Secondary segment */
+    DMUS_SEGF_QUEUE             = 1<<8,   /* 0x100 Queue at the end of the primary segment queue (primary only) */
+    DMUS_SEGF_CONTROL           = 1<<9,   /* 0x200 Play as a control track (secondary segments only) */
+    DMUS_SEGF_AFTERPREPARETIME  = 1<<10,  /* 0x400 Play after the prepare time (See IDirectMusicPerformance::GetPrepareTime) */
+    DMUS_SEGF_GRID              = 1<<11,  /* 0x800 Play on grid boundary */
+    DMUS_SEGF_BEAT              = 1<<12,  /* 0x1000 Play on beat boundary */
+    DMUS_SEGF_MEASURE           = 1<<13,  /* 0x2000 Play on measure boundary */
+    DMUS_SEGF_DEFAULT           = 1<<14,  /* 0x4000 Use segment's default boundary */
+    DMUS_SEGF_NOINVALIDATE      = 1<<15,  /* 0x8000 Play without invalidating the currently playing segment(s) */
+    DMUS_SEGF_ALIGN             = 1<<16,  /* 0x10000 Align segment with requested boundary, but switch at first valid point */
+    DMUS_SEGF_VALID_START_BEAT  = 1<<17,  /* 0x20000 In conjunction with DMUS_SEGF_ALIGN, allows the switch to occur on any beat. */
+    DMUS_SEGF_VALID_START_GRID  = 1<<18,  /* 0x40000 In conjunction with DMUS_SEGF_ALIGN, allows the switch to occur on any grid. */
+    DMUS_SEGF_VALID_START_TICK  = 1<<19,  /* 0x80000 In conjunction with DMUS_SEGF_ALIGN, allows the switch to occur any time. */
+    DMUS_SEGF_AUTOTRANSITION    = 1<<20,  /* 0x100000 Compose and play a transition segment, using the transition template. */
+    DMUS_SEGF_AFTERQUEUETIME    = 1<<21,  /* 0x200000 Make sure to play after the queue time. This is default for primary segments */
+    DMUS_SEGF_AFTERLATENCYTIME  = 1<<22,  /* 0x400000 Make sure to play after the latency time. This is true for all segments, so this is a nop */
+    DMUS_SEGF_SEGMENTEND        = 1<<23,  /* 0x800000 Play at the next end of segment. */
+    DMUS_SEGF_MARKER            = 1<<24,  /* 0x1000000 Play at next marker in the primary segment. If there are no markers, default to any other resolution requests. */
+    DMUS_SEGF_TIMESIG_ALWAYS    = 1<<25,  /* 0x2000000 Even if there is no primary segment, align start time with current time signature. */
+    DMUS_SEGF_USE_AUDIOPATH     = 1<<26,  /* 0x4000000 Uses the audio path that is embedded in the segment. */
+    DMUS_SEGF_VALID_START_MEASURE = 1<<27, /* 0x8000000 In conjunction with DMUS_SEGF_ALIGN, allows the switch to occur on any bar. */
+    DMUS_SEGF_INVALIDATE_PRI    = 1<<28   /* 0x10000000 invalidate only the current primary seg state */
+} DMUS_SEGF_FLAGS;
+
+#define DMUS_SEG_REPEAT_INFINITE    0xFFFFFFFF  /* For IDirectMusicSegment::SetRepeat*/
+#define DMUS_SEG_ALLTRACKS          0x80000000  /* For IDirectMusicSegment::SetParam() and SetTrackConfig() - selects all tracks instead on nth index. */
+#define DMUS_SEG_ANYTRACK           0x80000000  /* For IDirectMusicSegment::GetParam() - checks each track until it finds one that returns data (not DMUS_E_NOT_FOUND.) */
+
+
+/* DMUS_TIME_RESOLVE_FLAGS correspond to IDirectMusicPerformance::GetResolvedTime, and can */
+/* also be used interchangeably with the corresponding DMUS_SEGF_FLAGS, since their values */
+/* are intentionally the same */
+typedef enum enumDMUS_TIME_RESOLVE_FLAGS
+{
+    DMUS_TIME_RESOLVE_AFTERPREPARETIME  = DMUS_SEGF_AFTERPREPARETIME,
+    DMUS_TIME_RESOLVE_AFTERQUEUETIME    = DMUS_SEGF_AFTERQUEUETIME,
+    DMUS_TIME_RESOLVE_AFTERLATENCYTIME  = DMUS_SEGF_AFTERLATENCYTIME,
+    DMUS_TIME_RESOLVE_GRID              = DMUS_SEGF_GRID,
+    DMUS_TIME_RESOLVE_BEAT              = DMUS_SEGF_BEAT,
+    DMUS_TIME_RESOLVE_MEASURE           = DMUS_SEGF_MEASURE,
+    DMUS_TIME_RESOLVE_MARKER            = DMUS_SEGF_MARKER,
+    DMUS_TIME_RESOLVE_SEGMENTEND        = DMUS_SEGF_SEGMENTEND,
+} DMUS_TIME_RESOLVE_FLAGS;
+
+/* The following flags are sent inside the DMUS_CHORD_KEY.dwFlags parameter */
+typedef enum enumDMUS_CHORDKEYF_FLAGS
+{
+    DMUS_CHORDKEYF_SILENT            = 1,      /* is the chord silent? */
+} DMUS_CHORDKEYF_FLAGS;
+
+#define DMUS_MAXSUBCHORD 8
+
+typedef struct _DMUS_SUBCHORD
+{
+    DWORD   dwChordPattern;     /* Notes in the subchord */
+    DWORD   dwScalePattern;     /* Notes in the scale */
+    DWORD   dwInversionPoints;  /* Where inversions can occur */
+    DWORD   dwLevels;           /* Which levels are supported by this subchord */
+    BYTE    bChordRoot;         /* Root of the subchord */
+    BYTE    bScaleRoot;         /* Root of the scale */
+} DMUS_SUBCHORD;
+
+typedef struct _DMUS_CHORD_KEY
+{
+    WCHAR           wszName[16];        /* Name of the chord */
+    WORD            wMeasure;           /* Measure this falls on */
+    BYTE            bBeat;              /* Beat this falls on */
+    BYTE            bSubChordCount;     /* Number of chords in the list of subchords */
+    DMUS_SUBCHORD   SubChordList[DMUS_MAXSUBCHORD]; /* List of sub chords */
+    DWORD           dwScale;            /* Scale underlying the entire chord */
+    BYTE            bKey;               /* Key underlying the entire chord */
+    BYTE            bFlags;             /* Miscelaneous flags */
+} DMUS_CHORD_KEY;
+
+/* DMUS_NOTE_PMSG */
+typedef struct _DMUS_NOTE_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    MUSIC_TIME mtDuration;     /* duration */
+    WORD    wMusicValue;       /* Description of note in chord and key. */
+    WORD    wMeasure;          /* Measure in which this note occurs */
+    short   nOffset;           /* Offset from grid at which this note occurs */
+    BYTE    bBeat;             /* Beat (in measure) at which this note occurs */
+    BYTE    bGrid;             /* Grid offset from beat at which this note occurs */
+    BYTE    bVelocity;         /* Note velocity */
+    BYTE    bFlags;            /* see DMUS_NOTEF_FLAGS */
+    BYTE    bTimeRange;        /* Range to randomize time. */
+    BYTE    bDurRange;         /* Range to randomize duration. */
+    BYTE    bVelRange;         /* Range to randomize velocity. */
+    BYTE    bPlayModeFlags;    /* Play mode */
+    BYTE    bSubChordLevel;    /* Which subchord level this note uses.  */
+    BYTE    bMidiValue;        /* The MIDI note value, converted from wMusicValue */
+    char    cTranspose;        /* Transposition to add to midi note value after converted from wMusicValue. */
+} DMUS_NOTE_PMSG;
+
+typedef enum enumDMUS_NOTEF_FLAGS
+{
+    DMUS_NOTEF_NOTEON = 1,              /* Set if this is a MIDI Note On. Otherwise, it is MIDI Note Off */
+    /* DX8 flags: */
+    DMUS_NOTEF_NOINVALIDATE = 2,        /* Don't invalidate this note off. */
+    DMUS_NOTEF_NOINVALIDATE_INSCALE = 4,/* Don't invalidate if still within the scale. */
+    DMUS_NOTEF_NOINVALIDATE_INCHORD = 8,/* Don't invalidate if still within the chord. */
+    DMUS_NOTEF_REGENERATE = 0x10,       /* Regenerate the note on an invalidate. */
+} DMUS_NOTEF_FLAGS;
+
+/* The DMUS_PLAYMODE_FLAGS are used to determine how to convert wMusicValue
+   into the appropriate bMidiValue.
+*/
+
+typedef enum enumDMUS_PLAYMODE_FLAGS
+{
+    DMUS_PLAYMODE_KEY_ROOT          = 1,  /* Transpose on top of the key root. */
+    DMUS_PLAYMODE_CHORD_ROOT        = 2,  /* Transpose on top of the chord root. */
+    DMUS_PLAYMODE_SCALE_INTERVALS   = 4,  /* Use scale intervals from scale pattern. */
+    DMUS_PLAYMODE_CHORD_INTERVALS   = 8,  /* Use chord intervals from chord pattern. */
+    DMUS_PLAYMODE_NONE              = 16, /* No mode. Indicates the parent part's mode should be used. */
+} DMUS_PLAYMODE_FLAGS;
+
+/* The following are playback modes that can be created by combining the DMUS_PLAYMODE_FLAGS
+   in various ways:
+*/
+
+/* Fixed. wMusicValue holds final MIDI note value. This is used for drums, sound effects, and sequenced
+   notes that should not be transposed by the chord or scale.
+*/
+#define DMUS_PLAYMODE_FIXED             0
+/* In fixed to key, the musicvalue is again a fixed MIDI value, but it
+   is transposed on top of the key root.
+*/
+#define DMUS_PLAYMODE_FIXEDTOKEY        DMUS_PLAYMODE_KEY_ROOT
+/* In fixed to chord, the musicvalue is also a fixed MIDI value, but it
+   is transposed on top of the chord root.
+*/
+#define DMUS_PLAYMODE_FIXEDTOCHORD      DMUS_PLAYMODE_CHORD_ROOT
+/* In Pedalpoint, the key root is used and the notes only track the intervals in
+   the scale. The chord root and intervals are completely ignored. This is useful
+   for melodic lines that play relative to the key root.
+*/
+#define DMUS_PLAYMODE_PEDALPOINT        (DMUS_PLAYMODE_KEY_ROOT | DMUS_PLAYMODE_SCALE_INTERVALS)
+/* In the Melodic mode, the chord root is used but the notes only track the intervals in
+   the scale. The key root and chord intervals are completely ignored. This is useful
+   for melodic lines that play relative to the chord root.
+*/
+#define DMUS_PLAYMODE_MELODIC           (DMUS_PLAYMODE_CHORD_ROOT | DMUS_PLAYMODE_SCALE_INTERVALS)
+/* Normal chord mode is the prevalent playback mode.
+   The notes track the intervals in the chord, which is based on the chord root.
+   If there is a scale component to the MusicValue, the additional intervals
+   are pulled from the scale and added.
+   If the chord does not have an interval to match the chord component of
+   the MusicValue, the note is silent.
+*/
+#define DMUS_PLAYMODE_NORMALCHORD       (DMUS_PLAYMODE_CHORD_ROOT | DMUS_PLAYMODE_CHORD_INTERVALS)
+/* If it is desirable to play a note that is above the top of the chord, the
+   always play mode (known as "purpleized" in a former life) finds a position
+   for the note by using intervals from the scale. Essentially, this mode is
+   a combination of the Normal and Melodic playback modes, where a failure
+   in Normal causes a second try in Melodic mode.
+*/
+#define DMUS_PLAYMODE_ALWAYSPLAY        (DMUS_PLAYMODE_MELODIC | DMUS_PLAYMODE_NORMALCHORD)
+
+/* These playmodes are new for dx8. */
+/* In PedalpointChord, the key root is used and the notes only track the intervals in
+   the chord. The chord root and scale intervals are completely ignored. This is useful
+   for chordal lines that play relative to the key root.
+*/
+#define DMUS_PLAYMODE_PEDALPOINTCHORD   (DMUS_PLAYMODE_KEY_ROOT | DMUS_PLAYMODE_CHORD_INTERVALS)
+
+/* For completeness, here's a mode that tries for pedalpointchord, but if it fails
+   uses scale intervals
+*/
+#define DMUS_PLAYMODE_PEDALPOINTALWAYS  (DMUS_PLAYMODE_PEDALPOINT | DMUS_PLAYMODE_PEDALPOINTCHORD)
+
+
+/*  Legacy names for modes... */
+#define DMUS_PLAYMODE_PURPLEIZED        DMUS_PLAYMODE_ALWAYSPLAY
+#define DMUS_PLAYMODE_SCALE_ROOT        DMUS_PLAYMODE_KEY_ROOT
+#define DMUS_PLAYMODE_FIXEDTOSCALE      DMUS_PLAYMODE_FIXEDTOKEY
+
+
+/* DMUS_MIDI_PMSG */
+typedef struct _DMUS_MIDI_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    BYTE    bStatus;
+    BYTE    bByte1;
+    BYTE    bByte2;
+    BYTE    bPad[1];
+} DMUS_MIDI_PMSG;
+
+/* DMUS_PATCH_PMSG */
+typedef struct _DMUS_PATCH_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    BYTE    byInstrument;
+    BYTE    byMSB;
+    BYTE    byLSB;
+    BYTE    byPad[1];
+} DMUS_PATCH_PMSG;
+
+/* DMUS_TRANSPOSE_PMSG */
+typedef struct _DMUS_TRANSPOSE_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    short   nTranspose;
+    /* Following exists only under DX8 and on (check dwFlags for DMUS_PMSGF_DX8) */
+    WORD            wMergeIndex;     /* Allows multiple parameters to be merged (pitchbend, volume, and expression.)*/
+} DMUS_TRANSPOSE_PMSG;
+
+/* DMUS_CHANNEL_PRIORITY_PMSG */
+typedef struct _DMUS_CHANNEL_PRIORITY_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    DWORD   dwChannelPriority;
+} DMUS_CHANNEL_PRIORITY_PMSG;
+
+/* DMUS_TEMPO_PMSG */
+typedef struct _DMUS_TEMPO_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    double  dblTempo;                       /* the tempo */
+} DMUS_TEMPO_PMSG;
+
+#define DMUS_TEMPO_MAX          1000
+#define DMUS_TEMPO_MIN          1
+
+#define DMUS_MASTERTEMPO_MAX    100.0f
+#define DMUS_MASTERTEMPO_MIN    0.01f
+
+/* DMUS_SYSEX_PMSG */
+typedef struct _DMUS_SYSEX_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    DWORD   dwLen;          /* length of the data */
+    BYTE    abData[1];      /* array of data, length equal to dwLen */
+} DMUS_SYSEX_PMSG;
+
+/* DMUS_CURVE_PMSG */
+typedef struct _DMUS_CURVE_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    MUSIC_TIME      mtDuration;      /* how long this curve lasts */
+    MUSIC_TIME      mtOriginalStart; /* must be set to either zero when this PMSG is created or to the original mtTime of the curve */
+    MUSIC_TIME      mtResetDuration; /* how long after the curve is finished to allow a flush or
+                                        invalidation to reset to the reset value, nResetValue */
+    short           nStartValue;     /* curve's start value */
+    short           nEndValue;       /* curve's end value */
+    short           nResetValue;     /* curve's reset value, set when a flush or invalidation
+                                        occurs within mtDuration + mtResetDuration */
+    WORD            wMeasure;        /* Measure in which this curve occurs */
+    short           nOffset;         /* Offset from grid at which this curve occurs */
+    BYTE            bBeat;           /* Beat (in measure) at which this curve occurs */
+    BYTE            bGrid;           /* Grid offset from beat at which this curve occurs */
+    BYTE            bType;           /* type of curve */
+    BYTE            bCurveShape;     /* shape of curve */
+    BYTE            bCCData;         /* CC# if this is a control change type */
+    BYTE            bFlags;          /* Curve reset and start from current value flags. */
+    /* Following exists only under DX8 and on (check dwFlags for DMUS_PMSGF_DX8) */
+    WORD            wParamType;      /* RPN or NRPN parameter number. */
+    WORD            wMergeIndex;     /* Allows multiple parameters to be merged (pitchbend, volume, and expression.)*/
+} DMUS_CURVE_PMSG;
+
+typedef enum enumDMUS_CURVE_FLAGS
+{
+    DMUS_CURVE_RESET = 1,            /* When set, the nResetValue must be sent when the
+                                        time is reached or an invalidate occurs because
+                                        of a transition. If not set, the curve stays
+                                        permanently stuck at the new value. */
+    DMUS_CURVE_START_FROM_CURRENT = 2/* Ignore Start, start the curve at the current value.
+                                        This only works for volume, expression, and pitchbend. */
+} DMUS_CURVE_FLAGS;
+
+
+#define DMUS_CURVE_RESET    1
+
+/* Curve shapes */
+enum
+{
+    DMUS_CURVES_LINEAR  = 0,
+    DMUS_CURVES_INSTANT = 1,
+    DMUS_CURVES_EXP     = 2,
+    DMUS_CURVES_LOG     = 3,
+    DMUS_CURVES_SINE    = 4
+};
+/* curve types */
+#define DMUS_CURVET_PBCURVE      0x03   /* Pitch bend curve. */
+#define DMUS_CURVET_CCCURVE      0x04   /* Control change curve. */
+#define DMUS_CURVET_MATCURVE     0x05   /* Mono aftertouch curve. */
+#define DMUS_CURVET_PATCURVE     0x06   /* Poly aftertouch curve. */
+#define DMUS_CURVET_RPNCURVE     0x07   /* RPN curve with curve type in wParamType. */
+#define DMUS_CURVET_NRPNCURVE    0x08   /* NRPN curve with curve type in wParamType. */
+
+/* DMUS_TIMESIG_PMSG */
+typedef struct _DMUS_TIMESIG_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    /* Time signatures define how many beats per measure, which note receives */
+    /* the beat, and the grid resolution. */
+    BYTE    bBeatsPerMeasure;       /* beats per measure (top of time sig) */
+    BYTE    bBeat;                  /* what note receives the beat (bottom of time sig.) */
+                                    /* we can assume that 0 means 256th note */
+    WORD    wGridsPerBeat;          /* grids per beat */
+} DMUS_TIMESIG_PMSG;
+
+
+
+/* notification type values */
+/* The following correspond to GUID_NOTIFICATION_SEGMENT */
+#define DMUS_NOTIFICATION_SEGSTART       0
+#define DMUS_NOTIFICATION_SEGEND         1
+#define DMUS_NOTIFICATION_SEGALMOSTEND   2
+#define DMUS_NOTIFICATION_SEGLOOP        3
+#define DMUS_NOTIFICATION_SEGABORT       4
+/* The following correspond to GUID_NOTIFICATION_PERFORMANCE */
+#define DMUS_NOTIFICATION_MUSICSTARTED   0
+#define DMUS_NOTIFICATION_MUSICSTOPPED   1
+#define DMUS_NOTIFICATION_MUSICALMOSTEND 2
+/* The following corresponds to GUID_NOTIFICATION_MEASUREANDBEAT */
+#define DMUS_NOTIFICATION_MEASUREBEAT    0
+/* The following corresponds to GUID_NOTIFICATION_CHORD */
+#define DMUS_NOTIFICATION_CHORD          0
+/* The following correspond to GUID_NOTIFICATION_COMMAND */
+#define DMUS_NOTIFICATION_GROOVE         0
+#define DMUS_NOTIFICATION_EMBELLISHMENT  1
+/* The following corresponds to GUID_NOTIFICATION_RECOMPOSE */
+#define DMUS_NOTIFICATION_RECOMPOSE          0
+
+/* DMUS_NOTIFICATION_PMSG */
+typedef struct _DMUS_NOTIFICATION_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    GUID    guidNotificationType;
+    DWORD   dwNotificationOption;
+    DWORD   dwField1;
+    DWORD   dwField2;
+} DMUS_NOTIFICATION_PMSG;
+
+/* DMUS_WAVE_PMSG */
+typedef struct _DMUS_WAVE_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    REFERENCE_TIME rtStartOffset;   /* How far into the wave to start, in reference time units only. */
+    REFERENCE_TIME rtDuration;      /* Duration of the wave, in either reference time or music time. */
+    long    lOffset;                /* Offset from actual time to logical time, in music or ref time. */
+    long    lVolume;		        /* Initial volume, in 100ths of a dB. */
+    long    lPitch;			        /* Initial pitch, in 100ths of a semitone. */
+    BYTE    bFlags;                 /* Flags, including DMUS_WAVEF_OFF... */
+} DMUS_WAVE_PMSG;
+
+#define DMUS_WAVEF_OFF           1       /* If wave is playing and this is the off message. */
+#define DMUS_WAVEF_STREAMING     2       /* If wave is streaming. */
+#define DMUS_WAVEF_NOINVALIDATE  4       /* Don't invalidate this wave. */
+#define DMUS_WAVEF_NOPREROLL     8       /* Don't preroll any wave data. */
+#define DMUS_WAVEF_IGNORELOOPS   0x20    /* Ignore segment looping. */
+
+/* DMUS_LYRIC_PMSG */
+typedef struct _DMUS_LYRIC_PMSG
+{
+    /* begin DMUS_PMSG_PART */
+    DMUS_PMSG_PART
+    /* end DMUS_PMSG_PART */
+
+    WCHAR    wszString[1];      /* null-terminated Unicode lyric string (structure is actually larger than size 1) */
+} DMUS_LYRIC_PMSG;
+
+#define DMUS_MAX_NAME           64         /* Maximum object name length. */
+#define DMUS_MAX_CATEGORY       64         /* Maximum object category name length. */
+#define DMUS_MAX_FILENAME       MAX_PATH
+
+typedef struct _DMUS_VERSION {
+  DWORD    dwVersionMS;
+  DWORD    dwVersionLS;
+}DMUS_VERSION, FAR *LPDMUS_VERSION;
+
+/* Time Signature structure, used by IDirectMusicStyle */
+/* Also used as a parameter for GetParam() and SetParam */
+typedef struct _DMUS_TIMESIGNATURE
+{
+    MUSIC_TIME mtTime;
+    BYTE    bBeatsPerMeasure;       /* beats per measure (top of time sig) */
+    BYTE    bBeat;                  /* what note receives the beat (bottom of time sig.) */
+                                    /* we can assume that 0 means 256th note */
+    WORD    wGridsPerBeat;          /* grids per beat */
+} DMUS_TIMESIGNATURE;
+
+typedef struct _DMUS_VALID_START_PARAM
+{
+    MUSIC_TIME mtTime;                      /* Time of the first legal start
+                                               point after (or including) the requested time.
+                                               This is a returned value.
+                                               Time format is the relative offset from requested time. */
+} DMUS_VALID_START_PARAM;
+
+typedef struct _DMUS_PLAY_MARKER_PARAM
+{
+    MUSIC_TIME mtTime;                      /* Time of the first legal segment play
+                                               marker before (or including) the requested time.
+                                               This is a returned value.
+                                               Time format is the relative offset from requested time. */
+} DMUS_PLAY_MARKER_PARAM;
+
+/*      The DMUSOBJECTDESC structure is used to communicate everything you could */
+/*      possibly use to describe a DirectMusic object.  */
+
+typedef struct _DMUS_OBJECTDESC
+{
+    DWORD          dwSize;                 /* Size of this structure. */
+    DWORD          dwValidData;            /* Flags indicating which fields below are valid. */
+    GUID           guidObject;             /* Unique ID for this object. */
+    GUID           guidClass;              /* GUID for the class of object. */
+    FILETIME       ftDate;                 /* Last edited date of object. */
+    DMUS_VERSION   vVersion;               /* Version. */
+    WCHAR          wszName[DMUS_MAX_NAME]; /* Name of object. */
+    WCHAR          wszCategory[DMUS_MAX_CATEGORY]; /* Category for object (optional). */
+    WCHAR          wszFileName[DMUS_MAX_FILENAME]; /* File path. */
+    LONGLONG       llMemLength;            /* Size of Memory data. */
+    LPBYTE         pbMemData;              /* Memory pointer for data. */
+    IStream *      pStream;                /* Stream with data. */
+} DMUS_OBJECTDESC;
+
+typedef DMUS_OBJECTDESC *LPDMUS_OBJECTDESC;
+
+/*      Flags for dwValidData. When set, a flag indicates that the  */
+/*      corresponding field in DMUSOBJECTDESC holds valid data. */
+
+#define DMUS_OBJ_OBJECT         (1 << 0)     /* Object GUID is valid. */
+#define DMUS_OBJ_CLASS          (1 << 1)     /* Class GUID is valid. */
+#define DMUS_OBJ_NAME           (1 << 2)     /* Name is valid. */
+#define DMUS_OBJ_CATEGORY       (1 << 3)     /* Category is valid. */
+#define DMUS_OBJ_FILENAME       (1 << 4)     /* File path is valid. */
+#define DMUS_OBJ_FULLPATH       (1 << 5)     /* Path is full path. */
+#define DMUS_OBJ_URL            (1 << 6)     /* Path is URL. */
+#define DMUS_OBJ_VERSION        (1 << 7)     /* Version is valid. */
+#define DMUS_OBJ_DATE           (1 << 8)     /* Date is valid. */
+#define DMUS_OBJ_LOADED         (1 << 9)     /* Object is currently loaded in memory. */
+#define DMUS_OBJ_MEMORY         (1 << 10)    /* Object is pointed to by pbMemData. */
+#define DMUS_OBJ_STREAM         (1 << 11)    /* Object is stored in pStream. */
+
+/*      The DMUS_SCRIPT_ERRORINFO structure describes an error that occurred in a script.
+        It is returned by methods in IDirectMusicScript. */
+typedef struct _DMUS_SCRIPT_ERRORINFO
+{
+    DWORD dwSize; /* Size of this structure. */
+    HRESULT hr;
+    ULONG ulLineNumber;
+    LONG ichCharPosition;
+    WCHAR wszSourceFile[DMUS_MAX_FILENAME];
+    WCHAR wszSourceComponent[DMUS_MAX_FILENAME];
+    WCHAR wszDescription[DMUS_MAX_FILENAME];
+    WCHAR wszSourceLineText[DMUS_MAX_FILENAME];
+} DMUS_SCRIPT_ERRORINFO;
+
+/*  Track configuration flags, used with IDirectMusicSegment8::SetTrackConfig() */
+
+#define DMUS_TRACKCONFIG_OVERRIDE_ALL           1	  /* This track should get parameters from this segment before controlling and primary tracks. */
+#define DMUS_TRACKCONFIG_OVERRIDE_PRIMARY       2	  /* This track should get parameters from this segment before the primary segment tracks. */
+#define DMUS_TRACKCONFIG_FALLBACK               4  	  /* This track should get parameters from this segment if the primary and controlling segments don't succeed. */
+#define DMUS_TRACKCONFIG_CONTROL_ENABLED        8     /* GetParam() enabled for this track. */
+#define DMUS_TRACKCONFIG_PLAY_ENABLED           0x10  /* Play() enabled for this track. */
+#define DMUS_TRACKCONFIG_NOTIFICATION_ENABLED	0x20  /* Notifications enabled for this track. */
+#define DMUS_TRACKCONFIG_PLAY_CLOCKTIME         0x40  /* This track plays in Timer time, not music time. */
+#define DMUS_TRACKCONFIG_PLAY_COMPOSE 	        0x80  /* This track should regenerate data each time it starts playing. */
+#define DMUS_TRACKCONFIG_LOOP_COMPOSE           0x100 /* This track should regenerate data each time it repeats. */
+#define DMUS_TRACKCONFIG_COMPOSING              0x200 /* This track is used to compose other tracks. */
+#define DMUS_TRACKCONFIG_CONTROL_PLAY           0x10000 /* This track, when played in a controlling segment, overrides playback of primary segment tracks. */
+#define DMUS_TRACKCONFIG_CONTROL_NOTIFICATION   0x20000 /* This track, when played in a controlling segment, overrides notification of primary segment tracks. */
+/* Additional track config flags for composing transitions */
+#define DMUS_TRACKCONFIG_TRANS1_FROMSEGSTART    0x400  /* Get track info from start of From segment */
+#define DMUS_TRACKCONFIG_TRANS1_FROMSEGCURRENT  0x800  /* Get track info from current place in From segment */
+#define DMUS_TRACKCONFIG_TRANS1_TOSEGSTART      0x1000 /* Get track info from start of To segment */
+#define DMUS_TRACKCONFIG_DEFAULT    (DMUS_TRACKCONFIG_CONTROL_ENABLED | DMUS_TRACKCONFIG_PLAY_ENABLED | DMUS_TRACKCONFIG_NOTIFICATION_ENABLED)
+
+/* Get/SetParam structs for commands */
+/* PARAM structures, used by GetParam() and SetParam() */
+typedef struct _DMUS_COMMAND_PARAM
+{
+    BYTE bCommand;
+    BYTE bGrooveLevel;
+    BYTE bGrooveRange;
+    BYTE bRepeatMode;
+} DMUS_COMMAND_PARAM;
+
+typedef struct _DMUS_COMMAND_PARAM_2
+{
+	MUSIC_TIME mtTime;
+    BYTE bCommand;
+    BYTE bGrooveLevel;
+    BYTE bGrooveRange;
+    BYTE bRepeatMode;
+} DMUS_COMMAND_PARAM_2;
+
+typedef IDirectMusicObject __RPC_FAR *LPDMUS_OBJECT;
+typedef IDirectMusicLoader __RPC_FAR *LPDMUS_LOADER;
+typedef IDirectMusicBand __RPC_FAR *LPDMUS_BAND;
+
+#define DMUSB_LOADED    (1 << 0)        /* Set when band has been loaded */
+#define DMUSB_DEFAULT   (1 << 1)        /* Set when band is default band for a style */
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicBand */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicBand
+DECLARE_INTERFACE_(IDirectMusicBand, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicBand */
+    STDMETHOD(CreateSegment)        (THIS_ IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(Download)             (THIS_ IDirectMusicPerformance* pPerformance) PURE;
+    STDMETHOD(Unload)               (THIS_ IDirectMusicPerformance* pPerformance) PURE;
+};
+
+typedef IDirectMusicBand IDirectMusicBand8;
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicObject */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicObject
+DECLARE_INTERFACE_(IDirectMusicObject, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicObject */
+    STDMETHOD(GetDescriptor)        (THIS_ LPDMUS_OBJECTDESC pDesc) PURE;
+    STDMETHOD(SetDescriptor)        (THIS_ LPDMUS_OBJECTDESC pDesc) PURE;
+    STDMETHOD(ParseDescriptor)      (THIS_ LPSTREAM pStream,
+                                           LPDMUS_OBJECTDESC pDesc) PURE;
+};
+
+typedef IDirectMusicObject IDirectMusicObject8;
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicLoader */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicLoader
+DECLARE_INTERFACE_(IDirectMusicLoader, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicLoader */
+    STDMETHOD(GetObject)            (THIS_ LPDMUS_OBJECTDESC pDesc,
+                                           REFIID riid,
+                                           LPVOID FAR *ppv) PURE;
+    STDMETHOD(SetObject)            (THIS_ LPDMUS_OBJECTDESC pDesc) PURE;
+    STDMETHOD(SetSearchDirectory)   (THIS_ REFGUID rguidClass,
+                                           WCHAR *pwzPath,
+                                           BOOL fClear) PURE;
+    STDMETHOD(ScanDirectory)        (THIS_ REFGUID rguidClass,
+                                           WCHAR *pwzFileExtension,
+                                           WCHAR *pwzScanFileName) PURE;
+    STDMETHOD(CacheObject)          (THIS_ IDirectMusicObject * pObject) PURE;
+    STDMETHOD(ReleaseObject)        (THIS_ IDirectMusicObject * pObject) PURE;
+    STDMETHOD(ClearCache)           (THIS_ REFGUID rguidClass) PURE;
+    STDMETHOD(EnableCache)          (THIS_ REFGUID rguidClass,
+                                           BOOL fEnable) PURE;
+    STDMETHOD(EnumObject)           (THIS_ REFGUID rguidClass,
+                                           DWORD dwIndex,
+                                           LPDMUS_OBJECTDESC pDesc) PURE;
+};
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicLoader8 */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicLoader8
+DECLARE_INTERFACE_(IDirectMusicLoader8, IDirectMusicLoader)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicLoader */
+    STDMETHOD(GetObject)            (THIS_ LPDMUS_OBJECTDESC pDesc,
+                                           REFIID riid,
+                                           LPVOID FAR *ppv) PURE;
+    STDMETHOD(SetObject)            (THIS_ LPDMUS_OBJECTDESC pDesc) PURE;
+    STDMETHOD(SetSearchDirectory)   (THIS_ REFGUID rguidClass,
+                                           WCHAR *pwzPath,
+                                           BOOL fClear) PURE;
+    STDMETHOD(ScanDirectory)        (THIS_ REFGUID rguidClass,
+                                           WCHAR *pwzFileExtension,
+                                           WCHAR *pwzScanFileName) PURE;
+    STDMETHOD(CacheObject)          (THIS_ IDirectMusicObject * pObject) PURE;
+    STDMETHOD(ReleaseObject)        (THIS_ IDirectMusicObject * pObject) PURE;
+    STDMETHOD(ClearCache)           (THIS_ REFGUID rguidClass) PURE;
+    STDMETHOD(EnableCache)          (THIS_ REFGUID rguidClass,
+                                           BOOL fEnable) PURE;
+    STDMETHOD(EnumObject)           (THIS_ REFGUID rguidClass,
+                                           DWORD dwIndex,
+                                           LPDMUS_OBJECTDESC pDesc) PURE;
+
+    /* IDirectMusicLoader8 */
+    STDMETHOD_(void, CollectGarbage)                (THIS) PURE;
+    STDMETHOD(ReleaseObjectByUnknown)               (THIS_ IUnknown *pObject) PURE;
+    STDMETHOD(LoadObjectFromFile)                   (THIS_ REFGUID rguidClassID,
+                                                           REFIID iidInterfaceID,
+                                                           WCHAR *pwzFilePath,
+                                                           void ** ppObject) PURE;
+};
+
+/*  Stream object supports IDirectMusicGetLoader interface to access loader while file parsing. */
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicGetLoader
+DECLARE_INTERFACE_(IDirectMusicGetLoader, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicGetLoader */
+    STDMETHOD(GetLoader)            (THIS_ IDirectMusicLoader ** ppLoader) PURE;
+};
+
+typedef IDirectMusicGetLoader IDirectMusicGetLoader8;
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicSegment */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicSegment
+DECLARE_INTERFACE_(IDirectMusicSegment, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicSegment */
+    STDMETHOD(GetLength)                (THIS_ MUSIC_TIME* pmtLength) PURE;
+    STDMETHOD(SetLength)                (THIS_ MUSIC_TIME mtLength) PURE;
+    STDMETHOD(GetRepeats)               (THIS_ DWORD* pdwRepeats) PURE;
+    STDMETHOD(SetRepeats)               (THIS_ DWORD  dwRepeats) PURE;
+    STDMETHOD(GetDefaultResolution)     (THIS_ DWORD* pdwResolution) PURE;
+    STDMETHOD(SetDefaultResolution)     (THIS_ DWORD  dwResolution) PURE;
+    STDMETHOD(GetTrack)                 (THIS_ REFGUID rguidType,
+                                               DWORD dwGroupBits,
+                                               DWORD dwIndex,
+                                               IDirectMusicTrack** ppTrack) PURE;
+    STDMETHOD(GetTrackGroup)            (THIS_ IDirectMusicTrack* pTrack,
+                                               DWORD* pdwGroupBits) PURE;
+    STDMETHOD(InsertTrack)              (THIS_ IDirectMusicTrack* pTrack,
+                                               DWORD dwGroupBits) PURE;
+    STDMETHOD(RemoveTrack)              (THIS_ IDirectMusicTrack* pTrack) PURE;
+    STDMETHOD(InitPlay)                 (THIS_ IDirectMusicSegmentState** ppSegState,
+                                               IDirectMusicPerformance* pPerformance,
+                                               DWORD dwFlags) PURE;
+    STDMETHOD(GetGraph)                 (THIS_ IDirectMusicGraph** ppGraph) PURE;
+    STDMETHOD(SetGraph)                 (THIS_ IDirectMusicGraph* pGraph) PURE;
+    STDMETHOD(AddNotificationType)      (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(RemoveNotificationType)   (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(GetParam)                 (THIS_ REFGUID rguidType,
+                                               DWORD dwGroupBits,
+                                               DWORD dwIndex,
+                                               MUSIC_TIME mtTime,
+                                               MUSIC_TIME* pmtNext,
+                                               void* pParam) PURE;
+    STDMETHOD(SetParam)                 (THIS_ REFGUID rguidType,
+                                               DWORD dwGroupBits,
+                                               DWORD dwIndex,
+                                               MUSIC_TIME mtTime,
+                                               void* pParam) PURE;
+    STDMETHOD(Clone)                    (THIS_ MUSIC_TIME mtStart,
+                                               MUSIC_TIME mtEnd,
+                                               IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(SetStartPoint)            (THIS_ MUSIC_TIME mtStart) PURE;
+    STDMETHOD(GetStartPoint)            (THIS_ MUSIC_TIME* pmtStart) PURE;
+    STDMETHOD(SetLoopPoints)            (THIS_ MUSIC_TIME mtStart,
+                                               MUSIC_TIME mtEnd) PURE;
+    STDMETHOD(GetLoopPoints)            (THIS_ MUSIC_TIME* pmtStart,
+                                               MUSIC_TIME* pmtEnd) PURE;
+    STDMETHOD(SetPChannelsUsed)         (THIS_ DWORD dwNumPChannels,
+                                               DWORD* paPChannels) PURE;
+};
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicSegment8 */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicSegment8
+DECLARE_INTERFACE_(IDirectMusicSegment8, IDirectMusicSegment)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicSegment */
+    STDMETHOD(GetLength)                (THIS_ MUSIC_TIME* pmtLength) PURE;
+    STDMETHOD(SetLength)                (THIS_ MUSIC_TIME mtLength) PURE;
+    STDMETHOD(GetRepeats)               (THIS_ DWORD* pdwRepeats) PURE;
+    STDMETHOD(SetRepeats)               (THIS_ DWORD  dwRepeats) PURE;
+    STDMETHOD(GetDefaultResolution)     (THIS_ DWORD* pdwResolution) PURE;
+    STDMETHOD(SetDefaultResolution)     (THIS_ DWORD  dwResolution) PURE;
+    STDMETHOD(GetTrack)                 (THIS_ REFGUID rguidType,
+                                               DWORD dwGroupBits,
+                                               DWORD dwIndex,
+                                               IDirectMusicTrack** ppTrack) PURE;
+    STDMETHOD(GetTrackGroup)            (THIS_ IDirectMusicTrack* pTrack,
+                                               DWORD* pdwGroupBits) PURE;
+    STDMETHOD(InsertTrack)              (THIS_ IDirectMusicTrack* pTrack,
+                                               DWORD dwGroupBits) PURE;
+    STDMETHOD(RemoveTrack)              (THIS_ IDirectMusicTrack* pTrack) PURE;
+    STDMETHOD(InitPlay)                 (THIS_ IDirectMusicSegmentState** ppSegState,
+                                               IDirectMusicPerformance* pPerformance,
+                                               DWORD dwFlags) PURE;
+    STDMETHOD(GetGraph)                 (THIS_ IDirectMusicGraph** ppGraph) PURE;
+    STDMETHOD(SetGraph)                 (THIS_ IDirectMusicGraph* pGraph) PURE;
+    STDMETHOD(AddNotificationType)      (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(RemoveNotificationType)   (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(GetParam)                 (THIS_ REFGUID rguidType,
+                                               DWORD dwGroupBits,
+                                               DWORD dwIndex,
+                                               MUSIC_TIME mtTime,
+                                               MUSIC_TIME* pmtNext,
+                                               void* pParam) PURE;
+    STDMETHOD(SetParam)                 (THIS_ REFGUID rguidType,
+                                               DWORD dwGroupBits,
+                                               DWORD dwIndex,
+                                               MUSIC_TIME mtTime,
+                                               void* pParam) PURE;
+    STDMETHOD(Clone)                    (THIS_ MUSIC_TIME mtStart,
+                                               MUSIC_TIME mtEnd,
+                                               IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(SetStartPoint)            (THIS_ MUSIC_TIME mtStart) PURE;
+    STDMETHOD(GetStartPoint)            (THIS_ MUSIC_TIME* pmtStart) PURE;
+    STDMETHOD(SetLoopPoints)            (THIS_ MUSIC_TIME mtStart,
+                                               MUSIC_TIME mtEnd) PURE;
+    STDMETHOD(GetLoopPoints)            (THIS_ MUSIC_TIME* pmtStart,
+                                               MUSIC_TIME* pmtEnd) PURE;
+    STDMETHOD(SetPChannelsUsed)         (THIS_ DWORD dwNumPChannels,
+                                               DWORD* paPChannels) PURE;
+    /*  IDirectMusicSegment8 */
+    STDMETHOD(SetTrackConfig)           (THIS_ REFGUID rguidTrackClassID,   /* Class ID of the type of track on which to set the configuration flags. */
+                                               DWORD dwGroupBits,           /* Group bits. */
+                                               DWORD dwIndex,               /* Nth track (or DMUS_SEG_ALLTRACKS) that matches class id and group id. */
+                                               DWORD dwFlagsOn,             /* DMUS_TRACKCONFIG_ flags to enable. */
+                                               DWORD dwFlagsOff) PURE;      /* DMUS_TRACKCONFIG_ flags to disable. */
+    STDMETHOD(GetAudioPathConfig)       (THIS_ IUnknown ** ppAudioPathConfig) PURE;
+    STDMETHOD(Compose)                  (THIS_ MUSIC_TIME mtTime,
+                                               IDirectMusicSegment* pFromSegment,
+                                               IDirectMusicSegment* pToSegment,
+                                               IDirectMusicSegment** ppComposedSegment) PURE;
+    STDMETHOD(Download)                 (THIS_ IUnknown *pAudioPath) PURE;
+    STDMETHOD(Unload)                   (THIS_ IUnknown *pAudioPath) PURE;
+};
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicSegmentState */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicSegmentState
+DECLARE_INTERFACE_(IDirectMusicSegmentState, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicSegmentState */
+    STDMETHOD(GetRepeats)           (THIS_ DWORD* pdwRepeats) PURE;
+    STDMETHOD(GetSegment )          (THIS_ IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(GetStartTime)         (THIS_ MUSIC_TIME* pmtStart) PURE;
+    STDMETHOD(GetSeek)              (THIS_ MUSIC_TIME* pmtSeek) PURE;
+    STDMETHOD(GetStartPoint)        (THIS_ MUSIC_TIME* pmtStart) PURE;
+};
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicSegmentState8 */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicSegmentState8
+DECLARE_INTERFACE_(IDirectMusicSegmentState8, IDirectMusicSegmentState)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicSegmentState */
+    STDMETHOD(GetRepeats)           (THIS_ DWORD* pdwRepeats) PURE;
+    STDMETHOD(GetSegment )          (THIS_ IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(GetStartTime)         (THIS_ MUSIC_TIME* pmtStart) PURE;
+    STDMETHOD(GetSeek)              (THIS_ MUSIC_TIME* pmtSeek) PURE;
+    STDMETHOD(GetStartPoint)        (THIS_ MUSIC_TIME* pmtStart) PURE;
+
+    /* IDirectMusicSegmentState8 */
+    STDMETHOD(SetTrackConfig)       (THIS_ REFGUID rguidTrackClassID,   /* Class ID of the type of track on which to set the configuration flags. */
+                                           DWORD dwGroupBits,           /* Group bits. */
+                                           DWORD dwIndex,               /* Nth track (or DMUS_SEG_ALLTRACKS) that matches class id and group id. */
+                                           DWORD dwFlagsOn,             /* DMUS_TRACKCONFIG_ flags to enable. */
+                                           DWORD dwFlagsOff) PURE;      /* DMUS_TRACKCONFIG_ flags to disable. */
+    STDMETHOD(GetObjectInPath)      (THIS_ DWORD dwPChannel,    /* PChannel to search. */
+                                           DWORD dwStage,       /* Which stage in the path. */
+                                           DWORD dwBuffer,      /* Which buffer to address, if more than one. */
+                                           REFGUID guidObject,  /* ClassID of object. */
+                                           DWORD dwIndex,       /* Which object of that class. */
+                                           REFGUID iidInterface,/* Requested COM interface. */
+                                           void ** ppObject) PURE; /* Pointer to interface. */
+};
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicAudioPath */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicAudioPath
+DECLARE_INTERFACE_(IDirectMusicAudioPath, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicAudioPath */
+    STDMETHOD(GetObjectInPath)      (THIS_ DWORD dwPChannel,    /* PChannel to search. */
+                                           DWORD dwStage,       /* Which stage in the path. */
+                                           DWORD dwBuffer,      /* Which buffer to address, if more than one. */
+                                           REFGUID guidObject,  /* ClassID of object. */
+                                           DWORD dwIndex,       /* Which object of that class. */
+                                           REFGUID iidInterface,/* Requested COM interface. */
+                                           void ** ppObject) PURE; /* Pointer to interface. */
+    STDMETHOD(Activate)             (THIS_ BOOL fActivate) PURE;/* True to activate, False to deactivate. */
+    STDMETHOD(SetVolume)            (THIS_ long lVolume,        /* Gain, in 100ths of a dB. This must be negative (0 represents full volume.) */
+                                           DWORD dwDuration) PURE;/* Duration of volume ramp in  milliseconds. Note that 0 is more efficient. */
+    STDMETHOD(ConvertPChannel)      (THIS_ DWORD dwPChannelIn,   /* Pchannel of source. */
+                                           DWORD *pdwPChannelOut) PURE; /* Equivalent pchannel on performance. */
+};
+
+typedef IDirectMusicAudioPath IDirectMusicAudioPath8;
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicPerformance */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicPerformance
+DECLARE_INTERFACE_(IDirectMusicPerformance, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicPerformance */
+    STDMETHOD(Init)                 (THIS_ IDirectMusic** ppDirectMusic,
+                                           LPDIRECTSOUND pDirectSound,
+                                           HWND hWnd) PURE;
+    STDMETHOD(PlaySegment)          (THIS_ IDirectMusicSegment* pSegment,
+                                           DWORD dwFlags,
+                                           __int64 i64StartTime,
+                                           IDirectMusicSegmentState** ppSegmentState) PURE;
+    STDMETHOD(Stop)                 (THIS_ IDirectMusicSegment* pSegment,
+                                           IDirectMusicSegmentState* pSegmentState,
+                                           MUSIC_TIME mtTime,
+                                           DWORD dwFlags) PURE;
+    STDMETHOD(GetSegmentState)      (THIS_ IDirectMusicSegmentState** ppSegmentState,
+                                           MUSIC_TIME mtTime) PURE;
+    STDMETHOD(SetPrepareTime)       (THIS_ DWORD dwMilliSeconds) PURE;
+    STDMETHOD(GetPrepareTime)       (THIS_ DWORD* pdwMilliSeconds) PURE;
+    STDMETHOD(SetBumperLength)      (THIS_ DWORD dwMilliSeconds) PURE;
+    STDMETHOD(GetBumperLength)      (THIS_ DWORD* pdwMilliSeconds) PURE;
+    STDMETHOD(SendPMsg)             (THIS_ DMUS_PMSG* pPMSG) PURE;
+    STDMETHOD(MusicToReferenceTime) (THIS_ MUSIC_TIME mtTime,
+                                           REFERENCE_TIME* prtTime) PURE;
+    STDMETHOD(ReferenceToMusicTime) (THIS_ REFERENCE_TIME rtTime,
+                                           MUSIC_TIME* pmtTime) PURE;
+    STDMETHOD(IsPlaying)            (THIS_ IDirectMusicSegment* pSegment,
+                                           IDirectMusicSegmentState* pSegState) PURE;
+    STDMETHOD(GetTime)              (THIS_ REFERENCE_TIME* prtNow,
+                                           MUSIC_TIME* pmtNow) PURE;
+    STDMETHOD(AllocPMsg)            (THIS_ ULONG cb,
+                                           DMUS_PMSG** ppPMSG) PURE;
+    STDMETHOD(FreePMsg)             (THIS_ DMUS_PMSG* pPMSG) PURE;
+    STDMETHOD(GetGraph)             (THIS_ IDirectMusicGraph** ppGraph) PURE;
+    STDMETHOD(SetGraph)             (THIS_ IDirectMusicGraph* pGraph) PURE;
+    STDMETHOD(SetNotificationHandle)(THIS_ HANDLE hNotification,
+                                           REFERENCE_TIME rtMinimum) PURE;
+    STDMETHOD(GetNotificationPMsg)  (THIS_ DMUS_NOTIFICATION_PMSG** ppNotificationPMsg) PURE;
+    STDMETHOD(AddNotificationType)  (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(RemoveNotificationType)(THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(AddPort)              (THIS_ IDirectMusicPort* pPort) PURE;
+    STDMETHOD(RemovePort)           (THIS_ IDirectMusicPort* pPort ) PURE;
+    STDMETHOD(AssignPChannelBlock)  (THIS_ DWORD dwBlockNum,
+                                           IDirectMusicPort* pPort,
+                                           DWORD dwGroup ) PURE;
+    STDMETHOD(AssignPChannel)       (THIS_ DWORD dwPChannel,
+                                           IDirectMusicPort* pPort,
+                                           DWORD dwGroup,
+                                           DWORD dwMChannel ) PURE;
+    STDMETHOD(PChannelInfo)         (THIS_ DWORD dwPChannel,
+                                           IDirectMusicPort** ppPort,
+                                           DWORD* pdwGroup,
+                                           DWORD* pdwMChannel ) PURE;
+    STDMETHOD(DownloadInstrument)   (THIS_ IDirectMusicInstrument* pInst,
+                                           DWORD dwPChannel,
+                                           IDirectMusicDownloadedInstrument** ppDownInst,
+                                           DMUS_NOTERANGE* pNoteRanges,
+                                           DWORD dwNumNoteRanges,
+                                           IDirectMusicPort** ppPort,
+                                           DWORD* pdwGroup,
+                                           DWORD* pdwMChannel ) PURE;
+    STDMETHOD(Invalidate)           (THIS_ MUSIC_TIME mtTime,
+                                           DWORD dwFlags) PURE;
+    STDMETHOD(GetParam)             (THIS_ REFGUID rguidType,
+                                           DWORD dwGroupBits,
+                                           DWORD dwIndex,
+                                           MUSIC_TIME mtTime,
+                                           MUSIC_TIME* pmtNext,
+                                           void* pParam) PURE;
+    STDMETHOD(SetParam)             (THIS_ REFGUID rguidType,
+                                           DWORD dwGroupBits,
+                                           DWORD dwIndex,
+                                           MUSIC_TIME mtTime,
+                                           void* pParam) PURE;
+    STDMETHOD(GetGlobalParam)       (THIS_ REFGUID rguidType,
+                                           void* pParam,
+                                           DWORD dwSize) PURE;
+    STDMETHOD(SetGlobalParam)       (THIS_ REFGUID rguidType,
+                                           void* pParam,
+                                           DWORD dwSize) PURE;
+    STDMETHOD(GetLatencyTime)       (THIS_ REFERENCE_TIME* prtTime) PURE;
+    STDMETHOD(GetQueueTime)         (THIS_ REFERENCE_TIME* prtTime) PURE;
+    STDMETHOD(AdjustTime)           (THIS_ REFERENCE_TIME rtAmount) PURE;
+    STDMETHOD(CloseDown)            (THIS) PURE;
+    STDMETHOD(GetResolvedTime)      (THIS_ REFERENCE_TIME rtTime,
+                                           REFERENCE_TIME* prtResolved,
+                                           DWORD dwTimeResolveFlags) PURE;
+    STDMETHOD(MIDIToMusic)          (THIS_ BYTE bMIDIValue,
+                                           DMUS_CHORD_KEY* pChord,
+                                           BYTE bPlayMode,
+                                           BYTE bChordLevel,
+                                           WORD *pwMusicValue) PURE;
+    STDMETHOD(MusicToMIDI)          (THIS_ WORD wMusicValue,
+                                           DMUS_CHORD_KEY* pChord,
+                                           BYTE bPlayMode,
+                                           BYTE bChordLevel,
+                                           BYTE *pbMIDIValue) PURE;
+    STDMETHOD(TimeToRhythm)         (THIS_ MUSIC_TIME mtTime,
+                                           DMUS_TIMESIGNATURE *pTimeSig,
+                                           WORD *pwMeasure,
+                                           BYTE *pbBeat,
+                                           BYTE *pbGrid,
+                                           short *pnOffset) PURE;
+    STDMETHOD(RhythmToTime)         (THIS_ WORD wMeasure,
+                                           BYTE bBeat,
+                                           BYTE bGrid,
+                                           short nOffset,
+                                           DMUS_TIMESIGNATURE *pTimeSig,
+                                           MUSIC_TIME *pmtTime) PURE;
+};
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicPerformance8 */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicPerformance8
+DECLARE_INTERFACE_(IDirectMusicPerformance8, IDirectMusicPerformance)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicPerformance */
+    STDMETHOD(Init)                 (THIS_ IDirectMusic** ppDirectMusic,
+                                           LPDIRECTSOUND pDirectSound,
+                                           HWND hWnd) PURE;
+    STDMETHOD(PlaySegment)          (THIS_ IDirectMusicSegment* pSegment,
+                                           DWORD dwFlags,
+                                           __int64 i64StartTime,
+                                           IDirectMusicSegmentState** ppSegmentState) PURE;
+    STDMETHOD(Stop)                 (THIS_ IDirectMusicSegment* pSegment,
+                                           IDirectMusicSegmentState* pSegmentState,
+                                           MUSIC_TIME mtTime,
+                                           DWORD dwFlags) PURE;
+    STDMETHOD(GetSegmentState)      (THIS_ IDirectMusicSegmentState** ppSegmentState,
+                                           MUSIC_TIME mtTime) PURE;
+    STDMETHOD(SetPrepareTime)       (THIS_ DWORD dwMilliSeconds) PURE;
+    STDMETHOD(GetPrepareTime)       (THIS_ DWORD* pdwMilliSeconds) PURE;
+    STDMETHOD(SetBumperLength)      (THIS_ DWORD dwMilliSeconds) PURE;
+    STDMETHOD(GetBumperLength)      (THIS_ DWORD* pdwMilliSeconds) PURE;
+    STDMETHOD(SendPMsg)             (THIS_ DMUS_PMSG* pPMSG) PURE;
+    STDMETHOD(MusicToReferenceTime) (THIS_ MUSIC_TIME mtTime,
+                                           REFERENCE_TIME* prtTime) PURE;
+    STDMETHOD(ReferenceToMusicTime) (THIS_ REFERENCE_TIME rtTime,
+                                           MUSIC_TIME* pmtTime) PURE;
+    STDMETHOD(IsPlaying)            (THIS_ IDirectMusicSegment* pSegment,
+                                           IDirectMusicSegmentState* pSegState) PURE;
+    STDMETHOD(GetTime)              (THIS_ REFERENCE_TIME* prtNow,
+                                           MUSIC_TIME* pmtNow) PURE;
+    STDMETHOD(AllocPMsg)            (THIS_ ULONG cb,
+                                           DMUS_PMSG** ppPMSG) PURE;
+    STDMETHOD(FreePMsg)             (THIS_ DMUS_PMSG* pPMSG) PURE;
+    STDMETHOD(GetGraph)             (THIS_ IDirectMusicGraph** ppGraph) PURE;
+    STDMETHOD(SetGraph)             (THIS_ IDirectMusicGraph* pGraph) PURE;
+    STDMETHOD(SetNotificationHandle)(THIS_ HANDLE hNotification,
+                                           REFERENCE_TIME rtMinimum) PURE;
+    STDMETHOD(GetNotificationPMsg)  (THIS_ DMUS_NOTIFICATION_PMSG** ppNotificationPMsg) PURE;
+    STDMETHOD(AddNotificationType)  (THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(RemoveNotificationType)(THIS_ REFGUID rguidNotificationType) PURE;
+    STDMETHOD(AddPort)              (THIS_ IDirectMusicPort* pPort) PURE;
+    STDMETHOD(RemovePort)           (THIS_ IDirectMusicPort* pPort ) PURE;
+    STDMETHOD(AssignPChannelBlock)  (THIS_ DWORD dwBlockNum,
+                                           IDirectMusicPort* pPort,
+                                           DWORD dwGroup ) PURE;
+    STDMETHOD(AssignPChannel)       (THIS_ DWORD dwPChannel,
+                                           IDirectMusicPort* pPort,
+                                           DWORD dwGroup,
+                                           DWORD dwMChannel ) PURE;
+    STDMETHOD(PChannelInfo)         (THIS_ DWORD dwPChannel,
+                                           IDirectMusicPort** ppPort,
+                                           DWORD* pdwGroup,
+                                           DWORD* pdwMChannel ) PURE;
+    STDMETHOD(DownloadInstrument)   (THIS_ IDirectMusicInstrument* pInst,
+                                           DWORD dwPChannel,
+                                           IDirectMusicDownloadedInstrument** ppDownInst,
+                                           DMUS_NOTERANGE* pNoteRanges,
+                                           DWORD dwNumNoteRanges,
+                                           IDirectMusicPort** ppPort,
+                                           DWORD* pdwGroup,
+                                           DWORD* pdwMChannel ) PURE;
+    STDMETHOD(Invalidate)           (THIS_ MUSIC_TIME mtTime,
+                                           DWORD dwFlags) PURE;
+    STDMETHOD(GetParam)             (THIS_ REFGUID rguidType,
+                                           DWORD dwGroupBits,
+                                           DWORD dwIndex,
+                                           MUSIC_TIME mtTime,
+                                           MUSIC_TIME* pmtNext,
+                                           void* pParam) PURE;
+    STDMETHOD(SetParam)             (THIS_ REFGUID rguidType,
+                                           DWORD dwGroupBits,
+                                           DWORD dwIndex,
+                                           MUSIC_TIME mtTime,
+                                           void* pParam) PURE;
+    STDMETHOD(GetGlobalParam)       (THIS_ REFGUID rguidType,
+                                           void* pParam,
+                                           DWORD dwSize) PURE;
+    STDMETHOD(SetGlobalParam)       (THIS_ REFGUID rguidType,
+                                           void* pParam,
+                                           DWORD dwSize) PURE;
+    STDMETHOD(GetLatencyTime)       (THIS_ REFERENCE_TIME* prtTime) PURE;
+    STDMETHOD(GetQueueTime)         (THIS_ REFERENCE_TIME* prtTime) PURE;
+    STDMETHOD(AdjustTime)           (THIS_ REFERENCE_TIME rtAmount) PURE;
+    STDMETHOD(CloseDown)            (THIS) PURE;
+    STDMETHOD(GetResolvedTime)      (THIS_ REFERENCE_TIME rtTime,
+                                           REFERENCE_TIME* prtResolved,
+                                           DWORD dwTimeResolveFlags) PURE;
+    STDMETHOD(MIDIToMusic)          (THIS_ BYTE bMIDIValue,
+                                           DMUS_CHORD_KEY* pChord,
+                                           BYTE bPlayMode,
+                                           BYTE bChordLevel,
+                                           WORD *pwMusicValue) PURE;
+    STDMETHOD(MusicToMIDI)          (THIS_ WORD wMusicValue,
+                                           DMUS_CHORD_KEY* pChord,
+                                           BYTE bPlayMode,
+                                           BYTE bChordLevel,
+                                           BYTE *pbMIDIValue) PURE;
+    STDMETHOD(TimeToRhythm)         (THIS_ MUSIC_TIME mtTime,
+                                           DMUS_TIMESIGNATURE *pTimeSig,
+                                           WORD *pwMeasure,
+                                           BYTE *pbBeat,
+                                           BYTE *pbGrid,
+                                           short *pnOffset) PURE;
+    STDMETHOD(RhythmToTime)         (THIS_ WORD wMeasure,
+                                           BYTE bBeat,
+                                           BYTE bGrid,
+                                           short nOffset,
+                                           DMUS_TIMESIGNATURE *pTimeSig,
+                                           MUSIC_TIME *pmtTime) PURE;
+    /*  IDirectMusicPerformance8 */
+    STDMETHOD(InitAudio)            (THIS_ IDirectMusic** ppDirectMusic,            /* Optional DirectMusic pointer. */
+                                           IDirectSound** ppDirectSound,            /* Optional DirectSound pointer. */
+                                           HWND hWnd,                               /* HWND for DirectSound. */
+                                           DWORD dwDefaultPathType,                 /* Requested default audio path type, also optional. */
+                                           DWORD dwPChannelCount,                   /* Number of PChannels, if default audio path to be created. */
+                                           DWORD dwFlags,                           /* DMUS_AUDIOF flags, if no pParams structure. */
+                                           DMUS_AUDIOPARAMS *pParams) PURE;         /* Optional initialization structure, defining required voices, buffers, etc. */
+    STDMETHOD(PlaySegmentEx)        (THIS_ IUnknown* pSource,                       /* Segment to play. */
+                                           WCHAR *pwzSegmentName,                   /* Not supported in DX8. */
+                                           IUnknown* pTransition,                   /* Optional template segment to compose transition with. */
+                                           DWORD dwFlags,                           /* DMUS_SEGF_ flags. */
+                                           __int64 i64StartTime,                    /* Time to start playback. */
+                                           IDirectMusicSegmentState** ppSegmentState, /* Returned Segment State. */
+                                           IUnknown *pFrom,                         /* Optional segmentstate or audiopath to replace. */
+                                           IUnknown *pAudioPath) PURE;              /* Optional audioPath to play on. */
+    STDMETHOD(StopEx)               (THIS_ IUnknown *pObjectToStop,                 /* Segstate, AudioPath, or Segment. */
+                                           __int64 i64StopTime,
+                                           DWORD dwFlags) PURE;
+    STDMETHOD(ClonePMsg)            (THIS_ DMUS_PMSG* pSourcePMSG,
+                                           DMUS_PMSG** ppCopyPMSG) PURE;
+    STDMETHOD(CreateAudioPath)      (THIS_ IUnknown *pSourceConfig,                 /* Source configuration, from AudioPathConfig file. */
+                                           BOOL fActivate,                          /* TRUE to activate on creation. */
+                                           IDirectMusicAudioPath **ppNewPath) PURE; /* Returns created audiopath. */
+    STDMETHOD(CreateStandardAudioPath)(THIS_ DWORD dwType,                          /* Type of path to create. */
+                                           DWORD dwPChannelCount,                   /* How many PChannels to allocate for it. */
+                                           BOOL fActivate,                          /* TRUE to activate on creation. */
+                                           IDirectMusicAudioPath **ppNewPath) PURE; /* Returns created audiopath. */
+    STDMETHOD(SetDefaultAudioPath)  (THIS_ IDirectMusicAudioPath *pAudioPath) PURE;
+    STDMETHOD(GetDefaultAudioPath)  (THIS_ IDirectMusicAudioPath **ppAudioPath) PURE;
+    STDMETHOD(GetParamEx)           (THIS_ REFGUID rguidType,                       /* GetParam command ID. */
+                                           DWORD dwTrackID,                         /* Virtual track ID of caller. */
+                                           DWORD dwGroupBits,                       /* Group bits of caller. */
+                                           DWORD dwIndex,                           /* Index to Nth parameter. */
+                                           MUSIC_TIME mtTime,                       /* Time of requested parameter. */
+                                           MUSIC_TIME* pmtNext,                     /* Returned delta to next parameter. */
+                                           void* pParam) PURE;                      /* Data structure to fill with parameter. */
+};
+
+
+
+/*////////////////////////////////////////////////////////////////////
+// IDirectMusicGraph */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicGraph
+DECLARE_INTERFACE_(IDirectMusicGraph, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicGraph */
+    STDMETHOD(StampPMsg)            (THIS_ DMUS_PMSG* pPMSG) PURE;
+    STDMETHOD(InsertTool)           (THIS_ IDirectMusicTool* pTool,
+                                           DWORD* pdwPChannels,
+                                           DWORD cPChannels,
+                                           LONG lIndex) PURE;
+    STDMETHOD(GetTool)              (THIS_ DWORD dwIndex,
+                                           IDirectMusicTool** ppTool) PURE;
+    STDMETHOD(RemoveTool)           (THIS_ IDirectMusicTool* pTool) PURE;
+};
+
+typedef IDirectMusicGraph IDirectMusicGraph8;
+
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicStyle */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicStyle
+DECLARE_INTERFACE_(IDirectMusicStyle, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)         (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)          (THIS) PURE;
+    STDMETHOD_(ULONG,Release)         (THIS) PURE;
+
+    /*  IDirectMusicStyle */
+    STDMETHOD(GetBand)                (THIS_ WCHAR* pwszName,
+                                             IDirectMusicBand** ppBand) PURE;
+    STDMETHOD(EnumBand)               (THIS_ DWORD dwIndex,
+                                             WCHAR *pwszName) PURE;
+    STDMETHOD(GetDefaultBand)         (THIS_ IDirectMusicBand** ppBand) PURE;
+    STDMETHOD(EnumMotif)              (THIS_ DWORD dwIndex,
+                                             WCHAR* pwszName) PURE;
+    STDMETHOD(GetMotif)               (THIS_ WCHAR* pwszName,
+                                             IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(GetDefaultChordMap)     (THIS_ IDirectMusicChordMap** ppChordMap) PURE;
+    STDMETHOD(EnumChordMap)           (THIS_ DWORD dwIndex,
+                                             WCHAR *pwszName) PURE;
+    STDMETHOD(GetChordMap)            (THIS_ WCHAR* pwszName,
+                                             IDirectMusicChordMap** ppChordMap) PURE;
+    STDMETHOD(GetTimeSignature)       (THIS_ DMUS_TIMESIGNATURE* pTimeSig) PURE;
+    STDMETHOD(GetEmbellishmentLength) (THIS_ DWORD dwType,
+                                             DWORD dwLevel,
+                                             DWORD* pdwMin,
+                                             DWORD* pdwMax) PURE;
+    STDMETHOD(GetTempo)               (THIS_ double* pTempo) PURE;
+};
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicStyle8 */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicStyle8
+DECLARE_INTERFACE_(IDirectMusicStyle8, IDirectMusicStyle)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)               (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)                (THIS) PURE;
+    STDMETHOD_(ULONG,Release)               (THIS) PURE;
+
+    /*  IDirectMusicStyle */
+    STDMETHOD(GetBand)                (THIS_ WCHAR* pwszName,
+                                             IDirectMusicBand** ppBand) PURE;
+    STDMETHOD(EnumBand)               (THIS_ DWORD dwIndex,
+                                             WCHAR *pwszName) PURE;
+    STDMETHOD(GetDefaultBand)         (THIS_ IDirectMusicBand** ppBand) PURE;
+    STDMETHOD(EnumMotif)              (THIS_ DWORD dwIndex,
+                                             WCHAR* pwszName) PURE;
+    STDMETHOD(GetMotif)               (THIS_ WCHAR* pwszName,
+                                             IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(GetDefaultChordMap)     (THIS_ IDirectMusicChordMap** ppChordMap) PURE;
+    STDMETHOD(EnumChordMap)           (THIS_ DWORD dwIndex,
+                                             WCHAR *pwszName) PURE;
+    STDMETHOD(GetChordMap)            (THIS_ WCHAR* pwszName,
+                                             IDirectMusicChordMap** ppChordMap) PURE;
+    STDMETHOD(GetTimeSignature)       (THIS_ DMUS_TIMESIGNATURE* pTimeSig) PURE;
+    STDMETHOD(GetEmbellishmentLength) (THIS_ DWORD dwType,
+                                             DWORD dwLevel,
+                                             DWORD* pdwMin,
+                                             DWORD* pdwMax) PURE;
+    STDMETHOD(GetTempo)               (THIS_ double* pTempo) PURE;
+
+    /*  IDirectMusicStyle8 */
+    STDMETHOD(EnumPattern)            (THIS_ DWORD dwIndex,
+                                             DWORD dwPatternType,
+                                             WCHAR* pwszName) PURE;
+};
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicChordMap */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicChordMap
+DECLARE_INTERFACE_(IDirectMusicChordMap, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicChordMap */
+    STDMETHOD(GetScale)             (THIS_ DWORD* pdwScale) PURE;
+};
+
+typedef IDirectMusicChordMap IDirectMusicChordMap8;
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicComposer */
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicComposer
+DECLARE_INTERFACE_(IDirectMusicComposer, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)               (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)                (THIS) PURE;
+    STDMETHOD_(ULONG,Release)               (THIS) PURE;
+
+    /*  IDirectMusicComposer */
+    STDMETHOD(ComposeSegmentFromTemplate)   (THIS_ IDirectMusicStyle* pStyle,
+                                                   IDirectMusicSegment* pTemplate,
+                                                   WORD wActivity,
+                                                   IDirectMusicChordMap* pChordMap,
+                                                   IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(ComposeSegmentFromShape)      (THIS_ IDirectMusicStyle* pStyle,
+                                                   WORD wNumMeasures,
+                                                   WORD wShape,
+                                                   WORD wActivity,
+                                                   BOOL fIntro,
+                                                   BOOL fEnd,
+                                                   IDirectMusicChordMap* pChordMap,
+                                                   IDirectMusicSegment** ppSegment ) PURE;
+    STDMETHOD(ComposeTransition)            (THIS_ IDirectMusicSegment* pFromSeg,
+                                                   IDirectMusicSegment* pToSeg,
+                                                   MUSIC_TIME mtTime,
+                                                   WORD wCommand,
+                                                   DWORD dwFlags,
+                                                   IDirectMusicChordMap* pChordMap,
+                                                   IDirectMusicSegment** ppTransSeg) PURE;
+    STDMETHOD(AutoTransition)               (THIS_ IDirectMusicPerformance* pPerformance,
+                                                   IDirectMusicSegment* pToSeg,
+                                                   WORD wCommand,
+                                                   DWORD dwFlags,
+                                                   IDirectMusicChordMap* pChordMap,
+                                                   IDirectMusicSegment** ppTransSeg,
+                                                   IDirectMusicSegmentState** ppToSegState,
+                                                   IDirectMusicSegmentState** ppTransSegState) PURE;
+    STDMETHOD(ComposeTemplateFromShape)     (THIS_ WORD wNumMeasures,
+                                                   WORD wShape,
+                                                   BOOL fIntro,
+                                                   BOOL fEnd,
+                                                   WORD wEndLength,
+                                                   IDirectMusicSegment** ppTemplate) PURE;
+    STDMETHOD(ChangeChordMap)            (THIS_ IDirectMusicSegment* pSegment,
+                                                   BOOL fTrackScale,
+                                                   IDirectMusicChordMap* pChordMap) PURE;
+};
+
+typedef IDirectMusicComposer IDirectMusicComposer8;
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicPatternTrack */
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicPatternTrack
+DECLARE_INTERFACE_(IDirectMusicPatternTrack, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)               (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)                (THIS) PURE;
+    STDMETHOD_(ULONG,Release)               (THIS) PURE;
+
+    /*  IDirectMusicPatternTrack */
+    STDMETHOD(CreateSegment)             (THIS_ IDirectMusicStyle* pStyle,
+                                                IDirectMusicSegment** ppSegment) PURE;
+    STDMETHOD(SetVariation)              (THIS_ IDirectMusicSegmentState* pSegState,
+                                                DWORD dwVariationFlags,
+                                                DWORD dwPart) PURE;
+    STDMETHOD(SetPatternByName)          (THIS_ IDirectMusicSegmentState* pSegState,
+                                                WCHAR* wszName,
+                                                IDirectMusicStyle* pStyle,
+                                                DWORD dwPatternType,
+                                                DWORD* pdwLength) PURE;
+};
+
+typedef IDirectMusicPatternTrack IDirectMusicPatternTrack8;
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicScript */
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicScript
+DECLARE_INTERFACE_(IDirectMusicScript, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /*  IDirectMusicScript */
+    STDMETHOD(Init)                     (THIS_ IDirectMusicPerformance *pPerformance,
+                                               DMUS_SCRIPT_ERRORINFO *pErrorInfo) PURE;
+    STDMETHOD(CallRoutine)              (THIS_ WCHAR *pwszRoutineName,
+                                               DMUS_SCRIPT_ERRORINFO *pErrorInfo) PURE;
+    STDMETHOD(SetVariableVariant)       (THIS_ WCHAR *pwszVariableName,
+                                               VARIANT varValue,
+                                               BOOL fSetRef,
+                                               DMUS_SCRIPT_ERRORINFO *pErrorInfo) PURE;
+    STDMETHOD(GetVariableVariant)       (THIS_ WCHAR *pwszVariableName,
+                                               VARIANT *pvarValue,
+                                               DMUS_SCRIPT_ERRORINFO *pErrorInfo) PURE;
+    STDMETHOD(SetVariableNumber)        (THIS_ WCHAR *pwszVariableName,
+                                               LONG lValue,
+                                               DMUS_SCRIPT_ERRORINFO *pErrorInfo) PURE;
+    STDMETHOD(GetVariableNumber)        (THIS_ WCHAR *pwszVariableName,
+                                               LONG *plValue,
+                                               DMUS_SCRIPT_ERRORINFO *pErrorInfo) PURE;
+    STDMETHOD(SetVariableObject)        (THIS_ WCHAR *pwszVariableName,
+                                               IUnknown *punkValue,
+                                               DMUS_SCRIPT_ERRORINFO *pErrorInfo) PURE;
+    STDMETHOD(GetVariableObject)        (THIS_ WCHAR *pwszVariableName,
+                                               REFIID riid,
+                                               LPVOID FAR *ppv,
+                                               DMUS_SCRIPT_ERRORINFO *pErrorInfo) PURE;
+    STDMETHOD(EnumRoutine)              (THIS_ DWORD dwIndex,
+                                               WCHAR *pwszName) PURE;
+    STDMETHOD(EnumVariable)             (THIS_ DWORD dwIndex,
+                                               WCHAR *pwszName) PURE;
+};
+
+typedef IDirectMusicScript IDirectMusicScript8;
+
+/*/////////////////////////////////////////////////////////////////////
+// IDirectMusicContainer */
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicContainer
+DECLARE_INTERFACE_(IDirectMusicContainer, IUnknown)
+{
+    /*  IUnknown */
+    STDMETHOD(QueryInterface)               (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)                (THIS) PURE;
+    STDMETHOD_(ULONG,Release)               (THIS) PURE;
+
+    /*  IDirectMusicContainer */
+    STDMETHOD(EnumObject)           (THIS_ REFGUID rguidClass,
+                                           DWORD dwIndex,
+                                           LPDMUS_OBJECTDESC pDesc,
+                                           WCHAR *pwszAlias) PURE;
+};
+
+typedef IDirectMusicContainer IDirectMusicContainer8;
+
+/* CLSID's */
+DEFINE_GUID(CLSID_DirectMusicPerformance,0xd2ac2881, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicSegment,0xd2ac2882, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicSegmentState,0xd2ac2883, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicGraph,0xd2ac2884, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicStyle,0xd2ac288a, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicChordMap,0xd2ac288f, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicComposer,0xd2ac2890, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicLoader,0xd2ac2892, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicBand,0x79ba9e00, 0xb6ee, 0x11d1, 0x86, 0xbe, 0x0, 0xc0, 0x4f, 0xbf, 0x8f, 0xef);
+
+/* New CLSID's for DX8 */
+DEFINE_GUID(CLSID_DirectMusicPatternTrack,0xd2ac2897, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(CLSID_DirectMusicScript,0x810b5013, 0xe88d, 0x11d2, 0x8b, 0xc1, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xb6); /* {810B5013-E88D-11d2-8BC1-00600893B1B6} */
+DEFINE_GUID(CLSID_DirectMusicContainer,0x9301e380, 0x1f22, 0x11d3, 0x82, 0x26, 0xd2, 0xfa, 0x76, 0x25, 0x5d, 0x47);
+DEFINE_GUID(CLSID_DirectSoundWave,0x8a667154, 0xf9cb, 0x11d2, 0xad, 0x8a, 0x0, 0x60, 0xb0, 0x57, 0x5a, 0xbc);
+DEFINE_GUID(CLSID_DirectMusicAudioPathConfig,0xee0b9ca0, 0xa81e, 0x11d3, 0x9b, 0xd1, 0x0, 0x80, 0xc7, 0x15, 0xa, 0x74);
+
+/* Special GUID for all object types. This is used by the loader. */
+DEFINE_GUID(GUID_DirectMusicAllTypes,0xd2ac2893, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Notification guids */
+DEFINE_GUID(GUID_NOTIFICATION_SEGMENT,0xd2ac2899, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_NOTIFICATION_PERFORMANCE,0x81f75bc5, 0x4e5d, 0x11d2, 0xbc, 0xc7, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
+DEFINE_GUID(GUID_NOTIFICATION_MEASUREANDBEAT,0xd2ac289a, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_NOTIFICATION_CHORD,0xd2ac289b, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_NOTIFICATION_COMMAND,0xd2ac289c, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_NOTIFICATION_RECOMPOSE, 0xd348372b, 0x945b, 0x45ae, 0xa5, 0x22, 0x45, 0xf, 0x12, 0x5b, 0x84, 0xa5);
+
+/* Track param type guids */
+/* Use to get/set a DMUS_COMMAND_PARAM param in the Command track */
+DEFINE_GUID(GUID_CommandParam,0xd2ac289d, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Use to get a DMUS_COMMAND_PARAM_2 param in the Command track */
+DEFINE_GUID(GUID_CommandParam2, 0x28f97ef7, 0x9538, 0x11d2, 0x97, 0xa9, 0x0, 0xc0, 0x4f, 0xa3, 0x6e, 0x58);
+
+/* Use to get/set a DMUS_COMMAND_PARAM_2 param to be used as the command following all commands in
+the Command track (this information can't be saved) */
+DEFINE_GUID(GUID_CommandParamNext, 0x472afe7a, 0x281b, 0x11d3, 0x81, 0x7d, 0x0, 0xc0, 0x4f, 0xa3, 0x6e, 0x58);
+
+/* Use to get/set a DMUS_CHORD_PARAM param in the Chord track */
+DEFINE_GUID(GUID_ChordParam,0xd2ac289e, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Use to get a DMUS_RHYTHM_PARAM param in the Chord track */
+DEFINE_GUID(GUID_RhythmParam,0xd2ac289f, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Use to get/set an IDirectMusicStyle param in the Style track */
+DEFINE_GUID(GUID_IDirectMusicStyle,0xd2ac28a1, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Use to get a DMUS_TIMESIGNATURE param in the Style and TimeSig tracks */
+DEFINE_GUID(GUID_TimeSignature,0xd2ac28a4, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Use to get/set a DMUS_TEMPO_PARAM param in the Tempo track */
+DEFINE_GUID(GUID_TempoParam,0xd2ac28a5, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Use to get the next valid point in a segment at which it may start */
+DEFINE_GUID(GUID_Valid_Start_Time,0x7f6b1760, 0x1fdb, 0x11d3, 0x82, 0x26, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+
+/* Use to get the next point in the currently playing primary segment at which a new segment may start */
+DEFINE_GUID(GUID_Play_Marker,0xd8761a41, 0x801a, 0x11d3, 0x9b, 0xd1, 0xda, 0xf7, 0xe1, 0xc3, 0xd8, 0x34);
+
+/* Use to get (GetParam) or add (SetParam) bands in the Band track */
+DEFINE_GUID(GUID_BandParam,0x2bb1938, 0xcb8b, 0x11d2, 0x8b, 0xb9, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xb6);
+typedef struct _DMUS_BAND_PARAM
+{
+    MUSIC_TIME  mtTimePhysical; /* Note: If this is a Timer-time track, then this field is interpreted in the track's internal time format, which is the number of milliseconds after the beginning of playback. */
+    IDirectMusicBand *pBand;
+} DMUS_BAND_PARAM;
+
+/* Obsolete -- doesn't distinguish physical and logical time.  Use GUID_BandParam instead. */
+DEFINE_GUID(GUID_IDirectMusicBand,0xd2ac28ac, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Use to get/set an IDirectMusicChordMap param in the ChordMap track */
+DEFINE_GUID(GUID_IDirectMusicChordMap,0xd2ac28ad, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Use to get/set a DMUS_MUTE_PARAM param in the Mute track */
+DEFINE_GUID(GUID_MuteParam,0xd2ac28af, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* These guids are used in IDirectMusicSegment::SetParam to tell the band track to perform various actions.
+   Some of these guids (where noted) also apply to wave tracks.
+ */
+/* Download bands/waves for the IDirectMusicSegment */
+DEFINE_GUID(GUID_Download,0xd2ac28a7, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Unload bands/waves for the IDirectMusicSegment */
+DEFINE_GUID(GUID_Unload,0xd2ac28a8, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Connect segment's bands to an IDirectMusicCollection */
+DEFINE_GUID(GUID_ConnectToDLSCollection, 0x1db1ae6b, 0xe92e, 0x11d1, 0xa8, 0xc5, 0x0, 0xc0, 0x4f, 0xa3, 0x72, 0x6e);
+
+/* Enable/disable autodownloading of bands/waves */
+DEFINE_GUID(GUID_Enable_Auto_Download,0xd2ac28a9, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_Disable_Auto_Download,0xd2ac28aa, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Clear all bands */
+DEFINE_GUID(GUID_Clear_All_Bands,0xd2ac28ab, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Set segment to manage all program changes, bank selects, etc. for simple playback of a standard MIDI file */
+DEFINE_GUID(GUID_StandardMIDIFile, 0x6621075, 0xe92e, 0x11d1, 0xa8, 0xc5, 0x0, 0xc0, 0x4f, 0xa3, 0x72, 0x6e);
+/* For compatibility with beta releases... */
+#define GUID_IgnoreBankSelectForGM 	GUID_StandardMIDIFile
+
+/* Disable/enable param guids. Use these in SetParam calls to disable or enable sending
+ * specific PMsg types.
+ */
+DEFINE_GUID(GUID_DisableTimeSig, 0x45fc707b, 0x1db4, 0x11d2, 0xbc, 0xac, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
+DEFINE_GUID(GUID_EnableTimeSig, 0x45fc707c, 0x1db4, 0x11d2, 0xbc, 0xac, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
+DEFINE_GUID(GUID_DisableTempo, 0x45fc707d, 0x1db4, 0x11d2, 0xbc, 0xac, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
+DEFINE_GUID(GUID_EnableTempo, 0x45fc707e, 0x1db4, 0x11d2, 0xbc, 0xac, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
+
+/* Used in SetParam calls for pattern-based tracks.  A nonzero value seeds the random number
+generator for variation selection; a value of zero reverts to the default behavior of
+getting the seed from the system Timer.
+*/
+DEFINE_GUID(GUID_SeedVariations, 0x65b76fa5, 0xff37, 0x11d2, 0x81, 0x4e, 0x0, 0xc0, 0x4f, 0xa3, 0x6e, 0x58);
+
+/* Used to get the variations currently in effect across PChannels */
+DEFINE_GUID(GUID_Variations, 0x11f72cce, 0x26e6, 0x4ecd, 0xaf, 0x2e, 0xd6, 0x68, 0xe6, 0x67, 0x7, 0xd8);
+typedef struct _DMUS_VARIATIONS_PARAM
+{
+    DWORD   dwPChannelsUsed; /* number of PChannels in use */
+    DWORD*  padwPChannels;   /* array of PChannels in use */
+    DWORD*  padwVariations;  /* array of variations in effect for each PChannel */
+} DMUS_VARIATIONS_PARAM;
+
+/* Download bands/waves for the IDirectMusicSegment, passed an IDirectMusicAudioPath instead of an IDirectMusicPerformance */
+DEFINE_GUID(GUID_DownloadToAudioPath,0x9f2c0341, 0xc5c4, 0x11d3, 0x9b, 0xd1, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+
+/* Unload bands/waves for the IDirectMusicSegment, passed an IDirectMusicAudioPath instead of an IDirectMusicPerformance */
+DEFINE_GUID(GUID_UnloadFromAudioPath,0x9f2c0342, 0xc5c4, 0x11d3, 0x9b, 0xd1, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+
+
+/* Global data guids */
+DEFINE_GUID(GUID_PerfMasterTempo,0xd2ac28b0, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_PerfMasterVolume,0xd2ac28b1, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_PerfMasterGrooveLevel,0xd2ac28b2, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(GUID_PerfAutoDownload, 0xfb09565b, 0x3631, 0x11d2, 0xbc, 0xb8, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
+
+/* GUID for default GM/GS dls collection. */
+DEFINE_GUID(GUID_DefaultGMCollection, 0xf17e8673, 0xc3b4, 0x11d1, 0x87, 0xb, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* GUID to define default synth, placed in AudioPath configuration file. */
+DEFINE_GUID(GUID_Synth_Default,0x26bb9432, 0x45fe, 0x48d3, 0xa3, 0x75, 0x24, 0x72, 0xc5, 0xe3, 0xe7, 0x86);
+
+/* GUIDs to define default buffer configurations to place in AudioPath configuration file. */
+DEFINE_GUID(GUID_Buffer_Reverb,0x186cc541, 0xdb29, 0x11d3, 0x9b, 0xd1, 0x0, 0x80, 0xc7, 0x15, 0xa, 0x74);
+DEFINE_GUID(GUID_Buffer_EnvReverb,0x186cc542, 0xdb29, 0x11d3, 0x9b, 0xd1, 0x0, 0x80, 0xc7, 0x15, 0xa, 0x74);
+DEFINE_GUID(GUID_Buffer_Stereo,0x186cc545, 0xdb29, 0x11d3, 0x9b, 0xd1, 0x0, 0x80, 0xc7, 0x15, 0xa, 0x74);
+DEFINE_GUID(GUID_Buffer_3D_Dry,0x186cc546, 0xdb29, 0x11d3, 0x9b, 0xd1, 0x0, 0x80, 0xc7, 0x15, 0xa, 0x74);
+DEFINE_GUID(GUID_Buffer_Mono,0x186cc547, 0xdb29, 0x11d3, 0x9b, 0xd1, 0x0, 0x80, 0xc7, 0x15, 0xa, 0x74);
+
+/* IID's */
+DEFINE_GUID(IID_IDirectMusicLoader, 0x2ffaaca2, 0x5dca, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_GUID(IID_IDirectMusicGetLoader,0x68a04844, 0xd13d, 0x11d1, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_GUID(IID_IDirectMusicObject,0xd2ac28b5, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicSegment, 0xf96029a2, 0x4282, 0x11d2, 0x87, 0x17, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicSegmentState, 0xa3afdcc7, 0xd3ee, 0x11d1, 0xbc, 0x8d, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
+DEFINE_GUID(IID_IDirectMusicPerformance,0x7d43d03, 0x6523, 0x11d2, 0x87, 0x1d, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicGraph,0x2befc277, 0x5497, 0x11d2, 0xbc, 0xcb, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
+DEFINE_GUID(IID_IDirectMusicStyle,0xd2ac28bd, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicChordMap,0xd2ac28be, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicComposer,0xd2ac28bf, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+DEFINE_GUID(IID_IDirectMusicBand,0xd2ac28c0, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Alternate interface IDs, available in DX7 release and after. */
+DEFINE_GUID(IID_IDirectMusicPerformance2,0x6fc2cae0, 0xbc78, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_GUID(IID_IDirectMusicSegment2, 0xd38894d1, 0xc052, 0x11d2, 0x87, 0x2f, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
+
+/* Interface IDs for DX8 */
+/* changed interfaces (GUID only) */
+DEFINE_GUID(IID_IDirectMusicLoader8, 0x19e7c08c, 0xa44, 0x4e6a, 0xa1, 0x16, 0x59, 0x5a, 0x7c, 0xd5, 0xde, 0x8c);
+DEFINE_GUID(IID_IDirectMusicPerformance8, 0x679c4137, 0xc62e, 0x4147, 0xb2, 0xb4, 0x9d, 0x56, 0x9a, 0xcb, 0x25, 0x4c);
+DEFINE_GUID(IID_IDirectMusicSegment8,0xc6784488, 0x41a3, 0x418f, 0xaa, 0x15, 0xb3, 0x50, 0x93, 0xba, 0x42, 0xd4);
+DEFINE_GUID(IID_IDirectMusicSegmentState8, 0xa50e4730, 0xae4, 0x48a7, 0x98, 0x39, 0xbc, 0x4, 0xbf, 0xe0, 0x77, 0x72);
+DEFINE_GUID(IID_IDirectMusicStyle8, 0xfd24ad8a, 0xa260, 0x453d, 0xbf, 0x50, 0x6f, 0x93, 0x84, 0xf7, 0x9, 0x85);
+/* new interfaces (GUID + alias) */
+DEFINE_GUID(IID_IDirectMusicPatternTrack, 0x51c22e10, 0xb49f, 0x46fc, 0xbe, 0xc2, 0xe6, 0x28, 0x8f, 0xb9, 0xed, 0xe6);
+#define IID_IDirectMusicPatternTrack8 IID_IDirectMusicPatternTrack
+DEFINE_GUID(IID_IDirectMusicScript, 0x2252373a, 0x5814, 0x489b, 0x82, 0x9, 0x31, 0xfe, 0xde, 0xba, 0xf1, 0x37); /* {2252373A-5814-489b-8209-31FEDEBAF137} */
+#define IID_IDirectMusicScript8 IID_IDirectMusicScript
+DEFINE_GUID(IID_IDirectMusicContainer, 0x9301e386, 0x1f22, 0x11d3, 0x82, 0x26, 0xd2, 0xfa, 0x76, 0x25, 0x5d, 0x47);
+#define IID_IDirectMusicContainer8 IID_IDirectMusicContainer
+DEFINE_GUID(IID_IDirectMusicAudioPath,0xc87631f5, 0x23be, 0x4986, 0x88, 0x36, 0x5, 0x83, 0x2f, 0xcc, 0x48, 0xf9);
+#define IID_IDirectMusicAudioPath8 IID_IDirectMusicAudioPath
+/* unchanged interfaces (alias only) */
+#define IID_IDirectMusicGetLoader8 IID_IDirectMusicGetLoader
+#define IID_IDirectMusicChordMap8 IID_IDirectMusicChordMap
+#define IID_IDirectMusicGraph8 IID_IDirectMusicGraph
+#define IID_IDirectMusicBand8 IID_IDirectMusicBand
+#define IID_IDirectMusicObject8 IID_IDirectMusicObject
+#define IID_IDirectMusicComposer8 IID_IDirectMusicComposer
+
+
+#ifdef __cplusplus
+}; /* extern "C" */
+#endif
+
+#include <poppack.h>
+
+#endif /* #ifndef _DMUSICI_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dmusics.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,193 @@
+/************************************************************************
+*                                                                       *
+*   dmusics.h -- Definitions for created a DirectMusic software synth   *
+*                                                                       *
+*   Copyright (c) Microsoft Corporation.  All rights reserved.          *
+*                                                                       *
+************************************************************************/
+
+#ifndef _DMUSICS_
+#define _DMUSICS_
+
+#include "dmusicc.h"
+
+/* Software synths are enumerated from under this registry key.
+ */
+#define REGSTR_PATH_SOFTWARESYNTHS  "Software\\Microsoft\\DirectMusic\\SoftwareSynths"
+
+interface IDirectMusicSynth;
+interface IDirectMusicSynthSink;
+
+#ifndef __cplusplus 
+typedef interface IDirectMusicSynth IDirectMusicSynth;
+typedef interface IDirectMusicSynthSink IDirectMusicSynthSink;
+#endif
+
+#ifndef _DMUS_VOICE_STATE_DEFINED
+#define _DMUS_VOICE_STATE_DEFINED
+
+typedef struct _DMUS_VOICE_STATE
+{
+    BOOL                bExists;
+    SAMPLE_POSITION     spPosition;
+} DMUS_VOICE_STATE; 
+
+#endif /* _DMUS_VOICE_STATE_DEFINED */
+
+/* IDirectMusicSynth::Refresh
+ *
+ * This is the last buffer of the stream. It may be a partial block.
+ */
+#define REFRESH_F_LASTBUFFER        0x00000001
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicSynth
+DECLARE_INTERFACE_(IDirectMusicSynth, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicSynth */
+    STDMETHOD(Open)                 (THIS_ LPDMUS_PORTPARAMS pPortParams) PURE;
+    STDMETHOD(Close)                (THIS) PURE;
+    STDMETHOD(SetNumChannelGroups)  (THIS_ DWORD dwGroups) PURE;
+    STDMETHOD(Download)             (THIS_ LPHANDLE phDownload, 
+                                           LPVOID pvData, 
+                                           LPBOOL pbFree ) PURE;
+    STDMETHOD(Unload)               (THIS_ HANDLE hDownload, 
+                                           HRESULT ( CALLBACK *lpFreeHandle)(HANDLE,HANDLE), 
+                                           HANDLE hUserData ) PURE; 
+    STDMETHOD(PlayBuffer)           (THIS_ REFERENCE_TIME rt, 
+                                           LPBYTE pbBuffer, 
+                                           DWORD cbBuffer) PURE;
+    STDMETHOD(GetRunningStats)      (THIS_ LPDMUS_SYNTHSTATS pStats) PURE;
+    STDMETHOD(GetPortCaps)          (THIS_ LPDMUS_PORTCAPS pCaps) PURE;
+    STDMETHOD(SetMasterClock)       (THIS_ IReferenceClock *pClock) PURE;
+    STDMETHOD(GetLatencyClock)      (THIS_ IReferenceClock **ppClock) PURE;
+    STDMETHOD(Activate)             (THIS_ BOOL fEnable) PURE;
+    STDMETHOD(SetSynthSink)         (THIS_ IDirectMusicSynthSink *pSynthSink) PURE;
+    STDMETHOD(Render)               (THIS_ short *pBuffer, 
+                                           DWORD dwLength, 
+                                           LONGLONG llPosition) PURE;
+    STDMETHOD(SetChannelPriority)   (THIS_ DWORD dwChannelGroup,
+                                           DWORD dwChannel,
+                                           DWORD dwPriority) PURE;
+    STDMETHOD(GetChannelPriority)   (THIS_ DWORD dwChannelGroup,
+                                           DWORD dwChannel,
+                                           LPDWORD pdwPriority) PURE;
+    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pWaveFormatEx,
+                                           LPDWORD pdwWaveFormatExSize) PURE;
+    STDMETHOD(GetAppend)            (THIS_ DWORD* pdwAppend) PURE;
+};
+
+#undef  INTERFACE
+
+#define INTERFACE  IDirectMusicSynth8
+DECLARE_INTERFACE_(IDirectMusicSynth8, IDirectMusicSynth)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicSynth */
+    STDMETHOD(Open)                 (THIS_ LPDMUS_PORTPARAMS pPortParams) PURE;
+    STDMETHOD(Close)                (THIS) PURE;
+    STDMETHOD(SetNumChannelGroups)  (THIS_ DWORD dwGroups) PURE;
+    STDMETHOD(Download)             (THIS_ LPHANDLE phDownload, 
+                                           LPVOID pvData, 
+                                           LPBOOL pbFree ) PURE;
+    STDMETHOD(Unload)               (THIS_ HANDLE hDownload, 
+                                           HRESULT ( CALLBACK *lpFreeHandle)(HANDLE,HANDLE), 
+                                           HANDLE hUserData ) PURE; 
+    STDMETHOD(PlayBuffer)           (THIS_ REFERENCE_TIME rt, 
+                                           LPBYTE pbBuffer, 
+                                           DWORD cbBuffer) PURE;
+    STDMETHOD(GetRunningStats)      (THIS_ LPDMUS_SYNTHSTATS pStats) PURE;
+    STDMETHOD(GetPortCaps)          (THIS_ LPDMUS_PORTCAPS pCaps) PURE;
+    STDMETHOD(SetMasterClock)       (THIS_ IReferenceClock *pClock) PURE;
+    STDMETHOD(GetLatencyClock)      (THIS_ IReferenceClock **ppClock) PURE;
+    STDMETHOD(Activate)             (THIS_ BOOL fEnable) PURE;
+    STDMETHOD(SetSynthSink)         (THIS_ IDirectMusicSynthSink *pSynthSink) PURE;
+    STDMETHOD(Render)               (THIS_ short *pBuffer, 
+                                           DWORD dwLength, 
+                                           LONGLONG llPosition) PURE;
+    STDMETHOD(SetChannelPriority)   (THIS_ DWORD dwChannelGroup,
+                                           DWORD dwChannel,
+                                           DWORD dwPriority) PURE;
+    STDMETHOD(GetChannelPriority)   (THIS_ DWORD dwChannelGroup,
+                                           DWORD dwChannel,
+                                           LPDWORD pdwPriority) PURE;
+    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pWaveFormatEx,
+                                           LPDWORD pdwWaveFormatExSize) PURE;
+    STDMETHOD(GetAppend)            (THIS_ DWORD* pdwAppend) PURE;
+
+	/* IDirectMusicSynth8 */
+    STDMETHOD(PlayVoice)            (THIS_ REFERENCE_TIME rt, 
+										   DWORD dwVoiceId, 
+										   DWORD dwChannelGroup, 
+										   DWORD dwChannel, 
+										   DWORD dwDLId, 
+										   long	 prPitch,			/* PREL not defined here */
+										   long  vrVolume,          /* VREL not defined here */
+                                           SAMPLE_TIME stVoiceStart,
+                                           SAMPLE_TIME stLoopStart,
+                                           SAMPLE_TIME stLoopEnd) PURE;
+
+    STDMETHOD(StopVoice)            (THIS_ REFERENCE_TIME rt, 
+										   DWORD dwVoiceId ) PURE;
+
+    STDMETHOD(GetVoiceState)        (THIS_ DWORD dwVoice[], 
+										   DWORD cbVoice,
+										   DMUS_VOICE_STATE dwVoiceState[] ) PURE;
+    STDMETHOD(Refresh)              (THIS_ DWORD dwDownloadID,
+                                           DWORD dwFlags) PURE;
+    STDMETHOD(AssignChannelToBuses) (THIS_ DWORD dwChannelGroup,
+                                           DWORD dwChannel,
+                                           LPDWORD pdwBuses,
+                                           DWORD cBuses) PURE;                                           
+};
+
+#undef  INTERFACE
+#define INTERFACE  IDirectMusicSynthSink
+DECLARE_INTERFACE_(IDirectMusicSynthSink, IUnknown)
+{
+    /* IUnknown */
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID FAR *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    /* IDirectMusicSynthSink */
+    STDMETHOD(Init)                 (THIS_ IDirectMusicSynth *pSynth) PURE;
+    STDMETHOD(SetMasterClock)       (THIS_ IReferenceClock *pClock) PURE;
+    STDMETHOD(GetLatencyClock)      (THIS_ IReferenceClock **ppClock) PURE;
+    STDMETHOD(Activate)             (THIS_ BOOL fEnable) PURE;
+    STDMETHOD(SampleToRefTime)      (THIS_ LONGLONG llSampleTime,
+                                           REFERENCE_TIME *prfTime) PURE;
+    STDMETHOD(RefTimeToSample)      (THIS_ REFERENCE_TIME rfTime, 
+                                           LONGLONG *pllSampleTime) PURE;
+    STDMETHOD(SetDirectSound)       (THIS_ LPDIRECTSOUND pDirectSound,
+                                           LPDIRECTSOUNDBUFFER pDirectSoundBuffer) PURE;                                           
+    STDMETHOD(GetDesiredBufferSize) (THIS_ LPDWORD pdwBufferSizeInSamples) PURE;                                           
+};
+
+DEFINE_GUID(IID_IDirectMusicSynth, 0x9823661,  0x5c85, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_GUID(IID_IDirectMusicSynth8,0x53cab625, 0x2711, 0x4c9f, 0x9d, 0xe7, 0x1b, 0x7f, 0x92, 0x5f, 0x6f, 0xc8);
+DEFINE_GUID(IID_IDirectMusicSynthSink,0x9823663, 0x5c85, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+
+/* Property Set GUID_DMUS_PROP_SetSynthSink
+ *
+ * Item 0: An IUnknown on which the port can QueryInterface for a user-mode synth sink.
+ */
+DEFINE_GUID(GUID_DMUS_PROP_SetSynthSink,0x0a3a5ba5, 0x37b6, 0x11d2, 0xb9, 0xf9, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+
+/* Property Set GUID_DMUS_PROP_SinkUsesDSound
+ *
+ * Item 0: A DWORD boolean indicating whether or not the sink requires an IDirectSound interface. The
+ * default is FALSE if this property item is not implemented by the sink.
+ */
+DEFINE_GUID(GUID_DMUS_PROP_SinkUsesDSound, 0xbe208857, 0x8952, 0x11d2, 0xba, 0x1c, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); 
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dsconf.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,195 @@
+/*==========================================================================;
+ *
+ *  Copyright (c) Microsoft Corporation.  All rights reserved.
+ *
+ *  File:       dsconf.h
+ *  Content:    DirectSound configuration interface include file
+ *
+ **************************************************************************/
+
+#ifndef __DSCONF_INCLUDED__
+#define __DSCONF_INCLUDED__
+
+#ifndef __DSOUND_INCLUDED__
+#error dsound.h not included
+#endif // __DSOUND_INCLUDED__
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+
+// DirectSound Private Component GUID {11AB3EC0-25EC-11d1-A4D8-00C04FC28ACA}
+DEFINE_GUID(CLSID_DirectSoundPrivate, 0x11ab3ec0, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
+
+
+//
+// DirectSound Device Properties {84624F82-25EC-11d1-A4D8-00C04FC28ACA}
+//
+
+DEFINE_GUID(DSPROPSETID_DirectSoundDevice, 0x84624f82, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
+
+typedef enum
+{
+    DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A = 1,
+    DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1 = 2,
+    DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1 = 3,
+    DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W = 4,
+    DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A = 5,
+    DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W = 6,
+    DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A = 7,
+    DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W = 8,
+} DSPROPERTY_DIRECTSOUNDDEVICE;
+
+#if DIRECTSOUND_VERSION >= 0x0700
+#ifdef UNICODE
+#define DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W
+#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W
+#define DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W
+#else // UNICODE
+#define DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A
+#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A
+#define DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A
+#endif // UNICODE
+#else // DIRECTSOUND_VERSION >= 0x0700
+#define DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A
+#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1
+#define DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1
+#endif // DIRECTSOUND_VERSION >= 0x0700
+
+typedef enum
+{
+    DIRECTSOUNDDEVICE_TYPE_EMULATED,
+    DIRECTSOUNDDEVICE_TYPE_VXD,
+    DIRECTSOUNDDEVICE_TYPE_WDM
+} DIRECTSOUNDDEVICE_TYPE;
+
+typedef enum
+{
+    DIRECTSOUNDDEVICE_DATAFLOW_RENDER,
+    DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE
+} DIRECTSOUNDDEVICE_DATAFLOW;
+
+
+typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA
+{
+    LPSTR                       DeviceName; // waveIn/waveOut device name
+    DIRECTSOUNDDEVICE_DATAFLOW  DataFlow;   // Data flow (i.e. waveIn or waveOut)
+    GUID                        DeviceId;   // DirectSound device id
+} DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA;
+
+typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA
+{
+    LPWSTR                      DeviceName; // waveIn/waveOut device name
+    DIRECTSOUNDDEVICE_DATAFLOW  DataFlow;   // Data flow (i.e. waveIn or waveOut)
+    GUID                        DeviceId;   // DirectSound device id
+} DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA;
+
+#ifdef UNICODE
+#define DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_DATA DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA
+#define PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_DATA PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA
+#else // UNICODE
+#define DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_DATA DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA
+#define PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_DATA PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA
+#endif // UNICODE
+
+typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA
+{
+    GUID                        DeviceId;               // DirectSound device id
+    CHAR                        DescriptionA[0x100];    // Device description (ANSI)
+    WCHAR                       DescriptionW[0x100];    // Device description (Unicode)
+    CHAR                        ModuleA[MAX_PATH];      // Device driver module (ANSI)
+    WCHAR                       ModuleW[MAX_PATH];      // Device driver module (Unicode)
+    DIRECTSOUNDDEVICE_TYPE      Type;                   // Device type
+    DIRECTSOUNDDEVICE_DATAFLOW  DataFlow;               // Device dataflow
+    ULONG                       WaveDeviceId;           // Wave device id
+    ULONG                       Devnode;                // Devnode (or DevInst)
+} DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA;
+
+typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA
+{
+    DIRECTSOUNDDEVICE_TYPE      Type;           // Device type
+    DIRECTSOUNDDEVICE_DATAFLOW  DataFlow;       // Device dataflow
+    GUID                        DeviceId;       // DirectSound device id
+    LPSTR                       Description;    // Device description
+    LPSTR                       Module;         // Device driver module
+    LPSTR                       Interface;      // Device interface
+    ULONG                       WaveDeviceId;   // Wave device id
+} DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA;
+
+typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA
+{
+    DIRECTSOUNDDEVICE_TYPE      Type;           // Device type
+    DIRECTSOUNDDEVICE_DATAFLOW  DataFlow;       // Device dataflow
+    GUID                        DeviceId;       // DirectSound device id
+    LPWSTR                      Description;    // Device description
+    LPWSTR                      Module;         // Device driver module
+    LPWSTR                      Interface;      // Device interface
+    ULONG                       WaveDeviceId;   // Wave device id
+} DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA;
+
+#if DIRECTSOUND_VERSION >= 0x0700
+#ifdef UNICODE
+#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA
+#define PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA
+#else // UNICODE
+#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA
+#define PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA
+#endif // UNICODE
+#else // DIRECTSOUND_VERSION >= 0x0700
+#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA
+#define PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA
+#endif // DIRECTSOUND_VERSION >= 0x0700
+
+typedef BOOL (CALLBACK *LPFNDIRECTSOUNDDEVICEENUMERATECALLBACK1)(PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA, LPVOID);
+typedef BOOL (CALLBACK *LPFNDIRECTSOUNDDEVICEENUMERATECALLBACKA)(PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA, LPVOID);
+typedef BOOL (CALLBACK *LPFNDIRECTSOUNDDEVICEENUMERATECALLBACKW)(PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA, LPVOID);
+
+#if DIRECTSOUND_VERSION >= 0x0700
+#ifdef UNICODE
+#define LPFNDIRECTSOUNDDEVICEENUMERATECALLBACK LPFNDIRECTSOUNDDEVICEENUMERATECALLBACKW
+#else // UNICODE
+#define LPFNDIRECTSOUNDDEVICEENUMERATECALLBACK LPFNDIRECTSOUNDDEVICEENUMERATECALLBACKA
+#endif // UNICODE
+#else // DIRECTSOUND_VERSION >= 0x0700
+#define LPFNDIRECTSOUNDDEVICEENUMERATECALLBACK LPFNDIRECTSOUNDDEVICEENUMERATECALLBACK1
+#endif // DIRECTSOUND_VERSION >= 0x0700
+
+typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA
+{
+    LPFNDIRECTSOUNDDEVICEENUMERATECALLBACK1 Callback;   // Callback function pointer
+    LPVOID                                  Context;    // Callback function context argument
+} DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA;
+
+typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA
+{
+    LPFNDIRECTSOUNDDEVICEENUMERATECALLBACKA Callback;   // Callback function pointer
+    LPVOID                                  Context;    // Callback function context argument
+} DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA;
+
+typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA
+{
+    LPFNDIRECTSOUNDDEVICEENUMERATECALLBACKW Callback;   // Callback function pointer
+    LPVOID                                  Context;    // Callback function context argument
+} DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA;
+
+#if DIRECTSOUND_VERSION >= 0x0700
+#ifdef UNICODE
+#define DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA
+#define PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA
+#else // UNICODE
+#define DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA
+#define PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA
+#endif // UNICODE
+#else // DIRECTSOUND_VERSION >= 0x0700
+#define DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA
+#define PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA
+#endif // DIRECTSOUND_VERSION >= 0x0700
+
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif  // __DSCONF_INCLUDED__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dsound.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2358 @@
+/*==========================================================================;
+ *
+ *  Copyright (c) Microsoft Corporation.  All rights reserved.
+ *
+ *  File:       dsound.h
+ *  Content:    DirectSound include file
+ *
+ **************************************************************************/
+
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#include <float.h>
+
+#ifndef DIRECTSOUND_VERSION
+#define DIRECTSOUND_VERSION 0x0900  /* Version 9.0 */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#ifndef __DSOUND_INCLUDED__
+#define __DSOUND_INCLUDED__
+
+/* Type definitions shared with Direct3D */
+
+#ifndef DX_SHARED_DEFINES
+
+typedef float D3DVALUE, *LPD3DVALUE;
+
+#ifndef D3DCOLOR_DEFINED
+typedef DWORD D3DCOLOR;
+#define D3DCOLOR_DEFINED
+#endif
+
+#ifndef LPD3DCOLOR_DEFINED
+typedef DWORD *LPD3DCOLOR;
+#define LPD3DCOLOR_DEFINED
+#endif
+
+#ifndef D3DVECTOR_DEFINED
+typedef struct _D3DVECTOR {
+    float x;
+    float y;
+    float z;
+} D3DVECTOR;
+#define D3DVECTOR_DEFINED
+#endif
+
+#ifndef LPD3DVECTOR_DEFINED
+typedef D3DVECTOR *LPD3DVECTOR;
+#define LPD3DVECTOR_DEFINED
+#endif
+
+#define DX_SHARED_DEFINES
+#endif // DX_SHARED_DEFINES
+
+#define _FACDS  0x878   /* DirectSound's facility code */
+#define MAKE_DSHRESULT(code)  MAKE_HRESULT(1, _FACDS, code)
+
+// DirectSound Component GUID {47D4D946-62E8-11CF-93BC-444553540000}
+DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+
+// DirectSound 8.0 Component GUID {3901CC3F-84B5-4FA4-BA35-AA8172B8A09B}
+DEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b);
+
+// DirectSound Capture Component GUID {B0210780-89CD-11D0-AF08-00A0C925CD16}
+DEFINE_GUID(CLSID_DirectSoundCapture, 0xb0210780, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
+
+// DirectSound 8.0 Capture Component GUID {E4BCAC13-7F99-4908-9A8E-74E3BF24B6E1}
+DEFINE_GUID(CLSID_DirectSoundCapture8, 0xe4bcac13, 0x7f99, 0x4908, 0x9a, 0x8e, 0x74, 0xe3, 0xbf, 0x24, 0xb6, 0xe1);
+
+// DirectSound Full Duplex Component GUID {FEA4300C-7959-4147-B26A-2377B9E7A91D}
+DEFINE_GUID(CLSID_DirectSoundFullDuplex, 0xfea4300c, 0x7959, 0x4147, 0xb2, 0x6a, 0x23, 0x77, 0xb9, 0xe7, 0xa9, 0x1d);
+
+
+// DirectSound default playback device GUID {DEF00000-9C6D-47ED-AAF1-4DDA8F2B5C03}
+DEFINE_GUID(DSDEVID_DefaultPlayback, 0xdef00000, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03);
+
+// DirectSound default capture device GUID {DEF00001-9C6D-47ED-AAF1-4DDA8F2B5C03}
+DEFINE_GUID(DSDEVID_DefaultCapture, 0xdef00001, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03);
+
+// DirectSound default device for voice playback {DEF00002-9C6D-47ED-AAF1-4DDA8F2B5C03}
+DEFINE_GUID(DSDEVID_DefaultVoicePlayback, 0xdef00002, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03);
+
+// DirectSound default device for voice capture {DEF00003-9C6D-47ED-AAF1-4DDA8F2B5C03}
+DEFINE_GUID(DSDEVID_DefaultVoiceCapture, 0xdef00003, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03);
+
+
+//
+// Forward declarations for interfaces.
+// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined
+//
+
+#ifdef __cplusplus
+struct IDirectSound;
+struct IDirectSoundBuffer;
+struct IDirectSound3DListener;
+struct IDirectSound3DBuffer;
+struct IDirectSoundCapture;
+struct IDirectSoundCaptureBuffer;
+struct IDirectSoundNotify;
+#endif // __cplusplus
+
+
+//
+// DirectSound 8.0 interfaces.
+//
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+#ifdef __cplusplus
+struct IDirectSound8;
+struct IDirectSoundBuffer8;
+struct IDirectSoundCaptureBuffer8;
+struct IDirectSoundFXGargle;
+struct IDirectSoundFXChorus;
+struct IDirectSoundFXFlanger;
+struct IDirectSoundFXEcho;
+struct IDirectSoundFXDistortion;
+struct IDirectSoundFXCompressor;
+struct IDirectSoundFXParamEq;
+struct IDirectSoundFXWavesReverb;
+struct IDirectSoundFXI3DL2Reverb;
+struct IDirectSoundCaptureFXAec;
+struct IDirectSoundCaptureFXNoiseSuppress;
+struct IDirectSoundFullDuplex;
+#endif // __cplusplus
+
+// IDirectSound8, IDirectSoundBuffer8 and IDirectSoundCaptureBuffer8 are the
+// only DirectSound 7.0 interfaces with changed functionality in version 8.0.
+// The other level 8 interfaces as equivalent to their level 7 counterparts:
+
+#define IDirectSoundCapture8            IDirectSoundCapture
+#define IDirectSound3DListener8         IDirectSound3DListener
+#define IDirectSound3DBuffer8           IDirectSound3DBuffer
+#define IDirectSoundNotify8             IDirectSoundNotify
+#define IDirectSoundFXGargle8           IDirectSoundFXGargle
+#define IDirectSoundFXChorus8           IDirectSoundFXChorus
+#define IDirectSoundFXFlanger8          IDirectSoundFXFlanger
+#define IDirectSoundFXEcho8             IDirectSoundFXEcho
+#define IDirectSoundFXDistortion8       IDirectSoundFXDistortion
+#define IDirectSoundFXCompressor8       IDirectSoundFXCompressor
+#define IDirectSoundFXParamEq8          IDirectSoundFXParamEq
+#define IDirectSoundFXWavesReverb8      IDirectSoundFXWavesReverb
+#define IDirectSoundFXI3DL2Reverb8      IDirectSoundFXI3DL2Reverb
+#define IDirectSoundCaptureFXAec8       IDirectSoundCaptureFXAec
+#define IDirectSoundCaptureFXNoiseSuppress8 IDirectSoundCaptureFXNoiseSuppress
+#define IDirectSoundFullDuplex8         IDirectSoundFullDuplex
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+typedef struct IDirectSound                 *LPDIRECTSOUND;
+typedef struct IDirectSoundBuffer           *LPDIRECTSOUNDBUFFER;
+typedef struct IDirectSound3DListener       *LPDIRECTSOUND3DLISTENER;
+typedef struct IDirectSound3DBuffer         *LPDIRECTSOUND3DBUFFER;
+typedef struct IDirectSoundCapture          *LPDIRECTSOUNDCAPTURE;
+typedef struct IDirectSoundCaptureBuffer    *LPDIRECTSOUNDCAPTUREBUFFER;
+typedef struct IDirectSoundNotify           *LPDIRECTSOUNDNOTIFY;
+
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+typedef struct IDirectSoundFXGargle         *LPDIRECTSOUNDFXGARGLE;
+typedef struct IDirectSoundFXChorus         *LPDIRECTSOUNDFXCHORUS;
+typedef struct IDirectSoundFXFlanger        *LPDIRECTSOUNDFXFLANGER;
+typedef struct IDirectSoundFXEcho           *LPDIRECTSOUNDFXECHO;
+typedef struct IDirectSoundFXDistortion     *LPDIRECTSOUNDFXDISTORTION;
+typedef struct IDirectSoundFXCompressor     *LPDIRECTSOUNDFXCOMPRESSOR;
+typedef struct IDirectSoundFXParamEq        *LPDIRECTSOUNDFXPARAMEQ;
+typedef struct IDirectSoundFXWavesReverb    *LPDIRECTSOUNDFXWAVESREVERB;
+typedef struct IDirectSoundFXI3DL2Reverb    *LPDIRECTSOUNDFXI3DL2REVERB;
+typedef struct IDirectSoundCaptureFXAec     *LPDIRECTSOUNDCAPTUREFXAEC;
+typedef struct IDirectSoundCaptureFXNoiseSuppress *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS;
+typedef struct IDirectSoundFullDuplex       *LPDIRECTSOUNDFULLDUPLEX;
+
+typedef struct IDirectSound8                *LPDIRECTSOUND8;
+typedef struct IDirectSoundBuffer8          *LPDIRECTSOUNDBUFFER8;
+typedef struct IDirectSound3DListener8      *LPDIRECTSOUND3DLISTENER8;
+typedef struct IDirectSound3DBuffer8        *LPDIRECTSOUND3DBUFFER8;
+typedef struct IDirectSoundCapture8         *LPDIRECTSOUNDCAPTURE8;
+typedef struct IDirectSoundCaptureBuffer8   *LPDIRECTSOUNDCAPTUREBUFFER8;
+typedef struct IDirectSoundNotify8          *LPDIRECTSOUNDNOTIFY8;
+typedef struct IDirectSoundFXGargle8        *LPDIRECTSOUNDFXGARGLE8;
+typedef struct IDirectSoundFXChorus8        *LPDIRECTSOUNDFXCHORUS8;
+typedef struct IDirectSoundFXFlanger8       *LPDIRECTSOUNDFXFLANGER8;
+typedef struct IDirectSoundFXEcho8          *LPDIRECTSOUNDFXECHO8;
+typedef struct IDirectSoundFXDistortion8    *LPDIRECTSOUNDFXDISTORTION8;
+typedef struct IDirectSoundFXCompressor8    *LPDIRECTSOUNDFXCOMPRESSOR8;
+typedef struct IDirectSoundFXParamEq8       *LPDIRECTSOUNDFXPARAMEQ8;
+typedef struct IDirectSoundFXWavesReverb8   *LPDIRECTSOUNDFXWAVESREVERB8;
+typedef struct IDirectSoundFXI3DL2Reverb8   *LPDIRECTSOUNDFXI3DL2REVERB8;
+typedef struct IDirectSoundCaptureFXAec8    *LPDIRECTSOUNDCAPTUREFXAEC8;
+typedef struct IDirectSoundCaptureFXNoiseSuppress8 *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS8;
+typedef struct IDirectSoundFullDuplex8      *LPDIRECTSOUNDFULLDUPLEX8;
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+//
+// IID definitions for the unchanged DirectSound 8.0 interfaces
+//
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+#define IID_IDirectSoundCapture8            IID_IDirectSoundCapture
+#define IID_IDirectSound3DListener8         IID_IDirectSound3DListener
+#define IID_IDirectSound3DBuffer8           IID_IDirectSound3DBuffer
+#define IID_IDirectSoundNotify8             IID_IDirectSoundNotify
+#define IID_IDirectSoundFXGargle8           IID_IDirectSoundFXGargle
+#define IID_IDirectSoundFXChorus8           IID_IDirectSoundFXChorus
+#define IID_IDirectSoundFXFlanger8          IID_IDirectSoundFXFlanger
+#define IID_IDirectSoundFXEcho8             IID_IDirectSoundFXEcho
+#define IID_IDirectSoundFXDistortion8       IID_IDirectSoundFXDistortion
+#define IID_IDirectSoundFXCompressor8       IID_IDirectSoundFXCompressor
+#define IID_IDirectSoundFXParamEq8          IID_IDirectSoundFXParamEq
+#define IID_IDirectSoundFXWavesReverb8      IID_IDirectSoundFXWavesReverb
+#define IID_IDirectSoundFXI3DL2Reverb8      IID_IDirectSoundFXI3DL2Reverb
+#define IID_IDirectSoundCaptureFXAec8       IID_IDirectSoundCaptureFXAec
+#define IID_IDirectSoundCaptureFXNoiseSuppress8 IID_IDirectSoundCaptureFXNoiseSuppress
+#define IID_IDirectSoundFullDuplex8         IID_IDirectSoundFullDuplex
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+//
+// Compatibility typedefs
+//
+
+#ifndef _LPCWAVEFORMATEX_DEFINED
+#define _LPCWAVEFORMATEX_DEFINED
+typedef const WAVEFORMATEX *LPCWAVEFORMATEX;
+#endif // _LPCWAVEFORMATEX_DEFINED
+
+#ifndef __LPCGUID_DEFINED__
+#define __LPCGUID_DEFINED__
+typedef const GUID *LPCGUID;
+#endif // __LPCGUID_DEFINED__
+
+typedef LPDIRECTSOUND *LPLPDIRECTSOUND;
+typedef LPDIRECTSOUNDBUFFER *LPLPDIRECTSOUNDBUFFER;
+typedef LPDIRECTSOUND3DLISTENER *LPLPDIRECTSOUND3DLISTENER;
+typedef LPDIRECTSOUND3DBUFFER *LPLPDIRECTSOUND3DBUFFER;
+typedef LPDIRECTSOUNDCAPTURE *LPLPDIRECTSOUNDCAPTURE;
+typedef LPDIRECTSOUNDCAPTUREBUFFER *LPLPDIRECTSOUNDCAPTUREBUFFER;
+typedef LPDIRECTSOUNDNOTIFY *LPLPDIRECTSOUNDNOTIFY;
+
+#if DIRECTSOUND_VERSION >= 0x0800
+typedef LPDIRECTSOUND8 *LPLPDIRECTSOUND8;
+typedef LPDIRECTSOUNDBUFFER8 *LPLPDIRECTSOUNDBUFFER8;
+typedef LPDIRECTSOUNDCAPTURE8 *LPLPDIRECTSOUNDCAPTURE8;
+typedef LPDIRECTSOUNDCAPTUREBUFFER8 *LPLPDIRECTSOUNDCAPTUREBUFFER8;
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+//
+// Structures
+//
+
+typedef struct _DSCAPS
+{
+    DWORD           dwSize;
+    DWORD           dwFlags;
+    DWORD           dwMinSecondarySampleRate;
+    DWORD           dwMaxSecondarySampleRate;
+    DWORD           dwPrimaryBuffers;
+    DWORD           dwMaxHwMixingAllBuffers;
+    DWORD           dwMaxHwMixingStaticBuffers;
+    DWORD           dwMaxHwMixingStreamingBuffers;
+    DWORD           dwFreeHwMixingAllBuffers;
+    DWORD           dwFreeHwMixingStaticBuffers;
+    DWORD           dwFreeHwMixingStreamingBuffers;
+    DWORD           dwMaxHw3DAllBuffers;
+    DWORD           dwMaxHw3DStaticBuffers;
+    DWORD           dwMaxHw3DStreamingBuffers;
+    DWORD           dwFreeHw3DAllBuffers;
+    DWORD           dwFreeHw3DStaticBuffers;
+    DWORD           dwFreeHw3DStreamingBuffers;
+    DWORD           dwTotalHwMemBytes;
+    DWORD           dwFreeHwMemBytes;
+    DWORD           dwMaxContigFreeHwMemBytes;
+    DWORD           dwUnlockTransferRateHwBuffers;
+    DWORD           dwPlayCpuOverheadSwBuffers;
+    DWORD           dwReserved1;
+    DWORD           dwReserved2;
+} DSCAPS, *LPDSCAPS;
+
+typedef const DSCAPS *LPCDSCAPS;
+
+typedef struct _DSBCAPS
+{
+    DWORD           dwSize;
+    DWORD           dwFlags;
+    DWORD           dwBufferBytes;
+    DWORD           dwUnlockTransferRate;
+    DWORD           dwPlayCpuOverhead;
+} DSBCAPS, *LPDSBCAPS;
+
+typedef const DSBCAPS *LPCDSBCAPS;
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+    typedef struct _DSEFFECTDESC
+    {
+        DWORD       dwSize;
+        DWORD       dwFlags;
+        GUID        guidDSFXClass;
+        DWORD_PTR   dwReserved1;
+        DWORD_PTR   dwReserved2;
+    } DSEFFECTDESC, *LPDSEFFECTDESC;
+    typedef const DSEFFECTDESC *LPCDSEFFECTDESC;
+
+    #define DSFX_LOCHARDWARE    0x00000001
+    #define DSFX_LOCSOFTWARE    0x00000002
+
+    enum
+    {
+        DSFXR_PRESENT,          // 0
+        DSFXR_LOCHARDWARE,      // 1
+        DSFXR_LOCSOFTWARE,      // 2
+        DSFXR_UNALLOCATED,      // 3
+        DSFXR_FAILED,           // 4
+        DSFXR_UNKNOWN,          // 5
+        DSFXR_SENDLOOP          // 6
+    };
+
+    typedef struct _DSCEFFECTDESC
+    {
+        DWORD       dwSize;
+        DWORD       dwFlags;
+        GUID        guidDSCFXClass;
+        GUID        guidDSCFXInstance;
+        DWORD       dwReserved1;
+        DWORD       dwReserved2;
+    } DSCEFFECTDESC, *LPDSCEFFECTDESC;
+    typedef const DSCEFFECTDESC *LPCDSCEFFECTDESC;
+
+    #define DSCFX_LOCHARDWARE   0x00000001
+    #define DSCFX_LOCSOFTWARE   0x00000002
+
+    #define DSCFXR_LOCHARDWARE  0x00000010
+    #define DSCFXR_LOCSOFTWARE  0x00000020
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+typedef struct _DSBUFFERDESC
+{
+    DWORD           dwSize;
+    DWORD           dwFlags;
+    DWORD           dwBufferBytes;
+    DWORD           dwReserved;
+    LPWAVEFORMATEX  lpwfxFormat;
+#if DIRECTSOUND_VERSION >= 0x0700
+    GUID            guid3DAlgorithm;
+#endif
+} DSBUFFERDESC, *LPDSBUFFERDESC;
+
+typedef const DSBUFFERDESC *LPCDSBUFFERDESC;
+
+// Older version of this structure:
+
+typedef struct _DSBUFFERDESC1
+{
+    DWORD           dwSize;
+    DWORD           dwFlags;
+    DWORD           dwBufferBytes;
+    DWORD           dwReserved;
+    LPWAVEFORMATEX  lpwfxFormat;
+} DSBUFFERDESC1, *LPDSBUFFERDESC1;
+
+typedef const DSBUFFERDESC1 *LPCDSBUFFERDESC1;
+
+typedef struct _DS3DBUFFER
+{
+    DWORD           dwSize;
+    D3DVECTOR       vPosition;
+    D3DVECTOR       vVelocity;
+    DWORD           dwInsideConeAngle;
+    DWORD           dwOutsideConeAngle;
+    D3DVECTOR       vConeOrientation;
+    LONG            lConeOutsideVolume;
+    D3DVALUE        flMinDistance;
+    D3DVALUE        flMaxDistance;
+    DWORD           dwMode;
+} DS3DBUFFER, *LPDS3DBUFFER;
+
+typedef const DS3DBUFFER *LPCDS3DBUFFER;
+
+typedef struct _DS3DLISTENER
+{
+    DWORD           dwSize;
+    D3DVECTOR       vPosition;
+    D3DVECTOR       vVelocity;
+    D3DVECTOR       vOrientFront;
+    D3DVECTOR       vOrientTop;
+    D3DVALUE        flDistanceFactor;
+    D3DVALUE        flRolloffFactor;
+    D3DVALUE        flDopplerFactor;
+} DS3DLISTENER, *LPDS3DLISTENER;
+
+typedef const DS3DLISTENER *LPCDS3DLISTENER;
+
+typedef struct _DSCCAPS
+{
+    DWORD           dwSize;
+    DWORD           dwFlags;
+    DWORD           dwFormats;
+    DWORD           dwChannels;
+} DSCCAPS, *LPDSCCAPS;
+
+typedef const DSCCAPS *LPCDSCCAPS;
+
+typedef struct _DSCBUFFERDESC1
+{
+    DWORD           dwSize;
+    DWORD           dwFlags;
+    DWORD           dwBufferBytes;
+    DWORD           dwReserved;
+    LPWAVEFORMATEX  lpwfxFormat;
+} DSCBUFFERDESC1, *LPDSCBUFFERDESC1;
+
+typedef struct _DSCBUFFERDESC
+{
+    DWORD           dwSize;
+    DWORD           dwFlags;
+    DWORD           dwBufferBytes;
+    DWORD           dwReserved;
+    LPWAVEFORMATEX  lpwfxFormat;
+#if DIRECTSOUND_VERSION >= 0x0800
+    DWORD           dwFXCount;
+    LPDSCEFFECTDESC lpDSCFXDesc;
+#endif
+} DSCBUFFERDESC, *LPDSCBUFFERDESC;
+
+typedef const DSCBUFFERDESC *LPCDSCBUFFERDESC;
+
+typedef struct _DSCBCAPS
+{
+    DWORD           dwSize;
+    DWORD           dwFlags;
+    DWORD           dwBufferBytes;
+    DWORD           dwReserved;
+} DSCBCAPS, *LPDSCBCAPS;
+
+typedef const DSCBCAPS *LPCDSCBCAPS;
+
+typedef struct _DSBPOSITIONNOTIFY
+{
+    DWORD           dwOffset;
+    HANDLE          hEventNotify;
+} DSBPOSITIONNOTIFY, *LPDSBPOSITIONNOTIFY;
+
+typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY;
+
+//
+// DirectSound API
+//
+
+typedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID, LPCSTR, LPCSTR, LPVOID);
+typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID, LPCWSTR, LPCWSTR, LPVOID);
+
+extern HRESULT WINAPI DirectSoundCreate(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter);
+extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
+extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext);
+
+extern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE *ppDSC, LPUNKNOWN pUnkOuter);
+extern HRESULT WINAPI DirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
+extern HRESULT WINAPI DirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext);
+
+#if DIRECTSOUND_VERSION >= 0x0800
+extern HRESULT WINAPI DirectSoundCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter);
+extern HRESULT WINAPI DirectSoundCaptureCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE8 *ppDSC8, LPUNKNOWN pUnkOuter);
+extern HRESULT WINAPI DirectSoundFullDuplexCreate(LPCGUID pcGuidCaptureDevice, LPCGUID pcGuidRenderDevice,
+        LPCDSCBUFFERDESC pcDSCBufferDesc, LPCDSBUFFERDESC pcDSBufferDesc, HWND hWnd,
+        DWORD dwLevel, LPDIRECTSOUNDFULLDUPLEX* ppDSFD, LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
+        LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, LPUNKNOWN pUnkOuter);
+#define DirectSoundFullDuplexCreate8 DirectSoundFullDuplexCreate
+
+extern HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest);
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+#ifdef UNICODE
+#define LPDSENUMCALLBACK            LPDSENUMCALLBACKW
+#define DirectSoundEnumerate        DirectSoundEnumerateW
+#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateW
+#else // UNICODE
+#define LPDSENUMCALLBACK            LPDSENUMCALLBACKA
+#define DirectSoundEnumerate        DirectSoundEnumerateA
+#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateA
+#endif // UNICODE
+
+//
+// IUnknown
+//
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#ifndef IUnknown_QueryInterface
+#define IUnknown_QueryInterface(p,a,b)  (p)->lpVtbl->QueryInterface(p,a,b)
+#endif // IUnknown_QueryInterface
+#ifndef IUnknown_AddRef
+#define IUnknown_AddRef(p)              (p)->lpVtbl->AddRef(p)
+#endif // IUnknown_AddRef
+#ifndef IUnknown_Release
+#define IUnknown_Release(p)             (p)->lpVtbl->Release(p)
+#endif // IUnknown_Release
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#ifndef IUnknown_QueryInterface
+#define IUnknown_QueryInterface(p,a,b)  (p)->QueryInterface(a,b)
+#endif // IUnknown_QueryInterface
+#ifndef IUnknown_AddRef
+#define IUnknown_AddRef(p)              (p)->AddRef()
+#endif // IUnknown_AddRef
+#ifndef IUnknown_Release
+#define IUnknown_Release(p)             (p)->Release()
+#endif // IUnknown_Release
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#ifndef __IReferenceClock_INTERFACE_DEFINED__
+#define __IReferenceClock_INTERFACE_DEFINED__
+
+typedef LONGLONG REFERENCE_TIME;
+typedef REFERENCE_TIME *LPREFERENCE_TIME;
+
+DEFINE_GUID(IID_IReferenceClock, 0x56a86897, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+
+#undef INTERFACE
+#define INTERFACE IReferenceClock
+
+DECLARE_INTERFACE_(IReferenceClock, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IReferenceClock methods
+    STDMETHOD(GetTime)              (THIS_ REFERENCE_TIME *pTime) PURE;
+    STDMETHOD(AdviseTime)           (THIS_ REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime,
+                                           HANDLE hEvent, LPDWORD pdwAdviseCookie) PURE;
+    STDMETHOD(AdvisePeriodic)       (THIS_ REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime,
+                                           HANDLE hSemaphore, LPDWORD pdwAdviseCookie) PURE;
+    STDMETHOD(Unadvise)             (THIS_ DWORD dwAdviseCookie) PURE;
+};
+
+#endif // __IReferenceClock_INTERFACE_DEFINED__
+
+#ifndef IReferenceClock_QueryInterface
+
+#define IReferenceClock_QueryInterface(p,a,b)      IUnknown_QueryInterface(p,a,b)
+#define IReferenceClock_AddRef(p)                  IUnknown_AddRef(p)
+#define IReferenceClock_Release(p)                 IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IReferenceClock_GetTime(p,a)               (p)->lpVtbl->GetTime(p,a)
+#define IReferenceClock_AdviseTime(p,a,b,c,d)      (p)->lpVtbl->AdviseTime(p,a,b,c,d)
+#define IReferenceClock_AdvisePeriodic(p,a,b,c,d)  (p)->lpVtbl->AdvisePeriodic(p,a,b,c,d)
+#define IReferenceClock_Unadvise(p,a)              (p)->lpVtbl->Unadvise(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IReferenceClock_GetTime(p,a)               (p)->GetTime(a)
+#define IReferenceClock_AdviseTime(p,a,b,c,d)      (p)->AdviseTime(a,b,c,d)
+#define IReferenceClock_AdvisePeriodic(p,a,b,c,d)  (p)->AdvisePeriodic(a,b,c,d)
+#define IReferenceClock_Unadvise(p,a)              (p)->Unadvise(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#endif // IReferenceClock_QueryInterface
+
+//
+// IDirectSound
+//
+
+DEFINE_GUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);
+
+#undef INTERFACE
+#define INTERFACE IDirectSound
+
+DECLARE_INTERFACE_(IDirectSound, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSound methods
+    STDMETHOD(CreateSoundBuffer)    (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE;
+    STDMETHOD(GetCaps)              (THIS_ LPDSCAPS pDSCaps) PURE;
+    STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE;
+    STDMETHOD(SetCooperativeLevel)  (THIS_ HWND hwnd, DWORD dwLevel) PURE;
+    STDMETHOD(Compact)              (THIS) PURE;
+    STDMETHOD(GetSpeakerConfig)     (THIS_ LPDWORD pdwSpeakerConfig) PURE;
+    STDMETHOD(SetSpeakerConfig)     (THIS_ DWORD dwSpeakerConfig) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPCGUID pcGuidDevice) PURE;
+};
+
+#define IDirectSound_QueryInterface(p,a,b)       IUnknown_QueryInterface(p,a,b)
+#define IDirectSound_AddRef(p)                   IUnknown_AddRef(p)
+#define IDirectSound_Release(p)                  IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound_CreateSoundBuffer(p,a,b,c)  (p)->lpVtbl->CreateSoundBuffer(p,a,b,c)
+#define IDirectSound_GetCaps(p,a)                (p)->lpVtbl->GetCaps(p,a)
+#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b)
+#define IDirectSound_SetCooperativeLevel(p,a,b)  (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectSound_Compact(p)                  (p)->lpVtbl->Compact(p)
+#define IDirectSound_GetSpeakerConfig(p,a)       (p)->lpVtbl->GetSpeakerConfig(p,a)
+#define IDirectSound_SetSpeakerConfig(p,b)       (p)->lpVtbl->SetSpeakerConfig(p,b)
+#define IDirectSound_Initialize(p,a)             (p)->lpVtbl->Initialize(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound_CreateSoundBuffer(p,a,b,c)  (p)->CreateSoundBuffer(a,b,c)
+#define IDirectSound_GetCaps(p,a)                (p)->GetCaps(a)
+#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->DuplicateSoundBuffer(a,b)
+#define IDirectSound_SetCooperativeLevel(p,a,b)  (p)->SetCooperativeLevel(a,b)
+#define IDirectSound_Compact(p)                  (p)->Compact()
+#define IDirectSound_GetSpeakerConfig(p,a)       (p)->GetSpeakerConfig(a)
+#define IDirectSound_SetSpeakerConfig(p,b)       (p)->SetSpeakerConfig(b)
+#define IDirectSound_Initialize(p,a)             (p)->Initialize(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+//
+// IDirectSound8
+//
+
+DEFINE_GUID(IID_IDirectSound8, 0xC50A7E93, 0xF395, 0x4834, 0x9E, 0xF6, 0x7F, 0xA9, 0x9D, 0xE5, 0x09, 0x66);
+
+#undef INTERFACE
+#define INTERFACE IDirectSound8
+
+DECLARE_INTERFACE_(IDirectSound8, IDirectSound)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSound methods
+    STDMETHOD(CreateSoundBuffer)    (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE;
+    STDMETHOD(GetCaps)              (THIS_ LPDSCAPS pDSCaps) PURE;
+    STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE;
+    STDMETHOD(SetCooperativeLevel)  (THIS_ HWND hwnd, DWORD dwLevel) PURE;
+    STDMETHOD(Compact)              (THIS) PURE;
+    STDMETHOD(GetSpeakerConfig)     (THIS_ LPDWORD pdwSpeakerConfig) PURE;
+    STDMETHOD(SetSpeakerConfig)     (THIS_ DWORD dwSpeakerConfig) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPCGUID pcGuidDevice) PURE;
+
+    // IDirectSound8 methods
+    STDMETHOD(VerifyCertification)  (THIS_ LPDWORD pdwCertified) PURE;
+};
+
+#define IDirectSound8_QueryInterface(p,a,b)       IDirectSound_QueryInterface(p,a,b)
+#define IDirectSound8_AddRef(p)                   IDirectSound_AddRef(p)
+#define IDirectSound8_Release(p)                  IDirectSound_Release(p)
+#define IDirectSound8_CreateSoundBuffer(p,a,b,c)  IDirectSound_CreateSoundBuffer(p,a,b,c)
+#define IDirectSound8_GetCaps(p,a)                IDirectSound_GetCaps(p,a)
+#define IDirectSound8_DuplicateSoundBuffer(p,a,b) IDirectSound_DuplicateSoundBuffer(p,a,b)
+#define IDirectSound8_SetCooperativeLevel(p,a,b)  IDirectSound_SetCooperativeLevel(p,a,b)
+#define IDirectSound8_Compact(p)                  IDirectSound_Compact(p)
+#define IDirectSound8_GetSpeakerConfig(p,a)       IDirectSound_GetSpeakerConfig(p,a)
+#define IDirectSound8_SetSpeakerConfig(p,a)       IDirectSound_SetSpeakerConfig(p,a)
+#define IDirectSound8_Initialize(p,a)             IDirectSound_Initialize(p,a)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound8_VerifyCertification(p,a)           (p)->lpVtbl->VerifyCertification(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound8_VerifyCertification(p,a)           (p)->VerifyCertification(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+//
+// IDirectSoundBuffer
+//
+
+DEFINE_GUID(IID_IDirectSoundBuffer, 0x279AFA85, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundBuffer
+
+DECLARE_INTERFACE_(IDirectSoundBuffer, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundBuffer methods
+    STDMETHOD(GetCaps)              (THIS_ LPDSBCAPS pDSBufferCaps) PURE;
+    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE;
+    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;
+    STDMETHOD(GetVolume)            (THIS_ LPLONG plVolume) PURE;
+    STDMETHOD(GetPan)               (THIS_ LPLONG plPan) PURE;
+    STDMETHOD(GetFrequency)         (THIS_ LPDWORD pdwFrequency) PURE;
+    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE;
+    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,
+                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;
+    STDMETHOD(Play)                 (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE;
+    STDMETHOD(SetCurrentPosition)   (THIS_ DWORD dwNewPosition) PURE;
+    STDMETHOD(SetFormat)            (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE;
+    STDMETHOD(SetVolume)            (THIS_ LONG lVolume) PURE;
+    STDMETHOD(SetPan)               (THIS_ LONG lPan) PURE;
+    STDMETHOD(SetFrequency)         (THIS_ DWORD dwFrequency) PURE;
+    STDMETHOD(Stop)                 (THIS) PURE;
+    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;
+    STDMETHOD(Restore)              (THIS) PURE;
+};
+
+#define IDirectSoundBuffer_QueryInterface(p,a,b)        IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundBuffer_AddRef(p)                    IUnknown_AddRef(p)
+#define IDirectSoundBuffer_Release(p)                   IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundBuffer_GetCaps(p,a)                 (p)->lpVtbl->GetCaps(p,a)
+#define IDirectSoundBuffer_GetCurrentPosition(p,a,b)    (p)->lpVtbl->GetCurrentPosition(p,a,b)
+#define IDirectSoundBuffer_GetFormat(p,a,b,c)           (p)->lpVtbl->GetFormat(p,a,b,c)
+#define IDirectSoundBuffer_GetVolume(p,a)               (p)->lpVtbl->GetVolume(p,a)
+#define IDirectSoundBuffer_GetPan(p,a)                  (p)->lpVtbl->GetPan(p,a)
+#define IDirectSoundBuffer_GetFrequency(p,a)            (p)->lpVtbl->GetFrequency(p,a)
+#define IDirectSoundBuffer_GetStatus(p,a)               (p)->lpVtbl->GetStatus(p,a)
+#define IDirectSoundBuffer_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g)        (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g)
+#define IDirectSoundBuffer_Play(p,a,b,c)                (p)->lpVtbl->Play(p,a,b,c)
+#define IDirectSoundBuffer_SetCurrentPosition(p,a)      (p)->lpVtbl->SetCurrentPosition(p,a)
+#define IDirectSoundBuffer_SetFormat(p,a)               (p)->lpVtbl->SetFormat(p,a)
+#define IDirectSoundBuffer_SetVolume(p,a)               (p)->lpVtbl->SetVolume(p,a)
+#define IDirectSoundBuffer_SetPan(p,a)                  (p)->lpVtbl->SetPan(p,a)
+#define IDirectSoundBuffer_SetFrequency(p,a)            (p)->lpVtbl->SetFrequency(p,a)
+#define IDirectSoundBuffer_Stop(p)                      (p)->lpVtbl->Stop(p)
+#define IDirectSoundBuffer_Unlock(p,a,b,c,d)            (p)->lpVtbl->Unlock(p,a,b,c,d)
+#define IDirectSoundBuffer_Restore(p)                   (p)->lpVtbl->Restore(p)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundBuffer_GetCaps(p,a)                 (p)->GetCaps(a)
+#define IDirectSoundBuffer_GetCurrentPosition(p,a,b)    (p)->GetCurrentPosition(a,b)
+#define IDirectSoundBuffer_GetFormat(p,a,b,c)           (p)->GetFormat(a,b,c)
+#define IDirectSoundBuffer_GetVolume(p,a)               (p)->GetVolume(a)
+#define IDirectSoundBuffer_GetPan(p,a)                  (p)->GetPan(a)
+#define IDirectSoundBuffer_GetFrequency(p,a)            (p)->GetFrequency(a)
+#define IDirectSoundBuffer_GetStatus(p,a)               (p)->GetStatus(a)
+#define IDirectSoundBuffer_Initialize(p,a,b)            (p)->Initialize(a,b)
+#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g)        (p)->Lock(a,b,c,d,e,f,g)
+#define IDirectSoundBuffer_Play(p,a,b,c)                (p)->Play(a,b,c)
+#define IDirectSoundBuffer_SetCurrentPosition(p,a)      (p)->SetCurrentPosition(a)
+#define IDirectSoundBuffer_SetFormat(p,a)               (p)->SetFormat(a)
+#define IDirectSoundBuffer_SetVolume(p,a)               (p)->SetVolume(a)
+#define IDirectSoundBuffer_SetPan(p,a)                  (p)->SetPan(a)
+#define IDirectSoundBuffer_SetFrequency(p,a)            (p)->SetFrequency(a)
+#define IDirectSoundBuffer_Stop(p)                      (p)->Stop()
+#define IDirectSoundBuffer_Unlock(p,a,b,c,d)            (p)->Unlock(a,b,c,d)
+#define IDirectSoundBuffer_Restore(p)                   (p)->Restore()
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+//
+// IDirectSoundBuffer8
+//
+
+DEFINE_GUID(IID_IDirectSoundBuffer8, 0x6825a449, 0x7524, 0x4d82, 0x92, 0x0f, 0x50, 0xe3, 0x6a, 0xb3, 0xab, 0x1e);
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundBuffer8
+
+DECLARE_INTERFACE_(IDirectSoundBuffer8, IDirectSoundBuffer)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundBuffer methods
+    STDMETHOD(GetCaps)              (THIS_ LPDSBCAPS pDSBufferCaps) PURE;
+    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE;
+    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;
+    STDMETHOD(GetVolume)            (THIS_ LPLONG plVolume) PURE;
+    STDMETHOD(GetPan)               (THIS_ LPLONG plPan) PURE;
+    STDMETHOD(GetFrequency)         (THIS_ LPDWORD pdwFrequency) PURE;
+    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE;
+    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,
+                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;
+    STDMETHOD(Play)                 (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE;
+    STDMETHOD(SetCurrentPosition)   (THIS_ DWORD dwNewPosition) PURE;
+    STDMETHOD(SetFormat)            (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE;
+    STDMETHOD(SetVolume)            (THIS_ LONG lVolume) PURE;
+    STDMETHOD(SetPan)               (THIS_ LONG lPan) PURE;
+    STDMETHOD(SetFrequency)         (THIS_ DWORD dwFrequency) PURE;
+    STDMETHOD(Stop)                 (THIS) PURE;
+    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;
+    STDMETHOD(Restore)              (THIS) PURE;
+
+    // IDirectSoundBuffer8 methods
+    STDMETHOD(SetFX)                (THIS_ DWORD dwEffectsCount, LPDSEFFECTDESC pDSFXDesc, LPDWORD pdwResultCodes) PURE;
+    STDMETHOD(AcquireResources)     (THIS_ DWORD dwFlags, DWORD dwEffectsCount, LPDWORD pdwResultCodes) PURE;
+    STDMETHOD(GetObjectInPath)      (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE;
+};
+
+// Special GUID meaning "select all objects" for use in GetObjectInPath()
+DEFINE_GUID(GUID_All_Objects, 0xaa114de5, 0xc262, 0x4169, 0xa1, 0xc8, 0x23, 0xd6, 0x98, 0xcc, 0x73, 0xb5);
+
+#define IDirectSoundBuffer8_QueryInterface(p,a,b)           IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundBuffer8_AddRef(p)                       IUnknown_AddRef(p)
+#define IDirectSoundBuffer8_Release(p)                      IUnknown_Release(p)
+
+#define IDirectSoundBuffer8_GetCaps(p,a)                    IDirectSoundBuffer_GetCaps(p,a)
+#define IDirectSoundBuffer8_GetCurrentPosition(p,a,b)       IDirectSoundBuffer_GetCurrentPosition(p,a,b)
+#define IDirectSoundBuffer8_GetFormat(p,a,b,c)              IDirectSoundBuffer_GetFormat(p,a,b,c)
+#define IDirectSoundBuffer8_GetVolume(p,a)                  IDirectSoundBuffer_GetVolume(p,a)
+#define IDirectSoundBuffer8_GetPan(p,a)                     IDirectSoundBuffer_GetPan(p,a)
+#define IDirectSoundBuffer8_GetFrequency(p,a)               IDirectSoundBuffer_GetFrequency(p,a)
+#define IDirectSoundBuffer8_GetStatus(p,a)                  IDirectSoundBuffer_GetStatus(p,a)
+#define IDirectSoundBuffer8_Initialize(p,a,b)               IDirectSoundBuffer_Initialize(p,a,b)
+#define IDirectSoundBuffer8_Lock(p,a,b,c,d,e,f,g)           IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g)
+#define IDirectSoundBuffer8_Play(p,a,b,c)                   IDirectSoundBuffer_Play(p,a,b,c)
+#define IDirectSoundBuffer8_SetCurrentPosition(p,a)         IDirectSoundBuffer_SetCurrentPosition(p,a)
+#define IDirectSoundBuffer8_SetFormat(p,a)                  IDirectSoundBuffer_SetFormat(p,a)
+#define IDirectSoundBuffer8_SetVolume(p,a)                  IDirectSoundBuffer_SetVolume(p,a)
+#define IDirectSoundBuffer8_SetPan(p,a)                     IDirectSoundBuffer_SetPan(p,a)
+#define IDirectSoundBuffer8_SetFrequency(p,a)               IDirectSoundBuffer_SetFrequency(p,a)
+#define IDirectSoundBuffer8_Stop(p)                         IDirectSoundBuffer_Stop(p)
+#define IDirectSoundBuffer8_Unlock(p,a,b,c,d)               IDirectSoundBuffer_Unlock(p,a,b,c,d)
+#define IDirectSoundBuffer8_Restore(p)                      IDirectSoundBuffer_Restore(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundBuffer8_SetFX(p,a,b,c)                  (p)->lpVtbl->SetFX(p,a,b,c)
+#define IDirectSoundBuffer8_AcquireResources(p,a,b,c)       (p)->lpVtbl->AcquireResources(p,a,b,c)
+#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d)      (p)->lpVtbl->GetObjectInPath(p,a,b,c,d)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundBuffer8_SetFX(p,a,b,c)                  (p)->SetFX(a,b,c)
+#define IDirectSoundBuffer8_AcquireResources(p,a,b,c)       (p)->AcquireResources(a,b,c)
+#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d)      (p)->GetObjectInPath(a,b,c,d)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+//
+// IDirectSound3DListener
+//
+
+DEFINE_GUID(IID_IDirectSound3DListener, 0x279AFA84, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);
+
+#undef INTERFACE
+#define INTERFACE IDirectSound3DListener
+
+DECLARE_INTERFACE_(IDirectSound3DListener, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)           (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)            (THIS) PURE;
+    STDMETHOD_(ULONG,Release)           (THIS) PURE;
+
+    // IDirectSound3DListener methods
+    STDMETHOD(GetAllParameters)         (THIS_ LPDS3DLISTENER pListener) PURE;
+    STDMETHOD(GetDistanceFactor)        (THIS_ D3DVALUE* pflDistanceFactor) PURE;
+    STDMETHOD(GetDopplerFactor)         (THIS_ D3DVALUE* pflDopplerFactor) PURE;
+    STDMETHOD(GetOrientation)           (THIS_ D3DVECTOR* pvOrientFront, D3DVECTOR* pvOrientTop) PURE;
+    STDMETHOD(GetPosition)              (THIS_ D3DVECTOR* pvPosition) PURE;
+    STDMETHOD(GetRolloffFactor)         (THIS_ D3DVALUE* pflRolloffFactor) PURE;
+    STDMETHOD(GetVelocity)              (THIS_ D3DVECTOR* pvVelocity) PURE;
+    STDMETHOD(SetAllParameters)         (THIS_ LPCDS3DLISTENER pcListener, DWORD dwApply) PURE;
+    STDMETHOD(SetDistanceFactor)        (THIS_ D3DVALUE flDistanceFactor, DWORD dwApply) PURE;
+    STDMETHOD(SetDopplerFactor)         (THIS_ D3DVALUE flDopplerFactor, DWORD dwApply) PURE;
+    STDMETHOD(SetOrientation)           (THIS_ D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
+                                               D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop, DWORD dwApply) PURE;
+    STDMETHOD(SetPosition)              (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;
+    STDMETHOD(SetRolloffFactor)         (THIS_ D3DVALUE flRolloffFactor, DWORD dwApply) PURE;
+    STDMETHOD(SetVelocity)              (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;
+    STDMETHOD(CommitDeferredSettings)   (THIS) PURE;
+};
+
+#define IDirectSound3DListener_QueryInterface(p,a,b)            IUnknown_QueryInterface(p,a,b)
+#define IDirectSound3DListener_AddRef(p)                        IUnknown_AddRef(p)
+#define IDirectSound3DListener_Release(p)                       IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound3DListener_GetAllParameters(p,a)            (p)->lpVtbl->GetAllParameters(p,a)
+#define IDirectSound3DListener_GetDistanceFactor(p,a)           (p)->lpVtbl->GetDistanceFactor(p,a)
+#define IDirectSound3DListener_GetDopplerFactor(p,a)            (p)->lpVtbl->GetDopplerFactor(p,a)
+#define IDirectSound3DListener_GetOrientation(p,a,b)            (p)->lpVtbl->GetOrientation(p,a,b)
+#define IDirectSound3DListener_GetPosition(p,a)                 (p)->lpVtbl->GetPosition(p,a)
+#define IDirectSound3DListener_GetRolloffFactor(p,a)            (p)->lpVtbl->GetRolloffFactor(p,a)
+#define IDirectSound3DListener_GetVelocity(p,a)                 (p)->lpVtbl->GetVelocity(p,a)
+#define IDirectSound3DListener_SetAllParameters(p,a,b)          (p)->lpVtbl->SetAllParameters(p,a,b)
+#define IDirectSound3DListener_SetDistanceFactor(p,a,b)         (p)->lpVtbl->SetDistanceFactor(p,a,b)
+#define IDirectSound3DListener_SetDopplerFactor(p,a,b)          (p)->lpVtbl->SetDopplerFactor(p,a,b)
+#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g)  (p)->lpVtbl->SetOrientation(p,a,b,c,d,e,f,g)
+#define IDirectSound3DListener_SetPosition(p,a,b,c,d)           (p)->lpVtbl->SetPosition(p,a,b,c,d)
+#define IDirectSound3DListener_SetRolloffFactor(p,a,b)          (p)->lpVtbl->SetRolloffFactor(p,a,b)
+#define IDirectSound3DListener_SetVelocity(p,a,b,c,d)           (p)->lpVtbl->SetVelocity(p,a,b,c,d)
+#define IDirectSound3DListener_CommitDeferredSettings(p)        (p)->lpVtbl->CommitDeferredSettings(p)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound3DListener_GetAllParameters(p,a)            (p)->GetAllParameters(a)
+#define IDirectSound3DListener_GetDistanceFactor(p,a)           (p)->GetDistanceFactor(a)
+#define IDirectSound3DListener_GetDopplerFactor(p,a)            (p)->GetDopplerFactor(a)
+#define IDirectSound3DListener_GetOrientation(p,a,b)            (p)->GetOrientation(a,b)
+#define IDirectSound3DListener_GetPosition(p,a)                 (p)->GetPosition(a)
+#define IDirectSound3DListener_GetRolloffFactor(p,a)            (p)->GetRolloffFactor(a)
+#define IDirectSound3DListener_GetVelocity(p,a)                 (p)->GetVelocity(a)
+#define IDirectSound3DListener_SetAllParameters(p,a,b)          (p)->SetAllParameters(a,b)
+#define IDirectSound3DListener_SetDistanceFactor(p,a,b)         (p)->SetDistanceFactor(a,b)
+#define IDirectSound3DListener_SetDopplerFactor(p,a,b)          (p)->SetDopplerFactor(a,b)
+#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g)  (p)->SetOrientation(a,b,c,d,e,f,g)
+#define IDirectSound3DListener_SetPosition(p,a,b,c,d)           (p)->SetPosition(a,b,c,d)
+#define IDirectSound3DListener_SetRolloffFactor(p,a,b)          (p)->SetRolloffFactor(a,b)
+#define IDirectSound3DListener_SetVelocity(p,a,b,c,d)           (p)->SetVelocity(a,b,c,d)
+#define IDirectSound3DListener_CommitDeferredSettings(p)        (p)->CommitDeferredSettings()
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSound3DBuffer
+//
+
+DEFINE_GUID(IID_IDirectSound3DBuffer, 0x279AFA86, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);
+
+#undef INTERFACE
+#define INTERFACE IDirectSound3DBuffer
+
+DECLARE_INTERFACE_(IDirectSound3DBuffer, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSound3DBuffer methods
+    STDMETHOD(GetAllParameters)     (THIS_ LPDS3DBUFFER pDs3dBuffer) PURE;
+    STDMETHOD(GetConeAngles)        (THIS_ LPDWORD pdwInsideConeAngle, LPDWORD pdwOutsideConeAngle) PURE;
+    STDMETHOD(GetConeOrientation)   (THIS_ D3DVECTOR* pvOrientation) PURE;
+    STDMETHOD(GetConeOutsideVolume) (THIS_ LPLONG plConeOutsideVolume) PURE;
+    STDMETHOD(GetMaxDistance)       (THIS_ D3DVALUE* pflMaxDistance) PURE;
+    STDMETHOD(GetMinDistance)       (THIS_ D3DVALUE* pflMinDistance) PURE;
+    STDMETHOD(GetMode)              (THIS_ LPDWORD pdwMode) PURE;
+    STDMETHOD(GetPosition)          (THIS_ D3DVECTOR* pvPosition) PURE;
+    STDMETHOD(GetVelocity)          (THIS_ D3DVECTOR* pvVelocity) PURE;
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDS3DBUFFER pcDs3dBuffer, DWORD dwApply) PURE;
+    STDMETHOD(SetConeAngles)        (THIS_ DWORD dwInsideConeAngle, DWORD dwOutsideConeAngle, DWORD dwApply) PURE;
+    STDMETHOD(SetConeOrientation)   (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;
+    STDMETHOD(SetConeOutsideVolume) (THIS_ LONG lConeOutsideVolume, DWORD dwApply) PURE;
+    STDMETHOD(SetMaxDistance)       (THIS_ D3DVALUE flMaxDistance, DWORD dwApply) PURE;
+    STDMETHOD(SetMinDistance)       (THIS_ D3DVALUE flMinDistance, DWORD dwApply) PURE;
+    STDMETHOD(SetMode)              (THIS_ DWORD dwMode, DWORD dwApply) PURE;
+    STDMETHOD(SetPosition)          (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;
+    STDMETHOD(SetVelocity)          (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;
+};
+
+#define IDirectSound3DBuffer_QueryInterface(p,a,b)          IUnknown_QueryInterface(p,a,b)
+#define IDirectSound3DBuffer_AddRef(p)                      IUnknown_AddRef(p)
+#define IDirectSound3DBuffer_Release(p)                     IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound3DBuffer_GetAllParameters(p,a)          (p)->lpVtbl->GetAllParameters(p,a)
+#define IDirectSound3DBuffer_GetConeAngles(p,a,b)           (p)->lpVtbl->GetConeAngles(p,a,b)
+#define IDirectSound3DBuffer_GetConeOrientation(p,a)        (p)->lpVtbl->GetConeOrientation(p,a)
+#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a)      (p)->lpVtbl->GetConeOutsideVolume(p,a)
+#define IDirectSound3DBuffer_GetPosition(p,a)               (p)->lpVtbl->GetPosition(p,a)
+#define IDirectSound3DBuffer_GetMinDistance(p,a)            (p)->lpVtbl->GetMinDistance(p,a)
+#define IDirectSound3DBuffer_GetMaxDistance(p,a)            (p)->lpVtbl->GetMaxDistance(p,a)
+#define IDirectSound3DBuffer_GetMode(p,a)                   (p)->lpVtbl->GetMode(p,a)
+#define IDirectSound3DBuffer_GetVelocity(p,a)               (p)->lpVtbl->GetVelocity(p,a)
+#define IDirectSound3DBuffer_SetAllParameters(p,a,b)        (p)->lpVtbl->SetAllParameters(p,a,b)
+#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c)         (p)->lpVtbl->SetConeAngles(p,a,b,c)
+#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d)  (p)->lpVtbl->SetConeOrientation(p,a,b,c,d)
+#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b)    (p)->lpVtbl->SetConeOutsideVolume(p,a,b)
+#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d)         (p)->lpVtbl->SetPosition(p,a,b,c,d)
+#define IDirectSound3DBuffer_SetMinDistance(p,a,b)          (p)->lpVtbl->SetMinDistance(p,a,b)
+#define IDirectSound3DBuffer_SetMaxDistance(p,a,b)          (p)->lpVtbl->SetMaxDistance(p,a,b)
+#define IDirectSound3DBuffer_SetMode(p,a,b)                 (p)->lpVtbl->SetMode(p,a,b)
+#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d)         (p)->lpVtbl->SetVelocity(p,a,b,c,d)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound3DBuffer_GetAllParameters(p,a)          (p)->GetAllParameters(a)
+#define IDirectSound3DBuffer_GetConeAngles(p,a,b)           (p)->GetConeAngles(a,b)
+#define IDirectSound3DBuffer_GetConeOrientation(p,a)        (p)->GetConeOrientation(a)
+#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a)      (p)->GetConeOutsideVolume(a)
+#define IDirectSound3DBuffer_GetPosition(p,a)               (p)->GetPosition(a)
+#define IDirectSound3DBuffer_GetMinDistance(p,a)            (p)->GetMinDistance(a)
+#define IDirectSound3DBuffer_GetMaxDistance(p,a)            (p)->GetMaxDistance(a)
+#define IDirectSound3DBuffer_GetMode(p,a)                   (p)->GetMode(a)
+#define IDirectSound3DBuffer_GetVelocity(p,a)               (p)->GetVelocity(a)
+#define IDirectSound3DBuffer_SetAllParameters(p,a,b)        (p)->SetAllParameters(a,b)
+#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c)         (p)->SetConeAngles(a,b,c)
+#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d)  (p)->SetConeOrientation(a,b,c,d)
+#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b)    (p)->SetConeOutsideVolume(a,b)
+#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d)         (p)->SetPosition(a,b,c,d)
+#define IDirectSound3DBuffer_SetMinDistance(p,a,b)          (p)->SetMinDistance(a,b)
+#define IDirectSound3DBuffer_SetMaxDistance(p,a,b)          (p)->SetMaxDistance(a,b)
+#define IDirectSound3DBuffer_SetMode(p,a,b)                 (p)->SetMode(a,b)
+#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d)         (p)->SetVelocity(a,b,c,d)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundCapture
+//
+
+DEFINE_GUID(IID_IDirectSoundCapture, 0xb0210781, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundCapture
+
+DECLARE_INTERFACE_(IDirectSoundCapture, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundCapture methods
+    STDMETHOD(CreateCaptureBuffer)  (THIS_ LPCDSCBUFFERDESC pcDSCBufferDesc, LPDIRECTSOUNDCAPTUREBUFFER *ppDSCBuffer, LPUNKNOWN pUnkOuter) PURE;
+    STDMETHOD(GetCaps)              (THIS_ LPDSCCAPS pDSCCaps) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPCGUID pcGuidDevice) PURE;
+};
+
+#define IDirectSoundCapture_QueryInterface(p,a,b)           IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundCapture_AddRef(p)                       IUnknown_AddRef(p)
+#define IDirectSoundCapture_Release(p)                      IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c)    (p)->lpVtbl->CreateCaptureBuffer(p,a,b,c)
+#define IDirectSoundCapture_GetCaps(p,a)                    (p)->lpVtbl->GetCaps(p,a)
+#define IDirectSoundCapture_Initialize(p,a)                 (p)->lpVtbl->Initialize(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c)    (p)->CreateCaptureBuffer(a,b,c)
+#define IDirectSoundCapture_GetCaps(p,a)                    (p)->GetCaps(a)
+#define IDirectSoundCapture_Initialize(p,a)                 (p)->Initialize(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundCaptureBuffer
+//
+
+DEFINE_GUID(IID_IDirectSoundCaptureBuffer, 0xb0210782, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundCaptureBuffer
+
+DECLARE_INTERFACE_(IDirectSoundCaptureBuffer, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundCaptureBuffer methods
+    STDMETHOD(GetCaps)              (THIS_ LPDSCBCAPS pDSCBCaps) PURE;
+    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE;
+    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;
+    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE;
+    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,
+                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;
+    STDMETHOD(Start)                (THIS_ DWORD dwFlags) PURE;
+    STDMETHOD(Stop)                 (THIS) PURE;
+    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;
+};
+
+#define IDirectSoundCaptureBuffer_QueryInterface(p,a,b)         IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundCaptureBuffer_AddRef(p)                     IUnknown_AddRef(p)
+#define IDirectSoundCaptureBuffer_Release(p)                    IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCaptureBuffer_GetCaps(p,a)                  (p)->lpVtbl->GetCaps(p,a)
+#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b)     (p)->lpVtbl->GetCurrentPosition(p,a,b)
+#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c)            (p)->lpVtbl->GetFormat(p,a,b,c)
+#define IDirectSoundCaptureBuffer_GetStatus(p,a)                (p)->lpVtbl->GetStatus(p,a)
+#define IDirectSoundCaptureBuffer_Initialize(p,a,b)             (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g)         (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g)
+#define IDirectSoundCaptureBuffer_Start(p,a)                    (p)->lpVtbl->Start(p,a)
+#define IDirectSoundCaptureBuffer_Stop(p)                       (p)->lpVtbl->Stop(p)
+#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d)             (p)->lpVtbl->Unlock(p,a,b,c,d)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCaptureBuffer_GetCaps(p,a)                  (p)->GetCaps(a)
+#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b)     (p)->GetCurrentPosition(a,b)
+#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c)            (p)->GetFormat(a,b,c)
+#define IDirectSoundCaptureBuffer_GetStatus(p,a)                (p)->GetStatus(a)
+#define IDirectSoundCaptureBuffer_Initialize(p,a,b)             (p)->Initialize(a,b)
+#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g)         (p)->Lock(a,b,c,d,e,f,g)
+#define IDirectSoundCaptureBuffer_Start(p,a)                    (p)->Start(a)
+#define IDirectSoundCaptureBuffer_Stop(p)                       (p)->Stop()
+#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d)             (p)->Unlock(a,b,c,d)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+//
+// IDirectSoundCaptureBuffer8
+//
+
+DEFINE_GUID(IID_IDirectSoundCaptureBuffer8, 0x990df4, 0xdbb, 0x4872, 0x83, 0x3e, 0x6d, 0x30, 0x3e, 0x80, 0xae, 0xb6);
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundCaptureBuffer8
+
+DECLARE_INTERFACE_(IDirectSoundCaptureBuffer8, IDirectSoundCaptureBuffer)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundCaptureBuffer methods
+    STDMETHOD(GetCaps)              (THIS_ LPDSCBCAPS pDSCBCaps) PURE;
+    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE;
+    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;
+    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE;
+    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,
+                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;
+    STDMETHOD(Start)                (THIS_ DWORD dwFlags) PURE;
+    STDMETHOD(Stop)                 (THIS) PURE;
+    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;
+
+    // IDirectSoundCaptureBuffer8 methods
+    STDMETHOD(GetObjectInPath)      (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE;
+    STDMETHOD(GetFXStatus)          (DWORD dwFXCount, LPDWORD pdwFXStatus) PURE;
+};
+
+#define IDirectSoundCaptureBuffer8_QueryInterface(p,a,b)            IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundCaptureBuffer8_AddRef(p)                        IUnknown_AddRef(p)
+#define IDirectSoundCaptureBuffer8_Release(p)                       IUnknown_Release(p)
+
+#define IDirectSoundCaptureBuffer8_GetCaps(p,a)                     IDirectSoundCaptureBuffer_GetCaps(p,a)
+#define IDirectSoundCaptureBuffer8_GetCurrentPosition(p,a,b)        IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b)
+#define IDirectSoundCaptureBuffer8_GetFormat(p,a,b,c)               IDirectSoundCaptureBuffer_GetFormat(p,a,b,c)
+#define IDirectSoundCaptureBuffer8_GetStatus(p,a)                   IDirectSoundCaptureBuffer_GetStatus(p,a)
+#define IDirectSoundCaptureBuffer8_Initialize(p,a,b)                IDirectSoundCaptureBuffer_Initialize(p,a,b)
+#define IDirectSoundCaptureBuffer8_Lock(p,a,b,c,d,e,f,g)            IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g)
+#define IDirectSoundCaptureBuffer8_Start(p,a)                       IDirectSoundCaptureBuffer_Start(p,a)
+#define IDirectSoundCaptureBuffer8_Stop(p)                          IDirectSoundCaptureBuffer_Stop(p))
+#define IDirectSoundCaptureBuffer8_Unlock(p,a,b,c,d)                IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d)       (p)->lpVtbl->GetObjectInPath(p,a,b,c,d)
+#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b)               (p)->lpVtbl->GetFXStatus(p,a,b)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d)       (p)->GetObjectInPath(a,b,c,d)
+#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b)               (p)->GetFXStatus(a,b)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+//
+// IDirectSoundNotify
+//
+
+DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundNotify
+
+DECLARE_INTERFACE_(IDirectSoundNotify, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)           (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)            (THIS) PURE;
+    STDMETHOD_(ULONG,Release)           (THIS) PURE;
+
+    // IDirectSoundNotify methods
+    STDMETHOD(SetNotificationPositions) (THIS_ DWORD dwPositionNotifies, LPCDSBPOSITIONNOTIFY pcPositionNotifies) PURE;
+};
+
+#define IDirectSoundNotify_QueryInterface(p,a,b)            IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundNotify_AddRef(p)                        IUnknown_AddRef(p)
+#define IDirectSoundNotify_Release(p)                       IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundNotify_SetNotificationPositions(p,a,b)  (p)->lpVtbl->SetNotificationPositions(p,a,b)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundNotify_SetNotificationPositions(p,a,b)  (p)->SetNotificationPositions(a,b)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IKsPropertySet
+//
+
+#ifndef _IKsPropertySet_
+#define _IKsPropertySet_
+
+#ifdef __cplusplus
+// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined
+struct IKsPropertySet;
+#endif // __cplusplus
+
+typedef struct IKsPropertySet *LPKSPROPERTYSET;
+
+#define KSPROPERTY_SUPPORT_GET  0x00000001
+#define KSPROPERTY_SUPPORT_SET  0x00000002
+
+DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93);
+
+#undef INTERFACE
+#define INTERFACE IKsPropertySet
+
+DECLARE_INTERFACE_(IKsPropertySet, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)   (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)    (THIS) PURE;
+    STDMETHOD_(ULONG,Release)   (THIS) PURE;
+
+    // IKsPropertySet methods
+    STDMETHOD(Get)              (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength,
+                                       LPVOID pPropertyData, ULONG ulDataLength, PULONG pulBytesReturned) PURE;
+    STDMETHOD(Set)              (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength,
+                                       LPVOID pPropertyData, ULONG ulDataLength) PURE;
+    STDMETHOD(QuerySupport)     (THIS_ REFGUID rguidPropSet, ULONG ulId, PULONG pulTypeSupport) PURE;
+};
+
+#define IKsPropertySet_QueryInterface(p,a,b)       IUnknown_QueryInterface(p,a,b)
+#define IKsPropertySet_AddRef(p)                   IUnknown_AddRef(p)
+#define IKsPropertySet_Release(p)                  IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IKsPropertySet_Get(p,a,b,c,d,e,f,g)        (p)->lpVtbl->Get(p,a,b,c,d,e,f,g)
+#define IKsPropertySet_Set(p,a,b,c,d,e,f)          (p)->lpVtbl->Set(p,a,b,c,d,e,f)
+#define IKsPropertySet_QuerySupport(p,a,b,c)       (p)->lpVtbl->QuerySupport(p,a,b,c)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IKsPropertySet_Get(p,a,b,c,d,e,f,g)        (p)->Get(a,b,c,d,e,f,g)
+#define IKsPropertySet_Set(p,a,b,c,d,e,f)          (p)->Set(a,b,c,d,e,f)
+#define IKsPropertySet_QuerySupport(p,a,b,c)       (p)->QuerySupport(a,b,c)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#endif // _IKsPropertySet_
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+//
+// IDirectSoundFXGargle
+//
+
+DEFINE_GUID(IID_IDirectSoundFXGargle, 0xd616f352, 0xd622, 0x11ce, 0xaa, 0xc5, 0x00, 0x20, 0xaf, 0x0b, 0x99, 0xa3);
+
+typedef struct _DSFXGargle
+{
+    DWORD       dwRateHz;               // Rate of modulation in hz
+    DWORD       dwWaveShape;            // DSFXGARGLE_WAVE_xxx
+} DSFXGargle, *LPDSFXGargle;
+
+#define DSFXGARGLE_WAVE_TRIANGLE        0
+#define DSFXGARGLE_WAVE_SQUARE          1
+
+typedef const DSFXGargle *LPCDSFXGargle;
+
+#define DSFXGARGLE_RATEHZ_MIN           1
+#define DSFXGARGLE_RATEHZ_MAX           1000
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXGargle
+
+DECLARE_INTERFACE_(IDirectSoundFXGargle, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXGargle methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXGargle pcDsFxGargle) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXGargle pDsFxGargle) PURE;
+};
+
+#define IDirectSoundFXGargle_QueryInterface(p,a,b)          IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXGargle_AddRef(p)                      IUnknown_AddRef(p)
+#define IDirectSoundFXGargle_Release(p)                     IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXGargle_SetAllParameters(p,a)          (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXGargle_GetAllParameters(p,a)          (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXGargle_SetAllParameters(p,a)          (p)->SetAllParameters(a)
+#define IDirectSoundFXGargle_GetAllParameters(p,a)          (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundFXChorus
+//
+
+DEFINE_GUID(IID_IDirectSoundFXChorus, 0x880842e3, 0x145f, 0x43e6, 0xa9, 0x34, 0xa7, 0x18, 0x06, 0xe5, 0x05, 0x47);
+
+typedef struct _DSFXChorus
+{
+    FLOAT       fWetDryMix;
+    FLOAT       fDepth;
+    FLOAT       fFeedback;
+    FLOAT       fFrequency;
+    LONG        lWaveform;          // LFO shape; DSFXCHORUS_WAVE_xxx
+    FLOAT       fDelay;
+    LONG        lPhase;
+} DSFXChorus, *LPDSFXChorus;
+
+typedef const DSFXChorus *LPCDSFXChorus;
+
+#define DSFXCHORUS_WAVE_TRIANGLE        0
+#define DSFXCHORUS_WAVE_SIN             1
+
+#define DSFXCHORUS_WETDRYMIX_MIN        0.0f
+#define DSFXCHORUS_WETDRYMIX_MAX        100.0f
+#define DSFXCHORUS_DEPTH_MIN            0.0f
+#define DSFXCHORUS_DEPTH_MAX            100.0f
+#define DSFXCHORUS_FEEDBACK_MIN         -99.0f
+#define DSFXCHORUS_FEEDBACK_MAX         99.0f
+#define DSFXCHORUS_FREQUENCY_MIN        0.0f
+#define DSFXCHORUS_FREQUENCY_MAX        10.0f
+#define DSFXCHORUS_DELAY_MIN            0.0f
+#define DSFXCHORUS_DELAY_MAX            20.0f
+#define DSFXCHORUS_PHASE_MIN            0
+#define DSFXCHORUS_PHASE_MAX            4
+
+#define DSFXCHORUS_PHASE_NEG_180        0
+#define DSFXCHORUS_PHASE_NEG_90         1
+#define DSFXCHORUS_PHASE_ZERO           2
+#define DSFXCHORUS_PHASE_90             3
+#define DSFXCHORUS_PHASE_180            4
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXChorus
+
+DECLARE_INTERFACE_(IDirectSoundFXChorus, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXChorus methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXChorus pcDsFxChorus) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXChorus pDsFxChorus) PURE;
+};
+
+#define IDirectSoundFXChorus_QueryInterface(p,a,b)          IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXChorus_AddRef(p)                      IUnknown_AddRef(p)
+#define IDirectSoundFXChorus_Release(p)                     IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXChorus_SetAllParameters(p,a)          (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXChorus_GetAllParameters(p,a)          (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXChorus_SetAllParameters(p,a)          (p)->SetAllParameters(a)
+#define IDirectSoundFXChorus_GetAllParameters(p,a)          (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundFXFlanger
+//
+
+DEFINE_GUID(IID_IDirectSoundFXFlanger, 0x903e9878, 0x2c92, 0x4072, 0x9b, 0x2c, 0xea, 0x68, 0xf5, 0x39, 0x67, 0x83);
+
+typedef struct _DSFXFlanger
+{
+    FLOAT       fWetDryMix;
+    FLOAT       fDepth;
+    FLOAT       fFeedback;
+    FLOAT       fFrequency;
+    LONG        lWaveform;
+    FLOAT       fDelay;
+    LONG        lPhase;
+} DSFXFlanger, *LPDSFXFlanger;
+
+typedef const DSFXFlanger *LPCDSFXFlanger;
+
+#define DSFXFLANGER_WAVE_TRIANGLE       0
+#define DSFXFLANGER_WAVE_SIN            1
+
+#define DSFXFLANGER_WETDRYMIX_MIN       0.0f
+#define DSFXFLANGER_WETDRYMIX_MAX       100.0f
+#define DSFXFLANGER_FREQUENCY_MIN       0.0f
+#define DSFXFLANGER_FREQUENCY_MAX       10.0f
+#define DSFXFLANGER_DEPTH_MIN           0.0f
+#define DSFXFLANGER_DEPTH_MAX           100.0f
+#define DSFXFLANGER_PHASE_MIN           0
+#define DSFXFLANGER_PHASE_MAX           4
+#define DSFXFLANGER_FEEDBACK_MIN        -99.0f
+#define DSFXFLANGER_FEEDBACK_MAX        99.0f
+#define DSFXFLANGER_DELAY_MIN           0.0f
+#define DSFXFLANGER_DELAY_MAX           4.0f
+
+#define DSFXFLANGER_PHASE_NEG_180       0
+#define DSFXFLANGER_PHASE_NEG_90        1
+#define DSFXFLANGER_PHASE_ZERO          2
+#define DSFXFLANGER_PHASE_90            3
+#define DSFXFLANGER_PHASE_180           4
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXFlanger
+
+DECLARE_INTERFACE_(IDirectSoundFXFlanger, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXFlanger methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXFlanger pcDsFxFlanger) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXFlanger pDsFxFlanger) PURE;
+};
+
+#define IDirectSoundFXFlanger_QueryInterface(p,a,b)         IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXFlanger_AddRef(p)                     IUnknown_AddRef(p)
+#define IDirectSoundFXFlanger_Release(p)                    IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXFlanger_SetAllParameters(p,a)         (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXFlanger_GetAllParameters(p,a)         (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXFlanger_SetAllParameters(p,a)         (p)->SetAllParameters(a)
+#define IDirectSoundFXFlanger_GetAllParameters(p,a)         (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundFXEcho
+//
+
+DEFINE_GUID(IID_IDirectSoundFXEcho, 0x8bd28edf, 0x50db, 0x4e92, 0xa2, 0xbd, 0x44, 0x54, 0x88, 0xd1, 0xed, 0x42);
+
+typedef struct _DSFXEcho
+{
+    FLOAT   fWetDryMix;
+    FLOAT   fFeedback;
+    FLOAT   fLeftDelay;
+    FLOAT   fRightDelay;
+    LONG    lPanDelay;
+} DSFXEcho, *LPDSFXEcho;
+
+typedef const DSFXEcho *LPCDSFXEcho;
+
+#define DSFXECHO_WETDRYMIX_MIN      0.0f
+#define DSFXECHO_WETDRYMIX_MAX      100.0f
+#define DSFXECHO_FEEDBACK_MIN       0.0f
+#define DSFXECHO_FEEDBACK_MAX       100.0f
+#define DSFXECHO_LEFTDELAY_MIN      1.0f
+#define DSFXECHO_LEFTDELAY_MAX      2000.0f
+#define DSFXECHO_RIGHTDELAY_MIN     1.0f
+#define DSFXECHO_RIGHTDELAY_MAX     2000.0f
+#define DSFXECHO_PANDELAY_MIN       0
+#define DSFXECHO_PANDELAY_MAX       1
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXEcho
+
+DECLARE_INTERFACE_(IDirectSoundFXEcho, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXEcho methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXEcho pcDsFxEcho) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXEcho pDsFxEcho) PURE;
+};
+
+#define IDirectSoundFXEcho_QueryInterface(p,a,b)            IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXEcho_AddRef(p)                        IUnknown_AddRef(p)
+#define IDirectSoundFXEcho_Release(p)                       IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXEcho_SetAllParameters(p,a)            (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXEcho_GetAllParameters(p,a)            (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXEcho_SetAllParameters(p,a)            (p)->SetAllParameters(a)
+#define IDirectSoundFXEcho_GetAllParameters(p,a)            (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundFXDistortion
+//
+
+DEFINE_GUID(IID_IDirectSoundFXDistortion, 0x8ecf4326, 0x455f, 0x4d8b, 0xbd, 0xa9, 0x8d, 0x5d, 0x3e, 0x9e, 0x3e, 0x0b);
+
+typedef struct _DSFXDistortion
+{
+    FLOAT   fGain;
+    FLOAT   fEdge;
+    FLOAT   fPostEQCenterFrequency;
+    FLOAT   fPostEQBandwidth;
+    FLOAT   fPreLowpassCutoff;
+} DSFXDistortion, *LPDSFXDistortion;
+
+typedef const DSFXDistortion *LPCDSFXDistortion;
+
+#define DSFXDISTORTION_GAIN_MIN                     -60.0f
+#define DSFXDISTORTION_GAIN_MAX                     0.0f
+#define DSFXDISTORTION_EDGE_MIN                     0.0f
+#define DSFXDISTORTION_EDGE_MAX                     100.0f
+#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN    100.0f
+#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX    8000.0f
+#define DSFXDISTORTION_POSTEQBANDWIDTH_MIN          100.0f
+#define DSFXDISTORTION_POSTEQBANDWIDTH_MAX          8000.0f
+#define DSFXDISTORTION_PRELOWPASSCUTOFF_MIN         100.0f
+#define DSFXDISTORTION_PRELOWPASSCUTOFF_MAX         8000.0f
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXDistortion
+
+DECLARE_INTERFACE_(IDirectSoundFXDistortion, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXDistortion methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXDistortion pcDsFxDistortion) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXDistortion pDsFxDistortion) PURE;
+};
+
+#define IDirectSoundFXDistortion_QueryInterface(p,a,b)      IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXDistortion_AddRef(p)                  IUnknown_AddRef(p)
+#define IDirectSoundFXDistortion_Release(p)                 IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXDistortion_SetAllParameters(p,a)      (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXDistortion_GetAllParameters(p,a)      (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXDistortion_SetAllParameters(p,a)      (p)->SetAllParameters(a)
+#define IDirectSoundFXDistortion_GetAllParameters(p,a)      (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundFXCompressor
+//
+
+DEFINE_GUID(IID_IDirectSoundFXCompressor, 0x4bbd1154, 0x62f6, 0x4e2c, 0xa1, 0x5c, 0xd3, 0xb6, 0xc4, 0x17, 0xf7, 0xa0);
+
+typedef struct _DSFXCompressor
+{
+    FLOAT   fGain;
+    FLOAT   fAttack;
+    FLOAT   fRelease;
+    FLOAT   fThreshold;
+    FLOAT   fRatio;
+    FLOAT   fPredelay;
+} DSFXCompressor, *LPDSFXCompressor;
+
+typedef const DSFXCompressor *LPCDSFXCompressor;
+
+#define DSFXCOMPRESSOR_GAIN_MIN             -60.0f
+#define DSFXCOMPRESSOR_GAIN_MAX             60.0f
+#define DSFXCOMPRESSOR_ATTACK_MIN           0.01f
+#define DSFXCOMPRESSOR_ATTACK_MAX           500.0f
+#define DSFXCOMPRESSOR_RELEASE_MIN          50.0f
+#define DSFXCOMPRESSOR_RELEASE_MAX          3000.0f
+#define DSFXCOMPRESSOR_THRESHOLD_MIN        -60.0f
+#define DSFXCOMPRESSOR_THRESHOLD_MAX        0.0f
+#define DSFXCOMPRESSOR_RATIO_MIN            1.0f
+#define DSFXCOMPRESSOR_RATIO_MAX            100.0f
+#define DSFXCOMPRESSOR_PREDELAY_MIN         0.0f
+#define DSFXCOMPRESSOR_PREDELAY_MAX         4.0f
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXCompressor
+
+DECLARE_INTERFACE_(IDirectSoundFXCompressor, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXCompressor methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXCompressor pcDsFxCompressor) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXCompressor pDsFxCompressor) PURE;
+};
+
+#define IDirectSoundFXCompressor_QueryInterface(p,a,b)      IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXCompressor_AddRef(p)                  IUnknown_AddRef(p)
+#define IDirectSoundFXCompressor_Release(p)                 IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXCompressor_SetAllParameters(p,a)      (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXCompressor_GetAllParameters(p,a)      (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXCompressor_SetAllParameters(p,a)      (p)->SetAllParameters(a)
+#define IDirectSoundFXCompressor_GetAllParameters(p,a)      (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundFXParamEq
+//
+
+DEFINE_GUID(IID_IDirectSoundFXParamEq, 0xc03ca9fe, 0xfe90, 0x4204, 0x80, 0x78, 0x82, 0x33, 0x4c, 0xd1, 0x77, 0xda);
+
+typedef struct _DSFXParamEq
+{
+    FLOAT   fCenter;
+    FLOAT   fBandwidth;
+    FLOAT   fGain;
+} DSFXParamEq, *LPDSFXParamEq;
+
+typedef const DSFXParamEq *LPCDSFXParamEq;
+
+#define DSFXPARAMEQ_CENTER_MIN      80.0f
+#define DSFXPARAMEQ_CENTER_MAX      16000.0f
+#define DSFXPARAMEQ_BANDWIDTH_MIN   1.0f
+#define DSFXPARAMEQ_BANDWIDTH_MAX   36.0f
+#define DSFXPARAMEQ_GAIN_MIN        -15.0f
+#define DSFXPARAMEQ_GAIN_MAX        15.0f
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXParamEq
+
+DECLARE_INTERFACE_(IDirectSoundFXParamEq, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXParamEq methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXParamEq pcDsFxParamEq) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXParamEq pDsFxParamEq) PURE;
+};
+
+#define IDirectSoundFXParamEq_QueryInterface(p,a,b)      IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXParamEq_AddRef(p)                  IUnknown_AddRef(p)
+#define IDirectSoundFXParamEq_Release(p)                 IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXParamEq_SetAllParameters(p,a)      (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXParamEq_GetAllParameters(p,a)      (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXParamEq_SetAllParameters(p,a)      (p)->SetAllParameters(a)
+#define IDirectSoundFXParamEq_GetAllParameters(p,a)      (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundFXI3DL2Reverb
+//
+
+DEFINE_GUID(IID_IDirectSoundFXI3DL2Reverb, 0x4b166a6a, 0x0d66, 0x43f3, 0x80, 0xe3, 0xee, 0x62, 0x80, 0xde, 0xe1, 0xa4);
+
+typedef struct _DSFXI3DL2Reverb
+{
+    LONG    lRoom;                  // [-10000, 0]      default: -1000 mB
+    LONG    lRoomHF;                // [-10000, 0]      default: 0 mB
+    FLOAT   flRoomRolloffFactor;    // [0.0, 10.0]      default: 0.0
+    FLOAT   flDecayTime;            // [0.1, 20.0]      default: 1.49s
+    FLOAT   flDecayHFRatio;         // [0.1, 2.0]       default: 0.83
+    LONG    lReflections;           // [-10000, 1000]   default: -2602 mB
+    FLOAT   flReflectionsDelay;     // [0.0, 0.3]       default: 0.007 s
+    LONG    lReverb;                // [-10000, 2000]   default: 200 mB
+    FLOAT   flReverbDelay;          // [0.0, 0.1]       default: 0.011 s
+    FLOAT   flDiffusion;            // [0.0, 100.0]     default: 100.0 %
+    FLOAT   flDensity;              // [0.0, 100.0]     default: 100.0 %
+    FLOAT   flHFReference;          // [20.0, 20000.0]  default: 5000.0 Hz
+} DSFXI3DL2Reverb, *LPDSFXI3DL2Reverb;
+
+typedef const DSFXI3DL2Reverb *LPCDSFXI3DL2Reverb;
+
+#define DSFX_I3DL2REVERB_ROOM_MIN                   (-10000)
+#define DSFX_I3DL2REVERB_ROOM_MAX                   0
+#define DSFX_I3DL2REVERB_ROOM_DEFAULT               (-1000)
+
+#define DSFX_I3DL2REVERB_ROOMHF_MIN                 (-10000)
+#define DSFX_I3DL2REVERB_ROOMHF_MAX                 0
+#define DSFX_I3DL2REVERB_ROOMHF_DEFAULT             (-100)
+
+#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MIN      0.0f
+#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MAX      10.0f
+#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_DEFAULT  0.0f
+
+#define DSFX_I3DL2REVERB_DECAYTIME_MIN              0.1f
+#define DSFX_I3DL2REVERB_DECAYTIME_MAX              20.0f
+#define DSFX_I3DL2REVERB_DECAYTIME_DEFAULT          1.49f
+
+#define DSFX_I3DL2REVERB_DECAYHFRATIO_MIN           0.1f
+#define DSFX_I3DL2REVERB_DECAYHFRATIO_MAX           2.0f
+#define DSFX_I3DL2REVERB_DECAYHFRATIO_DEFAULT       0.83f
+
+#define DSFX_I3DL2REVERB_REFLECTIONS_MIN            (-10000)
+#define DSFX_I3DL2REVERB_REFLECTIONS_MAX            1000
+#define DSFX_I3DL2REVERB_REFLECTIONS_DEFAULT        (-2602)
+
+#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MIN       0.0f
+#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MAX       0.3f
+#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_DEFAULT   0.007f
+
+#define DSFX_I3DL2REVERB_REVERB_MIN                 (-10000)
+#define DSFX_I3DL2REVERB_REVERB_MAX                 2000
+#define DSFX_I3DL2REVERB_REVERB_DEFAULT             (200)
+
+#define DSFX_I3DL2REVERB_REVERBDELAY_MIN            0.0f
+#define DSFX_I3DL2REVERB_REVERBDELAY_MAX            0.1f
+#define DSFX_I3DL2REVERB_REVERBDELAY_DEFAULT        0.011f
+
+#define DSFX_I3DL2REVERB_DIFFUSION_MIN              0.0f
+#define DSFX_I3DL2REVERB_DIFFUSION_MAX              100.0f
+#define DSFX_I3DL2REVERB_DIFFUSION_DEFAULT          100.0f
+
+#define DSFX_I3DL2REVERB_DENSITY_MIN                0.0f
+#define DSFX_I3DL2REVERB_DENSITY_MAX                100.0f
+#define DSFX_I3DL2REVERB_DENSITY_DEFAULT            100.0f
+
+#define DSFX_I3DL2REVERB_HFREFERENCE_MIN            20.0f
+#define DSFX_I3DL2REVERB_HFREFERENCE_MAX            20000.0f
+#define DSFX_I3DL2REVERB_HFREFERENCE_DEFAULT        5000.0f
+
+#define DSFX_I3DL2REVERB_QUALITY_MIN                0
+#define DSFX_I3DL2REVERB_QUALITY_MAX                3
+#define DSFX_I3DL2REVERB_QUALITY_DEFAULT            2
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXI3DL2Reverb
+
+DECLARE_INTERFACE_(IDirectSoundFXI3DL2Reverb, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXI3DL2Reverb methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXI3DL2Reverb pcDsFxI3DL2Reverb) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXI3DL2Reverb pDsFxI3DL2Reverb) PURE;
+    STDMETHOD(SetPreset)            (THIS_ DWORD dwPreset) PURE;
+    STDMETHOD(GetPreset)            (THIS_ LPDWORD pdwPreset) PURE;
+    STDMETHOD(SetQuality)           (THIS_ LONG lQuality) PURE;
+    STDMETHOD(GetQuality)           (THIS_ LONG *plQuality) PURE;
+};
+
+#define IDirectSoundFXI3DL2Reverb_QueryInterface(p,a,b)     IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXI3DL2Reverb_AddRef(p)                 IUnknown_AddRef(p)
+#define IDirectSoundFXI3DL2Reverb_Release(p)                IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a)     (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a)     (p)->lpVtbl->GetAllParameters(p,a)
+#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a)            (p)->lpVtbl->SetPreset(p,a)
+#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a)            (p)->lpVtbl->GetPreset(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a)     (p)->SetAllParameters(a)
+#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a)     (p)->GetAllParameters(a)
+#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a)            (p)->SetPreset(a)
+#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a)            (p)->GetPreset(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundFXWavesReverb
+//
+
+DEFINE_GUID(IID_IDirectSoundFXWavesReverb,0x46858c3a,0x0dc6,0x45e3,0xb7,0x60,0xd4,0xee,0xf1,0x6c,0xb3,0x25);
+
+typedef struct _DSFXWavesReverb
+{
+    FLOAT   fInGain;                // [-96.0,0.0]            default: 0.0 dB
+    FLOAT   fReverbMix;             // [-96.0,0.0]            default: 0.0 db
+    FLOAT   fReverbTime;            // [0.001,3000.0]         default: 1000.0 ms
+    FLOAT   fHighFreqRTRatio;       // [0.001,0.999]          default: 0.001
+} DSFXWavesReverb, *LPDSFXWavesReverb;
+
+typedef const DSFXWavesReverb *LPCDSFXWavesReverb;
+
+#define DSFX_WAVESREVERB_INGAIN_MIN                 -96.0f
+#define DSFX_WAVESREVERB_INGAIN_MAX                 0.0f
+#define DSFX_WAVESREVERB_INGAIN_DEFAULT             0.0f
+#define DSFX_WAVESREVERB_REVERBMIX_MIN              -96.0f
+#define DSFX_WAVESREVERB_REVERBMIX_MAX              0.0f
+#define DSFX_WAVESREVERB_REVERBMIX_DEFAULT          0.0f
+#define DSFX_WAVESREVERB_REVERBTIME_MIN             0.001f
+#define DSFX_WAVESREVERB_REVERBTIME_MAX             3000.0f
+#define DSFX_WAVESREVERB_REVERBTIME_DEFAULT         1000.0f
+#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN        0.001f
+#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX        0.999f
+#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT    0.001f
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFXWavesReverb
+
+DECLARE_INTERFACE_(IDirectSoundFXWavesReverb, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundFXWavesReverb methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXWavesReverb pcDsFxWavesReverb) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXWavesReverb pDsFxWavesReverb) PURE;
+};
+
+#define IDirectSoundFXWavesReverb_QueryInterface(p,a,b)     IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFXWavesReverb_AddRef(p)                 IUnknown_AddRef(p)
+#define IDirectSoundFXWavesReverb_Release(p)                IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXWavesReverb_SetAllParameters(p,a)     (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundFXWavesReverb_GetAllParameters(p,a)     (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFXWavesReverb_SetAllParameters(p,a)     (p)->SetAllParameters(a)
+#define IDirectSoundFXWavesReverb_GetAllParameters(p,a)     (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+//
+// IDirectSoundCaptureFXAec
+//
+
+DEFINE_GUID(IID_IDirectSoundCaptureFXAec, 0xad74143d, 0x903d, 0x4ab7, 0x80, 0x66, 0x28, 0xd3, 0x63, 0x03, 0x6d, 0x65);
+
+typedef struct _DSCFXAec
+{
+    BOOL    fEnable;
+    BOOL    fNoiseFill;
+    DWORD   dwMode;
+} DSCFXAec, *LPDSCFXAec;
+
+typedef const DSCFXAec *LPCDSCFXAec;
+
+// These match the AEC_MODE_* constants in the DDK's ksmedia.h file
+#define DSCFX_AEC_MODE_PASS_THROUGH                     0x0
+#define DSCFX_AEC_MODE_HALF_DUPLEX                      0x1
+#define DSCFX_AEC_MODE_FULL_DUPLEX                      0x2
+
+// These match the AEC_STATUS_* constants in ksmedia.h
+#define DSCFX_AEC_STATUS_HISTORY_UNINITIALIZED          0x0
+#define DSCFX_AEC_STATUS_HISTORY_CONTINUOUSLY_CONVERGED 0x1
+#define DSCFX_AEC_STATUS_HISTORY_PREVIOUSLY_DIVERGED    0x2
+#define DSCFX_AEC_STATUS_CURRENTLY_CONVERGED            0x8
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundCaptureFXAec
+
+DECLARE_INTERFACE_(IDirectSoundCaptureFXAec, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundCaptureFXAec methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSCFXAec pDscFxAec) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSCFXAec pDscFxAec) PURE;
+    STDMETHOD(GetStatus)            (THIS_ PDWORD pdwStatus) PURE;
+    STDMETHOD(Reset)                (THIS) PURE;
+};
+
+#define IDirectSoundCaptureFXAec_QueryInterface(p,a,b)     IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundCaptureFXAec_AddRef(p)                 IUnknown_AddRef(p)
+#define IDirectSoundCaptureFXAec_Release(p)                IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCaptureFXAec_SetAllParameters(p,a)     (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundCaptureFXAec_GetAllParameters(p,a)     (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCaptureFXAec_SetAllParameters(p,a)     (p)->SetAllParameters(a)
+#define IDirectSoundCaptureFXAec_GetAllParameters(p,a)     (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+
+//
+// IDirectSoundCaptureFXNoiseSuppress
+//
+
+DEFINE_GUID(IID_IDirectSoundCaptureFXNoiseSuppress, 0xed311e41, 0xfbae, 0x4175, 0x96, 0x25, 0xcd, 0x8, 0x54, 0xf6, 0x93, 0xca);
+
+typedef struct _DSCFXNoiseSuppress
+{
+    BOOL    fEnable;
+} DSCFXNoiseSuppress, *LPDSCFXNoiseSuppress;
+
+typedef const DSCFXNoiseSuppress *LPCDSCFXNoiseSuppress;
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundCaptureFXNoiseSuppress
+
+DECLARE_INTERFACE_(IDirectSoundCaptureFXNoiseSuppress, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+
+    // IDirectSoundCaptureFXNoiseSuppress methods
+    STDMETHOD(SetAllParameters)     (THIS_ LPCDSCFXNoiseSuppress pcDscFxNoiseSuppress) PURE;
+    STDMETHOD(GetAllParameters)     (THIS_ LPDSCFXNoiseSuppress pDscFxNoiseSuppress) PURE;
+    STDMETHOD(Reset)                (THIS) PURE;
+};
+
+#define IDirectSoundCaptureFXNoiseSuppress_QueryInterface(p,a,b)     IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundCaptureFXNoiseSuppress_AddRef(p)                 IUnknown_AddRef(p)
+#define IDirectSoundCaptureFXNoiseSuppress_Release(p)                IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a)     (p)->lpVtbl->SetAllParameters(p,a)
+#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a)     (p)->lpVtbl->GetAllParameters(p,a)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a)     (p)->SetAllParameters(a)
+#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a)     (p)->GetAllParameters(a)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+
+//
+// IDirectSoundFullDuplex
+//
+
+#ifndef _IDirectSoundFullDuplex_
+#define _IDirectSoundFullDuplex_
+
+#ifdef __cplusplus
+// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined
+struct IDirectSoundFullDuplex;
+#endif // __cplusplus
+
+typedef struct IDirectSoundFullDuplex *LPDIRECTSOUNDFULLDUPLEX;
+
+DEFINE_GUID(IID_IDirectSoundFullDuplex, 0xedcb4c7a, 0xdaab, 0x4216, 0xa4, 0x2e, 0x6c, 0x50, 0x59, 0x6d, 0xdc, 0x1d);
+
+#undef INTERFACE
+#define INTERFACE IDirectSoundFullDuplex
+
+DECLARE_INTERFACE_(IDirectSoundFullDuplex, IUnknown)
+{
+    // IUnknown methods
+    STDMETHOD(QueryInterface)   (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG,AddRef)    (THIS) PURE;
+    STDMETHOD_(ULONG,Release)   (THIS) PURE;
+
+    // IDirectSoundFullDuplex methods
+    STDMETHOD(Initialize)     (THIS_ LPCGUID pCaptureGuid, LPCGUID pRenderGuid, LPCDSCBUFFERDESC lpDscBufferDesc, LPCDSBUFFERDESC lpDsBufferDesc, HWND hWnd, DWORD dwLevel, LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8, LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8) PURE;
+};
+
+#define IDirectSoundFullDuplex_QueryInterface(p,a,b)    IUnknown_QueryInterface(p,a,b)
+#define IDirectSoundFullDuplex_AddRef(p)                IUnknown_AddRef(p)
+#define IDirectSoundFullDuplex_Release(p)               IUnknown_Release(p)
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h)     (p)->lpVtbl->Initialize(p,a,b,c,d,e,f,g,h)
+#else // !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h)     (p)->Initialize(a,b,c,d,e,f,g,h)
+#endif // !defined(__cplusplus) || defined(CINTERFACE)
+
+#endif // _IDirectSoundFullDuplex_
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+//
+// Return Codes
+//
+
+// The function completed successfully
+#define DS_OK                           S_OK
+
+// The call succeeded, but we had to substitute the 3D algorithm
+#define DS_NO_VIRTUALIZATION            MAKE_HRESULT(0, _FACDS, 10)
+
+// The call failed because resources (such as a priority level)
+// were already being used by another caller
+#define DSERR_ALLOCATED                 MAKE_DSHRESULT(10)
+
+// The control (vol, pan, etc.) requested by the caller is not available
+#define DSERR_CONTROLUNAVAIL            MAKE_DSHRESULT(30)
+
+// An invalid parameter was passed to the returning function
+#define DSERR_INVALIDPARAM              E_INVALIDARG
+
+// This call is not valid for the current state of this object
+#define DSERR_INVALIDCALL               MAKE_DSHRESULT(50)
+
+// An undetermined error occurred inside the DirectSound subsystem
+#define DSERR_GENERIC                   E_FAIL
+
+// The caller does not have the priority level required for the function to
+// succeed
+#define DSERR_PRIOLEVELNEEDED           MAKE_DSHRESULT(70)
+
+// Not enough free memory is available to complete the operation
+#define DSERR_OUTOFMEMORY               E_OUTOFMEMORY
+
+// The specified WAVE format is not supported
+#define DSERR_BADFORMAT                 MAKE_DSHRESULT(100)
+
+// The function called is not supported at this time
+#define DSERR_UNSUPPORTED               E_NOTIMPL
+
+// No sound driver is available for use
+#define DSERR_NODRIVER                  MAKE_DSHRESULT(120)
+
+// This object is already initialized
+#define DSERR_ALREADYINITIALIZED        MAKE_DSHRESULT(130)
+
+// This object does not support aggregation
+#define DSERR_NOAGGREGATION             CLASS_E_NOAGGREGATION
+
+// The buffer memory has been lost, and must be restored
+#define DSERR_BUFFERLOST                MAKE_DSHRESULT(150)
+
+// Another app has a higher priority level, preventing this call from
+// succeeding
+#define DSERR_OTHERAPPHASPRIO           MAKE_DSHRESULT(160)
+
+// This object has not been initialized
+#define DSERR_UNINITIALIZED             MAKE_DSHRESULT(170)
+
+// The requested COM interface is not available
+#define DSERR_NOINTERFACE               E_NOINTERFACE
+
+// Access is denied
+#define DSERR_ACCESSDENIED              E_ACCESSDENIED
+
+// Tried to create a DSBCAPS_CTRLFX buffer shorter than DSBSIZE_FX_MIN milliseconds
+#define DSERR_BUFFERTOOSMALL            MAKE_DSHRESULT(180)
+
+// Attempt to use DirectSound 8 functionality on an older DirectSound object
+#define DSERR_DS8_REQUIRED              MAKE_DSHRESULT(190)
+
+// A circular loop of send effects was detected
+#define DSERR_SENDLOOP                  MAKE_DSHRESULT(200)
+
+// The GUID specified in an audiopath file does not match a valid MIXIN buffer
+#define DSERR_BADSENDBUFFERGUID         MAKE_DSHRESULT(210)
+
+// The object requested was not found (numerically equal to DMUS_E_NOT_FOUND)
+#define DSERR_OBJECTNOTFOUND            MAKE_DSHRESULT(4449)
+
+// The effects requested could not be found on the system, or they were found
+// but in the wrong order, or in the wrong hardware/software locations.
+#define DSERR_FXUNAVAILABLE             MAKE_DSHRESULT(220)
+
+//
+// Flags
+//
+
+#define DSCAPS_PRIMARYMONO          0x00000001
+#define DSCAPS_PRIMARYSTEREO        0x00000002
+#define DSCAPS_PRIMARY8BIT          0x00000004
+#define DSCAPS_PRIMARY16BIT         0x00000008
+#define DSCAPS_CONTINUOUSRATE       0x00000010
+#define DSCAPS_EMULDRIVER           0x00000020
+#define DSCAPS_CERTIFIED            0x00000040
+#define DSCAPS_SECONDARYMONO        0x00000100
+#define DSCAPS_SECONDARYSTEREO      0x00000200
+#define DSCAPS_SECONDARY8BIT        0x00000400
+#define DSCAPS_SECONDARY16BIT       0x00000800
+
+#define DSSCL_NORMAL                0x00000001
+#define DSSCL_PRIORITY              0x00000002
+#define DSSCL_EXCLUSIVE             0x00000003
+#define DSSCL_WRITEPRIMARY          0x00000004
+
+#define DSSPEAKER_DIRECTOUT         0x00000000
+#define DSSPEAKER_HEADPHONE         0x00000001
+#define DSSPEAKER_MONO              0x00000002
+#define DSSPEAKER_QUAD              0x00000003
+#define DSSPEAKER_STEREO            0x00000004
+#define DSSPEAKER_SURROUND          0x00000005
+#define DSSPEAKER_5POINT1           0x00000006
+#define DSSPEAKER_7POINT1           0x00000007
+
+#define DSSPEAKER_GEOMETRY_MIN      0x00000005  //   5 degrees
+#define DSSPEAKER_GEOMETRY_NARROW   0x0000000A  //  10 degrees
+#define DSSPEAKER_GEOMETRY_WIDE     0x00000014  //  20 degrees
+#define DSSPEAKER_GEOMETRY_MAX      0x000000B4  // 180 degrees
+
+#define DSSPEAKER_COMBINED(c, g)    ((DWORD)(((BYTE)(c)) | ((DWORD)((BYTE)(g))) << 16))
+#define DSSPEAKER_CONFIG(a)         ((BYTE)(a))
+#define DSSPEAKER_GEOMETRY(a)       ((BYTE)(((DWORD)(a) >> 16) & 0x00FF))
+
+#define DSBCAPS_PRIMARYBUFFER       0x00000001
+#define DSBCAPS_STATIC              0x00000002
+#define DSBCAPS_LOCHARDWARE         0x00000004
+#define DSBCAPS_LOCSOFTWARE         0x00000008
+#define DSBCAPS_CTRL3D              0x00000010
+#define DSBCAPS_CTRLFREQUENCY       0x00000020
+#define DSBCAPS_CTRLPAN             0x00000040
+#define DSBCAPS_CTRLVOLUME          0x00000080
+#define DSBCAPS_CTRLPOSITIONNOTIFY  0x00000100
+#define DSBCAPS_CTRLFX              0x00000200
+#define DSBCAPS_STICKYFOCUS         0x00004000
+#define DSBCAPS_GLOBALFOCUS         0x00008000
+#define DSBCAPS_GETCURRENTPOSITION2 0x00010000
+#define DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000
+#define DSBCAPS_LOCDEFER            0x00040000
+
+#define DSBPLAY_LOOPING             0x00000001
+#define DSBPLAY_LOCHARDWARE         0x00000002
+#define DSBPLAY_LOCSOFTWARE         0x00000004
+#define DSBPLAY_TERMINATEBY_TIME    0x00000008
+#define DSBPLAY_TERMINATEBY_DISTANCE    0x000000010
+#define DSBPLAY_TERMINATEBY_PRIORITY    0x000000020
+
+#define DSBSTATUS_PLAYING           0x00000001
+#define DSBSTATUS_BUFFERLOST        0x00000002
+#define DSBSTATUS_LOOPING           0x00000004
+#define DSBSTATUS_LOCHARDWARE       0x00000008
+#define DSBSTATUS_LOCSOFTWARE       0x00000010
+#define DSBSTATUS_TERMINATED        0x00000020
+
+#define DSBLOCK_FROMWRITECURSOR     0x00000001
+#define DSBLOCK_ENTIREBUFFER        0x00000002
+
+#define DSBFREQUENCY_ORIGINAL       0
+#define DSBFREQUENCY_MIN            100
+#if DIRECTSOUND_VERSION >= 0x0900
+#define DSBFREQUENCY_MAX            200000
+#else
+#define DSBFREQUENCY_MAX            100000
+#endif
+
+#define DSBPAN_LEFT                 -10000
+#define DSBPAN_CENTER               0
+#define DSBPAN_RIGHT                10000
+
+#define DSBVOLUME_MIN               -10000
+#define DSBVOLUME_MAX               0
+
+#define DSBSIZE_MIN                 4
+#define DSBSIZE_MAX                 0x0FFFFFFF
+#define DSBSIZE_FX_MIN              150  // NOTE: Milliseconds, not bytes
+
+#define DS3DMODE_NORMAL             0x00000000
+#define DS3DMODE_HEADRELATIVE       0x00000001
+#define DS3DMODE_DISABLE            0x00000002
+
+#define DS3D_IMMEDIATE              0x00000000
+#define DS3D_DEFERRED               0x00000001
+
+#define DS3D_MINDISTANCEFACTOR      FLT_MIN
+#define DS3D_MAXDISTANCEFACTOR      FLT_MAX
+#define DS3D_DEFAULTDISTANCEFACTOR  1.0f
+
+#define DS3D_MINROLLOFFFACTOR       0.0f
+#define DS3D_MAXROLLOFFFACTOR       10.0f
+#define DS3D_DEFAULTROLLOFFFACTOR   1.0f
+
+#define DS3D_MINDOPPLERFACTOR       0.0f
+#define DS3D_MAXDOPPLERFACTOR       10.0f
+#define DS3D_DEFAULTDOPPLERFACTOR   1.0f
+
+#define DS3D_DEFAULTMINDISTANCE     1.0f
+#define DS3D_DEFAULTMAXDISTANCE     1000000000.0f
+
+#define DS3D_MINCONEANGLE           0
+#define DS3D_MAXCONEANGLE           360
+#define DS3D_DEFAULTCONEANGLE       360
+
+#define DS3D_DEFAULTCONEOUTSIDEVOLUME DSBVOLUME_MAX
+
+// IDirectSoundCapture attributes
+
+#define DSCCAPS_EMULDRIVER          DSCAPS_EMULDRIVER
+#define DSCCAPS_CERTIFIED           DSCAPS_CERTIFIED
+#define DSCCAPS_MULTIPLECAPTURE     0x00000001
+
+// IDirectSoundCaptureBuffer attributes
+
+#define DSCBCAPS_WAVEMAPPED         0x80000000
+
+#if DIRECTSOUND_VERSION >= 0x0800
+#define DSCBCAPS_CTRLFX             0x00000200
+#endif
+
+
+#define DSCBLOCK_ENTIREBUFFER       0x00000001
+
+#define DSCBSTATUS_CAPTURING        0x00000001
+#define DSCBSTATUS_LOOPING          0x00000002
+
+#define DSCBSTART_LOOPING           0x00000001
+
+#define DSBPN_OFFSETSTOP            0xFFFFFFFF
+
+#define DS_CERTIFIED                0x00000000
+#define DS_UNCERTIFIED              0x00000001
+
+
+//
+// Flags for the I3DL2 effects
+//
+
+//
+// I3DL2 Material Presets
+//
+
+enum
+{
+    DSFX_I3DL2_MATERIAL_PRESET_SINGLEWINDOW,
+    DSFX_I3DL2_MATERIAL_PRESET_DOUBLEWINDOW,
+    DSFX_I3DL2_MATERIAL_PRESET_THINDOOR,
+    DSFX_I3DL2_MATERIAL_PRESET_THICKDOOR,
+    DSFX_I3DL2_MATERIAL_PRESET_WOODWALL,
+    DSFX_I3DL2_MATERIAL_PRESET_BRICKWALL,
+    DSFX_I3DL2_MATERIAL_PRESET_STONEWALL,
+    DSFX_I3DL2_MATERIAL_PRESET_CURTAIN
+};
+
+#define I3DL2_MATERIAL_PRESET_SINGLEWINDOW    -2800,0.71f
+#define I3DL2_MATERIAL_PRESET_DOUBLEWINDOW    -5000,0.40f
+#define I3DL2_MATERIAL_PRESET_THINDOOR        -1800,0.66f
+#define I3DL2_MATERIAL_PRESET_THICKDOOR       -4400,0.64f
+#define I3DL2_MATERIAL_PRESET_WOODWALL        -4000,0.50f
+#define I3DL2_MATERIAL_PRESET_BRICKWALL       -5000,0.60f
+#define I3DL2_MATERIAL_PRESET_STONEWALL       -6000,0.68f
+#define I3DL2_MATERIAL_PRESET_CURTAIN         -1200,0.15f
+
+enum
+{
+    DSFX_I3DL2_ENVIRONMENT_PRESET_DEFAULT,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_GENERIC,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_PADDEDCELL,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_ROOM,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_BATHROOM,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_LIVINGROOM,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_STONEROOM,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_AUDITORIUM,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_CONCERTHALL,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_CAVE,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_ARENA,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_HANGAR,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_HALLWAY,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_ALLEY,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_FOREST,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_CITY,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_MOUNTAINS,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_QUARRY,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_PLAIN,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_PARKINGLOT,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_SEWERPIPE,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_UNDERWATER,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_SMALLROOM,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEROOM,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEHALL,
+    DSFX_I3DL2_ENVIRONMENT_PRESET_PLATE
+};
+
+//
+// I3DL2 Reverberation Presets Values
+//
+
+#define I3DL2_ENVIRONMENT_PRESET_DEFAULT         -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f,   200, 0.011f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_GENERIC         -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f,   200, 0.011f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_PADDEDCELL      -1000,-6000, 0.0f, 0.17f, 0.10f, -1204, 0.001f,   207, 0.002f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_ROOM            -1000, -454, 0.0f, 0.40f, 0.83f, -1646, 0.002f,    53, 0.003f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_BATHROOM        -1000,-1200, 0.0f, 1.49f, 0.54f,  -370, 0.007f,  1030, 0.011f, 100.0f,  60.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_LIVINGROOM      -1000,-6000, 0.0f, 0.50f, 0.10f, -1376, 0.003f, -1104, 0.004f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_STONEROOM       -1000, -300, 0.0f, 2.31f, 0.64f,  -711, 0.012f,    83, 0.017f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_AUDITORIUM      -1000, -476, 0.0f, 4.32f, 0.59f,  -789, 0.020f,  -289, 0.030f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_CONCERTHALL     -1000, -500, 0.0f, 3.92f, 0.70f, -1230, 0.020f,    -2, 0.029f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_CAVE            -1000,    0, 0.0f, 2.91f, 1.30f,  -602, 0.015f,  -302, 0.022f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_ARENA           -1000, -698, 0.0f, 7.24f, 0.33f, -1166, 0.020f,    16, 0.030f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_HANGAR          -1000,-1000, 0.0f,10.05f, 0.23f,  -602, 0.020f,   198, 0.030f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY -1000,-4000, 0.0f, 0.30f, 0.10f, -1831, 0.002f, -1630, 0.030f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_HALLWAY         -1000, -300, 0.0f, 1.49f, 0.59f, -1219, 0.007f,   441, 0.011f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR   -1000, -237, 0.0f, 2.70f, 0.79f, -1214, 0.013f,   395, 0.020f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_ALLEY           -1000, -270, 0.0f, 1.49f, 0.86f, -1204, 0.007f,    -4, 0.011f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_FOREST          -1000,-3300, 0.0f, 1.49f, 0.54f, -2560, 0.162f,  -613, 0.088f,  79.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_CITY            -1000, -800, 0.0f, 1.49f, 0.67f, -2273, 0.007f, -2217, 0.011f,  50.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_MOUNTAINS       -1000,-2500, 0.0f, 1.49f, 0.21f, -2780, 0.300f, -2014, 0.100f,  27.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_QUARRY          -1000,-1000, 0.0f, 1.49f, 0.83f,-10000, 0.061f,   500, 0.025f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_PLAIN           -1000,-2000, 0.0f, 1.49f, 0.50f, -2466, 0.179f, -2514, 0.100f,  21.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_PARKINGLOT      -1000,    0, 0.0f, 1.65f, 1.50f, -1363, 0.008f, -1153, 0.012f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_SEWERPIPE       -1000,-1000, 0.0f, 2.81f, 0.14f,   429, 0.014f,   648, 0.021f,  80.0f,  60.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_UNDERWATER      -1000,-4000, 0.0f, 1.49f, 0.10f,  -449, 0.007f,  1700, 0.011f, 100.0f, 100.0f, 5000.0f
+
+//
+// Examples simulating 'musical' reverb presets
+//
+// Name       Decay time   Description
+// Small Room    1.1s      A small size room with a length of 5m or so.
+// Medium Room   1.3s      A medium size room with a length of 10m or so.
+// Large Room    1.5s      A large size room suitable for live performances.
+// Medium Hall   1.8s      A medium size concert hall.
+// Large Hall    1.8s      A large size concert hall suitable for a full orchestra.
+// Plate         1.3s      A plate reverb simulation.
+//
+
+#define I3DL2_ENVIRONMENT_PRESET_SMALLROOM       -1000, -600, 0.0f, 1.10f, 0.83f,  -400, 0.005f,   500, 0.010f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM      -1000, -600, 0.0f, 1.30f, 0.83f, -1000, 0.010f,  -200, 0.020f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_LARGEROOM       -1000, -600, 0.0f, 1.50f, 0.83f, -1600, 0.020f, -1000, 0.040f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL      -1000, -600, 0.0f, 1.80f, 0.70f, -1300, 0.015f,  -800, 0.030f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_LARGEHALL       -1000, -600, 0.0f, 1.80f, 0.70f, -2000, 0.030f, -1400, 0.060f, 100.0f, 100.0f, 5000.0f
+#define I3DL2_ENVIRONMENT_PRESET_PLATE           -1000, -200, 0.0f, 1.30f, 0.90f,     0, 0.002f,     0, 0.010f, 100.0f,  75.0f, 5000.0f
+
+//
+// DirectSound3D Algorithms
+//
+
+// Default DirectSound3D algorithm {00000000-0000-0000-0000-000000000000}
+#define DS3DALG_DEFAULT GUID_NULL
+
+// No virtualization (Pan3D) {C241333F-1C1B-11d2-94F5-00C04FC28ACA}
+DEFINE_GUID(DS3DALG_NO_VIRTUALIZATION, 0xc241333f, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
+
+// High-quality HRTF algorithm {C2413340-1C1B-11d2-94F5-00C04FC28ACA}
+DEFINE_GUID(DS3DALG_HRTF_FULL, 0xc2413340, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
+
+// Lower-quality HRTF algorithm {C2413342-1C1B-11d2-94F5-00C04FC28ACA}
+DEFINE_GUID(DS3DALG_HRTF_LIGHT, 0xc2413342, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
+
+
+#if DIRECTSOUND_VERSION >= 0x0800
+
+//
+// DirectSound Internal Effect Algorithms
+//
+
+
+// Gargle {DAFD8210-5711-4B91-9FE3-F75B7AE279BF}
+DEFINE_GUID(GUID_DSFX_STANDARD_GARGLE, 0xdafd8210, 0x5711, 0x4b91, 0x9f, 0xe3, 0xf7, 0x5b, 0x7a, 0xe2, 0x79, 0xbf);
+
+// Chorus {EFE6629C-81F7-4281-BD91-C9D604A95AF6}
+DEFINE_GUID(GUID_DSFX_STANDARD_CHORUS, 0xefe6629c, 0x81f7, 0x4281, 0xbd, 0x91, 0xc9, 0xd6, 0x04, 0xa9, 0x5a, 0xf6);
+
+// Flanger {EFCA3D92-DFD8-4672-A603-7420894BAD98}
+DEFINE_GUID(GUID_DSFX_STANDARD_FLANGER, 0xefca3d92, 0xdfd8, 0x4672, 0xa6, 0x03, 0x74, 0x20, 0x89, 0x4b, 0xad, 0x98);
+
+// Echo/Delay {EF3E932C-D40B-4F51-8CCF-3F98F1B29D5D}
+DEFINE_GUID(GUID_DSFX_STANDARD_ECHO, 0xef3e932c, 0xd40b, 0x4f51, 0x8c, 0xcf, 0x3f, 0x98, 0xf1, 0xb2, 0x9d, 0x5d);
+
+// Distortion {EF114C90-CD1D-484E-96E5-09CFAF912A21}
+DEFINE_GUID(GUID_DSFX_STANDARD_DISTORTION, 0xef114c90, 0xcd1d, 0x484e, 0x96, 0xe5, 0x09, 0xcf, 0xaf, 0x91, 0x2a, 0x21);
+
+// Compressor/Limiter {EF011F79-4000-406D-87AF-BFFB3FC39D57}
+DEFINE_GUID(GUID_DSFX_STANDARD_COMPRESSOR, 0xef011f79, 0x4000, 0x406d, 0x87, 0xaf, 0xbf, 0xfb, 0x3f, 0xc3, 0x9d, 0x57);
+
+// Parametric Equalization {120CED89-3BF4-4173-A132-3CB406CF3231}
+DEFINE_GUID(GUID_DSFX_STANDARD_PARAMEQ, 0x120ced89, 0x3bf4, 0x4173, 0xa1, 0x32, 0x3c, 0xb4, 0x06, 0xcf, 0x32, 0x31);
+
+// I3DL2 Environmental Reverberation: Reverb (Listener) Effect {EF985E71-D5C7-42D4-BA4D-2D073E2E96F4}
+DEFINE_GUID(GUID_DSFX_STANDARD_I3DL2REVERB, 0xef985e71, 0xd5c7, 0x42d4, 0xba, 0x4d, 0x2d, 0x07, 0x3e, 0x2e, 0x96, 0xf4);
+
+// Waves Reverberation {87FC0268-9A55-4360-95AA-004A1D9DE26C}
+DEFINE_GUID(GUID_DSFX_WAVES_REVERB, 0x87fc0268, 0x9a55, 0x4360, 0x95, 0xaa, 0x00, 0x4a, 0x1d, 0x9d, 0xe2, 0x6c);
+
+//
+// DirectSound Capture Effect Algorithms
+//
+
+
+// Acoustic Echo Canceller {BF963D80-C559-11D0-8A2B-00A0C9255AC1}
+// Matches KSNODETYPE_ACOUSTIC_ECHO_CANCEL in ksmedia.h
+DEFINE_GUID(GUID_DSCFX_CLASS_AEC, 0xBF963D80L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
+
+// Microsoft AEC {CDEBB919-379A-488a-8765-F53CFD36DE40}
+DEFINE_GUID(GUID_DSCFX_MS_AEC, 0xcdebb919, 0x379a, 0x488a, 0x87, 0x65, 0xf5, 0x3c, 0xfd, 0x36, 0xde, 0x40);
+
+// System AEC {1C22C56D-9879-4f5b-A389-27996DDC2810}
+DEFINE_GUID(GUID_DSCFX_SYSTEM_AEC, 0x1c22c56d, 0x9879, 0x4f5b, 0xa3, 0x89, 0x27, 0x99, 0x6d, 0xdc, 0x28, 0x10);
+
+// Noise Supression {E07F903F-62FD-4e60-8CDD-DEA7236665B5}
+// Matches KSNODETYPE_NOISE_SUPPRESS in post Windows ME DDK's ksmedia.h
+DEFINE_GUID(GUID_DSCFX_CLASS_NS, 0xe07f903f, 0x62fd, 0x4e60, 0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5);
+
+// Microsoft Noise Suppresion {11C5C73B-66E9-4ba1-A0BA-E814C6EED92D}
+DEFINE_GUID(GUID_DSCFX_MS_NS, 0x11c5c73b, 0x66e9, 0x4ba1, 0xa0, 0xba, 0xe8, 0x14, 0xc6, 0xee, 0xd9, 0x2d);
+
+// System Noise Suppresion {5AB0882E-7274-4516-877D-4EEE99BA4FD0}
+DEFINE_GUID(GUID_DSCFX_SYSTEM_NS, 0x5ab0882e, 0x7274, 0x4516, 0x87, 0x7d, 0x4e, 0xee, 0x99, 0xba, 0x4f, 0xd0);
+
+#endif // DIRECTSOUND_VERSION >= 0x0800
+
+#endif // __DSOUND_INCLUDED__
+
+
+
+#ifdef __cplusplus
+};
+#endif // __cplusplus
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/dvoice.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,857 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1999 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dpvoice.h
+ *  Content:    DirectPlayVoice include file
+ ***************************************************************************/
+
+#ifndef __DVOICE__
+#define __DVOICE__
+
+#include <ole2.h>			// for DECLARE_INTERFACE and HRESULT
+#include <mmsystem.h>
+#include <mmreg.h>
+#include <msacm.h>
+#include "dsound.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/****************************************************************************
+ *
+ * DirectPlayVoice CLSIDs
+ *
+ ****************************************************************************/
+
+
+// {B9F3EB85-B781-4ac1-8D90-93A05EE37D7D}
+DEFINE_GUID(CLSID_DirectPlayVoiceClient, 
+0xb9f3eb85, 0xb781, 0x4ac1, 0x8d, 0x90, 0x93, 0xa0, 0x5e, 0xe3, 0x7d, 0x7d);
+
+// {D3F5B8E6-9B78-4a4c-94EA-CA2397B663D3}
+DEFINE_GUID(CLSID_DirectPlayVoiceServer, 
+0xd3f5b8e6, 0x9b78, 0x4a4c, 0x94, 0xea, 0xca, 0x23, 0x97, 0xb6, 0x63, 0xd3);
+
+// {0F0F094B-B01C-4091-A14D-DD0CD807711A}
+DEFINE_GUID(CLSID_DirectPlayVoiceTest, 
+0xf0f094b, 0xb01c, 0x4091, 0xa1, 0x4d, 0xdd, 0xc, 0xd8, 0x7, 0x71, 0x1a);
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Interface IIDs
+ *
+ ****************************************************************************/
+
+
+// {1DFDC8EA-BCF7-41d6-B295-AB64B3B23306}
+DEFINE_GUID(IID_IDirectPlayVoiceClient, 
+0x1dfdc8ea, 0xbcf7, 0x41d6, 0xb2, 0x95, 0xab, 0x64, 0xb3, 0xb2, 0x33, 0x6);
+
+// {FAA1C173-0468-43b6-8A2A-EA8A4F2076C9}
+DEFINE_GUID(IID_IDirectPlayVoiceServer, 
+0xfaa1c173, 0x468, 0x43b6, 0x8a, 0x2a, 0xea, 0x8a, 0x4f, 0x20, 0x76, 0xc9);
+
+// {D26AF734-208B-41da-8224-E0CE79810BE1}
+DEFINE_GUID(IID_IDirectPlayVoiceTest,
+0xd26af734, 0x208b, 0x41da, 0x82, 0x24, 0xe0, 0xce, 0x79, 0x81, 0xb, 0xe1);
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Compression Type GUIDs
+ *
+ ****************************************************************************/
+
+// MS-ADPCM 32.8 kbit/s
+//
+// {699B52C1-A885-46a8-A308-97172419ADC7}
+DEFINE_GUID(DPVCTGUID_ADPCM,
+0x699b52c1, 0xa885, 0x46a8, 0xa3, 0x8, 0x97, 0x17, 0x24, 0x19, 0xad, 0xc7);
+
+// Microsoft GSM 6.10 13 kbit/s
+//
+// {24768C60-5A0D-11d3-9BE4-525400D985E7}
+DEFINE_GUID(DPVCTGUID_GSM,
+0x24768c60, 0x5a0d, 0x11d3, 0x9b, 0xe4, 0x52, 0x54, 0x0, 0xd9, 0x85, 0xe7);
+
+// MS-PCM 64 kbit/s
+// 
+// {8DE12FD4-7CB3-48ce-A7E8-9C47A22E8AC5}
+DEFINE_GUID(DPVCTGUID_NONE,
+0x8de12fd4, 0x7cb3, 0x48ce, 0xa7, 0xe8, 0x9c, 0x47, 0xa2, 0x2e, 0x8a, 0xc5);
+
+// Voxware SC03 3.2kbit/s
+//
+// {7D82A29B-2242-4f82-8F39-5D1153DF3E41}
+DEFINE_GUID(DPVCTGUID_SC03,
+0x7d82a29b, 0x2242, 0x4f82, 0x8f, 0x39, 0x5d, 0x11, 0x53, 0xdf, 0x3e, 0x41);
+
+// Voxware SC06 6.4kbit/s
+//
+// {53DEF900-7168-4633-B47F-D143916A13C7}
+DEFINE_GUID(DPVCTGUID_SC06,
+0x53def900, 0x7168, 0x4633, 0xb4, 0x7f, 0xd1, 0x43, 0x91, 0x6a, 0x13, 0xc7);
+
+// TrueSpeech(TM) 8.6 kbit/s
+//
+// {D7954361-5A0B-11d3-9BE4-525400D985E7}
+DEFINE_GUID(DPVCTGUID_TRUESPEECH,
+0xd7954361, 0x5a0b, 0x11d3, 0x9b, 0xe4, 0x52, 0x54, 0x0, 0xd9, 0x85, 0xe7);
+
+// Voxware VR12 1.4kbit/s
+//
+// {FE44A9FE-8ED4-48bf-9D66-1B1ADFF9FF6D}
+DEFINE_GUID(DPVCTGUID_VR12,
+0xfe44a9fe, 0x8ed4, 0x48bf, 0x9d, 0x66, 0x1b, 0x1a, 0xdf, 0xf9, 0xff, 0x6d);
+
+// Define the default compression type
+#define DPVCTGUID_DEFAULT	DPVCTGUID_SC03
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Interface Pointer definitions
+ *
+ ****************************************************************************/
+
+typedef struct IDirectPlayVoiceClient FAR *LPDIRECTPLAYVOICECLIENT, *PDIRECTPLAYVOICECLIENT;
+typedef struct IDirectPlayVoiceServer FAR *LPDIRECTPLAYVOICESERVER, *PDIRECTPLAYVOICESERVER;
+typedef struct IDirectPlayVoiceTest FAR *LPDIRECTPLAYVOICETEST, *PDIRECTPLAYVOICETEST;
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Callback Functions
+ *
+ ****************************************************************************/
+typedef HRESULT (FAR PASCAL *PDVMESSAGEHANDLER)(
+    PVOID   pvUserContext,
+    DWORD   dwMessageType,
+    LPVOID  lpMessage
+);
+
+typedef PDVMESSAGEHANDLER LPDVMESSAGEHANDLER;
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Datatypes (Non-Structure / Non-Message)
+ *
+ ****************************************************************************/
+
+typedef DWORD DVID, *LPDVID, *PDVID;
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Message Types
+ *
+ ****************************************************************************/
+
+#define DVMSGID_BASE                        0x0000
+
+#define DVMSGID_MINBASE                     (DVMSGID_CREATEVOICEPLAYER)
+#define DVMSGID_CREATEVOICEPLAYER           (DVMSGID_BASE+0x0001)
+#define DVMSGID_DELETEVOICEPLAYER           (DVMSGID_BASE+0x0002)
+#define DVMSGID_SESSIONLOST                 (DVMSGID_BASE+0x0003)
+#define DVMSGID_PLAYERVOICESTART            (DVMSGID_BASE+0x0004)
+#define DVMSGID_PLAYERVOICESTOP             (DVMSGID_BASE+0x0005)
+#define DVMSGID_RECORDSTART                 (DVMSGID_BASE+0x0006)
+#define DVMSGID_RECORDSTOP                  (DVMSGID_BASE+0x0007)
+#define DVMSGID_CONNECTRESULT               (DVMSGID_BASE+0x0008)
+#define DVMSGID_DISCONNECTRESULT            (DVMSGID_BASE+0x0009)
+#define DVMSGID_INPUTLEVEL                  (DVMSGID_BASE+0x000A)
+#define DVMSGID_OUTPUTLEVEL                 (DVMSGID_BASE+0x000B)
+#define DVMSGID_HOSTMIGRATED                (DVMSGID_BASE+0x000C)
+#define DVMSGID_SETTARGETS                  (DVMSGID_BASE+0x000D)
+#define DVMSGID_PLAYEROUTPUTLEVEL           (DVMSGID_BASE+0x000E)
+#define DVMSGID_LOSTFOCUS                   (DVMSGID_BASE+0x0010)
+#define DVMSGID_GAINFOCUS                   (DVMSGID_BASE+0x0011)
+#define DVMSGID_LOCALHOSTSETUP				(DVMSGID_BASE+0x0012)
+#define DVMSGID_MAXBASE                     (DVMSGID_LOCALHOSTSETUP)
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Constants
+ *
+ ****************************************************************************/
+
+//
+// Buffer Aggresiveness Value Ranges
+//
+#define DVBUFFERAGGRESSIVENESS_MIN          0x00000001
+#define DVBUFFERAGGRESSIVENESS_MAX          0x00000064
+#define DVBUFFERAGGRESSIVENESS_DEFAULT      0x00000000
+
+// 
+// Buffer Quality Value Ranges
+//
+#define DVBUFFERQUALITY_MIN                 0x00000001
+#define DVBUFFERQUALITY_MAX                 0x00000064
+#define DVBUFFERQUALITY_DEFAULT             0x00000000
+
+#define DVID_SYS                0
+
+//
+// Used to identify the session host in client/server
+//
+#define DVID_SERVERPLAYER       1
+
+//
+// Used to target all players
+//
+#define DVID_ALLPLAYERS         0
+
+//
+// Used to identify the main buffer
+//
+#define DVID_REMAINING          0xFFFFFFFF
+
+// 
+// Input level range
+//
+#define DVINPUTLEVEL_MIN                    0x00000000
+#define DVINPUTLEVEL_MAX                    0x00000063	// 99 decimal
+
+#define DVNOTIFYPERIOD_MINPERIOD            20
+
+
+#define DVPLAYBACKVOLUME_DEFAULT            DSBVOLUME_MAX
+
+#define DVRECORDVOLUME_LAST                 0x00000001
+
+
+//
+// Use the default value
+//
+#define DVTHRESHOLD_DEFAULT               0xFFFFFFFF
+
+//
+// Threshold Ranges
+//
+#define DVTHRESHOLD_MIN                   0x00000000
+#define DVTHRESHOLD_MAX                   0x00000063	// 99 decimal
+
+//
+// Threshold field is not used 
+//
+#define DVTHRESHOLD_UNUSED                0xFFFFFFFE
+
+//
+// Session Types
+//
+#define DVSESSIONTYPE_PEER                  0x00000001
+#define DVSESSIONTYPE_MIXING                0x00000002
+#define DVSESSIONTYPE_FORWARDING            0x00000003
+#define DVSESSIONTYPE_ECHO                  0x00000004
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Flags
+ *
+ ****************************************************************************/
+
+
+// 
+// Enable automatic adjustment of the recording volume
+//
+#define DVCLIENTCONFIG_AUTORECORDVOLUME     0x00000008
+
+//
+// Enable automatic voice activation
+//
+#define DVCLIENTCONFIG_AUTOVOICEACTIVATED   0x00000020
+
+// 
+// Enable echo suppression
+//
+#define DVCLIENTCONFIG_ECHOSUPPRESSION      0x08000000
+
+// 
+// Voice Activation manual mode
+//
+#define DVCLIENTCONFIG_MANUALVOICEACTIVATED 0x00000004
+
+// 
+// Only playback voices that have buffers created for them
+//
+#define DVCLIENTCONFIG_MUTEGLOBAL           0x00000010
+
+// 
+// Mute the playback
+//
+#define DVCLIENTCONFIG_PLAYBACKMUTE         0x00000002
+
+//
+// Mute the recording 
+//
+#define DVCLIENTCONFIG_RECORDMUTE           0x00000001
+
+// 
+// Complete the operation before returning
+//
+#define DVFLAGS_SYNC                        0x00000001
+
+// 
+// Just check to see if wizard has been run, and if so what it's results were
+//
+#define DVFLAGS_QUERYONLY                   0x00000002
+
+//
+// Shutdown the voice session without migrating the host
+//
+#define DVFLAGS_NOHOSTMIGRATE               0x00000008
+
+// 
+// Allow the back button to be enabled in the wizard
+//
+#define DVFLAGS_ALLOWBACK                   0x00000010
+
+//
+// Disable host migration in the voice session
+//
+#define DVSESSION_NOHOSTMIGRATION           0x00000001
+
+// 
+// Server controlled targetting
+//
+#define DVSESSION_SERVERCONTROLTARGET       0x00000002
+
+//
+// Use DirectSound Normal Mode instead of priority 
+//
+#define DVSOUNDCONFIG_NORMALMODE            0x00000001
+
+//
+// Automatically select the microphone
+//
+#define DVSOUNDCONFIG_AUTOSELECT            0x00000002
+
+// 
+// Run in half duplex mode
+//
+#define DVSOUNDCONFIG_HALFDUPLEX            0x00000004
+
+// 
+// No volume controls are available for the recording device
+//
+#define DVSOUNDCONFIG_NORECVOLAVAILABLE     0x00000010
+
+// 
+// Disable capture sharing
+//
+#define DVSOUNDCONFIG_NOFOCUS               0x20000000
+
+// 
+// Set system conversion quality to high
+//
+#define DVSOUNDCONFIG_SETCONVERSIONQUALITY	0x00000008
+
+//
+// Enable strict focus mode
+// 
+#define DVSOUNDCONFIG_STRICTFOCUS           0x40000000
+
+//
+// Player is in half duplex mode
+//
+#define DVPLAYERCAPS_HALFDUPLEX             0x00000001
+
+// 
+// Specifies that player is the local player
+//
+#define DVPLAYERCAPS_LOCAL                  0x00000002
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Structures (Non-Message)
+ *
+ ****************************************************************************/
+
+
+//
+// DirectPlayVoice Caps
+// (GetCaps / SetCaps)
+//
+typedef struct
+{
+    DWORD   dwSize;                 // Size of this structure
+    DWORD   dwFlags;                // Caps flags
+} DVCAPS, *LPDVCAPS, *PDVCAPS;
+
+//
+// DirectPlayVoice Client Configuration
+// (Connect / GetClientConfig)
+//
+typedef struct
+{
+    DWORD   dwSize;                 // Size of this structure
+    DWORD   dwFlags;                // Flags for client config (DVCLIENTCONFIG_...)
+    LONG    lRecordVolume;          // Recording volume 
+    LONG    lPlaybackVolume;        // Playback volume
+    DWORD   dwThreshold;          // Voice Activation Threshold
+    DWORD   dwBufferQuality;        // Buffer quality
+    DWORD   dwBufferAggressiveness; // Buffer aggressiveness
+    DWORD   dwNotifyPeriod;         // Period of notification messages (ms)
+} DVCLIENTCONFIG, *LPDVCLIENTCONFIG, *PDVCLIENTCONFIG;
+
+//
+// DirectPlayVoice Compression Type Information
+// (GetCompressionTypes)
+//
+typedef struct
+{
+    DWORD   dwSize;                 // Size of this structure
+    GUID    guidType;               // GUID that identifies this compression type
+    LPWSTR  lpszName;               // String name of this compression type
+    LPWSTR  lpszDescription;        // Description for this compression type
+    DWORD   dwFlags;                // Flags for this compression type
+    DWORD   dwMaxBitsPerSecond;		// Maximum # of bit/s this compression type uses
+} DVCOMPRESSIONINFO, *LPDVCOMPRESSIONINFO, *PDVCOMPRESSIONINFO;
+
+//
+// DirectPlayVoice Session Description
+// (Host / GetSessionDesc)
+//
+typedef struct
+{
+    DWORD   dwSize;                 // Size of this structure
+    DWORD   dwFlags;                // Session flags (DVSESSION_...)
+    DWORD   dwSessionType;          // Session type (DVSESSIONTYPE_...)
+    GUID    guidCT;                 // Compression Type to use
+    DWORD   dwBufferQuality;        // Buffer quality
+    DWORD   dwBufferAggressiveness; // Buffer aggresiveness
+} DVSESSIONDESC, *LPDVSESSIONDESC, *PDVSESSIONDESC;
+
+// 
+// DirectPlayVoice Client Sound Device Configuration
+// (Connect / GetSoundDeviceConfig)
+//
+typedef struct
+{
+    DWORD                   dwSize;                 // Size of this structure
+    DWORD                   dwFlags;                // Flags for sound config (DVSOUNDCONFIG_...)
+    GUID                    guidPlaybackDevice;     // GUID of the playback device to use
+    LPDIRECTSOUND           lpdsPlaybackDevice;     // DirectSound Object to use (optional)
+    GUID                    guidCaptureDevice;      // GUID of the capture device to use
+    LPDIRECTSOUNDCAPTURE    lpdsCaptureDevice;      // DirectSoundCapture Object to use (optional)
+    HWND                    hwndAppWindow;          // HWND of your application's top-level window
+    LPDIRECTSOUNDBUFFER     lpdsMainBuffer;         // DirectSoundBuffer to use for playback (optional)
+    DWORD                   dwMainBufferFlags;      // Flags to pass to Play() on the main buffer
+    DWORD                   dwMainBufferPriority;   // Priority to set when calling Play() on the main buffer
+} DVSOUNDDEVICECONFIG, *LPDVSOUNDDEVICECONFIG, *PDVSOUNDDEVICECONFIG;
+
+/****************************************************************************
+ *
+ * DirectPlayVoice message handler call back structures
+ *
+ ****************************************************************************/
+
+//
+// Result of the Connect() call.  (If it wasn't called Async)
+// (DVMSGID_CONNECTRESULT)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    HRESULT hrResult;                       // Result of the Connect() call
+} DVMSG_CONNECTRESULT, *LPDVMSG_CONNECTRESULT, *PDVMSG_CONNECTRESULT;
+
+//
+// A new player has entered the voice session
+// (DVMSGID_CREATEVOICEPLAYER)
+// 
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DVID    dvidPlayer;                     // DVID of the player who joined
+    DWORD   dwFlags;                        // Player flags (DVPLAYERCAPS_...)
+    PVOID	pvPlayerContext;                // Context value for this player (user set)
+} DVMSG_CREATEVOICEPLAYER, *LPDVMSG_CREATEVOICEPLAYER, *PDVMSG_CREATEVOICEPLAYER;
+
+//
+// A player has left the voice session
+// (DVMSGID_DELETEVOICEPLAYER)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DVID    dvidPlayer;                     // DVID of the player who left
+    PVOID	pvPlayerContext;                // Context value for the player
+} DVMSG_DELETEVOICEPLAYER, *LPDVMSG_DELETEVOICEPLAYER, *PDVMSG_DELETEVOICEPLAYER;
+
+//
+// Result of the Disconnect() call.  (If it wasn't called Async)
+// (DVMSGID_DISCONNECTRESULT)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    HRESULT hrResult;                       // Result of the Disconnect() call
+} DVMSG_DISCONNECTRESULT, *LPDVMSG_DISCONNECTRESULT, *PDVMSG_DISCONNECTRESULT;
+
+// 
+// The voice session host has migrated.
+// (DVMSGID_HOSTMIGRATED) 
+//
+typedef struct
+{
+    DWORD                   dwSize;         // Size of this structure
+    DVID                    dvidNewHostID;  // DVID of the player who is now the host
+    LPDIRECTPLAYVOICESERVER pdvServerInterface;
+                                            // Pointer to the new host object (if local player is now host)
+} DVMSG_HOSTMIGRATED, *LPDVMSG_HOSTMIGRATED, *PDVMSG_HOSTMIGRATED;
+
+//
+// The current input level / recording volume on the local machine
+// (DVMSGID_INPUTLEVEL)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DWORD   dwPeakLevel;                    // Current peak level of the audio
+    LONG    lRecordVolume;                  // Current recording volume
+    PVOID	pvLocalPlayerContext;           // Context value for the local player
+} DVMSG_INPUTLEVEL, *LPDVMSG_INPUTLEVEL, *PDVMSG_INPUTLEVEL;
+
+//
+// The local client is about to become the new host
+// (DVMSGID_LOCALHOSTSETUP)
+//
+typedef struct
+{
+	DWORD				dwSize;             // Size of this structure
+	PVOID				pvContext;			// Context value to be passed to Initialize() of new host object
+	PDVMESSAGEHANDLER	pMessageHandler;	// Message handler to be used by new host object
+} DVMSG_LOCALHOSTSETUP, *LPDVMSG_LOCALHOSTSETUP, *PDVMSG_LOCALHOSTSETUP;
+
+//
+// The current output level for the combined output of all incoming streams.
+// (DVMSGID_OUTPUTLEVEL)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DWORD   dwPeakLevel;                    // Current peak level of the output
+    LONG    lOutputVolume;                  // Current playback volume
+    PVOID	pvLocalPlayerContext;           // Context value for the local player
+} DVMSG_OUTPUTLEVEL, *LPDVMSG_OUTPUTLEVEL, *PDVMSG_OUTPUTLEVEL;
+
+//
+// The current peak level of an individual player's incoming audio stream as it is
+// being played back.
+// (DVMSGID_PLAYEROUTPUTLEVEL)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DVID    dvidSourcePlayerID;                   // DVID of the player
+    DWORD   dwPeakLevel;                    // Peak level of the player's stream
+    PVOID	pvPlayerContext;                // Context value for the player
+} DVMSG_PLAYEROUTPUTLEVEL, *LPDVMSG_PLAYEROUTPUTLEVEL, *PDVMSG_PLAYEROUTPUTLEVEL;
+
+// 
+// An audio stream from the specified player has started playing back on the local client.
+// (DVMSGID_PLAYERVOICESTART).
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DVID    dvidSourcePlayerID;             // DVID of the Player 
+    PVOID	pvPlayerContext;                // Context value for this player
+} DVMSG_PLAYERVOICESTART, *LPDVMSG_PLAYERVOICESTART, *PDVMSG_PLAYERVOICESTART;
+
+//
+// The audio stream from the specified player has stopped playing back on the local client.
+// (DVMSGID_PLAYERVOICESTOP)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DVID    dvidSourcePlayerID;             // DVID of the player
+    PVOID	pvPlayerContext;                // Context value for this player
+} DVMSG_PLAYERVOICESTOP, *LPDVMSG_PLAYERVOICESTOP, *PDVMSG_PLAYERVOICESTOP;
+
+// 
+// Transmission has started on the local machine
+// (DVMSGID_RECORDSTART)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DWORD   dwPeakLevel;                    // Peak level that caused transmission to start
+    PVOID	pvLocalPlayerContext;           // Context value for the local player
+} DVMSG_RECORDSTART, *LPDVMSG_RECORDSTART, *PDVMSG_RECORDSTART;
+
+// 
+// Transmission has stopped on the local machine
+// (DVMSGID_RECORDSTOP)
+// 
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DWORD   dwPeakLevel;                    // Peak level that caused transmission to stop
+    PVOID	pvLocalPlayerContext;           // Context value for the local player
+} DVMSG_RECORDSTOP, *LPDVMSG_RECORDSTOP, *PDVMSG_RECORDSTOP;
+
+// 
+// The voice session has been lost
+// (DVMSGID_SESSIONLOST)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    HRESULT hrResult;	                    // Reason the session was disconnected
+} DVMSG_SESSIONLOST, *LPDVMSG_SESSIONLOST, *PDVMSG_SESSIONLOST;
+
+//
+// The target list has been updated for the local client
+// (DVMSGID_SETTARGETS)
+//
+typedef struct
+{
+    DWORD   dwSize;                         // Size of this structure
+    DWORD   dwNumTargets;                   // # of targets 
+    PDVID   pdvidTargets;                   // An array of DVIDs specifying the current targets
+} DVMSG_SETTARGETS, *LPDVMSG_SETTARGETS, *PDVMSG_SETTARGETS;
+
+
+/****************************************************************************
+ *
+ * DirectPlayVoice Functions
+ *
+ ****************************************************************************/
+
+/*
+ * 
+ * This function is no longer supported.  It is recommended that CoCreateInstance be used to create 
+ * DirectPlay voice objects.  
+ *
+ * extern HRESULT WINAPI DirectPlayVoiceCreate( const GUID * pcIID, void **ppvInterface, IUnknown *pUnknown); 
+ *
+ */
+
+/****************************************************************************
+ *
+ * DirectPlay8 Application Interfaces
+ *
+ ****************************************************************************/
+
+#undef INTERFACE
+#define INTERFACE IDirectPlayVoiceClient
+DECLARE_INTERFACE_( IDirectPlayVoiceClient, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, PVOID *ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirectPlayVoiceClient methods ***/
+    STDMETHOD_(HRESULT, Initialize)   (THIS_ LPUNKNOWN, PDVMESSAGEHANDLER, PVOID, PDWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, Connect)      (THIS_ PDVSOUNDDEVICECONFIG, PDVCLIENTCONFIG, DWORD ) PURE;
+    STDMETHOD_(HRESULT, Disconnect)   (THIS_ DWORD ) PURE;
+    STDMETHOD_(HRESULT, GetSessionDesc)(THIS_ PDVSESSIONDESC ) PURE;
+    STDMETHOD_(HRESULT, GetClientConfig)(THIS_ PDVCLIENTCONFIG ) PURE;
+    STDMETHOD_(HRESULT, SetClientConfig)(THIS_ PDVCLIENTCONFIG ) PURE;
+    STDMETHOD_(HRESULT, GetCaps) 		(THIS_ PDVCAPS ) PURE;
+    STDMETHOD_(HRESULT, GetCompressionTypes)( THIS_ PVOID, PDWORD, PDWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, SetTransmitTargets)( THIS_ PDVID, DWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, GetTransmitTargets)( THIS_ PDVID, PDWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, Create3DSoundBuffer)( THIS_ DVID, LPDIRECTSOUNDBUFFER, DWORD, DWORD, LPDIRECTSOUND3DBUFFER * ) PURE;
+    STDMETHOD_(HRESULT, Delete3DSoundBuffer)( THIS_ DVID, LPDIRECTSOUND3DBUFFER * ) PURE;
+    STDMETHOD_(HRESULT, SetNotifyMask)( THIS_ PDWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, GetSoundDeviceConfig)( THIS_ PDVSOUNDDEVICECONFIG, PDWORD ) PURE;
+};
+
+
+#undef INTERFACE
+#define INTERFACE IDirectPlayVoiceServer
+DECLARE_INTERFACE_( IDirectPlayVoiceServer, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)       (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+    /*** IDirectPlayVoiceServer methods ***/
+    STDMETHOD_(HRESULT, Initialize)   (THIS_ LPUNKNOWN, PDVMESSAGEHANDLER, PVOID, LPDWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, StartSession)  (THIS_ PDVSESSIONDESC, DWORD ) PURE;
+    STDMETHOD_(HRESULT, StopSession)   (THIS_ DWORD ) PURE;
+    STDMETHOD_(HRESULT, GetSessionDesc)(THIS_ PDVSESSIONDESC ) PURE;
+    STDMETHOD_(HRESULT, SetSessionDesc)(THIS_ PDVSESSIONDESC ) PURE;
+    STDMETHOD_(HRESULT, GetCaps) 		(THIS_ PDVCAPS ) PURE;
+    STDMETHOD_(HRESULT, GetCompressionTypes)( THIS_ PVOID, PDWORD, PDWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, SetTransmitTargets)( THIS_ DVID, PDVID, DWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, GetTransmitTargets)( THIS_ DVID, PDVID, PDWORD, DWORD ) PURE;
+    STDMETHOD_(HRESULT, SetNotifyMask)( THIS_ PDWORD, DWORD ) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirectPlayVoiceTest
+DECLARE_INTERFACE_( IDirectPlayVoiceTest, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)       (THIS_ REFIID riid, PVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+    /*** IDirectPlayVoiceTest methods ***/
+    STDMETHOD_(HRESULT, CheckAudioSetup) (THIS_ const GUID *,  const GUID * , HWND, DWORD ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+
+#define IDirectPlayVoiceClient_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectPlayVoiceClient_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectPlayVoiceClient_Release(p)                   (p)->lpVtbl->Release(p)
+
+#define IDirectPlayVoiceClient_Initialize(p,a,b,c,d,e)      (p)->lpVtbl->Initialize(p,a,b,c,d,e)
+#define IDirectPlayVoiceClient_Connect(p,a,b,c)             (p)->lpVtbl->Connect(p,a,b,c)
+#define IDirectPlayVoiceClient_Disconnect(p,a)              (p)->lpVtbl->Disconnect(p,a)
+#define IDirectPlayVoiceClient_GetSessionDesc(p,a)          (p)->lpVtbl->GetSessionDesc(p,a)
+#define IDirectPlayVoiceClient_GetClientConfig(p,a)         (p)->lpVtbl->GetClientConfig(p,a)
+#define IDirectPlayVoiceClient_SetClientConfig(p,a)         (p)->lpVtbl->SetClientConfig(p,a)
+#define IDirectPlayVoiceClient_GetCaps(p,a)                 (p)->lpVtbl->GetCaps(p,a)
+#define IDirectPlayVoiceClient_GetCompressionTypes(p,a,b,c,d) (p)->lpVtbl->GetCompressionTypes(p,a,b,c,d)
+#define IDirectPlayVoiceClient_SetTransmitTargets(p,a,b,c)  (p)->lpVtbl->SetTransmitTargets(p,a,b,c)
+#define IDirectPlayVoiceClient_GetTransmitTargets(p,a,b,c)  (p)->lpVtbl->GetTransmitTargets(p,a,b,c)
+#define IDirectPlayVoiceClient_Create3DSoundBuffer(p,a,b,c,d,e)   (p)->lpVtbl->Create3DSoundBuffer(p,a,b,c,d,e)
+#define IDirectPlayVoiceClient_Delete3DSoundBuffer(p,a,b)   (p)->lpVtbl->Delete3DSoundBuffer(p,a,b)
+#define IDirectPlayVoiceClient_SetNotifyMask(p,a,b)         (p)->lpVtbl->SetNotifyMask(p,a,b)
+#define IDirectPlayVoiceClient_GetSoundDeviceConfig(p,a,b)  (p)->lpVtbl->GetSoundDeviceConfig(p,a,b)
+
+#define IDirectPlayVoiceServer_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectPlayVoiceServer_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectPlayVoiceServer_Release(p)                   (p)->lpVtbl->Release(p)
+
+#define IDirectPlayVoiceServer_Initialize(p,a,b,c,d,e)      (p)->lpVtbl->Initialize(p,a,b,c,d,e)
+#define IDirectPlayVoiceServer_StartSession(p,a,b)          (p)->lpVtbl->StartSession(p,a,b)
+#define IDirectPlayVoiceServer_StopSession(p,a)             (p)->lpVtbl->StopSession(p,a)
+#define IDirectPlayVoiceServer_GetSessionDesc(p,a)          (p)->lpVtbl->GetSessionDesc(p,a)
+#define IDirectPlayVoiceServer_SetSessionDesc(p,a)          (p)->lpVtbl->SetSessionDesc(p,a)
+#define IDirectPlayVoiceServer_GetCaps(p,a)                 (p)->lpVtbl->GetCaps(p,a)
+#define IDirectPlayVoiceServer_GetCompressionTypes(p,a,b,c,d) (p)->lpVtbl->GetCompressionTypes(p,a,b,c,d)
+#define IDirectPlayVoiceServer_SetTransmitTargets(p,a,b,c,d)	(p)->lpVtbl->SetTransmitTargets(p,a,b,c,d)
+#define IDirectPlayVoiceServer_GetTransmitTargets(p,a,b,c,d)	(p)->lpVtbl->GetTransmitTargets(p,a,b,c,d)
+#define IDirectPlayVoiceServer_SetNotifyMask(p,a,b)         (p)->lpVtbl->SetNotifyMask(p,a,b)
+#define IDirectPlayVoiceTest_QueryInterface(p,a,b)          (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectPlayVoiceTest_AddRef(p)                      (p)->lpVtbl->AddRef(p)
+#define IDirectPlayVoiceTest_Release(p)                	    (p)->lpVtbl->Release(p)
+#define IDirectPlayVoiceTest_CheckAudioSetup(p,a,b,c,d)     (p)->lpVtbl->CheckAudioSetup(p,a,b,c,d)
+
+
+#else /* C++ */
+
+#define IDirectPlayVoiceClient_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirectPlayVoiceClient_AddRef(p)                    (p)->AddRef()
+#define IDirectPlayVoiceClient_Release(p)               	(p)->Release()
+
+#define IDirectPlayVoiceClient_Initialize(p,a,b,c,d,e)      (p)->Initialize(a,b,c,d,e)
+#define IDirectPlayVoiceClient_Connect(p,a,b,c)             (p)->Connect(a,b,c)
+#define IDirectPlayVoiceClient_Disconnect(p,a)              (p)->Disconnect(a)
+#define IDirectPlayVoiceClient_GetSessionDesc(p,a)          (p)->GetSessionDesc(a)
+#define IDirectPlayVoiceClient_GetClientConfig(p,a)         (p)->GetClientConfig(a)
+#define IDirectPlayVoiceClient_SetClientConfig(p,a)         (p)->SetClientConfig(a)
+#define IDirectPlayVoiceClient_GetCaps(p,a)                 (p)->GetCaps(a)
+#define IDirectPlayVoiceClient_GetCompressionTypes(p,a,b,c,d) (p)->GetCompressionTypes(a,b,c,d)
+#define IDirectPlayVoiceClient_SetTransmitTargets(p,a,b,c)  (p)->SetTransmitTargets(a,b,c)
+#define IDirectPlayVoiceClient_GetTransmitTargets(p,a,b,c)  (p)->GetTransmitTargets(a,b,c)
+#define IDirectPlayVoiceClient_Create3DSoundBuffer(p,a,b,c,d,e)   (p)->Create3DSoundBuffer(a,b,c,d,e)
+#define IDirectPlayVoiceClient_Delete3DSoundBuffer(p,a,b)   (p)->Delete3DSoundBuffer(a,b)
+#define IDirectPlayVoiceClient_SetNotifyMask(p,a,b)         (p)->SetNotifyMask(a,b)
+#define IDirectPlayVoiceClient_GetSoundDeviceConfig(p,a,b)    (p)->GetSoundDeviceConfig(a,b)
+
+#define IDirectPlayVoiceServer_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirectPlayVoiceServer_AddRef(p)                    (p)->AddRef()
+#define IDirectPlayVoiceServer_Release(p)                   (p)->Release()
+
+#define IDirectPlayVoiceServer_Initialize(p,a,b,c,d,e)      (p)->Initialize(a,b,c,d,e)
+#define IDirectPlayVoiceServer_StartSession(p,a,b)          (p)->StartSession(a,b)
+#define IDirectPlayVoiceServer_StopSession(p,a)             (p)->StopSession(a)
+#define IDirectPlayVoiceServer_GetSessionDesc(p,a)            (p)->GetSessionDesc(a)
+#define IDirectPlayVoiceServer_SetSessionDesc(p,a)            (p)->SetSessionDesc(a)
+#define IDirectPlayVoiceServer_GetCaps(p,a)                 (p)->GetCaps(a)
+#define IDirectPlayVoiceServer_GetCompressionTypes(p,a,b,c,d) (p)->GetCompressionTypes(a,b,c,d)
+#define IDirectPlayVoiceServer_SetTransmitTargets(p,a,b,c,d) (p)->SetTransmitTargets(a,b,c,d)
+#define IDirectPlayVoiceServer_GetTransmitTargets(p,a,b,c,d) (p)->GetTransmitTargets(a,b,c,d)
+#define IDirectPlayVoiceServer_SetNotifyMask(p,a,b)         (p)->SetNotifyMask(a,b)
+
+#define IDirectPlayVoiceTest_QueryInterface(p,a,b)          (p)->QueryInterface(a,b)
+#define IDirectPlayVoiceTest_AddRef(p)                      (p)->AddRef()
+#define IDirectPlayVoiceTest_Release(p)                     (p)->Release()
+#define IDirectPlayVoiceTest_CheckAudioSetup(p,a,b,c,d)     (p)->CheckAudioSetup(a,b,c,d)
+
+
+#endif
+
+
+/****************************************************************************
+ *
+ * DIRECTPLAYVOICE ERRORS
+ *
+ * Errors are represented by negative values and cannot be combined.
+ *
+ ****************************************************************************/
+
+#define _FACDPV  0x15
+#define MAKE_DVHRESULT( code )          MAKE_HRESULT( 1, _FACDPV, code )
+
+#define DV_OK                           S_OK
+#define DV_FULLDUPLEX                   MAKE_HRESULT( 0, _FACDPV,  0x0005 )
+#define DV_HALFDUPLEX                   MAKE_HRESULT( 0, _FACDPV,  0x000A )
+#define DV_PENDING						MAKE_HRESULT( 0, _FACDPV,  0x0010 )
+
+#define DVERR_BUFFERTOOSMALL            MAKE_DVHRESULT(  0x001E )
+#define DVERR_EXCEPTION                 MAKE_DVHRESULT(  0x004A )
+#define DVERR_GENERIC                   E_FAIL
+#define DVERR_INVALIDFLAGS              MAKE_DVHRESULT( 0x0078 )
+#define DVERR_INVALIDOBJECT             MAKE_DVHRESULT( 0x0082 )
+#define DVERR_INVALIDPARAM              E_INVALIDARG
+#define DVERR_INVALIDPLAYER             MAKE_DVHRESULT( 0x0087 )
+#define DVERR_INVALIDGROUP              MAKE_DVHRESULT( 0x0091 )
+#define DVERR_INVALIDHANDLE             MAKE_DVHRESULT( 0x0096 )
+#define DVERR_OUTOFMEMORY               E_OUTOFMEMORY
+#define DVERR_PENDING                   DV_PENDING
+#define DVERR_NOTSUPPORTED              E_NOTIMPL
+#define DVERR_NOINTERFACE               E_NOINTERFACE
+#define DVERR_SESSIONLOST               MAKE_DVHRESULT( 0x012C )
+#define DVERR_NOVOICESESSION            MAKE_DVHRESULT( 0x012E )
+#define DVERR_CONNECTIONLOST            MAKE_DVHRESULT( 0x0168 )
+#define DVERR_NOTINITIALIZED            MAKE_DVHRESULT( 0x0169 )
+#define DVERR_CONNECTED                 MAKE_DVHRESULT( 0x016A )
+#define DVERR_NOTCONNECTED              MAKE_DVHRESULT( 0x016B )
+#define DVERR_CONNECTABORTING           MAKE_DVHRESULT( 0x016E )
+#define DVERR_NOTALLOWED                MAKE_DVHRESULT( 0x016F )
+#define DVERR_INVALIDTARGET             MAKE_DVHRESULT( 0x0170 )
+#define DVERR_TRANSPORTNOTHOST          MAKE_DVHRESULT( 0x0171 )
+#define DVERR_COMPRESSIONNOTSUPPORTED   MAKE_DVHRESULT( 0x0172 )
+#define DVERR_ALREADYPENDING            MAKE_DVHRESULT( 0x0173 )
+#define DVERR_SOUNDINITFAILURE          MAKE_DVHRESULT( 0x0174 )
+#define DVERR_TIMEOUT                   MAKE_DVHRESULT( 0x0175 )
+#define DVERR_CONNECTABORTED            MAKE_DVHRESULT( 0x0176 )
+#define DVERR_NO3DSOUND                 MAKE_DVHRESULT( 0x0177 )
+#define DVERR_ALREADYBUFFERED	        MAKE_DVHRESULT( 0x0178 )
+#define DVERR_NOTBUFFERED               MAKE_DVHRESULT( 0x0179 )
+#define DVERR_HOSTING                   MAKE_DVHRESULT( 0x017A )
+#define DVERR_NOTHOSTING                MAKE_DVHRESULT( 0x017B )
+#define DVERR_INVALIDDEVICE             MAKE_DVHRESULT( 0x017C )
+#define DVERR_RECORDSYSTEMERROR         MAKE_DVHRESULT( 0x017D )
+#define DVERR_PLAYBACKSYSTEMERROR       MAKE_DVHRESULT( 0x017E )
+#define DVERR_SENDERROR                 MAKE_DVHRESULT( 0x017F )
+#define DVERR_USERCANCEL                MAKE_DVHRESULT( 0x0180 )
+#define DVERR_RUNSETUP                  MAKE_DVHRESULT( 0x0183 )
+#define DVERR_INCOMPATIBLEVERSION       MAKE_DVHRESULT( 0x0184 )
+#define DVERR_INITIALIZED               MAKE_DVHRESULT( 0x0187 )
+#define DVERR_INVALIDPOINTER            E_POINTER
+#define DVERR_NOTRANSPORT               MAKE_DVHRESULT( 0x0188 )
+#define DVERR_NOCALLBACK                MAKE_DVHRESULT( 0x0189 )
+#define DVERR_TRANSPORTNOTINIT          MAKE_DVHRESULT( 0x018A )
+#define DVERR_TRANSPORTNOSESSION        MAKE_DVHRESULT( 0x018B )
+#define DVERR_TRANSPORTNOPLAYER         MAKE_DVHRESULT( 0x018C )
+#define DVERR_USERBACK                  MAKE_DVHRESULT( 0x018D )
+#define DVERR_NORECVOLAVAILABLE         MAKE_DVHRESULT( 0x018E )
+#define DVERR_INVALIDBUFFER				MAKE_DVHRESULT( 0x018F )
+#define DVERR_LOCKEDBUFFER				MAKE_DVHRESULT( 0x0190 )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/lib/.svn/all-wcprops	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,35 @@
+K 25
+svn:wc:ra_dav:version-url
+V 40
+/svn/bb7/!svn/ver/289/libs/legacy_dx/lib
+END
+dinput8.lib
+K 25
+svn:wc:ra_dav:version-url
+V 52
+/svn/bb7/!svn/ver/289/libs/legacy_dx/lib/dinput8.lib
+END
+ddraw.lib
+K 25
+svn:wc:ra_dav:version-url
+V 50
+/svn/bb7/!svn/ver/289/libs/legacy_dx/lib/ddraw.lib
+END
+dinput.lib
+K 25
+svn:wc:ra_dav:version-url
+V 51
+/svn/bb7/!svn/ver/289/libs/legacy_dx/lib/dinput.lib
+END
+dxguid.lib
+K 25
+svn:wc:ra_dav:version-url
+V 51
+/svn/bb7/!svn/ver/289/libs/legacy_dx/lib/dxguid.lib
+END
+d3dxof.lib
+K 25
+svn:wc:ra_dav:version-url
+V 51
+/svn/bb7/!svn/ver/289/libs/legacy_dx/lib/d3dxof.lib
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/lib/.svn/entries	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,198 @@
+10
+
+dir
+316
+http://svn2.assembla.com/svn/bb7/libs/legacy_dx/lib
+http://svn2.assembla.com/svn/bb7
+
+
+
+2010-12-18T21:09:41.003199Z
+289
+Feaerenil
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0b0191bc-8333-4b8d-b53c-6b3aa212730c
+
+dinput8.lib
+file
+
+
+
+
+2004-09-03T13:18:30.000000Z
+a9300cdf7a34c7da7be2117e099e15a7
+2010-12-18T21:09:41.003199Z
+289
+Feaerenil
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+173542
+
+ddraw.lib
+file
+
+
+
+
+2004-09-06T18:58:26.000000Z
+77752b153225ae97f64688aa5c16db31
+2010-12-18T21:09:41.003199Z
+289
+Feaerenil
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4540
+
+dinput.lib
+file
+
+
+
+
+2004-09-03T13:18:30.000000Z
+21f11641cd6d0b29f2979fcad555a81e
+2010-12-18T21:09:41.003199Z
+289
+Feaerenil
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+161464
+
+dxguid.lib
+file
+
+
+
+
+2005-05-26T12:11:04.000000Z
+b5d00b6a24df5706d25ae59b9ff77658
+2010-12-18T21:09:41.003199Z
+289
+Feaerenil
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+408632
+
+d3dxof.lib
+file
+
+
+
+
+2004-09-29T14:47:54.000000Z
+f17de8653cb71aa503a45d7908a6c296
+2010-12-18T21:09:41.003199Z
+289
+Feaerenil
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1746
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/lib/.svn/prop-base/d3dxof.lib.svn-base	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/lib/.svn/prop-base/ddraw.lib.svn-base	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/lib/.svn/prop-base/dinput.lib.svn-base	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/lib/.svn/prop-base/dinput8.lib.svn-base	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/lib/.svn/prop-base/dxguid.lib.svn-base	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
Binary file lib/legacy_dx/lib/.svn/text-base/d3dxof.lib.svn-base has changed
Binary file lib/legacy_dx/lib/.svn/text-base/ddraw.lib.svn-base has changed
Binary file lib/legacy_dx/lib/.svn/text-base/dinput.lib.svn-base has changed
Binary file lib/legacy_dx/lib/.svn/text-base/dinput8.lib.svn-base has changed
Binary file lib/legacy_dx/lib/.svn/text-base/dxguid.lib.svn-base has changed
Binary file lib/legacy_dx/lib/d3dxof.lib has changed
Binary file lib/legacy_dx/lib/ddraw.lib has changed
Binary file lib/legacy_dx/lib/dinput.lib has changed
Binary file lib/legacy_dx/lib/dinput8.lib has changed
Binary file lib/legacy_dx/lib/dxguid.lib has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/multimon.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,484 @@
+//=============================================================================
+//
+// multimon.h -- Stub module that fakes multiple monitor apis on Win32 OSes
+//               without them.
+//
+// By using this header your code will get back default values from
+// GetSystemMetrics() for new metrics, and the new multimonitor APIs
+// will act like only one display is present on a Win32 OS without
+// multimonitor APIs.
+//
+// Exactly one source must include this with COMPILE_MULTIMON_STUBS defined.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved. 
+//
+//=============================================================================
+
+#ifdef __cplusplus
+extern "C" {            // Assume C declarations for C++
+#endif // __cplusplus
+
+//
+// If we are building with Win95/NT4 headers, we need to declare
+// the multimonitor-related metrics and APIs ourselves.
+//
+#ifndef SM_CMONITORS
+
+#define SM_XVIRTUALSCREEN       76
+#define SM_YVIRTUALSCREEN       77
+#define SM_CXVIRTUALSCREEN      78
+#define SM_CYVIRTUALSCREEN      79
+#define SM_CMONITORS            80
+#define SM_SAMEDISPLAYFORMAT    81
+
+// HMONITOR is already declared if WINVER >= 0x0500 in windef.h
+// This is for components built with an older version number.
+//
+#if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500)
+DECLARE_HANDLE(HMONITOR);
+#define HMONITOR_DECLARED
+#endif
+
+#define MONITOR_DEFAULTTONULL       0x00000000
+#define MONITOR_DEFAULTTOPRIMARY    0x00000001
+#define MONITOR_DEFAULTTONEAREST    0x00000002
+
+#define MONITORINFOF_PRIMARY        0x00000001
+
+typedef struct tagMONITORINFO
+{
+    DWORD   cbSize;
+    RECT    rcMonitor;
+    RECT    rcWork;
+    DWORD   dwFlags;
+} MONITORINFO, *LPMONITORINFO;
+
+#ifndef CCHDEVICENAME
+#define CCHDEVICENAME 32
+#endif
+
+#ifdef __cplusplus
+typedef struct tagMONITORINFOEXA : public tagMONITORINFO
+{
+    CHAR        szDevice[CCHDEVICENAME];
+} MONITORINFOEXA, *LPMONITORINFOEXA;
+typedef struct tagMONITORINFOEXW : public tagMONITORINFO
+{
+    WCHAR       szDevice[CCHDEVICENAME];
+} MONITORINFOEXW, *LPMONITORINFOEXW;
+#ifdef UNICODE
+typedef MONITORINFOEXW MONITORINFOEX;
+typedef LPMONITORINFOEXW LPMONITORINFOEX;
+#else
+typedef MONITORINFOEXA MONITORINFOEX;
+typedef LPMONITORINFOEXA LPMONITORINFOEX;
+#endif // UNICODE
+#else // ndef __cplusplus
+typedef struct tagMONITORINFOEXA
+{
+    MONITORINFO;
+    CHAR        szDevice[CCHDEVICENAME];
+} MONITORINFOEXA, *LPMONITORINFOEXA;
+typedef struct tagMONITORINFOEXW
+{
+    MONITORINFO;
+    WCHAR       szDevice[CCHDEVICENAME];
+} MONITORINFOEXW, *LPMONITORINFOEXW;
+#ifdef UNICODE
+typedef MONITORINFOEXW MONITORINFOEX;
+typedef LPMONITORINFOEXW LPMONITORINFOEX;
+#else
+typedef MONITORINFOEXA MONITORINFOEX;
+typedef LPMONITORINFOEXA LPMONITORINFOEX;
+#endif // UNICODE
+#endif
+
+typedef BOOL (CALLBACK* MONITORENUMPROC)(HMONITOR, HDC, LPRECT, LPARAM);
+
+#ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
+typedef struct _DISPLAY_DEVICEA {
+    DWORD  cb;
+    CHAR   DeviceName[32];
+    CHAR   DeviceString[128];
+    DWORD  StateFlags;
+    CHAR   DeviceID[128];
+    CHAR   DeviceKey[128];
+} DISPLAY_DEVICEA, *PDISPLAY_DEVICEA, *LPDISPLAY_DEVICEA;
+typedef struct _DISPLAY_DEVICEW {
+    DWORD  cb;
+    WCHAR  DeviceName[32];
+    WCHAR  DeviceString[128];
+    DWORD  StateFlags;
+    WCHAR  DeviceID[128];
+    WCHAR  DeviceKey[128];
+} DISPLAY_DEVICEW, *PDISPLAY_DEVICEW, *LPDISPLAY_DEVICEW;
+#ifdef UNICODE
+typedef DISPLAY_DEVICEW DISPLAY_DEVICE;
+typedef PDISPLAY_DEVICEW PDISPLAY_DEVICE;
+typedef LPDISPLAY_DEVICEW LPDISPLAY_DEVICE;
+#else
+typedef DISPLAY_DEVICEA DISPLAY_DEVICE;
+typedef PDISPLAY_DEVICEA PDISPLAY_DEVICE;
+typedef LPDISPLAY_DEVICEA LPDISPLAY_DEVICE;
+#endif // UNICODE
+
+#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
+#define DISPLAY_DEVICE_MULTI_DRIVER        0x00000002
+#define DISPLAY_DEVICE_PRIMARY_DEVICE      0x00000004
+#define DISPLAY_DEVICE_MIRRORING_DRIVER    0x00000008
+#define DISPLAY_DEVICE_VGA_COMPATIBLE      0x00000010
+#endif
+
+#endif  // SM_CMONITORS
+
+#undef GetMonitorInfo
+#undef GetSystemMetrics
+#undef MonitorFromWindow
+#undef MonitorFromRect
+#undef MonitorFromPoint
+#undef EnumDisplayMonitors
+#undef EnumDisplayDevices
+
+//
+// Define COMPILE_MULTIMON_STUBS to compile the stubs;
+// otherwise, you get the declarations.
+//
+#ifdef COMPILE_MULTIMON_STUBS
+
+//-----------------------------------------------------------------------------
+//
+// Implement the API stubs.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef MULTIMON_FNS_DEFINED
+
+int      (WINAPI* g_pfnGetSystemMetrics)(int) = NULL;
+HMONITOR (WINAPI* g_pfnMonitorFromWindow)(HWND, DWORD) = NULL;
+HMONITOR (WINAPI* g_pfnMonitorFromRect)(LPCRECT, DWORD) = NULL;
+HMONITOR (WINAPI* g_pfnMonitorFromPoint)(POINT, DWORD) = NULL;
+BOOL     (WINAPI* g_pfnGetMonitorInfo)(HMONITOR, LPMONITORINFO) = NULL;
+BOOL     (WINAPI* g_pfnEnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM) = NULL;
+BOOL     (WINAPI* g_pfnEnumDisplayDevices)(PVOID, DWORD, PDISPLAY_DEVICE,DWORD) = NULL;
+BOOL     g_fMultiMonInitDone = FALSE;
+BOOL     g_fMultimonPlatformNT = FALSE;
+
+#endif
+
+BOOL IsPlatformNT()
+{ 
+    OSVERSIONINFOA osvi = {0};
+    osvi.dwOSVersionInfoSize = sizeof(osvi);
+    GetVersionExA((OSVERSIONINFOA*)&osvi);
+    return (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId);    
+}
+
+BOOL InitMultipleMonitorStubs(void)
+{
+    HMODULE hUser32;
+    if (g_fMultiMonInitDone)
+    {
+        return g_pfnGetMonitorInfo != NULL;
+    }
+
+    g_fMultimonPlatformNT = IsPlatformNT();
+    hUser32 = GetModuleHandle(TEXT("USER32"));
+    if (hUser32 &&
+        (*(FARPROC*)&g_pfnGetSystemMetrics    = GetProcAddress(hUser32,"GetSystemMetrics")) != NULL &&
+        (*(FARPROC*)&g_pfnMonitorFromWindow   = GetProcAddress(hUser32,"MonitorFromWindow")) != NULL &&
+        (*(FARPROC*)&g_pfnMonitorFromRect     = GetProcAddress(hUser32,"MonitorFromRect")) != NULL &&
+        (*(FARPROC*)&g_pfnMonitorFromPoint    = GetProcAddress(hUser32,"MonitorFromPoint")) != NULL &&
+        (*(FARPROC*)&g_pfnEnumDisplayMonitors = GetProcAddress(hUser32,"EnumDisplayMonitors")) != NULL &&
+#ifdef UNICODE
+        (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesW")) != NULL &&
+        (*(FARPROC*)&g_pfnGetMonitorInfo      = g_fMultimonPlatformNT ? GetProcAddress(hUser32,"GetMonitorInfoW") : 
+                                                GetProcAddress(hUser32,"GetMonitorInfoA")) != NULL
+#else
+        (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoA")) != NULL &&
+        (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesA")) != NULL
+#endif
+    ) {
+        g_fMultiMonInitDone = TRUE;
+        return TRUE;
+    }
+    else
+    {
+        g_pfnGetSystemMetrics    = NULL;
+        g_pfnMonitorFromWindow   = NULL;
+        g_pfnMonitorFromRect     = NULL;
+        g_pfnMonitorFromPoint    = NULL;
+        g_pfnGetMonitorInfo      = NULL;
+        g_pfnEnumDisplayMonitors = NULL;
+        g_pfnEnumDisplayDevices  = NULL;
+
+        g_fMultiMonInitDone = TRUE;
+        return FALSE;
+    }
+}
+
+//-----------------------------------------------------------------------------
+//
+// fake implementations of Monitor APIs that work with the primary display
+// no special parameter validation is made since these run in client code
+//
+//-----------------------------------------------------------------------------
+
+int WINAPI
+xGetSystemMetrics(int nIndex)
+{
+    if (InitMultipleMonitorStubs())
+        return g_pfnGetSystemMetrics(nIndex);
+
+    switch (nIndex)
+    {
+    case SM_CMONITORS:
+    case SM_SAMEDISPLAYFORMAT:
+        return 1;
+
+    case SM_XVIRTUALSCREEN:
+    case SM_YVIRTUALSCREEN:
+        return 0;
+
+    case SM_CXVIRTUALSCREEN:
+        nIndex = SM_CXSCREEN;
+        break;
+
+    case SM_CYVIRTUALSCREEN:
+        nIndex = SM_CYSCREEN;
+        break;
+    }
+
+    return GetSystemMetrics(nIndex);
+}
+
+#define xPRIMARY_MONITOR ((HMONITOR)0x12340042)
+
+HMONITOR WINAPI
+xMonitorFromPoint(POINT ptScreenCoords, DWORD dwFlags)
+{
+    if (InitMultipleMonitorStubs())
+        return g_pfnMonitorFromPoint(ptScreenCoords, dwFlags);
+
+    if ((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
+        ((ptScreenCoords.x >= 0) &&
+        (ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) &&
+        (ptScreenCoords.y >= 0) &&
+        (ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN))))
+    {
+        return xPRIMARY_MONITOR;
+    }
+
+    return NULL;
+}
+
+HMONITOR WINAPI
+xMonitorFromRect(LPCRECT lprcScreenCoords, DWORD dwFlags)
+{
+    if (InitMultipleMonitorStubs())
+        return g_pfnMonitorFromRect(lprcScreenCoords, dwFlags);
+
+    if ((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
+        ((lprcScreenCoords->right > 0) &&
+        (lprcScreenCoords->bottom > 0) &&
+        (lprcScreenCoords->left < GetSystemMetrics(SM_CXSCREEN)) &&
+        (lprcScreenCoords->top < GetSystemMetrics(SM_CYSCREEN))))
+    {
+        return xPRIMARY_MONITOR;
+    }
+
+    return NULL;
+}
+
+HMONITOR WINAPI
+xMonitorFromWindow(HWND hWnd, DWORD dwFlags)
+{
+    WINDOWPLACEMENT wp;
+
+    if (InitMultipleMonitorStubs())
+        return g_pfnMonitorFromWindow(hWnd, dwFlags);
+
+    if (dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST))
+        return xPRIMARY_MONITOR;
+
+    if (IsIconic(hWnd) ?
+            GetWindowPlacement(hWnd, &wp) :
+            GetWindowRect(hWnd, &wp.rcNormalPosition)) {
+
+        return xMonitorFromRect(&wp.rcNormalPosition, dwFlags);
+    }
+
+    return NULL;
+}
+
+BOOL WINAPI
+xGetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
+{
+    RECT rcWork;
+
+    if (InitMultipleMonitorStubs())
+    {
+        BOOL f = g_pfnGetMonitorInfo(hMonitor, lpMonitorInfo);
+#ifdef UNICODE
+        if (f && !g_fMultimonPlatformNT && (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX)))
+        { 
+            MultiByteToWideChar(CP_ACP, 0,
+                (LPSTR)((MONITORINFOEX*)lpMonitorInfo)->szDevice, -1,
+                ((MONITORINFOEX*)lpMonitorInfo)->szDevice, (sizeof(((MONITORINFOEX*)lpMonitorInfo)->szDevice)/sizeof(TCHAR)));
+        }
+#endif
+        return f;
+    }
+
+    if ((hMonitor == xPRIMARY_MONITOR) &&
+        lpMonitorInfo &&
+        (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
+        SystemParametersInfoA(SPI_GETWORKAREA, 0, &rcWork, 0))
+    {
+        lpMonitorInfo->rcMonitor.left = 0;
+        lpMonitorInfo->rcMonitor.top  = 0;
+        lpMonitorInfo->rcMonitor.right  = GetSystemMetrics(SM_CXSCREEN);
+        lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
+        lpMonitorInfo->rcWork = rcWork;
+        lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
+
+        if (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX))
+        {
+#ifdef UNICODE
+            MultiByteToWideChar(CP_ACP, 0, "DISPLAY", -1, ((MONITORINFOEX*)lpMonitorInfo)->szDevice, (sizeof(((MONITORINFOEX*)lpMonitorInfo)->szDevice)/sizeof(TCHAR)));
+#else // UNICODE
+            lstrcpy(((MONITORINFOEX*)lpMonitorInfo)->szDevice, TEXT("DISPLAY"));
+#endif // UNICODE
+        }
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+BOOL WINAPI
+xEnumDisplayMonitors(
+        HDC             hdcOptionalForPainting,
+        LPCRECT         lprcEnumMonitorsThatIntersect,
+        MONITORENUMPROC lpfnEnumProc,
+        LPARAM          dwData)
+{
+    RECT rcLimit;
+
+    if (InitMultipleMonitorStubs()) {
+        return g_pfnEnumDisplayMonitors(
+                hdcOptionalForPainting,
+                lprcEnumMonitorsThatIntersect,
+                lpfnEnumProc,
+                dwData);
+    }
+
+    if (!lpfnEnumProc)
+        return FALSE;
+
+    rcLimit.left   = 0;
+    rcLimit.top    = 0;
+    rcLimit.right  = GetSystemMetrics(SM_CXSCREEN);
+    rcLimit.bottom = GetSystemMetrics(SM_CYSCREEN);
+
+    if (hdcOptionalForPainting)
+    {
+        RECT    rcClip;
+        POINT   ptOrg;
+
+        switch (GetClipBox(hdcOptionalForPainting, &rcClip))
+        {
+        default:
+            if (!GetDCOrgEx(hdcOptionalForPainting, &ptOrg))
+                return FALSE;
+
+            OffsetRect(&rcLimit, -ptOrg.x, -ptOrg.y);
+            if (IntersectRect(&rcLimit, &rcLimit, &rcClip) &&
+                (!lprcEnumMonitorsThatIntersect ||
+                     IntersectRect(&rcLimit, &rcLimit, lprcEnumMonitorsThatIntersect))) {
+
+                break;
+            }
+            //fall thru
+        case NULLREGION:
+             return TRUE;
+        case ERROR:
+             return FALSE;
+        }
+    } else {
+        if (    lprcEnumMonitorsThatIntersect &&
+                !IntersectRect(&rcLimit, &rcLimit, lprcEnumMonitorsThatIntersect)) {
+
+            return TRUE;
+        }
+    }
+
+    return lpfnEnumProc(
+            xPRIMARY_MONITOR,
+            hdcOptionalForPainting,
+            &rcLimit,
+            dwData);
+}
+
+BOOL WINAPI
+xEnumDisplayDevices(
+    PVOID Unused,
+    DWORD iDevNum,
+    PDISPLAY_DEVICE lpDisplayDevice,
+    DWORD dwFlags)
+{
+    if (InitMultipleMonitorStubs())
+        return g_pfnEnumDisplayDevices(Unused, iDevNum, lpDisplayDevice, dwFlags);
+
+    if (Unused != NULL)
+        return FALSE;
+
+    if (iDevNum != 0)
+        return FALSE;
+
+    if (lpDisplayDevice == NULL || lpDisplayDevice->cb < sizeof(DISPLAY_DEVICE))
+        return FALSE;
+
+#ifdef UNICODE
+    MultiByteToWideChar(CP_ACP, 0, "DISPLAY", -1, lpDisplayDevice->DeviceName, (sizeof(lpDisplayDevice->DeviceName)/sizeof(TCHAR)));
+    MultiByteToWideChar(CP_ACP, 0, "DISPLAY", -1, lpDisplayDevice->DeviceString, (sizeof(lpDisplayDevice->DeviceName)/sizeof(TCHAR)));
+#else // UNICODE
+    lstrcpy((LPTSTR)lpDisplayDevice->DeviceName,   TEXT("DISPLAY"));
+    lstrcpy((LPTSTR)lpDisplayDevice->DeviceString, TEXT("DISPLAY"));
+#endif // UNICODE
+
+    lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE;
+
+    return TRUE;
+}
+
+#undef xPRIMARY_MONITOR
+#undef COMPILE_MULTIMON_STUBS
+
+#else   // COMPILE_MULTIMON_STUBS
+
+extern int  WINAPI xGetSystemMetrics(int);
+extern HMONITOR WINAPI xMonitorFromWindow(HWND, DWORD);
+extern HMONITOR WINAPI xMonitorFromRect(LPCRECT, DWORD);
+extern HMONITOR WINAPI xMonitorFromPoint(POINT, DWORD);
+extern BOOL WINAPI xGetMonitorInfo(HMONITOR, LPMONITORINFO);
+extern BOOL WINAPI xEnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
+extern BOOL WINAPI xEnumDisplayDevices(PVOID, DWORD, PDISPLAY_DEVICE, DWORD);
+
+#endif  // COMPILE_MULTIMON_STUBS
+
+//
+// build defines that replace the regular APIs with our versions
+//
+#define GetSystemMetrics    xGetSystemMetrics
+#define MonitorFromWindow   xMonitorFromWindow
+#define MonitorFromRect     xMonitorFromRect
+#define MonitorFromPoint    xMonitorFromPoint
+#define GetMonitorInfo      xGetMonitorInfo
+#define EnumDisplayMonitors xEnumDisplayMonitors
+#define EnumDisplayDevices  xEnumDisplayDevices
+
+#ifdef __cplusplus
+}
+#endif  // __cplusplus
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/rmxfguid.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,223 @@
+/***************************************************************************
+ *
+ *  Copyright (C) 1998-1999 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       rmxfguid.h
+ *
+ *  Content:    Defines GUIDs of D3DRM's templates.
+ *
+ ***************************************************************************/
+
+#ifndef __RMXFGUID_H_
+#define __RMXFGUID_H_
+
+/* {2B957100-9E9A-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMInfo,
+0x2b957100, 0x9e9a, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {3D82AB44-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMMesh,
+0x3d82ab44, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {3D82AB5E-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMVector,
+0x3d82ab5e, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {3D82AB5F-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMMeshFace,
+0x3d82ab5f, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {3D82AB4D-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMMaterial,
+0x3d82ab4d, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {35FF44E1-6C7C-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMaterialArray,
+0x35ff44e1, 0x6c7c, 0x11cf, 0x8F, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {3D82AB46-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMFrame,
+0x3d82ab46, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {F6F23F41-7686-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMFrameTransformMatrix,
+0xf6f23f41, 0x7686, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {F6F23F42-7686-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMeshMaterialList,
+0xf6f23f42, 0x7686, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {F6F23F40-7686-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMeshTextureCoords,
+0xf6f23f40, 0x7686, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {F6F23F43-7686-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMeshNormals,
+0xf6f23f43, 0x7686, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {F6F23F44-7686-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMCoords2d,
+0xf6f23f44, 0x7686, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {F6F23F45-7686-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMatrix4x4,
+0xf6f23f45, 0x7686, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {3D82AB4F-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMAnimation,
+0x3d82ab4f, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {3D82AB50-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMAnimationSet,
+0x3d82ab50, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {10DD46A8-775B-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMAnimationKey,
+0x10dd46a8, 0x775b, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xA3);
+
+/* {10DD46A9-775B-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMFloatKeys,
+0x10dd46a9, 0x775b, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xA3);
+
+/* {01411840-7786-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMaterialAmbientColor,
+0x01411840, 0x7786, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xA3);
+
+/* {01411841-7786-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMaterialDiffuseColor,
+0x01411841, 0x7786, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xA3);
+
+/* {01411842-7786-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMaterialSpecularColor,
+0x01411842, 0x7786, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xA3);
+
+/* {D3E16E80-7835-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMaterialEmissiveColor,
+0xd3e16e80, 0x7835, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {01411843-7786-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMaterialPower,
+0x01411843, 0x7786, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xA3);
+
+/* {35FF44E0-6C7C-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMColorRGBA,
+0x35ff44e0, 0x6c7c, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xA3);
+
+/* {D3E16E81-7835-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMColorRGB,
+0xd3e16e81, 0x7835, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {A42790E0-7810-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMGuid,
+0xa42790e0, 0x7810, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {A42790E1-7810-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMTextureFilename,
+0xa42790e1, 0x7810, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {A42790E2-7810-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMTextureReference,
+0xa42790e2, 0x7810, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {1630B820-7842-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMIndexedColor,
+0x1630b820, 0x7842, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {1630B821-7842-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMeshVertexColors,
+0x1630b821, 0x7842, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {4885AE60-78E8-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMMaterialWrap,
+0x4885ae60, 0x78e8, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {537DA6A0-CA37-11d0-941C-0080C80CFA7B} */
+DEFINE_GUID(TID_D3DRMBoolean,
+0x537da6a0, 0xca37, 0x11d0, 0x94, 0x1c, 0x0, 0x80, 0xc8, 0xc, 0xfa, 0x7b);
+
+/* {ED1EC5C0-C0A8-11d0-941C-0080C80CFA7B} */
+DEFINE_GUID(TID_D3DRMMeshFaceWraps,
+0xed1ec5c0, 0xc0a8, 0x11d0, 0x94, 0x1c, 0x0, 0x80, 0xc8, 0xc, 0xfa, 0x7b);
+
+/* {4885AE63-78E8-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMBoolean2d,
+0x4885ae63, 0x78e8, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {F406B180-7B3B-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMTimedFloatKeys,
+0xf406b180, 0x7b3b, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {E2BF56C0-840F-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMAnimationOptions,
+0xe2bf56c0, 0x840f, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {E2BF56C1-840F-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMFramePosition,
+0xe2bf56c1, 0x840f, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {E2BF56C2-840F-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMFrameVelocity,
+0xe2bf56c2, 0x840f, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {E2BF56C3-840F-11cf-8F52-0040333594A3} */
+DEFINE_GUID(TID_D3DRMFrameRotation,
+0xe2bf56c3, 0x840f, 0x11cf, 0x8f, 0x52, 0x0, 0x40, 0x33, 0x35, 0x94, 0xa3);
+
+/* {3D82AB4A-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMLight,
+0x3d82ab4a, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {3D82AB51-62DA-11cf-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMCamera,
+0x3d82ab51, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {E5745280-B24F-11cf-9DD5-00AA00A71A2F} */
+DEFINE_GUID(TID_D3DRMAppData,
+0xe5745280, 0xb24f, 0x11cf, 0x9d, 0xd5, 0x0, 0xaa, 0x0, 0xa7, 0x1a, 0x2f);
+
+/* {AED22740-B31F-11cf-9DD5-00AA00A71A2F} */
+DEFINE_GUID(TID_D3DRMLightUmbra,
+0xaed22740, 0xb31f, 0x11cf, 0x9d, 0xd5, 0x0, 0xaa, 0x0, 0xa7, 0x1a, 0x2f);
+
+/* {AED22742-B31F-11cf-9DD5-00AA00A71A2F} */
+DEFINE_GUID(TID_D3DRMLightRange,
+0xaed22742, 0xb31f, 0x11cf, 0x9d, 0xd5, 0x0, 0xaa, 0x0, 0xa7, 0x1a, 0x2f);
+
+/* {AED22741-B31F-11cf-9DD5-00AA00A71A2F} */
+DEFINE_GUID(TID_D3DRMLightPenumbra,
+0xaed22741, 0xb31f, 0x11cf, 0x9d, 0xd5, 0x0, 0xaa, 0x0, 0xa7, 0x1a, 0x2f);
+
+/* {A8A98BA0-C5E5-11cf-B941-0080C80CFA7B} */
+DEFINE_GUID(TID_D3DRMLightAttenuation,
+0xa8a98ba0, 0xc5e5, 0x11cf, 0xb9, 0x41, 0x0, 0x80, 0xc8, 0xc, 0xfa, 0x7b);
+
+/* {3A23EEA0-94B1-11d0-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMInlineData,
+0x3a23eea0, 0x94b1, 0x11d0, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {3A23EEA1-94B1-11d0-AB39-0020AF71E433} */
+DEFINE_GUID(TID_D3DRMUrl,
+0x3a23eea1, 0x94b1, 0x11d0, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
+
+/* {8A63C360-997D-11d0-941C-0080C80CFA7B} */
+DEFINE_GUID(TID_D3DRMProgressiveMesh,
+0x8A63C360, 0x997D, 0x11d0, 0x94, 0x1C, 0x0, 0x80, 0xC8, 0x0C, 0xFA, 0x7B);
+
+/* {98116AA0-BDBA-11d1-82C0-00A0C9697271} */
+DEFINE_GUID(TID_D3DRMExternalVisual,
+0x98116AA0, 0xBDBA, 0x11d1, 0x82, 0xC0, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x71);
+
+/* {7F0F21E0-BFE1-11d1-82C0-00A0C9697271} */
+DEFINE_GUID(TID_D3DRMStringProperty, 
+0x7f0f21e0, 0xbfe1, 0x11d1, 0x82, 0xc0, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x71);
+
+/* {7F0F21E1-BFE1-11d1-82C0-00A0C9697271} */
+DEFINE_GUID(TID_D3DRMPropertyBag, 
+0x7f0f21e1, 0xbfe1, 0x11d1, 0x82, 0xc0, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x71);
+
+// {7F5D5EA0-D53A-11d1-82C0-00A0C9697271}
+DEFINE_GUID(TID_D3DRMRightHanded, 
+0x7f5d5ea0, 0xd53a, 0x11d1, 0x82, 0xc0, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x71);
+
+#endif /* __RMXFGUID_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/rmxftmpl.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,339 @@
+/* D3DRM XFile templates in binary form */
+
+#ifndef _RMXFTMPL_H_
+#define _RMXFTMPL_H_
+
+unsigned char D3DRM_XTEMPLATES[] = {
+	0x78, 0x6f, 0x66, 0x20, 0x30, 0x33, 0x30, 0x32, 0x62, 
+	0x69, 0x6e, 0x20, 0x30, 0x30, 0x36, 0x34, 0x1f, 0, 0x1, 
+	0, 0x6, 0, 0, 0, 0x48, 0x65, 0x61, 0x64, 0x65, 
+	0x72, 0xa, 0, 0x5, 0, 0x43, 0xab, 0x82, 0x3d, 0xda, 
+	0x62, 0xcf, 0x11, 0xab, 0x39, 0, 0x20, 0xaf, 0x71, 0xe4, 
+	0x33, 0x28, 0, 0x1, 0, 0x5, 0, 0, 0, 0x6d, 
+	0x61, 0x6a, 0x6f, 0x72, 0x14, 0, 0x28, 0, 0x1, 0, 
+	0x5, 0, 0, 0, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x14, 
+	0, 0x29, 0, 0x1, 0, 0x5, 0, 0, 0, 0x66, 
+	0x6c, 0x61, 0x67, 0x73, 0x14, 0, 0xb, 0, 0x1f, 0, 
+	0x1, 0, 0x6, 0, 0, 0, 0x56, 0x65, 0x63, 0x74, 
+	0x6f, 0x72, 0xa, 0, 0x5, 0, 0x5e, 0xab, 0x82, 0x3d, 
+	0xda, 0x62, 0xcf, 0x11, 0xab, 0x39, 0, 0x20, 0xaf, 0x71, 
+	0xe4, 0x33, 0x2a, 0, 0x1, 0, 0x1, 0, 0, 0, 
+	0x78, 0x14, 0, 0x2a, 0, 0x1, 0, 0x1, 0, 0, 
+	0, 0x79, 0x14, 0, 0x2a, 0, 0x1, 0, 0x1, 0, 
+	0, 0, 0x7a, 0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 
+	0, 0x8, 0, 0, 0, 0x43, 0x6f, 0x6f, 0x72, 0x64, 
+	0x73, 0x32, 0x64, 0xa, 0, 0x5, 0, 0x44, 0x3f, 0xf2, 
+	0xf6, 0x86, 0x76, 0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 0x33, 
+	0x35, 0x94, 0xa3, 0x2a, 0, 0x1, 0, 0x1, 0, 0, 
+	0, 0x75, 0x14, 0, 0x2a, 0, 0x1, 0, 0x1, 0, 
+	0, 0, 0x76, 0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 
+	0, 0x9, 0, 0, 0, 0x4d, 0x61, 0x74, 0x72, 0x69, 
+	0x78, 0x34, 0x78, 0x34, 0xa, 0, 0x5, 0, 0x45, 0x3f, 
+	0xf2, 0xf6, 0x86, 0x76, 0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 
+	0x33, 0x35, 0x94, 0xa3, 0x34, 0, 0x2a, 0, 0x1, 0, 
+	0x6, 0, 0, 0, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 
+	0xe, 0, 0x3, 0, 0x10, 0, 0, 0, 0xf, 0, 
+	0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 0, 0x9, 0, 
+	0, 0, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x47, 0x42, 
+	0x41, 0xa, 0, 0x5, 0, 0xe0, 0x44, 0xff, 0x35, 0x7c, 
+	0x6c, 0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 0x33, 0x35, 0x94, 
+	0xa3, 0x2a, 0, 0x1, 0, 0x3, 0, 0, 0, 0x72, 
+	0x65, 0x64, 0x14, 0, 0x2a, 0, 0x1, 0, 0x5, 0, 
+	0, 0, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x14, 0, 0x2a, 
+	0, 0x1, 0, 0x4, 0, 0, 0, 0x62, 0x6c, 0x75, 
+	0x65, 0x14, 0, 0x2a, 0, 0x1, 0, 0x5, 0, 0, 
+	0, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x14, 0, 0xb, 0, 
+	0x1f, 0, 0x1, 0, 0x8, 0, 0, 0, 0x43, 0x6f, 
+	0x6c, 0x6f, 0x72, 0x52, 0x47, 0x42, 0xa, 0, 0x5, 0, 
+	0x81, 0x6e, 0xe1, 0xd3, 0x35, 0x78, 0xcf, 0x11, 0x8f, 0x52, 
+	0, 0x40, 0x33, 0x35, 0x94, 0xa3, 0x2a, 0, 0x1, 0, 
+	0x3, 0, 0, 0, 0x72, 0x65, 0x64, 0x14, 0, 0x2a, 
+	0, 0x1, 0, 0x5, 0, 0, 0, 0x67, 0x72, 0x65, 
+	0x65, 0x6e, 0x14, 0, 0x2a, 0, 0x1, 0, 0x4, 0, 
+	0, 0, 0x62, 0x6c, 0x75, 0x65, 0x14, 0, 0xb, 0, 
+	0x1f, 0, 0x1, 0, 0xc, 0, 0, 0, 0x49, 0x6e, 
+	0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 
+	0xa, 0, 0x5, 0, 0x20, 0xb8, 0x30, 0x16, 0x42, 0x78, 
+	0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 0x33, 0x35, 0x94, 0xa3, 
+	0x29, 0, 0x1, 0, 0x5, 0, 0, 0, 0x69, 0x6e, 
+	0x64, 0x65, 0x78, 0x14, 0, 0x1, 0, 0x9, 0, 0, 
+	0, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x47, 0x42, 0x41, 
+	0x1, 0, 0xa, 0, 0, 0, 0x69, 0x6e, 0x64, 0x65, 
+	0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x14, 0, 0xb, 0, 
+	0x1f, 0, 0x1, 0, 0x7, 0, 0, 0, 0x42, 0x6f, 
+	0x6f, 0x6c, 0x65, 0x61, 0x6e, 0xa, 0, 0x5, 0, 0xa0, 
+	0xa6, 0x7d, 0x53, 0x37, 0xca, 0xd0, 0x11, 0x94, 0x1c, 0, 
+	0x80, 0xc8, 0xc, 0xfa, 0x7b, 0x29, 0, 0x1, 0, 0x9, 
+	0, 0, 0, 0x74, 0x72, 0x75, 0x65, 0x66, 0x61, 0x6c, 
+	0x73, 0x65, 0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 0, 
+	0x9, 0, 0, 0, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 
+	0x6e, 0x32, 0x64, 0xa, 0, 0x5, 0, 0x63, 0xae, 0x85, 
+	0x48, 0xe8, 0x78, 0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 0x33, 
+	0x35, 0x94, 0xa3, 0x1, 0, 0x7, 0, 0, 0, 0x42, 
+	0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x1, 0, 0x1, 0, 
+	0, 0, 0x75, 0x14, 0, 0x1, 0, 0x7, 0, 0, 
+	0, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x1, 0, 
+	0x1, 0, 0, 0, 0x76, 0x14, 0, 0xb, 0, 0x1f, 
+	0, 0x1, 0, 0xc, 0, 0, 0, 0x4d, 0x61, 0x74, 
+	0x65, 0x72, 0x69, 0x61, 0x6c, 0x57, 0x72, 0x61, 0x70, 0xa, 
+	0, 0x5, 0, 0x60, 0xae, 0x85, 0x48, 0xe8, 0x78, 0xcf, 
+	0x11, 0x8f, 0x52, 0, 0x40, 0x33, 0x35, 0x94, 0xa3, 0x1, 
+	0, 0x7, 0, 0, 0, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 
+	0x61, 0x6e, 0x1, 0, 0x1, 0, 0, 0, 0x75, 0x14, 
+	0, 0x1, 0, 0x7, 0, 0, 0, 0x42, 0x6f, 0x6f, 
+	0x6c, 0x65, 0x61, 0x6e, 0x1, 0, 0x1, 0, 0, 0, 
+	0x76, 0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 0, 0xf, 
+	0, 0, 0, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 
+	0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0, 
+	0x5, 0, 0xe1, 0x90, 0x27, 0xa4, 0x10, 0x78, 0xcf, 0x11, 
+	0x8f, 0x52, 0, 0x40, 0x33, 0x35, 0x94, 0xa3, 0x31, 0, 
+	0x1, 0, 0x8, 0, 0, 0, 0x66, 0x69, 0x6c, 0x65, 
+	0x6e, 0x61, 0x6d, 0x65, 0x14, 0, 0xb, 0, 0x1f, 0, 
+	0x1, 0, 0x8, 0, 0, 0, 0x4d, 0x61, 0x74, 0x65, 
+	0x72, 0x69, 0x61, 0x6c, 0xa, 0, 0x5, 0, 0x4d, 0xab, 
+	0x82, 0x3d, 0xda, 0x62, 0xcf, 0x11, 0xab, 0x39, 0, 0x20, 
+	0xaf, 0x71, 0xe4, 0x33, 0x1, 0, 0x9, 0, 0, 0, 
+	0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x47, 0x42, 0x41, 0x1, 
+	0, 0x9, 0, 0, 0, 0x66, 0x61, 0x63, 0x65, 0x43, 
+	0x6f, 0x6c, 0x6f, 0x72, 0x14, 0, 0x2a, 0, 0x1, 0, 
+	0x5, 0, 0, 0, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x14, 
+	0, 0x1, 0, 0x8, 0, 0, 0, 0x43, 0x6f, 0x6c, 
+	0x6f, 0x72, 0x52, 0x47, 0x42, 0x1, 0, 0xd, 0, 0, 
+	0, 0x73, 0x70, 0x65, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x43, 
+	0x6f, 0x6c, 0x6f, 0x72, 0x14, 0, 0x1, 0, 0x8, 0, 
+	0, 0, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x47, 0x42, 
+	0x1, 0, 0xd, 0, 0, 0, 0x65, 0x6d, 0x69, 0x73, 
+	0x73, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x14, 
+	0, 0xe, 0, 0x12, 0, 0x12, 0, 0x12, 0, 0xf, 
+	0, 0xb, 0, 0x1f, 0, 0x1, 0, 0x8, 0, 0, 
+	0, 0x4d, 0x65, 0x73, 0x68, 0x46, 0x61, 0x63, 0x65, 0xa, 
+	0, 0x5, 0, 0x5f, 0xab, 0x82, 0x3d, 0xda, 0x62, 0xcf, 
+	0x11, 0xab, 0x39, 0, 0x20, 0xaf, 0x71, 0xe4, 0x33, 0x29, 
+	0, 0x1, 0, 0x12, 0, 0, 0, 0x6e, 0x46, 0x61, 
+	0x63, 0x65, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x49, 0x6e, 
+	0x64, 0x69, 0x63, 0x65, 0x73, 0x14, 0, 0x34, 0, 0x29, 
+	0, 0x1, 0, 0x11, 0, 0, 0, 0x66, 0x61, 0x63, 
+	0x65, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x49, 0x6e, 0x64, 
+	0x69, 0x63, 0x65, 0x73, 0xe, 0, 0x1, 0, 0x12, 0, 
+	0, 0, 0x6e, 0x46, 0x61, 0x63, 0x65, 0x56, 0x65, 0x72, 
+	0x74, 0x65, 0x78, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 
+	0xf, 0, 0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 0, 
+	0xd, 0, 0, 0, 0x4d, 0x65, 0x73, 0x68, 0x46, 0x61, 
+	0x63, 0x65, 0x57, 0x72, 0x61, 0x70, 0x73, 0xa, 0, 0x5, 
+	0, 0xc0, 0xc5, 0x1e, 0xed, 0xa8, 0xc0, 0xd0, 0x11, 0x94, 
+	0x1c, 0, 0x80, 0xc8, 0xc, 0xfa, 0x7b, 0x29, 0, 0x1, 
+	0, 0xf, 0, 0, 0, 0x6e, 0x46, 0x61, 0x63, 0x65, 
+	0x57, 0x72, 0x61, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 
+	0x14, 0, 0x34, 0, 0x1, 0, 0x9, 0, 0, 0, 
+	0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x32, 0x64, 0x1, 
+	0, 0xe, 0, 0, 0, 0x66, 0x61, 0x63, 0x65, 0x57, 
+	0x72, 0x61, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0xe, 
+	0, 0x1, 0, 0xf, 0, 0, 0, 0x6e, 0x46, 0x61, 
+	0x63, 0x65, 0x57, 0x72, 0x61, 0x70, 0x56, 0x61, 0x6c, 0x75, 
+	0x65, 0x73, 0xf, 0, 0x14, 0, 0xb, 0, 0x1f, 0, 
+	0x1, 0, 0x11, 0, 0, 0, 0x4d, 0x65, 0x73, 0x68, 
+	0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6f, 
+	0x72, 0x64, 0x73, 0xa, 0, 0x5, 0, 0x40, 0x3f, 0xf2, 
+	0xf6, 0x86, 0x76, 0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 0x33, 
+	0x35, 0x94, 0xa3, 0x29, 0, 0x1, 0, 0xe, 0, 0, 
+	0, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x43, 
+	0x6f, 0x6f, 0x72, 0x64, 0x73, 0x14, 0, 0x34, 0, 0x1, 
+	0, 0x8, 0, 0, 0, 0x43, 0x6f, 0x6f, 0x72, 0x64, 
+	0x73, 0x32, 0x64, 0x1, 0, 0xd, 0, 0, 0, 0x74, 
+	0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6f, 0x72, 
+	0x64, 0x73, 0xe, 0, 0x1, 0, 0xe, 0, 0, 0, 
+	0x6e, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 
+	0x6f, 0x72, 0x64, 0x73, 0xf, 0, 0x14, 0, 0xb, 0, 
+	0x1f, 0, 0x1, 0, 0x10, 0, 0, 0, 0x4d, 0x65, 
+	0x73, 0x68, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 
+	0x4c, 0x69, 0x73, 0x74, 0xa, 0, 0x5, 0, 0x42, 0x3f, 
+	0xf2, 0xf6, 0x86, 0x76, 0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 
+	0x33, 0x35, 0x94, 0xa3, 0x29, 0, 0x1, 0, 0xa, 0, 
+	0, 0, 0x6e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 
+	0x6c, 0x73, 0x14, 0, 0x29, 0, 0x1, 0, 0xc, 0, 
+	0, 0, 0x6e, 0x46, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x64, 
+	0x65, 0x78, 0x65, 0x73, 0x14, 0, 0x34, 0, 0x29, 0, 
+	0x1, 0, 0xb, 0, 0, 0, 0x66, 0x61, 0x63, 0x65, 
+	0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0xe, 0, 0x1, 
+	0, 0xc, 0, 0, 0, 0x6e, 0x46, 0x61, 0x63, 0x65, 
+	0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0xf, 0, 0x14, 
+	0, 0xe, 0, 0x1, 0, 0x8, 0, 0, 0, 0x4d, 
+	0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0xf, 0, 0xb, 
+	0, 0x1f, 0, 0x1, 0, 0xb, 0, 0, 0, 0x4d, 
+	0x65, 0x73, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 
+	0xa, 0, 0x5, 0, 0x43, 0x3f, 0xf2, 0xf6, 0x86, 0x76, 
+	0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 0x33, 0x35, 0x94, 0xa3, 
+	0x29, 0, 0x1, 0, 0x8, 0, 0, 0, 0x6e, 0x4e, 
+	0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 0x14, 0, 0x34, 0, 
+	0x1, 0, 0x6, 0, 0, 0, 0x56, 0x65, 0x63, 0x74, 
+	0x6f, 0x72, 0x1, 0, 0x7, 0, 0, 0, 0x6e, 0x6f, 
+	0x72, 0x6d, 0x61, 0x6c, 0x73, 0xe, 0, 0x1, 0, 0x8, 
+	0, 0, 0, 0x6e, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 
+	0x73, 0xf, 0, 0x14, 0, 0x29, 0, 0x1, 0, 0xc, 
+	0, 0, 0, 0x6e, 0x46, 0x61, 0x63, 0x65, 0x4e, 0x6f, 
+	0x72, 0x6d, 0x61, 0x6c, 0x73, 0x14, 0, 0x34, 0, 0x1, 
+	0, 0x8, 0, 0, 0, 0x4d, 0x65, 0x73, 0x68, 0x46, 
+	0x61, 0x63, 0x65, 0x1, 0, 0xb, 0, 0, 0, 0x66, 
+	0x61, 0x63, 0x65, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 
+	0xe, 0, 0x1, 0, 0xc, 0, 0, 0, 0x6e, 0x46, 
+	0x61, 0x63, 0x65, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 
+	0xf, 0, 0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 0, 
+	0x10, 0, 0, 0, 0x4d, 0x65, 0x73, 0x68, 0x56, 0x65, 
+	0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 
+	0xa, 0, 0x5, 0, 0x21, 0xb8, 0x30, 0x16, 0x42, 0x78, 
+	0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 0x33, 0x35, 0x94, 0xa3, 
+	0x29, 0, 0x1, 0, 0xd, 0, 0, 0, 0x6e, 0x56, 
+	0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 
+	0x73, 0x14, 0, 0x34, 0, 0x1, 0, 0xc, 0, 0, 
+	0, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 
+	0x6c, 0x6f, 0x72, 0x1, 0, 0xc, 0, 0, 0, 0x76, 
+	0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 
+	0x73, 0xe, 0, 0x1, 0, 0xd, 0, 0, 0, 0x6e, 
+	0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 
+	0x72, 0x73, 0xf, 0, 0x14, 0, 0xb, 0, 0x1f, 0, 
+	0x1, 0, 0x4, 0, 0, 0, 0x4d, 0x65, 0x73, 0x68, 
+	0xa, 0, 0x5, 0, 0x44, 0xab, 0x82, 0x3d, 0xda, 0x62, 
+	0xcf, 0x11, 0xab, 0x39, 0, 0x20, 0xaf, 0x71, 0xe4, 0x33, 
+	0x29, 0, 0x1, 0, 0x9, 0, 0, 0, 0x6e, 0x56, 
+	0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x14, 0, 0x34, 
+	0, 0x1, 0, 0x6, 0, 0, 0, 0x56, 0x65, 0x63, 
+	0x74, 0x6f, 0x72, 0x1, 0, 0x8, 0, 0, 0, 0x76, 
+	0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0xe, 0, 0x1, 
+	0, 0x9, 0, 0, 0, 0x6e, 0x56, 0x65, 0x72, 0x74, 
+	0x69, 0x63, 0x65, 0x73, 0xf, 0, 0x14, 0, 0x29, 0, 
+	0x1, 0, 0x6, 0, 0, 0, 0x6e, 0x46, 0x61, 0x63, 
+	0x65, 0x73, 0x14, 0, 0x34, 0, 0x1, 0, 0x8, 0, 
+	0, 0, 0x4d, 0x65, 0x73, 0x68, 0x46, 0x61, 0x63, 0x65, 
+	0x1, 0, 0x5, 0, 0, 0, 0x66, 0x61, 0x63, 0x65, 
+	0x73, 0xe, 0, 0x1, 0, 0x6, 0, 0, 0, 0x6e, 
+	0x46, 0x61, 0x63, 0x65, 0x73, 0xf, 0, 0x14, 0, 0xe, 
+	0, 0x12, 0, 0x12, 0, 0x12, 0, 0xf, 0, 0xb, 
+	0, 0x1f, 0, 0x1, 0, 0x14, 0, 0, 0, 0x46, 
+	0x72, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 
+	0x6f, 0x72, 0x6d, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0xa, 
+	0, 0x5, 0, 0x41, 0x3f, 0xf2, 0xf6, 0x86, 0x76, 0xcf, 
+	0x11, 0x8f, 0x52, 0, 0x40, 0x33, 0x35, 0x94, 0xa3, 0x1, 
+	0, 0x9, 0, 0, 0, 0x4d, 0x61, 0x74, 0x72, 0x69, 
+	0x78, 0x34, 0x78, 0x34, 0x1, 0, 0xb, 0, 0, 0, 
+	0x66, 0x72, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 
+	0x78, 0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 0, 0x5, 
+	0, 0, 0, 0x46, 0x72, 0x61, 0x6d, 0x65, 0xa, 0, 
+	0x5, 0, 0x46, 0xab, 0x82, 0x3d, 0xda, 0x62, 0xcf, 0x11, 
+	0xab, 0x39, 0, 0x20, 0xaf, 0x71, 0xe4, 0x33, 0xe, 0, 
+	0x12, 0, 0x12, 0, 0x12, 0, 0xf, 0, 0xb, 0, 
+	0x1f, 0, 0x1, 0, 0x9, 0, 0, 0, 0x46, 0x6c, 
+	0x6f, 0x61, 0x74, 0x4b, 0x65, 0x79, 0x73, 0xa, 0, 0x5, 
+	0, 0xa9, 0x46, 0xdd, 0x10, 0x5b, 0x77, 0xcf, 0x11, 0x8f, 
+	0x52, 0, 0x40, 0x33, 0x35, 0x94, 0xa3, 0x29, 0, 0x1, 
+	0, 0x7, 0, 0, 0, 0x6e, 0x56, 0x61, 0x6c, 0x75, 
+	0x65, 0x73, 0x14, 0, 0x34, 0, 0x2a, 0, 0x1, 0, 
+	0x6, 0, 0, 0, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 
+	0xe, 0, 0x1, 0, 0x7, 0, 0, 0, 0x6e, 0x56, 
+	0x61, 0x6c, 0x75, 0x65, 0x73, 0xf, 0, 0x14, 0, 0xb, 
+	0, 0x1f, 0, 0x1, 0, 0xe, 0, 0, 0, 0x54, 
+	0x69, 0x6d, 0x65, 0x64, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x4b, 
+	0x65, 0x79, 0x73, 0xa, 0, 0x5, 0, 0x80, 0xb1, 0x6, 
+	0xf4, 0x3b, 0x7b, 0xcf, 0x11, 0x8f, 0x52, 0, 0x40, 0x33, 
+	0x35, 0x94, 0xa3, 0x29, 0, 0x1, 0, 0x4, 0, 0, 
+	0, 0x74, 0x69, 0x6d, 0x65, 0x14, 0, 0x1, 0, 0x9, 
+	0, 0, 0, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x4b, 0x65, 
+	0x79, 0x73, 0x1, 0, 0x6, 0, 0, 0, 0x74, 0x66, 
+	0x6b, 0x65, 0x79, 0x73, 0x14, 0, 0xb, 0, 0x1f, 0, 
+	0x1, 0, 0xc, 0, 0, 0, 0x41, 0x6e, 0x69, 0x6d, 
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0xa, 0, 
+	0x5, 0, 0xa8, 0x46, 0xdd, 0x10, 0x5b, 0x77, 0xcf, 0x11, 
+	0x8f, 0x52, 0, 0x40, 0x33, 0x35, 0x94, 0xa3, 0x29, 0, 
+	0x1, 0, 0x7, 0, 0, 0, 0x6b, 0x65, 0x79, 0x54, 
+	0x79, 0x70, 0x65, 0x14, 0, 0x29, 0, 0x1, 0, 0x5, 
+	0, 0, 0, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x14, 0, 
+	0x34, 0, 0x1, 0, 0xe, 0, 0, 0, 0x54, 0x69, 
+	0x6d, 0x65, 0x64, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x4b, 0x65, 
+	0x79, 0x73, 0x1, 0, 0x4, 0, 0, 0, 0x6b, 0x65, 
+	0x79, 0x73, 0xe, 0, 0x1, 0, 0x5, 0, 0, 0, 
+	0x6e, 0x4b, 0x65, 0x79, 0x73, 0xf, 0, 0x14, 0, 0xb, 
+	0, 0x1f, 0, 0x1, 0, 0x10, 0, 0, 0, 0x41, 
+	0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 
+	0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa, 0, 0x5, 0, 0xc0, 
+	0x56, 0xbf, 0xe2, 0xf, 0x84, 0xcf, 0x11, 0x8f, 0x52, 0, 
+	0x40, 0x33, 0x35, 0x94, 0xa3, 0x29, 0, 0x1, 0, 0xa, 
+	0, 0, 0, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 
+	0x73, 0x65, 0x64, 0x14, 0, 0x29, 0, 0x1, 0, 0xf, 
+	0, 0, 0, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 
+	0x6e, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x14, 0, 
+	0xb, 0, 0x1f, 0, 0x1, 0, 0x9, 0, 0, 0, 
+	0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xa, 
+	0, 0x5, 0, 0x4f, 0xab, 0x82, 0x3d, 0xda, 0x62, 0xcf, 
+	0x11, 0xab, 0x39, 0, 0x20, 0xaf, 0x71, 0xe4, 0x33, 0xe, 
+	0, 0x12, 0, 0x12, 0, 0x12, 0, 0xf, 0, 0xb, 
+	0, 0x1f, 0, 0x1, 0, 0xc, 0, 0, 0, 0x41, 
+	0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 
+	0x74, 0xa, 0, 0x5, 0, 0x50, 0xab, 0x82, 0x3d, 0xda, 
+	0x62, 0xcf, 0x11, 0xab, 0x39, 0, 0x20, 0xaf, 0x71, 0xe4, 
+	0x33, 0xe, 0, 0x1, 0, 0x9, 0, 0, 0, 0x41, 
+	0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xf, 0, 
+	0xb, 0, 0x1f, 0, 0x1, 0, 0xa, 0, 0, 0, 
+	0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x61, 0x74, 0x61, 
+	0xa, 0, 0x5, 0, 0xa0, 0xee, 0x23, 0x3a, 0xb1, 0x94, 
+	0xd0, 0x11, 0xab, 0x39, 0, 0x20, 0xaf, 0x71, 0xe4, 0x33, 
+	0xe, 0, 0x1, 0, 0x6, 0, 0, 0, 0x42, 0x49, 
+	0x4e, 0x41, 0x52, 0x59, 0xf, 0, 0xb, 0, 0x1f, 0, 
+	0x1, 0, 0x3, 0, 0, 0, 0x55, 0x72, 0x6c, 0xa, 
+	0, 0x5, 0, 0xa1, 0xee, 0x23, 0x3a, 0xb1, 0x94, 0xd0, 
+	0x11, 0xab, 0x39, 0, 0x20, 0xaf, 0x71, 0xe4, 0x33, 0x29, 
+	0, 0x1, 0, 0x5, 0, 0, 0, 0x6e, 0x55, 0x72, 
+	0x6c, 0x73, 0x14, 0, 0x34, 0, 0x31, 0, 0x1, 0, 
+	0x4, 0, 0, 0, 0x75, 0x72, 0x6c, 0x73, 0xe, 0, 
+	0x1, 0, 0x5, 0, 0, 0, 0x6e, 0x55, 0x72, 0x6c, 
+	0x73, 0xf, 0, 0x14, 0, 0xb, 0, 0x1f, 0, 0x1, 
+	0, 0xf, 0, 0, 0, 0x50, 0x72, 0x6f, 0x67, 0x72, 
+	0x65, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x65, 0x73, 0x68, 
+	0xa, 0, 0x5, 0, 0x60, 0xc3, 0x63, 0x8a, 0x7d, 0x99, 
+	0xd0, 0x11, 0x94, 0x1c, 0, 0x80, 0xc8, 0xc, 0xfa, 0x7b, 
+	0xe, 0, 0x1, 0, 0x3, 0, 0, 0, 0x55, 0x72, 
+	0x6c, 0x13, 0, 0x1, 0, 0xa, 0, 0, 0, 0x49, 
+	0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x61, 0x74, 0x61, 0xf, 
+	0, 0xb, 0, 0x1f, 0, 0x1, 0, 0x4, 0, 0, 
+	0, 0x47, 0x75, 0x69, 0x64, 0xa, 0, 0x5, 0, 0xe0, 
+	0x90, 0x27, 0xa4, 0x10, 0x78, 0xcf, 0x11, 0x8f, 0x52, 0, 
+	0x40, 0x33, 0x35, 0x94, 0xa3, 0x29, 0, 0x1, 0, 0x5, 
+	0, 0, 0, 0x64, 0x61, 0x74, 0x61, 0x31, 0x14, 0, 
+	0x28, 0, 0x1, 0, 0x5, 0, 0, 0, 0x64, 0x61, 
+	0x74, 0x61, 0x32, 0x14, 0, 0x28, 0, 0x1, 0, 0x5, 
+	0, 0, 0, 0x64, 0x61, 0x74, 0x61, 0x33, 0x14, 0, 
+	0x34, 0, 0x2d, 0, 0x1, 0, 0x5, 0, 0, 0, 
+	0x64, 0x61, 0x74, 0x61, 0x34, 0xe, 0, 0x3, 0, 0x8, 
+	0, 0, 0, 0xf, 0, 0x14, 0, 0xb, 0, 0x1f, 
+	0, 0x1, 0, 0xe, 0, 0, 0, 0x53, 0x74, 0x72, 
+	0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 
+	0x79, 0xa, 0, 0x5, 0, 0xe0, 0x21, 0xf, 0x7f, 0xe1, 
+	0xbf, 0xd1, 0x11, 0x82, 0xc0, 0, 0xa0, 0xc9, 0x69, 0x72, 
+	0x71, 0x31, 0, 0x1, 0, 0x3, 0, 0, 0, 0x6b, 
+	0x65, 0x79, 0x14, 0, 0x31, 0, 0x1, 0, 0x5, 0, 
+	0, 0, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x14, 0, 0xb, 
+	0, 0x1f, 0, 0x1, 0, 0xb, 0, 0, 0, 0x50, 
+	0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x42, 0x61, 0x67, 
+	0xa, 0, 0x5, 0, 0xe1, 0x21, 0xf, 0x7f, 0xe1, 0xbf, 
+	0xd1, 0x11, 0x82, 0xc0, 0, 0xa0, 0xc9, 0x69, 0x72, 0x71, 
+	0xe, 0, 0x1, 0, 0xe, 0, 0, 0, 0x53, 0x74, 
+	0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 
+	0x74, 0x79, 0xf, 0, 0xb, 0, 0x1f, 0, 0x1, 0, 
+	0xe, 0, 0, 0, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 
+	0x61, 0x6c, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6c, 0xa, 0, 
+	0x5, 0, 0xa0, 0x6a, 0x11, 0x98, 0xba, 0xbd, 0xd1, 0x11, 
+	0x82, 0xc0, 0, 0xa0, 0xc9, 0x69, 0x72, 0x71, 0x1, 0, 
+	0x4, 0, 0, 0, 0x47, 0x75, 0x69, 0x64, 0x1, 0, 
+	0x12, 0, 0, 0, 0x67, 0x75, 0x69, 0x64, 0x45, 0x78, 
+	0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x56, 0x69, 0x73, 0x75, 
+	0x61, 0x6c, 0x14, 0, 0xe, 0, 0x12, 0, 0x12, 0, 
+	0x12, 0, 0xf, 0, 0xb, 0, 0x1f, 0, 0x1, 0, 
+	0xb, 0, 0, 0, 0x52, 0x69, 0x67, 0x68, 0x74, 0x48, 
+	0x61, 0x6e, 0x64, 0x65, 0x64, 0xa, 0, 0x5, 0, 0xa0, 
+	0x5e, 0x5d, 0x7f, 0x3a, 0xd5, 0xd1, 0x11, 0x82, 0xc0, 0, 
+	0xa0, 0xc9, 0x69, 0x72, 0x71, 0x29, 0, 0x1, 0, 0xc, 
+	0, 0, 0, 0x62, 0x52, 0x69, 0x67, 0x68, 0x74, 0x48, 
+	0x61, 0x6e, 0x64, 0x65, 0x64, 0x14, 0, 0xb, 0
+};
+
+#define D3DRM_XTEMPLATE_BYTES 3278
+
+#endif /* _RMXFTMPL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/legacy_dx/strsafe.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,6611 @@
+/******************************************************************
+*                                                                 *
+*  strsafe.h -- This module defines safer C library string        *
+*               routine replacements. These are meant to make C   *
+*               a bit more safe in reference to security and      *
+*               robustness                                        *
+*                                                                 *
+*  Copyright (c) Microsoft Corp.  All rights reserved.            *
+*                                                                 *
+******************************************************************/
+#ifndef _STRSAFE_H_INCLUDED_
+#define _STRSAFE_H_INCLUDED_
+#pragma once
+
+#include <stdio.h>      // for _vsnprintf, _vsnwprintf, getc, getwc
+#include <string.h>     // for memset
+#include <stdarg.h>     // for va_start, etc.
+
+
+#ifndef _SIZE_T_DEFINED
+#ifdef  _WIN64
+typedef unsigned __int64    size_t;
+#else
+typedef __w64 unsigned int  size_t;
+#endif  // !_WIN64
+#define _SIZE_T_DEFINED
+#endif  // !_SIZE_T_DEFINED
+
+#if !defined(_WCHAR_T_DEFINED) && !defined(_NATIVE_WCHAR_T_DEFINED)
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+#ifndef _HRESULT_DEFINED
+#define _HRESULT_DEFINED
+typedef long HRESULT;
+#endif // !_HRESULT_DEFINED
+
+#ifndef SUCCEEDED
+#define SUCCEEDED(hr)  ((HRESULT)(hr) >= 0)
+#endif
+
+#ifndef FAILED
+#define FAILED(hr)  ((HRESULT)(hr) < 0)
+#endif
+
+#ifndef S_OK
+#define S_OK  ((HRESULT)0x00000000L)
+#endif
+
+#ifdef __cplusplus
+#define _STRSAFE_EXTERN_C    extern "C"
+#else
+#define _STRSAFE_EXTERN_C    extern
+#endif
+
+// If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then
+// #define STRSAFE_LIB before including this header file.
+#if defined(STRSAFE_LIB)
+#define STRSAFEAPI  _STRSAFE_EXTERN_C HRESULT __stdcall
+#pragma comment(lib, "strsafe.lib")
+#elif defined(STRSAFE_LIB_IMPL)
+#define STRSAFEAPI  _STRSAFE_EXTERN_C HRESULT __stdcall
+#else
+#define STRSAFEAPI  __inline HRESULT __stdcall
+#define STRSAFE_INLINE
+#endif
+
+// Some functions always run inline because they use stdin and we want to avoid building multiple
+// versions of strsafe lib depending on if you use msvcrt, libcmt, etc.
+#define STRSAFE_INLINE_API  __inline HRESULT __stdcall
+
+// The user can request no "Cb" or no "Cch" fuctions, but not both!
+#if defined(STRSAFE_NO_CB_FUNCTIONS) && defined(STRSAFE_NO_CCH_FUNCTIONS)
+#error cannot specify both STRSAFE_NO_CB_FUNCTIONS and STRSAFE_NO_CCH_FUNCTIONS !!
+#endif
+
+// This should only be defined when we are building strsafe.lib
+#ifdef STRSAFE_LIB_IMPL
+#define STRSAFE_INLINE
+#endif
+
+
+// If both strsafe.h and ntstrsafe.h are included, only use definitions from one.
+#ifndef _NTSTRSAFE_H_INCLUDED_
+
+#define STRSAFE_MAX_CCH  2147483647 // max # of characters we support (same as INT_MAX)
+
+// Flags for controling the Ex functions
+//
+//      STRSAFE_FILL_BYTE(0xFF)     0x000000FF  // bottom byte specifies fill pattern
+#define STRSAFE_IGNORE_NULLS        0x00000100  // treat null as TEXT("") -- don't fault on NULL buffers
+#define STRSAFE_FILL_BEHIND_NULL    0x00000200  // fill in extra space behind the null terminator
+#define STRSAFE_FILL_ON_FAILURE     0x00000400  // on failure, overwrite pszDest with fill pattern and null terminate it
+#define STRSAFE_NULL_ON_FAILURE     0x00000800  // on failure, set *pszDest = TEXT('\0')
+#define STRSAFE_NO_TRUNCATION       0x00001000  // instead of returning a truncated result, copy/append nothing to pszDest and null terminate it
+
+#define STRSAFE_VALID_FLAGS         (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)
+
+// helper macro to set the fill character and specify buffer filling
+#define STRSAFE_FILL_BYTE(x)        ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL))
+#define STRSAFE_FAILURE_BYTE(x)     ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_ON_FAILURE))
+
+#define STRSAFE_GET_FILL_PATTERN(dwFlags)  ((int)(dwFlags & 0x000000FF))
+
+#endif // _NTSTRSAFE_H_INCLUDED_
+
+// STRSAFE error return codes
+//
+#define STRSAFE_E_INSUFFICIENT_BUFFER       ((HRESULT)0x8007007AL)  // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER
+#define STRSAFE_E_INVALID_PARAMETER         ((HRESULT)0x80070057L)  // 0x57 =  87L = ERROR_INVALID_PARAMETER
+#define STRSAFE_E_END_OF_FILE               ((HRESULT)0x80070026L)  // 0x26 =  38L = ERROR_HANDLE_EOF
+
+// prototypes for the worker functions
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc);
+STRSAFEAPI StringCopyWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc);
+STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCopyExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc);
+STRSAFEAPI StringCopyNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc);
+STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCopyNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc);
+STRSAFEAPI StringCatWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc);
+STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCatExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend);
+STRSAFEAPI StringCatNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend);
+STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCatNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList);
+STRSAFEAPI StringVPrintfWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList);
+STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
+STRSAFEAPI StringVPrintfExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList);
+STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch);
+STRSAFEAPI StringLengthWorkerW(const wchar_t* psz, size_t cchMax, size_t* pcch);
+#endif  // STRSAFE_INLINE
+
+#ifndef STRSAFE_LIB_IMPL
+// these functions are always inline
+STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFE_INLINE_API StringGetsExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+#endif
+
+#ifdef _NTSTRSAFE_H_INCLUDED_
+#pragma warning(push)
+#pragma warning(disable : 4995)
+#endif // _NTSTRSAFE_H_INCLUDED_
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchCopy(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cchDest,
+    IN  LPCTSTR pszSrc
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strcpy'.
+    The size of the destination buffer (in characters) is a parameter and
+    this function will not write past the end of this buffer and it will
+    ALWAYS null terminate the destination buffer (unless it is zero length).
+
+    This routine is not a replacement for strncpy.  That function will pad the
+    destination string with extra null termination characters if the count is
+    greater than the length of the source string, and it will fail to null
+    terminate the destination string if the source string length is greater
+    than or equal to the count. You can not blindly use this instead of strncpy:
+    it is common for code to use it to "patch" strings and you would introduce
+    errors if the code started null terminating in the middle of the string.
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string was copied without truncation and null terminated,
+    otherwise it will return a failure code. In failure cases as much of
+    pszSrc will be copied to pszDest as possible, and pszDest will be null
+    terminated.
+
+Arguments:
+
+    pszDest        -   destination string
+
+    cchDest        -   size of destination buffer in characters.
+                       length must be = (_tcslen(src) + 1) to hold all of the
+                       source including the null terminator
+
+    pszSrc         -   source string which must be null terminated
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL. See StringCchCopyEx if you require
+    the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all copied and the
+                       resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the copy
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc);
+STRSAFEAPI StringCchCopyW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc);
+#ifdef UNICODE
+#define StringCchCopy  StringCchCopyW
+#else
+#define StringCchCopy  StringCchCopyA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyWorkerA(pszDest, cchDest, pszSrc);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchCopyW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyWorkerW(pszDest, cchDest, pszSrc);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbCopy(
+    OUT LPTSTR pszDest,
+    IN  size_t cbDest,
+    IN  LPCTSTR pszSrc
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strcpy'.
+    The size of the destination buffer (in bytes) is a parameter and this
+    function will not write past the end of this buffer and it will ALWAYS
+    null terminate the destination buffer (unless it is zero length).
+
+    This routine is not a replacement for strncpy.  That function will pad the
+    destination string with extra null termination characters if the count is
+    greater than the length of the source string, and it will fail to null
+    terminate the destination string if the source string length is greater
+    than or equal to the count. You can not blindly use this instead of strncpy:
+    it is common for code to use it to "patch" strings and you would introduce
+    errors if the code started null terminating in the middle of the string.
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string was copied without truncation and null terminated,
+    otherwise it will return a failure code. In failure cases as much of pszSrc
+    will be copied to pszDest as possible, and pszDest will be null terminated.
+
+Arguments:
+
+    pszDest        -   destination string
+
+    cbDest         -   size of destination buffer in bytes.
+                       length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to
+                       hold all of the source including the null terminator
+
+    pszSrc         -   source string which must be null terminated
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL.  See StringCbCopyEx if you require
+    the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all copied and the
+                       resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the copy
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc);
+STRSAFEAPI StringCbCopyW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc);
+#ifdef UNICODE
+#define StringCbCopy  StringCbCopyW
+#else
+#define StringCbCopy  StringCbCopyA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    // convert to count of characters
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyWorkerA(pszDest, cchDest, pszSrc);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbCopyW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    // convert to count of characters
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyWorkerW(pszDest, cchDest, pszSrc);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchCopyEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cchDest,
+    IN  LPCTSTR pszSrc          OPTIONAL,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcchRemaining   OPTIONAL,
+    IN  DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strcpy' with
+    some additional parameters.  In addition to functionality provided by
+    StringCchCopy, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cchDest         -   size of destination buffer in characters.
+                        length must be = (_tcslen(pszSrc) + 1) to hold all of
+                        the source including the null terminator
+
+    pszSrc          -   source string which must be null terminated
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function copied any data, the result will point to the
+                        null termination character
+
+    pcchRemaining   -   if pcchRemaining is non-null, the function will return the
+                        number of characters left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT("")).
+                    this flag is useful for emulating functions like lstrcpy
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any truncated
+                    string returned when the failure is
+                    STRSAFE_E_INSUFFICIENT_BUFFER
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any truncated string
+                    returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
+    is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
+    may be NULL.  An error may still be returned even though NULLS are ignored
+    due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all copied and the
+                       resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the copy
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCchCopyExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCchCopyEx  StringCchCopyExW
+#else
+#define StringCchCopyEx  StringCchCopyExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
+        cbDest = cchDest * sizeof(char);
+
+        hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchCopyExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        cbDest = cchDest * sizeof(wchar_t);
+
+        hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbCopyEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cbDest,
+    IN  LPCTSTR pszSrc          OPTIONAL,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcbRemaining    OPTIONAL,
+    IN  DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strcpy' with
+    some additional parameters.  In addition to functionality provided by
+    StringCbCopy, this routine also returns a pointer to the end of the
+    destination string and the number of bytes left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cbDest          -   size of destination buffer in bytes.
+                        length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to
+                        hold all of the source including the null terminator
+
+    pszSrc          -   source string which must be null terminated
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function copied any data, the result will point to the
+                        null termination character
+
+    pcbRemaining    -   pcbRemaining is non-null,the function will return the
+                        number of bytes left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT("")).
+                    this flag is useful for emulating functions like lstrcpy
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any truncated
+                    string returned when the failure is
+                    STRSAFE_E_INSUFFICIENT_BUFFER
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any truncated string
+                    returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
+    is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
+    may be NULL.  An error may still be returned even though NULLS are ignored
+    due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all copied and the
+                       resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the copy
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCbCopyExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCbCopyEx  StringCbCopyExW
+#else
+#define StringCbCopyEx  StringCbCopyExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
+            *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbCopyExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+            *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchCopyN(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cchDest,
+    IN  LPCTSTR pszSrc,
+    IN  size_t  cchSrc
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strncpy'.
+    The size of the destination buffer (in characters) is a parameter and
+    this function will not write past the end of this buffer and it will
+    ALWAYS null terminate the destination buffer (unless it is zero length).
+
+    This routine is meant as a replacement for strncpy, but it does behave
+    differently. This function will not pad the destination buffer with extra
+    null termination characters if cchSrc is greater than the length of pszSrc.
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the entire string or the first cchSrc characters were copied
+    without truncation and the resultant destination string was null terminated,
+    otherwise it will return a failure code. In failure cases as much of pszSrc
+    will be copied to pszDest as possible, and pszDest will be null terminated.
+
+Arguments:
+
+    pszDest        -   destination string
+
+    cchDest        -   size of destination buffer in characters.
+                       length must be = (_tcslen(src) + 1) to hold all of the
+                       source including the null terminator
+
+    pszSrc         -   source string
+
+    cchSrc         -   maximum number of characters to copy from source string,
+                       not including the null terminator.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL. See StringCchCopyNEx if you require
+    the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all copied and the
+                       resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the copy
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc);
+STRSAFEAPI StringCchCopyNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc);
+#ifdef UNICODE
+#define StringCchCopyN  StringCchCopyNW
+#else
+#define StringCchCopyN  StringCchCopyNA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc)
+{
+    HRESULT hr;
+
+    if ((cchDest > STRSAFE_MAX_CCH) ||
+        (cchSrc > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchCopyNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc)
+{
+    HRESULT hr;
+
+    if ((cchDest > STRSAFE_MAX_CCH) ||
+        (cchSrc > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbCopyN(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cbDest,
+    IN  LPCTSTR pszSrc,
+    IN  size_t  cbSrc
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strncpy'.
+    The size of the destination buffer (in bytes) is a parameter and this
+    function will not write past the end of this buffer and it will ALWAYS
+    null terminate the destination buffer (unless it is zero length).
+
+    This routine is meant as a replacement for strncpy, but it does behave
+    differently. This function will not pad the destination buffer with extra
+    null termination characters if cbSrc is greater than the size of pszSrc.
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the entire string or the first cbSrc characters were
+    copied without truncation and the resultant destination string was null
+    terminated, otherwise it will return a failure code. In failure cases as
+    much of pszSrc will be copied to pszDest as possible, and pszDest will be
+    null terminated.
+
+Arguments:
+
+    pszDest        -   destination string
+
+    cbDest         -   size of destination buffer in bytes.
+                       length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to
+                       hold all of the source including the null terminator
+
+    pszSrc         -   source string
+
+    cbSrc          -   maximum number of bytes to copy from source string,
+                       not including the null terminator.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL.  See StringCbCopyEx if you require
+    the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all copied and the
+                       resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the copy
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc);
+STRSAFEAPI StringCbCopyNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc);
+#ifdef UNICODE
+#define StringCbCopyN  StringCbCopyNW
+#else
+#define StringCbCopyN  StringCbCopyNA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchSrc;
+
+    // convert to count of characters
+    cchDest = cbDest / sizeof(char);
+    cchSrc = cbSrc / sizeof(char);
+
+    if ((cchDest > STRSAFE_MAX_CCH) ||
+        (cchSrc > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbCopyNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchSrc;
+
+    // convert to count of characters
+    cchDest = cbDest / sizeof(wchar_t);
+    cchSrc = cbSrc / sizeof(wchar_t);
+
+    if ((cchDest > STRSAFE_MAX_CCH) ||
+        (cchSrc > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchCopyNEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cchDest,
+    IN  LPCTSTR pszSrc          OPTIONAL,
+    IN  size_t  cchSrc,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcchRemaining   OPTIONAL,
+    IN  DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strncpy' with
+    some additional parameters.  In addition to functionality provided by
+    StringCchCopyN, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination
+    string including the null terminator. The flags parameter allows
+    additional controls.
+
+    This routine is meant as a replacement for strncpy, but it does behave
+    differently. This function will not pad the destination buffer with extra
+    null termination characters if cchSrc is greater than the length of pszSrc.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cchDest         -   size of destination buffer in characters.
+                        length must be = (_tcslen(pszSrc) + 1) to hold all of
+                        the source including the null terminator
+
+    pszSrc          -   source string
+
+    cchSrc          -   maximum number of characters to copy from the source
+                        string
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function copied any data, the result will point to the
+                        null termination character
+
+    pcchRemaining   -   if pcchRemaining is non-null, the function will return the
+                        number of characters left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT("")).
+                    this flag is useful for emulating functions like lstrcpy
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any truncated
+                    string returned when the failure is
+                    STRSAFE_E_INSUFFICIENT_BUFFER
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any truncated string
+                    returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
+    is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
+    may be NULL. An error may still be returned even though NULLS are ignored
+    due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all copied and the
+                       resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the copy
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCchCopyNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCchCopyNEx  StringCchCopyNExW
+#else
+#define StringCchCopyNEx  StringCchCopyNExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if ((cchDest > STRSAFE_MAX_CCH) ||
+        (cchSrc > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
+        cbDest = cchDest * sizeof(char);
+
+        hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchCopyNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if ((cchDest > STRSAFE_MAX_CCH) ||
+        (cchSrc > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        cbDest = cchDest * sizeof(wchar_t);
+
+        hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbCopyNEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cbDest,
+    IN  LPCTSTR pszSrc          OPTIONAL,
+    IN  size_t  cbSrc,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcbRemaining    OPTIONAL,
+    IN  DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strncpy' with
+    some additional parameters.  In addition to functionality provided by
+    StringCbCopyN, this routine also returns a pointer to the end of the
+    destination string and the number of bytes left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+    This routine is meant as a replacement for strncpy, but it does behave
+    differently. This function will not pad the destination buffer with extra
+    null termination characters if cbSrc is greater than the size of pszSrc.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cbDest          -   size of destination buffer in bytes.
+                        length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to
+                        hold all of the source including the null terminator
+
+    pszSrc          -   source string
+
+    cbSrc           -   maximum number of bytes to copy from source string
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function copied any data, the result will point to the
+                        null termination character
+
+    pcbRemaining    -   pcbRemaining is non-null,the function will return the
+                        number of bytes left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT("")).
+                    this flag is useful for emulating functions like lstrcpy
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any truncated
+                    string returned when the failure is
+                    STRSAFE_E_INSUFFICIENT_BUFFER
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any truncated string
+                    returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
+    is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
+    may be NULL.  An error may still be returned even though NULLS are ignored
+    due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all copied and the
+                       resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the copy
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCbCopyNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCbCopyNEx  StringCbCopyNExW
+#else
+#define StringCbCopyNEx  StringCbCopyNExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchSrc;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(char);
+    cchSrc = cbSrc / sizeof(char);
+
+    if ((cchDest > STRSAFE_MAX_CCH) ||
+        (cchSrc > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
+            *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbCopyNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchSrc;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(wchar_t);
+    cchSrc = cbSrc / sizeof(wchar_t);
+
+    if ((cchDest > STRSAFE_MAX_CCH) ||
+        (cchSrc > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+            *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchCat(
+    IN OUT LPTSTR  pszDest,
+    IN     size_t  cchDest,
+    IN     LPCTSTR pszSrc
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strcat'.
+    The size of the destination buffer (in characters) is a parameter and this
+    function will not write past the end of this buffer and it will ALWAYS
+    null terminate the destination buffer (unless it is zero length).
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string was concatenated without truncation and null terminated,
+    otherwise it will return a failure code. In failure cases as much of pszSrc
+    will be appended to pszDest as possible, and pszDest will be null
+    terminated.
+
+Arguments:
+
+    pszDest     -  destination string which must be null terminated
+
+    cchDest     -  size of destination buffer in characters.
+                   length must be = (_tcslen(pszDest) + _tcslen(pszSrc) + 1)
+                   to hold all of the combine string plus the null
+                   terminator
+
+    pszSrc      -  source string which must be null terminated
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL.  See StringCchCatEx if you require
+    the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all concatenated and
+                       the resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the operation
+                       failed due to insufficient space. When this error occurs,
+                       the destination buffer is modified to contain a truncated
+                       version of the ideal result and is null terminated. This
+                       is useful for situations where truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc);
+STRSAFEAPI StringCchCatW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc);
+#ifdef UNICODE
+#define StringCchCat  StringCchCatW
+#else
+#define StringCchCat  StringCchCatA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCatWorkerA(pszDest, cchDest, pszSrc);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchCatW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCatWorkerW(pszDest, cchDest, pszSrc);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbCat(
+    IN OUT LPTSTR  pszDest,
+    IN     size_t  cbDest,
+    IN     LPCTSTR pszSrc
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strcat'.
+    The size of the destination buffer (in bytes) is a parameter and this
+    function will not write past the end of this buffer and it will ALWAYS
+    null terminate the destination buffer (unless it is zero length).
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string was concatenated without truncation and null terminated,
+    otherwise it will return a failure code. In failure cases as much of pszSrc
+    will be appended to pszDest as possible, and pszDest will be null
+    terminated.
+
+Arguments:
+
+    pszDest     -  destination string which must be null terminated
+
+    cbDest      -  size of destination buffer in bytes.
+                   length must be = ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR)
+                   to hold all of the combine string plus the null
+                   terminator
+
+    pszSrc      -  source string which must be null terminated
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL.  See StringCbCatEx if you require
+    the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all concatenated and
+                       the resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the operation
+                       failed due to insufficient space. When this error occurs,
+                       the destination buffer is modified to contain a truncated
+                       version of the ideal result and is null terminated. This
+                       is useful for situations where truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc);
+STRSAFEAPI StringCbCatW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc);
+#ifdef UNICODE
+#define StringCbCat  StringCbCatW
+#else
+#define StringCbCat  StringCbCatA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCatWorkerA(pszDest, cchDest, pszSrc);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbCatW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCatWorkerW(pszDest, cchDest, pszSrc);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchCatEx(
+    IN OUT LPTSTR  pszDest         OPTIONAL,
+    IN     size_t  cchDest,
+    IN     LPCTSTR pszSrc          OPTIONAL,
+    OUT    LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT    size_t* pcchRemaining   OPTIONAL,
+    IN     DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strcat' with
+    some additional parameters.  In addition to functionality provided by
+    StringCchCat, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string which must be null terminated
+
+    cchDest         -   size of destination buffer in characters
+                        length must be (_tcslen(pszDest) + _tcslen(pszSrc) + 1)
+                        to hold all of the combine string plus the null
+                        terminator.
+
+    pszSrc          -   source string which must be null terminated
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function appended any data, the result will point to the
+                        null termination character
+
+    pcchRemaining   -   if pcchRemaining is non-null, the function will return the
+                        number of characters left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT("")).
+                    this flag is useful for emulating functions like lstrcat
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any pre-existing
+                    or truncated string
+
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any pre-existing or
+                    truncated string
+
+        STRSAFE_NO_TRUNCATION
+                    if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
+                    will not contain a truncated string, it will remain unchanged.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
+    is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
+    may be NULL.  An error may still be returned even though NULLS are ignored
+    due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all concatenated and
+                       the resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the operation
+                       failed due to insufficient space. When this error
+                       occurs, the destination buffer is modified to contain
+                       a truncated version of the ideal result and is null
+                       terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCchCatExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCchCatEx  StringCchCatExW
+#else
+#define StringCchCatEx  StringCchCatExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
+        cbDest = cchDest * sizeof(char);
+
+        hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchCatExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        cbDest = cchDest * sizeof(wchar_t);
+
+        hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbCatEx(
+    IN OUT LPTSTR  pszDest         OPTIONAL,
+    IN     size_t  cbDest,
+    IN     LPCTSTR pszSrc          OPTIONAL,
+    OUT    LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT    size_t* pcbRemaining    OPTIONAL,
+    IN     DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strcat' with
+    some additional parameters.  In addition to functionality provided by
+    StringCbCat, this routine also returns a pointer to the end of the
+    destination string and the number of bytes left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string which must be null terminated
+
+    cbDest          -   size of destination buffer in bytes.
+                        length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR)
+                        to hold all of the combine string plus the null
+                        terminator.
+
+    pszSrc          -   source string which must be null terminated
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function appended any data, the result will point to the
+                        null termination character
+
+    pcbRemaining    -   if pcbRemaining is non-null, the function will return
+                        the number of bytes left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT("")).
+                    this flag is useful for emulating functions like lstrcat
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any pre-existing
+                    or truncated string
+
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any pre-existing or
+                    truncated string
+
+        STRSAFE_NO_TRUNCATION
+                    if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
+                    will not contain a truncated string, it will remain unchanged.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
+    is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
+    may be NULL.  An error may still be returned even though NULLS are ignored
+    due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all concatenated
+                       and the resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the operation
+                       failed due to insufficient space. When this error
+                       occurs, the destination buffer is modified to contain
+                       a truncated version of the ideal result and is null
+                       terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCbCatExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCbCatEx  StringCbCatExW
+#else
+#define StringCbCatEx  StringCbCatExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
+            *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbCatExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+            *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchCatN(
+    IN OUT LPTSTR  pszDest,
+    IN     size_t  cchDest,
+    IN     LPCTSTR pszSrc,
+    IN     size_t  cchMaxAppend
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strncat'.
+    The size of the destination buffer (in characters) is a parameter as well as
+    the maximum number of characters to append, excluding the null terminator.
+    This function will not write past the end of the destination buffer and it will
+    ALWAYS null terminate pszDest (unless it is zero length).
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if all of pszSrc or the first cchMaxAppend characters were appended
+    to the destination string and it was null terminated, otherwise it will
+    return a failure code. In failure cases as much of pszSrc will be appended
+    to pszDest as possible, and pszDest will be null terminated.
+
+Arguments:
+
+    pszDest         -   destination string which must be null terminated
+
+    cchDest         -   size of destination buffer in characters.
+                        length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1)
+                        to hold all of the combine string plus the null
+                        terminator.
+
+    pszSrc          -   source string
+
+    cchMaxAppend    -   maximum number of characters to append
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL. See StringCchCatNEx if you require
+    the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if all of pszSrc or the first cchMaxAppend characters
+                       were concatenated to pszDest and the resultant dest
+                       string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the operation
+                       failed due to insufficient space. When this error
+                       occurs, the destination buffer is modified to contain
+                       a truncated version of the ideal result and is null
+                       terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend);
+STRSAFEAPI StringCchCatNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend);
+#ifdef UNICODE
+#define StringCchCatN  StringCchCatNW
+#else
+#define StringCchCatN  StringCchCatNA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchCatNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbCatN(
+    IN OUT LPTSTR  pszDest,
+    IN     size_t  cbDest,
+    IN     LPCTSTR pszSrc,
+    IN     size_t  cbMaxAppend
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strncat'.
+    The size of the destination buffer (in bytes) is a parameter as well as
+    the maximum number of bytes to append, excluding the null terminator.
+    This function will not write past the end of the destination buffer and it will
+    ALWAYS null terminate pszDest (unless it is zero length).
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if all of pszSrc or the first cbMaxAppend bytes were appended
+    to the destination string and it was null terminated, otherwise it will
+    return a failure code. In failure cases as much of pszSrc will be appended
+    to pszDest as possible, and pszDest will be null terminated.
+
+Arguments:
+
+    pszDest         -   destination string which must be null terminated
+
+    cbDest          -   size of destination buffer in bytes.
+                        length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR)
+                        to hold all of the combine string plus the null
+                        terminator.
+
+    pszSrc          -   source string
+
+    cbMaxAppend     -   maximum number of bytes to append
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL. See StringCbCatNEx if you require
+    the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if all of pszSrc or the first cbMaxAppend bytes were
+                       concatenated to pszDest and the resultant dest string
+                       was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the operation
+                       failed due to insufficient space. When this error
+                       occurs, the destination buffer is modified to contain
+                       a truncated version of the ideal result and is null
+                       terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend);
+STRSAFEAPI StringCbCatNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend);
+#ifdef UNICODE
+#define StringCbCatN  StringCbCatNW
+#else
+#define StringCbCatN  StringCbCatNA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cchMaxAppend;
+
+        cchMaxAppend = cbMaxAppend / sizeof(char);
+
+        hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbCatNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cchMaxAppend;
+
+        cchMaxAppend = cbMaxAppend / sizeof(wchar_t);
+
+        hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchCatNEx(
+    IN OUT LPTSTR  pszDest         OPTIONAL,
+    IN     size_t  cchDest,
+    IN     LPCTSTR pszSrc          OPTIONAL,
+    IN     size_t  cchMaxAppend,
+    OUT    LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT    size_t* pcchRemaining   OPTIONAL,
+    IN     DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strncat', with
+    some additional parameters.  In addition to functionality provided by
+    StringCchCatN, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string which must be null terminated
+
+    cchDest         -   size of destination buffer in characters.
+                        length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1)
+                        to hold all of the combine string plus the null
+                        terminator.
+
+    pszSrc          -   source string
+
+    cchMaxAppend    -   maximum number of characters to append
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function appended any data, the result will point to the
+                        null termination character
+
+    pcchRemaining   -   if pcchRemaining is non-null, the function will return the
+                        number of characters left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT(""))
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any pre-existing
+                    or truncated string
+
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any pre-existing or
+                    truncated string
+
+        STRSAFE_NO_TRUNCATION
+                    if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
+                    will not contain a truncated string, it will remain unchanged.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
+    is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
+    may be NULL.  An error may still be returned even though NULLS are ignored
+    due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if all of pszSrc or the first cchMaxAppend characters
+                       were concatenated to pszDest and the resultant dest
+                       string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the operation
+                       failed due to insufficient space. When this error
+                       occurs, the destination buffer is modified to contain
+                       a truncated version of the ideal result and is null
+                       terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCchCatNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCchCatNEx  StringCchCatNExW
+#else
+#define StringCchCatNEx  StringCchCatNExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
+        cbDest = cchDest * sizeof(char);
+
+        hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchCatNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        cbDest = cchDest * sizeof(wchar_t);
+
+        hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbCatNEx(
+    IN OUT LPTSTR  pszDest         OPTIONAL,
+    IN     size_t  cbDest,
+    IN     LPCTSTR pszSrc          OPTIONAL,
+    IN     size_t  cbMaxAppend,
+    OUT    LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT    size_t* pcchRemaining   OPTIONAL,
+    IN     DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strncat', with
+    some additional parameters.  In addition to functionality provided by
+    StringCbCatN, this routine also returns a pointer to the end of the
+    destination string and the number of bytes left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string which must be null terminated
+
+    cbDest          -   size of destination buffer in bytes.
+                        length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR)
+                        to hold all of the combine string plus the null
+                        terminator.
+
+    pszSrc          -   source string
+
+    cbMaxAppend     -   maximum number of bytes to append
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function appended any data, the result will point to the
+                        null termination character
+
+    pcbRemaining    -   if pcbRemaining is non-null, the function will return the
+                        number of bytes left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT(""))
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any pre-existing
+                    or truncated string
+
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any pre-existing or
+                    truncated string
+
+        STRSAFE_NO_TRUNCATION
+                    if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
+                    will not contain a truncated string, it will remain unchanged.
+
+Notes:
+    Behavior is undefined if source and destination strings overlap.
+
+    pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
+    is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
+    may be NULL.  An error may still be returned even though NULLS are ignored
+    due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if all of pszSrc or the first cbMaxAppend bytes were
+                       concatenated to pszDest and the resultant dest string
+                       was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the operation
+                       failed due to insufficient space. When this error
+                       occurs, the destination buffer is modified to contain
+                       a truncated version of the ideal result and is null
+                       terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+STRSAFEAPI StringCbCatNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCbCatNEx  StringCbCatNExW
+#else
+#define StringCbCatNEx  StringCbCatNExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cchMaxAppend;
+
+        cchMaxAppend = cbMaxAppend / sizeof(char);
+
+        hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
+            *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbCatNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cchMaxAppend;
+
+        cchMaxAppend = cbMaxAppend / sizeof(wchar_t);
+
+        hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+            *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchVPrintf(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cchDest,
+    IN  LPCTSTR pszFormat,
+    IN  va_list argList
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'vsprintf'.
+    The size of the destination buffer (in characters) is a parameter and
+    this function will not write past the end of this buffer and it will
+    ALWAYS null terminate the destination buffer (unless it is zero length).
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string was printed without truncation and null terminated,
+    otherwise it will return a failure code. In failure cases it will return
+    a truncated version of the ideal result.
+
+Arguments:
+
+    pszDest     -  destination string
+
+    cchDest     -  size of destination buffer in characters
+                   length must be sufficient to hold the resulting formatted
+                   string, including the null terminator.
+
+    pszFormat   -  format string which must be null terminated
+
+    argList     -  va_list from the variable arguments according to the
+                   stdarg.h convention
+
+Notes:
+    Behavior is undefined if destination, format strings or any arguments
+    strings overlap.
+
+    pszDest and pszFormat should not be NULL.  See StringCchVPrintfEx if you
+    require the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if there was sufficient space in the dest buffer for
+                       the resultant string and it was null terminated.
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the print
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList);
+STRSAFEAPI StringCchVPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList);
+#ifdef UNICODE
+#define StringCchVPrintf  StringCchVPrintfW
+#else
+#define StringCchVPrintf  StringCchVPrintfA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchVPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbVPrintf(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cbDest,
+    IN  LPCTSTR pszFormat,
+    IN  va_list argList
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'vsprintf'.
+    The size of the destination buffer (in bytes) is a parameter and
+    this function will not write past the end of this buffer and it will
+    ALWAYS null terminate the destination buffer (unless it is zero length).
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string was printed without truncation and null terminated,
+    otherwise it will return a failure code. In failure cases it will return
+    a truncated version of the ideal result.
+
+Arguments:
+
+    pszDest     -  destination string
+
+    cbDest      -  size of destination buffer in bytes
+                   length must be sufficient to hold the resulting formatted
+                   string, including the null terminator.
+
+    pszFormat   -  format string which must be null terminated
+
+    argList     -  va_list from the variable arguments according to the
+                   stdarg.h convention
+
+Notes:
+    Behavior is undefined if destination, format strings or any arguments
+    strings overlap.
+
+    pszDest and pszFormat should not be NULL.  See StringCbVPrintfEx if you
+    require the handling of NULL values.
+
+
+Return Value:
+
+    S_OK           -   if there was sufficient space in the dest buffer for
+                       the resultant string and it was null terminated.
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the print
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList);
+STRSAFEAPI StringCbVPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, va_list argList);
+#ifdef UNICODE
+#define StringCbVPrintf  StringCbVPrintfW
+#else
+#define StringCbVPrintf  StringCbVPrintfA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbVPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, va_list argList)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchPrintf(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cchDest,
+    IN  LPCTSTR pszFormat,
+    ...
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'sprintf'.
+    The size of the destination buffer (in characters) is a parameter and
+    this function will not write past the end of this buffer and it will
+    ALWAYS null terminate the destination buffer (unless it is zero length).
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string was printed without truncation and null terminated,
+    otherwise it will return a failure code. In failure cases it will return
+    a truncated version of the ideal result.
+
+Arguments:
+
+    pszDest     -  destination string
+
+    cchDest     -  size of destination buffer in characters
+                   length must be sufficient to hold the resulting formatted
+                   string, including the null terminator.
+
+    pszFormat   -  format string which must be null terminated
+
+    ...         -  additional parameters to be formatted according to
+                   the format string
+
+Notes:
+    Behavior is undefined if destination, format strings or any arguments
+    strings overlap.
+
+    pszDest and pszFormat should not be NULL.  See StringCchPrintfEx if you
+    require the handling of NULL values.
+
+Return Value:
+
+    S_OK           -   if there was sufficient space in the dest buffer for
+                       the resultant string and it was null terminated.
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the print
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...);
+STRSAFEAPI StringCchPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, ...);
+#ifdef UNICODE
+#define StringCchPrintf  StringCchPrintfW
+#else
+#define StringCchPrintf  StringCchPrintfA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        va_list argList;
+
+        va_start(argList, pszFormat);
+
+        hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
+
+        va_end(argList);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, ...)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        va_list argList;
+
+        va_start(argList, pszFormat);
+
+        hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
+
+        va_end(argList);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbPrintf(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cbDest,
+    IN  LPCTSTR pszFormat,
+    ...
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'sprintf'.
+    The size of the destination buffer (in bytes) is a parameter and
+    this function will not write past the end of this buffer and it will
+    ALWAYS null terminate the destination buffer (unless it is zero length).
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string was printed without truncation and null terminated,
+    otherwise it will return a failure code. In failure cases it will return
+    a truncated version of the ideal result.
+
+Arguments:
+
+    pszDest     -  destination string
+
+    cbDest      -  size of destination buffer in bytes
+                   length must be sufficient to hold the resulting formatted
+                   string, including the null terminator.
+
+    pszFormat   -  format string which must be null terminated
+
+    ...         -  additional parameters to be formatted according to
+                   the format string
+
+Notes:
+    Behavior is undefined if destination, format strings or any arguments
+    strings overlap.
+
+    pszDest and pszFormat should not be NULL.  See StringCbPrintfEx if you
+    require the handling of NULL values.
+
+
+Return Value:
+
+    S_OK           -   if there was sufficient space in the dest buffer for
+                       the resultant string and it was null terminated.
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the print
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...);
+STRSAFEAPI StringCbPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, ...);
+#ifdef UNICODE
+#define StringCbPrintf  StringCbPrintfW
+#else
+#define StringCbPrintf  StringCbPrintfA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        va_list argList;
+
+        va_start(argList, pszFormat);
+
+        hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
+
+        va_end(argList);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, ...)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        va_list argList;
+
+        va_start(argList, pszFormat);
+
+        hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
+
+        va_end(argList);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchPrintfEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cchDest,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcchRemaining   OPTIONAL,
+    IN  DWORD   dwFlags,
+    IN  LPCTSTR pszFormat       OPTIONAL,
+    ...
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'sprintf' with
+    some additional parameters.  In addition to functionality provided by
+    StringCchPrintf, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cchDest         -   size of destination buffer in characters.
+                        length must be sufficient to contain the resulting
+                        formatted string plus the null terminator.
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function printed any data, the result will point to the
+                        null termination character
+
+    pcchRemaining   -   if pcchRemaining is non-null, the function will return
+                        the number of characters left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT(""))
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any truncated
+                    string returned when the failure is
+                    STRSAFE_E_INSUFFICIENT_BUFFER
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any truncated string
+                    returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
+
+    pszFormat       -   format string which must be null terminated
+
+    ...             -   additional parameters to be formatted according to
+                        the format string
+
+Notes:
+    Behavior is undefined if destination, format strings or any arguments
+    strings overlap.
+
+    pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
+    flag is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and
+    pszFormat may be NULL.  An error may still be returned even though NULLS
+    are ignored due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all concatenated and
+                       the resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the print
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...);
+STRSAFEAPI StringCchPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...);
+#ifdef UNICODE
+#define StringCchPrintfEx  StringCchPrintfExW
+#else
+#define StringCchPrintfEx  StringCchPrintfExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+        va_list argList;
+
+        // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
+        cbDest = cchDest * sizeof(char);
+        va_start(argList, pszFormat);
+
+        hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
+
+        va_end(argList);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+        va_list argList;
+
+        // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        cbDest = cchDest * sizeof(wchar_t);
+        va_start(argList, pszFormat);
+
+        hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
+
+        va_end(argList);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbPrintfEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cbDest,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcbRemaining    OPTIONAL,
+    IN  DWORD   dwFlags,
+    IN  LPCTSTR pszFormat       OPTIONAL,
+    ...
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'sprintf' with
+    some additional parameters.  In addition to functionality provided by
+    StringCbPrintf, this routine also returns a pointer to the end of the
+    destination string and the number of bytes left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cbDest          -   size of destination buffer in bytes.
+                        length must be sufficient to contain the resulting
+                        formatted string plus the null terminator.
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function printed any data, the result will point to the
+                        null termination character
+
+    pcbRemaining    -   if pcbRemaining is non-null, the function will return
+                        the number of bytes left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT(""))
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any truncated
+                    string returned when the failure is
+                    STRSAFE_E_INSUFFICIENT_BUFFER
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any truncated string
+                    returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
+
+    pszFormat       -   format string which must be null terminated
+
+    ...             -   additional parameters to be formatted according to
+                        the format string
+
+Notes:
+    Behavior is undefined if destination, format strings or any arguments
+    strings overlap.
+
+    pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
+    flag is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and
+    pszFormat may be NULL.  An error may still be returned even though NULLS
+    are ignored due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all concatenated and
+                       the resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the print
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...);
+STRSAFEAPI StringCbPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...);
+#ifdef UNICODE
+#define StringCbPrintfEx  StringCbPrintfExW
+#else
+#define StringCbPrintfEx  StringCbPrintfExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        va_list argList;
+
+        va_start(argList, pszFormat);
+
+        hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
+
+        va_end(argList);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
+            *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        va_list argList;
+
+        va_start(argList, pszFormat);
+
+        hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
+
+        va_end(argList);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+            *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchVPrintfEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cchDest,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcchRemaining   OPTIONAL,
+    IN  DWORD   dwFlags,
+    IN  LPCTSTR pszFormat       OPTIONAL,
+    IN  va_list argList
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'vsprintf' with
+    some additional parameters.  In addition to functionality provided by
+    StringCchVPrintf, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cchDest         -   size of destination buffer in characters.
+                        length must be sufficient to contain the resulting
+                        formatted string plus the null terminator.
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function printed any data, the result will point to the
+                        null termination character
+
+    pcchRemaining   -   if pcchRemaining is non-null, the function will return
+                        the number of characters left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT(""))
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any truncated
+                    string returned when the failure is
+                    STRSAFE_E_INSUFFICIENT_BUFFER
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any truncated string
+                    returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
+
+    pszFormat       -   format string which must be null terminated
+
+    argList         -   va_list from the variable arguments according to the
+                        stdarg.h convention
+
+Notes:
+    Behavior is undefined if destination, format strings or any arguments
+    strings overlap.
+
+    pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
+    flag is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and
+    pszFormat may be NULL.  An error may still be returned even though NULLS
+    are ignored due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all concatenated and
+                       the resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the print
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
+STRSAFEAPI StringCchVPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList);
+#ifdef UNICODE
+#define StringCchVPrintfEx  StringCchVPrintfExW
+#else
+#define StringCchVPrintfEx  StringCchVPrintfExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
+        cbDest = cchDest * sizeof(char);
+
+        hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchVPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        cbDest = cchDest * sizeof(wchar_t);
+
+        hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbVPrintfEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cbDest,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcbRemaining    OPTIONAL,
+    IN  DWORD   dwFlags,
+    IN  LPCTSTR pszFormat       OPTIONAL,
+    IN  va_list argList
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'vsprintf' with
+    some additional parameters.  In addition to functionality provided by
+    StringCbVPrintf, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cbDest          -   size of destination buffer in bytes.
+                        length must be sufficient to contain the resulting
+                        formatted string plus the null terminator.
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return
+                        a pointer to the end of the destination string.  If the
+                        function printed any data, the result will point to the
+                        null termination character
+
+    pcbRemaining    -   if pcbRemaining is non-null, the function will return
+                        the number of bytes left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT(""))
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated. This will overwrite any truncated
+                    string returned when the failure is
+                    STRSAFE_E_INSUFFICIENT_BUFFER
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string. This will overwrite any truncated string
+                    returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
+
+    pszFormat       -   format string which must be null terminated
+
+    argList         -   va_list from the variable arguments according to the
+                        stdarg.h convention
+
+Notes:
+    Behavior is undefined if destination, format strings or any arguments
+    strings overlap.
+
+    pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
+    flag is specified.  If STRSAFE_IGNORE_NULLS is passed, both pszDest and
+    pszFormat may be NULL.  An error may still be returned even though NULLS
+    are ignored due to insufficient space.
+
+Return Value:
+
+    S_OK           -   if there was source data and it was all concatenated and
+                       the resultant dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that the print
+                       operation failed due to insufficient space. When this
+                       error occurs, the destination buffer is modified to
+                       contain a truncated version of the ideal result and is
+                       null terminated. This is useful for situations where
+                       truncation is ok.
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function
+
+--*/
+
+STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
+STRSAFEAPI StringCbVPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList);
+#ifdef UNICODE
+#define StringCbVPrintfEx  StringCbVPrintfExW
+#else
+#define StringCbVPrintfEx  StringCbVPrintfExA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
+            *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbVPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+            *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchGets(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cchDest
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'gets'.
+    The size of the destination buffer (in characters) is a parameter and
+    this function will not write past the end of this buffer and it will
+    ALWAYS null terminate the destination buffer (unless it is zero length).
+
+    This routine is not a replacement for fgets.  That function does not replace
+    newline characters with a null terminator.
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if any characters were read from stdin and copied to pszDest and
+    pszDest was null terminated, otherwise it will return a failure code.
+
+Arguments:
+
+    pszDest     -   destination string
+
+    cchDest     -   size of destination buffer in characters.
+
+Notes:
+    pszDest should not be NULL. See StringCchGetsEx if you require the handling
+    of NULL values.
+
+    cchDest must be > 1 for this function to succeed.
+
+Return Value:
+
+    S_OK           -   data was read from stdin and copied, and the resultant
+                       dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_END_OF_FILE /
+      HRESULT_CODE(hr) == ERROR_HANDLE_EOF
+                   -   this return value indicates an error or end-of-file
+                       condition, use feof or ferror to determine which one has
+                       occured.
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that there was
+                       insufficient space in the destination buffer to copy any
+                       data
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+#ifndef STRSAFE_LIB_IMPL
+STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest);
+STRSAFE_INLINE_API StringCchGetsW(wchar_t* pszDest, size_t cchDest);
+#ifdef UNICODE
+#define StringCchGets  StringCchGetsW
+#else
+#define StringCchGets  StringCchGetsA
+#endif // !UNICODE
+
+STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
+        cbDest = cchDest * sizeof(char);
+
+        hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0);
+    }
+
+    return hr;
+}
+
+STRSAFE_INLINE_API StringCchGetsW(wchar_t* pszDest, size_t cchDest)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        cbDest = cchDest * sizeof(wchar_t);
+
+        hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, NULL, NULL, 0);
+    }
+
+    return hr;
+}
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+#endif  // !STRSAFE_LIB_IMPL
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbGets(
+    OUT LPTSTR  pszDest,
+    IN  size_t  cbDest
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'gets'.
+    The size of the destination buffer (in bytes) is a parameter and
+    this function will not write past the end of this buffer and it will
+    ALWAYS null terminate the destination buffer (unless it is zero length).
+
+    This routine is not a replacement for fgets.  That function does not replace
+    newline characters with a null terminator.
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if any characters were read from stdin and copied to pszDest
+    and pszDest was null terminated, otherwise it will return a failure code.
+
+Arguments:
+
+    pszDest     -   destination string
+
+    cbDest      -   size of destination buffer in bytes.
+
+Notes:
+    pszDest should not be NULL. See StringCbGetsEx if you require the handling
+    of NULL values.
+
+    cbDest must be > sizeof(TCHAR) for this function to succeed.
+
+Return Value:
+
+    S_OK           -   data was read from stdin and copied, and the resultant
+                       dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_END_OF_FILE /
+      HRESULT_CODE(hr) == ERROR_HANDLE_EOF
+                   -   this return value indicates an error or end-of-file
+                       condition, use feof or ferror to determine which one has
+                       occured.
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that there was
+                       insufficient space in the destination buffer to copy any
+                       data
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+#ifndef STRSAFE_LIB_IMPL
+STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest);
+STRSAFE_INLINE_API StringCbGetsW(wchar_t* pszDest, size_t cbDest);
+#ifdef UNICODE
+#define StringCbGets  StringCbGetsW
+#else
+#define StringCbGets  StringCbGetsA
+#endif // !UNICODE
+
+STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    // convert to count of characters
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0);
+    }
+
+    return hr;
+}
+
+STRSAFE_INLINE_API StringCbGetsW(wchar_t* pszDest, size_t cbDest)
+{
+    HRESULT hr;
+    size_t cchDest;
+
+    // convert to count of characters
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, NULL, NULL, 0);
+    }
+
+    return hr;
+}
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+#endif  // !STRSAFE_LIB_IMPL
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchGetsEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cchDest,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcchRemaining   OPTIONAL,
+    IN  DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'gets' with
+    some additional parameters. In addition to functionality provided by
+    StringCchGets, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cchDest         -   size of destination buffer in characters.
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function copied any data, the result will point to the
+                        null termination character
+
+    pcchRemaining   -   if pcchRemaining is non-null, the function will return the
+                        number of characters left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT("")).
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated.
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string.
+
+Notes:
+    pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified.
+    If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be
+    returned even though NULLS are ignored
+
+    cchDest must be > 1 for this function to succeed.
+
+Return Value:
+
+    S_OK           -   data was read from stdin and copied, and the resultant
+                       dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_END_OF_FILE /
+      HRESULT_CODE(hr) == ERROR_HANDLE_EOF
+                   -   this return value indicates an error or end-of-file
+                       condition, use feof or ferror to determine which one has
+                       occured.
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that there was
+                       insufficient space in the destination buffer to copy any
+                       data
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+#ifndef STRSAFE_LIB_IMPL
+STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+STRSAFE_INLINE_API StringCchGetsExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCchGetsEx  StringCchGetsExW
+#else
+#define StringCchGetsEx  StringCchGetsExA
+#endif // !UNICODE
+
+STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
+        cbDest = cchDest * sizeof(char);
+
+        hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+
+STRSAFE_INLINE_API StringCchGetsExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cbDest;
+
+        // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        cbDest = cchDest * sizeof(wchar_t);
+
+        hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags);
+    }
+
+    return hr;
+}
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+#endif  // !STRSAFE_LIB_IMPL
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbGetsEx(
+    OUT LPTSTR  pszDest         OPTIONAL,
+    IN  size_t  cbDest,
+    OUT LPTSTR* ppszDestEnd     OPTIONAL,
+    OUT size_t* pcbRemaining    OPTIONAL,
+    IN  DWORD   dwFlags
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'gets' with
+    some additional parameters. In addition to functionality provided by
+    StringCbGets, this routine also returns a pointer to the end of the
+    destination string and the number of characters left in the destination string
+    including the null terminator. The flags parameter allows additional controls.
+
+Arguments:
+
+    pszDest         -   destination string
+
+    cbDest          -   size of destination buffer in bytes.
+
+    ppszDestEnd     -   if ppszDestEnd is non-null, the function will return a
+                        pointer to the end of the destination string.  If the
+                        function copied any data, the result will point to the
+                        null termination character
+
+    pcbRemaining    -   if pbRemaining is non-null, the function will return the
+                        number of bytes left in the destination string,
+                        including the null terminator
+
+    dwFlags         -   controls some details of the string copy:
+
+        STRSAFE_FILL_BEHIND_NULL
+                    if the function succeeds, the low byte of dwFlags will be
+                    used to fill the uninitialize part of destination buffer
+                    behind the null terminator
+
+        STRSAFE_IGNORE_NULLS
+                    treat NULL string pointers like empty strings (TEXT("")).
+
+        STRSAFE_FILL_ON_FAILURE
+                    if the function fails, the low byte of dwFlags will be
+                    used to fill all of the destination buffer, and it will
+                    be null terminated.
+
+        STRSAFE_NO_TRUNCATION /
+        STRSAFE_NULL_ON_FAILURE
+                    if the function fails, the destination buffer will be set
+                    to the empty string.
+
+Notes:
+    pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified.
+    If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be
+    returned even though NULLS are ignored
+
+    cbDest must be > sizeof(TCHAR) for this function to succeed
+
+Return Value:
+
+    S_OK           -   data was read from stdin and copied, and the resultant
+                       dest string was null terminated
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+      STRSAFE_E_END_OF_FILE /
+      HRESULT_CODE(hr) == ERROR_HANDLE_EOF
+                   -   this return value indicates an error or end-of-file
+                       condition, use feof or ferror to determine which one has
+                       occured.
+
+      STRSAFE_E_INSUFFICIENT_BUFFER /
+      HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
+                   -   this return value is an indication that there was
+                       insufficient space in the destination buffer to copy any
+                       data
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+#ifndef STRSAFE_LIB_IMPL
+STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pbRemaining, unsigned long dwFlags);
+STRSAFE_INLINE_API StringCbGetsExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
+#ifdef UNICODE
+#define StringCbGetsEx  StringCbGetsExW
+#else
+#define StringCbGetsEx  StringCbGetsExA
+#endif // !UNICODE
+
+STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(char);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) ||
+        (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
+        (hr == STRSAFE_E_END_OF_FILE))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
+            *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+
+    return hr;
+}
+
+STRSAFE_INLINE_API StringCbGetsExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
+{
+    HRESULT hr;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+
+    cchDest = cbDest / sizeof(wchar_t);
+
+    if (cchDest > STRSAFE_MAX_CCH)
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags);
+    }
+
+    if (SUCCEEDED(hr) ||
+        (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
+        (hr == STRSAFE_E_END_OF_FILE))
+    {
+        if (pcbRemaining)
+        {
+            // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+            *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+
+    return hr;
+}
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+#endif  // !STRSAFE_LIB_IMPL
+
+#ifndef STRSAFE_NO_CCH_FUNCTIONS
+/*++
+
+STDAPI
+StringCchLength(
+    IN  LPCTSTR psz,
+    IN  size_t  cchMax,
+    OUT size_t* pcch    OPTIONAL
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strlen'.
+    It is used to make sure a string is not larger than a given length, and
+    it optionally returns the current length in characters not including
+    the null terminator.
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string is non-null and the length including the null
+    terminator is less than or equal to cchMax characters.
+
+Arguments:
+
+    psz         -   string to check the length of
+
+    cchMax      -   maximum number of characters including the null terminator
+                    that psz is allowed to contain
+
+    pcch        -   if the function succeeds and pcch is non-null, the current length
+                    in characters of psz excluding the null terminator will be returned.
+                    This out parameter is equivalent to the return value of strlen(psz)
+
+Notes:
+    psz can be null but the function will fail
+
+    cchMax should be greater than zero or the function will fail
+
+Return Value:
+
+    S_OK           -   psz is non-null and the length including the null
+                       terminator is less than or equal to cchMax characters
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch);
+STRSAFEAPI StringCchLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch);
+#ifdef UNICODE
+#define StringCchLength  StringCchLengthW
+#else
+#define StringCchLength  StringCchLengthA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch)
+{
+    HRESULT hr;
+
+    if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringLengthWorkerA(psz, cchMax, pcch);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCchLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch)
+{
+    HRESULT hr;
+
+    if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringLengthWorkerW(psz, cchMax, pcch);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CCH_FUNCTIONS
+
+
+#ifndef STRSAFE_NO_CB_FUNCTIONS
+/*++
+
+STDAPI
+StringCbLength(
+    IN  LPCTSTR psz,
+    IN  size_t  cbMax,
+    OUT size_t* pcb     OPTIONAL
+    );
+
+Routine Description:
+
+    This routine is a safer version of the C built-in function 'strlen'.
+    It is used to make sure a string is not larger than a given length, and
+    it optionally returns the current length in bytes not including
+    the null terminator.
+
+    This function returns a hresult, and not a pointer.  It returns
+    S_OK if the string is non-null and the length including the null
+    terminator is less than or equal to cbMax bytes.
+
+Arguments:
+
+    psz         -   string to check the length of
+
+    cbMax       -   maximum number of bytes including the null terminator
+                    that psz is allowed to contain
+
+    pcb         -   if the function succeeds and pcb is non-null, the current length
+                    in bytes of psz excluding the null terminator will be returned.
+                    This out parameter is equivalent to the return value of strlen(psz) * sizeof(TCHAR)
+
+Notes:
+    psz can be null but the function will fail
+
+    cbMax should be greater than or equal to sizeof(TCHAR) or the function will fail
+
+Return Value:
+
+    S_OK           -   psz is non-null and the length including the null
+                       terminator is less than or equal to cbMax bytes
+
+    failure        -   you can use the macro HRESULT_CODE() to get a win32
+                       error code for all hresult failure cases
+
+    It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
+    return value of this function.
+
+--*/
+
+STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch);
+STRSAFEAPI StringCbLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch);
+#ifdef UNICODE
+#define StringCbLength  StringCbLengthW
+#else
+#define StringCbLength  StringCbLengthA
+#endif // !UNICODE
+
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb)
+{
+    HRESULT hr;
+    size_t cchMax;
+    size_t cch = 0;
+
+    cchMax = cbMax / sizeof(char);
+
+    if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringLengthWorkerA(psz, cchMax, &cch);
+    }
+
+    if (SUCCEEDED(hr) && pcb)
+    {
+        // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1
+        *pcb = cch * sizeof(char);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCbLengthW(const wchar_t* psz, size_t cbMax, size_t* pcb)
+{
+    HRESULT hr;
+    size_t cchMax;
+    size_t cch = 0;
+
+    cchMax = cbMax / sizeof(wchar_t);
+
+    if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        hr = StringLengthWorkerW(psz, cchMax, &cch);
+    }
+
+    if (SUCCEEDED(hr) && pcb)
+    {
+        // safe to multiply cch * sizeof(wchar_t) since cch < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2
+        *pcb = cch * sizeof(wchar_t);
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+#endif  // !STRSAFE_NO_CB_FUNCTIONS
+
+
+// these are the worker functions that actually do the work
+#ifdef STRSAFE_INLINE
+STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc)
+{
+    HRESULT hr = S_OK;
+
+    if (cchDest == 0)
+    {
+        // can not null terminate a zero-byte dest buffer
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        while (cchDest && (*pszSrc != '\0'))
+        {
+            *pszDest++ = *pszSrc++;
+            cchDest--;
+        }
+
+        if (cchDest == 0)
+        {
+            // we are going to truncate pszDest
+            pszDest--;
+            hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+        }
+
+        *pszDest= '\0';
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCopyWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc)
+{
+    HRESULT hr = S_OK;
+
+    if (cchDest == 0)
+    {
+        // can not null terminate a zero-byte dest buffer
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        while (cchDest && (*pszSrc != L'\0'))
+        {
+            *pszDest++ = *pszSrc++;
+            cchDest--;
+        }
+
+        if (cchDest == 0)
+        {
+            // we are going to truncate pszDest
+            pszDest--;
+            hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+        }
+
+        *pszDest= L'\0';
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    char* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(char))    ||
+    //        cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest != 0) || (cbDest != 0))
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+
+            if (pszSrc == NULL)
+            {
+                pszSrc = "";
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+
+                // only fail if there was actually src data to copy
+                if (*pszSrc != '\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+
+                while (cchRemaining && (*pszSrc != '\0'))
+                {
+                    *pszDestEnd++= *pszSrc++;
+                    cchRemaining--;
+                }
+
+                if (cchRemaining > 0)
+                {
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
+                    }
+                }
+                else
+                {
+                    // we are going to truncate pszDest
+                    pszDestEnd--;
+                    cchRemaining++;
+
+                    hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                }
+
+                *pszDestEnd = '\0';
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCopyExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    wchar_t* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) ||
+    //        cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest != 0) || (cbDest != 0))
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+
+            if (pszSrc == NULL)
+            {
+                pszSrc = L"";
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+
+                // only fail if there was actually src data to copy
+                if (*pszSrc != L'\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+
+                while (cchRemaining && (*pszSrc != L'\0'))
+                {
+                    *pszDestEnd++= *pszSrc++;
+                    cchRemaining--;
+                }
+
+                if (cchRemaining > 0)
+                {
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+                    }
+                }
+                else
+                {
+                    // we are going to truncate pszDest
+                    pszDestEnd--;
+                    cchRemaining++;
+
+                    hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                }
+
+                *pszDestEnd = L'\0';
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc)
+{
+    HRESULT hr = S_OK;
+
+    if (cchDest == 0)
+    {
+        // can not null terminate a zero-byte dest buffer
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        while (cchDest && cchSrc && (*pszSrc != '\0'))
+        {
+            *pszDest++= *pszSrc++;
+            cchDest--;
+            cchSrc--;
+        }
+
+        if (cchDest == 0)
+        {
+            // we are going to truncate pszDest
+            pszDest--;
+            hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+        }
+
+        *pszDest= '\0';
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCopyNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc)
+{
+    HRESULT hr = S_OK;
+
+    if (cchDest == 0)
+    {
+        // can not null terminate a zero-byte dest buffer
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        while (cchDest && cchSrc && (*pszSrc != L'\0'))
+        {
+            *pszDest++= *pszSrc++;
+            cchDest--;
+            cchSrc--;
+        }
+
+        if (cchDest == 0)
+        {
+            // we are going to truncate pszDest
+            pszDest--;
+            hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+        }
+
+        *pszDest= L'\0';
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    char* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(char))    ||
+    //        cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest != 0) || (cbDest != 0))
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+
+            if (pszSrc == NULL)
+            {
+                pszSrc = "";
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+
+                // only fail if there was actually src data to copy
+                if (*pszSrc != '\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+
+                while (cchRemaining && cchSrc && (*pszSrc != '\0'))
+                {
+                    *pszDestEnd++= *pszSrc++;
+                    cchRemaining--;
+                    cchSrc--;
+                }
+
+                if (cchRemaining > 0)
+                {
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
+                    }
+                }
+                else
+                {
+                    // we are going to truncate pszDest
+                    pszDestEnd--;
+                    cchRemaining++;
+
+                    hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                }
+
+                *pszDestEnd = '\0';
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCopyNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    wchar_t* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) ||
+    //        cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest != 0) || (cbDest != 0))
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+
+            if (pszSrc == NULL)
+            {
+                pszSrc = L"";
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+
+                // only fail if there was actually src data to copy
+                if (*pszSrc != L'\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+
+                while (cchRemaining && cchSrc && (*pszSrc != L'\0'))
+                {
+                    *pszDestEnd++= *pszSrc++;
+                    cchRemaining--;
+                    cchSrc--;
+                }
+
+                if (cchRemaining > 0)
+                {
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+                    }
+                }
+                else
+                {
+                    // we are going to truncate pszDest
+                    pszDestEnd--;
+                    cchRemaining++;
+
+                    hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                }
+
+                *pszDestEnd = L'\0';
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc)
+{
+   HRESULT hr;
+   size_t cchDestCurrent;
+
+   hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
+
+   if (SUCCEEDED(hr))
+   {
+       hr = StringCopyWorkerA(pszDest + cchDestCurrent,
+                              cchDest - cchDestCurrent,
+                              pszSrc);
+   }
+
+   return hr;
+}
+
+STRSAFEAPI StringCatWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc)
+{
+   HRESULT hr;
+   size_t cchDestCurrent;
+
+   hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
+
+   if (SUCCEEDED(hr))
+   {
+       hr = StringCopyWorkerW(pszDest + cchDestCurrent,
+                              cchDest - cchDestCurrent,
+                              pszSrc);
+   }
+
+   return hr;
+}
+
+STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    char* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(char))    ||
+    //        cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cchDestCurrent;
+
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest == 0) && (cbDest == 0))
+                {
+                    cchDestCurrent = 0;
+                }
+                else
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+            else
+            {
+                hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
+
+                if (SUCCEEDED(hr))
+                {
+                    pszDestEnd = pszDest + cchDestCurrent;
+                    cchRemaining = cchDest - cchDestCurrent;
+                }
+            }
+
+            if (pszSrc == NULL)
+            {
+                pszSrc = "";
+            }
+        }
+        else
+        {
+            hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
+
+            if (SUCCEEDED(hr))
+            {
+                pszDestEnd = pszDest + cchDestCurrent;
+                cchRemaining = cchDest - cchDestCurrent;
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                // only fail if there was actually src data to append
+                if (*pszSrc != '\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
+                // those flags through
+                hr = StringCopyExWorkerA(pszDestEnd,
+                                         cchRemaining,
+                                         (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)),
+                                         pszSrc,
+                                         &pszDestEnd,
+                                         &cchRemaining,
+                                         dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA()
+
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+
+            if (dwFlags & STRSAFE_NULL_ON_FAILURE)
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCatExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    wchar_t* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) ||
+    //        cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        size_t cchDestCurrent;
+
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest == 0) && (cbDest == 0))
+                {
+                    cchDestCurrent = 0;
+                }
+                else
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+            else
+            {
+                hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
+
+                if (SUCCEEDED(hr))
+                {
+                    pszDestEnd = pszDest + cchDestCurrent;
+                    cchRemaining = cchDest - cchDestCurrent;
+                }
+            }
+
+            if (pszSrc == NULL)
+            {
+                pszSrc = L"";
+            }
+        }
+        else
+        {
+            hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
+
+            if (SUCCEEDED(hr))
+            {
+                pszDestEnd = pszDest + cchDestCurrent;
+                cchRemaining = cchDest - cchDestCurrent;
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                // only fail if there was actually src data to append
+                if (*pszSrc != L'\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
+                // those flags through
+                hr = StringCopyExWorkerW(pszDestEnd,
+                                         cchRemaining,
+                                         (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)),
+                                         pszSrc,
+                                         &pszDestEnd,
+                                         &cchRemaining,
+                                         dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerW()
+
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+
+            if (dwFlags & STRSAFE_NULL_ON_FAILURE)
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend)
+{
+    HRESULT hr;
+    size_t cchDestCurrent;
+
+    hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
+
+    if (SUCCEEDED(hr))
+    {
+        hr = StringCopyNWorkerA(pszDest + cchDestCurrent,
+                                cchDest - cchDestCurrent,
+                                pszSrc,
+                                cchMaxAppend);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCatNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend)
+{
+    HRESULT hr;
+    size_t cchDestCurrent;
+
+    hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
+
+    if (SUCCEEDED(hr))
+    {
+        hr = StringCopyNWorkerW(pszDest + cchDestCurrent,
+                                cchDest - cchDestCurrent,
+                                pszSrc,
+                                cchMaxAppend);
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    char* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    size_t cchDestCurrent = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(char))    ||
+    //        cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest == 0) && (cbDest == 0))
+                {
+                    cchDestCurrent = 0;
+                }
+                else
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+            else
+            {
+                hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
+
+                if (SUCCEEDED(hr))
+                {
+                    pszDestEnd = pszDest + cchDestCurrent;
+                    cchRemaining = cchDest - cchDestCurrent;
+                }
+            }
+
+            if (pszSrc == NULL)
+            {
+                pszSrc = "";
+            }
+        }
+        else
+        {
+            hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
+
+            if (SUCCEEDED(hr))
+            {
+                pszDestEnd = pszDest + cchDestCurrent;
+                cchRemaining = cchDest - cchDestCurrent;
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                // only fail if there was actually src data to append
+                if (*pszSrc != '\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
+                // those flags through
+                hr = StringCopyNExWorkerA(pszDestEnd,
+                                          cchRemaining,
+                                          (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)),
+                                          pszSrc,
+                                          cchMaxAppend,
+                                          &pszDestEnd,
+                                          &cchRemaining,
+                                          dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA()
+
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringCatNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    wchar_t* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    size_t cchDestCurrent = 0;
+
+
+    // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) ||
+    //        cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest == 0) && (cbDest == 0))
+                {
+                    cchDestCurrent = 0;
+                }
+                else
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+            else
+            {
+                hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
+
+                if (SUCCEEDED(hr))
+                {
+                    pszDestEnd = pszDest + cchDestCurrent;
+                    cchRemaining = cchDest - cchDestCurrent;
+                }
+            }
+
+            if (pszSrc == NULL)
+            {
+                pszSrc = L"";
+            }
+        }
+        else
+        {
+            hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
+
+            if (SUCCEEDED(hr))
+            {
+                pszDestEnd = pszDest + cchDestCurrent;
+                cchRemaining = cchDest - cchDestCurrent;
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                // only fail if there was actually src data to append
+                if (*pszSrc != L'\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
+                // those flags through
+                hr = StringCopyNExWorkerW(pszDestEnd,
+                                          cchRemaining,
+                                          (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)),
+                                          pszSrc,
+                                          cchMaxAppend,
+                                          &pszDestEnd,
+                                          &cchRemaining,
+                                          dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerW()
+
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList)
+{
+    HRESULT hr = S_OK;
+
+    if (cchDest == 0)
+    {
+        // can not null terminate a zero-byte dest buffer
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        int iRet;
+        size_t cchMax;
+
+        // leave the last space for the null terminator
+        cchMax = cchDest - 1;
+
+        iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList);
+        // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
+
+        if ((iRet < 0) || (((size_t)iRet) > cchMax))
+        {
+            // need to null terminate the string
+            pszDest += cchMax;
+            *pszDest = '\0';
+
+            // we have truncated pszDest
+            hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+        }
+        else if (((size_t)iRet) == cchMax)
+        {
+            // need to null terminate the string
+            pszDest += cchMax;
+            *pszDest = '\0';
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringVPrintfWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList)
+{
+    HRESULT hr = S_OK;
+
+    if (cchDest == 0)
+    {
+        // can not null terminate a zero-byte dest buffer
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        int iRet;
+        size_t cchMax;
+
+        // leave the last space for the null terminator
+        cchMax = cchDest - 1;
+
+        iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
+        // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
+
+        if ((iRet < 0) || (((size_t)iRet) > cchMax))
+        {
+            // need to null terminate the string
+            pszDest += cchMax;
+            *pszDest = L'\0';
+
+            // we have truncated pszDest
+            hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+        }
+        else if (((size_t)iRet) == cchMax)
+        {
+            // need to null terminate the string
+            pszDest += cchMax;
+            *pszDest = L'\0';
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
+{
+    HRESULT hr = S_OK;
+    char* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(char))    ||
+    //        cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest != 0) || (cbDest != 0))
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+
+            if (pszFormat == NULL)
+            {
+                pszFormat = "";
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+
+                // only fail if there was actually a non-empty format string
+                if (*pszFormat != '\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                int iRet;
+                size_t cchMax;
+
+                // leave the last space for the null terminator
+                cchMax = cchDest - 1;
+
+                iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList);
+                // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
+
+                if ((iRet < 0) || (((size_t)iRet) > cchMax))
+                {
+                    // we have truncated pszDest
+                    pszDestEnd = pszDest + cchMax;
+                    cchRemaining = 1;
+
+                    // need to null terminate the string
+                    *pszDestEnd = '\0';
+
+                    hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                }
+                else if (((size_t)iRet) == cchMax)
+                {
+                    // string fit perfectly
+                    pszDestEnd = pszDest + cchMax;
+                    cchRemaining = 1;
+
+                    // need to null terminate the string
+                    *pszDestEnd = '\0';
+                }
+                else if (((size_t)iRet) < cchMax)
+                {
+                    // there is extra room
+                    pszDestEnd = pszDest + iRet;
+                    cchRemaining = cchDest - iRet;
+
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
+                    }
+                }
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringVPrintfExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList)
+{
+    HRESULT hr = S_OK;
+    wchar_t* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) ||
+    //        cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest != 0) || (cbDest != 0))
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+
+            if (pszFormat == NULL)
+            {
+                pszFormat = L"";
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest == 0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+
+                // only fail if there was actually a non-empty format string
+                if (*pszFormat != L'\0')
+                {
+                    if (pszDest == NULL)
+                    {
+                        hr = STRSAFE_E_INVALID_PARAMETER;
+                    }
+                    else
+                    {
+                        hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                    }
+                }
+            }
+            else
+            {
+                int iRet;
+                size_t cchMax;
+
+                // leave the last space for the null terminator
+                cchMax = cchDest - 1;
+
+                iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
+                // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
+
+                if ((iRet < 0) || (((size_t)iRet) > cchMax))
+                {
+                    // we have truncated pszDest
+                    pszDestEnd = pszDest + cchMax;
+                    cchRemaining = 1;
+
+                    // need to null terminate the string
+                    *pszDestEnd = L'\0';
+
+                    hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+                }
+                else if (((size_t)iRet) == cchMax)
+                {
+                    // string fit perfectly
+                    pszDestEnd = pszDest + cchMax;
+                    cchRemaining = 1;
+
+                    // need to null terminate the string
+                    *pszDestEnd = L'\0';
+                }
+                else if (((size_t)iRet) < cchMax)
+                {
+                    // there is extra room
+                    pszDestEnd = pszDest + iRet;
+                    cchRemaining = cchDest - iRet;
+
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+                    }
+                }
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch)
+{
+    HRESULT hr = S_OK;
+    size_t cchMaxPrev = cchMax;
+
+    while (cchMax && (*psz != '\0'))
+    {
+        psz++;
+        cchMax--;
+    }
+
+    if (cchMax == 0)
+    {
+        // the string is longer than cchMax
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+
+    if (SUCCEEDED(hr) && pcch)
+    {
+        *pcch = cchMaxPrev - cchMax;
+    }
+
+    return hr;
+}
+
+STRSAFEAPI StringLengthWorkerW(const wchar_t* psz, size_t cchMax, size_t* pcch)
+{
+    HRESULT hr = S_OK;
+    size_t cchMaxPrev = cchMax;
+
+    while (cchMax && (*psz != L'\0'))
+    {
+        psz++;
+        cchMax--;
+    }
+
+    if (cchMax == 0)
+    {
+        // the string is longer than cchMax
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+
+    if (SUCCEEDED(hr) && pcch)
+    {
+        *pcch = cchMaxPrev - cchMax;
+    }
+
+    return hr;
+}
+#endif  // STRSAFE_INLINE
+
+#ifndef STRSAFE_LIB_IMPL
+STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    char* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(char))    ||
+    //        cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest != 0) || (cbDest != 0))
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest <= 1)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+
+                if (cchDest == 1)
+                {
+                    *pszDestEnd = '\0';
+                }
+
+                hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+            }
+            else
+            {
+                char ch;
+
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+
+                while ((cchRemaining > 1) && (ch = (char)getc(stdin)) != '\n')
+                {
+                    if (ch == EOF)
+                    {
+                        if (pszDestEnd == pszDest)
+                        {
+                            // we failed to read anything from stdin
+                            hr = STRSAFE_E_END_OF_FILE;
+                        }
+                        break;
+                    }
+
+                    *pszDestEnd = ch;
+
+                    pszDestEnd++;
+                    cchRemaining--;
+                }
+
+                if (cchRemaining > 0)
+                {
+                    // there is extra room
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
+                    }
+                }
+
+                *pszDestEnd = '\0';
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) ||
+        (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
+        (hr == STRSAFE_E_END_OF_FILE))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+
+STRSAFE_INLINE_API StringGetsExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
+{
+    HRESULT hr = S_OK;
+    wchar_t* pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+
+    // ASSERT(cbDest == (cchDest * sizeof(char))    ||
+    //        cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
+
+    // only accept valid flags
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+    {
+        hr = STRSAFE_E_INVALID_PARAMETER;
+    }
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (pszDest == NULL)
+            {
+                if ((cchDest != 0) || (cbDest != 0))
+                {
+                    // NULL pszDest and non-zero cchDest/cbDest is invalid
+                    hr = STRSAFE_E_INVALID_PARAMETER;
+                }
+            }
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (cchDest <= 1)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+
+                if (cchDest == 1)
+                {
+                    *pszDestEnd = L'\0';
+                }
+
+                hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+            }
+            else
+            {
+                wchar_t ch;
+
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+
+                while ((cchRemaining > 1) && (ch = (wchar_t)getwc(stdin)) != L'\n')
+                {
+                    if (ch == EOF)
+                    {
+                        if (pszDestEnd == pszDest)
+                        {
+                            // we failed to read anything from stdin
+                            hr = STRSAFE_E_END_OF_FILE;
+                        }
+                        break;
+                    }
+
+                    *pszDestEnd = ch;
+
+                    pszDestEnd++;
+                    cchRemaining--;
+                }
+
+                if (cchRemaining > 0)
+                {
+                    // there is extra room
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+                    }
+                }
+
+                *pszDestEnd = L'\0';
+            }
+        }
+    }
+
+    if (FAILED(hr))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
+
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest + cchDest - 1;
+                    cchRemaining = 1;
+
+                    // null terminate the end of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+
+                    // null terminate the beginning of the string
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hr) ||
+        (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
+        (hr == STRSAFE_E_END_OF_FILE))
+    {
+        if (ppszDestEnd)
+        {
+            *ppszDestEnd = pszDestEnd;
+        }
+
+        if (pcchRemaining)
+        {
+            *pcchRemaining = cchRemaining;
+        }
+    }
+
+    return hr;
+}
+#endif  // !STRSAFE_LIB_IMPL
+
+
+// Do not call these functions, they are worker functions for internal use within this file
+#ifdef DEPRECATE_SUPPORTED
+#pragma deprecated(StringCopyWorkerA)
+#pragma deprecated(StringCopyWorkerW)
+#pragma deprecated(StringCopyExWorkerA)
+#pragma deprecated(StringCopyExWorkerW)
+#pragma deprecated(StringCatWorkerA)
+#pragma deprecated(StringCatWorkerW)
+#pragma deprecated(StringCatExWorkerA)
+#pragma deprecated(StringCatExWorkerW)
+#pragma deprecated(StringCatNWorkerA)
+#pragma deprecated(StringCatNWorkerW)
+#pragma deprecated(StringCatNExWorkerA)
+#pragma deprecated(StringCatNExWorkerW)
+#pragma deprecated(StringVPrintfWorkerA)
+#pragma deprecated(StringVPrintfWorkerW)
+#pragma deprecated(StringVPrintfExWorkerA)
+#pragma deprecated(StringVPrintfExWorkerW)
+#pragma deprecated(StringLengthWorkerA)
+#pragma deprecated(StringLengthWorkerW)
+#else
+#define StringCopyWorkerA        StringCopyWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
+#define StringCopyWorkerW        StringCopyWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
+#define StringCopyExWorkerA      StringCopyExWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
+#define StringCopyExWorkerW      StringCopyExWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
+#define StringCatWorkerA         StringCatWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
+#define StringCatWorkerW         StringCatWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
+#define StringCatExWorkerA       StringCatExWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
+#define StringCatExWorkerW       StringCatExWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
+#define StringCatNWorkerA        StringCatNWorkerA_instead_use_StringCchCatNA_or_StrincCbCatNA;
+#define StringCatNWorkerW        StringCatNWorkerW_instead_use_StringCchCatNW_or_StringCbCatNW;
+#define StringCatNExWorkerA      StringCatNExWorkerA_instead_use_StringCchCatNExA_or_StringCbCatNExA;
+#define StringCatNExWorkerW      StringCatNExWorkerW_instead_use_StringCchCatNExW_or_StringCbCatNExW;
+#define StringVPrintfWorkerA     StringVPrintfWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
+#define StringVPrintfWorkerW     StringVPrintfWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
+#define StringVPrintfExWorkerA   StringVPrintfExWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
+#define StringVPrintfExWorkerW   StringVPrintfExWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
+#define StringLengthWorkerA      StringLengthWorkerA_instead_use_StringCchLengthA_or_StringCbLengthA;
+#define StringLengthWorkerW      StringLengthWorkerW_instead_use_StringCchLengthW_or_StringCbLengthW;
+#endif // !DEPRECATE_SUPPORTED
+
+
+#ifndef STRSAFE_NO_DEPRECATE
+// Deprecate all of the unsafe functions to generate compiletime errors. If you do not want
+// this then you can #define STRSAFE_NO_DEPRECATE before including this file.
+#ifdef DEPRECATE_SUPPORTED
+
+// First all the names that are a/w variants (or shouldn't be #defined by now anyway).
+#pragma deprecated(lstrcpyA)
+#pragma deprecated(lstrcpyW)
+#pragma deprecated(lstrcatA)
+#pragma deprecated(lstrcatW)
+#pragma deprecated(wsprintfA)
+#pragma deprecated(wsprintfW)
+
+#pragma deprecated(StrCpyW)
+#pragma deprecated(StrCatW)
+#pragma deprecated(StrNCatA)
+#pragma deprecated(StrNCatW)
+#pragma deprecated(StrCatNA)
+#pragma deprecated(StrCatNW)
+#pragma deprecated(wvsprintfA)
+#pragma deprecated(wvsprintfW)
+
+#pragma deprecated(strcpy)
+#pragma deprecated(wcscpy)
+#pragma deprecated(strcat)
+#pragma deprecated(wcscat)
+#pragma deprecated(sprintf)
+#pragma deprecated(swprintf)
+#pragma deprecated(vsprintf)
+#pragma deprecated(vswprintf)
+#pragma deprecated(_snprintf)
+#pragma deprecated(_snwprintf)
+#pragma deprecated(_vsnprintf)
+#pragma deprecated(_vsnwprintf)
+#pragma deprecated(gets)
+#pragma deprecated(_getws)
+
+// Then all the windows.h names - we need to undef and redef based on UNICODE setting
+#undef lstrcpy
+#undef lstrcat
+#undef wsprintf
+#undef wvsprintf
+#pragma deprecated(lstrcpy)
+#pragma deprecated(lstrcat)
+#pragma deprecated(wsprintf)
+#pragma deprecated(wvsprintf)
+#ifdef UNICODE
+#define lstrcpy    lstrcpyW
+#define lstrcat    lstrcatW
+#define wsprintf   wsprintfW
+#define wvsprintf  wvsprintfW
+#else
+#define lstrcpy    lstrcpyA
+#define lstrcat    lstrcatA
+#define wsprintf   wsprintfA
+#define wvsprintf  wvsprintfA
+#endif
+
+// Then the shlwapi names - they key off UNICODE also.
+#undef StrCpyA
+#undef StrCpy
+#undef StrCatA
+#undef StrCat
+#undef StrNCat
+#undef StrCatN
+#pragma deprecated(StrCpyA)
+#pragma deprecated(StrCatA)
+#pragma deprecated(StrCatN)
+#pragma deprecated(StrCpy)
+#pragma deprecated(StrCat)
+#pragma deprecated(StrNCat)
+#define StrCpyA lstrcpyA
+#define StrCatA lstrcatA
+#define StrCatN StrNCat
+#ifdef UNICODE
+#define StrCpy  StrCpyW
+#define StrCat  StrCatW
+#define StrNCat StrNCatW
+#else
+#define StrCpy  lstrcpyA
+#define StrCat  lstrcatA
+#define StrNCat StrNCatA
+#endif
+
+// Then all the CRT names - we need to undef/redef based on _UNICODE value.
+#undef _tcscpy
+#undef _ftcscpy
+#undef _tcscat
+#undef _ftcscat
+#undef _stprintf
+#undef _sntprintf
+#undef _vstprintf
+#undef _vsntprintf
+#undef _getts
+#pragma deprecated(_tcscpy)
+#pragma deprecated(_ftcscpy)
+#pragma deprecated(_tcscat)
+#pragma deprecated(_ftcscat)
+#pragma deprecated(_stprintf)
+#pragma deprecated(_sntprintf)
+#pragma deprecated(_vstprintf)
+#pragma deprecated(_vsntprintf)
+#pragma deprecated(_getts)
+#ifdef _UNICODE
+#define _tcscpy     wcscpy
+#define _ftcscpy    wcscpy
+#define _tcscat     wcscat
+#define _ftcscat    wcscat
+#define _stprintf   swprintf
+#define _sntprintf  _snwprintf
+#define _vstprintf  vswprintf
+#define _vsntprintf _vsnwprintf
+#define _getts      _getws
+#else
+#define _tcscpy     strcpy
+#define _ftcscpy    strcpy
+#define _tcscat     strcat
+#define _ftcscat    strcat
+#define _stprintf   sprintf
+#define _sntprintf  _snprintf
+#define _vstprintf  vsprintf
+#define _vsntprintf _vsnprintf
+#define _getts      gets
+#endif
+
+#else // DEPRECATE_SUPPORTED
+
+#undef strcpy
+#define strcpy      strcpy_instead_use_StringCbCopyA_or_StringCchCopyA;
+
+#undef wcscpy
+#define wcscpy      wcscpy_instead_use_StringCbCopyW_or_StringCchCopyW;
+
+#undef strcat
+#define strcat      strcat_instead_use_StringCbCatA_or_StringCchCatA;
+
+#undef wcscat
+#define wcscat      wcscat_instead_use_StringCbCatW_or_StringCchCatW;
+
+#undef sprintf
+#define sprintf     sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA;
+
+#undef swprintf
+#define swprintf    swprintf_instead_use_StringCbPrintfW_or_StringCchPrintfW;
+
+#undef vsprintf
+#define vsprintf    vsprintf_instead_use_StringCbVPrintfA_or_StringCchVPrintfA;
+
+#undef vswprintf
+#define vswprintf   vswprintf_instead_use_StringCbVPrintfW_or_StringCchVPrintfW;
+
+#undef _snprintf
+#define _snprintf   _snprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA;
+
+#undef _snwprintf
+#define _snwprintf  _snwprintf_instead_use_StringCbPrintfW_or_StringCchPrintfW;
+
+#undef _vsnprintf
+#define _vsnprintf  _vsnprintf_instead_use_StringCbVPrintfA_or_StringCchVPrintfA;
+
+#undef _vsnwprintf
+#define _vsnwprintf _vsnwprintf_instead_use_StringCbVPrintfW_or_StringCchVPrintfW;
+
+#undef strcpyA
+#define strcpyA     strcpyA_instead_use_StringCbCopyA_or_StringCchCopyA;
+
+#undef strcpyW
+#define strcpyW     strcpyW_instead_use_StringCbCopyW_or_StringCchCopyW;
+
+#undef lstrcpy
+#define lstrcpy     lstrcpy_instead_use_StringCbCopy_or_StringCchCopy;
+
+#undef lstrcpyA
+#define lstrcpyA    lstrcpyA_instead_use_StringCbCopyA_or_StringCchCopyA;
+
+#undef lstrcpyW
+#define lstrcpyW    lstrcpyW_instead_use_StringCbCopyW_or_StringCchCopyW;
+
+#undef StrCpy
+#define StrCpy      StrCpy_instead_use_StringCbCopy_or_StringCchCopy;
+
+#undef StrCpyA
+#define StrCpyA     StrCpyA_instead_use_StringCbCopyA_or_StringCchCopyA;
+
+#undef StrCpyW
+#define StrCpyW     StrCpyW_instead_use_StringCbCopyW_or_StringCchCopyW;
+
+#undef _tcscpy
+#define _tcscpy     _tcscpy_instead_use_StringCbCopy_or_StringCchCopy;
+
+#undef _ftcscpy
+#define _ftcscpy    _ftcscpy_instead_use_StringCbCopy_or_StringCchCopy;
+
+#undef lstrcat
+#define lstrcat     lstrcat_instead_use_StringCbCat_or_StringCchCat;
+
+#undef lstrcatA
+#define lstrcatA    lstrcatA_instead_use_StringCbCatA_or_StringCchCatA;
+
+#undef lstrcatW
+#define lstrcatW    lstrcatW_instead_use_StringCbCatW_or_StringCchCatW;
+
+#undef StrCat
+#define StrCat      StrCat_instead_use_StringCbCat_or_StringCchCat;
+
+#undef StrCatA
+#define StrCatA     StrCatA_instead_use_StringCbCatA_or_StringCchCatA;
+
+#undef StrCatW
+#define StrCatW     StrCatW_instead_use_StringCbCatW_or_StringCchCatW;
+
+#undef StrNCat
+#define StrNCat     StrNCat_instead_use_StringCbCatN_or_StringCchCatN;
+
+#undef StrNCatA
+#define StrNCatA    StrNCatA_instead_use_StringCbCatNA_or_StringCchCatNA;
+
+#undef StrNCatW
+#define StrNCatW    StrNCatW_instead_use_StringCbCatNW_or_StringCchCatNW;
+
+#undef StrCatN
+#define StrCatN     StrCatN_instead_use_StringCbCatN_or_StringCchCatN;
+
+#undef StrCatNA
+#define StrCatNA    StrCatNA_instead_use_StringCbCatNA_or_StringCchCatNA;
+
+#undef StrCatNW
+#define StrCatNW    StrCatNW_instead_use_StringCbCatNW_or_StringCchCatNW;
+
+#undef _tcscat
+#define _tcscat     _tcscat_instead_use_StringCbCat_or_StringCchCat;
+
+#undef _ftcscat
+#define _ftcscat    _ftcscat_instead_use_StringCbCat_or_StringCchCat;
+
+#undef wsprintf
+#define wsprintf    wsprintf_instead_use_StringCbPrintf_or_StringCchPrintf;
+
+#undef wsprintfA
+#define wsprintfA   wsprintfA_instead_use_StringCbPrintfA_or_StringCchPrintfA;
+
+#undef wsprintfW
+#define wsprintfW   wsprintfW_instead_use_StringCbPrintfW_or_StringCchPrintfW;
+
+#undef wvsprintf
+#define wvsprintf   wvsprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf;
+
+#undef wvsprintfA
+#define wvsprintfA  wvsprintfA_instead_use_StringCbVPrintfA_or_StringCchVPrintfA;
+
+#undef wvsprintfW
+#define wvsprintfW  wvsprintfW_instead_use_StringCbVPrintfW_or_StringCchVPrintfW;
+
+#undef _vstprintf
+#define _vstprintf  _vstprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf;
+
+#undef _vsntprintf
+#define _vsntprintf _vsntprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf;
+
+#undef _stprintf
+#define _stprintf   _stprintf_instead_use_StringCbPrintf_or_StringCchPrintf;
+
+#undef _sntprintf
+#define _sntprintf  _sntprintf_instead_use_StringCbPrintf_or_StringCchPrintf;
+
+#undef _getts
+#define _getts      _getts_instead_use_StringCbGets_or_StringCchGets;
+
+#undef gets
+#define gets        _gets_instead_use_StringCbGetsA_or_StringCchGetsA;
+
+#undef _getws
+#define _getws      _getws_instead_use_StringCbGetsW_or_StringCchGetsW;
+
+#endif  // !DEPRECATE_SUPPORTED
+#endif  // !STRSAFE_NO_DEPRECATE
+
+#ifdef _NTSTRSAFE_H_INCLUDED_
+#pragma warning(pop)
+#endif // _NTSTRSAFE_H_INCLUDED_
+
+#endif  // _STRSAFE_H_INCLUDED_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/adler32.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+	    buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+	    s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/compress.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,68 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+    int level;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    err = deflateInit(&stream, level);
+    if (err != Z_OK) return err;
+
+    err = deflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        deflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = deflateEnd(&stream);
+    return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/crc32.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,162 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+#define local static
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local int crc_table_empty = 1;
+local uLongf crc_table[256];
+local void make_crc_table OF((void));
+
+/*
+  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The table is simply the CRC of all possible eight bit values.  This is all
+  the information needed to generate CRC's on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.
+*/
+local void make_crc_table()
+{
+  uLong c;
+  int n, k;
+  uLong poly;            /* polynomial exclusive-or pattern */
+  /* terms of polynomial defining this crc (except x^32): */
+  static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* make exclusive-or pattern from polynomial (0xedb88320L) */
+  poly = 0L;
+  for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
+    poly |= 1L << (31 - p[n]);
+ 
+  for (n = 0; n < 256; n++)
+  {
+    c = (uLong)n;
+    for (k = 0; k < 8; k++)
+      c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+    crc_table[n] = c;
+  }
+  crc_table_empty = 0;
+}
+#else
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local const uLongf crc_table[256] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+#endif
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const uLongf * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+  if (crc_table_empty) make_crc_table();
+#endif
+  return (const uLongf *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+
+/* ========================================================================= */
+uLong ZEXPORT crc32(crc, buf, len)
+    uLong crc;
+    const Bytef *buf;
+    uInt len;
+{
+    if (buf == Z_NULL) return 0L;
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+      make_crc_table();
+#endif
+    crc = crc ^ 0xffffffffL;
+    while (len >= 8)
+    {
+      DO8(buf);
+      len -= 8;
+    }
+    if (len) do {
+      DO1(buf);
+    } while (--len);
+    return crc ^ 0xffffffffL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/deflate.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1350 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in ftp://ds.internic.net/rfc/rfc1951.txt
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+   " deflate 1.1.3 Copyright 1995-1998 Jean-loup Gailly ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* maximum speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of str are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+    z_streamp strm;
+    int level;
+    const char *version;
+    int stream_size;
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+			 Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+		  version, stream_size)
+    z_streamp strm;
+    int  level;
+    int  method;
+    int  windowBits;
+    int  memLevel;
+    int  strategy;
+    const char *version;
+    int stream_size;
+{
+    deflate_state *s;
+    int noheader = 0;
+    static const char* my_version = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+	return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == Z_NULL) {
+	strm->zalloc = zcalloc;
+	strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == Z_NULL) strm->zfree = zcfree;
+
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#ifdef FASTEST
+    level = 1;
+#endif
+
+    if (windowBits < 0) { /* undocumented feature: suppress zlib header */
+        noheader = 1;
+        windowBits = -windowBits;
+    }
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+	strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+        return Z_STREAM_ERROR;
+    }
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+
+    s->noheader = noheader;
+    s->w_bits = windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt  dictLength;
+{
+    deflate_state *s;
+    uInt length = dictLength;
+    uInt n;
+    IPos hash_head = 0;
+
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+        strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
+
+    s = strm->state;
+    strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+    if (length < MIN_MATCH) return Z_OK;
+    if (length > MAX_DIST(s)) {
+	length = MAX_DIST(s);
+#ifndef USE_DICT_HEAD
+	dictionary += dictLength - length; /* use the tail of the dictionary */
+#endif
+    }
+    zmemcpy(s->window, dictionary, length);
+    s->strstart = length;
+    s->block_start = (long)length;
+
+    /* Insert all strings in the hash table (except for the last two bytes).
+     * s->lookahead stays null, so s->ins_h will be recomputed at the next
+     * call of fill_window.
+     */
+    s->ins_h = s->window[0];
+    UPDATE_HASH(s, s->ins_h, s->window[1]);
+    for (n = 0; n <= length - MIN_MATCH; n++) {
+	INSERT_STRING(s, n, hash_head);
+    }
+    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+    
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->noheader < 0) {
+        s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
+    }
+    s->status = s->noheader ? BUSY_STATE : INIT_STATE;
+    strm->adler = 1;
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+    lm_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+    z_streamp strm;
+    int level;
+    int strategy;
+{
+    deflate_state *s;
+    compress_func func;
+    int err = Z_OK;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+
+    if (level == Z_DEFAULT_COMPRESSION) {
+	level = 6;
+    }
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+	return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if (func != configuration_table[level].func && strm->total_in != 0) {
+	/* Flush the last buffer: */
+	err = deflate(strm, Z_PARTIAL_FLUSH);
+    }
+    if (s->level != level) {
+	s->level = level;
+	s->max_lazy_match   = configuration_table[level].max_lazy;
+	s->good_match       = configuration_table[level].good_length;
+	s->nice_match       = configuration_table[level].nice_length;
+	s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return err;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+    deflate_state *s;
+    uInt b;
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}   
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+    z_streamp strm;
+{
+    unsigned len = strm->state->pending;
+
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    strm->next_out  += len;
+    strm->state->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out  -= len;
+    strm->state->pending -= len;
+    if (strm->state->pending == 0) {
+        strm->state->pending_out = strm->state->pending_buf;
+    }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+	flush > Z_FINISH || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+	(s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    s->strm = strm; /* just in case */
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Write the zlib header */
+    if (s->status == INIT_STATE) {
+
+        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+        uInt level_flags = (s->level-1) >> 1;
+
+        if (level_flags > 3) level_flags = 3;
+        header |= (level_flags << 6);
+	if (s->strstart != 0) header |= PRESET_DICT;
+        header += 31 - (header % 31);
+
+        s->status = BUSY_STATE;
+        putShortMSB(s, header);
+
+	/* Save the adler32 of the preset dictionary: */
+	if (s->strstart != 0) {
+	    putShortMSB(s, (uInt)(strm->adler >> 16));
+	    putShortMSB(s, (uInt)(strm->adler & 0xffff));
+	}
+	strm->adler = 1L;
+    }
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+	    /* Since avail_out is 0, deflate will be called again with
+	     * more output space, but possibly with both pending and
+	     * avail_in equal to zero. There won't be anything to do,
+	     * but this is not an error situation so make sure we
+	     * return OK instead of BUF_ERROR at next call of deflate:
+             */
+	    s->last_flush = -1;
+	    return Z_OK;
+	}
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUFF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && flush <= old_flush &&
+	       flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+	bstate = (*(configuration_table[s->level].func))(s, flush);
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+	    if (strm->avail_out == 0) {
+	        s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+	    }
+	    return Z_OK;
+	    /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+	     * of deflate should use the same flush parameter to make sure
+	     * that the flush is complete. So we don't have to output an
+	     * empty block here, this will be done at next call. This also
+	     * ensures that for a very small output buffer, we emit at most
+	     * one empty block.
+	     */
+	}
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                }
+            }
+            flush_pending(strm);
+	    if (strm->avail_out == 0) {
+	      s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+	      return Z_OK;
+	    }
+        }
+    }
+    Assert(strm->avail_out > 0, "bug2");
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->noheader) return Z_STREAM_END;
+
+    /* Write the zlib trailer (adler32) */
+    putShortMSB(s, (uInt)(strm->adler >> 16));
+    putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    s->noheader = -1; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+    z_streamp strm;
+{
+    int status;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+    if (status != INIT_STATE && status != BUSY_STATE &&
+	status != FINISH_STATE) {
+      return Z_STREAM_ERROR;
+    }
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+    z_streamp dest;
+    z_streamp source;
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    *dest = *source;
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    *ds = *ss;
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+    z_streamp strm;
+    Bytef *buf;
+    unsigned size;
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    if (!strm->state->noheader) {
+        strm->adler = adler32(strm->adler, strm->next_in, len);
+    }
+    zmemcpy(buf, strm->next_in, len);
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+    deflate_state *s;
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+#ifndef FASTEST
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = s->prev_length;              /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2:
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+
+#else /* FASTEST */
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 only
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return len <= s->lookahead ? len : s->lookahead;
+}
+#endif /* FASTEST */
+#endif /* ASMV */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+    deflate_state *s;
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+		start, match, length);
+        do {
+	    fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+	} while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(s)
+    deflate_state *s;
+{
+    register unsigned n, m;
+    register Posf *p;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+            more = wsize;
+
+        } else if (more == (unsigned)(-1)) {
+            /* Very unlikely, but possible on 16 bit machine if strstart == 0
+             * and lookahead == 1 (input done one byte at time)
+             */
+            more--;
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        } else if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+
+            /* Slide the hash table (could be avoided with 32 bit values
+               at the expense of memory usage). We slide even when level == 0
+               to keep the hash table consistent if we switch back to level > 0
+               later. (Using level 0 permanently is not an optimal usage of
+               zlib, so we don't care about this pathological case.)
+             */
+	    n = s->hash_size;
+	    p = &s->head[n];
+	    do {
+		m = *--p;
+		*p = (Pos)(m >= wsize ? m-wsize : NIL);
+	    } while (--n);
+
+	    n = wsize;
+#ifndef FASTEST
+	    p = &s->prev[n];
+	    do {
+		m = *--p;
+		*p = (Pos)(m >= wsize ? m-wsize : NIL);
+		/* If n is not on any hash chain, prev[n] is garbage but
+		 * its value will never be used.
+		 */
+	    } while (--n);
+#endif
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead >= MIN_MATCH) {
+            s->ins_h = s->window[s->strstart];
+            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+		(ulg)((long)s->strstart - s->block_start), \
+		(eof)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+   FLUSH_BLOCK_ONLY(s, eof); \
+   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+     * to pending_buf_size, and each stored block has a 5 byte header:
+     */
+    ulg max_block_size = 0xffff;
+    ulg max_start;
+
+    if (max_block_size > s->pending_buf_size - 5) {
+        max_block_size = s->pending_buf_size - 5;
+    }
+
+    /* Copy as much as possible from input to output: */
+    for (;;) {
+        /* Fill the window as much as possible: */
+        if (s->lookahead <= 1) {
+
+            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+		   s->block_start >= (long)s->w_size, "slide too late");
+
+            fill_window(s);
+            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+	Assert(s->block_start >= 0L, "block gone");
+
+	s->strstart += s->lookahead;
+	s->lookahead = 0;
+
+	/* Emit a stored block if pending_buf will be full: */
+ 	max_start = s->block_start + max_block_size;
+        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+	    /* strstart == 0 is possible when wraparound on 16-bit machine */
+	    s->lookahead = (uInt)(s->strstart - max_start);
+	    s->strstart = (uInt)max_start;
+            FLUSH_BLOCK(s, 0);
+	}
+	/* Flush if we may have to slide, otherwise block_start may become
+         * negative and the data will be gone:
+         */
+        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+            FLUSH_BLOCK(s, 0);
+	}
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL; /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+	        return need_more;
+	    }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy != Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            }
+            /* longest_match() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in hash table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++; 
+            } else
+#endif
+	    {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++; 
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL;    /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+	        return need_more;
+	    }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy != Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            }
+            /* longest_match() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
+                 (s->match_length == MIN_MATCH &&
+                  s->strstart - s->match_start > TOO_FAR))) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+			   s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+	    _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+	    if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/deflate.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,318 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-1998 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _DEFLATE_H
+#define _DEFLATE_H
+
+#include "zutil.h"
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE    42
+#define BUSY_STATE   113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    int   pending;       /* nb of bytes in the pending buffer */
+    int   noheader;      /* suppress zlib header and adler32 */
+    Byte  data_type;     /* UNKNOWN, BINARY or ASCII */
+    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to supress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    int last_eob_len;   /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+        /* in trees.c */
+void _tr_init         OF((deflate_state *s));
+int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
+			  int eof));
+void _tr_align        OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch _length_code[];
+  extern uch _dist_code[];
+#else
+  extern const uch _length_code[];
+  extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (length); \
+    ush dist = (distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length) 
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/infblock.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,398 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+  if (c != Z_NULL)
+    *c = s->check;
+  if (s->mode == BTREE || s->mode == DTREE)
+    ZFREE(z, s->sub.trees.blens);
+  if (s->mode == CODES)
+    inflate_codes_free(s->sub.decode.codes, z);
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+  Tracev((stderr, "inflate:   blocks reset\n"));
+}
+
+
+inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_streamp z;
+check_func c;
+uInt w;
+{
+  inflate_blocks_statef *s;
+
+  if ((s = (inflate_blocks_statef *)ZALLOC
+       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+    return s;
+  if ((s->hufts =
+       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
+  {
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+  {
+    ZFREE(z, s->hufts);
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Tracev((stderr, "inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, Z_NULL);
+  return s;
+}
+
+
+int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input based on current state */
+  while (1) switch (s->mode)
+  {
+    case TYPE:
+      NEEDBITS(3)
+      t = (uInt)b & 7;
+      s->last = t & 1;
+      switch (t >> 1)
+      {
+        case 0:                         /* stored */
+          Tracev((stderr, "inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Tracev((stderr, "inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BAD;
+          z->msg = (char*)"invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+      {
+        s->mode = BAD;
+        z->msg = (char*)"invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      zmemcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev((stderr, "inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      s->mode = s->last ? DRY : TYPE;
+      break;
+    case TABLE:
+      NEEDBITS(14)
+      s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+      {
+        s->mode = BAD;
+        z->msg = (char*)"too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+      {
+        r = Z_MEM_ERROR;
+        LEAVE
+      }
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       table sizes ok\n"));
+      s->mode = BTREE;
+    case BTREE:
+      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+      {
+        NEEDBITS(3)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+        DUMPBITS(3)
+      }
+      while (s->sub.trees.index < 19)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+      s->sub.trees.bb = 7;
+      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, s->hufts, z);
+      if (t != Z_OK)
+      {
+        ZFREE(z, s->sub.trees.blens);
+        r = t;
+        if (r == Z_DATA_ERROR)
+          s->mode = BAD;
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       bits tree ok\n"));
+      s->mode = DTREE;
+    case DTREE:
+      while (t = s->sub.trees.table,
+             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+      {
+        inflate_huft *h;
+        uInt i, j, c;
+
+        t = s->sub.trees.bb;
+        NEEDBITS(t)
+        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+        t = h->bits;
+        c = h->base;
+        if (c < 16)
+        {
+          DUMPBITS(t)
+          s->sub.trees.blens[s->sub.trees.index++] = c;
+        }
+        else /* c == 16..18 */
+        {
+          i = c == 18 ? 7 : c - 14;
+          j = c == 18 ? 11 : 3;
+          NEEDBITS(t + i)
+          DUMPBITS(t)
+          j += (uInt)b & inflate_mask[i];
+          DUMPBITS(i)
+          i = s->sub.trees.index;
+          t = s->sub.trees.table;
+          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+              (c == 16 && i < 1))
+          {
+            ZFREE(z, s->sub.trees.blens);
+            s->mode = BAD;
+            z->msg = (char*)"invalid bit length repeat";
+            r = Z_DATA_ERROR;
+            LEAVE
+          }
+          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+          do {
+            s->sub.trees.blens[i++] = c;
+          } while (--j);
+          s->sub.trees.index = i;
+        }
+      }
+      s->sub.trees.tb = Z_NULL;
+      {
+        uInt bl, bd;
+        inflate_huft *tl, *td;
+        inflate_codes_statef *c;
+
+        bl = 9;         /* must be <= 9 for lookahead assumptions */
+        bd = 6;         /* must be <= 9 for lookahead assumptions */
+        t = s->sub.trees.table;
+        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
+                                  s->hufts, z);
+        ZFREE(z, s->sub.trees.blens);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+            s->mode = BAD;
+          r = t;
+          LEAVE
+        }
+        Tracev((stderr, "inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        s->sub.decode.codes = c;
+      }
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      LOAD
+      Tracev((stderr, "inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONE;
+    case DONE:
+      r = Z_STREAM_END;
+      LEAVE
+    case BAD:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+int inflate_blocks_free(s, z)
+inflate_blocks_statef *s;
+z_streamp z;
+{
+  inflate_blocks_reset(s, z, Z_NULL);
+  ZFREE(z, s->window);
+  ZFREE(z, s->hufts);
+  ZFREE(z, s);
+  Tracev((stderr, "inflate:   blocks freed\n"));
+  return Z_OK;
+}
+
+
+void inflate_set_dictionary(s, d, n)
+inflate_blocks_statef *s;
+const Bytef *d;
+uInt  n;
+{
+  zmemcpy(s->window, d, n);
+  s->read = s->write = s->window + n;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
+ * IN assertion: s != Z_NULL
+ */
+int inflate_blocks_sync_point(s)
+inflate_blocks_statef *s;
+{
+  return s->mode == LENS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/infblock.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,39 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+    z_streamp z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+extern int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));                      /* initial return code */
+
+extern void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    uLongf *));                  /* check value on output */
+
+extern int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_streamp));
+
+extern void inflate_set_dictionary OF((
+    inflate_blocks_statef *s,
+    const Bytef *d,  /* dictionary */
+    uInt  n));       /* dictionary length */
+
+extern int inflate_blocks_sync_point OF((
+    inflate_blocks_statef *s));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/infcodes.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,257 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+      START,    /* x: set up for LEN */
+      LEN,      /* i: get length/literal/eob next */
+      LENEXT,   /* i: getting length extra (have base) */
+      DIST,     /* i: get distance next */
+      DISTEXT,  /* i: getting distance extra */
+      COPY,     /* o: copying bytes in window, waiting for space */
+      LIT,      /* o: got literal, waiting for output space */
+      WASH,     /* o: got eob, possibly still output waiting */
+      END,      /* x: got eob and all data flushed */
+      BADCODE}  /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  inflate_codes_mode mode;      /* current inflate_codes mode */
+
+  /* mode dependent information */
+  uInt len;
+  union {
+    struct {
+      inflate_huft *tree;       /* pointer into tree */
+      uInt need;                /* bits needed */
+    } code;             /* if LEN or DIST, where in tree */
+    uInt lit;           /* if LIT, literal */
+    struct {
+      uInt get;                 /* bits to get for extra */
+      uInt dist;                /* distance back to copy from */
+    } copy;             /* if EXT or COPY, where and how much */
+  } sub;                /* submode */
+
+  /* mode independent information */
+  Byte lbits;           /* ltree bits decoded per branch */
+  Byte dbits;           /* dtree bits decoder per branch */
+  inflate_huft *ltree;          /* literal/length/eob tree */
+  inflate_huft *dtree;          /* distance tree */
+
+};
+
+
+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+z_streamp z;
+{
+  inflate_codes_statef *c;
+
+  if ((c = (inflate_codes_statef *)
+       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev((stderr, "inflate:       codes new\n"));
+  }
+  return c;
+}
+
+
+int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt j;               /* temporary storage */
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Bytef *f;             /* pointer to copy strings from */
+  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input and output based on current state */
+  while (1) switch (c->mode)
+  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+    case START:         /* x: set up for LEN */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+        LOAD
+        if (r != Z_OK)
+        {
+          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+          break;
+        }
+      }
+#endif /* !SLOW */
+      c->sub.code.need = c->lbits;
+      c->sub.code.tree = c->ltree;
+      c->mode = LEN;
+    case LEN:           /* i: get length/literal/eob next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", t->base));
+        c->mode = LIT;
+        break;
+      }
+      if (e & 16)               /* length */
+      {
+        c->sub.copy.get = e & 15;
+        c->len = t->base;
+        c->mode = LENEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv((stderr, "inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid literal/length code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case LENEXT:        /* i: getting length extra (have base) */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->len += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv((stderr, "inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e & 16)               /* distance */
+      {
+        c->sub.copy.get = e & 15;
+        c->sub.copy.dist = t->base;
+        c->mode = DISTEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid distance code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case DISTEXT:       /* i: getting distance extra */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->sub.copy.dist += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+      f = (uInt)(q - s->window) < c->sub.copy.dist ?
+          s->end - (c->sub.copy.dist - (q - s->window)) :
+          q - c->sub.copy.dist;
+#else
+      f = q - c->sub.copy.dist;
+      if ((uInt)(q - s->window) < c->sub.copy.dist)
+        f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
+#endif
+      while (c->len)
+      {
+        NEEDOUT
+        OUTBYTE(*f++)
+        if (f == s->end)
+          f = s->window;
+        c->len--;
+      }
+      c->mode = START;
+      break;
+    case LIT:           /* o: got literal, waiting for output space */
+      NEEDOUT
+      OUTBYTE(c->sub.lit)
+      c->mode = START;
+      break;
+    case WASH:          /* o: got eob, possibly more output */
+      if (k > 7)        /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;            /* can always return one */
+      }
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      c->mode = END;
+    case END:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADCODE:       /* x: got error */
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+  ZFREE(z, c);
+  Tracev((stderr, "inflate:       codes free\n"));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/infcodes.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,27 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_streamp ));
+
+extern int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+extern void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_streamp ));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/inffast.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,170 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
+
+/* Called with number of bytes left to write in window at least 258
+   (the maximum string length) and number of input bytes available
+   at least ten.  The ten bytes are six bytes for the longest length/
+   distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp z;
+{
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  uInt ml;              /* mask for literal/length tree */
+  uInt md;              /* mask for distance tree */
+  uInt c;               /* bytes to copy */
+  uInt d;               /* distance back to copy from */
+  Bytef *r;             /* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks */
+  ml = inflate_mask[bl];
+  md = inflate_mask[bd];
+
+  /* do until not enough input or output space for fast loop */
+  do {                          /* assume called with m >= 258 && n >= 10 */
+    /* get literal/length code */
+    GRABBITS(20)                /* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+    {
+      DUMPBITS(t->bits)
+      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
+      *q++ = (Byte)t->base;
+      m--;
+      continue;
+    }
+    do {
+      DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv((stderr, "inflate:         * length %u\n", c));
+
+        /* decode distance base of block to copy */
+        GRABBITS(15);           /* max bits for distance code */
+        e = (t = td + ((uInt)b & md))->exop;
+        do {
+          DUMPBITS(t->bits)
+          if (e & 16)
+          {
+            /* get extra bits to add to distance base */
+            e &= 15;
+            GRABBITS(e)         /* get extra bits (up to 13) */
+            d = t->base + ((uInt)b & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv((stderr, "inflate:         * distance %u\n", d));
+
+            /* do the copy */
+            m -= c;
+            if ((uInt)(q - s->window) >= d)     /* offset before dest */
+            {                                   /*  just copy */
+              r = q - d;
+              *q++ = *r++;  c--;        /* minimum count is three, */
+              *q++ = *r++;  c--;        /*  so unroll loop a little */
+            }
+            else                        /* else offset after destination */
+            {
+              e = d - (uInt)(q - s->window); /* bytes from offset to end */
+              r = s->end - e;           /* pointer to offset */
+              if (c > e)                /* if source crosses, */
+              {
+                c -= e;                 /* copy to end of window */
+                do {
+                  *q++ = *r++;
+                } while (--e);
+                r = s->window;          /* copy rest from start of window */
+              }
+            }
+            do {                        /* copy all or what's left */
+              *q++ = *r++;
+            } while (--c);
+            break;
+          }
+          else if ((e & 64) == 0)
+          {
+            t += t->base;
+            e = (t += ((uInt)b & inflate_mask[e]))->exop;
+          }
+          else
+          {
+            z->msg = (char*)"invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
+      }
+      if ((e & 64) == 0)
+      {
+        t += t->base;
+        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
+      }
+      else if (e & 32)
+      {
+        Tracevv((stderr, "inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = (char*)"invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/inffast.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,17 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+extern int inflate_fast OF((
+    uInt,
+    uInt,
+    inflate_huft *,
+    inflate_huft *,
+    inflate_blocks_statef *,
+    z_streamp ));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/inffixed.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+local uInt fixed_bl = 9;
+local uInt fixed_bd = 5;
+local inflate_huft fixed_tl[] = {
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+  };
+local inflate_huft fixed_td[] = {
+    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+  };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/inflate.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,366 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+typedef enum {
+      METHOD,   /* waiting for method byte */
+      FLAG,     /* waiting for flag byte */
+      DICT4,    /* four dictionary check bytes to go */
+      DICT3,    /* three dictionary check bytes to go */
+      DICT2,    /* two dictionary check bytes to go */
+      DICT1,    /* one dictionary check byte to go */
+      DICT0,    /* waiting for inflateSetDictionary */
+      BLOCKS,   /* decompressing blocks */
+      CHECK4,   /* four check bytes to go */
+      CHECK3,   /* three check bytes to go */
+      CHECK2,   /* two check bytes to go */
+      CHECK1,   /* one check byte to go */
+      DONE,     /* finished check, done */
+      BAD}      /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  inflate_mode  mode;   /* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;        /* if FLAGS, method byte */
+    struct {
+      uLong was;                /* computed check value */
+      uLong need;               /* stream check value */
+    } check;            /* if CHECK, check values to compare */
+    uInt marker;        /* if BAD, inflateSync's marker bytes count */
+  } sub;        /* submode */
+
+  /* mode independent information */
+  int  nowrap;          /* flag for no wrapper */
+  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
+  inflate_blocks_statef 
+    *blocks;            /* current inflate_blocks state */
+
+};
+
+
+int ZEXPORT inflateReset(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+  Tracev((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateEnd(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z);
+  ZFREE(z, z->state);
+  z->state = Z_NULL;
+  Tracev((stderr, "inflate: end\n"));
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateInit2_(z, w, version, stream_size)
+z_streamp z;
+int w;
+const char *version;
+int stream_size;
+{
+  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+      stream_size != sizeof(z_stream))
+      return Z_VERSION_ERROR;
+
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->msg = Z_NULL;
+  if (z->zalloc == Z_NULL)
+  {
+    z->zalloc = zcalloc;
+    z->opaque = (voidpf)0;
+  }
+  if (z->zfree == Z_NULL) z->zfree = zcfree;
+  if ((z->state = (struct internal_state FAR *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->blocks = Z_NULL;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Tracev((stderr, "inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateInit_(z, version, stream_size)
+z_streamp z;
+const char *version;
+int stream_size;
+{
+  return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int ZEXPORT inflate(z, f)
+z_streamp z;
+int f;
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      NEEDBYTE
+      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"unknown compression method";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      NEEDBYTE
+      b = NEXTBYTE;
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib header ok\n"));
+      if (!(b & PRESET_DICT))
+      {
+        z->state->mode = BLOCKS;
+        break;
+      }
+      z->state->mode = DICT4;
+    case DICT4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = DICT3;
+    case DICT3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = DICT2;
+    case DICT2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = DICT1;
+    case DICT1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+      z->adler = z->state->sub.check.need;
+      z->state->mode = DICT0;
+      return Z_NEED_DICT;
+    case DICT0:
+      z->state->mode = BAD;
+      z->msg = (char*)"need dictionary";
+      z->state->sub.marker = 0;       /* can try inflateSync */
+      return Z_STREAM_ERROR;
+    case BLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = BAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r == Z_OK)
+        r = f;
+      if (r != Z_STREAM_END)
+        return r;
+      r = f;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = DONE;
+        break;
+      }
+      z->state->mode = CHECK4;
+    case CHECK4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = CHECK3;
+    case CHECK3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = CHECK2;
+    case CHECK2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = CHECK1;
+    case CHECK1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib check ok\n"));
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case BAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
+z_streamp z;
+const Bytef *dictionary;
+uInt  dictLength;
+{
+  uInt length = dictLength;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
+    return Z_STREAM_ERROR;
+
+  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
+  z->adler = 1L;
+
+  if (length >= ((uInt)1<<z->state->wbits))
+  {
+    length = (1<<z->state->wbits)-1;
+    dictionary += dictLength - length;
+  }
+  inflate_set_dictionary(z->state->blocks, dictionary, length);
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateSync(z)
+z_streamp z;
+{
+  uInt n;       /* number of bytes to look at */
+  Bytef *p;     /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != BAD)
+  {
+    z->state->mode = BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    static const Byte mark[4] = {0, 0, 0xff, 0xff};
+    if (*p == mark[m])
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
+    return Z_STREAM_ERROR;
+  return inflate_blocks_sync_point(z->state->blocks);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/inftrees.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,455 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#if !defined(BUILDFIXED) && !defined(STDC)
+#  define BUILDFIXED   /* non ANSI compilers may not accept inffixed.h */
+#endif
+
+const char inflate_copyright[] =
+   " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+struct internal_state  {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+    uIntf *,            /* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    const uIntf *,      /* list of base values for non-simple codes */
+    const uIntf *,      /* list of extra bits for non-simple codes */
+    inflate_huft * FAR*,/* result: starting table */
+    uIntf *,            /* maximum lookup bits (returns actual) */
+    inflate_huft *,     /* space for trees */
+    uInt *,             /* hufts used in space */
+    uIntf * ));         /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+local const uInt cpdext[30] = { /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+
+local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
+uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
+uInt n;                 /* number of codes (assumed <= 288) */
+uInt s;                 /* number of simple-valued codes (0..s-1) */
+const uIntf *d;         /* list of base values for non-simple codes */
+const uIntf *e;         /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t;  /* result: starting table */
+uIntf *m;               /* maximum lookup bits, returns actual */
+inflate_huft *hp;       /* space for trees */
+uInt *hn;               /* hufts used in space */
+uIntf *v;               /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+   if the given code set is incomplete (the tables are still built in this
+   case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+   lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+  uInt a;                       /* counter for codes of length k */
+  uInt c[BMAX+1];               /* bit length count table */
+  uInt f;                       /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register uInt i;              /* counter, current code */
+  register uInt j;              /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
+  register uIntf *p;            /* pointer into c[], b[], or v[] */
+  inflate_huft *q;              /* points to current table */
+  struct inflate_huft_s r;      /* table entry for structure assignment */
+  inflate_huft *u[BMAX];        /* table stack */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uIntf *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+  C4                            /* clear c[]--assume BMAX+1 is 16 */
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((uInt)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((uInt)l > i)
+    l = i;
+  *m = l;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return Z_DATA_ERROR;
+  if ((y -= c[i]) < 0)
+    return Z_DATA_ERROR;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+  n = x[g];                     /* set n to length of v */
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_NULL;   /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = g - w;
+        z = z > (uInt)l ? l : z;        /* table size upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          if (j < z)
+            while (++j < z)     /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;          /* enough codes to use up j bits */
+              f -= *xp;         /* else deduct codes from patterns */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate new table */
+        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
+          return Z_MEM_ERROR;   /* not enough memory */
+        u[h] = q = hp + *hn;
+        *hn += z;
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.bits = (Byte)l;     /* bits to dump before this table */
+          r.exop = (Byte)j;     /* bits in this table */
+          j = i >> (w - l);
+          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+        else
+          *t = q;               /* first table is returned result */
+      }
+
+      /* set up table entry in r */
+      r.bits = (Byte)(k - w);
+      if (p >= v + n)
+        r.exop = 128 + 64;      /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
+        r.base = *p++;          /* simple code is just the value */
+      }
+      else
+      {
+        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+        r.base = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
+      while ((i & mask) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+        mask = (1 << w) - 1;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+int inflate_trees_bits(c, bb, tb, hp, z)
+uIntf *c;               /* 19 code lengths */
+uIntf *bb;              /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+inflate_huft *hp;       /* space for trees */
+z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+
+  if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+                 tb, bb, hp, &hn, v);
+  if (r == Z_DATA_ERROR)
+    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR || *bb == 0)
+  {
+    z->msg = (char*)"incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  ZFREE(z, v);
+  return r;
+}
+
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
+uInt nl;                /* number of literal/length codes */
+uInt nd;                /* number of distance codes */
+uIntf *c;               /* that many (total) code lengths */
+uIntf *bl;              /* literal desired/actual bit depth */
+uIntf *bd;              /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+inflate_huft *hp;       /* space for trees */
+z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+
+  /* allocate work area */
+  if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+
+  /* build literal/length tree */
+  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+  if (r != Z_OK || *bl == 0)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed literal/length tree";
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+  }
+
+  /* build distance tree */
+  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+  if (r != Z_OK || (*bd == 0 && nl > 257))
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed distance tree";
+    else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      z->msg = (char*)"incomplete distance tree";
+      r = Z_DATA_ERROR;
+    }
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"empty distance tree with lengths";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+#endif
+  }
+
+  /* done */
+  ZFREE(z, v);
+  return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#ifdef BUILDFIXED
+local int fixed_built = 0;
+#define FIXEDH 544      /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+#else
+#include "inffixed.h"
+#endif
+
+
+int inflate_trees_fixed(bl, bd, tl, td, z)
+uIntf *bl;               /* literal desired/actual bit depth */
+uIntf *bd;               /* distance desired/actual bit depth */
+inflate_huft * FAR *tl;  /* literal/length tree result */
+inflate_huft * FAR *td;  /* distance tree result */
+z_streamp z;             /* for memory allocation */
+{
+#ifdef BUILDFIXED
+  /* build fixed tables if not already */
+  if (!fixed_built)
+  {
+    int k;              /* temporary variable */
+    uInt f = 0;         /* number of hufts used in fixed_mem */
+    uIntf *c;           /* length list for huft_build */
+    uIntf *v;           /* work area for huft_build */
+
+    /* allocate memory */
+    if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+      return Z_MEM_ERROR;
+    if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    {
+      ZFREE(z, c);
+      return Z_MEM_ERROR;
+    }
+
+    /* literal table */
+    for (k = 0; k < 144; k++)
+      c[k] = 8;
+    for (; k < 256; k++)
+      c[k] = 9;
+    for (; k < 280; k++)
+      c[k] = 7;
+    for (; k < 288; k++)
+      c[k] = 8;
+    fixed_bl = 9;
+    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
+               fixed_mem, &f, v);
+
+    /* distance table */
+    for (k = 0; k < 30; k++)
+      c[k] = 5;
+    fixed_bd = 5;
+    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
+               fixed_mem, &f, v);
+
+    /* done */
+    ZFREE(z, v);
+    ZFREE(z, c);
+    fixed_built = 1;
+  }
+#endif
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/inftrees.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,58 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+  union {
+    struct {
+      Byte Exop;        /* number of extra bits or operation */
+      Byte Bits;        /* number of bits in this code or subcode */
+    } what;
+    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
+  uInt base;            /* literal, length base, distance base,
+                           or table offset */
+};
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1004 huft structures (850 for length/literals
+   and 154 for distances, the latter actually the result of an
+   exhaustive search).  The actual maximum is not known, but the
+   value below is more than safe. */
+#define MANY 1440
+
+extern int inflate_trees_bits OF((
+    uIntf *,                    /* 19 code lengths */
+    uIntf *,                    /* bits tree desired/actual depth */
+    inflate_huft * FAR *,       /* bits tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uIntf *,                    /* that many (total) code lengths */
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_fixed OF((
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    z_streamp));                /* for memory allocation */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/infutil.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,87 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt n;
+  Bytef *p;
+  Bytef *q;
+
+  /* local copies of source and destination pointers */
+  p = z->next_out;
+  q = s->read;
+
+  /* compute number of bytes to copy as far as end of window */
+  n = (uInt)((q <= s->write ? s->write : s->end) - q);
+  if (n > z->avail_out) n = z->avail_out;
+  if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+  /* update counters */
+  z->avail_out -= n;
+  z->total_out += n;
+
+  /* update check information */
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as far as end of window */
+  zmemcpy(p, q, n);
+  p += n;
+  q += n;
+
+  /* see if more to copy at beginning of window */
+  if (q == s->end)
+  {
+    /* wrap pointers */
+    q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
+
+    /* compute bytes to copy */
+    n = (uInt)(s->write - q);
+    if (n > z->avail_out) n = z->avail_out;
+    if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+    /* update counters */
+    z->avail_out -= n;
+    z->total_out += n;
+
+    /* update check information */
+    if (s->checkfn != Z_NULL)
+      z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    zmemcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/infutil.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+      TYPE,     /* get type bits (3, including end bit) */
+      LENS,     /* get lengths for stored */
+      STORED,   /* processing stored block */
+      TABLE,    /* get table lengths */
+      BTREE,    /* get bit lengths tree for a dynamic block */
+      DTREE,    /* get length, distance trees for a dynamic block */
+      CODES,    /* processing fixed or dynamic block */
+      DRY,      /* output remaining window bytes */
+      DONE,     /* finished last block, done */
+      BAD}      /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  inflate_block_mode  mode;     /* current inflate_block mode */
+
+  /* mode dependent information */
+  union {
+    uInt left;          /* if STORED, bytes left to copy */
+    struct {
+      uInt table;               /* table lengths (14 bits) */
+      uInt index;               /* index into blens (or border) */
+      uIntf *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_codes_statef 
+         *codes;
+    } decode;           /* if CODES, current state */
+  } sub;                /* submode */
+  uInt last;            /* true if this block is the last block */
+
+  /* mode independent information */
+  uInt bitk;            /* bits in bit buffer */
+  uLong bitb;           /* bit buffer */
+  inflate_huft *hufts;  /* single malloc for tree space */
+  Bytef *window;        /* sliding window */
+  Bytef *end;           /* one byte after sliding window */
+  Bytef *read;          /* window read pointer */
+  Bytef *write;         /* window write pointer */
+  check_func checkfn;   /* check function */
+  uLong check;          /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/*   update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/*   get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/*   output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/*   load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+struct internal_state      {int dummy;}; /* for buggy compilers */
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/trees.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1214 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-1998 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values).  The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+#  include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+#  include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+    const ct_data *static_tree;  /* static tree or NULL */
+    const intf *extra_bits;      /* extra bits for each code or NULL */
+    int     extra_base;          /* base index for extra_bits */
+    int     elems;               /* max number of elements in the tree */
+    int     max_length;          /* max bit length for the codes */
+};
+
+local static_tree_desc  static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc  static_d_desc =
+{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
+
+local static_tree_desc  static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block     OF((deflate_state *s));
+local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
+local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree     OF((deflate_state *s, tree_desc *desc));
+local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local int  build_bl_tree  OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+                              int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+                              ct_data *dtree));
+local void set_data_type  OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup      OF((deflate_state *s));
+local void bi_flush       OF((deflate_state *s));
+local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
+                              int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+#  define send_code(s, c, tree) \
+     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+       send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+    put_byte(s, (uch)((w) & 0xff)); \
+    put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits      OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+    deflate_state *s;
+    int value;  /* value to send */
+    int length; /* number of bits */
+{
+    Tracevv((stderr," l %2d v %4x ", length, value));
+    Assert(length > 0 && length <= 15, "invalid length");
+    s->bits_sent += (ulg)length;
+
+    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+     * unused bits in value.
+     */
+    if (s->bi_valid > (int)Buf_size - length) {
+        s->bi_buf |= (value << s->bi_valid);
+        put_short(s, s->bi_buf);
+        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+        s->bi_valid += length - Buf_size;
+    } else {
+        s->bi_buf |= value << s->bi_valid;
+        s->bi_valid += length;
+    }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+  if (s->bi_valid > (int)Buf_size - len) {\
+    int val = value;\
+    s->bi_buf |= (val << s->bi_valid);\
+    put_short(s, s->bi_buf);\
+    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+    s->bi_valid += len - Buf_size;\
+  } else {\
+    s->bi_buf |= (value) << s->bi_valid;\
+    s->bi_valid += len;\
+  }\
+}
+#endif /* DEBUG */
+
+
+#define MAX(a,b) (a >= b ? a : b)
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+    static int static_init_done = 0;
+    int n;        /* iterates over tree elements */
+    int bits;     /* bit counter */
+    int length;   /* length value */
+    int code;     /* code value */
+    int dist;     /* distance index */
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    if (static_init_done) return;
+
+    /* For some embedded targets, global variables are not initialized: */
+    static_l_desc.static_tree = static_ltree;
+    static_l_desc.extra_bits = extra_lbits;
+    static_d_desc.static_tree = static_dtree;
+    static_d_desc.extra_bits = extra_dbits;
+    static_bl_desc.extra_bits = extra_blbits;
+
+    /* Initialize the mapping length (0..255) -> length code (0..28) */
+    length = 0;
+    for (code = 0; code < LENGTH_CODES-1; code++) {
+        base_length[code] = length;
+        for (n = 0; n < (1<<extra_lbits[code]); n++) {
+            _length_code[length++] = (uch)code;
+        }
+    }
+    Assert (length == 256, "tr_static_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    _length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            _dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: dist != 256");
+    dist >>= 7; /* from now on, all distances are divided by 128 */
+    for ( ; code < D_CODES; code++) {
+        base_dist[code] = dist << 7;
+        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+            _dist_code[256 + dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+    /* Construct the codes of the static literal tree */
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+    n = 0;
+    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+    /* Codes 286 and 287 do not exist, but we must include them in the
+     * tree construction to get a canonical Huffman tree (longest code
+     * all ones)
+     */
+    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+    /* The static distance tree is trivial: */
+    for (n = 0; n < D_CODES; n++) {
+        static_dtree[n].Len = 5;
+        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+    }
+    static_init_done = 1;
+
+#  ifdef GEN_TREES_H
+    gen_trees_header();
+#  endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+#  ifndef DEBUG
+#    include <stdio.h>
+#  endif
+
+#  define SEPARATOR(i, last, width) \
+      ((i) == (last)? "\n};\n\n" :    \
+       ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+    FILE *header = fopen("trees.h", "w");
+    int i;
+
+    Assert (header != NULL, "Can't open trees.h");
+    fprintf(header,
+	    "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+    for (i = 0; i < L_CODES+2; i++) {
+	fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+		static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+    }
+
+    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+	fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+		static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+    }
+
+    fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+    for (i = 0; i < DIST_CODE_LEN; i++) {
+	fprintf(header, "%2u%s", _dist_code[i],
+		SEPARATOR(i, DIST_CODE_LEN-1, 20));
+    }
+
+    fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+	fprintf(header, "%2u%s", _length_code[i],
+		SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+    }
+
+    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+    for (i = 0; i < LENGTH_CODES; i++) {
+	fprintf(header, "%1u%s", base_length[i],
+		SEPARATOR(i, LENGTH_CODES-1, 20));
+    }
+
+    fprintf(header, "local const int base_dist[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+	fprintf(header, "%5u%s", base_dist[i],
+		SEPARATOR(i, D_CODES-1, 10));
+    }
+
+    fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+    deflate_state *s;
+{
+    tr_static_init();
+
+    s->l_desc.dyn_tree = s->dyn_ltree;
+    s->l_desc.stat_desc = &static_l_desc;
+
+    s->d_desc.dyn_tree = s->dyn_dtree;
+    s->d_desc.stat_desc = &static_d_desc;
+
+    s->bl_desc.dyn_tree = s->bl_tree;
+    s->bl_desc.stat_desc = &static_bl_desc;
+
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+    s->compressed_len = 0L;
+    s->bits_sent = 0L;
+#endif
+
+    /* Initialize the first block of the first file: */
+    init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+    deflate_state *s;
+{
+    int n; /* iterates over tree elements */
+
+    /* Initialize the trees. */
+    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
+    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
+    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+    s->dyn_ltree[END_BLOCK].Freq = 1;
+    s->opt_len = s->static_len = 0L;
+    s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+    top = s->heap[SMALLEST]; \
+    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+    pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+    deflate_state *s;
+    ct_data *tree;  /* the tree to restore */
+    int k;               /* node to move down */
+{
+    int v = s->heap[k];
+    int j = k << 1;  /* left son of k */
+    while (j <= s->heap_len) {
+        /* Set j to the smallest of the two sons: */
+        if (j < s->heap_len &&
+            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+            j++;
+        }
+        /* Exit if v is smaller than both sons */
+        if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+        /* Exchange v with the smallest son */
+        s->heap[k] = s->heap[j];  k = j;
+
+        /* And continue down the tree, setting j to the left son of k */
+        j <<= 1;
+    }
+    s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+local void gen_bitlen(s, desc)
+    deflate_state *s;
+    tree_desc *desc;    /* the tree descriptor */
+{
+    ct_data *tree        = desc->dyn_tree;
+    int max_code         = desc->max_code;
+    const ct_data *stree = desc->stat_desc->static_tree;
+    const intf *extra    = desc->stat_desc->extra_bits;
+    int base             = desc->stat_desc->extra_base;
+    int max_length       = desc->stat_desc->max_length;
+    int h;              /* heap index */
+    int n, m;           /* iterate over the tree elements */
+    int bits;           /* bit length */
+    int xbits;          /* extra bits */
+    ush f;              /* frequency */
+    int overflow = 0;   /* number of elements with bit length too large */
+
+    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+    /* In a first pass, compute the optimal bit lengths (which may
+     * overflow in the case of the bit length tree).
+     */
+    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+        n = s->heap[h];
+        bits = tree[tree[n].Dad].Len + 1;
+        if (bits > max_length) bits = max_length, overflow++;
+        tree[n].Len = (ush)bits;
+        /* We overwrite tree[n].Dad which is no longer needed */
+
+        if (n > max_code) continue; /* not a leaf node */
+
+        s->bl_count[bits]++;
+        xbits = 0;
+        if (n >= base) xbits = extra[n-base];
+        f = tree[n].Freq;
+        s->opt_len += (ulg)f * (bits + xbits);
+        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+    }
+    if (overflow == 0) return;
+
+    Trace((stderr,"\nbit length overflow\n"));
+    /* This happens for example on obj2 and pic of the Calgary corpus */
+
+    /* Find the first bit length which could increase: */
+    do {
+        bits = max_length-1;
+        while (s->bl_count[bits] == 0) bits--;
+        s->bl_count[bits]--;      /* move one leaf down the tree */
+        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+        s->bl_count[max_length]--;
+        /* The brother of the overflow item also moves one step up,
+         * but this does not affect bl_count[max_length]
+         */
+        overflow -= 2;
+    } while (overflow > 0);
+
+    /* Now recompute all bit lengths, scanning in increasing frequency.
+     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+     * lengths instead of fixing only the wrong ones. This idea is taken
+     * from 'ar' written by Haruhiko Okumura.)
+     */
+    for (bits = max_length; bits != 0; bits--) {
+        n = s->bl_count[bits];
+        while (n != 0) {
+            m = s->heap[--h];
+            if (m > max_code) continue;
+            if (tree[m].Len != (unsigned) bits) {
+                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+                s->opt_len += ((long)bits - (long)tree[m].Len)
+                              *(long)tree[m].Freq;
+                tree[m].Len = (ush)bits;
+            }
+            n--;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+    ct_data *tree;             /* the tree to decorate */
+    int max_code;              /* largest code with non zero frequency */
+    ushf *bl_count;            /* number of codes at each bit length */
+{
+    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+    ush code = 0;              /* running code value */
+    int bits;                  /* bit index */
+    int n;                     /* code index */
+
+    /* The distribution counts are first used to generate the code values
+     * without bit reversal.
+     */
+    for (bits = 1; bits <= MAX_BITS; bits++) {
+        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+    }
+    /* Check that the bit counts in bl_count are consistent. The last code
+     * must be all ones.
+     */
+    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = bi_reverse(next_code[len]++, len);
+
+        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+    deflate_state *s;
+    tree_desc *desc; /* the tree descriptor */
+{
+    ct_data *tree         = desc->dyn_tree;
+    const ct_data *stree  = desc->stat_desc->static_tree;
+    int elems             = desc->stat_desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node;          /* new node being created */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            s->heap[++(s->heap_len)] = max_code = n;
+            s->depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (s->heap_len < 2) {
+        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+        tree[node].Freq = 1;
+        s->depth[node] = 0;
+        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+        /* node is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    node = elems;              /* next internal node of the tree */
+    do {
+        pqremove(s, tree, n);  /* n = node of least frequency */
+        m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+        s->heap[--(s->heap_max)] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = tree[n].Freq + tree[m].Freq;
+        s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+        if (tree == s->bl_tree) {
+            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        s->heap[SMALLEST] = node++;
+        pqdownheap(s, tree, SMALLEST);
+
+    } while (s->heap_len >= 2);
+
+    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen(s, (tree_desc *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree;   /* the tree to be scanned */
+    int max_code;    /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    if (nextlen == 0) max_count = 138, min_count = 3;
+    tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            s->bl_tree[curlen].Freq += count;
+        } else if (curlen != 0) {
+            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+            s->bl_tree[REP_3_6].Freq++;
+        } else if (count <= 10) {
+            s->bl_tree[REPZ_3_10].Freq++;
+        } else {
+            s->bl_tree[REPZ_11_138].Freq++;
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree; /* the tree to be scanned */
+    int max_code;       /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    /* tree[max_code+1].Len = -1; */  /* guard already set */
+    if (nextlen == 0) max_count = 138, min_count = 3;
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+        } else if (curlen != 0) {
+            if (curlen != prevlen) {
+                send_code(s, curlen, s->bl_tree); count--;
+            }
+            Assert(count >= 3 && count <= 6, " 3_6?");
+            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+        } else if (count <= 10) {
+            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+        } else {
+            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+    deflate_state *s;
+{
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    /* Determine the bit length frequencies for literal and distance trees */
+    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+    /* Build the bit length tree: */
+    build_tree(s, (tree_desc *)(&(s->bl_desc)));
+    /* opt_len now includes the length of the tree representations, except
+     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+     */
+
+    /* Determine the number of bit length codes to send. The pkzip format
+     * requires that at least 4 bit length codes be sent. (appnote.txt says
+     * 3 but the actual value used is 4.)
+     */
+    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+    }
+    /* Update opt_len to include the bit length tree and counts */
+    s->opt_len += 3*(max_blindex+1) + 5+5+4;
+    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+            s->opt_len, s->static_len));
+
+    return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+    deflate_state *s;
+    int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+    int rank;                    /* index in bl_order */
+
+    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+            "too many codes");
+    Tracev((stderr, "\nbl counts: "));
+    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+    send_bits(s, dcodes-1,   5);
+    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
+    for (rank = 0; rank < blcodes; rank++) {
+        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+    }
+    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+    deflate_state *s;
+    charf *buf;       /* input block */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    send_bits(s, (STORED_BLOCK<<1)+eof, 3);  /* send block type */
+#ifdef DEBUG
+    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+    s->compressed_len += (stored_len + 4) << 3;
+#endif
+    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+    deflate_state *s;
+{
+    send_bits(s, STATIC_TREES<<1, 3);
+    send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+    bi_flush(s);
+    /* Of the 10 bits for the empty block, we have already sent
+     * (10 - bi_valid) bits. The lookahead for the last real code (before
+     * the EOB of the previous block) was thus at least one plus the length
+     * of the EOB plus what we have just sent of the empty static block.
+     */
+    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+        send_bits(s, STATIC_TREES<<1, 3);
+        send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+        s->compressed_len += 10L;
+#endif
+        bi_flush(s);
+    }
+    s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block(s, buf, stored_len, eof)
+    deflate_state *s;
+    charf *buf;       /* input block, or NULL if too old */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+    int max_blindex = 0;  /* index of last bit length code of non zero freq */
+
+    /* Build the Huffman trees unless a stored block is forced */
+    if (s->level > 0) {
+
+	 /* Check if the file is ascii or binary */
+	if (s->data_type == Z_UNKNOWN) set_data_type(s);
+
+	/* Construct the literal and distance trees */
+	build_tree(s, (tree_desc *)(&(s->l_desc)));
+	Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+		s->static_len));
+
+	build_tree(s, (tree_desc *)(&(s->d_desc)));
+	Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+		s->static_len));
+	/* At this point, opt_len and static_len are the total bit lengths of
+	 * the compressed block data, excluding the tree representations.
+	 */
+
+	/* Build the bit length tree for the above two trees, and get the index
+	 * in bl_order of the last bit length code to send.
+	 */
+	max_blindex = build_bl_tree(s);
+
+	/* Determine the best encoding. Compute first the block length in bytes*/
+	opt_lenb = (s->opt_len+3+7)>>3;
+	static_lenb = (s->static_len+3+7)>>3;
+
+	Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+		opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+		s->last_lit));
+
+	if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+    } else {
+        Assert(buf != (char*)0, "lost buf");
+	opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+    }
+
+#ifdef FORCE_STORED
+    if (buf != (char*)0) { /* force stored block */
+#else
+    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+                       /* 4: two words for the lengths */
+#endif
+        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+         * Otherwise we can't have processed more than WSIZE input bytes since
+         * the last block flush, because compression would have been
+         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+         * transform a block into a stored block.
+         */
+        _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+    } else if (static_lenb >= 0) { /* force static trees */
+#else
+    } else if (static_lenb == opt_lenb) {
+#endif
+        send_bits(s, (STATIC_TREES<<1)+eof, 3);
+        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->static_len;
+#endif
+    } else {
+        send_bits(s, (DYN_TREES<<1)+eof, 3);
+        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+                       max_blindex+1);
+        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->opt_len;
+#endif
+    }
+    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+    /* The above check is made mod 2^32, for files larger than 512 MB
+     * and uLong implemented on 32 bits.
+     */
+    init_block(s);
+
+    if (eof) {
+        bi_windup(s);
+#ifdef DEBUG
+        s->compressed_len += 7;  /* align on byte boundary */
+#endif
+    }
+    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+           s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+    deflate_state *s;
+    unsigned dist;  /* distance of matched string */
+    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+    s->d_buf[s->last_lit] = (ush)dist;
+    s->l_buf[s->last_lit++] = (uch)lc;
+    if (dist == 0) {
+        /* lc is the unmatched char */
+        s->dyn_ltree[lc].Freq++;
+    } else {
+        s->matches++;
+        /* Here, lc is the match length - MIN_MATCH */
+        dist--;             /* dist = match distance - 1 */
+        Assert((ush)dist < (ush)MAX_DIST(s) &&
+               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
+
+        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+        s->dyn_dtree[d_code(dist)].Freq++;
+    }
+
+#ifdef TRUNCATE_BLOCK
+    /* Try to guess if it is profitable to stop the current block here */
+    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+        /* Compute an upper bound for the compressed length */
+        ulg out_length = (ulg)s->last_lit*8L;
+        ulg in_length = (ulg)((long)s->strstart - s->block_start);
+        int dcode;
+        for (dcode = 0; dcode < D_CODES; dcode++) {
+            out_length += (ulg)s->dyn_dtree[dcode].Freq *
+                (5L+extra_dbits[dcode]);
+        }
+        out_length >>= 3;
+        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+               s->last_lit, in_length, out_length,
+               100L - out_length*100L/in_length));
+        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+    }
+#endif
+    return (s->last_lit == s->lit_bufsize-1);
+    /* We avoid equality with lit_bufsize because of wraparound at 64K
+     * on 16 bit machines and because stored blocks are restricted to
+     * 64K-1 bytes.
+     */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+    deflate_state *s;
+    ct_data *ltree; /* literal tree */
+    ct_data *dtree; /* distance tree */
+{
+    unsigned dist;      /* distance of matched string */
+    int lc;             /* match length or unmatched char (if dist == 0) */
+    unsigned lx = 0;    /* running index in l_buf */
+    unsigned code;      /* the code to send */
+    int extra;          /* number of extra bits to send */
+
+    if (s->last_lit != 0) do {
+        dist = s->d_buf[lx];
+        lc = s->l_buf[lx++];
+        if (dist == 0) {
+            send_code(s, lc, ltree); /* send a literal byte */
+            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+        } else {
+            /* Here, lc is the match length - MIN_MATCH */
+            code = _length_code[lc];
+            send_code(s, code+LITERALS+1, ltree); /* send the length code */
+            extra = extra_lbits[code];
+            if (extra != 0) {
+                lc -= base_length[code];
+                send_bits(s, lc, extra);       /* send the extra length bits */
+            }
+            dist--; /* dist is now the match distance - 1 */
+            code = d_code(dist);
+            Assert (code < D_CODES, "bad d_code");
+
+            send_code(s, code, dtree);       /* send the distance code */
+            extra = extra_dbits[code];
+            if (extra != 0) {
+                dist -= base_dist[code];
+                send_bits(s, dist, extra);   /* send the extra distance bits */
+            }
+        } /* literal or match pair ? */
+
+        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+        Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
+
+    } while (lx < s->last_lit);
+
+    send_code(s, END_BLOCK, ltree);
+    s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+local void set_data_type(s)
+    deflate_state *s;
+{
+    int n = 0;
+    unsigned ascii_freq = 0;
+    unsigned bin_freq = 0;
+    while (n < 7)        bin_freq += s->dyn_ltree[n++].Freq;
+    while (n < 128)    ascii_freq += s->dyn_ltree[n++].Freq;
+    while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
+    s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+    unsigned code; /* the value to invert */
+    int len;       /* its bit length */
+{
+    register unsigned res = 0;
+    do {
+        res |= code & 1;
+        code >>= 1, res <<= 1;
+    } while (--len > 0);
+    return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+    deflate_state *s;
+{
+    if (s->bi_valid == 16) {
+        put_short(s, s->bi_buf);
+        s->bi_buf = 0;
+        s->bi_valid = 0;
+    } else if (s->bi_valid >= 8) {
+        put_byte(s, (Byte)s->bi_buf);
+        s->bi_buf >>= 8;
+        s->bi_valid -= 8;
+    }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+    deflate_state *s;
+{
+    if (s->bi_valid > 8) {
+        put_short(s, s->bi_buf);
+    } else if (s->bi_valid > 0) {
+        put_byte(s, (Byte)s->bi_buf);
+    }
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+#ifdef DEBUG
+    s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+    deflate_state *s;
+    charf    *buf;    /* the input data */
+    unsigned len;     /* its length */
+    int      header;  /* true if block header must be written */
+{
+    bi_windup(s);        /* align on byte boundary */
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+
+    if (header) {
+        put_short(s, (ush)len);   
+        put_short(s, (ush)~len);
+#ifdef DEBUG
+        s->bits_sent += 2*16;
+#endif
+    }
+#ifdef DEBUG
+    s->bits_sent += (ulg)len<<3;
+#endif
+    while (len--) {
+        put_byte(s, *buf++);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/trees.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
+{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
+{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
+{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
+{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
+{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
+{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
+{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
+{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
+{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
+{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
+{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
+{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
+{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
+{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
+{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
+{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
+{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
+{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
+{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
+{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
+{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
+{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
+{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
+{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
+{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
+{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
+{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
+{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
+{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
+{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
+{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
+{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
+{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
+{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
+{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
+{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
+{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
+{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
+{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
+{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
+{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
+{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
+{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
+{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
+{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
+{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
+{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
+{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
+{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
+{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
+{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
+{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
+{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
+{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
+{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
+{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
+{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
+ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
+   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
+ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/uncompr.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,58 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+
+    err = inflateInit(&stream);
+    if (err != Z_OK) return err;
+
+    err = inflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        inflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = inflateEnd(&stream);
+    return err;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/zconf.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,279 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_	z_deflateInit_
+#  define deflate	z_deflate
+#  define deflateEnd	z_deflateEnd
+#  define inflateInit_ 	z_inflateInit_
+#  define inflate	z_inflate
+#  define inflateEnd	z_inflateEnd
+#  define deflateInit2_	z_deflateInit2_
+#  define deflateSetDictionary z_deflateSetDictionary
+#  define deflateCopy	z_deflateCopy
+#  define deflateReset	z_deflateReset
+#  define deflateParams	z_deflateParams
+#  define inflateInit2_	z_inflateInit2_
+#  define inflateSetDictionary z_inflateSetDictionary
+#  define inflateSync	z_inflateSync
+#  define inflateSyncPoint z_inflateSyncPoint
+#  define inflateReset	z_inflateReset
+#  define compress	z_compress
+#  define compress2	z_compress2
+#  define uncompress	z_uncompress
+#  define adler32	z_adler32
+#  define crc32		z_crc32
+#  define get_crc_table z_get_crc_table
+
+#  define Byte		z_Byte
+#  define uInt		z_uInt
+#  define uLong		z_uLong
+#  define Bytef	        z_Bytef
+#  define charf		z_charf
+#  define intf		z_intf
+#  define uIntf		z_uIntf
+#  define uLongf	z_uLongf
+#  define voidpf	z_voidpf
+#  define voidp		z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#  define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32))  && !defined(STDC)
+#  define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+#  ifndef STDC
+#    define STDC
+#  endif
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+#  define NEED_DUMMY_RETURN
+#endif
+
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+   /* MSC small or medium model */
+#  define SMALL_MEDIUM
+#  ifdef _MSC_VER
+#    define FAR _far
+#  else
+#    define FAR far
+#  endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+#  ifndef __32BIT__
+#    define SMALL_MEDIUM
+#    define FAR _far
+#  endif
+#endif
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+#  if defined(_WINDOWS) || defined(WINDOWS)
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+#    define ZEXPORT  WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA  WINAPIV
+#    else
+#      define ZEXPORTVA  FAR _cdecl _export
+#    endif
+#  endif
+#  if defined (__BORLANDC__)
+#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+#      include <windows.h>
+#      define ZEXPORT __declspec(dllexport) WINAPI
+#      define ZEXPORTRVA __declspec(dllexport) WINAPIV
+#    else
+#      if defined (_Windows) && defined (__DLL__)
+#        define ZEXPORT _export
+#        define ZEXPORTVA _export
+#      endif
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  if defined (ZLIB_DLL)
+#    define ZEXTERN extern __declspec(dllexport)
+#  else
+#    define ZEXTERN extern __declspec(dllimport)
+#  endif
+#endif
+
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+
+#ifndef FAR
+#   define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void FAR *voidpf;
+   typedef void     *voidp;
+#else
+   typedef Byte FAR *voidpf;
+   typedef Byte     *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  define z_off_t  off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define  z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(inflate_blocks,"INBL")
+#   pragma map(inflate_blocks_new,"INBLNE")
+#   pragma map(inflate_blocks_free,"INBLFR")
+#   pragma map(inflate_blocks_reset,"INBLRE")
+#   pragma map(inflate_codes_free,"INCOFR")
+#   pragma map(inflate_codes,"INCO")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_flush,"INFLU")
+#   pragma map(inflate_mask,"INMA")
+#   pragma map(inflate_set_dictionary,"INSEDI2")
+#   pragma map(inflate_copyright,"INCOPY")
+#   pragma map(inflate_trees_bits,"INTRBI")
+#   pragma map(inflate_trees_dynamic,"INTRDY")
+#   pragma map(inflate_trees_fixed,"INTRFI")
+#   pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#endif /* _ZCONF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/zlib.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,893 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.1.3, July 9th, 1998
+
+  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.3"
+
+/* 
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/* 
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  the compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+  
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update data_type if it can make a good guess about
+  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/* 
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may some
+  introduce some output latency (reading input without producing any output)
+  except when forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+  output as possible to the output buffer. The flushing behavior of inflate is
+  not specified for values of the flush parameter other than Z_SYNC_FLUSH
+  and Z_FINISH, but the current implementation actually flushes as much output
+  as possible anyway.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster routine
+  may be used for the single inflate() call.
+
+     If a preset dictionary is needed at this point (see inflateSetDictionary
+  below), inflate sets strm-adler to the adler32 checksum of the
+  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
+  it sets strm->adler to the adler32 checksum of all output produced
+  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+  an error code as described below. At the end of the stream, inflate()
+  checks that its computed adler32 checksum is equal to that saved by the
+  compressor and returns Z_STREAM_END only if the checksum is correct.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect
+  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+  case, the application may then call inflateSync to look for a good
+  compression block.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*   
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match).  Filtered data consists mostly of small values with a
+   somewhat random distribution. In this case, the compression algorithm is
+   tuned to compress them better. The effect of Z_FILTERED is to force more
+   Huffman coding and less string matching; it is somewhat intermediate
+   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+   the compression ratio but not the correctness of the compressed output even
+   if it is not set appropriately.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+                            
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front.
+
+     Upon return of this function, strm->adler is set to the Adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The Adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.)
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+				      int level,
+				      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+/*   
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. If a compressed stream with a larger window size is given as
+   input, inflate() will return with the error code Z_DATA_ERROR instead of
+   trying to allocate a larger window.
+
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+   memLevel). msg is set to null if there is no error message.  inflateInit2
+   does not perform any decompression apart from reading the zlib header if
+   present: this will be done by inflate(). (So next_in and avail_in may be
+   modified, but next_out and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate
+   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the Adler32 value returned by this call of
+   inflate. The compressor and decompressor must use exactly the same
+   dictionary (see deflateSetDictionary).
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect Adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/* 
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least 0.1% larger than
+   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h". (See the description
+   of deflateInit2 for more information about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT    gzwrite OF((gzFile file, 
+				   const voidp buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
+				      z_off_t offset, int whence));
+/* 
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char   * ZEXPORT zError           OF((int err));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/zutil.c	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,225 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+struct internal_state      {int dummy;}; /* for buggy compilers */
+
+#ifndef STDC
+extern void exit OF((int));
+#endif
+
+const char *z_errmsg[10] = {
+"need dictionary",     /* Z_NEED_DICT       2  */
+"stream end",          /* Z_STREAM_END      1  */
+"",                    /* Z_OK              0  */
+"file error",          /* Z_ERRNO         (-1) */
+"stream error",        /* Z_STREAM_ERROR  (-2) */
+"data error",          /* Z_DATA_ERROR    (-3) */
+"insufficient memory", /* Z_MEM_ERROR     (-4) */
+"buffer error",        /* Z_BUF_ERROR     (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+    return ZLIB_VERSION;
+}
+
+#ifdef DEBUG
+
+#  ifndef verbose
+#    define verbose 0
+#  endif
+int z_verbose = verbose;
+
+void z_error (m)
+    char *m;
+{
+    fprintf(stderr, "%s\n", m);
+    exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+    int err;
+{
+    return ERR_MSG(err);
+}
+
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+    Bytef* dest;
+    const Bytef* source;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+    const Bytef* s1;
+    const Bytef* s2;
+    uInt  len;
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void zmemzero(dest, len)
+    Bytef* dest;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+#ifdef __TURBOC__
+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
+/* Small and medium model in Turbo C are for now limited to near allocation
+ * with reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf = opaque; /* just to make some compilers happy */
+    ulg bsize = (ulg)items*size;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ptr = opaque; /* just to make some compilers happy */
+    Assert(0, "zcfree: ptr not found");
+}
+#endif
+#endif /* __TURBOC__ */
+
+
+#if defined(M_I86) && !defined(__32BIT__)
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    return _halloc((long)items, size);
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    _hfree(ptr);
+}
+
+#endif /* MSC */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  calloc OF((uInt items, uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+    voidpf opaque;
+    unsigned items;
+    unsigned size;
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return (voidpf)calloc(items, size);
+}
+
+void  zcfree (opaque, ptr)
+    voidpf opaque;
+    voidpf ptr;
+{
+    free(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/zlib/zutil.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,220 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifdef STDC
+#  include <stddef.h>
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+    extern int errno;
+#else
+#   include <errno.h>
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#ifdef MSDOS
+#  define OS_CODE  0x00
+#  if defined(__TURBOC__) || defined(__BORLANDC__)
+#    if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+       /* Allow compilation with ANSI keywords only enabled */
+       void _Cdecl farfree( void *block );
+       void *_Cdecl farmalloc( unsigned long nbytes );
+#    else
+#     include <alloc.h>
+#    endif
+#  else /* MSC or DJGPP */
+#    include <malloc.h>
+#  endif
+#endif
+
+#ifdef OS2
+#  define OS_CODE  0x06
+#endif
+
+#ifdef WIN32 /* Window 95 & Windows NT */
+#  define OS_CODE  0x0b
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  0x02
+#  define F_OPEN(name, mode) \
+     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  0x01
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  0x05
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  0x07
+#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#    include <unix.h> /* for fdopen */
+#  else
+#    ifndef fdopen
+#      define fdopen(fd,mode) NULL /* No fdopen() */
+#    endif
+#  endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+#  define OS_CODE  0x0F
+#endif
+
+#ifdef TOPS20
+#  define OS_CODE  0x0a
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+#  define fdopen(fd,type)  _fdopen(fd,type)
+#endif
+
+
+        /* Common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#ifdef HAVE_STRERROR
+   extern char *strerror OF((int));
+#  define zstrerror(errnum) strerror(errnum)
+#else
+#  define zstrerror(errnum) ""
+#endif
+
+#if defined(pyr)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy memcpy
+#    define zmemcmp memcmp
+#    define zmemzero(dest, len) memset(dest, 0, len)
+#  endif
+#else
+   extern void zmemcpy  OF((Bytef* dest, const Bytef* source, uInt len));
+   extern int  zmemcmp  OF((const Bytef* s1, const Bytef* s2, uInt len));
+   extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  include <stdio.h>
+   extern int z_verbose;
+   extern void z_error    OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
+				       uInt len));
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void   zcfree  OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mm7_1.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,7676 @@
+/* This file has been generated by the Hex-Rays decompiler.
+   Copyright (c) 2007-2011 Hex-Rays <info@hex-rays.com>
+
+   Detected compiler: Visual C++
+*/
+
+//#include <defs.h>
+#include "MM7.h"
+
+#include "MapInfo.h"
+#include "Game.h"
+#include "GUIWindow.h"
+#include "GUIFont.h"
+#include "GUIButton.h"
+#include "GUIProgressBar.h"
+#include "Party.h"
+#include "AudioPlayer.h"
+#include "Outdoor.h"
+#include "IndoorCamera.h"
+#include "Overlays.h"
+#include "Monsters.h"
+#include "Arcomage.h"
+#include "LOD.h"
+#include "Actor.h"
+#include "Allocator.h"
+#include "Events.h"
+#include "Viewport.h"
+#include "FrameTableInc.h"
+#include "Math.h"
+#include "LayingItem.h"
+#include "ObjectList.h"
+#include "Chest.h"
+#include "PaletteManager.h"
+#include "DecorationList.h"
+#include "SaveLoad.h"
+#include "stru123.h"
+#include "Time.h"
+#include "IconFrameTable.h"
+#include "stru179.h"
+#include "Awards.h"
+#include "Autonotes.h"
+#include "stru160.h"
+#include "stru279.h"
+#include "TurnEngine.h"
+#include "stru277.h"
+#include "Weather.h"
+#include "stru272.h"
+#include "stru298.h"
+#include "StorylineTextTable.h"
+#include "Events2D.h"
+
+#include "mm7_data.h"
+
+
+
+
+int __stdcall aWinProc(HWND hWnd, UINT Msg, WPARAM wParam, unsigned int lParam);
+int __stdcall InsertMM7CDDialogFunc(HWND hDlg, int a2, __int16 a3, int a4);
+bool __fastcall FindMM7CD(HWND hWnd, char *pCDDrive);
+bool __fastcall Initialize(HINSTANCE hInst, char *pCmdLine);
+
+
+
+
+
+
+void __cdecl FreeSavegameThumbnails()
+{
+  for (int i = 0; i < 40; ++i)
+    //pAllocator->FreeChunk(pSavegameThumbnails[i].pPixels);
+    pSavegameThumbnails[i].Release();
+}
+
+
+//----- (004196A0) --------------------------------------------------------
+void __cdecl sub_4196A0()
+{
+  GUIButton *i; // esi@2
+  GUIButton *j; // esi@7
+
+  if ( dword_507CC0 )
+  {
+    dword_507CC0 = 0;
+    for ( i = pGUIWindow_CurrentMenu->pControlsHead; i; i = i->pNext )
+    {
+      if ( BYTE1(i->field_1C) & 0x80 )
+        GUIButton::_41D0D8(i);
+    }
+    for ( j = pGUIWindow_CurrentMenu->pControlsHead; j; j = j->pNext )
+    {
+      if ( j->uControlID == 120 )
+      {
+        j->uX = dword_50698C;
+        j->uY = dword_506988;
+        j->uZ = dword_506984;
+        j->uW = dword_506980;
+        pGUIWindow_CurrentMenu->_41D08F(1, 0, 0, 0);
+      }
+    }
+  }
+}
+// 506980: using guessed type int dword_506980;
+// 506984: using guessed type int dword_506984;
+// 506988: using guessed type int dword_506988;
+// 50698C: using guessed type int dword_50698C;
+// 507CC0: using guessed type int dword_507CC0;
+
+//----- (00419719) --------------------------------------------------------
+char __fastcall CharacterUI_SkillsTab_Draw(unsigned int uPlayerID)
+{
+  unsigned int v1; // esi@1
+  Player *pPlayer; // ebp@1
+  unsigned int v3; // eax@1
+  signed int v4; // ecx@1
+  int v5; // edi@3
+  GUIWindow *v6; // ecx@3
+  int v7; // eax@4
+  GUIButton *v8; // edx@5
+  int v9; // eax@7
+  unsigned int v10; // ecx@9
+  unsigned __int16 v11; // ax@9
+  int v12; // eax@9
+  unsigned __int8 v13; // cf@12
+  unsigned __int8 v14; // zf@12
+  unsigned int v15; // eax@12
+  char *v16; // ecx@22
+  GUIWindow *v17; // ecx@33
+  int v18; // edx@34
+  GUIButton *v19; // eax@35
+  int v20; // edx@37
+  unsigned __int16 v21; // cx@39
+  unsigned int v22; // eax@39
+  int v23; // edi@39
+  unsigned int v24; // eax@42
+  char v25; // sf@52
+  char *v26; // ecx@52
+  int v27; // edi@63
+  GUIWindow *v28; // ecx@63
+  int v29; // edx@64
+  GUIButton *v30; // eax@65
+  int v31; // edx@67
+  unsigned int v32; // ecx@69
+  int v33; // eax@69
+  unsigned int v34; // eax@72
+  char *v35; // ecx@82
+  GUIWindow *v36; // ecx@93
+  int v37; // edx@94
+  GUIButton *v38; // eax@94
+  int v39; // edx@97
+  unsigned __int16 v40; // cx@99
+  unsigned int v41; // eax@99
+  int v42; // edi@99
+  unsigned int v43; // eax@102
+  char *v44; // ecx@112
+  char *v46; // [sp-Ch] [bp-4Ch]@19
+  char *v47; // [sp-Ch] [bp-4Ch]@49
+  char *v48; // [sp-Ch] [bp-4Ch]@79
+  char *v49; // [sp-Ch] [bp-4Ch]@109
+  unsigned int v50; // [sp-8h] [bp-48h]@19
+  unsigned int v51; // [sp-8h] [bp-48h]@49
+  unsigned int v52; // [sp-8h] [bp-48h]@79
+  unsigned int v53; // [sp-8h] [bp-48h]@109
+  int v54; // [sp-4h] [bp-44h]@19
+  int v55; // [sp-4h] [bp-44h]@49
+  int v56; // [sp-4h] [bp-44h]@79
+  int v57; // [sp-4h] [bp-44h]@109
+  unsigned int v58; // [sp+10h] [bp-30h]@9
+  unsigned int v59; // [sp+10h] [bp-30h]@39
+  unsigned int v60; // [sp+10h] [bp-30h]@69
+  unsigned int v61; // [sp+10h] [bp-30h]@99
+  int v62; // [sp+14h] [bp-2Ch]@4
+  int v63; // [sp+14h] [bp-2Ch]@34
+  int v64; // [sp+14h] [bp-2Ch]@64
+  int v65; // [sp+14h] [bp-2Ch]@94
+  signed int i; // [sp+18h] [bp-28h]@4
+  signed int v67; // [sp+18h] [bp-28h]@34
+  signed int v68; // [sp+18h] [bp-28h]@64
+  signed int v69; // [sp+18h] [bp-28h]@94
+  int v70; // [sp+1Ch] [bp-24h]@3
+  int v71; // [sp+1Ch] [bp-24h]@33
+  int v72; // [sp+1Ch] [bp-24h]@63
+  int v73; // [sp+1Ch] [bp-24h]@93
+  int uY; // [sp+20h] [bp-20h]@9
+  int uYa; // [sp+20h] [bp-20h]@33
+  int uYb; // [sp+20h] [bp-20h]@69
+  int uYc; // [sp+20h] [bp-20h]@93
+  unsigned int a5; // [sp+24h] [bp-1Ch]@1
+  unsigned int v79; // [sp+28h] [bp-18h]@1
+  int *v80; // [sp+2Ch] [bp-14h]@3
+  int *v81; // [sp+2Ch] [bp-14h]@33
+  int *v82; // [sp+2Ch] [bp-14h]@63
+  int *v83; // [sp+2Ch] [bp-14h]@93
+  unsigned int v84; // [sp+30h] [bp-10h]@1
+  int v85; // [sp+34h] [bp-Ch]@1
+  unsigned int v86; // [sp+38h] [bp-8h]@1
+  unsigned __int16 v87; // [sp+3Ch] [bp-4h]@9
+  char *v88; // [sp+3Ch] [bp-4h]@24
+  char *v89; // [sp+3Ch] [bp-4h]@54
+  unsigned __int16 v90; // [sp+3Ch] [bp-4h]@69
+  char *v91; // [sp+3Ch] [bp-4h]@84
+  char *v92; // [sp+3Ch] [bp-4h]@114
+
+  v1 = uPlayerID;
+  a5 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v84 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xAFu, 0xFFu);
+  v85 = pGUIWindow_CurrentMenu->pCurrentPosActiveItem;
+  v86 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0, 0);
+  v79 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0);
+  pPlayer = (Player *)&stru_AA1058[3].pSounds[6972 * v1 + 40552];
+  v3 = pIcons_LOD->LoadTexture("fr_skill", TEXTURE_16BIT_PALETTE);
+  pRenderer->DrawTextureIndexed(8u, 8u, (Texture *)(v3 != -1 ? (int)&pIcons_LOD->pTextures[v3] : 0));
+  v4 = v79;
+  if ( !pPlayer->uSkillPoints )
+    v4 = 65535;
+  sprintf(
+    pTmpBuf,
+    "%s ",
+    pGlobalTXT_LocalizationStrings[206],        // Skills for
+    a5,
+    pPlayer->pName,
+    pGlobalTXT_LocalizationStrings[207],        // Skill Points
+    v4,
+    pPlayer->uSkillPoints);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 24, 18, 0, pTmpBuf, 0, 0, 0);
+  v5 = 2 * LOBYTE(pFontLucida->uFontHeight) + 13;// Weapons,   Level
+  sprintf(pTmpBuf, "%s\r400%s", pGlobalTXT_LocalizationStrings[242], pGlobalTXT_LocalizationStrings[131]);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 24, v5, a5, pTmpBuf, 0, 0, 0);
+  v6 = pGUIWindow_CurrentMenu;
+  v70 = 0;
+  v80 = dword_4E2A2C;
+  do
+  {
+    v62 = *v80;
+    v7 = 0;
+    for ( i = 0; i < (signed int)v6->uNumControls; v7 = i++ + 1 )
+    {
+      v8 = v6->pControlsHead;
+      if ( v7 > 0 )
+      {
+        do
+        {
+          v8 = v8->pNext;
+          --v7;
+        }
+        while ( v7 );
+      }
+      v9 = v8->field_1C;
+      if ( SBYTE1(v9) >= 0 )
+        continue;
+      BYTE1(v9) &= 0x7Fu;
+      if ( v9 != v62 )
+        continue;
+      v5 = v8->uY;
+      v10 = pPlayer->uSkillPoints;
+      ++v70;
+      v11 = pPlayer->pActiveSkills[v62];
+      v87 = pPlayer->pActiveSkills[v62];
+      v12 = v11 & 0x3F;
+      v58 = 0;
+      uY = v12;
+      if ( v10 >= v12 + 1 )
+        v58 = v84;
+      if ( v85 == i )
+      {
+        v13 = v10 < v12;
+        v14 = v10 == v12;
+        v15 = v86;
+        if ( !(v13 | v14) )
+          v15 = v79;
+        v58 = v15;
+      }
+      else
+      {
+        v15 = v58;
+      }
+      if ( HIBYTE(v87) & 1 )
+      {
+        if ( !v15 )
+          v15 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        v54 = uY;
+        v50 = v58;
+        v46 = pGlobalTXT_LocalizationStrings[96];
+      }
+      else
+      {
+        if ( !(v87 & 0xC0) )
+        {
+          sprintf(pTmpBuf, "%s\r400%2d", pSkillNames[v62], uY);
+          goto LABEL_28;
+        }
+        v16 = pGlobalTXT_LocalizationStrings[432];
+        if ( (v87 & 0x80u) == 0 )
+          v16 = pGlobalTXT_LocalizationStrings[433];
+        v88 = v16;
+        if ( !v15 )
+          v15 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        v54 = uY;
+        v50 = v58;
+        v46 = v88;
+      }
+      sprintf(pTmpBuf, "%s ", pSkillNames[v62], v15, v46, v50, v54);
+LABEL_28:
+      pGUIWindow_CurrentMenu->DrawText(pFontLucida, 24, v5, v58, pTmpBuf, 0, 0, 0);
+      v6 = pGUIWindow_CurrentMenu;
+    }
+    ++v80;
+  }
+  while ( (signed int)v80 < (signed int)dword_4E2A50 );
+  if ( !v70 )
+  {
+    v5 = v5 + LOBYTE(pFontLucida->uFontHeight) - 3;
+    v6->DrawText(pFontLucida, 24, v5, 0, pGlobalTXT_LocalizationStrings[153], 0, 0, 0);
+  }
+  uYa = v5 + 2 * LOBYTE(pFontLucida->uFontHeight) - 10;
+  sprintf(pTmpBuf, "%s\r400%s", pGlobalTXT_LocalizationStrings[138], pGlobalTXT_LocalizationStrings[131]);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 24, uYa, a5, pTmpBuf, 0, 0, 0);
+  v17 = pGUIWindow_CurrentMenu;
+  v71 = 0;
+  v81 = _4E2A80_skills;
+  do
+  {
+    v18 = 0;
+    v67 = 0;
+    v63 = *v81;
+    while ( v67 < (signed int)v17->uNumControls )
+    {
+      v19 = v17->pControlsHead;
+      if ( v18 > 0 )
+      {
+        do
+        {
+          v19 = v19->pNext;
+          --v18;
+        }
+        while ( v18 );
+      }
+      v20 = v19->field_1C;
+      if ( SBYTE1(v20) >= 0 || (BYTE1(v20) &= 0x7Fu, v20 != v63) )
+        goto LABEL_59;
+      ++v71;
+      uYa = v19->uY;
+      v21 = pPlayer->pActiveSkills[v63];
+      v22 = pPlayer->uSkillPoints;
+      v23 = pPlayer->pActiveSkills[v63] & 0x3F;
+      v59 = 0;
+      if ( v22 >= v23 + 1 )
+        v59 = v84;
+      if ( v85 == v67 )
+      {
+        v13 = v22 < v23;
+        v14 = v22 == v23;
+        v24 = v86;
+        if ( !(v13 | v14) )
+          v24 = v79;
+        v59 = v24;
+      }
+      else
+      {
+        v24 = v59;
+      }
+      if ( HIBYTE(v21) & 1 )
+      {
+        if ( !v24 )
+          v24 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        v55 = v23;
+        v51 = v59;
+        v47 = pGlobalTXT_LocalizationStrings[96];
+      }
+      else
+      {
+        if ( !(v21 & 0xC0) )
+        {
+          sprintf(pTmpBuf, "%s\r400%2d", pSkillNames[v63], v23);
+          goto LABEL_58;
+        }
+        v25 = (v21 & 0x80u) != 0;
+        v26 = pGlobalTXT_LocalizationStrings[432];
+        if ( !v25 )
+          v26 = pGlobalTXT_LocalizationStrings[433];
+        v89 = v26;
+        if ( !v24 )
+          v24 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        v55 = v23;
+        v51 = v59;
+        v47 = v89;
+      }
+      sprintf(pTmpBuf, "%s ", pSkillNames[v63], v24, v47, v51, v55);
+LABEL_58:
+      pGUIWindow_CurrentMenu->DrawText(pFontLucida, 24, uYa, v59, pTmpBuf, 0, 0, 0);
+      v17 = pGUIWindow_CurrentMenu;
+LABEL_59:
+      v18 = v67++ + 1;
+    }
+    ++v81;
+  }
+  while ( (signed int)v81 < (signed int)pAwardsTextColors );
+  if ( !v71 )
+    v17->DrawText(
+      pFontLucida,
+      24,
+      LOBYTE(pFontLucida->uFontHeight) + uYa - 3,
+      0,
+      pGlobalTXT_LocalizationStrings[153],
+      0,
+      0,
+      0);
+  v27 = 2 * LOBYTE(pFontLucida->uFontHeight) + 13;
+  sprintf(pTmpBuf, "%s\r177%s", pGlobalTXT_LocalizationStrings[11], pGlobalTXT_LocalizationStrings[131]);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 248, v27, a5, pTmpBuf, 0, 0, 0);
+  v28 = pGUIWindow_CurrentMenu;
+  v72 = 0;
+  v82 = dword_4E2A18;
+  do
+  {
+    v29 = 0;
+    v68 = 0;
+    v64 = *v82;
+    while ( v68 < (signed int)v28->uNumControls )
+    {
+      v30 = v28->pControlsHead;
+      if ( v29 > 0 )
+      {
+        do
+        {
+          v30 = v30->pNext;
+          --v29;
+        }
+        while ( v29 );
+      }
+      v31 = v30->field_1C;
+      if ( SBYTE1(v31) >= 0 || (BYTE1(v31) &= 0x7Fu, v31 != v64) )
+        goto LABEL_89;
+      v27 = v30->uY;
+      ++v72;
+      v60 = 0;
+      v90 = pPlayer->pActiveSkills[v64];
+      v32 = pPlayer->uSkillPoints;
+      v33 = pPlayer->pActiveSkills[v64] & 0x3F;
+      uYb = v33;
+      if ( v32 >= v33 + 1 )
+        v60 = v84;
+      if ( v85 == v68 )
+      {
+        v13 = v32 < v33;
+        v14 = v32 == v33;
+        v34 = v86;
+        if ( !(v13 | v14) )
+          v34 = v79;
+        v60 = v34;
+      }
+      else
+      {
+        v34 = v60;
+      }
+      if ( (pPlayer->pActiveSkills[v64] >> 8) & 1 )
+      {
+        if ( !v34 )
+          v34 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        v56 = uYb;
+        v52 = v60;
+        v48 = pGlobalTXT_LocalizationStrings[96];
+      }
+      else
+      {
+        if ( !(v90 & 0xC0) )
+        {
+          sprintf(pTmpBuf, "%s\r177%2d", pSkillNames[v64], uYb);
+          goto LABEL_88;
+        }
+        v35 = pGlobalTXT_LocalizationStrings[432];
+        if ( (v90 & 0x80u) == 0 )
+          v35 = pGlobalTXT_LocalizationStrings[433];
+        v91 = v35;
+        if ( !v34 )
+          v34 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        v56 = uYb;
+        v52 = v60;
+        v48 = v91;
+      }
+      sprintf(pTmpBuf, "%s ", pSkillNames[v64], v34, v48, v52, v56);
+LABEL_88:
+      pGUIWindow_CurrentMenu->DrawText(pFontLucida, 248, v27, v60, pTmpBuf, 0, 0, 0);
+      v28 = pGUIWindow_CurrentMenu;
+LABEL_89:
+      v29 = v68++ + 1;
+    }
+    ++v82;
+  }
+  while ( (signed int)v82 < (signed int)dword_4E2A2C );
+  if ( !v72 )
+  {
+    v27 = v27 + LOBYTE(pFontLucida->uFontHeight) - 3;
+    v28->DrawText(pFontLucida, 248, v27, 0, pGlobalTXT_LocalizationStrings[153], 0, 0, 0);
+  }
+  uYc = v27 + 2 * LOBYTE(pFontLucida->uFontHeight) - 10;
+  sprintf(pTmpBuf, "%s\r177%s", pGlobalTXT_LocalizationStrings[143], pGlobalTXT_LocalizationStrings[131]);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 248, uYc, a5, pTmpBuf, 0, 0, 0);
+  v36 = pGUIWindow_CurrentMenu;
+  v73 = 0;
+  v83 = dword_4E2A50;
+  do
+  {
+    v37 = 0;
+    v69 = 0;
+    v38 = (GUIButton *)*v83;
+    v65 = *v83;
+    while ( v69 < (signed int)v36->uNumControls )
+    {
+      v38 = v36->pControlsHead;
+      if ( v37 > 0 )
+      {
+        do
+        {
+          v38 = v38->pNext;
+          --v37;
+        }
+        while ( v37 );
+      }
+      v39 = v38->field_1C;
+      if ( SBYTE1(v39) >= 0 || (BYTE1(v39) &= 0x7Fu, v39 != v65) )
+        goto LABEL_119;
+      ++v73;
+      uYc = v38->uY;
+      v40 = pPlayer->pActiveSkills[v65];
+      v41 = pPlayer->uSkillPoints;
+      v42 = pPlayer->pActiveSkills[v65] & 0x3F;
+      v61 = 0;
+      if ( v41 >= v42 + 1 )
+        v61 = v84;
+      if ( v85 == v69 )
+      {
+        v13 = v41 < v42;
+        v14 = v41 == v42;
+        v43 = v86;
+        if ( !(v13 | v14) )
+          v43 = v79;
+        v61 = v43;
+      }
+      else
+      {
+        v43 = v61;
+      }
+      if ( HIBYTE(v40) & 1 )
+      {
+        if ( !v43 )
+          v43 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        v57 = v42;
+        v53 = v61;
+        v49 = pGlobalTXT_LocalizationStrings[96];
+      }
+      else
+      {
+        if ( !(v40 & 0xC0) )
+        {
+          sprintf(pTmpBuf, "%s\r177%2d", pSkillNames[v65], v42);
+          goto LABEL_118;
+        }
+        v25 = (v40 & 0x80u) != 0;
+        v44 = pGlobalTXT_LocalizationStrings[432];
+        if ( !v25 )
+          v44 = pGlobalTXT_LocalizationStrings[433];
+        v92 = v44;
+        if ( !v43 )
+          v43 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        v57 = v42;
+        v53 = v61;
+        v49 = v92;
+      }
+      sprintf(pTmpBuf, "%s ", pSkillNames[v65], v43, v49, v53, v57);
+LABEL_118:
+      LOBYTE(v38) = pGUIWindow_CurrentMenu->DrawText(pFontLucida, 248, uYc, v61, pTmpBuf, 0, 0, 0);
+      v36 = pGUIWindow_CurrentMenu;
+LABEL_119:
+      v37 = v69++ + 1;
+    }
+    ++v83;
+  }
+  while ( (signed int)v83 < (signed int)_4E2A80_skills );
+  if ( !v73 )
+    LOBYTE(v38) = v36->DrawText(
+                    pFontLucida,
+                    248,
+                    LOBYTE(pFontLucida->uFontHeight) + uYc - 3,
+                    0,
+                    pGlobalTXT_LocalizationStrings[153],
+                    0,
+                    0,
+                    0);
+  return (char)v38;
+}
+
+//----- (0041A000) --------------------------------------------------------
+unsigned int __fastcall CharacterUI_AwardsTab_Draw(unsigned int uPlayerID)
+{
+  unsigned int v1; // esi@1
+  unsigned int v2; // ebx@1
+  unsigned int v3; // eax@1
+  unsigned int result; // eax@1
+  int v5; // eax@15
+  char *v6; // ebx@15
+  int v7; // eax@23
+  int v8; // eax@24
+  int v9; // eax@25
+  int v10; // eax@27
+  int v11; // eax@32
+  int v12; // eax@33
+  int v13; // eax@34
+  signed int v14; // eax@43
+  unsigned int v15; // eax@43
+  int v16; // eax@43
+  int v17; // [sp-4h] [bp-D4h]@16
+  char Source[100]; // [sp+Ch] [bp-C4h]@1
+  GUIWindow a1; // [sp+70h] [bp-60h]@1
+  unsigned int v20; // [sp+C4h] [bp-Ch]@15
+  int v21; // [sp+C8h] [bp-8h]@14
+  int v22; // [sp+CCh] [bp-4h]@40
+
+  v1 = uPlayerID;
+  v2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v3 = pIcons_LOD->LoadTexture("fr_award", TEXTURE_16BIT_PALETTE);
+  pRenderer->DrawTextureIndexed(8u, 8u, (Texture *)(v3 != -1 ? (int)&pIcons_LOD->pTextures[v3] : 0));
+  sprintf(pTmpBuf, "%s ", pGlobalTXT_LocalizationStrings[23], v2);// TODO check args
+  sprintf(
+    Source,
+    pGlobalTXT_LocalizationStrings[429],
+    &stru_AA1058[3].pSounds[6972 * v1 + 40720],
+    pClassNames[stru_AA1058[3].pSounds[6972 * v1 + 40737]]);
+  strcat(pTmpBuf, Source);
+  strcat(pTmpBuf, "\xC" "00000");
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 24, 18, 0, pTmpBuf, 0, 0, 0);
+  result = dword_506528;
+  a1.uFrameX = 12;
+  a1.uFrameY = 48;
+  a1.uFrameWidth = 424;
+  a1.uFrameHeight = 290;
+  a1.uFrameZ = 435;
+  a1.uFrameW = 337;
+  if ( dword_506544 && dword_506520 + dword_506528 < dword_506524 )
+    result = dword_506528++ + 1;
+  if ( dword_506548 && result )
+  {
+    --result;
+    dword_506528 = result;
+  }
+  if ( dword_50651C < 0 )
+  {
+    result += dword_506520;
+    dword_506528 = result;
+    if ( (signed int)(dword_506520 + result) <= dword_506524 )
+      goto LABEL_14;
+    result = dword_506524 - dword_506520;
+    goto LABEL_13;
+  }
+  if ( dword_50651C > 0 )
+  {
+    result -= dword_506520;
+    dword_506528 = result;
+    if ( (result & 0x80000000u) != 0 )
+    {
+      result = 0;
+LABEL_13:
+      dword_506528 = result;
+      goto LABEL_14;
+    }
+  }
+LABEL_14:
+  dword_506544 = 0;
+  dword_506548 = 0;
+  dword_506520 = 0;
+  dword_50651C = 0;
+  v21 = result;
+  if ( (signed int)result < dword_506524 )
+  {
+    while ( 1 )
+    {
+      v5 = pStru179->field_0[v21];
+      v20 = 8 * pStru179->field_0[v21];
+      v6 = (char *)dword_723E80_award_related[v20 / 4];
+      if ( v5 != 1 )
+        break;
+      v17 = pParty->uFine;
+LABEL_42:
+      sprintf(pTmpBuf, v6, v17);
+      v6 = pTmpBuf;
+LABEL_43:
+      v14 = dword_723E84[v20 / 4];
+      ++dword_506520;
+      v15 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(
+              pAwardsTextColors[3 * v14 % 6],
+              pAwardsTextColors[3 * v14 % 6 + 1],
+              pAwardsTextColors[3 * v14 % 6 + 2]);
+      a1.DrawText(pFontArrus, 0, 0, v15, v6, 0, 0, 0);
+      v16 = pFontArrus->CalcTextHeight(v6, &a1, 0, 0);
+      result = v16 + a1.uFrameY + 4;
+      if ( (signed int)result <= (signed int)a1.uFrameHeight )
+      {
+        ++v21;
+        a1.uFrameY = result;
+        result = v21;
+        if ( v21 < dword_506524 )
+          continue;
+      }
+      return result;
+    }
+    if ( (v5 < 85 || v5 > 91) && (v5 < 103 || v5 > 104) )
+      goto LABEL_43;
+    if ( v5 > 89 )
+    {
+      v11 = v5 - 90;
+      if ( !v11 )
+      {
+        v10 = (unsigned __int8)pParty->uNumArenaKnightWins;
+        goto LABEL_40;
+      }
+      v12 = v11 - 1;
+      if ( !v12 )
+      {
+        v10 = (unsigned __int8)pParty->uNumArenaLordWins;
+        goto LABEL_40;
+      }
+      v13 = v12 - 12;
+      if ( !v13 )
+      {
+        v10 = pParty->field_874;
+        goto LABEL_40;
+      }
+      if ( v13 == 1 )
+      {
+        v10 = pParty->field_878;
+        goto LABEL_40;
+      }
+    }
+    else
+    {
+      if ( v5 == 89 )
+      {
+        v10 = (unsigned __int8)pParty->uNumArenaSquireWins;
+        goto LABEL_40;
+      }
+      v7 = v5 - 85;
+      if ( !v7 )
+      {
+        v10 = pParty->uNumDeaths;
+        goto LABEL_40;
+      }
+      v8 = v7 - 1;
+      if ( !v8 )
+      {
+        v10 = pParty->uNumBountiesCollected;
+        goto LABEL_40;
+      }
+      v9 = v8 - 1;
+      if ( !v9 )
+      {
+        v10 = pParty->uNumPrisonTerms;
+        goto LABEL_40;
+      }
+      if ( v9 == 1 )
+      {
+        v10 = (unsigned __int8)pParty->uNumArenaPageWins;
+LABEL_40:
+        v22 = v10;
+        goto LABEL_41;
+      }
+    }
+LABEL_41:
+    v17 = v22;
+    goto LABEL_42;
+  }
+  return result;
+}
+// 50651C: using guessed type int dword_50651C;
+// 506520: using guessed type int dword_506520;
+// 506524: using guessed type int dword_506524;
+// 506528: using guessed type int dword_506528;
+// 506544: using guessed type int dword_506544;
+// 506548: using guessed type int dword_506548;
+// 723E80: using guessed type int dword_723E80_award_related[];
+// 723E84: using guessed type int dword_723E84[];
+
+//----- (0041A2C1) --------------------------------------------------------
+unsigned int __fastcall GetSizeInInventorySlots(unsigned int uNumPixels)
+{
+  if ( (signed int)uNumPixels < 14 )
+    uNumPixels = 14;
+  return ((signed int)(uNumPixels - 14) >> 5) + 1;
+}
+
+//----- (0041A2D1) --------------------------------------------------------
+void __fastcall CharacterUI_InventoryTab_Draw(unsigned int uPlayerID, char a2)
+{
+  Player *v2; // esi@1
+  char v3; // bl@1
+  unsigned int v4; // eax@2
+  ItemGen *v5; // ebx@5
+  unsigned int v6; // eax@6
+  Texture *v7; // esi@6
+  __int16 v8; // ax@6
+  signed int v9; // edi@6
+  signed int v10; // ecx@6
+  signed int v11; // edx@6
+  signed int v12; // eax@11
+  int v13; // eax@13
+  signed int v14; // edx@13
+  int v15; // eax@13
+  unsigned int v16; // ebx@15
+  unsigned int v17; // edi@15
+  Texture *v18; // ebx@24
+  double v19; // st7@26
+  const char *v20; // [sp-8h] [bp-40h]@20
+  Player *v21; // [sp+14h] [bp-24h]@1
+  int uTextureId; // [sp+18h] [bp-20h]@6
+  int *v23; // [sp+1Ch] [bp-1Ch]@1
+  int v24; // [sp+20h] [bp-18h]@5
+  ItemGen *v25; // [sp+24h] [bp-14h]@5
+  int v26; // [sp+28h] [bp-10h]@3
+  signed int v27; // [sp+2Ch] [bp-Ch]@3
+  int a2a; // [sp+30h] [bp-8h]@5
+  int a3; // [sp+34h] [bp-4h]@5
+
+  v23 = pRenderer->pActiveZBuffer;
+  v2 = pPlayers[uPlayerID];
+  v3 = a2;
+  v21 = pPlayers[uPlayerID];
+  pRenderer->DrawTextureIndexed(
+    8u,
+    8u,
+    (Texture *)(uTextureID_507958 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507958] : 0));
+  if ( v3 )
+  {
+    v4 = pIcons_LOD->LoadTexture("fr_strip", TEXTURE_16BIT_PALETTE);
+    pRenderer->DrawTextureIndexed(8u, 0x131u, (Texture *)(v4 != -1 ? (int)&pIcons_LOD->pTextures[v4] : 0));
+  }
+  v27 = 0;
+  v26 = (int)v2->pInventoryIndices;
+  do
+  {
+    if ( *(int *)v26 > 0 )
+    {
+      v24 = *(int *)v26 - 1;
+      a3 = 32 * v27 / 14 + 17;
+      v5 = &v2->pInventoryItems[v24];
+      a2a = 32 * v27 % 14 + 14;
+      v25 = v5;
+      if ( v5->uItemID )
+      {
+        v6 = pIcons_LOD->LoadTexture(
+               pItemsTable->pItems[v5->uItemID].pIconName,
+               TEXTURE_16BIT_PALETTE);
+        uTextureId = v6;
+        v7 = (Texture *)(v6 != -1 ? (int)&pIcons_LOD->pTextures[v6] : 0);
+        v8 = (v6 != -1 ? pIcons_LOD->pTextures[v6].uTextureWidth : 24);
+        v9 = v7->uTextureHeight;
+        v10 = v7->uTextureWidth;
+        v11 = v7->uTextureWidth;
+        if ( v10 < 14 )
+          v11 = 14;
+        if ( (v11 - 14) >> 5 == 0 && v8 < 32 )
+          a2a += (32 - v10) / 2;
+        v12 = v7->uTextureWidth;
+        if ( v10 < 14 )
+          v12 = 14;
+        v13 = v12 - 14;
+        v14 = v7->uTextureHeight;
+        LOBYTE(v13) = v13 & 0xE0;
+        v15 = v13 + 32;
+        if ( v9 < 14 )
+          v14 = 14;
+        v16 = v5->uAttributes;
+        v17 = a2a + ((v15 - v10) >> 1) + pSRZBufferLineOffsets[a3 + ((((v14 - 14) & 0xFFFFFFE0) - v9 + 32) >> 1)];
+        if ( !(v16 & 0xF0) )
+        {
+          if ( v16 & 1
+            || pCurrentScreen != 13 )
+          {
+            if ( v16 & 2 )
+              pRenderer->_4A6776(a2a, a3, v7);
+            else
+              pRenderer->DrawTextureTransparent(a2a, a3, v7);
+          }
+          else
+          {
+            pRenderer->DrawTransparentGreenShade(a2a, a3, v7);
+          }
+          goto LABEL_33;
+        }
+        if ( (unsigned __int8)(v16 & 0xF0) != 16 )
+        {
+          if ( (unsigned __int8)(v16 & 0xF0) == 32 )
+          {
+            v20 = "sp28a";
+            goto LABEL_24;
+          }
+          if ( (unsigned __int8)(v16 & 0xF0) == 64 )
+          {
+            v20 = "sp30a";
+            goto LABEL_24;
+          }
+          if ( (unsigned __int8)(v16 & 0xF0) == 128 )
+          {
+            v20 = "sp91a";
+LABEL_24:
+            v18 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v20, TEXTURE_16BIT_PALETTE)];
+            dword_50C9A8 -= pEventTimer->uTimeElapsed;
+            if ( dword_50C9A8 <= 0 )
+            {
+              dword_50C9A8 = 0;
+              LOBYTE(v25->uAttributes) &= 0xFu;
+              ptr_50C9A4 = 0;
+            }
+            v19 = (double)GetTickCount() * 0.1;
+            pRenderer->_4A63E6(a2a, a3, v7, v18, (signed __int64)v19, 0, 255);
+LABEL_33:
+            ZBuffer_Fill(&v23[v17], uTextureId, v24 + 1);
+            v2 = v21;
+            goto LABEL_34;
+          }
+        }
+        v20 = "sptext01";
+        goto LABEL_24;
+      }
+    }
+LABEL_34:
+    ++v27;
+    v26 += 4;
+  }
+  while ( v27 < 126 );
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+// 507958: using guessed type int uTextureID_507958;
+// 50C9A8: using guessed type int dword_50C9A8;
+
+//----- (0041A556) --------------------------------------------------------
+void __cdecl draw_leather()
+{
+  pRenderer->DrawTextureIndexed(
+    8u,
+    8u,
+    (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0));
+}
+
+//----- (0041A57E) --------------------------------------------------------
+char __cdecl QuickRefDraw()
+{
+  unsigned int v0; // ebx@1
+  unsigned int v1; // eax@1
+  Player *pPlayer; // ebp@2
+  int v3; // eax@6
+  int v4; // edi@6
+  unsigned int v5; // eax@7
+  unsigned int v6; // edi@9
+  unsigned int v7; // edi@11
+  signed int v8; // eax@13
+  unsigned int v9; // eax@13
+  unsigned int v10; // edi@13
+  int v11; // eax@15
+  unsigned int v12; // eax@15
+  unsigned int v13; // edi@15
+  int v14; // eax@17
+  int v15; // ST18_4@17
+  int v16; // ebx@17
+  int v17; // eax@17
+  unsigned int v18; // eax@17
+  unsigned int v19; // edi@17
+  int v20; // eax@19
+  unsigned int v21; // edi@19
+  char *v22; // eax@21
+  unsigned int v23; // edi@21
+  int v24; // eax@23
+  unsigned int v25; // edi@23
+  char *v26; // eax@25
+  unsigned int v27; // edi@25
+  int v28; // ecx@27
+  char *v29; // eax@27
+  signed int v30; // edx@27
+  unsigned int v31; // edi@31
+  unsigned int v32; // edi@33
+  const char *v33; // ST10_4@35
+  unsigned int v34; // eax@35
+  unsigned int v35; // edi@35
+  unsigned __int8 v36; // al@37
+  char *v37; // eax@38
+  int v38; // eax@41
+  signed int v39; // edi@42
+  char *v40; // eax@45
+  unsigned int v41; // eax@45
+  signed int v43; // [sp+10h] [bp-1Ch]@1
+  unsigned int v44; // [sp+14h] [bp-18h]@2
+  int v45; // [sp+18h] [bp-14h]@1
+  unsigned int v46; // [sp+1Ch] [bp-10h]@1
+  unsigned int v47; // [sp+20h] [bp-Ch]@1
+  unsigned int v48; // [sp+24h] [bp-8h]@33
+  unsigned int v49; // [sp+28h] [bp-4h]@1
+
+  v0 = 0;
+  v47 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v49 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0, 0);
+  v46 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0);
+  v1 = pIcons_LOD->LoadTexture("quikref", TEXTURE_16BIT_PALETTE);
+  pRenderer->DrawTextureIndexed(8u, 8u, (Texture *)(v1 != -1 ? (int)&pIcons_LOD->pTextures[v1] : 0));
+  v43 = 0;
+  v45 = LOBYTE(pFontArrus->uFontHeight) + 1;
+  do
+  {
+    pPlayer = &pParty->pPlayers[v43];
+    v44 = 94 * v43 + 89;
+    if ( v43 == v0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        0x12u,
+        v0,
+        pGlobalTXT_LocalizationStrings[149],
+        60,
+        v0);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 94 * v43 + 89, 0x12u, v47, pPlayer->pName, 84, v0);
+    if ( v43 == v0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        0x2Fu,
+        v0,
+        pGlobalTXT_LocalizationStrings[131],
+        60,
+        v0);
+    v3 = pPlayer->GetActualLevel();
+    sprintf(pTmpBuf, "%lu", v3);
+    v4 = pPlayer->GetBaseLevel();
+    if ( pPlayer->GetActualLevel() <= v4 )
+      v5 = pPlayer->GetExperienceDisplayColor();
+    else
+      v5 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, v0);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, 0x2Fu, v5, pTmpBuf, 84, v0);
+    v6 = v45 + 47;
+    if ( v43 == v0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v45 + 47,
+        v0,
+        pGlobalTXT_LocalizationStrings[41],
+        60,
+        v0);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v6, v0, pClassNames[pPlayer->uClass], 84, v0);
+    v7 = v45 + v6;
+    if ( v43 == v0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v7,
+        v0,
+        pGlobalTXT_LocalizationStrings[107],
+        60,
+        v0);
+    sprintf(pTmpBuf, "%d", pPlayer->sHealth);
+    v8 = pPlayer->GetMaxHealth();
+    v9 = UI_GetHealthManaStringColor(pPlayer->sHealth, v8);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v7, v9, pTmpBuf, 84, v0);
+    v10 = v45 + v7;
+    if ( v43 == v0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v10,
+        v0,
+        pGlobalTXT_LocalizationStrings[209],
+        60,
+        v0);
+    sprintf(pTmpBuf, "%d", pPlayer->sMana);
+    v11 = pPlayer->GetMaxMana();
+    v12 = UI_GetHealthManaStringColor(pPlayer->sMana, v11);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v10, v12, pTmpBuf, 84, v0);
+    v13 = v45 + v10;
+    if ( v43 == v0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v13,
+        v0,
+        pGlobalTXT_LocalizationStrings[0],
+        60,
+        v0);
+    v14 = pPlayer->GetActualAC();
+    sprintf(pTmpBuf, "%d", v14);
+    v15 = v0;
+    v16 = pPlayer->GetBaseAC();
+    v17 = pPlayer->GetActualAC();
+    v18 = UI_GetHealthManaStringColor(v17, v16);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v13, v18, pTmpBuf, 84, v15);
+    v0 = 0;
+    v19 = v45 + v13;
+    if ( !v43 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v19,
+        0,
+        pGlobalTXT_LocalizationStrings[18],
+        60,
+        0);
+    v20 = pPlayer->GetActualAttack(0);
+    sprintf(pTmpBuf, "%+d", v20);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v19, 0, pTmpBuf, 84, 0);
+    v21 = v45 + v19;
+    if ( !v43 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v21,
+        0,
+        pGlobalTXT_LocalizationStrings[66],
+        60,
+        0);
+    v22 = pPlayer->GetMeleeDamageString();
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v21, 0, v22, 84, 0);
+    v23 = v45 + v21;
+    if ( !v43 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v23,
+        0,
+        pGlobalTXT_LocalizationStrings[203],
+        60,
+        0);
+    v24 = pPlayer->GetRangedAttack();
+    sprintf(pTmpBuf, "%+d", v24);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v23, 0, pTmpBuf, 84, 0);
+    v25 = v45 + v23;
+    if ( !v43 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v25,
+        0,
+        pGlobalTXT_LocalizationStrings[66],
+        60,
+        0);
+    v26 = pPlayer->GetRangedDamageString();
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v25, 0, v26, 84, 0);
+    v27 = v45 + v25;
+    if ( !v43 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v27,
+        0,
+        pGlobalTXT_LocalizationStrings[205],
+        60,
+        0);
+    v28 = 0;
+    v29 = (char *)pPlayer->pActiveSkills;
+    v30 = 36;
+    do
+    {
+      if ( *(short *)v29 )
+        ++v28;
+      v29 += 2;
+      --v30;
+    }
+    while ( v30 );
+    sprintf(pTmpBuf, "%lu", v28);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v27, 0, pTmpBuf, 84, 0);
+    v31 = v45 + v27;
+    if ( !v43 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v31,
+        0,
+        pGlobalTXT_LocalizationStrings[168],
+        60,
+        0);
+    sprintf(pTmpBuf, "%lu", pPlayer->uSkillPoints);
+    pGUIWindow_CurrentMenu->DrawTextInRect(
+      pFontArrus,
+      v44,
+      v31,
+      pPlayer->uSkillPoints != 0 ? v46 : 0,
+      pTmpBuf,
+      84,
+      0);
+    v32 = v45 + v31;
+    v48 = pPlayer->GetMajorConditionIdx();
+    if ( !v43 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v32,
+        0,
+        pGlobalTXT_LocalizationStrings[45],
+        60,
+        0);
+    v33 = aCharacterConditionNames[v48];
+    v34 = GetConditionDrawColor(v48);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v32, v34, v33, 84, 0);
+    v35 = v45 + v32;
+    if ( !v43 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(
+        pFontArrus,
+        0x16u,
+        v35,
+        0,
+        pGlobalTXT_LocalizationStrings[170],
+        60,
+        0);
+    v36 = pPlayer->uQuickSpell;
+    if ( v36 )
+      v37 = pSpellStats->pInfos[v36].pShortName;
+    else
+      v37 = pGlobalTXT_LocalizationStrings[153];
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, v44, v35, 0, v37, 84, 0);
+    ++v43;
+  }
+  while ( v43 < 4 );
+  v38 = GetPartyReputation();
+  if ( v38 >= 0 )
+  {
+    v39 = v49;
+    if ( v38 <= 5 )
+      v39 = 65535;
+  }
+  else
+  {
+    v39 = v46;
+  }
+  v40 = GetReputationString(v38);
+  sprintf(pTmpBuf, "%s: ", pGlobalTXT_LocalizationStrings[180], v39, v40);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 22, 323, 0, pTmpBuf, 0, 0, 0);
+  v41 = pParty->GetPartyFame();
+  sprintf(pTmpBuf, "\r261%s: %d", pGlobalTXT_LocalizationStrings[84], v41);// Fame
+  return pGUIWindow_CurrentMenu->DrawText(pFontArrus, 0, 323, 0, pTmpBuf, 0, 0, 0);
+}
+
+//----- (0041ABFD) --------------------------------------------------------
+void __thiscall CharacterUI_CharacterScreen_Draw(unsigned int uPlayerIdx)
+{
+  unsigned int v1; // edi@1
+  unsigned int v2; // eax@6
+  Texture *v3; // ecx@6
+  GUIButton *v4; // eax@6
+  unsigned int v5; // eax@7
+  unsigned int v6; // eax@10
+  unsigned int v7; // eax@11
+
+  v1 = uPlayerIdx;
+  if ( uPlayerIdx )
+  {
+    pRenderer->ClearZBuffer(0, 479);
+    switch ( pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] )
+    {
+      case 0x64:                                // stats
+        sub_4196A0();
+        sub_419379();
+        CharacterUI_StatsTab_Draw(v1);
+        v7 = pIcons_LOD->LoadTexture("ib-cd1-d", TEXTURE_16BIT_PALETTE);
+        v3 = (Texture *)(v7 != -1 ? (int)&pIcons_LOD->pTextures[v7] : 0);
+        v4 = pCharacterScreen_StatsBtn;
+        break;
+      case 0x65:                                // skills
+        if ( dword_507CC0 != uActiveCharacter )
+        {
+          sub_4196A0();
+          sub_419401();
+        }
+        sub_419379();
+        CharacterUI_SkillsTab_Draw(v1);
+        v6 = pIcons_LOD->LoadTexture("ib-cd2-d", TEXTURE_16BIT_PALETTE);
+        v3 = (Texture *)(v6 != -1 ? (int)&pIcons_LOD->pTextures[v6] : 0);
+        v4 = pCharacterScreen_SkillsBtn;
+        break;
+      case 0x66:                                // awards
+        sub_4196A0();
+        sub_419379();
+        sub_419220();
+        CharacterUI_AwardsTab_Draw(v1);
+        v5 = pIcons_LOD->LoadTexture("ib-cd4-d", TEXTURE_16BIT_PALETTE);
+        v3 = (Texture *)(v5 != -1 ? (int)&pIcons_LOD->pTextures[v5] : 0);
+        v4 = pCharacterScreen_AwardsBtn;
+        break;
+      default:
+        if ( pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] != 103 )
+          goto LABEL_13;
+        sub_4196A0();
+        sub_419379();
+        CharacterUI_InventoryTab_Draw(v1, 0);
+        v2 = pIcons_LOD->LoadTexture("ib-cd3-d", TEXTURE_16BIT_PALETTE);
+        v3 = (Texture *)(v2 != -1 ? (int)&pIcons_LOD->pTextures[v2] : 0);
+        v4 = pCharacterScreen_InventoryBtn;
+        break;
+    }
+    pRenderer->DrawTextureIndexed(v4->uX, v4->uY, v3);
+LABEL_13:
+    if ( bRingsShownInCharScreen )
+      CharacterUI_DrawPaperdollWithRingOverlay(v1);
+    else
+      CharacterUI_DrawPaperdoll(v1);
+  }
+}
+// 507CC0: using guessed type int dword_507CC0;
+// 5118E0: using guessed type int bRingsShownInCharScreen;
+
+//----- (0041AD6E) --------------------------------------------------------
+void __cdecl GameUI_DrawRightPanelItems()
+{
+  if ( (signed int)((pParty->uTimePlayed - qword_507CC8) >> 32) <= 0
+    && (((pParty->uTimePlayed - qword_507CC8) >> 32) & 0x80000000u) != 0i64 )
+    qword_507CC8 = 0i64;
+  if ( (((pParty->uTimePlayed - qword_507CC8) >> 32) & 0x80000000u) == 0i64
+    && (!(SHIDWORD(pParty->uTimePlayed) < (LODWORD(pParty->uTimePlayed) < (unsigned int)qword_507CC8)
+                                       + HIDWORD(qword_507CC8) | (pParty->uTimePlayed - qword_507CC8) >> 32 == 0)
+     || (unsigned int)(LODWORD(pParty->uTimePlayed) - qword_507CC8) > 0x80) )
+  {
+    qword_507CC8 = pParty->uTimePlayed;
+    byte_50697C = byte_50697C == 0;
+    if ( byte_50697C
+      && pCurrentScreen != 5 )
+    {
+      if ( bFlashQuestBook )
+        pRenderer->DrawTextureTransparent(
+          493u,
+          355u,
+          (Texture *)(uTextureID_ib_td1_A != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_ib_td1_A] : 0));
+      if ( bFlashAutonotesBook )
+        pRenderer->DrawTextureTransparent(
+          527u,
+          353u,
+          (Texture *)(uTextureID_ib_td2_A != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_ib_td2_A] : 0));
+      if ( bFlashHistoryBook )
+        pRenderer->DrawTextureTransparent(
+          600u,
+          361u,
+          (Texture *)(uTextureID_ib_td5_A != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_ib_td5_A] : 0));
+    }
+    else
+    {
+      pRenderer->DrawTextureRGB(468u, 0, pTexture_RightFrame);
+      DrawHiredNPCs();
+    }
+  }
+}
+
+//----- (0041AEBB) --------------------------------------------------------
+void __cdecl GameUI_DrawFoodAndGold()
+{
+  unsigned int v0; // ebx@2
+  unsigned int v1; // ebp@2
+  int v2; // esi@2
+
+  if ( uGameState != GAME_STATE_FINAL_WINDOW )
+  {
+    v0 = uGameUIFontMain;
+    v1 = uGameUIFontShadow;
+    v2 = sub_44100D() != 0 ? 381 : 322;
+    sprintf(pTmpBuf, "\r087%lu", pParty->uNumFoodRations);
+    pPrimaryWindow->DrawText(pFontSmallnum, 0, v2, v0, pTmpBuf, 0, 0, v1);
+    sprintf(pTmpBuf, "\r028%lu", pParty->uNumGold);
+    pPrimaryWindow->DrawText(pFontSmallnum, 0, v2, v0, pTmpBuf, 0, 0, v1);
+  }
+}
+
+//----- (0041AF52) --------------------------------------------------------
+void Actor::DrawHealthBar(Actor *a1, GUIWindow *a2)
+{
+  unsigned int v2; // eax@1
+  GUIWindow *v3; // edi@1
+  unsigned int v4; // esi@1
+  signed int v5; // ebx@4
+  double v6; // st7@5
+  unsigned int v7; // eax@6
+  unsigned int v8; // ebx@10
+  unsigned int v9; // [sp+14h] [bp-Ch]@4
+  unsigned int v10; // [sp+1Ch] [bp-4h]@4
+
+  v2 = a1->pMonsterInfo.uHP;
+  v3 = a2;
+  v4 = 25;
+  if ( (signed int)v2 > 25 )
+  {
+    v4 = 200;
+    if ( (signed int)v2 < 200 )
+      v4 = a1->pMonsterInfo.uHP;
+  }
+  v5 = a1->sCurrentHP;
+  v10 = v4;
+  v9 = uTextureID_mhp_grn;
+  if ( v5 < (signed int)v2 )
+  {
+    v6 = (double)(signed int)v2;
+    v10 = (signed __int64)((double)(signed int)v4 / (double)(signed int)v2 * (double)a1->sCurrentHP);
+    if ( v5 <= (signed int)(signed __int64)(0.34 * v6) )
+    {
+      v7 = uTextureID_mhp_red;
+LABEL_9:
+      v9 = v7;
+      goto LABEL_10;
+    }
+    if ( v5 <= (signed int)(signed __int64)(v6 * 0.67) )
+    {
+      v7 = uTextureID_mhp_yel;
+      goto LABEL_9;
+    }
+  }
+LABEL_10:
+  v8 = a2->uFrameX + (signed int)(a2->uFrameWidth - v4) / 2;
+  pRenderer->Clip(v8, a2->uFrameY + 32, v8 + v4, a2->uFrameY + 52);
+  pRenderer->DrawTextureIndexed(
+    v8,
+    v3->uFrameY + 32,
+    (Texture *)(uTextureID_mhp_bd != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_mhp_bd] : 0));
+  pRenderer->Clip(v8, v3->uFrameY + 32, v8 + v10, v3->uFrameY + 52);
+  pRenderer->DrawTextureIndexed(
+    v8,
+    v3->uFrameY + 34,
+    (Texture *)(v9 != -1 ? (int)&pIcons_LOD->pTextures[v9] : 0));
+  pRenderer->ResetClip();
+  pRenderer->DrawTextureIndexed(
+    v8 - 5,
+    v3->uFrameY + 32,
+    (Texture *)(uTextureID_mhp_capl != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_mhp_capl] : 0));
+  pRenderer->DrawTextureIndexed(
+    v8 + v4,
+    v3->uFrameY + 32,
+    (Texture *)(uTextureID_mhp_capr != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_mhp_capr] : 0));
+}
+
+//----- (0041B0C9) --------------------------------------------------------
+void __cdecl GameUI_DrawLifeManaBars()
+{
+  Texture *v0; // ebx@1
+  Player *v1; // ecx@2
+  float v2; // ST38_4@3
+  double v3; // st7@3
+  signed __int64 v4; // qax@6
+  Player *v5; // ecx@24
+  float v6; // ST30_4@25
+  double v7; // st7@25
+  bool v8; // ST38_4@27
+  Texture *v9; // [sp-4h] [bp-30h]@10
+  Texture *v10; // [sp+Ch] [bp-20h]@1
+  Player *v11; // [sp+10h] [bp-1Ch]@2
+  int v12; // [sp+10h] [bp-1Ch]@24
+  Texture *v13; // [sp+14h] [bp-18h]@1
+  Texture *v14; // [sp+18h] [bp-14h]@1
+  float v15; // [sp+1Ch] [bp-10h]@1
+  signed int v16; // [sp+24h] [bp-8h]@1
+  signed int v17; // [sp+28h] [bp-4h]@8
+
+  v0 = (Texture *)(uTextureID_BarGreen != -1 ? &pIcons_LOD->pTextures[uTextureID_BarGreen] : 0);
+  v14 = (Texture *)(uTextureID_BarYellow != -1 ? &pIcons_LOD->pTextures[uTextureID_BarYellow] : 0);
+  v13 = (Texture *)(uTextureID_BarRed != -1 ? &pIcons_LOD->pTextures[uTextureID_BarRed] : 0);
+  v16 = 0;
+  v10 = (Texture *)(uTextureID_BarBlue != -1 ? &pIcons_LOD->pTextures[uTextureID_BarBlue] : 0);
+  v15 = (double)(uTextureID_BarGreen != -1 ? pIcons_LOD->pTextures[uTextureID_BarGreen].uTextureHeight : 26);
+  do
+  {
+    v1 = &pParty->pPlayers[v16];
+    v11 = v1;
+    if ( v1->sHealth <= 0 )
+      goto LABEL_24;
+    v11 = &pParty->pPlayers[v16];
+    v2 = (double)v1->sHealth;
+    v3 = v2 / (double)v1->GetMaxHealth();
+    if ( v3 <= 0.5 )
+    {
+      if ( v3 <= 0.25 )
+      {
+        if ( v3 <= 0.0 )
+          goto LABEL_24;
+        if ( v16 == 2 || v16 == 3 )
+          v17 = 2;
+        else
+          v17 = 0;
+        pRenderer->Clip(
+          v17 + pHealthBarPos[v16],
+          (unsigned __int64)(signed __int64)((1.0 - v3) * v15) + 402,
+          v17 + pHealthBarPos[v16] + v13->uTextureWidth,
+          v13->uTextureHeight + 402);
+        v9 = v13;
+      }
+      else
+      {
+        if ( v16 == 2 || v16 == 3 )
+          v17 = 2;
+        else
+          v17 = 0;
+        pRenderer->Clip(
+          v17 + pHealthBarPos[v16],
+          (unsigned __int64)(signed __int64)((1.0 - v3) * v15) + 402,
+          v17 + pHealthBarPos[v16] + v14->uTextureWidth,
+          v14->uTextureHeight + 402);
+        v9 = v14;
+      }
+    }
+    else
+    {
+      if ( v3 > 1.0 )
+        v3 = 1.0;
+      v4 = (signed __int64)((1.0 - v3) * v15);
+      if ( v16 == 2 || v16 == 3 )
+        v17 = 2;
+      else
+        v17 = 0;
+      pRenderer->Clip(
+        v17 + pHealthBarPos[v16],
+        v4 + 402,
+        v17 + pHealthBarPos[v16] + v0->uTextureWidth,
+        v0->uTextureHeight + 402);
+      v9 = v0;
+    }
+    pRenderer->DrawTextureIndexed(v17 + pHealthBarPos[v16], 0x192u, v9);
+    pRenderer->ResetClip();
+LABEL_24:
+    v5 = v11;
+    v12 = v11->sMana;
+    if ( v12 > 0 )
+    {
+      v6 = (double)v12;
+      v7 = v6 / (double)v5->GetMaxMana();
+      if ( v7 > 1.0 )
+        v7 = 1.0;
+      v8 = v16 == 2;
+      pRenderer->Clip(
+        (v16 == 2) + pManaBarPos[v16],
+        (unsigned __int64)(signed __int64)((1.0 - v7) * v15) + 402,
+        v8 + pManaBarPos[v16] + v10->uTextureWidth,
+        v10->uTextureHeight + 402);
+      pRenderer->DrawTextureIndexed(v8 + pManaBarPos[v16], 0x192u, v10);
+      pRenderer->ResetClip();
+    }
+    ++v16;
+  }
+  while ( v16 < 4 );
+}
+
+//----- (0041B3B6) --------------------------------------------------------
+void __cdecl draw_right_panel()
+{
+  pRenderer->DrawTextureTransparent(
+    pViewport->uViewportZ,
+    0,
+    (Texture *)(uTextureID_right_panel != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_right_panel] : 0));
+}
+
+//----- (0041B3E2) --------------------------------------------------------
+void __cdecl GameUI_DrawRightPanelFrames()
+{
+  pRenderer->DrawTextureRGB(0, 0, pTexture_TopFrame);
+  pRenderer->DrawTextureRGB(0, 8u, pTexture_LeftFrame);
+  pRenderer->DrawTextureRGB(468u, 0, pTexture_RightFrame);
+  pRenderer->DrawTextureRGB(0, 352u, pTexture_BottomFrame);
+  GameUI_DrawFoodAndGold();
+  GameUI_DrawRightPanelItems();
+}
+
+//----- (0041B438) --------------------------------------------------------
+GUIButton *__fastcall GUI_HandleHotkey(unsigned __int8 uHotkey)
+{
+  char v1; // al@1
+  int v2; // esi@1
+  char v3; // dl@1
+  GUIWindow *v4; // ecx@2
+  GUIButton *result; // eax@2
+  int v6; // edx@12
+
+  v1 = toupper(uHotkey);
+  v2 = uNumVisibleWindows;
+  v3 = v1;
+  if ( uNumVisibleWindows >= 0 )
+  {
+    while ( 2 )
+    {
+      v4 = &pWindowList[pVisibleWindowsIdxs[v2] - 1];
+      for ( result = v4->pControlsHead; result; result = result->pNext )
+      {
+        if ( result->uHotkey == v3 )
+        {
+          v6 = result->uControlParam;
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+          {
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)result->uControlID;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v6;
+            *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+          return result;
+        }
+      }
+      if ( v4->uFrameX || v4->uFrameY || !(v4->uFrameWidth == 640 & v4->uFrameHeight == 480) )
+      {
+        --v2;
+        if ( v2 >= 0 )
+          continue;
+      }
+      break;
+    }
+  }
+  return 0;
+}
+// 5075E0: using guessed type int pVisibleWindowsIdxs[20];
+
+//----- (0041B4E1) --------------------------------------------------------
+int __fastcall GUI_ReplaceHotkey(unsigned __int8 uOldHotkey, unsigned __int8 uNewHotkey, char bFirstCall)
+{
+  unsigned __int8 v3; // bl@1
+  int result; // eax@1
+  int i; // edx@2
+  GUIButton *j; // ecx@3
+  int k; // edx@7
+  GUIButton *l; // ecx@8
+  unsigned __int8 v9; // [sp+4h] [bp-8h]@1
+  char v10; // [sp+8h] [bp-4h]@1
+
+  v3 = uNewHotkey;
+  v10 = toupper(uOldHotkey);
+  result = toupper(v3);
+  v9 = result;
+  if ( bFirstCall )
+  {
+    for ( i = uNumVisibleWindows; i >= 0; --i )
+    {
+      result = 84 * pVisibleWindowsIdxs[i];
+      //for ( j = *(GUIButton **)((char *)pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_ + result); j; j = j->pNext )
+      for ( j = pWindowList[pVisibleWindowsIdxs[i] - 1].pControlsHead; j; j = j->pNext )
+        j->field_28 = 0;
+    }
+  }
+  for ( k = uNumVisibleWindows; k >= 0; --k )
+  {
+    result = 84 * pVisibleWindowsIdxs[k];
+    //for ( l = *(GUIButton **)((char *)pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_ + result); l; l = l->pNext )
+    for ( l = pWindowList[pVisibleWindowsIdxs[k] - 1].pControlsHead; l; l = l->pNext )
+    {
+      LOBYTE(result) = v10;
+      if ( l->uHotkey == v10 )
+      {
+        if ( !l->field_28 )
+        {
+          LOBYTE(result) = v9;
+          l->field_28 = 1;
+          l->uHotkey = v9;
+        }
+      }
+    }
+  }
+  return result;
+}
+// 5075E0: using guessed type int pVisibleWindowsIdxs[20];
+
+//----- (0041B578) --------------------------------------------------------
+void __cdecl MainMenuUI_LoadFontsAndSomeStuff()
+{
+  pIcons_LOD->SetupPalettes(pRenderer->uTargetRBits,
+    pRenderer->uTargetGBits,
+    pRenderer->uTargetBBits);
+  pPaletteManager->SetColorChannelInfo(pRenderer->uTargetRBits,
+    pRenderer->uTargetGBits,
+    pRenderer->uTargetBBits);
+  pPaletteManager->RecalculateAll();
+
+  for (uint i = 0; i < 480; ++i)
+    pSRZBufferLineOffsets[i] = 640 * i;
+
+  pRenderer->ResetClip();
+
+  uTextureID_FONTPAL = pIcons_LOD->LoadTexture("FONTPAL", TEXTURE_16BIT_PALETTE);
+  pFontArrus = LoadFont("arrus.fnt", "FONTPAL", 0);
+  pFontLucida = LoadFont("lucida.fnt", "FONTPAL", 0);
+  pFontCreate = LoadFont("create.fnt", "FONTPAL", 0);
+  pFontSmallnum = LoadFont("smallnum.fnt", "FONTPAL", 0);
+  pFontComic = LoadFont("comic.fnt", "FONTPAL", 0);
+  pFontArrus->field_3 = 0;
+  pFontLucida->field_3 = 0;
+  pFontCreate->field_3 = 0;
+
+  for (uint i = 0; i < 20; ++i)
+    pWindowList[i].eWindowType = WINDOW_null;
+
+  uNumVisibleWindows = -1;
+  memset(pVisibleWindowsIdxs, 0, sizeof(pVisibleWindowsIdxs));
+}
+
+//----- (0041B690) --------------------------------------------------------
+void __cdecl MainMenuUI_Create()
+{
+  unsigned int v0; // eax@1
+  unsigned int v1; // eax@1
+  unsigned int v2; // eax@1
+  unsigned int v3; // eax@1
+  unsigned int v4; // eax@1
+  unsigned int v5; // eax@1
+  Texture *v6; // ST78_4@1
+  const char *v7; // ST5C_4@1
+  unsigned __int8 v8; // al@1
+  //Texture *v9; // ST60_4@1
+  Texture *v10; // ST78_4@1
+  const char *v11; // ST5C_4@1
+  unsigned __int8 v12; // al@1
+  //Texture *v13; // ST60_4@1
+  unsigned int v14; // eax@1
+  Texture *v15; // ST78_4@1
+  const char *v16; // ST5C_4@1
+  unsigned __int8 v17; // al@1
+  //Texture *v18; // ST60_4@1
+  unsigned int uTextureID_ib_td4_A; // eax@1
+  Texture *v20; // ST78_4@1
+  const char *v21; // ST5C_4@1
+  unsigned __int8 v22; // al@1
+  //Texture *v23; // ST60_4@1
+  Texture *v24; // eax@1
+  Texture *v25; // esi@1
+  Texture *v26; // ST60_4@1
+  const char *v27; // ST5C_4@1
+  unsigned __int8 v28; // al@1
+  Texture *v29; // eax@1
+  Texture *v30; // esi@1
+  Texture *v31; // ST60_4@1
+  const char *v32; // ST5C_4@1
+  unsigned __int8 v33; // al@1
+
+  v0 = pIconsFrameTable->FindIcon("wizeyeC");
+  pIconsFrameTable->InitializeAnimation(v0);
+  v1 = pIconsFrameTable->FindIcon("wizeyeB");
+  pIconsFrameTable->InitializeAnimation(v1);
+  v2 = pIconsFrameTable->FindIcon("wizeyeA");
+  pIconsFrameTable->InitializeAnimation(v2);
+  v3 = pIconsFrameTable->FindIcon("torchC");
+  pIconsFrameTable->InitializeAnimation(v3);
+  v4 = pIconsFrameTable->FindIcon("torchB");
+  pIconsFrameTable->InitializeAnimation(v4);
+  v5 = pIconsFrameTable->FindIcon("torchA");
+  pIconsFrameTable->InitializeAnimation(v5);
+  pTextureIDs_pMapDirs[0] = pIcons_LOD->LoadTexture("MAPDIR8", TEXTURE_16BIT_PALETTE);
+  pTextureIDs_pMapDirs[1] = pIcons_LOD->LoadTexture("MAPDIR1", TEXTURE_16BIT_PALETTE);
+  pTextureIDs_pMapDirs[2] = pIcons_LOD->LoadTexture("MAPDIR2", TEXTURE_16BIT_PALETTE);
+  pTextureIDs_pMapDirs[3] = pIcons_LOD->LoadTexture("MAPDIR3", TEXTURE_16BIT_PALETTE);
+  pTextureIDs_pMapDirs[4] = pIcons_LOD->LoadTexture("MAPDIR4", TEXTURE_16BIT_PALETTE);
+  pTextureIDs_pMapDirs[5] = pIcons_LOD->LoadTexture("MAPDIR5", TEXTURE_16BIT_PALETTE);
+  pTextureIDs_pMapDirs[6] = pIcons_LOD->LoadTexture("MAPDIR6", TEXTURE_16BIT_PALETTE);
+  pTextureIDs_pMapDirs[7] = pIcons_LOD->LoadTexture("MAPDIR7", TEXTURE_16BIT_PALETTE);
+  uTextureID_BarBlue = pIcons_LOD->LoadTexture("ib-statB", TEXTURE_16BIT_PALETTE);
+  uTextureID_BarGreen = pIcons_LOD->LoadTexture("ib-statG", TEXTURE_16BIT_PALETTE);
+  uTextureID_BarYellow = pIcons_LOD->LoadTexture("ib-statY", TEXTURE_16BIT_PALETTE);
+  uTextureID_BarRed = pIcons_LOD->LoadTexture("ib-statR", TEXTURE_16BIT_PALETTE);
+  uTextureID_mhp_bd = pIcons_LOD->LoadTexture("mhp_bg", TEXTURE_16BIT_PALETTE);
+  uTextureID_mhp_capl = pIcons_LOD->LoadTexture("mhp_capl", TEXTURE_16BIT_PALETTE);
+  uTextureID_mhp_capr = pIcons_LOD->LoadTexture("mhp_capr", TEXTURE_16BIT_PALETTE);
+  uTextureID_mhp_grn = pIcons_LOD->LoadTexture("mhp_grn", TEXTURE_16BIT_PALETTE);
+  uTextureID_mhp_red = pIcons_LOD->LoadTexture("mhp_red", TEXTURE_16BIT_PALETTE);
+  uTextureID_mhp_yel = pIcons_LOD->LoadTexture("mhp_yel", TEXTURE_16BIT_PALETTE);
+  uTextureID_Leather = pIcons_LOD->LoadTexture("LEATHER", TEXTURE_16BIT_PALETTE);
+  pTexture_Leather = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("ibground", TEXTURE_16BIT_PALETTE)];
+  uTextureID_x_x_u = pIcons_LOD->LoadTexture("x_x_u", TEXTURE_16BIT_PALETTE);
+  uTextureID_BUTTDESC2 = pIcons_LOD->LoadTexture("BUTTESC2", TEXTURE_16BIT_PALETTE);
+  uTextureID_x_ok_u = pIcons_LOD->LoadTexture("x_ok_u", TEXTURE_16BIT_PALETTE);
+  uTextureID_BUTTYES2 = pIcons_LOD->LoadTexture("BUTTYES2", TEXTURE_16BIT_PALETTE);
+  uTextureID_BUTTMAKE = pIcons_LOD->LoadTexture("BUTTMAKE", TEXTURE_16BIT_PALETTE);
+  uTextureID_BUTTMAKE2 = pIcons_LOD->LoadTexture("BUTTMAKE2", TEXTURE_16BIT_PALETTE);
+
+  pPrimaryWindow = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0);
+  pPrimaryWindow->CreateButton(7u, 8u, 0x1CCu, 0x157u, 1, 0, 0xAu, 0, 0, "", 0);
+  pPrimaryWindow->CreateButton(0x3Du, 0x1A8u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+  pPrimaryWindow->CreateButton(0xB1u, 0x1A8u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+  pPrimaryWindow->CreateButton(0x124u, 0x1A8u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+  pPrimaryWindow->CreateButton(0x197u, 0x1A8u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+  pPrimaryWindow->CreateButton(0x18u, 0x194u, 5u, 0x31u, 1, 93, 0, 1u, 0, "", 0);
+  pPrimaryWindow->CreateButton(0x8Bu, 0x194u, 5u, 0x31u, 1, 93, 0, 2u, 0, "", 0);
+  pPrimaryWindow->CreateButton(0xFFu, 0x194u, 5u, 0x31u, 1, 93, 0, 3u, 0, "", 0);
+  pPrimaryWindow->CreateButton(0x172u, 0x194u, 5u, 0x31u, 1, 93, 0, 4u, 0, "", 0);
+  pPrimaryWindow->CreateButton(0x61u, 0x194u, 5u, 0x31u, 1, 93, 0, 1u, 0, "", 0);
+  pPrimaryWindow->CreateButton(0xD4u, 0x194u, 5u, 0x31u, 1, 93, 0, 2u, 0, "", 0);
+  pPrimaryWindow->CreateButton(0x148u, 0x194u, 5u, 0x31u, 1, 93, 0, 3u, 0, "", 0);
+  pPrimaryWindow->CreateButton(0x1BBu, 0x194u, 5u, 0x31u, 1, 93, 0, 4u, 0, "", 0);
+  uTextureID_ib_td1_A = pIcons_LOD->LoadTexture("ib-td1-A", TEXTURE_16BIT_PALETTE);
+  v6 = (Texture *)(uTextureID_ib_td1_A != -1 ? &pIcons_LOD->pTextures[uTextureID_ib_td1_A] : 0);
+  v7 = pGlobalTXT_LocalizationStrings[174];
+  v8 = pKeyActionMap->GetActionVKey(INPUT_Quest);
+  pBtn_Quests = pPrimaryWindow->CreateButton(
+                 0x1EBu,
+                 0x161u,
+                 v6->uTextureWidth,
+                 v6->uTextureHeight,
+                 1,
+                 0,
+                 0xC8u,
+                 0,
+                 v8,
+                 v7,
+                 v6, 0);
+  uTextureID_ib_td2_A = pIcons_LOD->LoadTexture("ib-td2-A", TEXTURE_16BIT_PALETTE);
+  v10 = (Texture *)(uTextureID_ib_td2_A != -1 ? &pIcons_LOD->pTextures[uTextureID_ib_td2_A] : 0);
+  v11 = pGlobalTXT_LocalizationStrings[154];
+  v12 = pKeyActionMap->GetActionVKey(INPUT_Autonotes);
+  pBtn_Autonotes = pPrimaryWindow->CreateButton(
+                 0x20Fu,
+                 0x161u,
+                 v10->uTextureWidth,
+                 v10->uTextureHeight,
+                 1,
+                 0,
+                 0xC9u,
+                 0,
+                 v12,
+                 v11,
+                 v10);
+  v14 = pIcons_LOD->LoadTexture("ib-td3-A", TEXTURE_16BIT_PALETTE);
+  v15 = (Texture *)(v14 != -1 ? (int)&pIcons_LOD->pTextures[v14] : 0);
+  v16 = pGlobalTXT_LocalizationStrings[139];
+  v17 = pKeyActionMap->GetActionVKey(INPUT_Mapbook);
+  pBtn_Maps = pPrimaryWindow->CreateButton(
+                 0x222u,
+                 0x161u,
+                 v15->uTextureWidth,
+                 v15->uTextureHeight,
+                 1,
+                 0,
+                 0xCAu,
+                 0,
+                 v17,
+                 v16,
+                 v15);
+  uTextureID_ib_td4_A = pIcons_LOD->LoadTexture("ib-td4-A", TEXTURE_16BIT_PALETTE);
+  v20 = (Texture *)(uTextureID_ib_td4_A != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_ib_td4_A] : 0);
+  v21 = pGlobalTXT_LocalizationStrings[78];
+  v22 = pKeyActionMap->GetActionVKey(INPUT_TimeCal);
+  pBtn_Calendar = pPrimaryWindow->CreateButton(
+                   0x23Au,
+                   0x161u,
+                   v20->uTextureWidth,
+                   v20->uTextureHeight,
+                   1,
+                   0,
+                   0xCBu,
+                   0,
+                   v22,
+                   v21,
+                   v20);
+  uTextureID_ib_td5_A = pIcons_LOD->LoadTexture("ib-td5-A", TEXTURE_16BIT_PALETTE);
+  pBtn_History = pPrimaryWindow->CreateButton(
+                 0x258u,
+                 0x169u,
+                 (uTextureID_ib_td5_A != -1 ? pIcons_LOD->pTextures[uTextureID_ib_td5_A].uTextureWidth : 24),
+                 (uTextureID_ib_td5_A != -1 ? pIcons_LOD->pTextures[uTextureID_ib_td5_A].uTextureHeight : 26),
+                 1,
+                 0,
+                 0xE0u,
+                 0,
+                 0x48u,
+                 pGlobalTXT_LocalizationStrings[602],
+                 (Texture *)(uTextureID_ib_td5_A != -1 ? &pIcons_LOD->pTextures[uTextureID_ib_td5_A] : 0),
+                 0);
+  v24 = &pIcons_LOD->pTextures[uTextureID_507980];
+  v25 = (Texture *)(uTextureID_507980 != -1 ? (int)v24 : 0);
+  bFlashHistoryBook = 0;
+  v26 = (Texture *)(uTextureID_507980 != -1 ? (int)v24 : 0);
+  bFlashAutonotesBook = 0;
+  v27 = pGlobalTXT_LocalizationStrings[252];
+  bFlashQuestBook = 0;
+  v28 = pKeyActionMap->GetActionVKey(INPUT_ZoomIn);
+  dword_507A18 = pPrimaryWindow->CreateButton(
+                   0x23Eu,
+                   0x88u,
+                   v25->uTextureWidth,
+                   v25->uTextureHeight,
+                   2,
+                   0,
+                   0x170u,
+                   0,
+                   v28,
+                   v27,
+                   v26,
+                   0);
+  v29 = &pIcons_LOD->pTextures[uTextureID_507984];
+  v30 = (Texture *)(uTextureID_507984 != -1 ? (int)v29 : 0);
+  v31 = (Texture *)(uTextureID_507984 != -1 ? (int)v29 : 0);
+  v32 = pGlobalTXT_LocalizationStrings[251];
+  v33 = pKeyActionMap->GetActionVKey(INPUT_ZoomOut);
+  dword_507A14 = pPrimaryWindow->CreateButton(
+                   0x207u,
+                   0x88u,
+                   v30->uTextureWidth,
+                   v30->uTextureHeight,
+                   2,
+                   0,
+                   0x16Fu,
+                   0,
+                   v33,
+                   v32,
+                   v31,
+                   0);
+  pPrimaryWindow->CreateButton(0x1E1u, 0, 0x99u, 0x43u, 1, 92, 0, 0, 0, "", 0);
+  pPrimaryWindow->CreateButton(0x1EBu, 0x95u, 0x40u, 0x4Au, 1, 0, 0x86u, 0, 0x35u, "", 0);
+  pPrimaryWindow->CreateButton(0x231u, 0x95u, 0x40u, 0x4Au, 1, 0, 0x87u, 0, 0x36u, "", 0);
+  pPrimaryWindow->CreateButton(0x1DCu, 0x142u, 0x4Du, 0x11u, 1, 100, 0, 0, 0, "", 0);
+  pPrimaryWindow->CreateButton(0x22Bu, 0x142u, 0x4Du, 0x11u, 1, 101, 0, 0, 0, "", 0);
+  pBtn_CastSpell = pPrimaryWindow->CreateButton(
+                 0x1DCu,
+                 0x1C2u,
+                 (uTextureID_50797C != -1 ? pIcons_LOD->pTextures[uTextureID_50797C].uTextureWidth : 24),
+                 (uTextureID_50797C != -1 ? pIcons_LOD->pTextures[uTextureID_50797C].uTextureHeight : 26),
+                 1,
+                 0,
+                 0x69u,
+                 0,
+                 0x43u,
+                 pGlobalTXT_LocalizationStrings[38],
+                 (Texture *)(uTextureID_50797C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50797C] : 0),
+                 0);
+  pBtn_Rest = pPrimaryWindow->CreateButton(
+                 0x206u,
+                 0x1C2u,
+                 (uTextureID_507978 != -1 ? pIcons_LOD->pTextures[uTextureID_507978].uTextureWidth : 24),
+                 (uTextureID_507978 != -1 ? pIcons_LOD->pTextures[uTextureID_507978].uTextureHeight : 26),
+                 1,
+                 0,
+                 0x68u,
+                 0,
+                 0x52u,
+                 pGlobalTXT_LocalizationStrings[182],
+                 (Texture *)(uTextureID_507978 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507978] : 0),
+                 0);
+  pBtn_QuickReference = pPrimaryWindow->CreateButton(
+                 0x230u,
+                 0x1C2u,
+                 (dword_507974 != -1 ? pIcons_LOD->pTextures[dword_507974].uTextureWidth : 24),
+                 (dword_507974 != -1 ? pIcons_LOD->pTextures[dword_507974].uTextureHeight : 26),
+                 1,
+                 0,
+                 0x6Au,
+                 0,
+                 0x5Au,
+                 pGlobalTXT_LocalizationStrings[173],
+                 (Texture *)(dword_507974 != -1 ? &pIcons_LOD->pTextures[dword_507974] : 0),
+                 0);
+  pBtn_GameSettings = pPrimaryWindow->CreateButton(
+                 0x25Au,
+                 0x1C2u,
+                 (uTextureID_507970 != -1 ? pIcons_LOD->pTextures[uTextureID_507970].uTextureWidth : 24),
+                 (uTextureID_507970 != -1 ? pIcons_LOD->pTextures[uTextureID_507970].uTextureHeight : 26),
+                 1,
+                 0,
+                 0x6Bu,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[93],
+                 (Texture *)(uTextureID_507970 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507970] : 0),
+                 0);
+  pBtn_NPCLeft = pPrimaryWindow->CreateButton(
+                 0x1D5u,
+                 0xB2u,
+                 (uTextureID_507990 != -1 ? pIcons_LOD->pTextures[uTextureID_507990].uTextureWidth : 24),
+                 (uTextureID_507990 != -1 ? pIcons_LOD->pTextures[uTextureID_507990].uTextureHeight : 26),
+                 1,
+                 0,
+                 0xBCu,
+                 0,
+                 0,
+                 "",
+                 (Texture *)(uTextureID_507990 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507990] : 0),
+                 0);
+  pBtn_NPCRight = pPrimaryWindow->CreateButton(
+                 0x272u,
+                 0xB2u,
+                 (uTextureID_50798C != -1 ? pIcons_LOD->pTextures[uTextureID_50798C].uTextureWidth : 24),
+                 (uTextureID_50798C != -1 ? pIcons_LOD->pTextures[uTextureID_50798C].uTextureHeight : 26),
+                 1,
+                 0,
+                 0xBCu,
+                 1u,
+                 0,
+                 "",
+                 (Texture *)(uTextureID_50798C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50798C] : 0),
+                 0);
+  Load_isn_spells_21_27();
+}
+
+
+
+//----- (0041C047) --------------------------------------------------------
+void __cdecl GameUI_DrawStatusBar_2()
+{
+  unsigned int v0; // eax@1
+  char *v1; // edx@2
+  unsigned int v2; // ST18_4@5
+  const char *v3; // ST0C_4@5
+  unsigned int v4; // ST08_4@5
+  int v5; // eax@5
+
+  pRenderer->DrawTextureRGB(0, 352u, pTexture_StatusBar);
+  if ( GameUI_StatusBar_TimedStringTimeLeft )
+  {
+    v1 = GameUI_StatusBar_TimedString;
+  }
+  else
+  {
+    if ( !pStatusBarString[0] )
+      return;
+    v1 = pStatusBarString;
+  }
+  LOWORD(v0) = uGameUIFontShadow;
+  v2 = v0;
+  LOWORD(v0) = uGameUIFontMain;
+  v3 = v1;
+  v4 = v0;
+  v5 = pFontLucida->AlignText_Center(0x1C2u, v1);
+  pPrimaryWindow->DrawText(pFontLucida, v5 + 11, 357, v4, v3, 0, 0, v2);
+}
+
+//----- (0041C0B8) --------------------------------------------------------
+void __thiscall sub_41C0B8_set_status_string(const char *pStr)
+{
+  const char *v1; // esi@1
+  int i; // eax@7
+  int j; // eax@11
+
+  v1 = pStr;
+  if ( pStr && strcmp(pStr, "test") && !IsBadStringPtrA(v1, 1u) && (*v1 || GameUI_StatusBar_TimedStringTimeLeft) )
+  {
+    if ( GameUI_StatusBar_TimedStringTimeLeft )
+    {
+      for ( i = pFontLucida->GetLineWidth(GameUI_StatusBar_TimedString);
+            i > 450;
+            i = pFontLucida->GetLineWidth(GameUI_StatusBar_TimedString) )
+        byte_5C3427[strlen(GameUI_StatusBar_TimedString)] = 0;
+    }
+    else
+    {
+      strcpy(pStatusBarString, v1);
+      for ( j = pFontLucida->GetLineWidth(pStatusBarString);
+            j > 450;
+            j = pFontLucida->GetLineWidth(pStatusBarString) )
+        GameUI_StatusBar_TimedString[strlen(pStatusBarString) + 199] = 0;
+    }
+  }
+}
+
+//----- (0041C179) --------------------------------------------------------
+void __cdecl GameUI_DrawStatusBar()
+{
+  unsigned int v0; // ebp@1
+  char *v1; // edi@5
+  int v2; // eax@5
+  unsigned int v3; // esi@5
+  size_t v4; // eax@6
+  GUIFont *v5; // ecx@6
+  int v6; // eax@9
+  size_t v7; // eax@10
+  GUIFont *v8; // ecx@10
+  char v9; // zf@12
+  unsigned int v10; // ST08_4@13
+  int v11; // eax@13
+
+  v0 = uGameUIFontShadow;
+  if ( pStatusBarString[0] || GameUI_StatusBar_TimedStringTimeLeft || bForceDrawStatusBar )
+  {
+    pRenderer->DrawTextureRGB(0, 352u, pTexture_StatusBar);
+    if ( GameUI_StatusBar_TimedStringTimeLeft )
+    {
+      v1 = GameUI_StatusBar_TimedString;
+      v2 = pFontLucida->GetLineWidth(GameUI_StatusBar_TimedString);
+      v3 = 450;
+      while ( v2 > 450 )
+      {
+        v4 = strlen(GameUI_StatusBar_TimedString);
+        v5 = pFontLucida;
+        byte_5C3427[v4] = 0;
+        v2 = pFontLucida->GetLineWidth(GameUI_StatusBar_TimedString);
+      }
+    }
+    else
+    {
+      v1 = pStatusBarString;
+      v6 = pFontLucida->GetLineWidth(pStatusBarString);
+      v3 = 450;
+      while ( v6 > 450 )
+      {
+        v7 = strlen(pStatusBarString);
+        v8 = pFontLucida;
+        GameUI_StatusBar_TimedString[v7 + 199] = 0;
+        v6 = pFontLucida->GetLineWidth(pStatusBarString);
+      }
+    }
+    v9 = *v1 == 0;
+    bForceDrawStatusBar = 0;
+    if ( !v9 )
+    {
+      v10 = uGameUIFontMain;
+      v11 = pFontLucida->AlignText_Center(v3, v1);
+      pPrimaryWindow->DrawText(pFontLucida, v11 + 11, 357, v10, v1, 0, 0, v0);
+    }
+  }
+}
+// 5C35BC: using guessed type int bForceDrawStatusBar;
+
+
+//----- (0041CD4F) --------------------------------------------------------
+bool __thiscall sub_41CD4F(unsigned int _this)
+{
+  unsigned int v1; // edi@1
+  unsigned int v2; // eax@2
+  int v3; // esi@3
+  int v4; // ecx@10
+  GUIButton *v5; // eax@11
+  int v6; // edx@12
+  int v7; // ecx@20
+  char v8; // zf@21
+  GUIButton *v9; // ecx@24
+  int v10; // esi@24
+  int v11; // edx@26
+  int v12; // edx@28
+  int v13; // esi@32
+  GUIButton *v14; // eax@37
+  int v15; // edx@38
+  int v17; // ecx@50
+  int v18; // edx@50
+  GUIButton *v19; // ecx@54
+  int v20; // esi@54
+  int v21; // edx@56
+  int v22; // ecx@59
+  int v23; // edx@59
+  int v24; // ecx@60
+  int v25; // esi@63
+  unsigned int v26; // [sp+Ch] [bp-14h]@1
+  int v27; // [sp+10h] [bp-10h]@1
+  int v28; // [sp+14h] [bp-Ch]@10
+  int v29; // [sp+14h] [bp-Ch]@36
+  unsigned int uClickX; // [sp+18h] [bp-8h]@10
+  unsigned int uClickY; // [sp+1Ch] [bp-4h]@10
+
+  v1 = 0;
+  v26 = _this;
+  v27 = uNumVisibleWindows;
+  if ( uNumVisibleWindows < 0 )
+    return 0;
+  v2 = pMessageQueue_50CBD0->uNumMessages;
+  while ( 1 )
+  {
+    v3 = pVisibleWindowsIdxs[v27] - 1;
+    if ( pWindowList[v3].field_44 == v1 )
+      goto LABEL_47;
+    if ( v26 != 34 )
+      break;
+    if ( pWindowList[v3].field_30 != v1 )
+    {
+      pMouse->GetClickPos(&uClickX, &uClickY);
+      v4 = pWindowList[v3].pStartingPosActiveItem;
+      v29 = v4 + pWindowList[v3].pNumPresenceButton;
+      if ( v4 < v4 + pWindowList[v3].pNumPresenceButton )
+      {
+        while ( 1 )
+        {
+          v14 = pWindowList[v3].pControlsHead;
+          if ( v4 > 0 )
+          {
+            v15 = v4;
+            do
+            {
+              v14 = v14->pNext;
+              --v15;
+            }
+            while ( v15 );
+          }
+          if ( (signed int)uClickX >= (signed int)v14->uX
+            && (signed int)uClickX <= (signed int)v14->uZ
+            && (signed int)uClickY >= (signed int)v14->uY
+            && (signed int)uClickY <= (signed int)v14->uW )
+            goto LABEL_66;
+          ++v4;
+          if ( v4 >= v29 )
+          {
+LABEL_45:
+            v1 = 0;
+            goto LABEL_46;
+          }
+        }
+      }
+      goto LABEL_46;
+    }
+LABEL_47:
+    --v27;
+    if ( v27 < 0 )
+      return 0;
+  }
+  if ( v26 == 37 )
+  {
+    v12 = pWindowList[v3].field_34;
+    if ( pWindowList[v3].pCurrentPosActiveItem - pWindowList[v3].pStartingPosActiveItem - v12 >= 0 )
+    {
+      v8 = pCurrentScreen == 21;
+      pWindowList[v3].pCurrentPosActiveItem -= v12;
+      if ( v8 )
+      {
+        pAudioPlayer->PlaySound((SoundID)66, v1, v1, -1, v1, v1, v1, v1);
+        v2 = pMessageQueue_50CBD0->uNumMessages;
+      }
+    }
+    if ( pWindowList[v3].field_30 != v1 )
+      goto LABEL_47;
+    v9 = pWindowList[v3].pControlsHead;
+    v13 = pWindowList[v3].pCurrentPosActiveItem;
+    if ( v13 > (signed int)v1 )
+    {
+      do
+      {
+        v9 = v9->pNext;
+        --v13;
+      }
+      while ( v13 );
+    }
+LABEL_26:
+    v11 = v9->uControlParam;
+    if ( (signed int)v2 < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[v2].eType = (UIMessageType)v9->uControlID;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v11;
+      *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = v1;
+      v2 = pMessageQueue_50CBD0->uNumMessages + 1;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+    goto LABEL_47;
+  }
+  if ( v26 != 38 )
+  {
+    if ( v26 == 39 )
+    {
+      v7 = pWindowList[v3].pCurrentPosActiveItem + pWindowList[v3].field_34;
+      if ( v7 < pWindowList[v3].pNumPresenceButton + pWindowList[v3].pStartingPosActiveItem )
+      {
+        v8 = pCurrentScreen == 21;
+        pWindowList[v3].pCurrentPosActiveItem = v7;
+        if ( v8 )
+        {
+          pAudioPlayer->PlaySound((SoundID)66, v1, v1, -1, v1, v1, v1, v1);
+          v2 = pMessageQueue_50CBD0->uNumMessages;
+        }
+      }
+      if ( pWindowList[v3].field_30 != v1 )
+        goto LABEL_47;
+      v9 = pWindowList[v3].pControlsHead;
+      v10 = pWindowList[v3].pCurrentPosActiveItem;
+      if ( v10 > (signed int)v1 )
+      {
+        do
+        {
+          v9 = v9->pNext;
+          --v10;
+        }
+        while ( v10 );
+      }
+      goto LABEL_26;
+    }
+    if ( v26 == 40 )
+    {
+      v17 = pWindowList[v3].pStartingPosActiveItem;
+      v18 = pWindowList[v3].pCurrentPosActiveItem;
+      if ( v18 >= pWindowList[v3].pNumPresenceButton + v17 - 1 )
+        pWindowList[v3].pCurrentPosActiveItem = v17;
+      else
+        pWindowList[v3].pCurrentPosActiveItem = v18 + 1;
+      if ( pWindowList[v3].field_30 != v1 )
+        return 1;
+      v19 = pWindowList[v3].pControlsHead;
+      v20 = pWindowList[v3].pCurrentPosActiveItem;
+      if ( v20 > (signed int)v1 )
+      {
+        do
+        {
+          v19 = v19->pNext;
+          --v20;
+        }
+        while ( v20 );
+      }
+      goto LABEL_56;
+    }
+    if ( v26 == 41 )
+    {
+      pMouse->GetClickPos(&uClickX, &uClickY);
+      v4 = pWindowList[v3].pStartingPosActiveItem;
+      v28 = v4 + pWindowList[v3].pNumPresenceButton;
+      if ( v4 < v4 + pWindowList[v3].pNumPresenceButton )
+      {
+        while ( 1 )
+        {
+          v5 = pWindowList[v3].pControlsHead;
+          if ( v4 > 0 )
+          {
+            v6 = v4;
+            do
+            {
+              v5 = v5->pNext;
+              --v6;
+            }
+            while ( v6 );
+          }
+          if ( (signed int)uClickX >= (signed int)v5->uX
+            && (signed int)uClickX <= (signed int)v5->uZ
+            && (signed int)uClickY >= (signed int)v5->uY
+            && (signed int)uClickY <= (signed int)v5->uW )
+            break;
+          ++v4;
+          if ( v4 >= v28 )
+            goto LABEL_45;
+        }
+LABEL_66:
+        pWindowList[v3].pCurrentPosActiveItem = v4;
+        return 1;
+      }
+LABEL_46:
+      v2 = pMessageQueue_50CBD0->uNumMessages;
+      goto LABEL_47;
+    }
+    goto LABEL_47;
+  }
+  v22 = pWindowList[v3].pCurrentPosActiveItem;
+  v23 = pWindowList[v3].pStartingPosActiveItem;
+  if ( v22 <= v23 )
+    v24 = pWindowList[v3].pNumPresenceButton + v23 - 1;
+  else
+    v24 = v22 - 1;
+  v8 = pWindowList[v3].field_30 == v1;
+  pWindowList[v3].pCurrentPosActiveItem = v24;
+  if ( !v8 )
+    return 1;
+  v19 = pWindowList[v3].pControlsHead;
+  v25 = pWindowList[v3].pCurrentPosActiveItem;
+  if ( v25 > (signed int)v1 )
+  {
+    do
+    {
+      v19 = v19->pNext;
+      --v25;
+    }
+    while ( v25 );
+  }
+LABEL_56:
+  v21 = v19->uControlParam;
+  if ( (signed int)v2 < 40 )
+  {
+    pMessageQueue_50CBD0->pMessages[v2].eType = (UIMessageType)v19->uControlID;
+    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v21;
+    *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = v1;
+    ++pMessageQueue_50CBD0->uNumMessages;
+  }
+  return 1;
+}
+
+//----- (0041D20D) --------------------------------------------------------
+char __fastcall sub_41D20D_buff_remaining_time_string(int ecx0, GUIWindow *edx0, __int64 a3, GUIFont *a2)
+{
+  unsigned int v4; // edi@1
+  unsigned int v5; // esi@1
+  unsigned int v6; // ebp@1
+  unsigned int v7; // ebx@1
+  signed __int64 v8; // ST34_8@1
+  signed __int64 v9; // kr00_8@1
+  char *v10; // eax@2
+  char *v11; // eax@7
+  char *v12; // eax@13
+  char *v13; // eax@19
+  int uY; // [sp+0h] [bp-20h]@1
+  GUIWindow *a1; // [sp+4h] [bp-1Ch]@1
+  signed __int64 v17; // [sp+10h] [bp-10h]@1
+  signed __int64 v18; // [sp+18h] [bp-8h]@1
+  unsigned int v19; // [sp+24h] [bp+4h]@1
+
+  a1 = edx0;
+  uY = ecx0;
+  v4 = (unsigned __int64)(signed __int64)((double)a3 * 0.234375) >> 32;
+  v5 = (signed __int64)((double)a3 * 0.234375);
+  v6 = (unsigned __int64)((signed __int64)((double)a3 * 0.234375) / 60) >> 32;
+  v7 = (signed __int64)((double)a3 * 0.234375) / 60;
+  v8 = (signed __int64)((double)a3 * 0.234375) / 60 / 60;
+  v19 = (unsigned int)v8 / 0x18;
+  v18 = (signed __int64)__PAIR__(v4, v5) % 60;
+  v17 = (signed __int64)__PAIR__(v6, v7) % 60;
+  v9 = v8 % 24;
+  strcpy(pTmpBuf, "\r020");
+  if ( (unsigned int)v8 / 0x18 )
+  {
+    v10 = pGlobalTXT_LocalizationStrings[57];   // Days
+    if ( v19 <= 1 )
+      v10 = pGlobalTXT_LocalizationStrings[56]; // Day
+    sprintf(pTmpBuf2, "%d %s ", v19, v10);
+    strcat(pTmpBuf, pTmpBuf2);
+  }
+  if ( v9 )
+  {
+    if ( v9 <= 1 )
+      v11 = pGlobalTXT_LocalizationStrings[109];// Hour
+    else
+      v11 = pGlobalTXT_LocalizationStrings[110];// Hours
+    sprintf(pTmpBuf2, "%d %s ", v9, v11);
+    strcat(pTmpBuf, pTmpBuf2);
+  }
+  if ( v17 && !v19 )
+  {
+    if ( v17 <= 1 )
+      v12 = pGlobalTXT_LocalizationStrings[437];// Minute
+    else
+      v12 = pGlobalTXT_LocalizationStrings[436];// Minutes
+    sprintf(pTmpBuf2, "%d %s ", v17, v12);
+    strcat(pTmpBuf, pTmpBuf2);
+  }
+  if ( v18 && !v9 )
+  {
+    if ( v18 <= 1 )
+      v13 = pGlobalTXT_LocalizationStrings[439];// Second
+    else
+      v13 = pGlobalTXT_LocalizationStrings[438];// Seconds
+    sprintf(pTmpBuf2, "%d %s ", v18, v13);
+    strcat(pTmpBuf, pTmpBuf2);
+  }
+  return a1->DrawText(a2, 32, uY, 0, pTmpBuf, 0, 0, 0);
+}
+
+
+//----- (0041D895) --------------------------------------------------------
+void __thiscall GameUI_DrawItemInfo(ItemGen *ecx0)
+{
+  ItemGen *v1; // esi@1
+  unsigned int v2; // eax@3
+  char *v3; // edi@5
+  unsigned int v4; // eax@5
+  unsigned int v5; // esi@5
+  signed int v6; // eax@5
+  int v7; // edx@5
+  ItemGen *v8; // ecx@10
+  unsigned int v9; // eax@12
+  char v10; // zf@16
+  ItemGen *v11; // eax@16
+  ItemGen *v12; // eax@25
+  unsigned int v13; // ecx@32
+  unsigned int v14; // eax@32
+  Render *v15; // edi@33
+  const char *v16; // eax@34
+  int v17; // eax@36
+  int v18; // esi@37
+  unsigned __int16 v19; // ax@37
+  char v20; // al@40
+  char v21; // al@44
+  char v22; // al@48
+  char v23; // al@51
+  int v24; // eax@52
+  int v25; // eax@57
+  int v26; // eax@60
+  int v27; // eax@67
+  const char *v28; // edi@69
+  int v29; // eax@70
+  char *v30; // edi@78
+  const char *v31; // eax@78
+  int v32; // ecx@81
+  unsigned int v33; // eax@81
+  int v34; // esi@81
+  const char *v35; // eax@85
+  const char *v36; // eax@87
+  unsigned int v37; // eax@109
+  unsigned int v38; // eax@109
+  int v39; // eax@113
+  GUIFont *v40; // edx@113
+  signed int v41; // [sp-20h] [bp-298h]@113
+  int v42; // [sp-1Ch] [bp-294h]@113
+  char *v43; // [sp-18h] [bp-290h]@46
+  unsigned int v44; // [sp-18h] [bp-290h]@113
+  int v45; // [sp-14h] [bp-28Ch]@46
+  const char *v46; // [sp-14h] [bp-28Ch]@58
+  char *v47; // [sp-14h] [bp-28Ch]@110
+  char *v48; // [sp-10h] [bp-288h]@46
+  const char *v49; // [sp-10h] [bp-288h]@56
+  char *v50; // [sp-10h] [bp-288h]@58
+  int v51; // [sp-10h] [bp-288h]@110
+  const char *v52; // [sp-Ch] [bp-284h]@36
+  int v53; // [sp-Ch] [bp-284h]@46
+  char *v54; // [sp-Ch] [bp-284h]@56
+  int v55; // [sp-Ch] [bp-284h]@58
+  int v56; // [sp-Ch] [bp-284h]@110
+  unsigned int v57; // [sp-8h] [bp-280h]@36
+  int v58; // [sp-8h] [bp-280h]@46
+  int v59; // [sp-8h] [bp-280h]@56
+  int v60; // [sp-8h] [bp-280h]@58
+  unsigned int v61; // [sp-8h] [bp-280h]@110
+  char a1[100]; // [sp+8h] [bp-270h]@40
+  char Dest[100]; // [sp+6Ch] [bp-20Ch]@40
+  char v64[100]; // [sp+D0h] [bp-1A8h]@40
+  char v65[120]; // [sp+134h] [bp-144h]@92
+  char Source[40]; // [sp+1ACh] [bp-CCh]@49
+  int v67; // [sp+1D4h] [bp-A4h]@91
+  int v68; // [sp+1D8h] [bp-A0h]@106
+  int v69; // [sp+1DCh] [bp-9Ch]@101
+  int v70; // [sp+1E0h] [bp-98h]@97
+  int v71; // [sp+1E8h] [bp-90h]@93
+  int v72; // [sp+1ECh] [bp-8Ch]@91
+  int var88; // [sp+1F0h] [bp-88h]@1
+  Texture *v73; // [sp+1F4h] [bp-84h]@5
+  unsigned int v75; // [sp+1F8h] [bp-80h]@5
+  char *v76; // [sp+1FCh] [bp-7Ch]@5
+  int v77; // [sp+200h] [bp-78h]@12
+  int v78; // [sp+204h] [bp-74h]@5
+  GUIWindow v79; // [sp+208h] [bp-70h]@2
+  POINT a2; // [sp+25Ch] [bp-1Ch]@2
+  int v81; // [sp+264h] [bp-14h]@5
+  GUIFont *v82; // [sp+268h] [bp-10h]@1
+  char *v83; // [sp+26Ch] [bp-Ch]@18
+  char *Str; // [sp+270h] [bp-8h]@65
+  ItemGen *_this; // [sp+274h] [bp-4h]@1
+
+  v1 = ecx0;
+  _this = ecx0;
+  var88 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v82 = pFontComic;
+  if ( v1->uItemID )
+  {
+    v79.Hint = 0;
+    v79.uFrameWidth = 384;
+    v79.uFrameHeight = 180;
+    v79.uFrameY = 40;
+    if ( pMouse->GetCursorPos(&a2)->x <= 320 )
+      v2 = pMouse->GetCursorPos(&a2)->x + 30;
+    else
+      v2 = pMouse->GetCursorPos(&a2)->x - v79.uFrameWidth - 30;
+    v79.uFrameX = v2;
+    v3 = (char *)&pItemsTable->pItems[_this->uItemID].pIconName;
+    v76 = v3;
+    v4 = pIcons_LOD->LoadTexture(*(const char **)v3, TEXTURE_16BIT_PALETTE);
+    v5 = v4;
+    v4 *= 72;
+    v75 = v4;
+    v73 = (struct Texture *)((char *)pIcons_LOD->pTextures + v4);
+    v6 = 100 - *(unsigned __int16 *)((char *)&pIcons_LOD->pTextures[0].uTextureWidth + v4);
+    v7 = v73->uTextureHeight;
+    v78 = v6;
+    v81 = 144 - v7;
+    if ( v6 > 0 )
+      v78 = v6 >> 1;
+    if ( v81 <= 0 )
+      v81 = 0;
+    else
+      v81 >>= 1;
+    v8 = _this;
+    if ( !v3[46] )
+      _this->uAttributes |= 1u;
+    v9 = v8->uAttributes;
+    v77 = 0;
+    a2.y = v9 & 2;
+    if ( pItemsTable->pItems[v8->uItemID].uEquipType == 18 )
+      v77 = v8->uAdditionalValue;
+    if ( uActiveCharacter )
+    {
+      if ( !(v9 & 1) )
+      {
+        v10 = pPlayers[uActiveCharacter]->CanIdentify(_this) == 1;
+        v11 = _this;
+        if ( v10 )
+          _this->uAttributes |= 1u;
+        v10 = (v11->uAttributes & 1) == 0;
+        v83 = (char *)9;
+        if ( v10 )
+        {
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[446], 2u);
+        }
+        else
+        {
+          v83 = (char *)8;
+          if ( _this->GetValue() < 100 * (pPlayers[uActiveCharacter]->uLevel + 5) )
+            v83 = (char *)7;
+        }
+        if ( dword_4E455C )
+        {
+          pPlayers[uActiveCharacter]->PlaySound((int)v83, 0);
+          dword_4E455C = 0;
+        }
+      }
+      _this->UpdateTempBonus(pParty->uTimePlayed);
+      if ( a2.y )
+      {
+        v10 = pPlayers[uActiveCharacter]->CanRepair(_this) == 1;
+        v12 = _this;
+        if ( v10 )
+          _this->uAttributes = _this->uAttributes & 0xFFFFFFFD | 1;
+        v10 = (v12->uAttributes & 2) == 0;
+        v83 = (char *)11;
+        if ( v10 )
+          v83 = (char *)10;
+        else
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[448], 2u);
+        if ( dword_4E455C )
+        {
+          pPlayers[uActiveCharacter]->PlaySound((int)v83, 0);
+          dword_4E455C = 0;
+        }
+      }
+    }
+    v13 = _this->uAttributes;
+    v14 = _this->uAttributes & 1;
+    a2.y = _this->uAttributes & 1;
+    if ( v13 & 2 )
+    {
+      v79.DrawMessageBox(0);
+      //v15 = &;
+      pRenderer->Clip(
+        v79.uFrameX + 12,
+        v79.uFrameY + 12,
+        v79.uFrameX + v79.uFrameWidth - 12,
+        v79.uFrameY + v79.uFrameHeight - 12);
+      v79.uFrameWidth -= 24;
+      v79.uFrameHeight -= 12;
+      v79.uFrameZ = v79.uFrameX + v79.uFrameWidth - 1;
+      v79.uFrameW = v79.uFrameY + v79.uFrameHeight - 1;
+      pRenderer->_4A6776(
+        v79.uFrameX + v78,
+        v81 + v79.uFrameY + 30,
+        (Texture *)(v5 != -1 ? (int)((char *)pIcons_LOD->pTextures + v75) : 0));
+      if ( a2.y )
+        v16 = _this->GetIdentifiedName();
+      else
+        v16 = (const char *)*((int *)v76 + 2);
+      v79.DrawTitleText(pFontArrus, 0, 0xCu, var88, v16, 3u);
+      v17 = pFontArrus->CalcTextHeight(pGlobalTXT_LocalizationStrings[32], &v79, 0, 0);
+      v57 = 3;
+      v52 = pGlobalTXT_LocalizationStrings[32];
+      goto LABEL_37;
+    }
+    if ( !v14 )
+    {
+      v79.DrawMessageBox(0);
+      v15 = pRenderer;
+      pRenderer->Clip(
+        v79.uFrameX + 12,
+        v79.uFrameY + 12,
+        v79.uFrameX + v79.uFrameWidth - 12,
+        v79.uFrameY + v79.uFrameHeight - 12);
+      v79.uFrameWidth -= 24;
+      v79.uFrameHeight -= 12;
+      v79.uFrameZ = v79.uFrameX + v79.uFrameWidth - 1;
+      v79.uFrameW = v79.uFrameY + v79.uFrameHeight - 1;
+      pRenderer->DrawTextureTransparent(
+        v79.uFrameX + v78,
+        v81 + v79.uFrameY + 30,
+        (Texture *)(v5 != -1 ? (int)((char *)pIcons_LOD->pTextures + v75) : 0));
+      v79.DrawTitleText(pFontArrus, 0, 0xCu, var88, *((const char **)v76 + 2), 3u);
+      v17 = pFontArrus->CalcTextHeight(pGlobalTXT_LocalizationStrings[232], &v79, 0, 0);
+      v57 = 3;
+      v52 = pGlobalTXT_LocalizationStrings[232];
+LABEL_37:
+      v18 = v17 >> 1;
+      v19 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0x19u, 0x19u);
+      v79.DrawTitleText(pFontArrus, 0x64u, ((signed int)v79.uFrameHeight >> 1) - v18, v19, v52, v57);
+      goto LABEL_116;
+    }
+    sprintf(a1, pGlobalTXT_LocalizationStrings[463], *((int *)v3 + 2));
+    strcpy(Dest, "");
+    strcpy(v64, "");
+    v20 = v3[28];
+    if ( (unsigned __int8)v20 <= 1u )
+    {
+      v58 = (unsigned __int8)v3[31];
+      v53 = (unsigned __int8)v3[30];
+      v48 = pGlobalTXT_LocalizationStrings[53];
+      v45 = (unsigned __int8)v3[32];
+      v43 = pGlobalTXT_LocalizationStrings[18];
+    }
+    else
+    {
+      if ( v20 != 2 )
+      {
+        if ( (unsigned __int8)v20 > 2u )
+        {
+          if ( (unsigned __int8)v20 <= 0xBu )
+          {
+            v21 = v3[30];
+            if ( v21 )
+              sprintf(
+                Dest,
+                "%s: +%d",
+                pGlobalTXT_LocalizationStrings[11],
+                (unsigned __int8)v21 + (unsigned __int8)v3[32]);
+          }
+        }
+        goto LABEL_50;
+      }
+      v58 = (unsigned __int8)v3[31];
+      v53 = (unsigned __int8)v3[30];
+      v48 = pGlobalTXT_LocalizationStrings[53];
+      v45 = (unsigned __int8)v3[32];
+      v43 = pGlobalTXT_LocalizationStrings[203];
+    }
+    sprintf(Dest, "%s: +%d   %s: %dd%d", v43, v45, v48, v53, v58);
+    v22 = v3[32];
+    if ( v22 )
+    {
+      sprintf(Source, " +%d", (unsigned __int8)v22);
+      strcat(Dest, Source);
+    }
+LABEL_50:
+    if ( v77 )
+      goto LABEL_65;
+    v23 = v3[28];
+    if ( v23 == 14 )
+    {
+      v24 = _this->_bonus_type;
+      if ( v24 )
+        goto LABEL_56;
+LABEL_65:
+      v79.uFrameWidth -= 12;
+      a2.y = 3;
+      v79.uFrameZ = v79.uFrameX + v79.uFrameWidth - 1;
+      v79.uFrameW = v79.uFrameY + v79.uFrameHeight - 1;
+      Str = (char *)(3 * (LOBYTE(pFontArrus->uFontHeight) + 8));
+      v83 = a1;
+      do
+      {
+        if ( *v83 )
+        {
+          v27 = v82->CalcTextHeight(v83, &v79, 100, 0);
+          Str += v27 + 3;
+        }
+        v83 += 100;
+        --a2.y;
+      }
+      while ( a2.y );
+      v28 = (const char *)*((int *)v3 + 3);
+      if ( *v28 )
+      {
+        v29 = pFontSmallnum->CalcTextHeight(v28, &v79, 100, 0);
+        Str += v29;
+      }
+      v79.uFrameHeight = v73->uTextureHeight + v81 + 54;
+      if ( (signed int)Str > (signed int)v79.uFrameHeight )
+        v79.uFrameHeight = (unsigned int)Str;
+      if ( _this->uAttributes & 8 && (_this->uAdditionalValue || _this->_bonus_type) )
+        v79.uFrameHeight += LOBYTE(v82->uFontHeight);
+      v83 = 0;
+      if ( LOBYTE(pFontArrus->uFontHeight) )
+      {
+        v79.uFrameWidth -= 24;
+        v30 = (char *)LOBYTE(pFontArrus->uFontHeight);
+        v31 = _this->GetIdentifiedName();
+        if ( pFontArrus->CalcTextHeight(v31, &v79, 0, 0) / (signed int)v30 )
+          v83 = v30;
+        v79.uFrameWidth += 24;
+      }
+      v79.uFrameWidth += 12;
+      v79.uFrameHeight += (unsigned int)v83;
+      v79.uFrameW = v79.uFrameY + v79.uFrameHeight - 1;
+      v79.uFrameZ = v79.uFrameX + v79.uFrameWidth - 1;
+      v79.DrawMessageBox(0);
+      v15 = pRenderer;
+      pRenderer->Clip(
+        v79.uFrameX + 12,
+        v79.uFrameY + 12,
+        v79.uFrameX + v79.uFrameWidth - 12,
+        v79.uFrameY + v79.uFrameHeight - 12);
+      v79.uFrameWidth -= 12;
+      v32 = v73->uTextureHeight;
+      v33 = v79.uFrameHeight;
+      v79.uFrameHeight -= 12;
+      v79.uFrameZ = v79.uFrameX + v79.uFrameWidth - 1;
+      v79.uFrameW = v79.uFrameY + v79.uFrameHeight - 1;
+      pRenderer->DrawTextureTransparent(
+        v79.uFrameX + v78,
+        v79.uFrameY + (signed int)(v33 - v32) / 2,
+        (Texture *)(v5 != -1 ? (int)((char *)pIcons_LOD->pTextures + v75) : 0));
+      a2.y = 3;
+      v34 = (int)(v83 + 35);
+      Str = a1;
+      do
+      {
+        if ( *Str )
+        {
+          v79.DrawText(v82, 100, v34, 0, Str, 0, 0, 0);
+          v34 += v82->CalcTextHeight(Str, &v79, 100, 0) + 3;
+        }
+        Str += 100;
+        --a2.y;
+      }
+      while ( a2.y );
+      v35 = (const char *)*((int *)v76 + 3);
+      if ( *v35 )
+        v79.DrawText(pFontSmallnum, 100, v34, 0, v35, 0, 0, 0);
+      v79.uFrameX += 12;
+      v79.uFrameWidth -= 24;
+      v36 = _this->GetIdentifiedName();
+      v79.DrawTitleText(pFontArrus, 0, 0xCu, var88, v36, 3u);
+      v79.uFrameWidth += 24;
+      v79.uFrameX -= 12;
+      if ( v77 )
+      {
+        sprintf(pTmpBuf, "%s: %lu", pGlobalTXT_LocalizationStrings[465], v77);
+        v40 = v82;
+        v61 = 0;
+        v56 = 0;
+        v51 = 0;
+        v47 = pTmpBuf;
+        v44 = 0;
+        v42 = v79.uFrameHeight - LOBYTE(v82->uFontHeight);
+        v41 = 100;
+      }
+      else
+      {
+        if ( _this->uAttributes & 8 && (_this->uAdditionalValue || _this->_bonus_type) )
+        {
+          sub_493F79((stru351 *)&v67, _this->uExpireTime - pParty->uTimePlayed);
+          strcpy(pTmpBuf, "Duration:");
+          Str = (char *)(v72 - 1168);
+          if ( v72 != 1168 )
+          {
+            sprintf(v65, " %d:yr", v72 - 1168);
+            strcat(pTmpBuf, v65);
+          }
+          if ( (((v71 || Str) && ((sprintf(v65, " %d:mo", v71), strcat(pTmpBuf, v65), v71) || Str) || v70)
+             && ((sprintf(v65, " %d:dy", v70), strcat(pTmpBuf, v65), v71) || Str || v70)
+             || v69)
+            && ((sprintf(v65, " %d:hr", v69), strcat(pTmpBuf, v65), v71) || Str || v70 || v69)
+            || v68 )
+          {
+            sprintf(v65, " %d:mn", v68);
+            strcat(pTmpBuf, v65);
+          }
+          v79.DrawText(v82, 100, v79.uFrameHeight - 2 * LOBYTE(v82->uFontHeight), 0, pTmpBuf, 0, 0, 0);
+        }
+        v37 = _this->GetValue();
+        sprintf(pTmpBuf, "%s: %lu", pGlobalTXT_LocalizationStrings[465], v37);
+        v79.DrawText(v82, 100, v79.uFrameHeight - LOBYTE(v82->uFontHeight), 0, pTmpBuf, 0, 0, 0);
+        v38 = _this->uAttributes;
+        if ( BYTE1(v38) & 1 )
+        {
+          v61 = 0;
+          v56 = 0;
+          v51 = 0;
+          v47 = pGlobalTXT_LocalizationStrings[187];
+        }
+        else
+        {
+          if ( !(BYTE1(v38) & 2) )
+            goto LABEL_116;
+          v61 = 0;
+          v56 = 0;
+          v51 = 0;
+          v47 = pGlobalTXT_LocalizationStrings[651];
+        }
+        LOWORD(v38) = LOWORD(pRenderer->uTargetRMask);
+        v44 = v38;
+        v42 = v79.uFrameHeight - LOBYTE(v82->uFontHeight);
+        v39 = v82->GetLineWidth(pTmpBuf);
+        v40 = v82;
+        v41 = v39 + 132;
+      }
+      v79.DrawText(v40, v41, v42, v44, v47, v51, v56, v61);
+LABEL_116:
+      pRenderer->ResetClip();
+      if ( !areWeLoadingTexture )
+      {
+        v73->Release();
+        pIcons_LOD->_40F9C5();
+      }
+      return;
+    }
+    if ( v23 == 13 )
+    {
+      v24 = pItemsTable->pItems[_this->uItemID].uDamageDice;
+LABEL_56:
+      v59 = v24;
+      v54 = pGlobalTXT_LocalizationStrings[449];
+      v49 = "%s: %d";
+LABEL_64:
+      sprintf(v64, v49, v54, v59);
+      goto LABEL_65;
+    }
+    v25 = _this->_bonus_type;
+    if ( v25 )
+    {
+      v60 = _this->_bonus_strength;
+      v55 = *((int *)&pItemsTable->pItems[799].uDamageMod + 5 * v25);
+      v50 = pGlobalTXT_LocalizationStrings[210];
+      v46 = "%s: %s +%d";
+    }
+    else
+    {
+      v26 = _this->uAdditionalValue;
+      if ( !v26 )
+      {
+        if ( _this->uNumCharges )
+        {
+          v59 = _this->uNumCharges;
+          v54 = pGlobalTXT_LocalizationStrings[464];
+          v49 = "%s: %lu";
+          goto LABEL_64;
+        }
+        goto LABEL_65;
+      }
+      v60 = _this->_bonus_strength;
+      v55 = *((int *)&pItemsTable->pEnchantments[23].pName + 7 * v26);
+      v50 = pGlobalTXT_LocalizationStrings[210];
+      v46 = "%s: %s";
+    }
+    sprintf(v64, v46, v50, v55, v60);
+    goto LABEL_65;
+  }
+}
+// 4E455C: using guessed type int dword_4E455C;
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (0041E360) --------------------------------------------------------
+char *__fastcall MonsterPopup_Draw(unsigned int uActorID, GUIWindow *edx0)
+{
+  unsigned int v2; // esi@1
+  Actor *v3; // esi@3
+  int v4; // eax@3
+  unsigned int v5; // ecx@3
+  NPCData *v6; // eax@3
+  unsigned __int16 v7; // cx@3
+  int v8; // eax@4
+  unsigned __int16 v9; // dx@4
+  SpriteFrame *v10; // edi@17
+  int v11; // esi@17
+  unsigned int v12; // ecx@17
+  Sprite *v13; // edi@18
+  int v14; // ecx@18
+  int v15; // edx@18
+  int v16; // edx@18
+  int v17; // eax@18
+  unsigned int v18; // ecx@19
+  unsigned int v19; // eax@21
+  char *v20; // esi@28
+  int v21; // edx@29
+  unsigned __int16 *v22; // ecx@29
+  int v23; // eax@29
+  int v24; // eax@32
+  int v25; // esi@32
+  char *v26; // edx@34
+  unsigned __int8 v27; // sf@36
+  unsigned __int8 v28; // of@36
+  int v29; // esi@40
+  char *v30; // ecx@40
+  int v31; // eax@40
+  int v32; // esi@43
+  unsigned __int16 v33; // ax@45
+  int v34; // edx@45
+  int v35; // eax@45
+  int v36; // eax@49
+  char *v37; // eax@52
+  int v38; // eax@55
+  unsigned __int16 v39; // ax@59
+  SpellBuff *v40; // eax@60
+  int v41; // edi@61
+  unsigned int v42; // eax@61
+  int v43; // eax@62
+  int v44; // eax@63
+  signed int v45; // edi@65
+  unsigned __int16 v46; // ax@73
+  Player *v47; // ecx@77
+  unsigned int v48; // eax@85
+  GUIFont *v49; // edi@90
+  int v50; // edi@90
+  SpellBuff *v51; // eax@91
+  char *v52; // ecx@98
+  char *v53; // ecx@101
+  char *v54; // ST0C_4@118
+  unsigned int v55; // eax@118
+  GUIFont *v56; // edi@124
+  unsigned __int8 v57; // al@128
+  int v58; // eax@132
+  Actor *v59; // ecx@133
+  unsigned __int8 v60; // dl@138
+  char *v61; // eax@145
+  char *v62; // eax@147
+  int v63; // eax@152
+  char *result; // eax@152
+  int v65; // eax@155
+  const char *v66; // [sp-10h] [bp-1FCh]@121
+  const char *v67; // [sp-10h] [bp-1FCh]@125
+  const char *v68; // [sp-10h] [bp-1FCh]@142
+  int v69; // [sp-Ch] [bp-1F8h]@121
+  char *v70; // [sp-Ch] [bp-1F8h]@125
+  char *v71; // [sp-Ch] [bp-1F8h]@142
+  char *v72; // [sp-8h] [bp-1F4h]@54
+  int v73; // [sp-8h] [bp-1F4h]@79
+  int v74; // [sp-8h] [bp-1F4h]@121
+  int v75; // [sp-8h] [bp-1F4h]@125
+  int v76; // [sp-8h] [bp-1F4h]@142
+  size_t v77; // [sp-4h] [bp-1F0h]@54
+  unsigned int v78; // [sp-4h] [bp-1F0h]@121
+  unsigned int v79; // [sp-4h] [bp-1F0h]@125
+  char *v80; // [sp-4h] [bp-1F0h]@142
+  char *v81; // [sp-4h] [bp-1F0h]@148
+  DDBLTFX Dst; // [sp+Ch] [bp-1E0h]@18
+  DDSURFACEDESC2 pDesc; // [sp+70h] [bp-17Ch]@18
+  RECT v84; // [sp+ECh] [bp-100h]@26
+  char *v85; // [sp+FCh] [bp-F0h]@145
+  char *v86; // [sp+100h] [bp-ECh]@145
+  char *v87; // [sp+104h] [bp-E8h]@145
+  char *v88; // [sp+108h] [bp-E4h]@145
+  char *v89; // [sp+10Ch] [bp-E0h]@145
+  char *v90; // [sp+110h] [bp-DCh]@145
+  char *v91; // [sp+114h] [bp-D8h]@145
+  char *v92; // [sp+118h] [bp-D4h]@145
+  char *v93; // [sp+11Ch] [bp-D0h]@145
+  char *v94; // [sp+120h] [bp-CCh]@145
+  char *v95; // [sp+124h] [bp-C8h]@127
+  char *v96; // [sp+128h] [bp-C4h]@127
+  char *v97; // [sp+12Ch] [bp-C0h]@127
+  char *v98; // [sp+130h] [bp-BCh]@127
+  char *v99; // [sp+134h] [bp-B8h]@127
+  char *v100; // [sp+138h] [bp-B4h]@127
+  char *v101; // [sp+13Ch] [bp-B0h]@127
+  char *v102; // [sp+140h] [bp-ACh]@127
+  char *v103; // [sp+144h] [bp-A8h]@127
+  char *v104; // [sp+148h] [bp-A4h]@127
+  char *v105; // [sp+14Ch] [bp-A0h]@127
+  RenderBillboardTransform_local0 v106; // [sp+150h] [bp-9Ch]@3
+  unsigned int v107; // [sp+1A0h] [bp-4Ch]@18
+  unsigned __int16 *v108; // [sp+1A4h] [bp-48h]@34
+  unsigned int v109; // [sp+1A8h] [bp-44h]@32
+  LPVOID v110; // [sp+1ACh] [bp-40h]@28
+  unsigned int v111; // [sp+1B0h] [bp-3Ch]@29
+  char **v112; // [sp+1B4h] [bp-38h]@3
+  IDirectDrawSurface *v222; // [sp+1B8h] [bp-34h]@18
+  unsigned __int8 v114; // [sp+1BFh] [bp-2Dh]@133
+  int v115; // [sp+1C0h] [bp-2Ch]@3
+  unsigned int v116; // [sp+1C4h] [bp-28h]@18
+  int i; // [sp+1C8h] [bp-24h]@18
+  Player *a2; // [sp+1CCh] [bp-20h]@28
+  int v119; // [sp+1D0h] [bp-1Ch]@18
+  SpellBuff *v120; // [sp+1D4h] [bp-18h]@18
+  Actor *v121; // [sp+1D8h] [bp-14h]@3
+  int a5; // [sp+1DCh] [bp-10h]@3
+  GUIWindow *a1; // [sp+1E0h] [bp-Ch]@1
+  int v124; // [sp+1E4h] [bp-8h]@18
+  char *a4; // [sp+1E8h] [bp-4h]@18
+
+  a1 = edx0;
+  v2 = uActorID;
+
+  static Actor pMonsterInfoUI_Doll;
+  /*if ( !(bMonsterInfoUI_bDollInitialized & 1) )
+  {
+    bMonsterInfoUI_bDollInitialized |= 1u;
+    Actor::Actor(&pMonsterInfoUI_Doll);
+    atexit(nullsub_3);
+  }*/
+  v106.uParentBillboardID = -1;
+  v3 = &pActors[v2];
+  v121 = v3;
+  v4 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xFFu, 0x9Bu);
+  v5 = v3->uNPC_ID;
+  a5 = v4;
+  v6 = GetNPCData(v5);
+  v7 = v3->pMonsterInfo.uID;
+  v112 = (char **)v6;
+  v115 = byte_4E2B70[((signed __int16)v7 - 1) / 3] - 40;
+  if ( v7 == pMonsterInfoUI_Doll.pMonsterInfo.uID )
+  {
+    v9 = pMonsterInfoUI_Doll.uCurrentActionLength;
+  }
+  else
+  {
+    memcpy(&pMonsterInfoUI_Doll, v3, sizeof(pMonsterInfoUI_Doll));
+    pMonsterInfoUI_Doll.uCurrentActionAnimation = 7;
+    pMonsterInfoUI_Doll.uCurrentActionTime = 0;
+    v8 = rand();
+    v3 = v121;
+    v9 = v8 % 256 + 128;
+    pMonsterInfoUI_Doll.uCurrentActionLength = v8 % 256 + 128;
+  }
+  if ( (signed int)pMonsterInfoUI_Doll.uCurrentActionTime > (signed __int16)v9 )
+  {
+    pMonsterInfoUI_Doll.uCurrentActionTime = 0;
+    if ( pMonsterInfoUI_Doll.uCurrentActionAnimation == 7 || pMonsterInfoUI_Doll.uCurrentActionAnimation == 2 )
+    {
+      pMonsterInfoUI_Doll.uCurrentActionAnimation = 0;
+      pMonsterInfoUI_Doll.uCurrentActionLength = rand() % 128 + 128;
+    }
+    else
+    {
+      rand();
+      pMonsterInfoUI_Doll.uCurrentActionAnimation = 7;
+      if ( (pMonsterInfoUI_Doll.pMonsterInfo.uID < 115 || pMonsterInfoUI_Doll.pMonsterInfo.uID > 186)
+        && (pMonsterInfoUI_Doll.pMonsterInfo.uID < 232 || pMonsterInfoUI_Doll.pMonsterInfo.uID > 249)
+        && rand() % 30 < 100 )
+        pMonsterInfoUI_Doll.uCurrentActionAnimation = 2;
+      pMonsterInfoUI_Doll.uCurrentActionLength = 8
+                                               * pSpriteFrameTable->pSpriteSFrames[v3->pSpriteIDs[(signed __int16)pMonsterInfoUI_Doll.uCurrentActionAnimation]].uAnimLength;
+    }
+  }
+  v10 = pSpriteFrameTable->GetFrame(
+          v3->pSpriteIDs[(signed __int16)pMonsterInfoUI_Doll.uCurrentActionAnimation],
+          pMonsterInfoUI_Doll.uCurrentActionTime);
+  v11 = 40 * v10->pHwSpriteIDs[0] + 7218180;
+  v106.pTarget = pRenderer->pTargetSurface;
+  v106.pTargetZ = pRenderer->pActiveZBuffer;
+  v106.uTargetPitch = pRenderer->uTargetSurfacePitch;
+  v12 = a1->uFrameY + 52;
+  v106.uViewportX = a1->uFrameX + 13;
+  v106.uViewportY = v12;
+  v106.uViewportW = v12 + 128;
+  v106.uViewportZ = v106.uViewportX + 128;
+  v106.uScreenSpaceX = (signed int)(v106.uViewportX + 128 + v106.uViewportX) / 2;
+  v106.field_10 = 65536;
+  v106.field_14 = 65536;
+  v106.uScreenSpaceY = v115 + v12 + *(short *)(v11 + 18);
+  v106.pPalette = PaletteManager::Get_Dark_or_Red_LUT(v10->uPaletteIndex, 0, 1);
+  v106.sZValue = 0;
+  v106.uFlags = 0;
+  pRenderer->Clip_v2(0, 0, 0x27Fu, 0x1DFu);
+  pRenderer->Line2D(v106.uViewportX - 1, v106.uViewportY - 1, v106.uViewportX + 129, v106.uViewportY - 1, a5);
+  pRenderer->Line2D(
+    v106.uViewportX + 129,
+    v106.uViewportY - 1,
+    v106.uViewportX + 129,
+    v106.uViewportW + 1,
+    a5);
+  pRenderer->Line2D(v106.uViewportX + 129, v106.uViewportW + 1, v106.uViewportX - 1, v106.uViewportW + 1, a5);
+  pRenderer->Line2D(v106.uViewportX - 1, v106.uViewportW + 1, v106.uViewportX - 1, v106.uViewportY - 1, a5);
+  if ( pRenderer->pRenderD3D )
+  {
+    v13 = &pSprites_LOD->pHardwareSprites[v10->pHwSpriteIDs[0]];
+    v106.uScreenSpaceY = v115 + v106.uViewportY + v13->uBufferHeight;
+    v222 = (IDirectDrawSurface *)v13->pTextureSurface;
+    memset(&Dst, 0, 0x64u);
+    Dst.dwSize = 100;
+    Dst.dwFillColor = 0;
+    memset(&pDesc, 0, 0x7Cu);
+    pDesc.dwSize = 124;
+    v222->GetSurfaceDesc((LPDDSURFACEDESC)&pDesc);
+    v14 = v13->uBufferHeight;
+    v120 = (SpellBuff *)v13->uBufferWidth;
+    v107 = 0;
+    v15 = v13->uAreaX;
+    v119 = (signed int)v120 / 2;
+    i = 0;
+    a4 = (char *)(v106.uScreenSpaceX + v15 - (signed int)v120 / 2);
+    v115 = v13->uAreaY;
+    v16 = v13->uAreaWidth + (signed int)v120 / 2 + v15 - (int)v120;
+    v124 = v106.uScreenSpaceY + v115 - v14;
+    v17 = v13->uAreaHeight + v115 - v14;
+    v116 = v106.uScreenSpaceX + v16;
+    v119 = v106.uScreenSpaceY + v17;
+    if ( (signed int)a4 < (signed int)v106.uViewportX )
+    {
+      v18 = v106.uViewportX - (int)a4;
+      a4 = (char *)v106.uViewportX;
+      v107 = v18;
+    }
+    if ( v124 < (signed int)v106.uViewportY )
+    {
+      v19 = v106.uViewportY - v124;
+      v124 = v106.uViewportY;
+      i = v19;
+    }
+    if ( (signed int)v116 > (signed int)v106.uViewportZ )
+      v116 = v106.uViewportZ;
+    if ( v119 > (signed int)v106.uViewportW )
+      v119 = v106.uViewportW;
+    pRenderer->FillRectFast(
+      v106.uViewportX,
+      v106.uViewportY,
+      v106.uViewportZ - v106.uViewportX,
+      v106.uViewportW - v106.uViewportY,
+      pRenderer->uTargetBMask | pRenderer->uTargetGMask);
+    pRenderer->FillRectFast(
+      v106.uViewportX,
+      v106.uViewportY,
+      v106.uViewportZ - v106.uViewportX,
+      v106.uViewportW - v106.uViewportY,
+      pRenderer->uTargetBMask | pRenderer->uTargetGMask);
+    v84.left = v106.uViewportX;
+    v84.top = v106.uViewportY;
+    v84.right = v106.uViewportZ;
+    v84.bottom = v106.uViewportW;
+    ErrD3D(pRenderer->pBackBuffer4->Blt(&v84, 0, 0, 16778240u, &Dst));
+    if ( pRenderer->uTargetGBits == 5 )
+    {
+      memset(&pDesc, 0, 0x7Cu);
+      pDesc.dwSize = 124;
+      if ( !pRenderer->LockSurface_DDraw4((IDirectDrawSurface4 *)v222, &pDesc, 1u) )
+        goto LABEL_51;
+      v20 = (char *)v124;
+      v110 = pDesc.lpSurface;
+      a2 = (Player *)v124;
+      if ( v124 < v119 )
+      {
+        v111 = 2 * pRenderer->uTargetSurfacePitch;
+        v21 = (int)a4;
+        v22 = &pRenderer->pTargetSurface[(int)&a4[v124 * pRenderer->uTargetSurfacePitch]];
+        v23 = i - v124;
+        v120 = (SpellBuff *)&pRenderer->pTargetSurface[(int)&a4[v124 * pRenderer->uTargetSurfacePitch]];
+        v115 = i - v124;
+        while ( 1 )
+        {
+          v124 = v21;
+          if ( v21 < (signed int)v116 )
+          {
+            v24 = (int)&v20[v23];
+            v25 = v107 - v21;
+            v109 = v24;
+            for ( i = v107 - v21; ; v25 = i )
+            {
+              v108 = (unsigned __int16 *)((pDesc.lPitch >> 1) * pDesc.dwHeight * v109 / v13->uAreaHeight);
+              v26 = (char *)v108 + pDesc.dwWidth * (v25 + v124++) / v13->uAreaWidth;
+              *v22 = *((short *)v110 + (int)v26);
+              ++v22;
+              if ( v124 >= (signed int)v116 )
+                break;
+            }
+            v23 = v115;
+          }
+          v22 = (unsigned __int16 *)((char *)v120 + v111);
+          v20 = (char *)&a2->pConditions[0] + 1;
+          v28 = __OFSUB__((int)&a2->pConditions[0] + 1, v119);
+          v27 = (signed int)((char *)&a2->pConditions[0] + -v119 + 1) < 0;
+          a2 = (Player *)((char *)a2 + 1);
+          v120 = (SpellBuff *)((char *)v120 + v111);
+          if ( !(v27 ^ v28) )
+            break;
+          v21 = (int)a4;
+        }
+      }
+      goto LABEL_37;
+    }
+    memset(&pDesc, 0, 0x7Cu);
+    pDesc.dwSize = 124;
+    if ( pRenderer->LockSurface_DDraw4((IDirectDrawSurface4 *)v222, &pDesc, 1u) )
+    {
+      v108 = (unsigned __int16 *)pDesc.lpSurface;
+      a2 = (Player *)v124;
+      if ( v124 < v119 )
+      {
+        v109 = 2 * pRenderer->uTargetSurfacePitch;
+        v29 = (int)a4;
+        v30 = (char *)&pRenderer->pTargetSurface[(int)&a4[v124 * pRenderer->uTargetSurfacePitch]];
+        v31 = i - v124;
+        v120 = (SpellBuff *)&pRenderer->pTargetSurface[(int)&a4[v124 * pRenderer->uTargetSurfacePitch]];
+        v115 = i - v124;
+        while ( 1 )
+        {
+          v124 = v29;
+          if ( v29 < (signed int)v116 )
+          {
+            v32 = v107 - (int)a4;
+            v111 = (unsigned int)((char *)a2 + v31);
+            for ( i = v107 - (int)a4; ; v32 = i )
+            {
+              v110 = (LPVOID)((pDesc.lPitch >> 1) * pDesc.dwHeight * v111 / v13->uAreaHeight);
+              v33 = v108[(int)((char *)v110 + pDesc.dwWidth * (v32 + v124) / v13->uAreaWidth)];
+              v34 = v33 & 0x1F | 2
+                               * (unsigned __int16)(v108[(int)((char *)v110
+                                                                + pDesc.dwWidth * (v32 + v124++) / v13->uAreaWidth)] & 0xFFE0);
+              v35 = v124;
+              *(short *)v30 = v34;
+              v30 += 2;
+              if ( v35 >= (signed int)v116 )
+                break;
+            }
+            v31 = v115;
+          }
+          a2 = (Player *)((char *)a2 + 1);
+          v30 = (char *)v120 + v109;
+          v120 = (SpellBuff *)((char *)v120 + v109);
+          if ( (signed int)a2 >= v119 )
+            break;
+          v29 = (int)a4;
+        }
+      }
+LABEL_37:
+      v222->Unlock(0);
+      goto LABEL_51;
+    }
+  }
+  else
+  {
+    pRenderer->FillRectFast(
+      v106.uViewportX,
+      v106.uViewportY,
+      v106.uViewportZ - v106.uViewportX,
+      v106.uViewportW - v106.uViewportY,
+      0);
+    v36 = v10->pHwSpriteIDs[0];
+    if ( v36 >= 0 )
+      pSprites_LOD->pSpriteHeaders[v36]._4ACC38(&v106, 0);
+  }
+LABEL_51:
+  if ( v121->uNPC_ID )
+  {
+    v37 = v112[6];
+    if ( v37 )
+    {
+      sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[429], *v112, aNPCProfessionNames[(signed int)v37]);
+      goto LABEL_59;
+    }
+    v77 = 2000;
+    v72 = *v112;
+  }
+  else
+  {
+    v38 = v121->dword_000334_unique_name;
+    v77 = 2000;
+    if ( v38 )
+      v72 = (char *)*(&pMonsterStats->pPlacement.uNumStrings + v38);
+    else
+      v72 = pMonsterStats->pInfos[v121->pMonsterInfo.uID].pName;
+  }
+  strncpy(pTmpBuf, v72, v77);
+LABEL_59:
+  v39 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  a1->DrawTitleText(pFontComic, 0, 0xCu, v39, pTmpBuf, 3u);
+  Actor::DrawHealthBar(v121, a1);
+  v119 = 0;
+  pMonsterInfoUI_Doll.uCurrentActionTime += pMiscTimer->uTimeElapsed;
+  v115 = 0;
+  v116 = 0;
+  i = 0;
+  v112 = 0;
+  if ( !uActiveCharacter )
+  {
+    v45 = 1;
+    goto LABEL_84;
+  }
+  LOBYTE(v40) = pPlayers[uActiveCharacter]->GetActualSkillLevel(PLAYER_SKILL_MONSTER_ID);
+  v120 = v40;
+  if ( !v40 )
+    goto LABEL_72;
+  v41 = (unsigned __int8)v40 & 0x3F;
+  v42 = SkillToMastery((unsigned __int16)v40) - 1;
+  if ( !v42 )
+  {
+    if ( v41 + 10 >= v121->pMonsterInfo.uLevel )
+    {
+      v45 = 1;
+      v119 = 1;
+      goto LABEL_73;
+    }
+    goto LABEL_72;
+  }
+  v43 = v42 - 1;
+  if ( !v43 )
+  {
+    if ( 2 * v41 + 10 >= v121->pMonsterInfo.uLevel )
+    {
+      v45 = 1;
+      v119 = 1;
+      v116 = 1;
+      goto LABEL_73;
+    }
+    goto LABEL_72;
+  }
+  v44 = v43 - 1;
+  if ( !v44 )
+  {
+    if ( 3 * v41 + 10 >= v121->pMonsterInfo.uLevel )
+    {
+      v45 = 1;
+      v119 = 1;
+      v116 = 1;
+      i = 1;
+      goto LABEL_73;
+    }
+LABEL_72:
+    v45 = 1;
+    goto LABEL_73;
+  }
+  if ( v44 != 1 )
+    goto LABEL_72;
+  v45 = 1;
+  v119 = 1;
+  v116 = 1;
+  i = 1;
+  v112 = (char **)1;
+LABEL_73:
+  v46 = v121->uAIState;
+  if ( v46 != 5 && v46 != 4 && !dword_507BF0_is_there_popup_onscreen && v120 )
+  {
+    v47 = pPlayers[uActiveCharacter];
+    if ( v119 | v116 | i | (unsigned int)v112 )
+    {
+      if ( v121->pMonsterInfo.uLevel >= v47->uLevel - 5 )
+        v73 = 105;
+      else
+        v73 = 104;
+    }
+    else
+    {
+      v73 = 106;
+    }
+    v47->PlaySound(v73, 0);
+  }
+LABEL_84:
+  a2 = pParty->pPlayers;
+  do
+  {
+    LOBYTE(v48) = a2->GetActualSkillLevel(PLAYER_SKILL_MONSTER_ID);
+    v111 = v48;
+    v120 = (SpellBuff *)138;
+    do
+    {
+      if ( (signed int)SkillToMastery(v111) >= 3 )
+        v115 = v45;
+      v120 = (SpellBuff *)((char *)v120 - 1);
+    }
+    while ( v120 );
+    ++a2;
+  }
+  while ( (signed int)a2 < (signed int)pParty->pHirelings );
+  v49 = pFontSmallnum;
+  a2 = (Player *)pFontSmallnum;
+  a1->DrawText(pFontSmallnum, 12, 196, a5, pGlobalTXT_LocalizationStrings[631], 0, 0, 0);
+  v50 = LOBYTE(v49->uFontHeight) + 193;
+  if ( !v115 )
+  {
+    v78 = 0;
+    v74 = 0;
+    v69 = 0;
+    v66 = pGlobalTXT_LocalizationStrings[630];
+    goto LABEL_123;
+  }
+  a4 = 0;
+  v51 = &v121->pActorBuffs[1];
+  v222 = 0;
+  v120 = &v121->pActorBuffs[1];
+  do
+  {
+    if ( (signed __int64)v51->uExpireTime > 0 )
+    {
+      switch ( (int)v51 )
+      {
+        case 0u:
+          v124 = 60;
+          a4 = pGlobalTXT_LocalizationStrings[591];
+          break;
+        case 1u:
+          v124 = 82;
+          a4 = pGlobalTXT_LocalizationStrings[649];
+          break;
+        case 2u:
+          v124 = 92;
+          a4 = pGlobalTXT_LocalizationStrings[592];
+          break;
+        case 3u:
+          v124 = 63;
+          a4 = pGlobalTXT_LocalizationStrings[4];
+          break;
+        case 4u:
+          v52 = pGlobalTXT_LocalizationStrings[220];
+          goto LABEL_100;
+        case 5u:
+          v52 = pGlobalTXT_LocalizationStrings[162];
+LABEL_100:
+          a4 = v52;
+          v124 = 81;
+          break;
+        case 6u:
+          v53 = pGlobalTXT_LocalizationStrings[593];
+          v124 = 35;
+          goto LABEL_103;
+        case 8u:
+          v53 = pGlobalTXT_LocalizationStrings[608];
+          v124 = 62;
+LABEL_103:
+          a4 = v53;
+          break;
+        case 7u:
+        case 9u:
+          a4 = 0;
+          v124 = 0;
+          goto LABEL_119;
+        case 0xAu:
+          v124 = 47;
+          a4 = pGlobalTXT_LocalizationStrings[221];
+          break;
+        case 0xBu:
+          v124 = 66;
+          a4 = pGlobalTXT_LocalizationStrings[607];
+          break;
+        case 0xCu:
+          v124 = 85;
+          a4 = pGlobalTXT_LocalizationStrings[610];
+          break;
+        case 0xDu:
+          v124 = 86;
+          a4 = pGlobalTXT_LocalizationStrings[609];
+          break;
+        case 0xEu:
+          v124 = 17;
+          a4 = pGlobalTXT_LocalizationStrings[279];
+          break;
+        case 0xFu:
+          v124 = 38;
+          a4 = pGlobalTXT_LocalizationStrings[442];
+          break;
+        case 0x10u:
+          v124 = 46;
+          a4 = pGlobalTXT_LocalizationStrings[443];
+          break;
+        case 0x11u:
+          v124 = 51;
+          a4 = pGlobalTXT_LocalizationStrings[440];
+          break;
+        case 0x12u:
+          v124 = 5;
+          a4 = pGlobalTXT_LocalizationStrings[441];
+          break;
+        case 0x13u:
+          v124 = 95;
+          a4 = pGlobalTXT_LocalizationStrings[229];
+          break;
+        case 0x14u:
+          v124 = 73;
+          a4 = pGlobalTXT_LocalizationStrings[228];
+          break;
+        default:
+          a4 = 0;
+          break;
+      }
+      if ( a4 )
+      {
+        v54 = a4;
+        v55 = GetSpellColor(v124);
+        a1->DrawText((GUIFont *)a2, 28, v50, v55, v54, 0, 0, 0);
+        v50 = v50 + BYTE5(a2->pConditions[0]) - 3;
+        v51 = v120;
+      }
+    }
+LABEL_119:
+    ++v51;
+    v222 = (IDirectDrawSurface *)((char *)v222 + 1);
+    v120 = v51;
+
+    __debugbreak(); // fix condition
+  }
+  //while ( (signed int)((char *)&v222->lpVtbl + 1) < 22 );
+  while (true);
+  if ( !a4 )
+  {
+    v78 = 0;
+    v74 = 0;
+    v69 = 0;
+    v66 = pGlobalTXT_LocalizationStrings[153];
+LABEL_123:
+    a1->DrawText((GUIFont *)a2, 28, v50, a5, v66, v69, v74, v78);
+  }
+  v56 = pFontSmallnum;
+  a4 = (char *)v106.uViewportY;
+  if ( v119 )
+  {
+    sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[108], 0, v121->pMonsterInfo.uHP);
+    a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+    a4 = &a4[LOBYTE(v56->uFontHeight) - 3];
+    v79 = v121->pMonsterInfo.uAC;
+    v75 = 0;
+    v70 = pGlobalTXT_LocalizationStrings[12];
+    v67 = "%s";
+  }
+  else
+  {
+    sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[108], 0, pGlobalTXT_LocalizationStrings[630]);
+    a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+    v79 = (unsigned int)pGlobalTXT_LocalizationStrings[630];
+    v75 = 0;
+    v70 = pGlobalTXT_LocalizationStrings[12];
+    a4 = &a4[LOBYTE(v56->uFontHeight) - 3];
+    v67 = "%s";
+  }
+  sprintf(pTmpBuf, v67, v70, v75, v79);
+  a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+  a4 = &a4[LOBYTE(v56->uFontHeight) - 6] + LOBYTE(v56->uFontHeight);
+  v95 = pGlobalTXT_LocalizationStrings[87];
+  v96 = pGlobalTXT_LocalizationStrings[6];
+  v97 = pGlobalTXT_LocalizationStrings[240];
+  v98 = pGlobalTXT_LocalizationStrings[70];
+  v99 = pGlobalTXT_LocalizationStrings[624];
+  v100 = pGlobalTXT_LocalizationStrings[138];
+  v101 = pGlobalTXT_LocalizationStrings[214];
+  v102 = pGlobalTXT_LocalizationStrings[142];
+  v103 = pGlobalTXT_LocalizationStrings[29];
+  v104 = pGlobalTXT_LocalizationStrings[133];
+  v105 = pGlobalTXT_LocalizationStrings[54];
+  if ( v116 )
+  {
+    sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[18], 0, (&v95)[4 * v121->pMonsterInfo.uAttack1Type]);
+    a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+    a4 = &a4[LOBYTE(v56->uFontHeight) - 3];
+    v57 = v121->pMonsterInfo.uAttack1DamageBonus;
+    if ( v57 )
+      sprintf(
+        pTmpBuf,
+        "%s",
+        pGlobalTXT_LocalizationStrings[53],
+        0,
+        v121->pMonsterInfo.uAttack1DamageDiceRolls,
+        v121->pMonsterInfo.uAttack1DamageDiceSides,
+        v57);
+    else
+      sprintf(
+        pTmpBuf,
+        "%s",
+        pGlobalTXT_LocalizationStrings[53],
+        0,
+        v121->pMonsterInfo.uAttack1DamageDiceRolls,
+        v121->pMonsterInfo.uAttack1DamageDiceSides);
+  }
+  else
+  {
+    sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[18], 0, pGlobalTXT_LocalizationStrings[630]);
+    a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+    a4 = &a4[LOBYTE(v56->uFontHeight) - 3];
+    sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[53], 0, pGlobalTXT_LocalizationStrings[630]);
+  }
+  a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+  v58 = LOBYTE(v56->uFontHeight);
+  a4 = &a4[v58 - 6] + v58;
+  if ( !i )
+  {
+    v80 = pGlobalTXT_LocalizationStrings[630];
+    v76 = 0;
+    v71 = pGlobalTXT_LocalizationStrings[628];
+    v68 = "%s";
+    goto LABEL_144;
+  }
+  v120 = (SpellBuff *)pGlobalTXT_LocalizationStrings[628];
+  v59 = v121;
+  v114 = v121->pMonsterInfo.uSpell1ID;
+  if ( v114 && v121->pMonsterInfo.uSpell2ID )
+    v120 = (SpellBuff *)pGlobalTXT_LocalizationStrings[629];
+  if ( v114 )
+  {
+    sprintf(pTmpBuf, "%s", v120, 0, pSpellStats->pInfos[v114].pShortName);
+    a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+    v58 = LOBYTE(v56->uFontHeight);
+    a4 = &a4[v58 - 3];
+    v59 = v121;
+  }
+  v60 = v59->pMonsterInfo.uSpell2ID;
+  if ( v60 )
+  {
+    __debugbreak();
+    const char *fmt = "\xC\x25\x30\x35\x75\x9\x30\x36\x30\x25\x73\n";
+    sprintf(pTmpBuf, fmt, 0, pSpellStats->pInfos[v60].pShortName);
+    a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+    v58 = LOBYTE(v56->uFontHeight);
+    a4 = &a4[v58 - 3];
+    v59 = v121;
+  }
+  if ( !v59->pMonsterInfo.uSpell1ID && !v59->pMonsterInfo.uSpell2ID )
+  {
+    v80 = pGlobalTXT_LocalizationStrings[153];
+    v76 = 0;
+    v71 = pGlobalTXT_LocalizationStrings[628];
+    v68 = "%s";
+LABEL_144:
+    sprintf(pTmpBuf, v68, v71, v76, v80);
+    a1->DrawText(v56, 150, (int)a4, a5, pTmpBuf, 0, 0, 0);
+    v58 = LOBYTE(v56->uFontHeight);
+    a4 = &a4[v58 - 3];
+  }
+  a4 = &a4[v58 - 3];
+  a1->DrawText(v56, 150, (int)a4, a5, pGlobalTXT_LocalizationStrings[626], 0, 0, 0);
+  a4 = &a4[LOBYTE(v56->uFontHeight) - 3];
+  v85 = pGlobalTXT_LocalizationStrings[87];
+  v86 = pGlobalTXT_LocalizationStrings[6];
+  v87 = pGlobalTXT_LocalizationStrings[240];
+  v88 = pGlobalTXT_LocalizationStrings[70];
+  v89 = pGlobalTXT_LocalizationStrings[142];
+  v90 = pGlobalTXT_LocalizationStrings[214];
+  v91 = pGlobalTXT_LocalizationStrings[29];
+  v92 = pGlobalTXT_LocalizationStrings[133];
+  v93 = pGlobalTXT_LocalizationStrings[54];
+  v94 = pGlobalTXT_LocalizationStrings[624];
+  v96 = (char *)v121->pMonsterInfo.uResFire;
+  v97 = (char *)v121->pMonsterInfo.uResAir;
+  v98 = (char *)v121->pMonsterInfo.uResWater;
+  v99 = (char *)v121->pMonsterInfo.uResEarth;
+  v100 = (char *)v121->pMonsterInfo.uResMind;
+  v101 = (char *)v121->pMonsterInfo.uResSpirit;
+  v102 = (char *)v121->pMonsterInfo.uResBody;
+  v103 = (char *)v121->pMonsterInfo.uResLight;
+  v61 = (char *)v121->pMonsterInfo.uResPhysical;
+  v104 = (char *)v121->pMonsterInfo.uResDark;
+  v105 = v61;
+  if ( v112 )
+  {
+    v124 = 0;
+    do
+    {
+      v62 = (&v96)[v124];
+      if ( v62 == (char *)200 )
+      {
+        v81 = pGlobalTXT_LocalizationStrings[625];
+      }
+      else
+      {
+        if ( v62 )
+          v81 = pGlobalTXT_LocalizationStrings[627];
+        else
+          v81 = pGlobalTXT_LocalizationStrings[153];
+      }
+      sprintf(pTmpBuf, "%s", (&v85)[v124], 0, v81);
+      a1->DrawText(v56, 170, (int)a4, a5, pTmpBuf, 0, 0, 0);
+      v63 = LOBYTE(v56->uFontHeight);
+      v124 += 4;
+      result = &a4[v63 - 3];
+      a4 = result;
+    }
+    while ( v124 < 40 );
+  }
+  else
+  {
+    i = 0;
+    do
+    {
+      sprintf(pTmpBuf, "%s", (&v85)[4 * i], 0, pGlobalTXT_LocalizationStrings[630]);
+      a1->DrawText(v56, 170, (int)a4, a5, pTmpBuf, 0, 0, 0);
+      v65 = LOBYTE(v56->uFontHeight);
+      ++i;
+      result = &a4[v65 - 3];
+      a4 = result;
+    }
+    while ( i < 10 );
+  }
+  if ( (signed __int64)pParty->pPartyBuffs[3].uExpireTime > 0 )
+  {
+    sprintf(pTmpBuf, "%s: %d", pGlobalTXT_LocalizationStrings[650], v121->sCurrentHP);
+    pFontSmallnum->GetLineWidth(pTmpBuf);
+    result = a1->DrawTitleText(
+               pFontSmallnum,
+               0,
+               a1->uFrameHeight - LOBYTE(pFontSmallnum->uFontHeight) - 12,
+               0,
+               pTmpBuf,
+               3u);
+  }
+  return result;
+}
+
+
+
+//----- (0041F54A) --------------------------------------------------------
+void __cdecl LoadActualSkyFrame()
+{
+  if ( pTexture_RestUI_CurrentSkyFrame )
+    pTexture_RestUI_CurrentSkyFrame->Release();
+  if ( pTexture_RestUI_CurrentHourglassFrame )
+    pTexture_RestUI_CurrentHourglassFrame->Release();
+  pIcons_LOD->_40F9C5();
+  sprintf(pTmpBuf, "TERRA%03d", pParty->uCurrentMinute / 6 + 10 * pParty->uCurrentHour);
+  pTexture_RestUI_CurrentSkyFrame = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pTmpBuf, TEXTURE_16BIT_PALETTE)];
+}
+
+//----- (0041F5BE) --------------------------------------------------------
+void __cdecl Sleep6Hours()
+{
+  if ( _506F18_num_hours_to_sleep < 6 )
+  {
+    pParty->pPlayers[3].pConditions[2] = 0i64;
+    pParty->pPlayers[2].pConditions[2] = 0i64;
+    pParty->pPlayers[1].pConditions[2] = 0i64;
+    pParty->pPlayers[0].pConditions[2] = 0i64;
+    if ( _506F18_num_hours_to_sleep )
+    {
+      Rest(_506F18_num_hours_to_sleep);
+      _506F18_num_hours_to_sleep = 0;
+      LoadActualSkyFrame();
+    }
+    if ( dword_506F14 == 2 )
+    {
+      pGUIWindow_CurrentMenu->Release();
+      pEventTimer->Resume();
+      if ( pTexture_RestUI_CurrentSkyFrame )
+        pTexture_RestUI_CurrentSkyFrame->Release();
+      if ( pTexture_RestUI_CurrentHourglassFrame )
+        pTexture_RestUI_CurrentHourglassFrame->Release();
+      pTexture_RestUI_CurrentHourglassFrame = 0;
+      pTexture_RestUI_CurrentSkyFrame = 0;
+      pIcons_LOD->_4114F2();
+      pIcons_LOD->_40F9C5();
+      pCurrentScreen = 0;
+      viewparams->bRedrawGameUI = 1;
+      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+      {
+        pOutdoor->UpdateSunlightVectors();
+        pOutdoor->UpdateFog();
+      }
+    }
+    dword_506F14 = 0;
+  }
+  else
+  {
+    Rest(6u);
+    _506F18_num_hours_to_sleep -= 6;
+    LoadActualSkyFrame();
+  }
+  viewparams->bRedrawGameUI = 1;
+}
+
+//----- (0041F6C1) --------------------------------------------------------
+void __cdecl RestUI_Initialize()
+{
+  char *v0; // eax@10
+
+  if ( !dword_506F14 )
+    pAudioPlayer->StopChannels(-1, -1);
+  if ( pCurrentScreen )
+  {
+    pGUIWindow_CurrentMenu->Release();
+    pCurrentScreen = 0;
+    viewparams->bRedrawGameUI = 1;
+  }
+  pEventTimer->Pause();
+  if ( dword_506F14 != 2 )
+    GUIWindow::Create(518u, 450u, 0, 0, (enum WindowType)90, (int)pBtn_Rest, 0);
+  _506F18_num_hours_to_sleep = 0;
+  dword_506F14 = 0;
+  uRestUI_FoodRequiredToRest = 2;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    uRestUI_FoodRequiredToRest = pOutdoor->GetNumFoodRequiredToRestInCurrentPos(
+                                   pParty->vPosition.x,
+                                   pParty->vPosition.y,
+                                   pParty->vPosition.z);
+  if ( sub_476387() )
+  {
+    v0 = (char *)&pParty->pPlayers[0].uClass;
+    while ( *v0 != 31 )
+    {
+      v0 += 6972;
+      if ( (signed int)v0 >= (signed int)((char *)&pParty->pPickedItem.uExpireTime + 5) )
+        goto LABEL_15;
+    }
+    ++uRestUI_FoodRequiredToRest;
+  }
+LABEL_15:
+  if ( CheckHiredNPCSpeciality(0x1Du) )
+    --uRestUI_FoodRequiredToRest;
+  if ( CheckHiredNPCSpeciality(0x1Eu) )
+    uRestUI_FoodRequiredToRest -= 2;
+  if ( CheckHiredNPCSpeciality(0x30u) )
+    --uRestUI_FoodRequiredToRest;
+  if ( uRestUI_FoodRequiredToRest < 1 )
+    uRestUI_FoodRequiredToRest = 1;
+  if ( !_strcmpi(pCurrentMapName, "d29.blv") && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 98) )
+    uRestUI_FoodRequiredToRest = 0;
+  ++pIcons_LOD->uTexturePacksCount;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  pCurrentScreen = 5;
+  _507CD4_RestUI_hourglass_anim_controller = 0;
+  uTextureID_RestUI_restmain = pIcons_LOD->LoadTexture("restmain", TEXTURE_16BIT_PALETTE);
+  uTextureID_RestUI_restb1 = pIcons_LOD->LoadTexture("restb1", TEXTURE_16BIT_PALETTE);
+  uTextureID_RestUI_restb2 = pIcons_LOD->LoadTexture("restb2", TEXTURE_16BIT_PALETTE);
+  uTextureID_RestUI_restb3 = pIcons_LOD->LoadTexture("restb3", TEXTURE_16BIT_PALETTE);
+  uTextureID_RestUI_restb4 = pIcons_LOD->LoadTexture("restb4", TEXTURE_16BIT_PALETTE);
+  uTextureID_RestUI_restexit = pIcons_LOD->LoadTexture("restexit", TEXTURE_16BIT_PALETTE);
+  LoadActualSkyFrame();
+  pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640u, 480u, (enum WindowType)16, 0, 0);
+  pButton_RestUI_Exit = pGUIWindow_CurrentMenu->CreateButton(
+                          280u,
+                          297u,
+                          154u,
+                          37u,
+                          1,
+                          0,
+                          0xA7u,
+                          0,
+                          0,
+                          "",
+                          (Texture *)(uTextureID_RestUI_restexit != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_RestUI_restexit] : 0),
+                          0);
+  pButton_RestUI_Main = pGUIWindow_CurrentMenu->CreateButton(
+                            24u,
+                            154u,
+                            225u,
+                            37u,
+                            1,
+                            0,
+                            0x61u,
+                            0,
+                            0x52u,
+                            "",
+                            (Texture *)(uTextureID_RestUI_restb4 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_RestUI_restb4] : 0),
+                            0);
+  pButton_RestUI_WaitUntilDawn = pGUIWindow_CurrentMenu->CreateButton(
+                                   61u,
+                                   232u,
+                                   154u,
+                                   33u,
+                                   1,
+                                   0,
+                                   0x6Du,
+                                   0,
+                                   0x44u,
+                                   "",
+                                   (Texture *)(uTextureID_RestUI_restb1 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_RestUI_restb1] : 0),
+                                   0);
+  pButton_RestUI_Wait1Hour = pGUIWindow_CurrentMenu->CreateButton(
+                               61u,
+                               264u,
+                               154u,
+                               33u,
+                               1,
+                               0,
+                               0x60u,
+                               0,
+                               0x48u,
+                               "",
+                               (Texture *)(uTextureID_RestUI_restb2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_RestUI_restb2] : 0),
+                               0);
+  pButton_RestUI_Wait5Minutes = pGUIWindow_CurrentMenu->CreateButton(
+                                  61u,
+                                  296u,
+                                  154u,
+                                  33u,
+                                  1,
+                                  0,
+                                  0x5Fu,
+                                  0,
+                                  0x4Du,
+                                  "",
+                                  (Texture *)(uTextureID_RestUI_restb3 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_RestUI_restb3] : 0),
+                                  0);
+}
+
+//----- (0041FA01) --------------------------------------------------------
+void __cdecl RestUI_Draw()
+{
+  int v0; // esi@1
+  Player **ppPlayers; // ecx@1
+  Player *pPlayer; // eax@2
+  unsigned int v3; // eax@15
+  char v4; // al@17
+  bool v5; // eax@21
+  GUIButton Dst; // [sp+8h] [bp-DCh]@19
+  //double v7; // [sp+C4h] [bp-20h]@17
+  float v8; // [sp+CCh] [bp-18h]@17
+  __int64 v9; // [sp+D0h] [bp-14h]@17
+  unsigned int v10; // [sp+D8h] [bp-Ch]@9
+  __int16 a9[2]; // [sp+DCh] [bp-8h]@1
+  int a5; // [sp+E0h] [bp-4h]@1
+
+  v0 = 0;
+  a5 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xAu, 0, 0);
+  *(int *)a9 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE6u, 0xD6u, 0xC1u);
+  ppPlayers = &pPlayers[1];
+  do
+  {
+    pPlayer = *ppPlayers;
+    if ( !(*ppPlayers)->pConditions[14] && !pPlayer->pConditions[16] && pPlayer->sHealth > 0 )
+      ++v0;
+    ++ppPlayers;
+  }
+  while ( (signed int)ppPlayers <= (signed int)&pPlayers[4] );
+  if ( v0 )
+  {
+    pRenderer->DrawTextureIndexed(
+      8u,
+      8u,
+      (Texture *)(uTextureID_RestUI_restmain != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_RestUI_restmain] : 0));
+    v10 = pParty->uCurrentHour;
+    dword_506F1C = pGUIWindow_CurrentMenu->pCurrentPosActiveItem;
+    if ( (signed int)pParty->uCurrentHour <= 12 )
+    {
+      if ( !v10 )
+        v10 = 12;
+    }
+    else
+    {
+      v10 -= 12;
+    }
+    pRenderer->DrawTextureIndexed(16u, 26u, pTexture_RestUI_CurrentSkyFrame);
+    if ( pTexture_RestUI_CurrentHourglassFrame )
+    {
+      pTexture_RestUI_CurrentHourglassFrame->Release();
+      pIcons_LOD->_40F9C5();
+    }
+    v3 = pEventTimer->uTimeElapsed + _507CD4_RestUI_hourglass_anim_controller;
+    _507CD4_RestUI_hourglass_anim_controller += pEventTimer->uTimeElapsed;
+    if ( (unsigned int)_507CD4_RestUI_hourglass_anim_controller >= 512 )
+    {
+      v3 = 0;
+      _507CD4_RestUI_hourglass_anim_controller = 0;
+    }
+    v9 = v3;
+    v8 = (double)v3 * 0.001953125 * 120.0;
+    //v7 = v8 + 6.7553994e15;
+    HIDWORD(v9) = floorf(v8 + 0.5f);//LODWORD(v7);
+    v4 = (int)floorf(v8 + 0.5f) % 256 + 1;//LOBYTE(v7) + 1;
+    byte_4E2BC8 = v4;
+    if ( (unsigned __int8)(v4) >= 0x78u )
+    {
+      v4 = 1;
+      byte_4E2BC8 = 1;
+    }
+    sprintf(pTmpBuf, "hglas%03d", (unsigned __int8)v4);
+    pTexture_RestUI_CurrentHourglassFrame = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pTmpBuf, TEXTURE_16BIT_PALETTE)];
+    pRenderer->DrawTextureIndexed(0x10Bu, 0x9Fu, pTexture_RestUI_CurrentHourglassFrame);
+    memset(&Dst, 0, 0xBCu);
+    Dst.uX = 24;
+    Dst.uY = 154;
+    Dst.uWidth = 171;
+    Dst.uHeight = 37;
+    Dst.uZ = 194;
+    Dst.uW = 190;
+    Dst.pParent = pButton_RestUI_WaitUntilDawn->pParent;
+    Dst.DrawLabel(pGlobalTXT_LocalizationStrings[183], pFontCreate, a5, *(int **)a9);
+    Dst.pParent = 0;
+    sprintf(pTmpBuf, "\r408%d", uRestUI_FoodRequiredToRest);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, 0, 164, a5, pTmpBuf, 0, 0, *(unsigned int *)a9);
+    pButton_RestUI_WaitUntilDawn->DrawLabel(
+      pGlobalTXT_LocalizationStrings[237],
+      pFontCreate,
+      a5,
+      *(int **)a9);
+    pButton_RestUI_Wait1Hour->DrawLabel(pGlobalTXT_LocalizationStrings[239], pFontCreate, a5, *(int **)a9);
+    pButton_RestUI_Wait5Minutes->DrawLabel(pGlobalTXT_LocalizationStrings[238], pFontCreate, a5, *(int **)a9);
+    pButton_RestUI_Exit->DrawLabel(pGlobalTXT_LocalizationStrings[81], pFontCreate, a5, *(int **)a9);
+    memset(&Dst, 0, 0xBCu);
+    Dst.uX = 45;
+    Dst.uY = 199;
+    Dst.uWidth = 185;
+    Dst.uHeight = 30;
+    Dst.uZ = 229;
+    Dst.uW = 228;
+    Dst.pParent = pButton_RestUI_WaitUntilDawn->pParent;
+    Dst.DrawLabel(pGlobalTXT_LocalizationStrings[236], pFontCreate, a5, *(int **)a9);
+    Dst.pParent = 0;
+    v5 = pParty->uCurrentHour >= 0xC && pParty->uCurrentHour < 0x18;
+    sprintf(pTmpBuf, "%d:%02d %s", v10, pParty->uCurrentMinute, aAMPMNames[v5]);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, 368, 168, a5, pTmpBuf, 0, 0, *(unsigned int *)a9);
+    sprintf(pTmpBuf, "%s\r190%d", pGlobalTXT_LocalizationStrings[56], pParty->uDaysPlayed + 1);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, 350, 190, a5, pTmpBuf, 0, 0, *(unsigned int *)a9);
+    sprintf(pTmpBuf, "%s\r190%d", pGlobalTXT_LocalizationStrings[146], pParty->uCurrentMonth + 1);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, 350, 222, a5, pTmpBuf, 0, 0, *(unsigned int *)a9);
+    sprintf(pTmpBuf, "%s\r190%d", pGlobalTXT_LocalizationStrings[245], pParty->uCurrentYear);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, 350, 254, a5, pTmpBuf, 0, 0, *(unsigned int *)a9);
+    if ( dword_506F14 )
+      Sleep6Hours();
+  }
+  else
+  {
+    GUIWindow::Create(
+      pButton_RestUI_Exit->uX,
+      pButton_RestUI_Exit->uY,
+      0,
+      0,
+      (enum WindowType)96,
+      (int)pButton_RestUI_Exit,
+      (int)pGlobalTXT_LocalizationStrings[81]);
+  }
+}
+// 4E2BC8: using guessed type char byte_4E2BC8;
+// 506F14: using guessed type int dword_506F14;
+// 506F1C: using guessed type int dword_506F1C;
+// 50765C: using guessed type int uTextureID_RestUI_restmain;
+// 507CD4: using guessed type int 507CD4_RestUI_hourglass_anim_controller;
+
+//----- (0041FE71) --------------------------------------------------------
+int Chest::CanPlaceItemAt(signed int a1, int a2, unsigned int uChestID)
+{
+  int v3; // eax@1
+  unsigned int v4; // eax@1
+  Texture *v5; // ecx@1
+  signed int v6; // eax@1
+  signed int v7; // edi@3
+  signed int v8; // eax@3
+  int v9; // edi@3
+  int v10; // ebx@5
+  int v11; // esi@9
+  int v12; // edx@10
+  int v13; // ecx@11
+  char *v14; // eax@12
+  int v16; // [sp+Ch] [bp-Ch]@1
+  signed int v17; // [sp+10h] [bp-8h]@1
+  signed int v18; // [sp+14h] [bp-4h]@1
+
+  v17 = a1;
+  v3 = pChests[uChestID].uChestBitmapID;
+  v16 = pChestHeightsByType[v3];
+  v18 = pChestWidthsByType[v3];
+  v4 = pIcons_LOD->LoadTexture(pItemsTable->pItems[a2].pIconName, TEXTURE_16BIT_PALETTE);
+  v5 = (Texture *)(v4 != -1 ? (int)&pIcons_LOD->pTextures[v4] : 0);
+  v6 = (v4 != -1 ? pIcons_LOD->pTextures[v4].uTextureWidth : 24);
+  if ( v6 < 14 )
+    v6 = 14;
+  v7 = v6 - 14;
+  v8 = v5->uTextureHeight;
+  v9 = (v7 >> 5) + 1;
+  if ( v8 < 14 )
+    v8 = 14;
+  v10 = ((v8 - 14) >> 5) + 1;
+  if ( !areWeLoadingTexture )
+  {
+    v5->Release();
+    pIcons_LOD->_40F9C5();
+  }
+  if ( v9 + v17 % v18 <= v18 && v10 + v17 / v18 <= v16 )
+  {
+    v11 = 0;
+    if ( v10 <= 0 )
+      return 1;
+    v12 = 0;
+    while ( 1 )
+    {
+      v13 = 0;
+      if ( v9 > 0 )
+        break;
+LABEL_15:
+      v12 += v18;
+      ++v11;
+      if ( v11 >= v10 )
+        return 1;
+    }
+    v14 = (char *)&pChests[0].pInventoryIndices[v17 + v12 + 2662 * uChestID];
+    while ( !*(short *)v14 )
+    {
+      ++v13;
+      v14 += 2;
+      if ( v13 >= v9 )
+        goto LABEL_15;
+    }
+  }
+  return 0;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (0041FF64) --------------------------------------------------------
+int Chest::_41FF64(unsigned int uChestID)
+{
+  unsigned int v1; // ecx@1
+  signed int result; // eax@1
+  int v3; // edx@1
+  ItemGen *pItem; // ecx@2
+
+  v1 = uChestID;
+  result = 0;
+  v3 = pChestWidthsByType[pChests[v1].uChestBitmapID] * pChestHeightsByType[pChests[v1].uChestBitmapID];
+  if ( v3 <= 0 )
+  {
+LABEL_5:
+    result = -1;
+  }
+  else
+  {
+    pItem = pChests[v1].mm7__vector_pItems;
+    while ( pItem->uItemID )
+    {
+      ++result;
+      ++pItem;
+      if ( result >= v3 )
+        goto LABEL_5;
+    }
+  }
+  return result;
+}
+
+//----- (0041FFA2) --------------------------------------------------------
+int Chest::_41FFA2(int a1, ItemGen *a2, unsigned int uChestID)
+{
+  int v3; // eax@1
+  ItemGen *v4; // edi@1
+  int v5; // esi@1
+  int result; // eax@11
+  unsigned int v7; // eax@12
+  int v8; // edx@12
+  int v9; // ecx@12
+  signed int v10; // eax@12
+  signed int v11; // edi@14
+  unsigned int v12; // esi@14
+  int v13; // edi@16
+  void *v14; // edi@21
+  int v15; // edi@21
+  int i; // ecx@21
+  ItemGen *Src; // [sp+Ch] [bp-18h]@1
+  signed int v18; // [sp+10h] [bp-14h]@2
+  int v19; // [sp+14h] [bp-10h]@1
+  int v20; // [sp+18h] [bp-Ch]@19
+  signed int v21; // [sp+1Ch] [bp-8h]@1
+  signed int v22; // [sp+20h] [bp-4h]@3
+  int v23; // [sp+20h] [bp-4h]@19
+
+  v21 = 0;
+  v3 = pChests[uChestID].uChestBitmapID;
+  v4 = a2;
+  v5 = pChestWidthsByType[v3] * pChestHeightsByType[v3];
+  Src = a2;
+  v19 = pChestWidthsByType[v3];
+  if ( a1 == -1 )
+  {
+    v18 = _41FF64(uChestID);
+    if ( v18 == -1 )
+      return 0;
+    v22 = 0;
+    if ( v5 > 0 )
+    {
+      while ( !Chest::CanPlaceItemAt(v22, v4->uItemID, (unsigned int)pChestWindow->ptr_1C) )
+      {
+        ++v22;
+        if ( v22 >= v5 )
+          goto LABEL_8;
+      }
+      v21 = v22;
+    }
+LABEL_8:
+    if ( v22 == v5 )
+    {
+      if ( uActiveCharacter )
+        pPlayers[uActiveCharacter]->PlaySound(15, 0);
+      return 0;
+    }
+    v7 = pIcons_LOD->LoadTexture(pItemsTable->pItems[v4->uItemID].pIconName, TEXTURE_16BIT_PALETTE);
+    HIWORD(v8) = 0;
+    v9 = v7 != -1 ? (int)&pIcons_LOD->pTextures[v7] : 0;
+    v10 = (v7 != -1 ? pIcons_LOD->pTextures[v7].uTextureWidth : 24);
+    if ( v10 < 14 )
+      v10 = 14;
+    v11 = *(short *)(v9 + 26);
+    v12 = ((v10 - 14) >> 5) + 1;
+    if ( v11 < 14 )
+      v11 = 14;
+    v13 = ((v11 - 14) >> 5) + 1;
+    if ( !areWeLoadingTexture )
+    {
+      ((Texture *)v9)->Release();
+      pIcons_LOD->_40F9C5();
+    }
+    if ( v13 > 0 )
+    {
+      v23 = 0;
+      v20 = v13;
+      do
+      {
+        if ( (signed int)v12 > 0 )
+        {
+          v14 = &pChests[0].pInventoryIndices[v21 + v23 + 2662 * uChestID];
+          LOWORD(v8) = -1 - v21;
+          v8 <<= 16;
+          LOWORD(v8) = -1 - v21;
+          memset32(v14, v8, v12 >> 1);
+          v15 = (int)((char *)v14 + 4 * (v12 >> 1));
+          for ( i = v12 & 1; i; --i )
+          {
+            *(short *)v15 = v8;
+            v15 += 2;
+          }
+        }
+        v23 += v19;
+        --v20;
+      }
+      while ( v20 );
+    }
+    pChests[0].pInventoryIndices[v21 + 2662 * uChestID] = v18 + 1;
+    memcpy(&pChests[uChestID].mm7__vector_pItems[v18], Src, 0x24u);
+    result = v21 + 1;
+  }
+  else
+  {
+    result = 1;
+  }
+  return result;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (0042013E) --------------------------------------------------------
+unsigned int Chest::PlaceItemAt(unsigned int a1, unsigned int uItemIdx, unsigned int uChestID)
+{
+  int v3; // esi@1
+  unsigned int v4; // ebx@1
+  int uItemID; // edi@1
+  int v6; // edx@4
+  unsigned int v7; // eax@5
+  Texture *v8; // ecx@5
+  signed int v9; // eax@5
+  signed int v10; // edi@7
+  unsigned int v11; // ebx@7
+  int v12; // edi@9
+  int v13; // edx@12
+  void *v14; // edi@14
+  int v15; // edi@14
+  int i; // ecx@14
+  unsigned int result; // eax@18
+  __int16 v18; // [sp+Ch] [bp-10h]@1
+  int v19; // [sp+10h] [bp-Ch]@11
+  int v20; // [sp+14h] [bp-8h]@12
+  unsigned int v21; // [sp+18h] [bp-4h]@1
+
+  v3 = 5324 * uChestID;
+  v21 = a1;
+  v4 = 5324 * uChestID + 36 * uItemIdx;
+  v18 = uItemIdx;
+  uItemID = *(unsigned int *)((char *)&pChests[0].mm7__vector_pItems[0].uItemID + v4);
+  pItemsTable->SetSpecialBonus((ItemGen *)((char *)pChests[0].mm7__vector_pItems + v4));
+  if ( uItemID >= 135 && uItemID <= 159 && !*(int *)((char *)&pChests[0].mm7__vector_pItems[0].uNumCharges + v4) )
+  {
+    v6 = rand() % 21 + 10;
+    *(int *)((char *)&pChests[0].mm7__vector_pItems[0].uNumCharges + v4) = v6;
+    *(&pChests[0].mm7__vector_pItems[0].uMaxCharges + v4) = v6;
+  }
+  v7 = pIcons_LOD->LoadTexture(pItemsTable->pItems[uItemID].pIconName, TEXTURE_16BIT_PALETTE);
+  v8 = (Texture *)(v7 != -1 ? (int)&pIcons_LOD->pTextures[v7] : 0);
+  v9 = (v7 != -1 ? pIcons_LOD->pTextures[v7].uTextureWidth : 24);
+  if ( v9 < 14 )
+    v9 = 14;
+  v10 = v8->uTextureHeight;
+  v11 = ((v9 - 14) >> 5) + 1;
+  if ( v10 < 14 )
+    v10 = 14;
+  v12 = ((v10 - 14) >> 5) + 1;
+  if ( !areWeLoadingTexture )
+  {
+    v8->Release();
+    pIcons_LOD->_40F9C5();
+  }
+  v19 = pChestWidthsByType[*(unsigned __int16 *)((char *)&pChests[0].uChestBitmapID + v3)];
+  if ( v12 > 0 )
+  {
+    v13 = 0;
+    v20 = v12;
+    do
+    {
+      if ( (signed int)v11 > 0 )
+      {
+        v14 = &pChests[0].pInventoryIndices[v21 + v13 + 2662 * uChestID];
+        LOWORD(v3) = -1 - v21;
+        v3 <<= 16;
+        LOWORD(v3) = -1 - v21;
+        memset32(v14, v3, v11 >> 1);
+        v15 = (int)((char *)v14 + 4 * (v11 >> 1));
+        for ( i = v11 & 1; i; --i )
+        {
+          *(short *)v15 = v3;
+          v15 += 2;
+        }
+      }
+      v13 += v19;
+      --v20;
+    }
+    while ( v20 );
+  }
+  result = v21 + 2662 * uChestID;
+  pChests[0].pInventoryIndices[result] = v18 + 1;
+  return result;
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (00420284) --------------------------------------------------------
+char *Chest::_420284(unsigned int uChestID)
+{
+  int v1; // ebx@1
+  unsigned int v2; // esi@1
+  unsigned int v3; // esi@1
+  int uChestArea; // edi@1
+  int v5; // eax@2
+  int v6; // ebx@11
+  char *result; // eax@18
+  char Dst[144]; // [sp+Ch] [bp-A0h]@1
+  int v9; // [sp+9Ch] [bp-10h]@10
+  unsigned int v10; // [sp+A0h] [bp-Ch]@1
+  unsigned int v11; // [sp+A4h] [bp-8h]@8
+  unsigned int *v12; // [sp+A8h] [bp-4h]@9
+
+  v1 = 0;
+  v2 = uChestID;
+  v10 = uChestID;
+  pRenderer->ClearZBuffer(0, 479);
+  v3 = v2;
+  uChestArea = pChestWidthsByType[pChests[v3].uChestBitmapID] * pChestHeightsByType[pChests[v3].uChestBitmapID];
+  memset(Dst, 0, 0x90u);
+  if ( uChestArea > 0 )
+  {
+    do
+    {
+      do
+        v5 = (unsigned __int8)rand();
+      while ( v5 >= uChestArea );
+      while ( Dst[v5] )
+      {
+        ++v5;
+        if ( v5 == uChestArea )
+          v5 = 0;
+      }
+      Dst[v5] = v1++;
+    }
+    while ( v1 < uChestArea );
+  }
+  v11 = 0;
+  if ( uChestArea > 0 )
+  {
+    v12 = &pChests[v3].mm7__vector_pItems[0].uAttributes;
+    do
+    {
+      v9 = *(v12 - 5);
+      if ( v9 )
+      {
+        v6 = 0;
+        while ( !Chest::CanPlaceItemAt((unsigned __int8)Dst[v6], v9, v10) )
+        {
+          ++v6;
+          if ( v6 >= uChestArea )
+            goto LABEL_17;
+        }
+        Chest::PlaceItemAt((unsigned __int8)Dst[v6], v11, v10);
+        if ( pChests[v3].uFlags & 4 )
+          *v12 |= 1u;
+      }
+LABEL_17:
+      ++v11;
+      v12 += 9;
+    }
+    while ( (signed int)v11 < uChestArea );
+  }
+  result = (char *)&pChests[v3].uFlags;
+  pChests[v3].uFlags = pChests[v3].uFlags & 0xFFFB | 2;
+  return result;
+}
+// 420284: using guessed type char Dst[144];
+
+//----- (0042038D) --------------------------------------------------------
+void __cdecl sub_42038D()
+{
+  POINT *v0; // esi@2
+  int v1; // ecx@2
+  const char *v2; // eax@3
+  POINT v3; // [sp+0h] [bp-10h]@2
+  POINT a2; // [sp+8h] [bp-8h]@1
+
+  if ( pMouse->GetCursorPos(&a2)->y < 350 )
+  {
+    v0 = pMouse->GetCursorPos(&a2);
+    v1 = pRenderer->pActiveZBuffer[v0->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v3)->y]];
+    if ( v1 )
+    {
+      auto _w = (ItemGen *)(&pOtherOverlayList->pOverlays[49].field_4 + 2662 * (unsigned int)pChestWindow->ptr_1C
+                                             + 18 * *((short *)&pChests[0].mm7__vector_pItems[139].uExpireTime
+                                               + v1 + 2662 * (unsigned int)pChestWindow->ptr_1C + 3));
+      v2 = _w->GetDisplayName();
+      sub_41C0B8_set_status_string(v2);
+    }
+  }
+}
+
+//----- (0042041E) --------------------------------------------------------
+bool Chest::Open(unsigned int uChestID)
+{
+  char *v1; // edi@5
+  unsigned int v2; // eax@8
+  GUIWindow *v3; // eax@15
+  int v5; // edx@16
+  int v6; // eax@16
+  ODMFace *v7; // eax@19
+  int v8; // edx@19
+  int v9; // edi@19
+  signed int v10; // ebx@19
+  int v11; // ecx@19
+  int v12; // eax@19
+  BLVFace *v13; // eax@20
+  int v14; // ebx@21
+  int v15; // edi@21
+  int v16; // ecx@22
+  __int64 v17; // qax@22
+  double v18; // st7@23
+  double v19; // st6@23
+  double v20; // st7@23
+  int v21; // ecx@26
+  char v22[12]; // ST4C_12@28
+  unsigned int *v23; // edi@28
+  unsigned __int16 v24; // di@28
+  signed int v25; // ecx@28
+  char *v26; // edx@29
+  unsigned __int16 v27; // ax@32
+  //LayingItem a1; // [sp+14h] [bp-B0h]@28
+  int v29; // [sp+84h] [bp-40h]@16
+  int v30; // [sp+88h] [bp-3Ch]@16
+  int v31; // [sp+8Ch] [bp-38h]@16
+  int v32; // [sp+90h] [bp-34h]@16
+  float v33; // [sp+94h] [bp-30h]@23
+  char *v34; // [sp+98h] [bp-2Ch]@5
+  int v35; // [sp+9Ch] [bp-28h]@16
+  Vec3_int_ pOut; // [sp+A0h] [bp-24h]@28
+  int a4; // [sp+ACh] [bp-18h]@1
+  int v38; // [sp+B0h] [bp-14h]@21
+  int sRotX; // [sp+B4h] [bp-10h]@23
+  float v40; // [sp+B8h] [bp-Ch]@23
+  float v41; // [sp+BCh] [bp-8h]@23
+  int sRotY; // [sp+C0h] [bp-4h]@8
+
+  a4 = uChestID;
+  if ( (uChestID & 0x80000000u) != 0 || (signed int)uChestID >= 20 )
+    return 0;
+  ++pIcons_LOD->uTexturePacksCount;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  v1 = (char *)&pChests[uChestID].uFlags;
+  v34 = v1;
+  if ( !(*v1 & CHEST_ITEMS_PLACED) )
+    Chest::_420284(uChestID);
+  if ( !uActiveCharacter )
+    return 0;
+  *(float *)&sRotY = 0.0;
+  v2 = pMapStats->GetMapInfo(pCurrentMapName);
+  if ( !(*v1 & 1) || !v2 )
+    goto LABEL_12;
+  if ( pPlayers[uActiveCharacter]->GetDisarmTrap() < 2 * pMapStats->pInfos[v2].field_2D )
+  {
+    v29 = 811;
+    v30 = 812;
+    v31 = 813;
+    v32 = 814;
+    v5 = rand() % 4;
+    v6 = dword_5B5920 >> 3;
+    v35 = v5;
+    if ( (dword_5B5920 & 7) == 5 )
+    {
+      v16 = v6;
+      v14 = pLevelDecorations[v6].vPosition.x;
+      v38 = pLevelDecorations[v6].vPosition.y;
+      v17 = pDecorationList->pDecorations[pLevelDecorations[v6].uDecorationDescID].uDecorationHeight;
+      v15 = pLevelDecorations[v16].vPosition.z + (((signed int)v17 - HIDWORD(v17)) >> 1);
+    }
+    else
+    {
+      if ( (dword_5B5920 & 7) != 6 )
+        goto LABEL_12;
+      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+      {
+        v7 = &pOutdoor->pBModels[dword_5B5920 >> 9].pFaces[(dword_5B5920 >> 3) & 0x3F];
+        v8 = v7->pBoundingBox.y1;
+        v9 = v7->pBoundingBox.z2;
+        v10 = v7->pBoundingBox.x1 + v7->pBoundingBox.x2;
+        v11 = v7->pBoundingBox.y2;
+        v12 = v7->pBoundingBox.z1;
+      }
+      else
+      {
+        v13 = &pIndoor->pFaces[v6];
+        v8 = v13->pBounding.y1;
+        v9 = v13->pBounding.z2;
+        v10 = v13->pBounding.x1 + v13->pBounding.x2;
+        v11 = v13->pBounding.y2;
+        v12 = v13->pBounding.z1;
+      }
+      v14 = v10 >> 1;
+      v38 = (v8 + v11) >> 1;
+      v15 = (v12 + v9) >> 1;
+    }
+    v18 = (double)pParty->vPosition.x - (double)v14;
+    *(float *)&a4 = v18;
+    v19 = (double)pParty->vPosition.y - (double)v38;
+    v33 = v19;
+    v41 = (double)pParty->sEyelevel + (double)pParty->vPosition.z - (double)v15;
+    *(float *)&sRotY = v19 * v19;
+    *(float *)&sRotX = v18 * v18;
+    v20 = sqrt(v41 * v41 + *(float *)&sRotX + *(float *)&sRotY);
+    v40 = v20;
+    if ( v20 <= 1.0 )
+    {
+      *(float *)&sRotX = 0.0;
+      *(float *)&sRotY = 0.0;
+    }
+    else
+    {
+      sRotY = (signed __int64)sqrt(*(float *)&sRotX + *(float *)&sRotY);
+      sRotX = stru_5C6E00->Atan2((signed __int64)*(float *)&a4, (signed __int64)v33);
+      sRotY = stru_5C6E00->Atan2(sRotY, (signed __int64)v41);
+    }
+    v21 = 256;
+    if ( v40 < 256.0 )
+      v21 = (signed __int64)v40 / 4;
+    *(int *)&v22[8] = v15;
+    *(_QWORD *)v22 = __PAIR__(v38, v14);
+    Vec3_int_::Rotate(v21, sRotX, sRotY, *(Vec3_int_ *)v22, &pOut.x, &pOut.z, &pOut.y);
+    v23 = (unsigned int *)(&v29 + v35);
+    sub_42F7EB_DropItemAt(*v23, pOut.x, pOut.z, pOut.y, 0, 1, 0, 0x30u, 0);
+    
+    LayingItem a1; // [sp+14h] [bp-B0h]@28
+    //LayingItem::LayingItem(&a1);
+
+    a1.stru_24.Reset();
+    v24 = *(short *)v23;
+    v25 = 0;
+    a1.field_50 = 0;
+    a1.field_4C = 0;
+    a1.field_48 = 0;
+    a1.field_54 = 0;
+    a1.uItemType = v24;
+    if ( (signed int)pObjectList->uNumObjects <= 0 )
+    {
+LABEL_32:
+      v27 = 0;
+    }
+    else
+    {
+      v26 = (char *)&pObjectList->pObjects->uObjectID;
+      while ( v24 != *(short *)v26 )
+      {
+        ++v25;
+        v26 += 56;
+        if ( v25 >= (signed int)pObjectList->uNumObjects )
+          goto LABEL_32;
+      }
+      v27 = v25;
+    }
+    a1.uObjectDescID = v27;
+    a1.vPosition.y = pOut.z;
+    a1.vPosition.x = pOut.x;
+    a1.vPosition.z = pOut.y;
+    a1.uSoundID = 0;
+    a1.uAttributes = 48;
+    a1.uSectorID = pIndoor->GetSector(pOut.x, pOut.z, pOut.y);
+    a1.uSpriteFrameID = 0;
+    a1.field_58 = 0;
+    a1.field_5C = 0;
+    a1.uFacing = 0;
+    a1.Create(0, 0, 0, 0);
+    pAudioPlayer->PlaySound(SOUND_8, 0, 0, -1, 0, 0, 0, 0);
+    a1._438E35();
+    *v34 &= 0xFEu;
+    if ( uActiveCharacter && !qword_A750D8 && !dword_507CD8 )
+    {
+      qword_A750D8 = 256i64;
+      word_A750E0 = 5;
+      word_A750E2 = uActiveCharacter;
+    }
+    pIcons_LOD->_4114F2();
+    dword_507CD8 = 0;
+    return 0;
+  }
+  *v1 &= 0xFEu;
+  sRotY = 1;
+LABEL_12:
+  pAudioPlayer->StopChannels(-1, -1);
+  pAudioPlayer->PlaySound((SoundID)208, 0, 0, -1, 0, 0, 0, 0);
+  if ( *(float *)&sRotY != 0.0 )
+  {
+    if ( !dword_507CD8 )
+      pPlayers[uActiveCharacter]->PlaySound(4, 0);
+  }
+  dword_507CD8 = 0;
+  v3 = GUIWindow::Create(0, 0, 640u, 480u, WINDOW_Chest, a4, 0);
+  pGUIWindow_CurrentMenu = v3;
+  pChestWindow = v3;
+  pBtn_ExitCancel = v3->CreateButton(
+                 0x1D7u,
+                 0x1BDu,
+                 0xA9u,
+                 0x23u,
+                 1,
+                 0,
+                 0x71u,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[79],// Exit
+                 (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                 0);
+  pChestWindow->CreateButton(7u, 8u, 460u, 343u, 1, 0, 0xCu, 0, 0, "", 0);
+  pCurrentScreen = 10;
+  pEventTimer->Pause();
+  return 1;
+}
+
+//----- (0042092D) --------------------------------------------------------
+void Chest::DrawChestUI(unsigned int uChestID)
+{
+  Render *v1; // edi@1
+  unsigned int v2; // ebx@1
+  unsigned int v3; // ebx@1
+  int v4; // eax@1
+  unsigned int v5; // eax@1
+  int v6; // ecx@3
+  unsigned int v7; // eax@4
+  Texture *v8; // esi@4
+  signed int v9; // ecx@4
+  signed int v10; // edx@4
+  signed int v11; // eax@4
+  int v12; // eax@6
+  int v13; // eax@6
+  unsigned int v14; // ST34_4@8
+  int v15; // edi@8
+  int *v16; // [sp+Ch] [bp-28h]@1
+  int v17; // [sp+10h] [bp-24h]@4
+  int v18; // [sp+14h] [bp-20h]@1
+  signed int v19; // [sp+18h] [bp-1Ch]@1
+  int v20; // [sp+1Ch] [bp-18h]@1
+  signed int v21; // [sp+20h] [bp-14h]@1
+  char *v22; // [sp+2Ch] [bp-8h]@2
+  signed int v23; // [sp+30h] [bp-4h]@1
+
+  v1 = pRenderer;
+  v2 = uChestID;
+  v16 = pRenderer->pActiveZBuffer;
+  pRenderer->ClearZBuffer(0, 479);
+  v3 = v2;
+  v4 = pChests[v3].uChestBitmapID;
+  v20 = pChestSmthn1ByType[v4];
+  v18 = pChestSmthn2ByType[v4];
+  v21 = pChestWidthsByType[v4];
+  v19 = pChestHeightsByType[v4];
+  sprintf(pTmpBuf, "chest%02d", pChestList->pChests[pChests[v3].uChestBitmapID].uTextureID);
+  v5 = pIcons_LOD->LoadTexture(pTmpBuf, TEXTURE_16BIT_PALETTE);
+  pRenderer->DrawTextureIndexed(8u, 8u, (Texture *)(v5 != -1 ? (int)&pIcons_LOD->pTextures[v5] : 0));
+  v23 = 0;
+  if ( v21 * v19 > 0 )
+  {
+    v22 = (char *)pChests[v3].pInventoryIndices;
+    do
+    {
+      v6 = *(short *)v22;
+      if ( v6 > 0 )
+      {
+        v17 = v18 + 32 * v23 / v19;
+        v7 = pIcons_LOD->LoadTexture(
+               pItemsTable->pItems[*(int *)((char *)&pOtherOverlayList->pOverlays[49].field_4 + 36 * v6 + v3 * 5324)].pIconName,
+               TEXTURE_16BIT_PALETTE);
+        v8 = (Texture *)(v7 != -1 ? &pIcons_LOD->pTextures[v7] : 0);
+        v9 = (v7 != -1 ? pIcons_LOD->pTextures[v7].uTextureWidth : 24);
+        v10 = (v7 != -1 ? pIcons_LOD->pTextures[v7].uTextureHeight : 26);
+        v11 = (v7 != -1 ? pIcons_LOD->pTextures[v7].uTextureWidth : 24);
+        if ( v9 < 14 )
+          v11 = 14;
+        v12 = v11 - 14;
+        LOBYTE(v12) = v12 & 0xE0;
+        v13 = v12 + 32;
+        if ( (signed int)v8->uTextureHeight < 14 )
+          v10 = 14;
+        v14 = v20 + 32 * v23 % v21 + ((v13 - v9) >> 1);
+        v15 = v17 + ((((v10 - 14) & 0xFFFFFFE0) - v8->uTextureHeight + 32) >> 1);
+        pRenderer->DrawTextureTransparent(
+          v14,
+          v17 + ((((v10 - 14) & 0xFFFFFFE0) - v8->uTextureHeight + 32) >> 1),
+          v8);
+        sub_40F92A(&v16[v14 + pSRZBufferLineOffsets[v15]], v8, v23 + 1);
+        v1 = pRenderer;
+      }
+      ++v23;
+      v22 += 2;
+    }
+    while ( v23 < v21 * v19 );
+  }
+  pRenderer->DrawTextureIndexed(
+    pBtn_ExitCancel->uX,
+    pBtn_ExitCancel->uY,
+    (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0));
+}
+
+//----- (00420B13) --------------------------------------------------------
+void __fastcall sub_420B13(int a1, int a2)
+{
+  void *v2; // eax@1
+  ItemGen *v3; // ebx@1
+  unsigned int v4; // eax@1
+  Texture *v5; // ecx@1
+  signed int v6; // eax@1
+  signed int v7; // edi@3
+  signed int v8; // eax@3
+  int v9; // edi@3
+  int v10; // eax@5
+  int v11; // esi@8
+  unsigned int v12; // ecx@10
+  void *v13; // edi@10
+  unsigned __int8 v14; // cf@10
+  int v15; // edi@10
+  int i; // ecx@10
+  int v17; // [sp+Ch] [bp-14h]@1
+  int v18; // [sp+10h] [bp-10h]@3
+  int v19; // [sp+14h] [bp-Ch]@1
+  void *v20; // [sp+18h] [bp-8h]@1
+  int v21; // [sp+1Ch] [bp-4h]@5
+  int v22; // [sp+1Ch] [bp-4h]@8
+
+  v19 = a2;
+  v2 = pChestWindow->ptr_1C;
+  v20 = v2;
+  v2 = (void *)(5324 * (int)v2);
+  v3 = (ItemGen *)((char *)v2 + 36 * a1 + (int)((char *)pChests + 4));
+  v17 = pChestWidthsByType[*(short *)((char *)v2 + (int)pChests)];
+  v4 = pIcons_LOD->LoadTexture(pItemsTable->pItems[v3->uItemID].pIconName, TEXTURE_16BIT_PALETTE);
+  v5 = (Texture *)(v4 != -1 ? (int)&pIcons_LOD->pTextures[v4] : 0);
+  v6 = (v4 != -1 ? pIcons_LOD->pTextures[v4].uTextureWidth : 24);
+  if ( v6 < 14 )
+    v6 = 14;
+  v7 = v6 - 14;
+  v8 = v5->uTextureHeight;
+  v9 = (v7 >> 5) + 1;
+  v18 = v9;
+  if ( v8 < 14 )
+    v8 = 14;
+  v10 = ((v8 - 14) >> 5) + 1;
+  v21 = v10;
+  if ( !areWeLoadingTexture )
+  {
+    v5->Release();
+    pIcons_LOD->_40F9C5();
+    v10 = v21;
+  }
+  if ( v10 > 0 )
+  {
+    v11 = 0;
+    v22 = v10;
+    do
+    {
+      if ( v9 > 0 )
+      {
+        v12 = v9;
+        v13 = &pChests[0].pInventoryIndices[v19 + v11 + 2662 * (int)v20];
+        v14 = v12 & 1;
+        v12 >>= 1;
+        memset(v13, 0, 4 * v12);
+        v15 = (int)((char *)v13 + 4 * v12);
+        for ( i = v14; i; --i )
+        {
+          *(short *)v15 = 0;
+          v15 += 2;
+        }
+        v9 = v18;
+      }
+      v11 += v17;
+      --v22;
+    }
+    while ( v22 );
+  }
+  v3->Reset();
+}
+// 506128: using guessed type int areWeLoadingTexture;
+
+//----- (00420C05) --------------------------------------------------------
+void __fastcall party_finds_gold(unsigned int uNumGold, int _1_dont_share_with_followers___2_the_same_but_without_a_message__else_normal)
+{
+  unsigned int v2; // edi@1
+  int v3; // ebp@1
+  unsigned int v4; // esi@1
+  int v5; // ecx@6
+  NPCData *v6; // eax@6
+  signed int v7; // edx@8
+  signed int v8; // ebx@10
+  char *v9; // edi@11
+  signed int v10; // ecx@17
+  int v11; // eax@21
+  NPCData *v12; // ecx@21
+  unsigned int v13; // ecx@23
+  signed int v14; // [sp+Ch] [bp-4h]@6
+
+  v2 = 0;
+  v3 = 0;
+  v4 = uNumGold;
+  if ( _1_dont_share_with_followers___2_the_same_but_without_a_message__else_normal )
+  {
+    if ( _1_dont_share_with_followers___2_the_same_but_without_a_message__else_normal == 1 )
+    {
+      sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[467], uNumGold);// You found %lu gold!
+    }
+    else
+    {
+      if ( _1_dont_share_with_followers___2_the_same_but_without_a_message__else_normal == 2 )
+        pTmpBuf2[0] = 0;
+    }
+  }
+  else
+  {
+    v14 = 0;
+    v5 = 0;
+    v6 = pParty->pHirelings;
+    do
+    {
+      if ( v6->pName )
+      {
+        v7 = v14++;
+        pTmpBuf[v7] = v5;
+      }
+      ++v6;
+      ++v5;
+    }
+    while ( (signed int)v6 < (signed int)&pParty->pPickedItem );
+    v8 = 0;
+    if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+    {
+      v9 = (char *)pNPCStats->pNewNPCData;
+      do
+      {
+        if ( v9[8] & 0x80
+          && (!pParty->pHirelings[0].pName || strcmp(*(const char **)v9, pParty->pHirelings[0].pName))
+          && (!pParty->pHirelings[1].pName || strcmp(*(const char **)v9, pParty->pHirelings[1].pName)) )
+        {
+          v10 = v14++;
+          pTmpBuf[v10] = v8 + 2;
+        }
+        ++v8;
+        v9 += 76;
+      }
+      while ( v8 < (signed int)pNPCStats->uNumNewNPCs );
+      v2 = 0;
+    }
+    if ( v14 > 0 )
+    {
+      do
+      {
+        v11 = (unsigned __int8)pTmpBuf[v2];
+        v12 = &pNPCStats->pNPCData[v11 + 499];
+        if ( (unsigned __int8)pTmpBuf[v2] < 2u )
+          v12 = &pParty->pHirelings[v11];
+        v13 = v12->uProfession;
+        if ( v13 )
+          v3 += *(&pNPCStats->field_13A58 + 5 * v13);
+        ++v2;
+      }
+      while ( (signed int)v2 < v14 );
+    }
+    if ( CheckHiredNPCSpeciality(0x1Fu) )
+      v4 += (signed int)(10 * v4) / 100;
+    if ( CheckHiredNPCSpeciality(0x20u) )
+      v4 += (signed int)(20 * v4) / 100;
+    if ( CheckHiredNPCSpeciality(0x2Du) )
+      v4 += (signed int)(10 * v4) / 100;
+    if ( v3 )
+    {
+      v3 = (signed int)(v4 * v3 / 100) / 100;
+      if ( v3 < 1 )
+        v3 = 1;
+      sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[466], v4, v3);// You found %lu gold (followers take %lu)!
+    }
+    else
+    {
+      sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[467], v4);// You found %lu gold!
+    }
+    v2 = 0;
+  }
+  pParty->uNumGold += v4 - v3;
+  pUIAnim_Gold->uAnimTime = v2;
+  pUIAnim_Gold->uAnimLength = 8 * pIconsFrameTable->pIcons[(signed __int16)pUIAnim_Gold->uIconID].uAnimLength;
+  if ( pTmpBuf2[0] )
+    ShowStatusBarString(pTmpBuf2, 2u);
+  pAudioPlayer->PlaySound(SOUND_GoldReceived, v2, v2, -1, v2, v2, v2, v2);
+}
+
+//----- (00420E01) --------------------------------------------------------
+void __cdecl sub_420E01()
+{
+  void *v0; // edi@1
+  POINT *v1; // esi@2
+  int v2; // eax@2
+  int v3; // ebx@4
+  int v4; // esi@6
+  int v5; // ecx@6
+  //LayingItem v6; // [sp+Ch] [bp-80h]@1
+  char v7; // [sp+7Ch] [bp-10h]@2
+  POINT a2; // [sp+84h] [bp-8h]@2
+  
+  LayingItem v6; // [sp+Ch] [bp-80h]@1
+  //LayingItem::LayingItem(&v6);
+
+  v0 = pGUIWindow_CurrentMenu->ptr_1C;
+  if ( pParty->pPickedItem.uItemID )
+  {
+    if ( Chest::_41FFA2(-1, &pParty->pPickedItem, (unsigned int)pGUIWindow_CurrentMenu->ptr_1C) )
+      pMouse->RemoveHoldingItem();
+  }
+  else
+  {
+    v1 = pMouse->GetCursorPos(&a2);
+    v2 = pRenderer->pActiveZBuffer[v1->x + pSRZBufferLineOffsets[pMouse->GetCursorPos((POINT *)&v7)->y]] & 0xFFFF;
+    if ( v2 )
+    {
+      if ( v2 )
+        v3 = v2 - 1;
+      else
+        v3 = -1;
+      v4 = pChests[0].pInventoryIndices[v3 + 2662 * (int)v0] - 1;
+      v5 = 5324 * (int)v0 + 36 * v4;
+      if ( pItemsTable->pItems[*(unsigned int *)((char *)&pChests[0].mm7__vector_pItems[0].uItemID + v5)].uEquipType == 18 )
+      {
+        party_finds_gold(*(int *)((char *)&pChests[0].mm7__vector_pItems[0].uAdditionalValue + v5), 0);
+        viewparams->bRedrawGameUI = 1;
+      }
+      else
+      {
+        pParty->SetHoldingItem((ItemGen *)((char *)pChests[0].mm7__vector_pItems + v5));
+      }
+      sub_420B13(v4, v3);
+    }
+  }
+}
+
+//----- (00420EFF) --------------------------------------------------------
+void __cdecl GameUI_WritePointedObjectStatusString()
+{
+  int v1; // ebx@6
+  GUIWindow *v2; // edi@7
+  GUIButton *i; // ecx@11
+  Player *v4; // eax@19
+  char v5; // cl@19
+  unsigned int v6; // eax@19
+  int v7; // ecx@19
+  __int16 v8; // fps@23
+  unsigned __int8 v9; // c0@23
+  unsigned __int8 v10; // c3@23
+  enum UIMessageType v11; // esi@24
+  int v12; // edx@25
+  char *v13; // ecx@28
+  int v14; // eax@41
+  ItemGen *v15; // ecx@44
+  int v16; // ecx@46
+  const char *v17; // eax@49
+  signed int v18; // eax@55
+  signed int v19; // ecx@63
+  BLVFace *pFace; // eax@69
+  __int16 v21; // ax@70
+  const char *v22; // eax@72
+  LevelDecoration *v23; // ecx@75
+  LevelDecoration *v24; // esi@75
+  __int16 v25; // ax@75
+  const char *v26; // ecx@79
+  Actor *pActor; // ecx@82
+  char *v28; // esi@82
+  int v29; // eax@82
+  signed int v30; // ecx@88
+  const char *v31; // eax@91
+  __int16 v32; // fps@109
+  unsigned __int8 v33; // c0@109
+  unsigned __int8 v34; // c3@109
+  enum UIMessageType v35; // esi@110
+  int v36; // edx@111
+  enum UIMessageType v37; // edx@117
+  int v38; // ecx@118
+  const char *v39; // [sp-8h] [bp-E8h]@20
+  char *v40; // [sp-8h] [bp-E8h]@83
+  int v41; // [sp-4h] [bp-E4h]@20
+  char Str1[200]; // [sp+Ch] [bp-D4h]@129
+  unsigned int pX; // [sp+D4h] [bp-Ch]@1
+  unsigned int pY; // [sp+D8h] [bp-8h]@1
+  unsigned int v45; // [sp+DCh] [bp-4h]@21
+
+  v13 = nullptr;
+
+  pMouse->uPointingObjectID = 0;
+  pMouse->GetClickPos(&pX, &pY);
+  if ( (pX & 0x80000000u) != 0 || (signed int)pX > 639 || (pY & 0x80000000u) != 0 || (signed int)pY > 479 )
+    return;
+  if ( !pCurrentScreen )
+  {
+    if ( (signed int)pX > 467 || (signed int)pY > 351 )
+      goto _click_on_game_ui;
+    if ( pRenderer->pRenderD3D )
+    {
+      v18 = pGame->pVisInstance->get_picked_object_zbuf_val();
+      if ( (signed int)pX < (signed int)pViewport->uScreenX
+        || (signed int)pX > (signed int)pViewport->uScreenZ
+        || (signed int)pY < (signed int)pViewport->uScreenY
+        || (signed int)pY > (signed int)pViewport->uScreenW )
+        v18 = -1;
+      if ( v18 == -1 )
+        goto LABEL_61;
+    }
+    else
+    {
+      v18 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]];
+    }
+    pMouse->uPointingObjectID = (unsigned __int16)v18;
+    v19 = (signed int)(unsigned __int16)v18 >> 3;
+    if ( (v18 & 7) == OBJECT_Item )
+    {
+      v30 = v19;
+      if ( pObjectList->pObjects[pLayingItems[v30].uObjectDescID].uFlags & 0x10 )
+        goto LABEL_73;
+      if ( v18 >= (signed int)0x2000000u || pParty->pPickedItem.uItemID )
+      {
+        v22 = pLayingItems[v30].stru_24.GetDisplayName();
+LABEL_93:
+        v26 = v22;
+        goto LABEL_87;
+      }
+      v31 = pLayingItems[v30].stru_24.GetDisplayName();
+      v28 = pTmpBuf;
+      sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[470], v31);// "Get %s"
+    }
+    else
+    {
+      if ( (v18 & 7) != OBJECT_Actor )
+      {
+        if ( (v18 & 7) == OBJECT_Decoration )
+        {
+          v23 = &pLevelDecorations[v19];
+          v24 = v23;
+          v25 = v23->field_16_event_id;
+          if ( !v25 )
+          {
+            if ( v23->IsInteractive() )
+              v26 = pNPCTopics[stru_5E4C90._decor_events[v24->_idx_in_stru123 - 75] + 379].pTopic;
+            else
+              v26 = pDecorationList->pDecorations[v24->uDecorationDescID].field_20;
+            goto LABEL_87;
+          }
+          v22 = _444732_GetEventHintString(v25);
+          if ( !v22 )
+            goto _return;
+          goto LABEL_93;
+        }
+        if ( (v18 & 7) == 6 )                   // bmodel
+        {
+          if ( v18 < (signed int)0x2000000u )
+          {
+            if ( uCurrentlyLoadedLevelType != LEVEL_Indoor)
+            {
+              v21 = pOutdoor->pBModels[(signed int)(unsigned __int16)v18 >> 9].pFaces[v19 & 0x3F].sCogTriggeredID;
+              goto LABEL_71;
+            }
+            pFace = &pIndoor->pFaces[v19];
+            if ( BYTE3(pFace->uAttributes) & 6 )
+            {
+              v21 = pIndoor->pFaceExtras[pFace->uFaceExtraID].uEventID;
+LABEL_71:
+              if ( !v21 || (v22 = _444732_GetEventHintString(v21)) == 0 )
+                goto LABEL_73;
+              goto LABEL_93;
+            }
+          }
+LABEL_73:
+          pMouse->uPointingObjectID = 0;
+          goto LABEL_50;
+        }
+LABEL_61:
+        pMouse->uPointingObjectID = 0;
+        goto _return;
+      }
+      if ( v18 >= 335544320 )
+        goto LABEL_61;
+      pActor = &pActors[v19];
+      v28 = pTmpBuf;
+      v29 = pActor->dword_000334_unique_name;
+      if ( v29 )
+        v40 = (char *)*(&pMonsterStats->pPlacement.uNumStrings + v29);
+      else
+        v40 = pMonsterStats->pInfos[pActor->pMonsterInfo.uID].pName;
+      strncpy(pTmpBuf, v40, 0x7D0u);
+    }
+    v26 = v28;
+LABEL_87:
+    sub_41C0B8_set_status_string(v26);
+    goto _return;
+  }
+  v1 = uNumVisibleWindows;
+  if ( uNumVisibleWindows <= 0 )
+  {
+LABEL_38:
+    if ( pCurrentScreen == 10 )
+    {
+      sub_42038D();
+      goto _return;
+    }
+    if ( pCurrentScreen == 13 )
+    {
+      if ( dword_F8B19C != 2
+        || (v16 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]], v16 == 0)
+        || v16 == -65536 )
+        goto _return;
+      v15 = (ItemGen *)((char *)&pParty->pPickedItem + 36 * (v16 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 4);
+LABEL_49:
+      v17 = v15->GetDisplayName();
+      sub_41C0B8_set_status_string(v17);
+LABEL_50:
+      uLastPointedObjectID = 1;
+_return:
+      if ( pMouse->uPointingObjectID == 0 )
+      {
+        if ( uLastPointedObjectID != 0 )
+        {
+          pStatusBarString[0] = 0;
+          bForceDrawStatusBar = 1;
+        }
+      }
+      uLastPointedObjectID = pMouse->uPointingObjectID;
+      return;
+    }
+    if ( (signed int)pY < 350 )
+    {
+      v14 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]];
+      if ( v14 == 0 || v14 == -65536 || (unsigned int)v14 >= 0x1388 )
+        goto _return;
+      v15 = (ItemGen *)&pPlayers[uActiveCharacter]->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v14 + 5];
+      goto LABEL_49;
+    }
+_click_on_game_ui:
+    if ( (signed int)pX >= (signed int)pWindowList[0].uFrameX
+      && (signed int)pX <= (signed int)pWindowList[0].uFrameZ
+      && (signed int)pY >= (signed int)pWindowList[0].uFrameY
+      && (signed int)pY <= (signed int)pWindowList[0].uFrameW )
+    {
+      for ( i = pWindowList[0].pControlsHead; i != (GUIButton *)0; i = i->pNext )
+      {
+        if ( i->uButtonType == 1 )
+        {
+          if ( (signed int)pX >= (signed int)i->uX
+            && (signed int)pX <= (signed int)i->uZ
+            && (signed int)pY >= (signed int)i->uY
+            && (signed int)pY <= (signed int)i->uW )
+          {
+            v37 = (UIMessageType)i->field_1C;
+            if ( v37 == 0 )
+              goto LABEL_28;
+            v38 = i->uControlParam;
+            if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+            {
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = v37;
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v38;
+              *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+              ++pMessageQueue_50CBD0->uNumMessages;
+            }
+            goto LABEL_131;
+          }
+        }
+        else
+        {
+          if ( i->uButtonType == 2 )
+          {
+            v45 = pX - i->uX;
+            v45 = pY - i->uY;
+
+            if (pX >= i->uX && pX <= i->uZ &&
+                pY >= i->uY && pY <= i->uW)
+            //if ( (double)(signed int)i->uWidth != 0.0 )
+            //{
+            //  if ( (double)(signed int)i->uHeight != 0.0 )
+            //  {
+                 //UNDEF(v32);
+                //if ( v33 | v34 )
+                {
+                  v35 = (UIMessageType)i->field_1C;
+                  if ( v35 != 0 )
+                  {
+                    v36 = i->uControlParam;
+                    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+                    {
+                      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = v35;
+                      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v36;
+                      *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+                      goto LABEL_27;
+                    }
+                  }
+                  goto LABEL_28;
+                //}
+              //}
+            }
+          }
+          else
+          {
+            if ( i->uButtonType == 3
+              && (signed int)pX >= (signed int)i->uX
+              && (signed int)pX <= (signed int)i->uZ
+              && (signed int)pY >= (signed int)i->uY
+              && (signed int)pY <= (signed int)i->uW )
+              goto LABEL_19;
+          }
+        }
+      }
+    }
+    pMouse->uPointingObjectID = sub_46A99B();
+    goto _return;
+  }
+  while ( 1 )                                   // some other fullscreen ui
+  {
+    v2 = &pWindowList[pVisibleWindowsIdxs[v1] - 1];
+    if ( (signed int)pX >= (signed int)v2->uFrameX
+      && (signed int)pX <= (signed int)v2->uFrameZ
+      && (signed int)pY >= (signed int)v2->uFrameY
+      && (signed int)pY <= (signed int)v2->uFrameW )
+    {
+      for ( i = v2->pControlsHead; ; i = i->pNext )
+      {
+        if ( !i )
+          break;
+        if ( i->uButtonType == 1 )
+        {
+          if ( (signed int)pX >= (signed int)i->uX
+            && (signed int)pX <= (signed int)i->uZ
+            && (signed int)pY >= (signed int)i->uY
+            && (signed int)pY <= (signed int)i->uW )
+          {
+LABEL_24:
+            v11 = (UIMessageType)i->field_1C;
+            if ( v11 )
+            {
+              v12 = i->uControlParam;
+              if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+              {
+                pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = v11;
+                pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v12;
+                *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+LABEL_27:
+                ++pMessageQueue_50CBD0->uNumMessages;
+              }
+            }
+LABEL_28:
+            v13 = i->pButtonName;
+_set_status_and_ret:
+            sub_41C0B8_set_status_string(v13);
+LABEL_131:
+            uLastPointedObjectID = 1;
+            return;
+          }
+        }
+        else
+        {
+          if ( i->uButtonType == 2 )
+          {
+            v45 = pX - i->uX;
+            v45 = pY - i->uY;
+            if ( (double)(signed int)i->uWidth != 0.0 )
+            {
+              if ( (double)(signed int)i->uHeight != 0.0 )
+              {
+                //UNDEF(v8);
+                if ( v9 | v10 )
+                  goto LABEL_24;
+              }
+            }
+          }
+          else                                  // click on skill
+          {
+            if ( i->uButtonType == 3
+              && (signed int)pX >= (signed int)i->uX
+              && (signed int)pX <= (signed int)i->uZ
+              && (signed int)pY >= (signed int)i->uY
+              && (signed int)pY <= (signed int)i->uW )
+            {
+LABEL_19:
+              v4 = pPlayers[uActiveCharacter];
+              v5 = LOBYTE(v4->pActiveSkills[i->uControlParam]);
+              v6 = v4->uSkillPoints;
+              v7 = (v5 & 0x3F) + 1;
+              if ( v6 < v7 )
+              {
+                v41 = v7 - v6;
+                v39 = pGlobalTXT_LocalizationStrings[469];// "You need %d more Skill Points to advance here"
+              }
+              else
+              {
+                v41 = v7;
+                v39 = pGlobalTXT_LocalizationStrings[468];// "Clicking here will spend %d Skill Points"
+              }
+              sprintf(Str1, v39, v41);
+              v13 = Str1;
+              goto _set_status_and_ret;
+            }
+          }
+        }
+      }
+    }
+    if ( v2->uFrameHeight == 480 )
+      break;
+    --v1;
+    if ( v1 <= 0 )
+    {
+      goto LABEL_38;
+    }
+  }
+}
+
+
+//----- (00421626) --------------------------------------------------------
+GUIWindow *GameUI_InitializeCharacterWindow(unsigned int _this)
+{
+  unsigned int v1; // edi@1
+  GUIWindow *v2; // edi@3
+
+  ++pIcons_LOD->uTexturePacksCount;
+  v1 = _this;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  pEventTimer->Pause();
+  pAudioPlayer->StopChannels(-1, -1);
+  bRingsShownInCharScreen = 0;
+  CharacterUI_LoadPaperdollTextures();
+  pCurrentScreen = v1;
+  v2 = GUIWindow::Create(0, 0, 640, 480, WINDOW_CharacterRecord, uActiveCharacter, 0);
+  pCharacterScreen_StatsBtn = v2->CreateButton(
+                                pViewport->uViewportX + 12,
+                                pViewport->uViewportY + 308,
+                                (papredoll_dbrds[9] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[9]].uTextureWidth : 24),
+                                (papredoll_dbrds[9] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[9]].uTextureHeight : 26),
+                                1,
+                                0,
+                                0x73u,
+                                0,
+                                0x53u,
+                                pGlobalTXT_LocalizationStrings[216],
+                                (Texture *)(papredoll_dbrds[10] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[10]] : 0),
+                                papredoll_dbrds[9] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[9]] : 0,
+                                0);
+  pCharacterScreen_SkillsBtn = v2->CreateButton(
+                                 pViewport->uViewportX + 102,
+                                 pViewport->uViewportY + 308,
+                                 (papredoll_dbrds[7] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[7]].uTextureWidth : 24),
+                                 (papredoll_dbrds[7] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[7]].uTextureHeight : 26),
+                                 1,
+                                 0,
+                                 0x72u,
+                                 0,
+                                 0x4Bu,
+                                 pGlobalTXT_LocalizationStrings[205],
+                                 (Texture *)(papredoll_dbrds[8] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[8]] : 0),
+                                 papredoll_dbrds[7] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[7]] : 0,
+                                 0);
+  pCharacterScreen_InventoryBtn = v2->CreateButton(
+                                    pViewport->uViewportX + 192,
+                                    pViewport->uViewportY + 308,
+                                    (papredoll_dbrds[5] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[5]].uTextureWidth : 24),
+                                    (papredoll_dbrds[5] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[5]].uTextureHeight : 26),
+                                    1,
+                                    0,
+                                    0x74u,
+                                    0,
+                                    0x49u,
+                                    pGlobalTXT_LocalizationStrings[120],
+                                    (Texture *)(papredoll_dbrds[6] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[6]] : 0),
+                                    papredoll_dbrds[5] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[5]] : 0,
+                                    0);
+  pCharacterScreen_AwardsBtn = v2->CreateButton(
+                                 pViewport->uViewportX + 282,
+                                 pViewport->uViewportY + 308,
+                                 (papredoll_dbrds[3] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[3]].uTextureWidth : 24),
+                                 (papredoll_dbrds[3] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[3]].uTextureHeight : 26),
+                                 1,
+                                 0,
+                                 0x75u,
+                                 0,
+                                 0x41u,
+                                 pGlobalTXT_LocalizationStrings[22],
+                                 (Texture *)(papredoll_dbrds[4] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[4]] : 0),
+                                 papredoll_dbrds[3] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[3]] : 0,
+                                 0);
+  pCharacterScreen_ExitBtn = v2->CreateButton(
+                 pViewport->uViewportX + 371,
+                 pViewport->uViewportY + 308,
+                 (papredoll_dbrds[1] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[1]].uTextureWidth : 24),
+                 (papredoll_dbrds[1] != -1 ? pIcons_LOD->pTextures[papredoll_dbrds[1]].uTextureHeight : 26),
+                 1,
+                 0,
+                 0xA8u,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[79],
+                 (Texture *)(papredoll_dbrds[2] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[2]] : 0),
+                 papredoll_dbrds[1] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[1]] : 0,
+                 0);
+  v2->CreateButton(0, 0, 0x1DCu, 0x159u, 1, 122, 0x78u, 0, 0, "", 0);
+  pCharacterScreen_DetalizBtn = v2->CreateButton(
+                 0x258u,
+                 0x12Cu,
+                 0x1Eu,
+                 0x1Eu,
+                 1,
+                 0,
+                 0x55u,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[64],
+                 0);
+  pCharacterScreen_DollBtn = v2->CreateButton(0x1DCu, 0, 0xA4u, 0x159u, 1, 0, 0x85u, 0, 0, "", 0);
+  v2->CreateButton(0x3Du, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+  v2->CreateButton(0xB1u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+  v2->CreateButton(0x124u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+  v2->CreateButton(0x197u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+  v2->CreateButton(0, 0, 0, 0, 1, 0, 0xB0u, 0, 9u, "", 0);
+  sub_419100();
+  return v2;
+}
+
+
+
+//----- (004219BE) --------------------------------------------------------
+GUIWindow *stru277::sub_4219BE()
+{
+  int v1; // esi@1
+  GUIWindow *v2; // ebx@1
+
+  auto a4 = this;
+  v1 = (int)a4;
+  pEventTimer->Pause();
+  pAudioPlayer->StopChannels(-1, -1);
+  bRingsShownInCharScreen = 0;
+  CharacterUI_LoadPaperdollTextures();
+  pCurrentScreen = 23;
+  v2 = GUIWindow::Create(0, 0, 640, 480, (WindowType)(WINDOW_HouseInterior|WINDOW_Options), v1, 0);
+  pCharacterScreen_ExitBtn = v2->CreateButton(
+                 394u,
+                 318u,
+                 75u,
+                 33u,
+                 1,
+                 0,
+                 0xA8u,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[79],
+                 (Texture *)(papredoll_dbrds[2] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[2]] : 0),
+                 papredoll_dbrds[1] != -1 ? (int)&pIcons_LOD->pTextures[papredoll_dbrds[1]] : 0,
+                 0);
+  v2->CreateButton(0, 0, 0x1DCu, 0x159u, 1, 122, 0x78u, 0, 0, "", 0);
+  pCharacterScreen_DollBtn = v2->CreateButton(0x1DCu, 0, 0xA4u, 0x159u, 1, 0, 0x85u, 0, 0, "", 0);
+  v2->CreateButton(61u, 424u, 0x1Fu, 0, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+  v2->CreateButton(177u, 424u, 0x1Fu, 0, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+  v2->CreateButton(292u, 424u, 0x1Fu, 0, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+  v2->CreateButton(407u, 424u, 0x1Fu, 0, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+  return v2;
+}
+
+
+//----- (00421B2C) --------------------------------------------------------
+bool __cdecl sub_421B2C_PlaceInInventory_or_DropPickedItem()
+{
+  unsigned int v0; // eax@2
+  Texture *v1; // ebx@2
+  int v2; // eax@3
+  Player *v3; // esi@5
+  int v4; // eax@6
+  unsigned __int16 v5; // dx@11
+  signed int v6; // eax@11
+  char *v7; // edi@12
+  __int16 v8; // ax@16
+  LayingItem a1; // [sp+4h] [bp-78h]@11
+  int v11; // [sp+74h] [bp-8h]@2
+  int v12; // [sp+78h] [bp-4h]@5
+
+  if ( !pParty->pPickedItem.uItemID )
+    return 1;
+  v0 = pIcons_LOD->LoadTexture(
+         pItemsTable->pItems[pParty->pPickedItem.uItemID].pIconName,
+         TEXTURE_16BIT_PALETTE);
+  v1 = (Texture *)(v0 != -1 ? (int)&pIcons_LOD->pTextures[v0] : 0);
+  v11 = areWeLoadingTexture;
+  if ( uActiveCharacter
+    && (v2 = pPlayers[uActiveCharacter]->AddItem(0xFFFFFFFFu, pParty->pPickedItem.uItemID)) != 0 )
+  {
+    memcpy(&pPlayers[uActiveCharacter]->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5], &pParty->pPickedItem, 0x24u);
+  }
+  else
+  {
+    v12 = 0;
+    v3 = pParty->pPlayers;
+    while ( 1 )
+    {
+      v4 = v3->AddItem(0xFFFFFFFFu, pParty->pPickedItem.uItemID);
+      if ( v4 )
+        break;
+      ++v12;
+      ++v3;
+      if ( (signed int)v3 >= (signed int)pParty->pHirelings )
+        goto LABEL_10;
+    }
+    memcpy(&pParty->pPlayers[v12].spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4 + 5], &pParty->pPickedItem, 0x24u);
+    pMouse->RemoveHoldingItem();
+LABEL_10:
+    if ( v12 != 4 )
+      goto LABEL_18;
+    v5 = pItemsTable->pItems[pParty->pPickedItem.uItemID].uSpriteID;
+    v6 = 0;
+    a1.uItemType = pItemsTable->pItems[pParty->pPickedItem.uItemID].uSpriteID;
+    if ( (signed int)pObjectList->uNumObjects <= 0 )
+    {
+LABEL_15:
+      LOWORD(v6) = 0;
+    }
+    else
+    {
+      v7 = (char *)&pObjectList->pObjects->uObjectID;
+      while ( v5 != *(short *)v7 )
+      {
+        ++v6;
+        v7 += 56;
+        if ( v6 >= (signed int)pObjectList->uNumObjects )
+          goto LABEL_15;
+      }
+    }
+    a1.field_58 = 4;
+    a1.uObjectDescID = v6;
+    a1.vPosition.y = pParty->vPosition.y;
+    a1.vPosition.x = pParty->vPosition.x;
+    a1.vPosition.z = pParty->sEyelevel + pParty->vPosition.z;
+    a1.uSoundID = 0;
+    a1.uFacing = 0;
+    a1.uAttributes = 8;
+    v8 = pIndoor->GetSector(
+           pParty->vPosition.x,
+           pParty->vPosition.y,
+           pParty->sEyelevel + pParty->vPosition.z);
+    a1.uSpriteFrameID = 0;
+    a1.uSectorID = v8;
+    memcpy(&a1.stru_24, &pParty->pPickedItem, sizeof(a1.stru_24));
+    a1.Create(pParty->sRotationY, 184, 200, 0);
+  }
+  pMouse->RemoveHoldingItem();
+LABEL_18:
+  if ( !v11 )
+  {
+    v1->Release();
+    pIcons_LOD->_40F9C5();
+  }
+  return 1;
+}
+
+
+//----- (00421D00) --------------------------------------------------------
+void __fastcall GameUI_OnPlayerPortraitLeftClick(unsigned int uPlayerID)
+{
+  unsigned int v1; // esi@1
+  int v2; // eax@2
+  Player *v3; // ecx@2
+  Player *v4; // ecx@5
+  unsigned int v5; // [sp-4h] [bp-10h]@21
+
+  v1 = uPlayerID;
+  if ( pParty->pPickedItem.uItemID )
+  {
+    v2 = pPlayers[uPlayerID]->AddItem(0xFFFFFFFFu, pParty->pPickedItem.uItemID);
+    v3 = pPlayers[v1];
+    if ( v2 )
+    {
+      memcpy(&v3->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5], &pParty->pPickedItem, 0x24u);
+      viewparams->bRedrawGameUI = 1;
+      pMouse->RemoveHoldingItem();
+      return;
+    }
+    if ( v3->CanAct() )
+    {
+      v4 = pPlayers[v1];
+    }
+    else
+    {
+      if ( !pPlayers[uActiveCharacter]->CanAct() )
+        goto LABEL_9;
+      v4 = pPlayers[uActiveCharacter];
+    }
+    v4->PlaySound(15, 0);
+  }
+LABEL_9:
+  if ( !pCurrentScreen )
+  {
+    viewparams->bRedrawGameUI = 1;
+    if ( uActiveCharacter != v1 )
+      goto LABEL_27;
+    v5 = 7;
+LABEL_22:
+    pGUIWindow_CurrentMenu = GameUI_InitializeCharacterWindow(v5);
+    return;
+  }
+  if ( pCurrentScreen == 8 )
+    return;
+  if ( pCurrentScreen == 10 )
+  {
+LABEL_23:
+    viewparams->bRedrawGameUI = 1;
+    if ( uActiveCharacter == v1 )
+    {
+      pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
+      pCurrentScreen = 15;
+      goto LABEL_28;
+    }
+LABEL_27:
+    if ( pPlayers[v1]->uTimeToRecovery )
+      return;
+    goto LABEL_28;
+  }
+  if ( pCurrentScreen != 13 )
+  {
+    if ( pCurrentScreen == 14 )
+    {
+LABEL_28:
+      uActiveCharacter = v1;
+      return;
+    }
+    if ( pCurrentScreen != 15 )
+    {
+      viewparams->bRedrawGameUI = 1;
+      uActiveCharacter = v1;
+      if ( pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] == 102 )
+        sub_419100();
+      return;
+    }
+    goto LABEL_23;
+  }
+  if ( ptr_507BC0->field_40 == 1 )
+    return;
+  viewparams->bRedrawGameUI = 1;
+  if ( uActiveCharacter != v1 )
+    goto LABEL_28;
+  if ( dword_F8B19C == 2 || dword_F8B19C == 6 )
+  {
+    pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
+    v5 = 14;
+    goto LABEL_22;
+  }
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+// F8B19C: using guessed type int dword_F8B19C;
+
+//----- (00421EA6) --------------------------------------------------------
+void __cdecl sub_421EA6_OnInventoryLeftClick()
+{
+  Player *v0; // ebx@1
+  signed int v1; // eax@2
+  signed int v2; // ecx@2
+  int v3; // eax@2
+  char v4; // sf@2
+  int v5; // eax@2
+  unsigned int v6; // eax@7
+  unsigned int v7; // esi@12
+  unsigned int v8; // eax@12
+  unsigned int v9; // eax@16
+  unsigned int v10; // eax@18
+  ItemGen this_; // [sp+Ch] [bp-3Ch]@1
+  POINT a2; // [sp+30h] [bp-18h]@4
+  unsigned int v13; // [sp+38h] [bp-10h]@13
+  unsigned int pY; // [sp+3Ch] [bp-Ch]@2
+  unsigned int pX; // [sp+40h] [bp-8h]@2
+  int a4; // [sp+44h] [bp-4h]@2
+
+  v0 = pPlayers[uActiveCharacter];
+  if ( pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] != 103
+    || (pMouse->GetClickPos(&pX, &pY),
+        v1 = pY - 17,
+        v2 = pX - 14,
+        pY = v1,
+        pX = v2,
+        v3 = 14 * (v1 >> 5),
+        v2 >>= 5,
+        v4 = v2 + v3 < 0,
+        v5 = v2 + v3,
+        a4 = v5,
+        v4)
+    || v5 > 126
+    || pMouse->GetCursorPos(&a2)->x >= 462
+    || pMouse->GetCursorPos(&a2)->x < 14 )
+    return;
+  if ( unk_50C9A0 )
+  {
+    v6 = v0->GetItemIDAtInventoryIndex(&a4);
+    if ( v6 )
+    {
+      *((char *)pGUIWindow_Settings->ptr_1C + 8) &= 0x7Fu;
+      *((short *)pGUIWindow_Settings->ptr_1C + 2) = uActiveCharacter - 1;
+      *((int *)pGUIWindow_Settings->ptr_1C + 3) = v6 - 1;
+      *((short *)pGUIWindow_Settings->ptr_1C + 3) = a4;
+      ptr_50C9A4 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6 + 5];
+      unk_50C9A0 = 0;
+      if ( pMessageQueue_50CBD0->uNumMessages )
+        pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+      pMouse->SetCursorBitmap("MICON1");
+      dword_50C9D0 = 113;
+      dword_50C9D4 = 0;
+      dword_50C9D8 = 256;
+    }
+    return;
+  }
+  if ( ptr_50C9A4 )
+    return;
+  v7 = pParty->pPickedItem.uItemID;
+  v8 = v0->GetItemIDAtInventoryIndex(&a4);
+  if ( !v7 )
+  {
+    if ( !v8 )
+      return;
+    memcpy(&pParty->pPickedItem, &v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5], sizeof(pParty->pPickedItem));
+    v0->RemoveItemAtInventoryIndex(a4);
+    v9 = pParty->pPickedItem.uItemID;
+    goto LABEL_24;
+  }
+  v13 = v8;
+  if ( v8 )
+  {
+    a2.y = (LONG)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
+    memcpy(&this_, (const void *)a2.y, sizeof(this_));
+    v0->RemoveItemAtInventoryIndex(a4);
+    pX = v0->AddItem2(a4, &pParty->pPickedItem);
+    if ( !pX )
+    {
+      pX = v0->AddItem2(0xFFFFFFFFu, &pParty->pPickedItem);
+      if ( !pX )
+      {
+        v0->_49298B(&this_, v13 - 1, a4);
+        memcpy((void *)a2.y, &this_, sizeof(ItemGen));
+        return;
+      }
+    }
+    v9 = this_.uItemID;
+    memcpy(&pParty->pPickedItem, &this_, sizeof(pParty->pPickedItem));
+LABEL_24:
+    pMouse->SetCursorBitmap(pItemsTable->pItems[v9].pIconName);
+    return;
+  }
+  v10 = v0->AddItem(a4, v7);
+  pX = v10;
+  if ( v10 || (v10 = v0->AddItem(0xFFFFFFFFu, pParty->pPickedItem.uItemID), (pX = v10) != 0) )
+  {
+    memcpy(&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5], &pParty->pPickedItem, 0x24u);
+    pMouse->RemoveHoldingItem();
+  }
+}
+
+
+//----- (0042213C) --------------------------------------------------------
+void __cdecl OnGameViewportClick()
+{
+  signed int v0; // ebx@2
+  POINT *v1; // esi@3
+  signed int v2; // eax@9
+  BLVFace *v3; // eax@10
+  unsigned int v4; // eax@11
+  unsigned __int16 v5; // dx@14
+  signed int v6; // eax@14
+  char *v7; // esi@15
+  int *v8; // eax@19
+  int v9; // eax@19
+  unsigned int v10; // eax@19
+  int v11; // ecx@21
+  ODMFace *v12; // eax@22
+  LevelDecoration *v13; // esi@24
+  __int16 v14; // ax@25
+  int v15; // ecx@29
+  signed int v16; // edx@30
+  Actor *v17; // esi@30
+  int v18; // ebx@47
+  unsigned __int16 v19; // ax@50
+  const char *v20; // eax@51
+  signed int v21; // eax@58
+  ItemGen *v22; // esi@62
+  unsigned int v23; // eax@62
+  LayingItem a1; // [sp+Ch] [bp-80h]@1
+  POINT v25; // [sp+7Ch] [bp-10h]@3
+  POINT a2; // [sp+84h] [bp-8h]@3
+
+  if ( pRenderer->pRenderD3D )
+  {
+    v0 = pGame->pVisInstance->get_picked_object_zbuf_val();
+  }
+  else
+  {
+    v1 = pMouse->GetCursorPos(&a2);
+    v0 = pRenderer->pActiveZBuffer[v1->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v25)->y]];
+  }
+  if ( (v0 & 7) == 2 )
+  {
+    a2.y = (signed int)(unsigned __int16)v0 >> 3;
+    v21 = (signed int)(unsigned __int16)v0 >> 3;
+    if ( !(pObjectList->pObjects[pLayingItems[v21].uObjectDescID].uFlags & 0x10)
+      && a2.y < 1000
+      && pLayingItems[v21].uObjectDescID
+      && (unsigned int)v0 < 0x2000000 )
+    {
+      v22 = &pLayingItems[v21].stru_24;
+      v23 = pLayingItems[v21].stru_24.uItemID;
+      if ( pItemsTable->pItems[v23].uEquipType == 18 )
+      {
+        party_finds_gold(v22->uAdditionalValue, 0);
+        viewparams->bRedrawGameUI = 1;
+      }
+      else
+      {
+        sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[471], pItemsTable->pItems[v23].pUnidentifiedName);
+        ShowStatusBarString(pTmpBuf2, 2u);
+        if ( v22->uItemID == 506 )
+          _449B7E_toggle_bit(pParty->_award_bits, 184, 1u);
+        if ( v22->uItemID == 455 )
+          _449B7E_toggle_bit(pParty->_award_bits, 185, 1u);
+        if ( !pParty->AddItem(v22) )
+          pParty->SetHoldingItem(v22);
+      }
+      LayingItem::_42F933(a2.y);
+      return;
+    }
+    goto LABEL_13;
+  }
+  if ( (v0 & 7) != 3 )
+  {
+    if ( (v0 & 7) == 5 )
+    {
+      v13 = &pLevelDecorations[(signed int)(unsigned __int16)v0 >> 3];
+      if ( (signed int)(((unsigned int)v0 >> 16) - pDecorationList->pDecorations[v13->uDecorationDescID].uRadius) >= 512 )
+        goto LABEL_13;
+      v14 = v13->field_16_event_id;
+      if ( !v14 )
+      {
+        if ( pLevelDecorations[(signed int)(unsigned __int16)v0 >> 3].IsInteractive() )
+        {
+          v15 = stru_5E4C90._decor_events[v13->_idx_in_stru123 - 75] + 380;
+          _5C3420_pDecoration = &pLevelDecorations[(signed int)(unsigned __int16)v0 >> 3];
+          EventProcessor(v15, 0, 1);
+          _5C3420_pDecoration = 0;
+        }
+        return;
+      }
+      v11 = v14;
+    }
+    else
+    {
+      if ( (v0 & 7) != 6 || (unsigned int)v0 >= 0x2000000 )
+        goto LABEL_13;
+      v2 = (signed int)(unsigned __int16)v0 >> 3;
+      if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+      {
+        v3 = &pIndoor->pFaces[v2];
+        if ( !(v3->uAttributes & 0x2000000) )
+        {
+LABEL_11:
+          v4 = pParty->pPickedItem.uItemID;
+          if ( pParty->pPickedItem.uItemID )
+          {
+LABEL_14:
+            v5 = pItemsTable->pItems[v4].uSpriteID;
+            v6 = 0;
+            a1.uItemType = v5;
+            if ( (signed int)pObjectList->uNumObjects <= 0 )
+            {
+LABEL_18:
+              LOWORD(v6) = 0;
+            }
+            else
+            {
+              v7 = (char *)&pObjectList->pObjects->uObjectID;
+              while ( v5 != *(short *)v7 )
+              {
+                ++v6;
+                v7 += 56;
+                if ( v6 >= (signed int)pObjectList->uNumObjects )
+                  goto LABEL_18;
+              }
+            }
+            a1.uObjectDescID = v6;
+            a1.vPosition.y = pParty->vPosition.y;
+            a1.field_58 = 4;
+            a1.vPosition.x = pParty->vPosition.x;
+            a1.vPosition.z = pParty->sEyelevel + pParty->vPosition.z;
+            a1.uSoundID = 0;
+            a1.uFacing = 0;
+            a1.uAttributes = 8;
+            a1.uSectorID = pIndoor->GetSector(
+                             pParty->vPosition.x,
+                             pParty->vPosition.y,
+                             pParty->sEyelevel + pParty->vPosition.z);
+            a1.uSpriteFrameID = 0;
+            memcpy(&a1.stru_24, &pParty->pPickedItem, 0x24u);
+            v8 = (int *)pMouse->GetCursorPos(&v25);
+            v9 = UnprojectX(*v8);
+            a1.Create(pParty->sRotationY + v9, 184, 200, 0);
+            v10 = pIcons_LOD->LoadTexture(
+                    pItemsTable->pItems[pParty->pPickedItem.uItemID].pIconName,
+                    TEXTURE_16BIT_PALETTE);
+            if (v10 != -1)
+              pIcons_LOD->pTextures[v10].Release();
+            pMouse->RemoveHoldingItem();
+            pIcons_LOD->_40F9C5();
+            return;
+          }
+          ShowNothingHereStatus();
+LABEL_13:
+          v4 = pParty->pPickedItem.uItemID;
+          if ( !pParty->pPickedItem.uItemID )
+            return;
+          goto LABEL_14;
+        }
+        v11 = pIndoor->pFaceExtras[v3->uFaceExtraID].uEventID;
+      }
+      else
+      {
+        v12 = &pOutdoor->pBModels[(signed int)(unsigned __int16)v0 >> 9].pFaces[v2 & 0x3F];
+        if ( !(v12->uAttributes & 0x2000000) )
+          goto LABEL_11;
+        v11 = v12->sCogTriggeredID;
+      }
+    }
+    EventProcessor(v11, (unsigned __int16)v0, 1);
+    return;
+  }
+  v16 = (signed int)(unsigned __int16)v0 >> 3;
+  a2.y = v16;
+  v17 = &pActors[v16];
+  if ( v17->uAIState == 5 )
+  {
+    if ( (unsigned int)v0 < 0x2000000 )
+    {
+      stru_50C198.LootActor(&pActors[v16]);
+      return;
+    }
+    goto LABEL_13;
+  }
+  if ( GetAsyncKeyState(VK_SHIFT) >= 0 )
+  {
+    if ( !v17->GetActorsRelation(0) && !(BYTE2(v17->uAttributes) & 8) )
+    {
+      if ( (unsigned int)v0 >= 0x2000000 )
+        goto LABEL_13;
+      if ( !v17->CanAct() )
+        return;
+      v18 = a2.y;
+      Actor::FaceObject(a2.y, 4u, 0, 0);
+      if ( !v17->uNPC_ID )
+      {
+        v19 = pNPCStats->pGroups_copy[v17->uGroup];
+        if ( v19 )
+        {
+          v20 = pNPCStats->pCatchPhrases[v19];
+          if ( v20 )
+          {
+            pParty->uFlags |= 2u;
+            strcpy(byte_5B0938, v20);
+            sub_4451A8_press_any_key(0, 0, 0);
+          }
+        }
+        return;
+      }
+      if ( (signed int)pMessageQueue_50CBD0->uNumMessages >= 40 )
+        return;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)161;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v18;
+LABEL_42:
+      *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+      ++pMessageQueue_50CBD0->uNumMessages;
+      return;
+    }
+    if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 3 )
+    {
+      pTurnEngine->field_18 |= 8u;
+      return;
+    }
+    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)23;
+      goto LABEL_41;
+    }
+  }
+  else
+  {
+    if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 3 )
+    {
+      pParty->uFlags |= 8u;
+      return;
+    }
+    if ( uActiveCharacter
+      && sub_427769_spell(pPlayers[uActiveCharacter]->uQuickSpell)
+      && (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)25;
+LABEL_41:
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+      goto LABEL_42;
+    }
+  }
+}
+
+//----- (004226C2) --------------------------------------------------------
+bool __cdecl sub_4226C2()
+{
+  if ( pCurrentScreen
+    && pCurrentScreen != 4
+    && pCurrentScreen != 17 )
+  {
+    if ( pCurrentScreen == 18 )
+      return pVideoPlayer->pSmackerMovie != 0;
+    if ( pCurrentScreen != 19 )
+      return 1;
+  }
+  return 0;
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (004226EF) --------------------------------------------------------
+void __fastcall SetUserInterface(int a1, bool bReplace)
+{
+  int v2; // ecx@2
+  unsigned int v3; // eax@7
+  unsigned __int16 v4; // dx@7
+  unsigned __int16 v5; // cx@7
+  unsigned __int16 v6; // [sp-4h] [bp-14h]@7
+
+  if ( a1 )
+  {
+    v2 = a1 - 1;
+    if ( v2 )
+    {
+      if ( v2 != 1 )
+        return;
+      if ( bReplace )
+      {
+        pTexture_RightFrame->Reload("ib-r-C.pcx");
+        pTexture_BottomFrame->Reload("ib-b-C.pcx");
+        pTexture_TopFrame->Reload("ib-t-C.pcx");
+        pTexture_LeftFrame->Reload("ib-l-C.pcx");
+        pTexture_StatusBar->Reload("IB-Foot-c.pcx");
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_right_panel], "ib-mb-C", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079D8], "ib-autmask-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079B4], "IB-COMP-C", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079D0], "IB-InitG-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079C8], "IB-InitY-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079CC], "IB-InitR-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507990], "IB-NPCLD-C", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50798C], "IB-NPCRD-C", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507980], "ib-autout-C", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507984], "ib-autin-C", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_50C98C], "IB-selec-C", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50797C], "ib-m1d-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507978], "ib-m2d-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507974], "ib-m3d-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507970], "ib-m4d-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_50796C], "isg-01-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507968], "isg-02-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507964], "isg-03-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507960], "isg-04-c", 2);
+        pUIAnim_WizardEye->uIconID = pIconsFrameTable->FindIcon("wizeyeC");
+        pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnim_WizardEye->uIconID);
+        pUIAnum_Torchlight->uIconID = pIconsFrameTable->FindIcon("torchC");
+        pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnum_Torchlight->uIconID);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_506438], "ib-bcu-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50795C], "evtnpc-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507958], "fr_inven-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_Parchment], "parchment", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076B4], "cornr_ll-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076B0], "cornr_lr-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076AC], "cornr_ul-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A8], "cornr_ur-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A4], "edge_btm-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A0], "edge_lf-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50769C], "edge_rt-c", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507698], "edge_top-c", 2);
+        pIcons_LOD->ReloadTexture(pTexture_591428, "endcap-c", 2);
+      }
+      else
+      {
+        pTexture_RightFrame->Load("ib-r-C.pcx", 0);
+        pTexture_BottomFrame->Load("ib-b-c.pcx", 0);
+        pTexture_TopFrame->Load("ib-t-C.pcx", 0);
+        pTexture_LeftFrame->Load("ib-l-C.pcx", 0);
+        pTexture_StatusBar->Load("IB-Foot-c.pcx", 0);
+        uTextureID_right_panel = pIcons_LOD->LoadTexture("ib-mb-C", TEXTURE_16BIT_PALETTE);
+        dword_5079D8 = pIcons_LOD->LoadTexture("ib-autmask-c", TEXTURE_16BIT_PALETTE);
+        dword_5079B4 = pIcons_LOD->LoadTexture("IB-COMP-C", TEXTURE_16BIT_PALETTE);
+        dword_5079D0 = pIcons_LOD->LoadTexture("IB-InitG-c", TEXTURE_16BIT_PALETTE);
+        dword_5079C8 = pIcons_LOD->LoadTexture("IB-InitY-c", TEXTURE_16BIT_PALETTE);
+        dword_5079CC = pIcons_LOD->LoadTexture("IB-InitR-c", TEXTURE_16BIT_PALETTE);
+        uTextureID_507990 = pIcons_LOD->LoadTexture("IB-NPCLD-C", TEXTURE_16BIT_PALETTE);
+        uTextureID_50798C = pIcons_LOD->LoadTexture("IB-NPCRD-C", TEXTURE_16BIT_PALETTE);
+        uTextureID_507980 = pIcons_LOD->LoadTexture("ib-autout-C", TEXTURE_16BIT_PALETTE);
+        uTextureID_507984 = pIcons_LOD->LoadTexture("ib-autin-C", TEXTURE_16BIT_PALETTE);
+        dword_50C98C = pIcons_LOD->LoadTexture("IB-selec-C", TEXTURE_16BIT_PALETTE);
+        uTextureID_50797C = pIcons_LOD->LoadTexture("ib-m1d-c", TEXTURE_16BIT_PALETTE);
+        uTextureID_507978 = pIcons_LOD->LoadTexture("ib-m2d-c", TEXTURE_16BIT_PALETTE);
+        dword_507974 = pIcons_LOD->LoadTexture("ib-m3d-c", TEXTURE_16BIT_PALETTE);
+        uTextureID_507970 = pIcons_LOD->LoadTexture("ib-m4d-c", TEXTURE_16BIT_PALETTE);
+        uTextureID_506438 = pIcons_LOD->LoadTexture("ib-bcu-c", TEXTURE_16BIT_PALETTE);
+        dword_50796C = pIcons_LOD->LoadTexture("isg-01-c", TEXTURE_16BIT_PALETTE);
+        dword_507968 = pIcons_LOD->LoadTexture("isg-02-c", TEXTURE_16BIT_PALETTE);
+        dword_507964 = pIcons_LOD->LoadTexture("isg-03-c", TEXTURE_16BIT_PALETTE);
+        dword_507960 = pIcons_LOD->LoadTexture("isg-04-c", TEXTURE_16BIT_PALETTE);
+        uTextureID_50795C = pIcons_LOD->LoadTexture("evtnpc-c", TEXTURE_16BIT_PALETTE);
+        uTextureID_507958 = pIcons_LOD->LoadTexture("fr_inven", TEXTURE_16BIT_PALETTE);
+        pUIAnim_WizardEye->uIconID = pIconsFrameTable->FindIcon("wizeyeC");
+        pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnim_WizardEye->uIconID);
+        pUIAnum_Torchlight->uIconID = pIconsFrameTable->FindIcon("torchC");
+        pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnum_Torchlight->uIconID);
+      }
+      v3 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xC8u, 0, 0);
+      v4 = 0;
+      v6 = 0;
+      v5 = 10;
+    }
+    else
+    {
+      if ( bReplace )
+      {
+        pTexture_RightFrame->Reload("ib-r-a.pcx");
+        pTexture_BottomFrame->Reload("ib-b-a.pcx");
+        pTexture_TopFrame->Reload("ib-t-a.pcx");
+        pTexture_LeftFrame->Reload("ib-l-a.pcx");
+        pTexture_StatusBar->Reload("IB-Foot-a.pcx");
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_right_panel], "ib-mb-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079D8], "ib-autmask-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079B4], "IB-COMP-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079D0], "IB-InitG-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079C8], "IB-InitY-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079CC], "IB-InitR-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507990], "IB-NPCLD-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50798C], "IB-NPCRD-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507980], "ib-autout-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507984], "ib-autin-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_50C98C], "IB-selec-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50797C], "ib-m1d-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507978], "ib-m2d-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507974], "ib-m3d-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507970], "ib-m4d-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_50796C], "isg-01-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507968], "isg-02-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507964], "isg-03-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507960], "isg-04-a", 2);
+        pUIAnim_WizardEye->uIconID = pIconsFrameTable->FindIcon("wizeyeA");
+        pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnim_WizardEye->uIconID);
+        pUIAnum_Torchlight->uIconID = pIconsFrameTable->FindIcon("torchA");
+        pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnum_Torchlight->uIconID);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_506438], "ib-bcu-a", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50795C], "evtnpc", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507958], "fr_inven", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_Parchment], "parchment", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076B4], "cornr_ll", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076B0], "cornr_lr", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076AC], "cornr_ul", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A8], "cornr_ur", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A4], "edge_btm", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A0], "edge_lf", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50769C], "edge_rt", 2);
+        pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507698], "edge_top", 2);
+        pIcons_LOD->ReloadTexture(pTexture_591428, "endcap", 2);
+      }
+      else
+      {
+        pTexture_RightFrame->Load("ib-r-A.pcx", 0);
+        pTexture_BottomFrame->Load("ib-b-A.pcx", 0);
+        pTexture_TopFrame->Load("ib-t-A.pcx", 0);
+        pTexture_LeftFrame->Load("ib-l-A.pcx", 0);
+        pTexture_StatusBar->Load("IB-Foot-a.pcx", 0);
+        uTextureID_right_panel = pIcons_LOD->LoadTexture("ib-mb-A", TEXTURE_16BIT_PALETTE);
+        dword_5079D8 = pIcons_LOD->LoadTexture("ib-autmask-a", TEXTURE_16BIT_PALETTE);
+        dword_5079B4 = pIcons_LOD->LoadTexture("IB-COMP-A", TEXTURE_16BIT_PALETTE);
+        dword_5079D0 = pIcons_LOD->LoadTexture("IB-InitG-a", TEXTURE_16BIT_PALETTE);
+        dword_5079C8 = pIcons_LOD->LoadTexture("IB-InitY-a", TEXTURE_16BIT_PALETTE);
+        dword_5079CC = pIcons_LOD->LoadTexture("IB-InitR-a", TEXTURE_16BIT_PALETTE);
+        uTextureID_507990 = pIcons_LOD->LoadTexture("IB-NPCLD-A", TEXTURE_16BIT_PALETTE);
+        uTextureID_50798C = pIcons_LOD->LoadTexture("IB-NPCRD-A", TEXTURE_16BIT_PALETTE);
+        dword_50C98C = pIcons_LOD->LoadTexture("IB-selec-A", TEXTURE_16BIT_PALETTE);
+        uTextureID_50797C = pIcons_LOD->LoadTexture("ib-m1d-a", TEXTURE_16BIT_PALETTE);
+        uTextureID_507978 = pIcons_LOD->LoadTexture("ib-m2d-a", TEXTURE_16BIT_PALETTE);
+        dword_507974 = pIcons_LOD->LoadTexture("ib-m3d-a", TEXTURE_16BIT_PALETTE);
+        uTextureID_507970 = pIcons_LOD->LoadTexture("ib-m4d-a", TEXTURE_16BIT_PALETTE);
+        uTextureID_507980 = pIcons_LOD->LoadTexture("ib-autout-a", TEXTURE_16BIT_PALETTE);
+        uTextureID_507984 = pIcons_LOD->LoadTexture("ib-autin-a", TEXTURE_16BIT_PALETTE);
+        uTextureID_506438 = pIcons_LOD->LoadTexture("ib-bcu-a", TEXTURE_16BIT_PALETTE);
+        dword_50796C = pIcons_LOD->LoadTexture("isg-01-a", TEXTURE_16BIT_PALETTE);
+        dword_507968 = pIcons_LOD->LoadTexture("isg-02-a", TEXTURE_16BIT_PALETTE);
+        dword_507964 = pIcons_LOD->LoadTexture("isg-03-a", TEXTURE_16BIT_PALETTE);
+        dword_507960 = pIcons_LOD->LoadTexture("isg-04-a", TEXTURE_16BIT_PALETTE);
+        uTextureID_50795C = pIcons_LOD->LoadTexture("evtnpc", TEXTURE_16BIT_PALETTE);
+        uTextureID_507958 = pIcons_LOD->LoadTexture("fr_inven", TEXTURE_16BIT_PALETTE);
+        pUIAnim_WizardEye->uIconID = pIconsFrameTable->FindIcon("wizeyeA");
+        pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnim_WizardEye->uIconID);
+        pUIAnum_Torchlight->uIconID = pIconsFrameTable->FindIcon("torchA");
+        pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnum_Torchlight->uIconID);
+        uTextureID_Parchment = pIcons_LOD->LoadTexture("parchment", TEXTURE_16BIT_PALETTE);
+        uTextureID_5076B4 = pIcons_LOD->LoadTexture("cornr_ll", TEXTURE_16BIT_PALETTE);
+        uTextureID_5076B0 = pIcons_LOD->LoadTexture("cornr_lr", TEXTURE_16BIT_PALETTE);
+        uTextureID_5076AC = pIcons_LOD->LoadTexture("cornr_ul", TEXTURE_16BIT_PALETTE);
+        uTextureID_5076A8 = pIcons_LOD->LoadTexture("cornr_ur", TEXTURE_16BIT_PALETTE);
+        uTextureID_5076A4 = pIcons_LOD->LoadTexture("edge_btm", TEXTURE_16BIT_PALETTE);
+        uTextureID_5076A0 = pIcons_LOD->LoadTexture("edge_lf", TEXTURE_16BIT_PALETTE);
+        uTextureID_50769C = pIcons_LOD->LoadTexture("edge_rt", TEXTURE_16BIT_PALETTE);
+        uTextureID_507698 = pIcons_LOD->LoadTexture("edge_top", TEXTURE_16BIT_PALETTE);
+        pTexture_591428 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("endcap", TEXTURE_16BIT_PALETTE)];
+
+      }
+      v3 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xAu, 0, 0);
+      v4 = 214;
+      v5 = 230;
+      v6 = 193;
+    }
+  }
+  else
+  {
+    if ( bReplace )
+    {
+      pTexture_RightFrame->Reload("ib-r-B.pcx");
+      pTexture_BottomFrame->Reload("ib-b-B.pcx");
+      pTexture_TopFrame->Reload("ib-t-B.pcx");
+      pTexture_LeftFrame->Reload("ib-l-B.pcx");
+      pTexture_StatusBar->Reload("IB-Foot-b.pcx");
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_right_panel], "ib-mb-B", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079D8], "ib-autmask-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079B4], "IB-COMP-B", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079D0], "IB-InitG-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079C8], "IB-InitY-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_5079CC], "IB-InitR-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507990], "IB-NPCLD-B", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50798C], "IB-NPCRD-B", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507980], "ib-autout-B", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507984], "ib-autin-B", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_50C98C], "IB-selec-B", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50797C], "ib-m1d-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507978], "ib-m2d-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507974], "ib-m3d-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507970], "ib-m4d-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_50796C], "isg-01-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507968], "isg-02-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507964], "isg-03-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[dword_507960], "isg-04-b", 2);
+      pUIAnim_WizardEye->uIconID = pIconsFrameTable->FindIcon("wizeyeB");
+      pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnim_WizardEye->uIconID);
+      pUIAnum_Torchlight->uIconID = pIconsFrameTable->FindIcon("torchB");
+      pIconsFrameTable->InitializeAnimation((signed __int16)pUIAnum_Torchlight->uIconID);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_506438], "ib-bcu-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50795C], "evtnpc-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507958], "fr_inven-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_Parchment], "parchment", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076B4], "cornr_ll-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076B0], "cornr_lr-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076AC], "cornr_ul-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A8], "cornr_ur-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A4], "edge_btm-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_5076A0], "edge_lf-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_50769C], "edge_rt-b", 2);
+      pIcons_LOD->ReloadTexture(&pIcons_LOD->pTextures[uTextureID_507698], "edge_top-b", 2);
+      pIcons_LOD->ReloadTexture(pTexture_591428, "endcap-b", 2);
+    }
+    v3 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0, 0xC8u);
+    v5 = 255;
+    v4 = 225;
+    v6 = 255;
+  }
+  uGameUIFontMain = v3;
+  uGameUIFontShadow = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v5, v4, v6);
+}
+
+
+
+//----- (00423AEE) --------------------------------------------------------
+void __cdecl reset_some_strus_flt_2Cs()
+{
+  float *v0; // eax@1
+  signed int v1; // ecx@1
+  signed int v2; // edx@1
+  float *v3; // eax@3
+  signed int v4; // edx@3
+  float *v5; // eax@5
+  signed int v6; // edx@5
+  float *v7; // eax@7
+  signed int v8; // edx@7
+  float *v9; // eax@9
+
+  v0 = &array_50AC10[0].flt_2C;
+  v1 = 50;
+  v2 = 50;
+  do
+  {
+    *v0 = 0.0;
+    v0 += 12;
+    --v2;
+  }
+  while ( v2 );
+  v3 = &array_50A2B0[0].flt_2C;
+  v4 = 50;
+  do
+  {
+    *v3 = 0.0;
+    v3 += 12;
+    --v4;
+  }
+  while ( v4 );
+  v5 = &array_509950[0].flt_2C;
+  v6 = 50;
+  do
+  {
+    *v5 = 0.0;
+    v5 += 12;
+    --v6;
+  }
+  while ( v6 );
+  v7 = &array_508FF0[0].flt_2C;
+  v8 = 50;
+  do
+  {
+    *v7 = 0.0;
+    v7 += 12;
+    --v8;
+  }
+  while ( v8 );
+  v9 = &array_508690[0].flt_2C;
+  do
+  {
+    *v9 = 0.0;
+    v9 += 12;
+    --v1;
+  }
+  while ( v1 );
+}
+
+//----- (00423B4A) --------------------------------------------------------
+void __cdecl sub_423B4A()
+{
+  float *v0; // eax@1
+  signed int v1; // ecx@1
+
+  v0 = &array_507D30[0].flt_2C;
+  v1 = 50;
+  do
+  {
+    *v0 = 0.0;
+    v0 += 12;
+    --v1;
+  }
+  while ( v1 );
+}
+
+//----- (00423B5D) --------------------------------------------------------
+int __fastcall sub_423B5D(unsigned int uFaceID)
+{
+  BLVFace *v1; // ebx@1
+  Vec3_short_ *v2; // esi@1
+  //int v3; // ST28_4@1
+  __int16 v4; // ST2C_2@1
+  //signed int v5; // esi@1
+  //Vec3_short_ *v6; // eax@4
+  //signed int v7; // edi@5
+  //signed int v8; // eax@5
+  //signed int i_; // ecx@10
+  int v10; // eax@10
+  int v11; // edx@11
+  int v12; // ST28_4@12
+  signed int v13; // edx@12
+  signed __int64 v14; // qtt@12
+  int *v15; // ebx@12
+  int v16; // ST28_4@14
+  signed int v17; // eax@14
+  signed __int64 v18; // qtt@14
+  signed int v19; // edx@15
+  signed int v20; // edx@17
+  signed int v21; // ebx@19
+  signed int v22; // esi@20
+  int v23; // edi@21
+  int v24; // eax@21
+  int v25; // eax@22
+  int v26; // eax@22
+  signed int v27; // ST30_4@24
+  signed __int64 v28; // qtt@24
+  int v29; // ST18_4@25
+  int v30; // eax@26
+  int v31; // eax@27
+  int v32; // eax@27
+  signed int v33; // ST30_4@29
+  signed __int64 v34; // qtt@29
+  int v35; // ST30_4@30
+  signed int v36; // edi@31
+  unsigned int v37; // eax@31
+  bool v38; // edx@31
+  int v39; // ecx@31
+  int v40; // ecx@32
+  int v41; // esi@32
+  int v42; // eax@34
+  signed int v43; // ebx@41
+  unsigned int v44; // eax@41
+  signed int v45; // ecx@42
+  int v46; // esi@42
+  int v47; // eax@44
+  signed int v48; // edi@51
+  unsigned int v49; // eax@51
+  bool v50; // edx@51
+  int v51; // ecx@51
+  int v52; // ecx@52
+  signed int v53; // esi@52
+  int v54; // eax@54
+  int v55; // ebx@61
+  unsigned int v56; // eax@61
+  signed int v57; // ecx@62
+  int v58; // esi@62
+  int v59; // eax@64
+  char v61; // zf@72
+  signed int v62; // edx@75
+  int v63; // ecx@76
+  int v64; // esi@76
+  int v65; // ecx@83
+  //signed int v66; // [sp+14h] [bp-14h]@3
+  int v67; // [sp+14h] [bp-14h]@34
+  int v68; // [sp+14h] [bp-14h]@44
+  int v69; // [sp+14h] [bp-14h]@54
+  int v70; // [sp+14h] [bp-14h]@64
+  signed int v71; // [sp+14h] [bp-14h]@75
+  bool thisa; // [sp+18h] [bp-10h]@9
+  int thisb; // [sp+18h] [bp-10h]@12
+  int thisc; // [sp+18h] [bp-10h]@20
+  bool thisd; // [sp+18h] [bp-10h]@41
+  bool thise; // [sp+18h] [bp-10h]@61
+  int thisf; // [sp+18h] [bp-10h]@74
+  signed int v79; // [sp+1Ch] [bp-Ch]@9
+  int v80; // [sp+1Ch] [bp-Ch]@76
+  bool v81; // [sp+20h] [bp-8h]@10
+  bool v82; // [sp+20h] [bp-8h]@32
+  bool v83; // [sp+20h] [bp-8h]@42
+  bool v84; // [sp+20h] [bp-8h]@52
+  bool v85; // [sp+20h] [bp-8h]@62
+  //signed int i; // [sp+24h] [bp-4h]@9
+  signed int ia; // [sp+24h] [bp-4h]@19
+  signed int ib; // [sp+24h] [bp-4h]@31
+  signed int ic; // [sp+24h] [bp-4h]@41
+  signed int id; // [sp+24h] [bp-4h]@51
+  signed int ie; // [sp+24h] [bp-4h]@61
+
+  v1 = &pIndoor->pFaces[uFaceID];
+  //this = pGame->pIndoorCameraD3D;
+  v2 = &pIndoor->pVertices[v1->pVertexIDs[0]];
+  //v3 = *(_DWORD *)&v2->x;
+  v4 = v2->z;
+  //v5 = 0;
+  if ( v1->pFacePlane_old.vNormal.x * (v2->x - pBLVRenderParams->vPartyPos.x)
+     + v1->pFacePlane_old.vNormal.y * (v2->y - pBLVRenderParams->vPartyPos.y)
+     + v1->pFacePlane_old.vNormal.z * (v2->z - pBLVRenderParams->vPartyPos.z) < 0 )
+  {
+    dword_50B700 = 1;
+  }
+  else
+  {
+    dword_50B700 = 0;
+    if ( !(v1->uAttributes & 1) )
+      return 0;
+  }
+  //v66 = v1->uNumVertices;
+  for (uint i = 0; i < v1->uNumVertices; ++i)
+  {
+      auto v6 = &pIndoor->pVertices[v1->pVertexIDs[i]];
+      pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(
+        v6->x,
+        v6->y,
+        v6->z,
+        &_50B924_view_transformed_xs[i],
+        &_50B834_view_transformed_zs[i],
+        &_50B744_view_transformed_ys[i],
+        0);
+  }
+
+  //v7 = v1->uNumVertices;
+  //v8 = 0;
+  if (v1->uNumVertices <= 0)
+    return 0;
+
+  bool bFound = false;
+  for (uint i = 0; i < v1->uNumVertices; ++i)
+    if (_50B924_view_transformed_xs[i] >= 0x80000u)
+    {
+      bFound = true;
+      break;
+    }
+  if (!bFound)
+    return 0;
+
+  v79 = 0;
+  _50B924_view_transformed_xs[v1->uNumVertices] = _50B924_view_transformed_xs[0];
+  _50B834_view_transformed_zs[v1->uNumVertices] = _50B834_view_transformed_zs[0];
+  _50B744_view_transformed_ys[v1->uNumVertices] = _50B744_view_transformed_ys[0];
+  thisa = _50B924_view_transformed_xs[0] >= 0x80000u;
+  //int i = 1;
+  for (uint i = 1; i < v1->uNumVertices; ++i)
+  {
+      v10 = _50B924_view_transformed_xs[i];
+      v81 = v10 >= (signed int)0x80000u;
+      if ( thisa ^ v81 )
+      {
+        v11 = _50B924_view_transformed_xs[i - 1];
+        if ( v10 >= (signed int)0x80000u )
+        {
+          v12 = v10 - v11;
+          v13 = 0x80000 - v11;
+          LODWORD(v14) = v13 << 16;
+          HIDWORD(v14) = v13 >> 16;
+          v15 = &_50B744_view_transformed_ys[i - 1];
+          dword_50B828[v79] = ((unsigned __int64)((_50B834_view_transformed_zs[i] - _50B834_view_transformed_zs[i - 1])
+                                                * v14
+                                                / v12) >> 16)
+                            + _50B834_view_transformed_zs[i - 1];
+          thisb = (unsigned __int64)((_50B744_view_transformed_ys[i] - _50B744_view_transformed_ys[i - 1]) * v14 / v12) >> 16;
+        }
+        else
+        {
+          v16 = v11 - v10;
+          v17 = 0x80000 - v10;
+          LODWORD(v18) = v17 << 16;
+          HIDWORD(v18) = v17 >> 16;
+          v15 = &_50B744_view_transformed_ys[i];
+          dword_50B828[v79] = ((unsigned __int64)((_50B834_view_transformed_zs[i - 1] - _50B834_view_transformed_zs[i])
+                                                * v18
+                                                / v16) >> 16)
+                            + _50B834_view_transformed_zs[i];
+          thisb = (unsigned __int64)((_50B744_view_transformed_ys[i - 1] - _50B744_view_transformed_ys[i]) * v18 / v16) >> 16;
+        }
+        v19 = v79++;
+        //v7 = v66;
+        dword_50B738[v19] = thisb + *v15;
+        dword_50B918[v19] = 0x80000u;
+      }
+      if ( v81 )
+      {
+        v20 = v79++;
+        dword_50B918[v20] = _50B924_view_transformed_xs[i];
+        dword_50B828[v20] = _50B834_view_transformed_zs[i];
+        dword_50B738[v20] = _50B744_view_transformed_ys[i];
+      }
+      //++i;
+      thisa = v81;
+  }
+  ia = 0;
+  v21 = v79;
+  dword_50B918[v79] = dword_50B918[0];
+  dword_50B828[v79] = dword_50B828[0];
+  for ( dword_50B738[v79] = dword_50B738[0]; ia < v79; dword_50BA08[v22] = pBLVRenderParams->uViewportCenterY - v35 )
+  {
+    v22 = ia;
+    thisc = abs(dword_50B918[ia]);
+    if ( abs(dword_50B828[ia]) >> 13 <= thisc )
+    {
+      v27 = dword_50B828[v22];
+      LODWORD(v28) = v27 << 16;
+      HIDWORD(v28) = v27 >> 16;
+      v26 = v28 / dword_50B918[v22];
+      v23 = 0;
+    }
+    else
+    {
+      v23 = 0;
+      v24 = 0;
+      if ( dword_50B828[v22] >= 0 )
+      {
+        LOBYTE(v24) = dword_50B918[v22] >= 0;
+        v26 = ((v24 - 1) & 0xFF800000) + 0x400000;
+      }
+      else
+      {
+        LOBYTE(v24) = dword_50B918[v22] >= 0;
+        v25 = v24 - 1;
+        v26 = (v25 & 0x800000) - 0x400000;
+      }
+    }
+    v29 = dword_50B738[v22];
+    dword_50BAF4_xs[v22 + 1] = v26;
+    if ( abs(v29) >> 13 <= thisc )
+    {
+      v33 = dword_50B738[v22];
+      LODWORD(v34) = v33 << 16;
+      HIDWORD(v34) = v33 >> 16;
+      v32 = v34 / dword_50B918[v22];
+    }
+    else
+    {
+      v30 = 0;
+      if ( dword_50B738[v22] >= v23 )
+      {
+        LOBYTE(v30) = dword_50B918[v22] >= v23;
+        v32 = ((v30 - 1) & 0xFF800000) + 0x400000;
+      }
+      else
+      {
+        LOBYTE(v30) = dword_50B918[v22] >= v23;
+        v31 = v30 - 1;
+        v32 = (v31 & 0x800000) - 0x400000;
+      }
+    }
+    dword_50BA08[v22] = v32;
+    dword_50BAF4_xs[v22 + 1] = (unsigned __int64)(SHIWORD(pBLVRenderParams->field_40)
+                                                * (signed __int64)dword_50BAF4_xs[v22 + 1]) >> 16;
+    v35 = (unsigned __int64)(SHIWORD(pBLVRenderParams->field_40) * (signed __int64)dword_50BA08[v22]) >> 16;
+    dword_50BAF4_xs[v22 + 1] = pBLVRenderParams->uViewportCenterX - dword_50BAF4_xs[v22 + 1];
+    ++ia;
+  }
+  v36 = 0;
+  dword_50BAF4_xs[v21 + 1] = dword_50BAF4_xs[1];
+  dword_50BA08[v21] = dword_50BA08[0];
+  v37 = pBLVRenderParams->uViewportX;
+  v38 = dword_50BAF4_xs[1] < (signed int)pBLVRenderParams->uViewportX;
+  LOBYTE(v38) = dword_50BAF4_xs[1] >= (signed int)pBLVRenderParams->uViewportX;
+  v39 = 1;
+  ib = 1;
+  if ( v79 < 1 )
+    return 0;
+  do
+  {
+    v40 = v39;
+    v41 = dword_50BAF4_xs[v40 + 1];
+    v82 = v41 >= (signed int)v37;
+    if ( v38 ^ v82 )
+    {
+      if ( v41 >= (signed int)v37 )
+      {
+        v67 = (signed int)(v37 - dword_50BAF4_xs[v40])
+            * (signed __int64)(dword_50BA08[v40] - dword_50B9F8[v40 + 3])
+            / (v41 - dword_50BAF4_xs[v40]);
+        v42 = dword_50B9F8[v40 + 3];
+      }
+      else
+      {
+        v67 = (signed int)(v37 - v41)
+            * (signed __int64)(dword_50B9F8[v40 + 3] - dword_50BA08[v40])
+            / (dword_50BAF4_xs[v40] - v41);
+        v42 = dword_50BA08[v40];
+      }
+      ++v36;
+      dword_50B9F8[v36] = v67 + v42;
+      v37 = pBLVRenderParams->uViewportX;
+      dword_50BAE8_xs[v36] = pBLVRenderParams->uViewportX;
+    }
+    v38 = v82;
+    if ( v82 )
+    {
+      dword_50BAE8_xs[v36 + 1] = dword_50BAF4_xs[v40 + 1];
+      dword_50B9F8[v36++ + 1] = dword_50BA08[v40];
+    }
+    v39 = ib++ + 1;
+  }
+  while ( ib <= v79 );
+
+  if ( !v36
+    || (v43 = 0,
+        dword_50BAE8_xs[v36 + 1] = dword_50BAE8_xs[1],
+        dword_50B9F8[v36 + 1] = dword_50B9F8[1],
+        v44 = pBLVRenderParams->uViewportZ,
+        thisd = dword_50BAE8_xs[1] <= (signed int)pBLVRenderParams->uViewportZ,
+        ic = 1,
+        v36 < 1) )
+    return 0;
+
+  do
+  {
+    v45 = ic;
+    v46 = dword_50BAE8_xs[ic + 1];
+    v83 = v46 <= (signed int)v44;
+    if ( thisd ^ v83 )
+    {
+      if ( v46 <= (signed int)v44 )
+      {
+        v68 = (signed int)(v44 - dword_50BAE8_xs[v45])
+            * (signed __int64)(dword_50B9F8[v45 + 1] - dword_50B9F8[v45])
+            / (v46 - dword_50BAE8_xs[v45]);
+        v47 = dword_50B9F8[v45];
+      }
+      else
+      {
+        v68 = (signed int)(v44 - v46)
+            * (signed __int64)(dword_50B9F8[v45] - dword_50B9F8[v45 + 1])
+            / (dword_50BAE8_xs[v45] - v46);
+        v47 = dword_50B9F8[v45 + 1];
+      }
+      ++v43;
+      dword_50B9EC[v43] = v68 + v47;
+      v44 = pBLVRenderParams->uViewportZ;
+      dword_50BADC_xs[v43] = pBLVRenderParams->uViewportZ;
+    }
+    if ( v83 )
+    {
+      dword_50BAE0[v43] = dword_50BAE8_xs[v45 + 1];
+      dword_50B9F0[v43++] = dword_50B9F8[v45 + 1];
+    }
+    ++ic;
+    thisd = v83;
+  }
+  while ( ic <= v36 );
+  if ( !v43
+    || (v48 = 0,
+        dword_50BAE0[v43] = dword_50BAE0[0],
+        dword_50B9F0[v43] = dword_50B9F0[0],
+        v49 = pBLVRenderParams->uViewportY,
+        v50 = dword_50B9F0[0] < (signed int)pBLVRenderParams->uViewportY,
+        LOBYTE(v50) = dword_50B9F0[0] >= (signed int)pBLVRenderParams->uViewportY,
+        v51 = 1,
+        id = 1,
+        v43 < 1) )
+    return 0;
+  do
+  {
+    v52 = v51;
+    v53 = dword_50B9F0[v52];
+    v84 = v53 >= (signed int)v49;
+    if ( v50 ^ v84 )
+    {
+      if ( v53 >= (signed int)v49 )
+      {
+        v69 = (signed int)(v49 - dword_50B9EC[v52])
+            * (signed __int64)(dword_50BAE0[v52] - dword_50BADC_xs[v52])
+            / (v53 - dword_50B9EC[v52]);
+        v54 = dword_50BADC_xs[v52];
+      }
+      else
+      {
+        v69 = (signed int)(v49 - v53)
+            * (signed __int64)(dword_50BADC_xs[v52] - dword_50BAE0[v52])
+            / (dword_50B9EC[v52] - v53);
+        v54 = dword_50BAE0[v52];
+      }
+      ++v48;
+      dword_50BAD0[v48] = v69 + v54;
+      v49 = pBLVRenderParams->uViewportY;
+      dword_50B9E0_ys[v48] = pBLVRenderParams->uViewportY;
+    }
+    v50 = v84;
+    if ( v84 )
+    {
+      dword_50BAD4[v48] = dword_50BAE0[v52];
+      dword_50B9E0_ys[v48++ + 1] = dword_50B9F0[v52];
+    }
+    v51 = id++ + 1;
+  }
+  while ( id <= v43 );
+  if ( !v48
+    || (v55 = 0,
+        dword_50BAD4[v48] = dword_50BAD4[0],
+        dword_50B9E0_ys[v48 + 1] = dword_50B9E0_ys[1],
+        v56 = pBLVRenderParams->uViewportW,
+        thise = dword_50B9E0_ys[1] <= (signed int)pBLVRenderParams->uViewportW,
+        ie = 1,
+        v48 < 1) )
+    return 0;
+  do
+  {
+    v57 = ie;
+    v58 = dword_50B9E0_ys[ie + 1];
+    v85 = v58 <= (signed int)v56;
+    if ( thise ^ v85 )
+    {
+      if ( v58 <= (signed int)v56 )
+      {
+        v70 = (signed int)(v56 - dword_50B9E0_ys[v57])
+            * (signed __int64)(dword_50BAD4[v57] - dword_50BAD0[v57])
+            / (v58 - dword_50B9E0_ys[v57]);
+        v59 = dword_50BAD0[v57];
+      }
+      else
+      {
+        v70 = (signed int)(v56 - v58)
+            * (signed __int64)(dword_50BAD0[v57] - dword_50BAD4[v57])
+            / (dword_50B9E0_ys[v57] - v58);
+        v59 = dword_50BAD4[v57];
+      }
+      ++v55;
+      dword_50BAC4[v55] = v70 + v59;
+      v56 = pBLVRenderParams->uViewportW;
+      unk_50B9D4[v55] = pBLVRenderParams->uViewportW;
+    }
+    if ( v85 )
+    {
+      dword_50BAC8[v55] = dword_50BAD4[v57];
+      dword_50B9D8_ys[v55++] = dword_50B9E0_ys[v57 + 1];
+    }
+    ++ie;
+    thise = v85;
+  }
+  while ( ie <= v48 );
+  if ( !v55 )
+    return 0;
+  v61 = pRenderer->pRenderD3D == 0;
+  dword_50BAC8[v55] = dword_50BAC8[0];
+  dword_50B9D8_ys[v55] = dword_50B9D8_ys[0];
+  if ( v61 && v55 > 3 )
+  {
+    dword_50BAC8[v55 + 1] = dword_50BAC8[1];
+    dword_50B9D8_ys[v55 + 1] = dword_50B9D8_ys[1];
+    thisf = 2 * (dword_50B700 != 0) - 1;
+    if ( v55 > 0 )
+    {
+      v62 = 1;
+      v71 = 1;
+      do
+      {
+        v63 = v62 - 1;
+        v64 = v62 + 1;
+        v80 = v62 + 1;
+        if ( v62 - 1 >= v55 )
+          v63 -= v55;
+        if ( v62 >= v55 )
+          v62 -= v55;
+        if ( v64 >= v55 )
+          v64 -= v55;
+        if ( thisf
+           * ((dword_50B9D8_ys[v64] - dword_50B9D8_ys[v63]) * (dword_50BAC8[v62] - dword_50BAC8[v63])
+            - (dword_50B9D8_ys[v62] - dword_50B9D8_ys[v63]) * (dword_50BAC8[v64] - dword_50BAC8[v63])) < 0 )
+        {
+          v62 = v80;
+          v71 = v80;
+        }
+        else
+        {
+          v62 = v71;
+          v65 = v71;
+          if ( v71 < v55 || (v65 = v71 - v55, v71 - v55 < v55) )
+          {
+            memcpy(&dword_50B9D8_ys[v65], &dword_50B9D8_ys[v65 + 1], 4 * ((unsigned int)(4 * (v55 - v65)) >> 2));
+            memcpy(&dword_50BAC8[v65], &dword_50BAC8[v65 + 1], 4 * ((unsigned int)(4 * (v55 - v65)) >> 2));
+          }
+          --v55;
+        }
+      }
+      while ( v62 - 1 < v55 );
+    }
+    dword_50BAC8[v55] = dword_50BAC8[0];
+    dword_50B9D8_ys[v55] = dword_50B9D8_ys[0];
+  }
+  return v55;
+}
+
+
+//----- (00424579) --------------------------------------------------------
+int __fastcall sub_424579(int uFaceID, stru320 *a2)
+{
+  __debugbreak();
+  return 0;
+  /*BLVFace *v2; // eax@1
+  Vec3_short_ *v3; // ebx@1
+  Vec3_short_ *v4; // esi@1
+  unsigned int v5; // esi@3
+  int v7; // ST1C_4@5
+  int v8; // ST1C_4@5
+  int v9; // ST1C_4@5
+  int v10; // ST1C_4@5
+  int v11; // esi@5
+  int v12; // ST1C_4@5
+  unsigned int v15; // ecx@8
+  unsigned int v19; // ecx@13
+  signed int v20; // ecx@16
+  signed int result; // eax@20
+  signed int v24; // edx@22
+  unsigned int v25; // [sp+Ch] [bp-1Ch]@3
+  float v26; // [sp+14h] [bp-14h]@3
+  float v27; // [sp+1Ch] [bp-Ch]@3
+  float v28; // [sp+20h] [bp-8h]@3
+  signed int v29; // [sp+24h] [bp-4h]@3
+
+  v2 = &pIndoor->pFaces[uFaceID];
+  v3 = pIndoor->pVertices;
+  v4 = &pIndoor->pVertices[*v2->pVertexIDs];
+  if ( v2->pFacePlane_old.vNormal.x * ((signed __int16)*(int *)&v4->x - pBLVRenderParams->vPartyPos.x)
+     + v2->pFacePlane_old.vNormal.y * ((signed __int16)(*(int *)&v4->x >> 16) - pBLVRenderParams->vPartyPos.y)
+     + v2->pFacePlane_old.vNormal.z * (v4->z - pBLVRenderParams->vPartyPos.z) < 0 )
+  {
+    dword_50B700 = 1;
+  }
+  else
+  {
+    dword_50B700 = 0;
+    if ( !(v2->uAttributes & 1) )
+      return 0;
+  }
+  v29 = 0;
+  v5 = v2->uNumVertices;
+  __asm { fld     pBLVRenderParams->fCosineY }
+  v28 = pBLVRenderParams->fSineY;
+  v26 = pBLVRenderParams->fCosineNegX;
+  v27 = pBLVRenderParams->fSineNegX;
+  v25 = v5;
+  if ( (signed int)v5 > 0 )
+  {
+    _ECX = (char *)&array_50AC10[0].vWorldPosition.z;
+    do
+    {
+      v7 = v3[v2->pVertexIDs[v29]].x;
+      __asm
+      {
+        fild    [ebp+var_10]
+        fstp    dword ptr [ecx-8]
+      }
+      v8 = v3[v2->pVertexIDs[v29]].y;
+      __asm
+      {
+        fild    [ebp+var_10]
+        fstp    dword ptr [ecx-4]
+      }
+      v9 = v3[v2->pVertexIDs[v29]].z;
+      __asm
+      {
+        fild    [ebp+var_10]
+        fstp    dword ptr [ecx]
+      }
+      _ECX += 48;
+      v10 = a2->pDeltaUV[0] + v2->pVertexUIDs[v29];
+      __asm
+      {
+        fild    [ebp+var_10]
+        fstp    dword ptr [ecx-14h]
+      }
+      v11 = a2->pDeltaUV[1] + v2->pVertexVIDs[v29++];
+      v12 = v11;
+      v5 = v25;
+      __asm
+      {
+        fild    [ebp+var_10]
+        fstp    dword ptr [ecx-10h]
+      }
+    }
+    while ( v29 < (signed int)v25 );
+  }
+  _EDX = (char *)&array_50AC10[0].vWorldViewPosition;
+  if ( pBLVRenderParams->sPartyRotX )
+  {
+    if ( (signed int)v5 > 0 )
+    {
+      __asm
+      {
+        fild    pBLVRenderParams->vPartyPos.x
+        fild    pBLVRenderParams->vPartyPos.y
+        fild    pBLVRenderParams->vPartyPos.z
+      }
+      _EAX = (char *)&array_50AC10[0].vWorldPosition.z;
+      v15 = v5;
+      do
+      {
+        __asm
+        {
+          fld     dword ptr [eax-8]
+          fsub    st, st(3)
+          fld     dword ptr [eax-4]
+          fsub    st, st(3)
+          fld     st(1)
+          fmul    st, st(6)
+          fld     st(1)
+          fmul    [ebp+var_8]
+          fsubp   st(1), st
+          fstp    [ebp+var_4]
+          fld     dword ptr [eax]
+          fsub    st, st(3)
+        }
+        _EAX += 48;
+        --v15;
+        __asm
+        {
+          fstp    [ebp+var_10]
+          fld     [ebp+var_4]
+          fmul    [ebp+var_14]
+          fld     [ebp+var_10]
+          fmul    [ebp+var_C]
+          fsubp   st(1), st
+          fstp    dword ptr [eax-2Ch]
+          fld     st(1)
+          fmul    [ebp+var_8]
+          fld     st(1)
+          fmul    st, st(7)
+          faddp   st(1), st
+          fstp    dword ptr [eax-28h]
+          fstp    st
+          fstp    st
+          fld     [ebp+var_4]
+          fmul    [ebp+var_C]
+          fld     [ebp+var_10]
+          fmul    [ebp+var_14]
+          faddp   st(1), st
+          fstp    dword ptr [eax-24h]
+        }
+      }
+      while ( v15 );
+LABEL_15:
+      __asm
+      {
+        fstp    st
+        fstp    st
+        fstp    st
+      }
+      goto LABEL_16;
+    }
+  }
+  else
+  {
+    if ( (signed int)v5 > 0 )
+    {
+      __asm
+      {
+        fild    pBLVRenderParams->vPartyPos.x
+        fild    pBLVRenderParams->vPartyPos.y
+        fild    pBLVRenderParams->vPartyPos.z
+      }
+      _EAX = (char *)&array_50AC10[0].vWorldViewPosition;
+      v19 = v5;
+      do
+      {
+        __asm
+        {
+          fld     dword ptr [eax-0Ch]
+          fsub    st, st(3)
+          fld     dword ptr [eax-8]
+          fsub    st, st(3)
+          fld     st(1)
+          fmul    st, st(6)
+          fld     st(1)
+          fmul    [ebp+var_8]
+          fsubp   st(1), st
+          fstp    dword ptr [eax]
+          fld     st(1)
+          fmul    [ebp+var_8]
+          fld     st(1)
+          fmul    st, st(7)
+        }
+        _EAX += 48;
+        --v19;
+        __asm
+        {
+          faddp   st(1), st
+          fstp    dword ptr [eax-2Ch]
+          fstp    st
+          fstp    st
+          fld     dword ptr [eax-34h]
+          fsub    st, st(1)
+          fstp    dword ptr [eax-28h]
+        }
+      }
+      while ( v19 );
+      goto LABEL_15;
+    }
+  }
+LABEL_16:
+  v20 = 0;
+  __asm { fstp    st }
+  if ( (signed int)v5 <= 0 )
+    return 0;
+  do
+  {
+    __asm
+    {
+      fld     dword ptr [edx]
+      fcomp   ds:flt_4D8524
+      fnstsw  ax
+    }
+    if ( !(HIBYTE(_AX) & 1) )
+      break;
+    ++v20;
+    _EDX += 48;
+  }
+  while ( v20 < (signed int)v5 );
+  if ( v20 >= (signed int)v5 )
+    return 0;
+  result = sr_424CD7(v5);
+  if ( result > 0 )
+  {
+    __asm { fild    pBLVRenderParams->field_40 }
+    _ECX = (char *)&array_507D30[0].vWorldViewPosition;
+    v24 = result;
+    __asm
+    {
+      fmul    ds:flt_4D84A4
+      fild    pBLVRenderParams->uViewportCenterX
+      fild    pBLVRenderParams->uViewportCenterY
+    }
+    do
+    {
+      __asm
+      {
+        fld1
+        fdiv    dword ptr [ecx]
+      }
+      _ECX += 48;
+      --v24;
+      __asm
+      {
+        fld     st
+        fmul    dword ptr [ecx-2Ch]
+        fmul    st, st(4)
+        fsubr   st, st(3)
+        fstp    dword ptr [ecx-24h]
+        fmul    dword ptr [ecx-28h]
+        fmul    st, st(3)
+        fsubr   st, st(1)
+        fstp    dword ptr [ecx-20h]
+      }
+    }
+    while ( v24 );
+    __asm
+    {
+      fstp    st
+      fstp    st
+      fstp    st
+    }
+  }
+  memcpy(&array_507D30[result], array_507D30, sizeof(array_507D30[result]));
+  return result;*/
+}
+
+
+//----- (00424829) --------------------------------------------------------
+bool sub_424829(int a1, BspRenderer_stru2 *a2, BspRenderer_stru2 *a3, int a4)
+{
+  int v4; // edi@1
+  BspRenderer_stru2 *v5; // ebx@1
+  int v6; // eax@3
+  int v7; // esi@5
+  int v8; // edx@5
+  int v9; // ecx@6
+  int v10; // eax@12
+  int v11; // edi@13
+  int v12; // edx@18
+  int v13; // eax@22
+  int v14; // edi@28
+  int v15; // ecx@29
+  int v16; // edi@30
+  int v17; // edx@35
+  int v18; // eax@39
+  int v19; // eax@44
+  int v20; // ecx@44
+  int v21; // edi@45
+  int v22; // edi@46
+  __int16 *v23; // ecx@47
+  int v24; // edx@48
+  int v25; // eax@50
+  int v26; // eax@55
+  signed int v27; // edi@55
+  int v28; // edx@56
+  int v29; // edx@57
+  int v30; // eax@59
+  int v31; // eax@64
+  signed int v32; // edi@64
+  int v33; // edx@65
+  __int16 *v34; // eax@66
+  __int16 v35; // dx@66
+  __int16 v36; // dx@67
+  __int16 v37; // di@67
+  __int16 v38; // dx@67
+  BspRenderer_stru2 *v39; // ecx@69
+  int v40; // edx@69
+  int v41; // edi@70
+  __int16 *v42; // eax@76
+  __int16 *v43; // eax@81
+  __int16 *v45; // eax@87
+  int v46; // edx@87
+  __int16 v47; // cx@88
+  int v48; // eax@93
+  int v49; // esi@93
+  __int16 *v50; // ecx@94
+  int v51; // eax@95
+  int v52; // eax@97
+  int v53; // [sp+Ch] [bp-34h]@44
+  int v54; // [sp+10h] [bp-30h]@0
+  int v55; // [sp+14h] [bp-2Ch]@12
+  __int16 *v56; // [sp+14h] [bp-2Ch]@47
+  __int16 *v57; // [sp+14h] [bp-2Ch]@76
+  __int16 *v58; // [sp+14h] [bp-2Ch]@81
+  __int16 *v59; // [sp+14h] [bp-2Ch]@87
+  BspRenderer_stru2 *v60; // [sp+18h] [bp-28h]@1
+  int v61; // [sp+1Ch] [bp-24h]@29
+  int v62; // [sp+20h] [bp-20h]@0
+  signed int v63; // [sp+24h] [bp-1Ch]@3
+  signed int v64; // [sp+28h] [bp-18h]@3
+  int v65; // [sp+2Ch] [bp-14h]@5
+  int v66; // [sp+2Ch] [bp-14h]@39
+  int v67; // [sp+30h] [bp-10h]@22
+  int v68; // [sp+34h] [bp-Ch]@12
+  int v69; // [sp+34h] [bp-Ch]@29
+  int v70; // [sp+34h] [bp-Ch]@46
+  int v71; // [sp+34h] [bp-Ch]@75
+  int v72; // [sp+34h] [bp-Ch]@80
+  int v73; // [sp+38h] [bp-8h]@11
+  int v74; // [sp+3Ch] [bp-4h]@1
+  int a3a; // [sp+48h] [bp+8h]@76
+  int a3b; // [sp+48h] [bp+8h]@87
+
+  v4 = a1;
+  v5 = a2;
+  v74 = a1;
+  v60 = a2;
+  if ( !a1
+    || (!dword_50B700 ? (v64 = -1, v6 = 1, v63 = 1) : (v6 = 1, v63 = -1, v64 = 1),
+        v7 = dword_50B9D8_ys[0],
+        v65 = 0,
+        v8 = dword_50B9D8_ys[0],
+        a1 <= v6) )
+    return 0;
+  do
+  {
+    v9 = dword_50B9D8_ys[v6];
+    if ( v9 >= v7 )
+    {
+      if ( v9 > v8 )
+        v8 = dword_50B9D8_ys[v6];
+    }
+    else
+    {
+      v65 = v6;
+      v7 = dword_50B9D8_ys[v6];
+    }
+    ++v6;
+  }
+  while ( v6 < v4 );
+  v73 = v8;
+  if ( v8 == v7 )
+    return 0;
+  v10 = v65;
+  v68 = 0;
+  v5->_viewport_space_y = v7;
+  v5->_viewport_space_w = v8;
+  v55 = v65;
+  if ( v4 > 0 )
+  {
+    v11 = v65;
+    do
+    {
+      v10 += v64;
+      if ( v10 < v74 )
+      {
+        if ( v10 < 0 )
+          v10 += v74;
+      }
+      else
+      {
+        v10 -= v74;
+      }
+      v12 = dword_50B9D8_ys[v10];
+      if ( v12 <= dword_50B9D8_ys[v11] )
+      {
+        v55 = v10;
+        v11 = v10;
+      }
+      if ( v12 == v73 )
+        break;
+      ++v68;
+    }
+    while ( v68 < v74 );
+  }
+  v13 = v55 + v64;
+  v67 = v55 + v64;
+  if ( v55 + v64 < v74 )
+  {
+    if ( v13 >= 0 )
+      goto LABEL_27;
+    v13 += v74;
+  }
+  else
+  {
+    v13 -= v74;
+  }
+  v67 = v13;
+LABEL_27:
+  if ( dword_50B9D8_ys[v13] != dword_50B9D8_ys[v55] )
+  {
+    v14 = dword_50BAC8[v55];
+    v62 = v14 << 16;
+    v54 = ((dword_50BAC8[v13] - v14) << 16) / (dword_50B9D8_ys[v13] - dword_50B9D8_ys[v55]);
+    v5->array_18[v7] = LOWORD(dword_50BAC8[v55]);
+  }
+  v15 = v65;
+  v69 = 0;
+  v61 = v65;
+  if ( v74 > 0 )
+  {
+    v16 = v65;
+    do
+    {
+      v15 += v63;
+      if ( v15 < v74 )
+      {
+        if ( v15 < 0 )
+          v15 += v74;
+      }
+      else
+      {
+        v15 -= v74;
+      }
+      v17 = dword_50B9D8_ys[v15];
+      if ( v17 <= dword_50B9D8_ys[v16] )
+      {
+        v61 = v15;
+        v16 = v15;
+      }
+      if ( v17 == v73 )
+        break;
+      ++v69;
+    }
+    while ( v69 < v74 );
+  }
+  v18 = v63 + v61;
+  v66 = v63 + v61;
+  if ( v63 + v61 < v74 )
+  {
+    if ( v18 >= 0 )
+      goto LABEL_44;
+    v18 += v74;
+  }
+  else
+  {
+    v18 -= v74;
+  }
+  v66 = v18;
+LABEL_44:
+  v19 = v18;
+  v20 = v61;
+  v53 = dword_50B9D8_ys[v19] - dword_50B9D8_ys[v61];
+  if ( dword_50B9D8_ys[v19] != dword_50B9D8_ys[v61] )
+  {
+    v21 = dword_50BAC8[v20];
+    v5 = v60;
+    v61 = v21 << 16;
+    v53 = ((dword_50BAC8[v19] - v21) << 16) / v53;
+    v60->array_3D8[v73] = LOWORD(dword_50BAC8[v20]);
+  }
+  v22 = v7;
+  v70 = v7;
+  if ( v7 <= v73 )
+  {
+    v56 = &v5->array_3D8[v7];
+    v23 = &v5->array_18[v7];
+    do
+    {
+      v24 = v67;
+      if ( v22 < dword_50B9D8_ys[v67] || v22 == v73 )
+        goto LABEL_57;
+      v25 = v64 + v67;
+      v67 = v25;
+      if ( v25 < v74 )
+      {
+        if ( v25 >= 0 )
+          goto LABEL_55;
+        v25 += v74;
+      }
+      else
+      {
+        v25 -= v74;
+      }
+      v67 = v25;
+LABEL_55:
+      v26 = v25;
+      v27 = dword_50B9D8_ys[v26] - dword_50B9D8_ys[v24];
+      if ( dword_50B9D8_ys[v26] - dword_50B9D8_ys[v24] > 0 )
+      {
+        v28 = dword_50BAC8[v24];
+        v54 = ((dword_50BAC8[v26] - v28) << 16) / v27;
+        v62 = v28 << 16;
+      }
+LABEL_57:
+      v29 = v66;
+      if ( v70 >= dword_50B9D8_ys[v66] && v70 != v73 )
+      {
+        v30 = v63 + v66;
+        v66 += v63;
+        if ( v66 >= v74 )
+        {
+          v30 -= v74;
+          goto LABEL_63;
+        }
+        if ( v30 < 0 )
+        {
+          v30 += v74;
+LABEL_63:
+          v66 = v30;
+        }
+        v31 = v30;
+        v32 = dword_50B9D8_ys[v31] - dword_50B9D8_ys[v29];
+        if ( dword_50B9D8_ys[v31] - dword_50B9D8_ys[v29] > 0 )
+        {
+          v33 = dword_50BAC8[v29];
+          v53 = ((dword_50BAC8[v31] - v33) << 16) / v32;
+          v61 = v33 << 16;
+        }
+      }
+      *(__int16 *)((char *)v56 + (int)(char *)v5->array_18 - (char *)v5->array_3D8) = HIWORD(v62);
+      *v56 = HIWORD(v61);
+      v34 = v23 + 480;
+      v35 = v23[480];
+      if ( *v23 > v35 )
+      {
+        v36 = *v23 ^ v35;
+        v37 = *v34;
+        *v23 = v36;
+        v38 = v37 ^ v36;
+        *v23 ^= v38;
+        *v34 = v38;
+      }
+      ++v56;
+      v62 += v54;
+      v22 = v70 + 1;
+      v61 += v53;
+      ++v23;
+      ++v70;
+    }
+    while ( v70 <= v73 );
+  }
+  v39 = a3;
+  v40 = v73;
+  if ( v73 < a3->_viewport_space_y || (v41 = a3->_viewport_space_w, v7 > v41) )
+    return 0;
+  if ( v7 < a3->_viewport_space_y )
+    v7 = a3->_viewport_space_y;
+  if ( v73 > v41 )
+  {
+    v40 = a3->_viewport_space_w;
+    v73 = a3->_viewport_space_w;
+  }
+  v71 = v7;
+  if ( v7 <= v40 )
+  {
+    a3a = (char *)v5 - (char *)a3;
+    v57 = &v5->array_18[v7];
+    v42 = &v39->array_3D8[v7];
+    do
+    {
+      if ( *(__int16 *)((char *)v42 + a3a) >= *(v42 - 480) && *v57 <= *v42 )
+        break;
+      ++v57;
+      ++v7;
+      ++v71;
+      ++v42;
+    }
+    while ( v71 <= v40 );
+  }
+  v72 = v40;
+  if ( v40 < v7 )
+    return 0;
+  v58 = &v5->array_18[v40];
+  v43 = &v39->array_3D8[v40];
+  do
+  {
+    if ( *(__int16 *)((char *)v43 + (int)(char *)v5 - (char *)v39) >= *(v43 - 480) && *v58 <= *v43 )
+      break;
+    --v58;
+    --v40;
+    --v72;
+    --v43;
+    v73 = v40;
+  }
+  while ( v72 >= v7 );
+  if ( v7 >= v40 )
+    return 0;
+  a3b = (char *)v39 - (char *)v5;
+  v59 = &v39->array_3D8[v7];
+  v45 = &v5->array_18[v7];
+  v46 = v73 - v7 + 1;
+  do
+  {
+    v47 = *(__int16 *)((char *)v45 + a3b);
+    if ( *v45 < v47 )
+      *v45 = v47;
+    if ( v45[480] > *v59 )
+      v45[480] = *v59;
+    ++v59;
+    ++v45;
+    --v46;
+  }
+  while ( v46 );
+  v5->_viewport_space_y = v7;
+  v5->_viewport_space_w = v73;
+  v5->field_8 = v5->array_18[v7];
+  v48 = v5->array_3D8[v7];
+  v5->field_10 = v7;
+  v5->field_14 = v7;
+  v49 = v7 + 1;
+  v5->field_C = v48;
+  if ( v49 <= v73 )
+  {
+    v50 = &v5->array_3D8[v49];
+    do
+    {
+      v51 = *(v50 - 480);
+      if ( v51 < v5->field_8 )
+      {
+        v5->field_8 = v51;
+        v5->field_10 = v49;
+      }
+      v52 = *v50;
+      if ( v52 > v5->field_C )
+      {
+        v5->field_C = v52;
+        v5->field_14 = v49;
+      }
+      ++v49;
+      ++v50;
+    }
+    while ( v49 <= v73 );
+  }
+  return 1;
+}
+// 50B700: using guessed type int dword_50B700;
+
+//----- (00424CD7) --------------------------------------------------------
+signed int __fastcall sr_424CD7(unsigned int uVertexID)
+{
+  unsigned int v1; // edx@1
+  signed int v2; // edi@1
+  char *v3; // esi@4
+  char *v4; // ecx@4
+  unsigned int v5; // eax@4
+  char *v6; // edx@4
+  double v7; // st6@10
+  double v8; // st5@10
+  double v9; // st6@11
+  unsigned __int8 v10; // c2@15
+  unsigned __int8 v11; // c3@15
+  RenderVertexSoft *v12; // edi@22
+  char *v13; // eax@22
+  double v14; // st6@22
+  signed int result; // eax@24
+  unsigned int v16; // [sp+8h] [bp-28h]@4
+  bool v17; // [sp+Ch] [bp-24h]@6
+  char *v18; // [sp+10h] [bp-20h]@4
+  char *v19; // [sp+14h] [bp-1Ch]@4
+  signed int v20; // [sp+18h] [bp-18h]@1
+  RenderVertexSoft *v21; // [sp+1Ch] [bp-14h]@4
+  char *v22; // [sp+20h] [bp-10h]@4
+  char *v23; // [sp+24h] [bp-Ch]@4
+  char *v24; // [sp+28h] [bp-8h]@4
+  char *v25; // [sp+2Ch] [bp-4h]@4
+
+  v1 = uVertexID;
+  memcpy(&array_50AC10[uVertexID], array_50AC10, sizeof(array_50AC10[uVertexID]));
+  v2 = 0;
+  v20 = 0;
+  if ( array_50AC10[0].vWorldViewPosition.x >= 8.0 )
+    v2 = 1;
+  if ( (signed int)(uVertexID + 1) <= 1 )
+    return 0;
+  v3 = (char *)&array_507D30[0].vWorldViewPosition.z;
+  v4 = (char *)&array_507D30[0].vWorldViewPosition.y;
+  v5 = v1;
+  v23 = (char *)&array_507D30[0].flt_20;
+  v21 = array_507D30;
+  v18 = (char *)&array_507D30[0].vWorldViewPosition.z;
+  v19 = (char *)&array_507D30[0].vWorldViewPosition.y;
+  v22 = (char *)&array_507D30[0].vWorldViewPosition;
+  v24 = (char *)&array_507D30[0].v;
+  v25 = (char *)&array_507D30[0].u;
+  v6 = (char *)&array_50AC10[0].v;
+  v16 = v5;
+  do
+  {
+    v17 = *((float *)v6 + 5) >= 8.0;
+    if ( v2 != v17 )
+    {
+      if ( v17 )
+      {
+        v7 = (8.0 - *((float *)v6 - 7)) / (*((float *)v6 + 5) - *((float *)v6 - 7));
+        *(float *)v4 = (*((float *)v6 + 6) - *((float *)v6 - 6)) * v7 + *((float *)v6 - 6);
+        *(float *)v3 = (*((float *)v6 + 7) - *((float *)v6 - 5)) * v7 + *((float *)v6 - 5);
+        *(float *)v25 = (*((float *)v6 + 11) - *((float *)v6 - 1)) * v7 + *((float *)v6 - 1);
+        v8 = (*((float *)v6 + 12) - *(float *)v6) * v7 + *(float *)v6;
+      }
+      else
+      {
+        v9 = (8.0 - *((float *)v6 + 5)) / (*((float *)v6 - 7) - *((float *)v6 + 5));
+        *(float *)v4 = (*((float *)v6 - 6) - *((float *)v6 + 6)) * v9 + *((float *)v6 + 6);
+        *(float *)v3 = (*((float *)v6 - 5) - *((float *)v6 + 7)) * v9 + *((float *)v6 + 7);
+        *(float *)v25 = (*((float *)v6 - 1) - *((float *)v6 + 11)) * v9 + *((float *)v6 + 11);
+        v8 = (*(float *)v6 - *((float *)v6 + 12)) * v9 + *((float *)v6 + 12);
+      }
+      *(float *)v24 = v8;
+      *(float *)v22 = 8.0;
+      *(int *)v23 = 0x3E000000u;
+      if ( v2 )
+      {
+        if ( 8.0 == *((float *)v6 - 7) && *(float *)v4 == *((float *)v6 - 6) )
+        {
+          v10 = 0;
+          v11 = *(float *)v3 == *((float *)v6 - 5);
+          goto LABEL_19;
+        }
+      }
+      else
+      {
+        if ( 8.0 == *((float *)v6 + 5) && *(float *)v4 == *((float *)v6 + 6) )
+        {
+          v10 = 0;
+          v11 = *(float *)v3 == *((float *)v6 + 7);
+LABEL_19:
+          if ( v11 | v10 )
+            goto LABEL_21;
+          goto LABEL_20;
+        }
+      }
+LABEL_20:
+      ++v21;
+      v22 += 48;
+      v24 += 48;
+      v25 += 48;
+      v4 += 48;
+      v3 += 48;
+      ++v20;
+      v23 += 48;
+      v19 = v4;
+      v18 = v3;
+    }
+LABEL_21:
+    if ( v17 )
+    {
+      v12 = v21;
+      v13 = v23;
+      v19 += 48;
+      v18 += 48;
+      v14 = 1.0 / (*((float *)v6 + 5) + 0.0000001);
+      ++v20;
+      v25 += 48;
+      v24 += 48;
+      v22 += 48;
+      ++v21;
+      v23 += 48;
+      memcpy(v12, v6 + 8, 0x30u);
+      v4 = v19;
+      v3 = v18;
+      *(float *)v13 = v14;
+    }
+    v2 = v17;
+    v6 += 48;
+    --v16;
+  }
+  while ( v16 );
+  result = v20;
+  if ( v20 < 3 )
+    return 0;
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mm7_2.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,17436 @@
+#include <io.h>
+#include <direct.h>
+#include <assert.h>
+
+#include "MapInfo.h"
+#include "Game.h"
+#include "GUIWindow.h"
+#include "GUIButton.h"
+#include "GUIFont.h"
+#include "Party.h"
+#include "AudioPlayer.h"
+#include "Outdoor.h"
+#include "IndoorCamera.h"
+#include "Overlays.h"
+#include "Monsters.h"
+#include "Arcomage.h"
+#include "LOD.h"
+#include "Actor.h"
+#include "Allocator.h"
+#include "Events.h"
+#include "Viewport.h"
+#include "FrameTableInc.h"
+#include "Math.h"
+#include "LayingItem.h"
+#include "ObjectList.h"
+#include "Chest.h"
+#include "PaletteManager.h"
+#include "DecorationList.h"
+#include "SaveLoad.h"
+#include "stru123.h"
+#include "stru287.h"
+#include "Time.h"
+#include "IconFrameTable.h"
+#include "GUIProgressBar.h"
+#include "stru157.h"
+#include "Bink_Smacker.h"
+#include "TileFrameTable.h"
+#include "PlayerFrameTable.h"
+#include "Awards.h"
+#include "Autonotes.h"
+#include "stru160.h"
+#include "stru279.h"
+#include "TurnEngine.h"
+#include "FactionTable.h"
+#include "StorylineTextTable.h"
+#include "Random.h"
+#include "stru277.h"
+#include "stru298.h"
+#include "stru12.h"
+#include "stru351.h"
+#include "Events2D.h"
+#include "stru159.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+//----- (004B4F4F) --------------------------------------------------------
+char *__cdecl sub_4B4F4F()
+{
+  const char *v0; // esi@1
+  const char *v1; // ST10_4@1
+  unsigned __int16 v2; // ST0C_2@1
+  int v3; // eax@1
+  GUIWindow v5; // [sp+8h] [bp-54h]@1
+
+  memcpy(&v5, ptr_507BC0, sizeof(v5));
+  v0 = pGlobalTXT_LocalizationStrings[672];
+  v1 = pGlobalTXT_LocalizationStrings[672];
+  v5.uFrameX = 483;
+  v5.uFrameWidth = 148;
+  v5.uFrameZ = 334;
+  v2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v3 = pFontArrus->CalcTextHeight(v0, &v5, 0, 0);
+  return v5.DrawTitleText(pFontArrus, 0, (310 - v3) / 2 + 18, v2, v1, 3u);
+}
+
+
+
+//----- (004B68EA) --------------------------------------------------------
+bool __fastcall sub_4B68EA(int a1)
+{
+  signed int v1; // edi@1
+  int *v2; // esi@1
+  int v3; // ecx@2
+
+  v1 = 0;
+  v2 = &dword_4F0E10[a1];
+  while ( 1 )
+  {
+    v3 = 8 * *((char *)v2 + v1);
+    if ( *(&byte_4F09B1[pParty->uDaysPlayed % 7] + v3 * 4) )
+    {
+      if ( !dword_4F09CC[v3] || (unsigned __int16)_449B57_test_bit(pParty->_award_bits, LOWORD(dword_4F09CC[v3])) )
+        break;
+    }
+    ++v1;
+    if ( v1 >= 4 )
+      return 0;
+  }
+  return 1;
+}
+
+
+
+//----- (004B7911) --------------------------------------------------------
+void __cdecl sub_4B7911()
+{
+  GUIWindow *v0; // eax@4
+  int v1; // eax@10
+  int v2; // esi@10
+  GUIFont *v3; // ST20_4@20
+  int v4; // eax@20
+  MonsterInfo *v5; // edi@21
+  unsigned int v6; // ST20_4@21
+  char *v7; // ST1C_4@21
+  unsigned int v8; // eax@21
+  int v9; // esi@21
+  char *v10; // eax@23
+  signed int v11; // ebx@24
+  signed int i; // esi@26
+  int v13; // eax@27
+  GUIWindow *v14; // ecx@28
+  __int64 v15; // qax@28
+  signed int v16; // ebx@28
+  int v17; // ebx@28
+  unsigned __int8 v18; // sf@28
+  char **v19; // edi@29
+  GUIButton *v20; // eax@30
+  GUIButton *v21; // esi@30
+  int v22; // eax@30
+  unsigned int v23; // ecx@30
+  unsigned __int16 v24; // ax@30
+  GUIWindow a1; // [sp+Ch] [bp-110h]@21
+  GUIWindow w; // [sp+60h] [bp-BCh]@21
+  GUIWindow _this; // [sp+B4h] [bp-68h]@1
+  int v28; // [sp+108h] [bp-14h]@1
+  int v29; // [sp+10Ch] [bp-10h]@28
+  int v30; // [sp+110h] [bp-Ch]@1
+  int v31; // [sp+114h] [bp-8h]@29
+  GUIFont *pOutString; // [sp+118h] [bp-4h]@21
+
+  memcpy(&_this, ptr_507BC0, sizeof(_this));
+  _this.uFrameX = 483;
+  _this.uFrameWidth = 148;
+  _this.uFrameZ = 334;
+  v28 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v30 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  sprintf(pTmpBuf, "%s: %d", pGlobalTXT_LocalizationStrings[605], pParty->uFine);
+  _this.DrawTitleText(pFontArrus, 0, 0x104u, v30, pTmpBuf, 3u);
+  if ( dword_F8B19C == 1 )
+  {
+    v11 = 1;
+    pOutString = 0;
+    pShopOptions[0] = pGlobalTXT_LocalizationStrings[604];
+    if ( pParty->uFine )
+    {
+      pShopOptions[1] = pGlobalTXT_LocalizationStrings[603];
+      v11 = 2;
+    }
+    for ( i = 0; i < v11; ++i )
+    {
+      v13 = pFontArrus->CalcTextHeight(pShopOptions[i], &_this, 0, 0);
+      pOutString = (GUIFont *)((char *)pOutString + v13);
+    }
+    v29 = (100 - (signed int)pOutString) / v11;
+    v14 = pDialogueWindow;
+    v15 = 80 - v11 * (100 - (signed int)pOutString) / v11 - (signed int)pOutString;
+    v16 = v15 - HIDWORD(v15);
+    LODWORD(v15) = pDialogueWindow->pStartingPosActiveItem;
+    HIDWORD(v15) = v15 + pDialogueWindow->pNumPresenceButton;
+    v17 = (v16 >> 1) - v29 / 2 + 158;
+    v18 = -pDialogueWindow->pNumPresenceButton < 0;
+    pOutString = (GUIFont *)pDialogueWindow->pStartingPosActiveItem;
+    if ( v18 ^ __OFSUB__((int)v15, HIDWORD(v15)) )
+    {
+      v31 = 2;
+      v19 = pShopOptions;
+      do
+      {
+        v20 = v14->GetControl((unsigned int)pOutString);
+        v21 = v20;
+        v20->uY = v29 + v17;
+        v22 = pFontArrus->CalcTextHeight(*v19, &_this, 0, 0);
+        v23 = v21->uY;
+        v21->uHeight = v22;
+        v17 = v23 + v22 - 1;
+        v21->uW = v17;
+        v24 = v30;
+        if ( pDialogueWindow->pCurrentPosActiveItem != v31 )
+          v24 = v28;
+        _this.DrawTitleText(pFontArrus, 0, v23, v24, *v19, 3u);
+        v14 = pDialogueWindow;
+        ++v31;
+        ++v19;
+        pOutString = (GUIFont *)((char *)pOutString + 1);
+      }
+      while ( (signed int)pOutString < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem );
+    }
+  }
+  else
+  {
+    if ( dword_F8B19C != 99 )
+    {
+      if ( dword_F8B19C != 100 )
+        return;
+      v0 = ptr_507BC0;
+      if ( ptr_507BC0->field_40 == 1 )
+      {
+        sprintf(pTmpBuf, "%s\n%s", pGlobalTXT_LocalizationStrings[606], pGlobalTXT_LocalizationStrings[112]);
+        _this.DrawTitleText(pFontArrus, 0, 0x92u, v30, pTmpBuf, 3u);
+        _this.DrawTitleText(pFontArrus, 0, 0xBAu, v28, (const char *)pKeyActionMap->pPressedKeysBuffer, 3u);
+        v3 = pFontArrus;
+        v4 = pFontArrus->GetLineWidth((const char *)pKeyActionMap->pPressedKeysBuffer);
+        _this.DrawFlashingInputCursor(v4 / 2 + 80, 185, v3);
+        return;
+      }
+      if ( ptr_507BC0->field_40 == 2 )
+      {
+        v1 = atoi((const char *)pKeyActionMap->pPressedKeysBuffer);
+        v2 = v1;
+        if ( v1 <= 0 )
+        {
+LABEL_8:
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+          {
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+            *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+          return;
+        }
+        if ( v1 > pParty->uNumGold )
+        {
+          HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 2);
+          v2 = pParty->uNumGold;
+        }
+        if ( v2 > pParty->uFine )
+          v2 = pParty->uFine;
+        Party::TakeGold(v2);
+        pParty->uFine -= v2;
+        if ( pParty->uFine < 0 )
+          pParty->uFine = 0;
+        if ( uActiveCharacter )
+          pPlayers[uActiveCharacter]->PlaySound(81, 0);
+        v0 = ptr_507BC0;
+      }
+      else
+      {
+        if ( ptr_507BC0->field_40 != 3 )
+          return;
+      }
+      v0->field_40 = 0;
+      goto LABEL_8;
+    }
+    v5 = &pMonsterStats->pInfos[word_F8B1A0];
+    v6 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+    v7 = v5->pName;
+    v8 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+    sprintf(pTmpBuf, &byte_4F0F98, v8, v7, v6);
+    sprintf(pTmpBuf2, dword_F8B1A4, pTmpBuf, 100 * v5->uLevel);
+    ptr_F8B1E8 = pTmpBuf2;
+    memcpy(&a1, pDialogueWindow, sizeof(a1));
+    w.uFrameWidth = 458;
+    w.uFrameZ = 457;
+    pOutString = pFontArrus;
+    v9 = pFontArrus->CalcTextHeight(pTmpBuf2, &w, 13, 0) + 7;
+    if ( 352 - v9 < 8 )
+    {
+      pOutString = pFontCreate;
+      v9 = pFontCreate->CalcTextHeight(ptr_F8B1E8, &w, 13, 0) + 7;
+    }
+
+    auto pTex = (uTextureID_Leather != -1 ? &pIcons_LOD->pTextures[uTextureID_Leather] : 0);
+    pRenderer->_4A6A68(
+      8u,
+      352 - v9,
+      pTex,
+      (pTex ? pTex->uTextureHeight : 26) - v9);
+    pRenderer->DrawTextureIndexed(8u, 347 - v9, pTexture_591428);
+    v10 = FitTextInAWindow(ptr_F8B1E8, pOutString, &w, 0xDu, 0);
+    a1.DrawText(pOutString, 13, 354 - v9, 0, v10, 0, 0, 0);
+  }
+}
+// F8B19C: using guessed type int dword_F8B19C;
+// F8B1A0: using guessed type __int16 word_F8B1A0;
+
+//----- (004B7D7E) --------------------------------------------------------
+void __cdecl _4B7D7E_bank()
+{
+  GUIWindow *v0; // eax@4
+  int v1; // ecx@5
+  int v2; // eax@6
+  unsigned int v3; // esi@6
+  GUIFont *v4; // ST10_4@12
+  int v5; // eax@12
+  int v6; // eax@19
+  unsigned int v7; // esi@19
+  unsigned __int16 v8; // ax@27
+  unsigned __int16 v9; // ax@29
+  char *v10; // [sp-8h] [bp-70h]@11
+  char *v11; // [sp-4h] [bp-6Ch]@11
+  GUIWindow _this; // [sp+Ch] [bp-5Ch]@1
+  __int16 v13[2]; // [sp+60h] [bp-8h]@1
+  __int16 v14[2]; // [sp+64h] [bp-4h]@1
+
+  memcpy(&_this, ptr_507BC0, sizeof(_this));
+  _this.uFrameX = 483;
+  _this.uFrameWidth = 148;
+  _this.uFrameZ = 334;
+  *(int *)v13 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  *(int *)v14 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  sprintf(pTmpBuf, "%s: %d", pGlobalTXT_LocalizationStrings[25], pParty->uNumGoldInBank);
+  _this.DrawTitleText(pFontArrus, 0, 0xDCu, v14[0], pTmpBuf, 3u);
+  if ( dword_F8B19C != 1 )
+  {
+    if ( dword_F8B19C == 7 )
+    {
+      v0 = ptr_507BC0;
+      if ( ptr_507BC0->field_40 != 1 )
+      {
+        v1 = ptr_507BC0->field_40 - 2;
+        if ( ptr_507BC0->field_40 == 2 )
+        {
+          v6 = atoi((const char *)pKeyActionMap->pPressedKeysBuffer);
+          v7 = v6;
+          if ( !v6 )
+          {
+LABEL_17:
+            if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+            {
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+              *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+              ++pMessageQueue_50CBD0->uNumMessages;
+            }
+            return;
+          }
+          if ( v6 > pParty->uNumGold )
+          {
+            HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 2);
+            v7 = pParty->uNumGold;
+          }
+          if ( v7 )
+          {
+            Party::TakeGold(v7);
+            pParty->uNumGoldInBank += v7;
+            if ( uActiveCharacter )
+              pPlayers[uActiveCharacter]->PlaySound(81, 0);
+          }
+          v0 = ptr_507BC0;
+LABEL_16:
+          v0->field_40 = 0;
+          goto LABEL_17;
+        }
+LABEL_15:
+        if ( v1 != 1 )
+          return;
+        goto LABEL_16;
+      }
+      v11 = pGlobalTXT_LocalizationStrings[112];
+      v10 = pGlobalTXT_LocalizationStrings[60];
+    }
+    else
+    {
+      if ( dword_F8B19C != 8 )
+        return;
+      v0 = ptr_507BC0;
+      if ( ptr_507BC0->field_40 != 1 )
+      {
+        v1 = ptr_507BC0->field_40 - 2;
+        if ( ptr_507BC0->field_40 == 2 )
+        {
+          ptr_507BC0->field_40 = 0;
+          v2 = atoi((const char *)pKeyActionMap->pPressedKeysBuffer);
+          v3 = v2;
+          if ( v2 )
+          {
+            if ( v2 > pParty->uNumGoldInBank )
+            {
+              HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 2);
+              v3 = pParty->uNumGoldInBank;
+            }
+            if ( v3 )
+            {
+              Party::SetGold(pParty->uNumGold + v3);
+              pParty->uNumGoldInBank -= v3;
+            }
+          }
+          goto LABEL_17;
+        }
+        goto LABEL_15;
+      }
+      v11 = pGlobalTXT_LocalizationStrings[112];
+      v10 = pGlobalTXT_LocalizationStrings[244];
+    }
+    sprintf(pTmpBuf, "%s\n%s", v10, v11);
+    _this.DrawTitleText(pFontArrus, 0, 0x92u, v14[0], pTmpBuf, 3u);
+    _this.DrawTitleText(pFontArrus, 0, 0xBAu, v13[0], (const char *)pKeyActionMap->pPressedKeysBuffer, 3u);
+    v4 = pFontArrus;
+    v5 = pFontArrus->GetLineWidth((const char *)pKeyActionMap->pPressedKeysBuffer);
+    _this.DrawFlashingInputCursor(v5 / 2 + 80, 185, v4);
+    return;
+  }
+  v8 = v14[0];
+  if ( pDialogueWindow->pCurrentPosActiveItem != 2 )
+    v8 = v13[0];
+  _this.DrawTitleText(pFontArrus, 0, 0x92u, v8, pGlobalTXT_LocalizationStrings[60], 3u);
+  v9 = v14[0];
+  if ( pDialogueWindow->pCurrentPosActiveItem != 3 )
+    v9 = v13[0];
+  _this.DrawTitleText(pFontArrus, 0, 0xB0u, v9, pGlobalTXT_LocalizationStrings[244], 3u);
+}
+// F8B19C: using guessed type int dword_F8B19C;
+
+//----- (004B8285) --------------------------------------------------------
+void __cdecl sub_4B8285_prolly_draw_arcomage_result()
+{
+  GUIWindow *v0; // ebx@1
+  Player *v1; // edi@1
+  double v2; // st7@1
+  signed int v3; // ebx@1
+  int v4; // ecx@1
+  int v5; // esi@3
+  signed int v6; // edi@5
+  int v7; // ecx@5
+  GUIWindow *v8; // edi@16
+  signed int v9; // esi@16
+  unsigned int v10; // esi@18
+  int v11; // eax@18
+  unsigned int v12; // eax@19
+  int v13; // eax@21
+  int v14; // ecx@26
+  GUIButton *v15; // eax@28
+  GUIButton *v16; // esi@28
+  int v17; // eax@28
+  char *v18; // eax@30
+  int v19; // eax@30
+  unsigned int v20; // ecx@30
+  int v21; // edx@30
+  int v22; // eax@30
+  unsigned __int16 v23; // ax@30
+  int v24; // eax@34
+  int v25; // eax@34
+  char *v26; // esi@36
+  int v27; // edi@46
+  unsigned int v28; // eax@53
+  unsigned int v29; // eax@55
+  unsigned int v30; // eax@57
+  signed int v31; // eax@59
+  unsigned int v32; // eax@61
+  GUIWindow *v33; // edi@64
+  int v34; // eax@64
+  int v35; // ecx@64
+  int v36; // esi@64
+  char v37; // sf@64
+  GUIButton *v38; // eax@65
+  int v39; // edx@69
+  int v40; // ecx@69
+  int v41; // ecx@69
+  int v42; // ecx@70
+  unsigned int v43; // edx@70
+  int v44; // edx@71
+  int v45; // ecx@71
+  int v46; // ecx@72
+  int v47; // eax@74
+  signed int v48; // edi@77
+  signed int i; // esi@79
+  int v50; // eax@80
+  GUIWindow *v51; // ecx@81
+  _QWORD v52; // qax@81
+  signed int v53; // edi@81
+  int v54; // edi@81
+  GUIButton *v55; // esi@83
+  const char **v56; // eax@83
+  int v57; // eax@83
+  unsigned int v58; // ecx@83
+  Player *v59; // edx@83
+  unsigned __int16 v60; // ax@83
+  int v61; // eax@99
+  int v62; // edi@99
+  char *v63; // eax@99
+  GUIFont *v64; // edx@99
+  GUIFont *v65; // edi@100
+  unsigned int v66; // [sp-10h] [bp-284h]@75
+  unsigned __int16 v67; // [sp-Ch] [bp-280h]@75
+  int v68; // [sp-Ch] [bp-280h]@99
+  char *v69; // [sp-8h] [bp-27Ch]@75
+  int v70; // [sp-8h] [bp-27Ch]@99
+  unsigned int v71; // [sp-4h] [bp-278h]@75
+  const char *v72; // [sp-4h] [bp-278h]@93
+  unsigned int v73; // [sp-4h] [bp-278h]@99
+  char Dest; // [sp+Ch] [bp-268h]@55
+  char v75; // [sp+70h] [bp-204h]@59
+  char a1; // [sp+D4h] [bp-1A0h]@57
+  char v77; // [sp+138h] [bp-13Ch]@59
+  GUIWindow v78; // [sp+19Ch] [bp-D8h]@99
+  GUIWindow v79; // [sp+1F0h] [bp-84h]@1
+  char *Str[2]; // [sp+244h] [bp-30h]@30
+  unsigned int v81; // [sp+24Ch] [bp-28h]@1
+  unsigned __int8 v82; // [sp+253h] [bp-21h]@59
+  int v83; // [sp+254h] [bp-20h]@1
+  __int16 v84[2]; // [sp+258h] [bp-1Ch]@1
+  Player *v85; // [sp+25Ch] [bp-18h]@1
+  int v86; // [sp+260h] [bp-14h]@18
+  unsigned __int8 v87; // [sp+266h] [bp-Eh]@59
+  unsigned __int8 v88; // [sp+267h] [bp-Dh]@57
+  int v89; // [sp+268h] [bp-Ch]@1
+  unsigned __int8 v90; // [sp+26Fh] [bp-5h]@55
+  GUIFont *pOutString; // [sp+270h] [bp-4h]@3
+
+  v0 = ptr_507BC0;
+  memcpy(&v79, ptr_507BC0, sizeof(v79));
+  v85 = pPlayers[uActiveCharacter];
+  v1 = v85;
+  v79.uFrameX = 483;
+  v79.uFrameWidth = 148;
+  v79.uFrameZ = 334;
+  v81 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  *(int *)v84 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  //v2 = p2DEvents_minus1__20[13 * (unsigned int)v0->ptr_1C];
+  v2 = p2DEvents[(unsigned int)v0->ptr_1C - 1].fPriceMultiplier;
+  *(float *)&v83 = v2;
+  *(float *)&v89 = v2 * v2;
+  v3 = (signed __int64)(*(float *)&v89 * 0.1);
+  v4 = v3 * (100 - v1->GetMerchant()) / 100;
+  if ( v4 < v3 / 3 )
+    v4 = v3 / 3;
+  v5 = 1;
+  pOutString = (GUIFont *)v4;
+  if ( v4 <= 0 )
+    pOutString = (GUIFont *)1;
+  v6 = (signed __int64)(*(float *)&v89 * *(float *)&v83 * 0.0099999998);
+  v7 = v6 * (100 - v85->GetMerchant()) / 100;
+  if ( v7 < v6 / 3 )
+    v7 = v6 / 3;
+  v83 = v7;
+  if ( v7 <= 0 )
+  {
+    v7 = 1;
+    v83 = 1;
+  }
+  if ( dword_F8B19C > 101 )
+  {
+    if ( dword_F8B19C == 102 )
+    {
+      v65 = pFontArrus;
+      pOutString = pFontArrus;
+      strcpy(pTmpBuf, pNPCTopics[354].pText);
+      v78.uFrameWidth = 460;
+      v78.uFrameZ = 452;
+      v62 = v65->CalcTextHeight(pTmpBuf, &v78, 12, 0) + 7;
+      if ( 352 - v62 < 8 )
+      {
+        pOutString = pFontCreate;
+        v62 = pFontCreate->CalcTextHeight(pTmpBuf, &v78, 12, 0) + 7;
+      }
+
+      auto pTex = (uTextureID_Leather != -1 ? &pIcons_LOD->pTextures[uTextureID_Leather] : 0);
+      pRenderer->_4A6A68(
+        8u,
+        352 - v62,
+        pTex,
+        (pTex ? pTex->uTextureHeight : 26) - v62);
+
+      pRenderer->DrawTextureIndexed(8u, 347 - v62, pTexture_591428);
+      v73 = 0;
+      v70 = 0;
+      v68 = 0;
+      v63 = FitTextInAWindow(pTmpBuf, pOutString, &v78, 0xCu, 0);
+      v64 = pOutString;
+    }
+    else
+    {
+      if ( dword_F8B19C != 103 )
+      {
+        if ( dword_F8B19C != 104 || pArcomageGame->bGameInProgress == 1 )
+          return;
+        v26 = pTmpBuf;
+        if ( pArcomageGame->uGameResult )
+        {
+          if ( pArcomageGame->uGameResult == 1 )
+            v72 = pGlobalTXT_LocalizationStrings[640];// You won!
+          else
+            v72 = pGlobalTXT_LocalizationStrings[641];// You lost!
+        }
+        else
+        {
+          v72 = pGlobalTXT_LocalizationStrings[639];// A tie!
+        }
+        strcpy(pTmpBuf, v72);
+LABEL_97:
+        v71 = 3;
+        v69 = v26;
+        v67 = v84[0];
+        v66 = (174 - pFontArrus->CalcTextHeight(v26, &v79, 0, 0)) / 2 + 138;
+        goto LABEL_98;
+      }
+      strcpy(pTmpBuf, pNPCTopics[(uint)ptr_507BC0->ptr_1C + 247].pText);
+      v78.uFrameWidth = 460;
+      v78.uFrameZ = 452;
+      v61 = pFontArrus->CalcTextHeight(pTmpBuf, &v78, 12, 0);
+      v62 = v61 + 7;
+
+      auto pTex = (uTextureID_Leather != -1 ? &pIcons_LOD->pTextures[uTextureID_Leather] : nullptr);
+      pRenderer->_4A6A68(
+        8u,
+        352 - (v61 + 7),
+        pTex,
+        (pTex ? pTex->uTextureHeight : 26) - (v61 + 7));
+
+      pRenderer->DrawTextureIndexed(8u, 347 - v62, pTexture_591428);
+      v73 = 0;
+      v70 = 0;
+      v68 = 0;
+      v63 = FitTextInAWindow(pTmpBuf, pFontArrus, &v78, 0xCu, 0);
+      v64 = pFontArrus;
+    }
+    ptr_507BC0->DrawText(v64, 12, 354 - v62, 0, v63, v68, v70, v73);
+    return;
+  }
+  if ( dword_F8B19C != 101 )
+  {
+    if ( dword_F8B19C != 1 )
+    {
+      if ( dword_F8B19C == 15 )
+      {
+        if ( pParty->uNumGold >= (unsigned int)pOutString )
+        {
+          Party::TakeGold((unsigned int)pOutString);
+          v27 = (int)ptr_507BC0->ptr_1C;
+          HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 2);
+          dword_F8B19C = 0;
+          while ( sub_4BD8B5() )
+            ;
+          sub_4B1D27();
+          pVideoPlayer->Unload();
+          ptr_507BC0->Release();
+          ptr_507BC0 = 0;
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          pMessageQueue_50CBD0->pMessages[0].eType = (UIMessageType)409;
+          pMessageQueue_50CBD0->pMessages[0].param = v27;
+          pMessageQueue_50CBD0->pMessages[0].field_8 = 1;
+LABEL_51:
+          ++pMessageQueue_50CBD0->uNumMessages;
+          return;
+        }
+      }
+      else
+      {
+        if ( dword_F8B19C != 16 )
+        {
+          if ( dword_F8B19C != 96 || !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+            return;
+          v8 = pDialogueWindow;
+          *(float *)&v89 = 0.0;
+
+          //v9 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (unsigned int)ptr_507BC0->ptr_1C] * 500.0);
+          v9 = (signed __int64)(p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].flt_24 * 500.0);
+
+          pOutString = (GUIFont *)(v9 * (100 - v85->GetMerchant()) / 100);
+          if ( (signed int)pOutString < v9 / 3 )
+            pOutString = (GUIFont *)(v9 / 3);
+          v10 = v8->pStartingPosActiveItem;
+          v11 = v10 + v8->pNumPresenceButton;
+          v86 = 0;
+          if ( (signed int)v10 < v11 )
+          {
+            do
+            {
+              v12 = v8->GetControl(v10)->uControlParam - 36;
+              if ( byte_4ED970_skill_learn_ability_by_class_table[v85->uClass][v12] && !v85->pActiveSkills[v12] )
+              {
+                v13 = pFontArrus->CalcTextHeight(pSkillNames[v12], &v79, 0, 0);
+                v89 += v13;
+                ++v86;
+              }
+              ++v10;
+            }
+            while ( (signed int)v10 < v8->pStartingPosActiveItem + v8->pNumPresenceButton );
+            if ( v86 )
+            {
+              sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], pOutString);
+              v79.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+              pOutString = (GUIFont *)((149 - v89) / v86);
+              if ( (149 - v89) / v86 > 32 )
+                pOutString = (GUIFont *)32;
+              v14 = (149 - v86 * (signed int)pOutString - v89) / 2 - (signed int)pOutString / 2 + 162;
+              v89 = v8->pStartingPosActiveItem;
+              v83 = v14;
+              if ( v89 < v89 + v8->pNumPresenceButton )
+              {
+                v86 = 2;
+                do
+                {
+                  v15 = v8->GetControl(v89);
+                  v16 = v15;
+                  v17 = v15->uControlParam - 36;
+                  if ( !byte_4ED970_skill_learn_ability_by_class_table[v85->uClass][v17] || v85->pActiveSkills[v17] )
+                  {
+                    v16->uW = 0;
+                    v16->uHeight = 0;
+                    v16->uY = 0;
+                  }
+                  else
+                  {
+                    v18 = pSkillNames[v17];
+                    v16->uY = (unsigned int)((char *)pOutString + v83);
+                    Str[1] = v18;
+                    v19 = pFontArrus->CalcTextHeight(v18, &v79, 0, 0);
+                    v20 = v16->uY;
+                    v21 = v86;
+                    v16->uHeight = v19;
+                    v22 = v19 + v20 - 1;
+                    v16->uW = v22;
+                    v83 = v22;
+                    v23 = v84[0];
+                    if ( pDialogueWindow->pCurrentPosActiveItem != v21 )
+                      v23 = v81;
+                    v79.DrawTitleText(pFontArrus, 0, v20, v23, Str[1], 3u);
+                  }
+                  v24 = v8->pNumPresenceButton;
+                  ++v89;
+                  v25 = v8->pStartingPosActiveItem + v24;
+                  ++v86;
+                }
+                while ( v89 < v25 );
+              }
+              return;
+            }
+          }
+          v26 = pTmpBuf;
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], v85->pName, pClassNames[v85->uClass]);
+          strcat(pTmpBuf, "\n \n");
+          strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);
+          goto LABEL_97;
+        }
+        *(_QWORD *)Str = pParty->uNumFoodRations;
+        //if ( (double)pParty->uNumFoodRations >= p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C] )
+        if ( (double)pParty->uNumFoodRations >= p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].fPriceMultiplier )
+        {
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[140], 2u);
+          if ( uActiveCharacter )
+            pPlayers[uActiveCharacter]->PlaySound(67, 0);
+          goto LABEL_43;
+        }
+        if ( pParty->uNumGold >= v7 )
+        {
+          Party::TakeGold(v7);
+          //pParty->uNumFoodRations = (signed __int64)p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C];
+          pParty->uNumFoodRations = (signed __int64)p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].fPriceMultiplier;
+          HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 3);
+          v5 = 1;
+LABEL_43:
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages >= 40 )
+            return;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v5;
+          *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+          goto LABEL_51;
+        }
+      }
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
+      HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 4);
+      goto LABEL_43;
+    }
+    if ( !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+      return;
+    v28 = *(int *)v84;
+    if ( pDialogueWindow->pCurrentPosActiveItem != 2 )
+      v28 = v81;
+    sprintf(&Dest, format_4E2DC8, v28);
+    sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[178], pOutString);
+    strcat(&Dest, pTmpBuf2);
+    v90 = pFontArrus->CalcTextHeight(&Dest, &v79, 0, 0);
+    strcat(&Dest, "\n \n");
+    v29 = *(int *)v84;
+    if ( pDialogueWindow->pCurrentPosActiveItem != 3 )
+      v29 = v81;
+    sprintf(&a1, format_4E2DC8, v29);
+    sprintf(pTmpBuf2,
+      pGlobalTXT_LocalizationStrings[86],
+      //(signed __int64)p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C],
+      (signed __int64)p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].fPriceMultiplier,
+      v83);
+    strcat(&a1, pTmpBuf2);
+    v88 = pFontArrus->CalcTextHeight(&a1, &v79, 0, 0);
+    strcat(&a1, "\n \n");
+    v30 = *(int *)v84;
+    if ( pDialogueWindow->pCurrentPosActiveItem != 4 )
+      v30 = v81;
+    sprintf(&v77, format_4E2DC8, v30);
+    strcat(&v77, pGlobalTXT_LocalizationStrings[160]);
+    v82 = pFontArrus->CalcTextHeight(&v77, &v79, 0, 0);
+    strcat(&v77, "\n \n");
+    v75 = 0;
+    v87 = 0;
+    v31 = (signed int)ptr_507BC0->ptr_1C;
+    if ( v31 >= 108 && v31 <= 120 )
+    {
+      v32 = *(int *)v84;
+      if ( pDialogueWindow->pCurrentPosActiveItem != 5 )
+        v32 = v81;
+      sprintf(&v75, format_4E2DC8, v32);
+      strcat(&v75, pGlobalTXT_LocalizationStrings[611]);
+      v87 = pFontArrus->CalcTextHeight(&v75, &v79, 0, 0);
+    }
+    v33 = pDialogueWindow;
+    Str[1] = (char *)pDialogueWindow;
+    v34 = pDialogueWindow->pStartingPosActiveItem;
+    v35 = v34 + pDialogueWindow->pNumPresenceButton;
+    v36 = LOBYTE(pFontArrus->uFontHeight) - 3;
+    v37 = -pDialogueWindow->pNumPresenceButton < 0;
+    pOutString = (GUIFont *)pDialogueWindow->pStartingPosActiveItem;
+    if ( !(v37 ^ __OFSUB__(v34, v35)) )
+    {
+LABEL_75:
+      sprintf(pTmpBuf, "%s%s%s%s", &Dest, &a1, &v77, &v75);
+      v71 = 3;
+      v69 = pTmpBuf;
+      v67 = 0;
+      v66 = 146;
+LABEL_98:
+      v79.DrawTitleText(pFontArrus, 0, v66, v67, v69, v71);
+      return;
+    }
+    while ( 1 )
+    {
+      v38 = v33->GetControl((unsigned int)pOutString);
+      if ( v38->uControlParam == 15 )
+      {
+        v46 = v90;
+        v38->uHeight = v90;
+        v38->uY = 146;
+        v41 = v46 + 145;
+        goto LABEL_73;
+      }
+      if ( v38->uControlParam == 16 )
+      {
+        v44 = v88;
+        v45 = v90 + v36 + 146;
+        v38->uHeight = v88;
+        v38->uY = v45;
+        v41 = v45 + v44 - 1;
+        goto LABEL_73;
+      }
+      if ( v38->uControlParam == 96 )
+        break;
+      if ( v38->uControlParam == 101 )
+      {
+        v39 = v90 + 3 * v36 + v87 + v88 + 146;
+        v33 = (GUIWindow *)Str[1];
+        v40 = v87;
+        v38->uHeight = v87;
+        v38->uY = v39;
+        v41 = v39 + v40 - 1;
+LABEL_73:
+        v38->uW = v41;
+      }
+      v47 = v33->pStartingPosActiveItem;
+      pOutString = (GUIFont *)((char *)pOutString + 1);
+      if ( (signed int)pOutString >= v33->pNumPresenceButton + v47 )
+        goto LABEL_75;
+    }
+    v42 = v90 + v88 + 2 * v36 + 146;
+    v43 = v82;
+    v38->uY = v42;
+    v38->uHeight = v43;
+    v41 = v43 + v42 - 1;
+    goto LABEL_73;
+  }
+  if ( sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+  {
+    v48 = 2;
+    pShopOptions[0] = pGlobalTXT_LocalizationStrings[620];
+    pOutString = 0;
+    pShopOptions[1] = pGlobalTXT_LocalizationStrings[622];
+    if ( pParty->HasItem(0x28Bu) )
+    {
+      pShopOptions[2] = pGlobalTXT_LocalizationStrings[621];
+      v48 = 3;
+    }
+    for ( i = 0; i < v48; ++i )
+    {
+      v50 = pFontArrus->CalcTextHeight(pShopOptions[i], &v79, 0, 0);
+      pOutString = (GUIFont *)((char *)pOutString + v50);
+    }
+    v86 = (174 - (signed int)pOutString) / v48;
+    v51 = pDialogueWindow;
+    v52 = 174 - v48 * (174 - (signed int)pOutString) / v48 - (signed int)pOutString;
+    v53 = v52 - HIDWORD(v52);
+    LODWORD(v52) = pDialogueWindow->pStartingPosActiveItem;
+    HIDWORD(v52) = v52 + pDialogueWindow->pNumPresenceButton;
+    v54 = (v53 >> 1) - v86 / 2 + 138;
+    v37 = -pDialogueWindow->pNumPresenceButton < 0;
+    v89 = pDialogueWindow->pStartingPosActiveItem;
+    if ( v37 ^ __OFSUB__((int)v52, HIDWORD(v52)) )
+    {
+      v85 = (Player *)2;
+      pOutString = (GUIFont *)pShopOptions;
+      do
+      {
+        v55 = v51->GetControl(v89);
+        v56 = (const char **)pOutString;
+        v55->uY = v86 + v54;
+        v57 = pFontArrus->CalcTextHeight(*v56, &v79, 0, 0);
+        v58 = v55->uY;
+        v59 = v85;
+        v55->uHeight = v57;
+        v54 = v57 + v58 - 1;
+        v55->uW = v54;
+        v60 = v84[0];
+        if ( (Player *)pDialogueWindow->pCurrentPosActiveItem != v59 )
+          v60 = v81;
+        v79.DrawTitleText(pFontArrus, 0, v58, v60, *(const char **)&pOutString->cFirstChar, 3u);
+        v51 = pDialogueWindow;
+        v85 = (Player *)((char *)v85 + 1);
+        pOutString = (GUIFont *)((char *)pOutString + 4);
+        ++v89;
+      }
+      while ( v89 < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem );
+    }
+  }
+}
+
+//----- (004B8E3D) --------------------------------------------------------
+void *__cdecl GenerateShopItems()
+{
+  GUIWindow *v0; // eax@1
+  signed int v1; // edi@1
+  signed int v2; // esi@1
+  int v3; // ecx@3
+  int v4; // ebx@3
+  int v5; // ecx@3
+  bool v6; // ebp@5
+  int v7; // ecx@5
+  void *result; // eax@15
+  signed int v9; // [sp-Ch] [bp-14h]@7
+
+  v0 = ptr_507BC0;
+  v1 = 0;
+  v2 = (signed int)ptr_507BC0->ptr_1C;
+  //if ( _4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)ptr_507BC0->ptr_1C]] )
+  if ( _4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].uType] )
+  {
+    while ( v2 > 14 )
+    {
+      if ( v2 <= 28 )
+      {
+        v6 = v1 > 3;
+        v7 = v6 + 2 * v2 - 30;
+        v2 = (signed int)v0->ptr_1C;
+        v4 = word_4F0498[5 * v7];
+        __debugbreak();
+        //things happen around word_4F0400 actually
+        //v5 = *(short *)&aTooManyStation[2 * (5 * (v6 + 2 * v2) + rand() % 4) + 10];
+        goto LABEL_13;
+      }
+      if ( v2 <= 41 )
+      {
+        v4 = word_4F0576[v2];
+        v9 = 22;
+        goto LABEL_12;
+      }
+      if ( v2 <= 53 )
+      {
+        if ( v1 >= 6 )
+        {
+          v4 = word_4F0578[v2];
+          v9 = 45;
+LABEL_12:
+          v5 = v9;
+LABEL_13:
+          pItemsTable->GenerateItem(v4, v5, (ItemGen *)&pParty->field_777C[9 * (v1 + 12 * v2)]);
+          v0 = ptr_507BC0;
+          pParty->field_777C[9 * (v1 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 5] = 1;
+          goto LABEL_14;
+        }
+        auto _t = (ItemGen *)&pParty->field_777C[9 * (v1 + 12 * v2)];
+        _t->Reset();
+        v0 = ptr_507BC0;
+        pParty->field_777C[9 * (v1 + 12 * (unsigned int)ptr_507BC0->ptr_1C)] = 220;
+      }
+LABEL_14:
+      v2 = (signed int)v0->ptr_1C;
+      ++v1;
+      //if ( v1 >= (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)v0->ptr_1C]] )
+      if ( v1 >= (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)v0->ptr_1C - 1].uType] )
+        goto LABEL_15;
+    }
+    v3 = 5 * v2;
+    v2 = (signed int)v0->ptr_1C;
+    v4 = word_4F03FE[v3];
+    v5 = word_4F0400[5 * v2 + rand() % 4];
+    goto LABEL_13;
+  }
+LABEL_15:
+  result = v0->ptr_1C;
+  *(int *)&pParty->field_16154[4 * (int)result] = 0;
+  return result;
+}
+
+
+
+//----- (004B910F) --------------------------------------------------------
+char *__cdecl sub_4B910F()
+{
+  Player *v0; // ebx@1
+  char *result; // eax@6
+  signed int v2; // esi@8
+  unsigned int v3; // ebx@10
+  ItemGen *v4; // eax@11
+  char *v5; // ecx@12
+  unsigned __int8 v6; // dl@13
+  char *v7; // edx@14
+  int v8; // eax@15
+  int v9; // ST08_4@16
+  int v10; // eax@16
+  signed int v11; // esi@18
+  int v12; // ST08_4@21
+  int v13; // eax@21
+  int v14; // edi@23
+  char **v15; // esi@23
+  int v16; // eax@24
+  GUIWindow *v17; // ecx@25
+  int v18; // edx@25
+  int v19; // edi@25
+  unsigned __int8 v20; // sf@25
+  GUIButton *v21; // esi@27
+  const char **v22; // eax@27
+  int v23; // eax@27
+  unsigned int v24; // ecx@27
+  int v25; // edx@27
+  unsigned __int16 v26; // ax@27
+  signed int v27; // esi@32
+  int v28; // ST08_4@36
+  int v29; // eax@36
+  GUIWindow *v30; // edi@41
+  void *v31; // eax@41
+  signed int v32; // esi@41
+  unsigned int v33; // esi@43
+  int v34; // eax@43
+  unsigned int v35; // eax@44
+  int v36; // eax@46
+  __int32 v37; // ecx@51
+  GUIButton *v38; // eax@53
+  GUIButton *v39; // esi@53
+  int v40; // eax@53
+  char *v41; // eax@55
+  int v42; // eax@55
+  unsigned int v43; // ecx@55
+  const char **v44; // edx@55
+  int v45; // eax@55
+  unsigned __int16 v46; // ax@55
+  int v47; // eax@59
+  const char **v48; // eax@63
+  unsigned int v49; // esi@65
+  Texture *v50; // eax@65
+  int v51; // edi@65
+  int v52; // esi@70
+  Texture *v53; // ST1C_4@70
+  int v54; // edi@70
+  signed int v55; // ecx@73
+  SHORT v56; // di@82
+  bool v57; // eax@82
+  const char *v58; // ecx@84
+  POINT *v59; // esi@89
+  LONG v60; // ecx@90
+  int v61; // eax@90
+  int v62; // ecx@90
+  ItemGen *v63; // esi@90
+  int v64; // eax@95
+  int v65; // esi@96
+  char **v66; // edi@96
+  int v67; // eax@97
+  GUIWindow *v68; // ecx@98
+  int v69; // edx@98
+  int v70; // edi@98
+  GUIButton *v71; // esi@100
+  const char **v72; // eax@100
+  int v73; // eax@100
+  unsigned int v74; // ecx@100
+  Player *v75; // edx@100
+  unsigned __int16 v76; // ax@100
+  GUIWindow *v77; // [sp-18h] [bp-110h]@14
+  int v78; // [sp-14h] [bp-10Ch]@14
+  ItemGen *v79; // [sp-10h] [bp-108h]@12
+  int v80; // [sp-10h] [bp-108h]@14
+  void *v81; // [sp-Ch] [bp-104h]@12
+  unsigned __int16 v82; // [sp-Ch] [bp-104h]@14
+  int v83; // [sp-8h] [bp-100h]@11
+  char *v84; // [sp-8h] [bp-100h]@14
+  __int64 *v85; // [sp-4h] [bp-FCh]@11
+  unsigned int v86; // [sp-4h] [bp-FCh]@14
+  POINT v87; // [sp+Ch] [bp-ECh]@8
+  POINT v88; // [sp+14h] [bp-E4h]@18
+  POINT v89; // [sp+1Ch] [bp-DCh]@89
+  POINT v90; // [sp+24h] [bp-D4h]@19
+  POINT v91; // [sp+2Ch] [bp-CCh]@89
+  POINT v92; // [sp+34h] [bp-C4h]@9
+  POINT v93; // [sp+3Ch] [bp-BCh]@33
+  POINT v94; // [sp+44h] [bp-B4h]@18
+  POINT v95; // [sp+4Ch] [bp-ACh]@32
+  POINT v96; // [sp+54h] [bp-A4h]@18
+  POINT v97; // [sp+5Ch] [bp-9Ch]@32
+  POINT a2; // [sp+64h] [bp-94h]@8
+  POINT v99; // [sp+6Ch] [bp-8Ch]@32
+  POINT v100; // [sp+74h] [bp-84h]@8
+  GUIWindow v101; // [sp+7Ch] [bp-7Ch]@1
+  char *Str; // [sp+D0h] [bp-28h]@55
+  __int32 v103; // [sp+D4h] [bp-24h]@25
+  int v104; // [sp+D8h] [bp-20h]@1
+  int v105; // [sp+DCh] [bp-1Ch]@1
+  POINT v106; // [sp+E0h] [bp-18h]@8
+  Player *_this; // [sp+E8h] [bp-10h]@1
+  int v108; // [sp+ECh] [bp-Ch]@26
+  const char **v109; // [sp+F0h] [bp-8h]@26
+  unsigned __int8 v110; // [sp+F7h] [bp-1h]@16
+
+  v0 = pPlayers[uActiveCharacter];
+  _this = pPlayers[uActiveCharacter];
+  memcpy(&v101, ptr_507BC0, sizeof(v101));
+  v101.uFrameX = 483;
+  v101.uFrameWidth = 148;
+  v101.uFrameZ = 334;
+  v105 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v104 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  if ( dword_F8B19C > 5 )
+  {
+    if ( dword_F8B19C == 94 )
+    {
+      draw_leather();
+      CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+      pShopOptions[0] = pGlobalTXT_LocalizationStrings[200];
+      pShopOptions[1] = pGlobalTXT_LocalizationStrings[113];
+      pShopOptions[2] = pGlobalTXT_LocalizationStrings[179];
+      v65 = 0;
+      v66 = pShopOptions;
+      do
+      {
+        v67 = pFontArrus->CalcTextHeight(*v66, &v101, 0, 0);
+        ++v66;
+        v65 += v67;
+      }
+      while ( (signed int)v66 < (signed int)&pShopOptions[3] );
+      v68 = pDialogueWindow;
+      v109 = (const char **)((174 - v65) / 3);
+      result = (char *)pDialogueWindow->pStartingPosActiveItem;
+      v69 = (int)&result[pDialogueWindow->pNumPresenceButton];
+      v70 = (3 * (58 - (signed int)v109) - v65) / 2 - (174 - v65) / 3 / 2 + 138;
+      v20 = -pDialogueWindow->pNumPresenceButton < 0;
+      v106.y = pDialogueWindow->pStartingPosActiveItem;
+      if ( v20 ^ __OFSUB__((int)result, (int)v69) )
+      {
+        _this = (Player *)2;
+        v108 = (int)pShopOptions;
+        do
+        {
+          v71 = v68->GetControl(v106.y);
+          v72 = (const char **)v108;
+          v71->uY = (unsigned int)((char *)v109 + v70);
+          v73 = pFontArrus->CalcTextHeight(*v72, &v101, 0, 0);
+          v74 = v71->uY;
+          v75 = _this;
+          v71->uHeight = v73;
+          v70 = v73 + v74 - 1;
+          v71->uW = v70;
+          v76 = v104;
+          if ( (Player *)pDialogueWindow->pCurrentPosActiveItem != v75 )
+            v76 = v105;
+          v101.DrawTitleText(pFontArrus, 0, v74, v76, *(const char **)v108, 3u);
+          v68 = pDialogueWindow;
+          _this = (Player *)((char *)_this + 1);
+          v108 += 4;
+          ++v106.y;
+          result = (char *)(pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem);
+        }
+        while ( v106.y < (signed int)result );
+      }
+      return result;
+    }
+    if ( dword_F8B19C != 95 )
+    {
+      result = (char *)(dword_F8B19C - 96);
+      if ( dword_F8B19C == 96 )
+      {
+        result = (char *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+        if ( result )
+        {
+          v30 = pDialogueWindow;
+          v3 = 0;
+          v31 = ptr_507BC0->ptr_1C;
+          v106.y = 0;
+          //v32 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (signed int)v31] * 500.0);
+          v32 = (signed __int64)(p2DEvents[(signed int)v31 - 1].flt_24 * 500.0);
+          v108 = v32 * (100 - _this->GetMerchant()) / 100;
+          if ( v108 < v32 / 3 )
+            v108 = v32 / 3;
+          v33 = v30->pStartingPosActiveItem;
+          v34 = v33 + v30->pNumPresenceButton;
+          v109 = 0;
+          if ( (signed int)v33 >= v34 )
+            goto LABEL_105;
+          do
+          {
+            v35 = v30->GetControl(v33)->uControlParam - 36;
+            if ( byte_4ED970_skill_learn_ability_by_class_table[_this->uClass][v35] && !_this->pActiveSkills[v35] )
+            {
+              v36 = pFontArrus->CalcTextHeight(pSkillNames[v35], &v101, 0, 0);
+              v106.y += v36;
+              v109 = (const char **)((char *)v109 + 1);
+            }
+            ++v33;
+          }
+          while ( (signed int)v33 < v30->pNumPresenceButton + v30->pStartingPosActiveItem );
+          if ( !v109 )
+          {
+LABEL_105:
+            sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], _this->pName, pClassNames[_this->uClass]);
+            strcat(pTmpBuf, "\n \n");
+            strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);
+            v7 = pTmpBuf;
+            v86 = 3;
+            v84 = pTmpBuf;
+            v82 = v104;
+            v80 = 0;
+            v78 = 0;
+            v77 = &v101;
+            goto LABEL_15;
+          }
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], v108);
+          v101.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+          v108 = (149 - v106.y) / (signed int)v109;
+          if ( (149 - v106.y) / (signed int)v109 > 32 )
+            v108 = 32;
+          result = (char *)v30->pStartingPosActiveItem;
+          v37 = (149 - (signed int)v109 * v108 - v106.y) / 2 - v108 / 2 + 162;
+          v106.y = (LONG)result;
+          v103 = v37;
+          if ( (signed int)result < (signed int)&result[v30->pNumPresenceButton] )
+          {
+            v109 = (const char **)2;
+            do
+            {
+              v38 = v30->GetControl(v106.y);
+              v39 = v38;
+              v40 = v38->uControlParam - 36;
+              if ( !byte_4ED970_skill_learn_ability_by_class_table[_this->uClass][v40] || _this->pActiveSkills[v40] )
+              {
+                v39->uW = 0;
+                v39->uHeight = 0;
+                v39->uY = 0;
+              }
+              else
+              {
+                v41 = pSkillNames[v40];
+                v39->uY = v108 + v103;
+                Str = v41;
+                v42 = pFontArrus->CalcTextHeight(v41, &v101, 0, 0);
+                v43 = v39->uY;
+                v44 = v109;
+                v39->uHeight = v42;
+                v45 = v43 + v42 - 1;
+                v39->uW = v45;
+                v103 = v45;
+                v46 = v104;
+                if ( (const char **)pDialogueWindow->pCurrentPosActiveItem != v44 )
+                  v46 = v105;
+                v101.DrawTitleText(pFontArrus, 0, v43, v46, Str, 3u);
+              }
+              v47 = v30->pStartingPosActiveItem;
+              ++v106.y;
+              result = (char *)(v30->pNumPresenceButton + v47);
+              v109 = (const char **)((char *)v109 + 1);
+            }
+            while ( v106.y < (signed int)result );
+          }
+        }
+      }
+      return result;
+    }
+  }
+  else
+  {
+    if ( dword_F8B19C == 5 )
+    {
+      draw_leather();
+      CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+      sub_4B46A5(pGlobalTXT_LocalizationStrings[198], 0);
+      result = (char *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+      if ( result )
+      {
+        v27 = pMouse->GetCursorPos(&v99)->x - 14;
+        v106.x = (v27 >> 5) + 14 * ((pMouse->GetCursorPos(&v97)->y - 17) >> 5);
+        result = (char *)pMouse->GetCursorPos(&v95);
+        if ( *(int *)result > 13 )
+        {
+          result = (char *)pMouse->GetCursorPos(&v93);
+          if ( *(int *)result < 462 )
+          {
+            result = (char *)v0->GetItemIDAtInventoryIndex((int *)&v106.x);
+            v3 = 0;
+            if ( result )
+            {
+              result = (char *)(9 * (int)result);
+              if ( _this->field_1F5[4 * (int)result + 15] & 2 )
+              {
+                v85 = 0;
+                v83 = 5;
+                v81 = ptr_507BC0->ptr_1C;
+                v79 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * (int)result + 5];
+                v28 = (int)ptr_507BC0->ptr_1C;
+                v110 = uActiveCharacter - 1;
+                v29 = _this->_490EEE(
+                        (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * (int)result + 5],
+                        1,
+                        v28,
+                        5);
+                v6 = v110;
+                v5 = (char *)pMerchantsRepairPhrases[v29];
+                goto LABEL_14;
+              }
+            }
+          }
+        }
+      }
+      return result;
+    }
+    if ( dword_F8B19C == 1 )
+    {
+      result = (char *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+      if ( result )
+      {
+        pShopOptions[0] = pGlobalTXT_LocalizationStrings[134];
+        pShopOptions[1] = pGlobalTXT_LocalizationStrings[152];
+        pShopOptions[2] = pGlobalTXT_LocalizationStrings[159];
+        v14 = 0;
+        pShopOptions[3] = pGlobalTXT_LocalizationStrings[160];
+        v15 = pShopOptions;
+        do
+        {
+          v16 = pFontArrus->CalcTextHeight(*v15, &v101, 0, 0);
+          ++v15;
+          v14 += v16;
+        }
+        while ( (signed int)v15 < (signed int)&unk_F8B1C8 );
+        v17 = pDialogueWindow;
+        v103 = (174 - v14) / 4;
+        result = (char *)pDialogueWindow->pStartingPosActiveItem;
+        v18 = (int)&result[pDialogueWindow->pNumPresenceButton];
+        v19 = (174 - 4 * (174 - v14) / 4 - v14) / 2 - (174 - v14) / 4 / 2 + 138;
+        v20 = -pDialogueWindow->pNumPresenceButton < 0;
+        _this = (Player *)pDialogueWindow->pStartingPosActiveItem;
+        if ( v20 ^ __OFSUB__((int)result, v18) )
+        {
+          v108 = 2;
+          v109 = (const char **)pShopOptions;
+          do
+          {
+            v21 = v17->GetControl((unsigned int)_this);
+            v22 = v109;
+            v21->uY = v103 + v19;
+            v23 = pFontArrus->CalcTextHeight(*v22, &v101, 0, 0);
+            v24 = v21->uY;
+            v25 = v108;
+            v21->uHeight = v23;
+            v19 = v24 + v23 - 1;
+            v21->uW = v19;
+            v26 = v104;
+            if ( pDialogueWindow->pCurrentPosActiveItem != v25 )
+              v26 = v105;
+            v101.DrawTitleText(pFontArrus, 0, v24, v26, *v109, 3u);
+            v17 = pDialogueWindow;
+            ++v108;
+            ++v109;
+            _this = (Player *)((char *)_this + 1);
+            result = (char *)(pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem);
+          }
+          while ( (signed int)_this < (signed int)result );
+        }
+      }
+      return result;
+    }
+    if ( dword_F8B19C != 2 )
+    {
+      if ( dword_F8B19C == 3 )
+      {
+        draw_leather();
+        CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+        sub_4B46A5(pGlobalTXT_LocalizationStrings[199], 0);
+        result = (char *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+        if ( result )
+        {
+          v11 = pMouse->GetCursorPos(&v96)->x - 14;
+          v106.x = (v11 >> 5) + 14 * ((pMouse->GetCursorPos(&v88)->y - 17) >> 5);
+          result = (char *)pMouse->GetCursorPos(&v94);
+          if ( *(int *)result > 13 )
+          {
+            result = (char *)pMouse->GetCursorPos(&v90);
+            if ( *(int *)result < 462 )
+            {
+              result = (char *)v0->GetItemIDAtInventoryIndex((int *)&v106.x);
+              v3 = 0;
+              if ( result )
+              {
+                v85 = 0;
+                v83 = 3;
+                v81 = ptr_507BC0->ptr_1C;
+                v79 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
+                v12 = (int)ptr_507BC0->ptr_1C;
+                v110 = uActiveCharacter - 1;
+                v13 = _this->_490EEE(v79, 1, v12, 3);
+                v6 = v110;
+                v5 = (char *)pMerchantsSellPhrases[v13];
+                goto LABEL_14;
+              }
+            }
+          }
+        }
+      }
+      else
+      {
+        result = (char *)(dword_F8B19C - 4);
+        if ( dword_F8B19C == 4 )
+        {
+          draw_leather();
+          CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+          sub_4B46A5(pGlobalTXT_LocalizationStrings[197], 0);
+          result = (char *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+          if ( result )
+          {
+            v2 = pMouse->GetCursorPos(&a2)->x - 14;
+            v106.x = (v2 >> 5) + 14 * ((pMouse->GetCursorPos(&v87)->y - 17) >> 5);
+            result = (char *)pMouse->GetCursorPos(&v100);
+            if ( *(int *)result > 13 )
+            {
+              result = (char *)pMouse->GetCursorPos(&v92);
+              if ( *(int *)result < 462 )
+              {
+                result = (char *)v0->GetItemIDAtInventoryIndex((int *)&v106.x);
+                v3 = 0;
+                if ( result )
+                {
+                  v85 = 0;
+                  v83 = 4;
+                  v4 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
+                  if ( !(v4->uAttributes & 1) )
+                  {
+                    v81 = ptr_507BC0->ptr_1C;
+                    v79 = v4;
+                    v9 = (int)ptr_507BC0->ptr_1C;
+                    v110 = uActiveCharacter - 1;
+                    v10 = _this->_490EEE(v4, 1, v9, 4);
+                    v6 = v110;
+                    v5 = (char *)pMerchantsIdentifyPhrases[v10];
+                    goto LABEL_14;
+                  }
+                  v81 = ptr_507BC0->ptr_1C;
+                  v5 = "%24";
+                  v79 = v4;
+LABEL_13:
+                  v6 = uActiveCharacter - 1;
+LABEL_14:
+                  v7 = sub_495461(v5, v6, v79, (char *)v81, v83, v85);
+                  v86 = 3;
+                  v84 = v7;
+                  v82 = v105;
+                  v80 = v3;
+                  v78 = v3;
+                  v77 = &v101;
+LABEL_15:
+                  v8 = pFontArrus->CalcTextHeight(v7, v77, v78, v80);
+                  return v101.DrawTitleText(pFontArrus, v3, (174 - v8) / 2 + 138, v82, v84, v86);
+                }
+              }
+            }
+          }
+        }
+      }
+      return result;
+    }
+  }
+  pRenderer->DrawTextureIndexed(8u, 8u, dword_F8B164);
+  v3 = 0;
+  if ( dword_F8B19C == 2 )
+  {
+    v48 = 0;
+    v108 = 0;
+    v109 = 0;
+    do
+    {
+      if ( pParty->field_777C[9 * (int)&v48[3 * (unsigned int)ptr_507BC0->ptr_1C]] )
+      {
+        v49 = word_F8B158[(signed int)v48];
+        v50 = dword_F8B168[(signed int)v48];
+        v49 += 30;
+        v51 = 60 - ((signed int)v50->uTextureWidth >> 1);
+        pRenderer->DrawTextureTransparent(v51 + v108, v49, v50);
+        sub_40F92A(
+          &pRenderer->pActiveZBuffer[v51 + v108 + 640 * v49],
+          dword_F8B168[(signed int)v109],
+          (int)((char *)v109 + 1));
+        v48 = v109;
+      }
+      v108 += 70;
+      v48 = (const char **)((char *)v48 + 1);
+      v109 = v48;
+    }
+    while ( (signed int)v48 < 6 );
+  }
+  else
+  {
+    v109 = 0;
+    v108 = 0;
+    do
+    {
+      if ( pParty->field_C59C[9 * (int)&v109[3 * (unsigned int)ptr_507BC0->ptr_1C] + 724] )
+      {
+        v52 = word_F8B158[(signed int)v109] + 30;
+        v53 = dword_F8B168[(signed int)v109];
+        v54 = 60 - ((signed int)v53->uTextureWidth >> 1);
+        pRenderer->DrawTextureTransparent(v54 + v108, word_F8B158[(signed int)v109] + 30, v53);
+        sub_40F92A(
+          &pRenderer->pActiveZBuffer[v54 + v108 + 640 * v52],
+          dword_F8B168[(signed int)v109],
+          (int)((char *)v109 + 1));
+      }
+      v109 = (const char **)((char *)v109 + 1);
+      v108 += 70;
+    }
+    while ( (signed int)v109 < 6 );
+  }
+  result = (char *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+  if ( result )
+  {
+    v55 = 0;
+    v106.x = 0;
+    if ( dword_F8B19C == 2 )
+    {
+      v106.x = 0;
+      do
+      {
+        if ( pParty->field_777C[9 * (v55 + 12 * (unsigned int)ptr_507BC0->ptr_1C)] )
+          ++v106.x;
+        ++v55;
+      }
+      while ( v55 < 6 );
+    }
+    else
+    {
+      do
+      {
+        if ( pParty->field_C59C[9 * (v55 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] )
+          ++v106.x;
+        ++v55;
+      }
+      while ( v55 < 6 );
+    }
+    v56 = GetAsyncKeyState(17);
+    v57 = _this->CanSteal();
+    Str = (char *)v57;
+    if ( v56 && v57 )
+    {
+      v58 = pGlobalTXT_LocalizationStrings[185];
+    }
+    else
+    {
+      v58 = pGlobalTXT_LocalizationStrings[195];
+      if ( dword_F8B19C != 2 )
+        v58 = pGlobalTXT_LocalizationStrings[196];
+    }
+    sub_4B46A5(v58, 0);
+    if ( v106.x )
+    {
+      v59 = pMouse->GetCursorPos(&v91);
+      result = (char *)(v59->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v89)->y]);
+      if ( pRenderer->pActiveZBuffer[(int)result] & 0xFFFF )
+      {
+        v60 = (pRenderer->pActiveZBuffer[(int)result] & 0xFFFF) - 1;
+        v106.x = v60;
+        v61 = (int)ptr_507BC0->ptr_1C;
+        v62 = 9 * (v60 + 12 * v61);
+        v63 = (ItemGen *)&pParty->field_777C[v62];
+        if ( dword_F8B19C != 2 )
+          v63 = (ItemGen *)&pParty->field_C59C[v62 + 724];
+        if ( !v56 || !Str )
+        {
+          v85 = 0;
+          v83 = 2;
+          v81 = ptr_507BC0->ptr_1C;
+          v79 = v63;
+          v110 = uActiveCharacter - 1;
+          v64 = _this->_490EEE(v63, 1, v61, 2);
+          v6 = v110;
+          v5 = (char *)pMerchantsBuyPhrases[v64];
+          goto LABEL_14;
+        }
+        v5 = pGlobalTXT_LocalizationStrings[181];
+        v85 = 0;
+        v83 = 2;
+        v81 = ptr_507BC0->ptr_1C;
+        v79 = v63;
+        goto LABEL_13;
+      }
+    }
+    else
+    {
+      result = v101._4B1854(
+                 __PAIR__(
+                   pParty->field_3C.field_50[2 * (unsigned int)ptr_507BC0->ptr_1C + 1],
+                   pParty->field_3C.field_50[2 * (unsigned int)ptr_507BC0->ptr_1C])
+               - pParty->uTimePlayed);
+    }
+  }
+  return result;
+}
+
+
+//----- (004B9CC6) --------------------------------------------------------
+POINT *__cdecl sub_4B9CC6()
+{
+  Player *v0; // ebx@1
+  POINT *result; // eax@7
+  GUIWindow *v2; // edi@9
+  unsigned int v3; // ebx@9
+  void *v4; // eax@9
+  signed int v5; // esi@9
+  unsigned int v6; // esi@11
+  int v7; // eax@11
+  unsigned int v8; // eax@12
+  int v9; // eax@14
+  int v10; // ecx@19
+  GUIButton *v11; // eax@21
+  GUIButton *v12; // esi@21
+  int v13; // eax@21
+  char *v14; // eax@23
+  int v15; // eax@23
+  unsigned int v16; // ecx@23
+  int v17; // edx@23
+  int v18; // eax@23
+  unsigned __int16 v19; // ax@23
+  int v20; // eax@27
+  char *v21; // edx@29
+  int v22; // esi@30
+  char **v23; // edi@30
+  int v24; // eax@31
+  GUIWindow *v25; // ecx@32
+  int v26; // edx@32
+  int v27; // edi@32
+  unsigned __int8 v28; // sf@32
+  GUIButton *v29; // esi@34
+  const char **v30; // eax@34
+  int v31; // eax@34
+  unsigned int v32; // ecx@34
+  Player *v33; // edx@34
+  int v34; // eax@34
+  unsigned __int16 v35; // ax@34
+  signed int v36; // esi@39
+  ItemGen *v37; // eax@42
+  char *v38; // ecx@43
+  unsigned __int8 v39; // dl@44
+  int v40; // eax@46
+  int v41; // ST08_4@47
+  int v42; // eax@47
+  signed int v43; // esi@49
+  int v44; // ST08_4@52
+  int v45; // eax@52
+  Texture *v46; // ecx@55
+  unsigned int v47; // edi@55
+  unsigned int v48; // esi@57
+  int v49; // edx@61
+  Texture *v50; // ecx@67
+  unsigned int v51; // edi@67
+  unsigned int v52; // esi@69
+  int v53; // edx@73
+  Texture *v54; // ecx@79
+  unsigned int v55; // edi@79
+  unsigned int v56; // esi@81
+  int v57; // edx@85
+  Texture *v58; // ecx@91
+  unsigned int v59; // edi@91
+  unsigned int v60; // esi@93
+  int v61; // edx@97
+  signed int v62; // ecx@102
+  SHORT v63; // di@110
+  bool v64; // eax@110
+  const char *v65; // ecx@112
+  POINT *v66; // esi@117
+  int v67; // ecx@118
+  int v68; // eax@118
+  int v69; // ecx@118
+  ItemGen *v70; // esi@118
+  int v71; // eax@123
+  int v72; // edi@125
+  char **v73; // esi@125
+  int v74; // eax@126
+  GUIWindow *v75; // ecx@127
+  int v76; // edx@127
+  int v77; // edi@127
+  GUIButton *v78; // esi@129
+  const char **v79; // eax@129
+  int v80; // eax@129
+  unsigned int v81; // ecx@129
+  Player *v82; // edx@129
+  unsigned __int16 v83; // ax@129
+  GUIWindow *v84; // [sp-18h] [bp-F0h]@29
+  int v85; // [sp-14h] [bp-ECh]@29
+  int v86; // [sp-10h] [bp-E8h]@29
+  ItemGen *v87; // [sp-10h] [bp-E8h]@43
+  unsigned __int16 v88; // [sp-Ch] [bp-E4h]@29
+  void *v89; // [sp-Ch] [bp-E4h]@43
+  char *v90; // [sp-8h] [bp-E0h]@29
+  int v91; // [sp-8h] [bp-E0h]@42
+  unsigned int v92; // [sp-4h] [bp-DCh]@29
+  __int64 *v93; // [sp-4h] [bp-DCh]@42
+  POINT v94; // [sp+Ch] [bp-CCh]@39
+  POINT v95; // [sp+14h] [bp-C4h]@49
+  POINT v96; // [sp+1Ch] [bp-BCh]@117
+  POINT v97; // [sp+24h] [bp-B4h]@40
+  POINT v98; // [sp+2Ch] [bp-ACh]@117
+  POINT v99; // [sp+34h] [bp-A4h]@49
+  POINT v100; // [sp+3Ch] [bp-9Ch]@50
+  POINT v101; // [sp+44h] [bp-94h]@39
+  POINT v102; // [sp+4Ch] [bp-8Ch]@49
+  POINT a2; // [sp+54h] [bp-84h]@39
+  GUIWindow v104; // [sp+5Ch] [bp-7Ch]@1
+  int v105; // [sp+B0h] [bp-28h]@19
+  int v106; // [sp+B4h] [bp-24h]@1
+  char *Str; // [sp+B8h] [bp-20h]@23
+  int v108; // [sp+BCh] [bp-1Ch]@1
+  __int32 v109; // [sp+C0h] [bp-18h]@39
+  Player *_this; // [sp+C4h] [bp-14h]@1
+  const char **v111; // [sp+C8h] [bp-10h]@9
+  unsigned int v112; // [sp+CCh] [bp-Ch]@9
+  unsigned __int8 v113; // [sp+D3h] [bp-5h]@47
+  int v114; // [sp+D4h] [bp-4h]@11
+
+  v0 = pPlayers[uActiveCharacter];
+  _this = pPlayers[uActiveCharacter];
+  memcpy(&v104, ptr_507BC0, sizeof(v104));
+  v104.uFrameX = 483;
+  v104.uFrameWidth = 148;
+  v104.uFrameZ = 334;
+  v108 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v106 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  if ( dword_F8B19C == 1 )
+  {
+    result = (POINT *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+    if ( result )
+    {
+      pShopOptions[0] = pGlobalTXT_LocalizationStrings[134];
+      pShopOptions[1] = pGlobalTXT_LocalizationStrings[152];
+      pShopOptions[2] = pGlobalTXT_LocalizationStrings[159];
+      v72 = 0;
+      pShopOptions[3] = pGlobalTXT_LocalizationStrings[160];
+      v73 = pShopOptions;
+      do
+      {
+        v74 = pFontArrus->CalcTextHeight(*v73, &v104, 0, 0);
+        ++v73;
+        v72 += v74;
+      }
+      while ( (signed int)v73 < (signed int)&unk_F8B1C8 );
+      v75 = pDialogueWindow;
+      Str = (char *)((174 - v72) / 4);
+      result = (POINT *)pDialogueWindow->pStartingPosActiveItem;
+      v76 = (int)((char *)result + pDialogueWindow->pNumPresenceButton);
+      v77 = (174 - 4 * (174 - v72) / 4 - v72) / 2 - (174 - v72) / 4 / 2 + 138;
+      v28 = -pDialogueWindow->pNumPresenceButton < 0;
+      v112 = pDialogueWindow->pStartingPosActiveItem;
+      if ( v28 ^ __OFSUB__((int)result, v76) )
+      {
+        _this = (Player *)2;
+        v111 = (const char **)pShopOptions;
+        do
+        {
+          v78 = v75->GetControl(v112);
+          v79 = v111;
+          v78->uY = (unsigned int)&Str[v77];
+          v80 = pFontArrus->CalcTextHeight(*v79, &v104, 0, 0);
+          v81 = v78->uY;
+          v82 = _this;
+          v78->uHeight = v80;
+          v77 = v81 + v80 - 1;
+          v78->uW = v77;
+          v83 = v106;
+          if ( (Player *)pDialogueWindow->pCurrentPosActiveItem != v82 )
+            v83 = v108;
+          v104.DrawTitleText(pFontArrus, 0, v81, v83, *v111, 3u);
+          v75 = pDialogueWindow;
+          _this = (Player *)((char *)_this + 1);
+          ++v111;
+          ++v112;
+          result = (POINT *)(pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem);
+        }
+        while ( (signed int)v112 < (signed int)result );
+      }
+    }
+  }
+  else
+  {
+    if ( dword_F8B19C != 2 )
+    {
+      if ( dword_F8B19C == 3 )
+      {
+        draw_leather();
+        CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+        sub_4B46A5(pGlobalTXT_LocalizationStrings[199], 0);
+        result = (POINT *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+        if ( !result
+          || (v43 = pMouse->GetCursorPos(&v99)->x - 14,
+              v109 = (v43 >> 5) + 14 * ((pMouse->GetCursorPos(&v95)->y - 17) >> 5),
+              result = pMouse->GetCursorPos(&v102),
+              result->x <= 13)
+          || (result = pMouse->GetCursorPos(&v100), result->x >= 462)
+          || (result = (POINT *)v0->GetItemIDAtInventoryIndex((int *)&v109), v3 = 0, !result) )
+          return result;
+        v93 = 0;
+        v91 = 3;
+        v89 = ptr_507BC0->ptr_1C;
+        v87 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
+        v44 = (int)ptr_507BC0->ptr_1C;
+        v113 = uActiveCharacter - 1;
+        v45 = _this->_490EEE(v87, 4, v44, 3);
+        v39 = v113;
+        v38 = (char *)pMerchantsSellPhrases[v45];
+        goto LABEL_45;
+      }
+      if ( dword_F8B19C == 4 )
+      {
+        draw_leather();
+        CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+        sub_4B46A5(pGlobalTXT_LocalizationStrings[197], 0);
+        result = (POINT *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+        if ( !result
+          || (v36 = pMouse->GetCursorPos(&a2)->x - 14,
+              v109 = (v36 >> 5) + 14 * ((pMouse->GetCursorPos(&v94)->y - 17) >> 5),
+              result = pMouse->GetCursorPos(&v101),
+              result->x <= 13)
+          || (result = pMouse->GetCursorPos(&v97), result->x >= 462)
+          || (result = (POINT *)v0->GetItemIDAtInventoryIndex((int *)&v109), v3 = 0, !result) )
+          return result;
+        v93 = 0;
+        v91 = 4;
+        v37 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
+        if ( !(v37->uAttributes & 1) )
+        {
+          v89 = ptr_507BC0->ptr_1C;
+          v87 = v37;
+          v41 = (int)ptr_507BC0->ptr_1C;
+          v113 = uActiveCharacter - 1;
+          v42 = _this->_490EEE(v37, 4, v41, 4);
+          v39 = v113;
+          v38 = (char *)pMerchantsIdentifyPhrases[v42];
+          goto LABEL_45;
+        }
+        v89 = ptr_507BC0->ptr_1C;
+        v38 = "%24";
+        v87 = v37;
+LABEL_44:
+        v39 = uActiveCharacter - 1;
+LABEL_45:
+        v21 = sub_495461(v38, v39, v87, (char *)v89, v91, v93);
+        v92 = 3;
+        v90 = v21;
+        v88 = v108;
+        v86 = v3;
+        v85 = v3;
+        v84 = &v104;
+        goto LABEL_46;
+      }
+      if ( dword_F8B19C == 94 )
+      {
+        draw_leather();
+        CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+        pShopOptions[0] = pGlobalTXT_LocalizationStrings[200];
+        pShopOptions[1] = pGlobalTXT_LocalizationStrings[113];
+        v22 = 0;
+        v23 = pShopOptions;
+        do
+        {
+          v24 = pFontArrus->CalcTextHeight(*v23, &v104, 0, 0);
+          ++v23;
+          v22 += v24;
+        }
+        while ( (signed int)v23 < (signed int)&pShopOptions[2] );
+        Str = (char *)((174 - v22) / 2);
+        v25 = pDialogueWindow;
+        result = (POINT *)pDialogueWindow->pStartingPosActiveItem;
+        v26 = (int)((char *)result + pDialogueWindow->pNumPresenceButton);
+        v27 = (2 * (87 - (174 - v22) / 2) - v22) / 2 - (174 - v22) / 2 / 2 + 138;
+        v28 = -pDialogueWindow->pNumPresenceButton < 0;
+        v112 = pDialogueWindow->pStartingPosActiveItem;
+        if ( v28 ^ __OFSUB__((int)result, v26) )
+        {
+          _this = (Player *)2;
+          v111 = (const char **)pShopOptions;
+          do
+          {
+            v29 = v25->GetControl(v112);
+            v30 = v111;
+            v29->uY = (unsigned int)&Str[v27];
+            v31 = pFontArrus->CalcTextHeight(*v30, &v104, 0, 0);
+            v32 = v29->uY;
+            v33 = _this;
+            v29->uHeight = v31;
+            v34 = v31 + v32 - 1;
+            v29->uW = v34;
+            v27 = v34;
+            v35 = v106;
+            if ( (Player *)pDialogueWindow->pCurrentPosActiveItem != v33 )
+              v35 = v108;
+            v104.DrawTitleText(pFontArrus, 0, v32, v35, *v111, 3u);
+            v25 = pDialogueWindow;
+            _this = (Player *)((char *)_this + 1);
+            ++v111;
+            ++v112;
+            result = (POINT *)(pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem);
+          }
+          while ( (signed int)v112 < (signed int)result );
+        }
+        return result;
+      }
+      if ( dword_F8B19C != 95 )
+      {
+        result = (POINT *)(dword_F8B19C - 96);
+        if ( dword_F8B19C != 96
+          || (result = (POINT *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win()) == 0 )
+          return result;
+        v2 = pDialogueWindow;
+        v3 = 0;
+        v4 = ptr_507BC0->ptr_1C;
+        v112 = 0;
+        //v5 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (signed int)v4] * 500.0);
+        v5 = (signed __int64)(p2DEvents[(signed int)v4 - 1].flt_24 * 500.0);
+        v111 = (const char **)(v5 * (100 - _this->GetMerchant()) / 100);
+        if ( (signed int)v111 < v5 / 3 )
+          v111 = (const char **)(v5 / 3);
+        v6 = v2->pStartingPosActiveItem;
+        v7 = v6 + v2->pNumPresenceButton;
+        v114 = 0;
+        if ( (signed int)v6 < v7 )
+        {
+          do
+          {
+            v8 = v2->GetControl(v6)->uControlParam - 36;
+            if ( byte_4ED970_skill_learn_ability_by_class_table[_this->uClass][v8] && !_this->pActiveSkills[v8] )
+            {
+              v9 = pFontArrus->CalcTextHeight(pSkillNames[v8], &v104, 0, 0);
+              v112 += v9;
+              ++v114;
+            }
+            ++v6;
+          }
+          while ( (signed int)v6 < v2->pNumPresenceButton + v2->pStartingPosActiveItem );
+          if ( v114 )
+          {
+            sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], v111);
+            v104.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+            v111 = (const char **)((signed int)(149 - v112) / v114);
+            if ( (signed int)(149 - v112) / v114 > 32 )
+              v111 = (const char **)32;
+            result = (POINT *)v2->pStartingPosActiveItem;
+            v10 = (signed int)(149 - v114 * (int)v111 - v112) / 2 - (signed int)v111 / 2 + 162;
+            v112 = (unsigned int)result;
+            v105 = v10;
+            if ( (signed int)result < (signed int)((char *)result + v2->pNumPresenceButton) )
+            {
+              v114 = 2;
+              do
+              {
+                v11 = v2->GetControl(v112);
+                v12 = v11;
+                v13 = v11->uControlParam - 36;
+                if ( !byte_4ED970_skill_learn_ability_by_class_table[_this->uClass][v13] || _this->pActiveSkills[v13] )
+                {
+                  v12->uW = 0;
+                  v12->uHeight = 0;
+                  v12->uY = 0;
+                }
+                else
+                {
+                  v14 = pSkillNames[v13];
+                  v12->uY = (unsigned int)((char *)v111 + v105);
+                  Str = v14;
+                  v15 = pFontArrus->CalcTextHeight(v14, &v104, 0, 0);
+                  v16 = v12->uY;
+                  v17 = v114;
+                  v12->uHeight = v15;
+                  v18 = v16 + v15 - 1;
+                  v12->uW = v18;
+                  v105 = v18;
+                  v19 = v106;
+                  if ( pDialogueWindow->pCurrentPosActiveItem != v17 )
+                    v19 = v108;
+                  v104.DrawTitleText(pFontArrus, 0, v16, v19, Str, 3u);
+                }
+                v20 = v2->pStartingPosActiveItem;
+                ++v112;
+                result = (POINT *)(v2->pNumPresenceButton + v20);
+                ++v114;
+              }
+              while ( (signed int)v112 < (signed int)result );
+            }
+            return result;
+          }
+        }
+        sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], _this->pName, pClassNames[_this->uClass]);
+        strcat(pTmpBuf, "\n \n");
+        strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);
+        v21 = pTmpBuf;
+        v92 = 3;
+        v90 = pTmpBuf;
+        v88 = v106;
+        v86 = 0;
+        v85 = 0;
+        v84 = &v104;
+LABEL_46:
+        v40 = pFontArrus->CalcTextHeight(v21, v84, v85, v86);
+        return (POINT *)v104.DrawTitleText(pFontArrus, v3, (174 - v40) / 2 + 138, v88, v90, v92);
+      }
+    }
+    pRenderer->DrawTextureIndexed(8u, 8u, dword_F8B164);
+    v3 = 0;
+    v114 = 0;
+    if ( dword_F8B19C == 2 )
+    {
+      do
+      {
+        if ( pParty->field_777C[9 * (v114 + 12 * (unsigned int)ptr_507BC0->ptr_1C)] )
+        {
+          v46 = dword_F8B168[v114];
+          v47 = 152 - v46->uTextureHeight;
+          if ( (signed int)v47 < 1 )
+            v47 = 0;
+          v48 = 75 * v114 - v46->uTextureWidth / 2 + 40;
+          if ( v114 )
+          {
+            if ( v114 == 5 )
+            {
+              v49 = dword_F8B168[5]->uTextureWidth;
+              if ( (signed int)v48 > 457 - v49 )
+                v48 = 457 - v49;
+            }
+          }
+          else
+          {
+            if ( (signed int)v48 < 18 )
+              v48 = 18;
+          }
+          pRenderer->DrawTextureTransparent(v48, v47, v46);
+          sub_40F92A(&pRenderer->pActiveZBuffer[v48 + 640 * v47], dword_F8B168[v114], v114 + 1);
+        }
+        ++v114;
+      }
+      while ( v114 < 6 );
+      v114 = 0;
+      do
+      {
+        if ( pParty->field_777C[9 * (v114 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 54] )
+        {
+          v50 = dword_F8B168[v114 + 6];
+          v51 = 308 - v50->uTextureHeight;
+          if ( (signed int)v51 < 1 )
+            v51 = 0;
+          v52 = 75 * v114 - v50->uTextureWidth / 2 + 40;
+          if ( v114 )
+          {
+            if ( v114 == 5 )
+            {
+              v53 = dword_F8B168[11]->uTextureWidth;
+              if ( (signed int)v52 > 457 - v53 )
+                v52 = 457 - v53;
+            }
+          }
+          else
+          {
+            if ( (signed int)v52 < 18 )
+              v52 = 18;
+          }
+          pRenderer->DrawTextureTransparent(v52, v51, v50);
+          sub_40F92A(&pRenderer->pActiveZBuffer[v52 + 640 * v51], dword_F8B168[v114 + 6], v114 + 7);
+        }
+        ++v114;
+      }
+      while ( v114 < 6 );
+    }
+    else
+    {
+      do
+      {
+        if ( pParty->field_C59C[9 * (v114 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] )
+        {
+          v54 = dword_F8B168[v114];
+          v55 = 152 - v54->uTextureHeight;
+          if ( (signed int)v55 < 1 )
+            v55 = 0;
+          v56 = 75 * v114 - v54->uTextureWidth / 2 + 40;
+          if ( v114 )
+          {
+            if ( v114 == 5 )
+            {
+              v57 = dword_F8B168[5]->uTextureWidth;
+              if ( (signed int)v56 > 457 - v57 )
+                v56 = 457 - v57;
+            }
+          }
+          else
+          {
+            if ( (signed int)v56 < 18 )
+              v56 = 18;
+          }
+          pRenderer->DrawTextureTransparent(v56, v55, v54);
+          sub_40F92A(&pRenderer->pActiveZBuffer[v56 + 640 * v55], dword_F8B168[v114], v114 + 1);
+        }
+        ++v114;
+      }
+      while ( v114 < 6 );
+      v114 = 0;
+      do
+      {
+        if ( pParty->field_C59C[9 * (v114 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 778] )
+        {
+          v58 = dword_F8B168[v114 + 6];
+          v59 = 308 - v58->uTextureHeight;
+          if ( (signed int)v59 < 1 )
+            v59 = 0;
+          v60 = 75 * v114 - v58->uTextureWidth / 2 + 40;
+          if ( v114 )
+          {
+            if ( v114 == 5 )
+            {
+              v61 = dword_F8B168[11]->uTextureWidth;
+              if ( (signed int)v60 > 457 - v61 )
+                v60 = 457 - v61;
+            }
+          }
+          else
+          {
+            if ( (signed int)v60 < 18 )
+              v60 = 18;
+          }
+          pRenderer->DrawTextureTransparent(v60, v59, v58);
+          sub_40F92A(&pRenderer->pActiveZBuffer[v60 + 640 * v59], dword_F8B168[v114 + 6], v114 + 7);
+        }
+        ++v114;
+      }
+      while ( v114 < 6 );
+    }
+    result = (POINT *)sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+    if ( result )
+    {
+      v62 = 0;
+      v109 = 0;
+      if ( dword_F8B19C == 2 )
+      {
+        do
+        {
+          if ( pParty->field_777C[9 * (v62 + 12 * (unsigned int)ptr_507BC0->ptr_1C)] )
+            ++v109;
+          ++v62;
+        }
+        while ( v62 < 12 );
+      }
+      else
+      {
+        do
+        {
+          if ( pParty->field_C59C[9 * (v62 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] )
+            ++v109;
+          ++v62;
+        }
+        while ( v62 < 12 );
+      }
+      v63 = GetAsyncKeyState(17);
+      v64 = _this->CanSteal();
+      Str = (char *)v64;
+      if ( v63 && v64 )
+      {
+        v65 = pGlobalTXT_LocalizationStrings[185];
+      }
+      else
+      {
+        v65 = pGlobalTXT_LocalizationStrings[195];
+        if ( dword_F8B19C != 2 )
+          v65 = pGlobalTXT_LocalizationStrings[196];
+      }
+      sub_4B46A5(v65, 0);
+      if ( !v109 )
+        return (POINT *)v104._4B1854(
+                          __PAIR__(
+                            pParty->field_3C.field_50[2 * (unsigned int)ptr_507BC0->ptr_1C + 1],
+                            pParty->field_3C.field_50[2 * (unsigned int)ptr_507BC0->ptr_1C])
+                        - pParty->uTimePlayed);
+      v66 = pMouse->GetCursorPos(&v98);
+      result = (POINT *)(v66->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v96)->y]);
+      if ( pRenderer->pActiveZBuffer[(int)result] & 0xFFFF )
+      {
+        v67 = (pRenderer->pActiveZBuffer[(int)result] & 0xFFFF) - 1;
+        v109 = v67;
+        v68 = (int)ptr_507BC0->ptr_1C;
+        v69 = 9 * (v67 + 12 * v68);
+        v70 = (ItemGen *)&pParty->field_777C[v69];
+        if ( dword_F8B19C != 2 )
+          v70 = (ItemGen *)&pParty->field_C59C[v69 + 724];
+        if ( !v63 || !Str )
+        {
+          v93 = 0;
+          v91 = 2;
+          v89 = ptr_507BC0->ptr_1C;
+          v87 = v70;
+          v113 = uActiveCharacter - 1;
+          v71 = _this->_490EEE(v70, 4, v68, 2);
+          v39 = v113;
+          v38 = (char *)pMerchantsBuyPhrases[v71];
+          goto LABEL_45;
+        }
+        v38 = pGlobalTXT_LocalizationStrings[181];
+        v93 = 0;
+        v91 = 2;
+        v89 = ptr_507BC0->ptr_1C;
+        v87 = v70;
+        goto LABEL_44;
+      }
+    }
+  }
+  return result;
+}
+
+
+//----- (004BA928) --------------------------------------------------------
+void __cdecl sub_4BA928()
+{
+  Player *v0; // ebx@1
+  signed int v1; // esi@8
+  unsigned int v2; // eax@10
+  ItemGen *v3; // eax@11
+  unsigned __int8 v4; // dl@12
+  char *v5; // ecx@12
+  char *v6; // eax@13
+  int v7; // ST08_4@15
+  int v8; // eax@15
+  signed int v9; // esi@17
+  unsigned int v10; // eax@19
+  char *v11; // edi@19
+  int v12; // ST08_4@20
+  int v13; // eax@20
+  unsigned __int8 v14; // dl@20
+  char *v15; // ecx@20
+  char **v16; // edi@22
+  int v17; // ebx@22
+  char **v18; // esi@22
+  int v19; // eax@23
+  GUIWindow *v20; // ecx@24
+  int v21; // eax@24
+  int v22; // edx@24
+  int v23; // ebx@24
+  unsigned __int8 v24; // sf@24
+  GUIButton *v25; // eax@26
+  GUIButton *v26; // esi@26
+  int v27; // eax@26
+  unsigned int v28; // ecx@26
+  Player *v29; // edx@26
+  unsigned __int16 v30; // ax@26
+  signed int v31; // esi@31
+  unsigned int v32; // eax@33
+  int v33; // eax@34
+  int v34; // ST08_4@35
+  int v35; // eax@35
+  char *v36; // edx@36
+  GUIWindow *v37; // edi@42
+  signed int v38; // esi@42
+  unsigned int v39; // esi@44
+  int v40; // eax@44
+  unsigned int v41; // eax@45
+  int v42; // eax@47
+  int v43; // ecx@52
+  GUIButton *v44; // eax@54
+  GUIButton *v45; // esi@54
+  int v46; // eax@54
+  char *v47; // eax@56
+  int v48; // eax@56
+  unsigned int v49; // ecx@56
+  int v50; // edx@56
+  int v51; // eax@56
+  unsigned __int16 v52; // ax@56
+  int v53; // eax@60
+  int v54; // eax@60
+  signed int v55; // ebx@65
+  Texture *v56; // eax@67
+  unsigned int v57; // edi@68
+  Texture *v58; // ST1C_4@68
+  int v59; // eax@68
+  int v60; // edi@69
+  signed int v61; // ebx@73
+  Texture *v62; // eax@75
+  int v63; // edi@76
+  Texture *v64; // ST1C_4@76
+  unsigned int v65; // ST18_4@76
+  int v66; // eax@76
+  int v67; // edi@77
+  signed int v68; // ecx@81
+  SHORT v69; // bx@89
+  bool v70; // eax@89
+  const char *v71; // ecx@91
+  void *v72; // eax@95
+  POINT *v73; // esi@97
+  int v74; // ecx@97
+  int v75; // eax@98
+  int v76; // ecx@98
+  ItemGen *v77; // ecx@99
+  unsigned __int8 v78; // bl@104
+  char **v79; // edi@105
+  int v80; // ebx@105
+  char **v81; // esi@105
+  int v82; // eax@106
+  GUIWindow *v83; // ecx@107
+  int v84; // eax@107
+  int v85; // edx@107
+  int v86; // ebx@107
+  GUIButton *v87; // eax@109
+  GUIButton *v88; // esi@109
+  int v89; // eax@109
+  unsigned int v90; // ecx@109
+  int v91; // edx@109
+  unsigned __int16 v92; // ax@109
+  signed int v93; // edx@114
+  POINT *v94; // edi@120
+  __int32 v95; // ecx@120
+  void *v96; // ST14_4@122
+  unsigned __int8 v97; // bl@122
+  ItemGen *v98; // ST10_4@122
+  int v99; // eax@122
+  char *v100; // eax@122
+  const char *v101; // ST18_4@122
+  unsigned __int16 v102; // ST14_2@122
+  int v103; // eax@122
+  signed int v104; // edi@123
+  Texture *v105; // eax@125
+  int v106; // ebx@126
+  Texture *v107; // ST1C_4@126
+  unsigned int v108; // ST18_4@126
+  int v109; // eax@126
+  int v110; // ebx@127
+  GUIWindow *v111; // [sp-18h] [bp-11Ch]@36
+  unsigned int v112; // [sp-14h] [bp-118h]@13
+  int v113; // [sp-14h] [bp-118h]@36
+  ItemGen *v114; // [sp-10h] [bp-114h]@12
+  unsigned int v115; // [sp-10h] [bp-114h]@13
+  ItemGen *v116; // [sp-10h] [bp-114h]@20
+  int v117; // [sp-10h] [bp-114h]@36
+  void *v118; // [sp-Ch] [bp-110h]@12
+  unsigned __int16 v119; // [sp-Ch] [bp-110h]@13
+  void *v120; // [sp-Ch] [bp-110h]@20
+  char *v121; // [sp-8h] [bp-10Ch]@13
+  int v122; // [sp-8h] [bp-10Ch]@20
+  unsigned int v123; // [sp-4h] [bp-108h]@13
+  __int64 *v124; // [sp-4h] [bp-108h]@20
+  int v125; // [sp-4h] [bp-108h]@68
+  int v126; // [sp-4h] [bp-108h]@76
+  int v127; // [sp-4h] [bp-108h]@126
+  POINT v128; // [sp+Ch] [bp-F8h]@8
+  POINT v129; // [sp+14h] [bp-F0h]@18
+  char v130; // [sp+1Ch] [bp-E8h]@120
+  POINT a2; // [sp+24h] [bp-E0h]@8
+  POINT v132; // [sp+2Ch] [bp-D8h]@120
+  POINT v133; // [sp+34h] [bp-D0h]@17
+  char v134; // [sp+3Ch] [bp-C8h]@97
+  POINT v135; // [sp+44h] [bp-C0h]@31
+  POINT v136; // [sp+4Ch] [bp-B8h]@97
+  POINT v137; // [sp+54h] [bp-B0h]@17
+  POINT v138; // [sp+5Ch] [bp-A8h]@32
+  POINT v139; // [sp+64h] [bp-A0h]@17
+  POINT v140; // [sp+6Ch] [bp-98h]@31
+  POINT v141; // [sp+74h] [bp-90h]@8
+  POINT v142; // [sp+7Ch] [bp-88h]@31
+  POINT v143; // [sp+84h] [bp-80h]@9
+  GUIWindow v144; // [sp+8Ch] [bp-78h]@1
+  char *Str; // [sp+E0h] [bp-24h]@56
+  int v146; // [sp+E4h] [bp-20h]@24
+  int v147; // [sp+E8h] [bp-1Ch]@1
+  int v148; // [sp+ECh] [bp-18h]@1
+  __int32 v149; // [sp+F0h] [bp-14h]@8
+  Player *_this; // [sp+F4h] [bp-10h]@1
+  unsigned __int8 uPlayerID; // [sp+FBh] [bp-9h]@15
+  int v152; // [sp+FCh] [bp-8h]@24
+  int v153; // [sp+100h] [bp-4h]@44
+
+  v0 = pPlayers[uActiveCharacter];
+  _this = pPlayers[uActiveCharacter];
+  memcpy(&v144, ptr_507BC0, sizeof(v144));
+  v144.uFrameX = 483;
+  v144.uFrameWidth = 148;
+  v144.uFrameZ = 334;
+  v148 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v147 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  if ( dword_F8B19C > 5 )
+  {
+    if ( dword_F8B19C == 6 )
+    {
+      pRenderer->DrawTextureIndexed(8u, 8u, dword_F8B164);
+      sub_4B46A5(pGlobalTXT_LocalizationStrings[195], 0);
+      if ( !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+        return;
+      v149 = 0;
+      v93 = 0;
+      do
+      {
+        if ( pParty->field_C59C[9 * (v93 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] )
+          ++v149;
+        ++v93;
+      }
+      while ( v93 < 8 );
+      if ( v149 )
+      {
+        v94 = pMouse->GetCursorPos(&v132);
+        v149 = pRenderer->pActiveZBuffer[v94->x + pSRZBufferLineOffsets[pMouse->GetCursorPos((POINT *)&v130)->y]];
+        v95 = v149;
+        if ( v149 && v149 != -65536 )
+        {
+          --v149;
+          v96 = ptr_507BC0->ptr_1C;
+          v97 = uActiveCharacter - 1;
+          v98 = (ItemGen *)&pParty->field_C59C[9 * (v95 - 1 + 12 * (int)v96) + 724];
+          v99 = _this->_490EEE(
+                  (ItemGen *)&pParty->field_C59C[9 * (v95 - 1 + 12 * (int)v96) + 724],
+                  2,
+                  (int)ptr_507BC0->ptr_1C,
+                  2);
+          v100 = sub_495461((char *)pMerchantsBuyPhrases[v99], v97, v98, (char *)v96, 2, 0);
+          v101 = v100;
+          v102 = v148;
+          v103 = pFontArrus->CalcTextHeight(v100, &v144, 0, 0);
+          v144.DrawTitleText(pFontArrus, 0, (174 - v103) / 2 + 138, v102, v101, 3u);
+        }
+        v104 = 0;
+        v153 = 0;
+        do
+        {
+          if ( pParty->field_C59C[9 * (v104 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] )
+          {
+            v105 = dword_F8B168[v104];
+            if ( v104 >= 4 )
+            {
+              v110 = 90 - ((signed int)v105->uTextureWidth >> 1);
+              pRenderer->DrawTextureTransparent(v153 + v110 - 420, 0x7Eu, dword_F8B168[v104]);
+              v127 = v104 + 1;
+              v109 = v153 + v110 + 80220;
+            }
+            else
+            {
+              v106 = 98 - v105->uTextureHeight;
+              v107 = dword_F8B168[v104];
+              v108 = 98 - v105->uTextureHeight;
+              v152 = 86 - ((signed int)v105->uTextureWidth >> 1);
+              pRenderer->DrawTextureTransparent(v152 + v153, v108, v107);
+              v127 = v104 + 1;
+              v109 = v152 + v153 + 640 * v106;
+            }
+            ZBuffer_DoFill(&pRenderer->pActiveZBuffer[v109], dword_F8B168[v104], v127);
+          }
+          v153 += 105;
+          ++v104;
+        }
+        while ( v104 < 8 );
+        return;
+      }
+      v72 = ptr_507BC0->ptr_1C;
+      goto LABEL_96;
+    }
+    if ( dword_F8B19C == 94 )
+    {
+      draw_leather();
+      CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+      v79 = pShopOptions;
+      pShopOptions[0] = pGlobalTXT_LocalizationStrings[200];
+      pShopOptions[1] = pGlobalTXT_LocalizationStrings[113];
+      pShopOptions[2] = pGlobalTXT_LocalizationStrings[179];
+      v80 = 0;
+      v81 = pShopOptions;
+      do
+      {
+        v82 = pFontArrus->CalcTextHeight(*v81, &v144, 0, 0);
+        ++v81;
+        v80 += v82;
+      }
+      while ( (signed int)v81 < (signed int)&pShopOptions[3] );
+      v83 = pDialogueWindow;
+      v152 = (174 - v80) / 3;
+      v84 = pDialogueWindow->pStartingPosActiveItem;
+      v85 = v84 + pDialogueWindow->pNumPresenceButton;
+      v86 = (3 * (58 - v152) - v80) / 2 - v152 / 2 + 138;
+      v24 = -pDialogueWindow->pNumPresenceButton < 0;
+      _this = (Player *)pDialogueWindow->pStartingPosActiveItem;
+      if ( v24 ^ __OFSUB__(v84, v85) )
+      {
+        v153 = 2;
+        do
+        {
+          v87 = v83->GetControl((unsigned int)_this);
+          v88 = v87;
+          v87->uY = v152 + v86;
+          v89 = pFontArrus->CalcTextHeight(*v79, &v144, 0, 0);
+          v90 = v88->uY;
+          v91 = v153;
+          v88->uHeight = v89;
+          v86 = v90 + v89 - 1;
+          v88->uW = v86;
+          v92 = v147;
+          if ( pDialogueWindow->pCurrentPosActiveItem != v91 )
+            v92 = v148;
+          v144.DrawTitleText(pFontArrus, 0, v90, v92, *v79, 3u);
+          v83 = pDialogueWindow;
+          ++v153;
+          ++v79;
+          _this = (Player *)((char *)_this + 1);
+        }
+        while ( (signed int)_this < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem );
+      }
+      return;
+    }
+    if ( dword_F8B19C != 95 )
+    {
+      if ( dword_F8B19C != 96 || !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+        return;
+      v152 = 0;
+      v37 = pDialogueWindow;
+      //v38 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (unsigned int)ptr_507BC0->ptr_1C] * 500.0);
+      v38 = (signed __int64)(p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].flt_24 * 500.0);
+      _this = (Player *)(v38 * (100 - v0->GetMerchant()) / 100);
+      if ( (signed int)_this < v38 / 3 )
+        _this = (Player *)(v38 / 3);
+      v39 = v37->pStartingPosActiveItem;
+      v40 = v37->pNumPresenceButton;
+      v153 = 0;
+      if ( (signed int)v39 < (signed int)(v39 + v40) )
+      {
+        do
+        {
+          v41 = v37->GetControl(v39)->uControlParam - 36;
+          if ( byte_4ED970_skill_learn_ability_by_class_table[v0->uClass][v41] && !v0->pActiveSkills[v41] )
+          {
+            v42 = pFontArrus->CalcTextHeight(pSkillNames[v41], &v144, 0, 0);
+            v152 += v42;
+            ++v153;
+          }
+          ++v39;
+        }
+        while ( (signed int)v39 < v37->pNumPresenceButton + v37->pStartingPosActiveItem );
+        if ( v153 )
+        {
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], _this);
+          v144.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+          _this = (Player *)((149 - v152) / v153);
+          if ( (149 - v152) / v153 > 32 )
+            _this = (Player *)32;
+          v43 = (149 - v153 * (signed int)_this - v152) / 2 - (signed int)_this / 2 + 162;
+          v152 = v37->pStartingPosActiveItem;
+          v146 = v43;
+          if ( v152 < v152 + v37->pNumPresenceButton )
+          {
+            v153 = 2;
+            do
+            {
+              v44 = v37->GetControl(v152);
+              v45 = v44;
+              v46 = v44->uControlParam - 36;
+              if ( !byte_4ED970_skill_learn_ability_by_class_table[v0->uClass][v46] || v0->pActiveSkills[v46] )
+              {
+                v45->uW = 0;
+                v45->uHeight = 0;
+                v45->uY = 0;
+              }
+              else
+              {
+                v47 = pSkillNames[v46];
+                v45->uY = (unsigned int)((char *)_this + v146);
+                Str = v47;
+                v48 = pFontArrus->CalcTextHeight(v47, &v144, 0, 0);
+                v49 = v45->uY;
+                v50 = v153;
+                v45->uHeight = v48;
+                v51 = v49 + v48 - 1;
+                v45->uW = v51;
+                v146 = v51;
+                v52 = v147;
+                if ( pDialogueWindow->pCurrentPosActiveItem != v50 )
+                  v52 = v148;
+                v144.DrawTitleText(pFontArrus, 0, v49, v52, Str, 3u);
+              }
+              v53 = v37->pStartingPosActiveItem;
+              ++v152;
+              v54 = v37->pNumPresenceButton + v53;
+              ++v153;
+            }
+            while ( v152 < v54 );
+          }
+          return;
+        }
+      }
+      sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], v0->pName, pClassNames[v0->uClass]);
+      strcat(pTmpBuf, "\n \n");
+      strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);
+      v11 = 0;
+      v36 = pTmpBuf;
+      v123 = 3;
+      v121 = pTmpBuf;
+      v119 = v147;
+      v117 = 0;
+      v113 = 0;
+      v111 = &v144;
+LABEL_63:
+      v115 = (174 - pFontArrus->CalcTextHeight(v36, v111, v113, v117)) / 2 + 138;
+      v112 = (unsigned int)v11;
+LABEL_14:
+      v144.DrawTitleText(pFontArrus, v112, v115, v119, v121, v123);
+      return;
+    }
+LABEL_64:
+    pRenderer->DrawTextureIndexed(8u, 8u, dword_F8B164);
+    if ( dword_F8B19C == 2 )
+    {
+      v55 = 0;
+      v153 = 0;
+      do
+      {
+        if ( pParty->field_777C[9 * (v55 + 12 * (unsigned int)ptr_507BC0->ptr_1C)] )
+        {
+          v56 = dword_F8B168[v55];
+          if ( v55 >= 4 )
+          {
+            v60 = 90 - ((signed int)v56->uTextureWidth >> 1);
+            pRenderer->DrawTextureTransparent(v60 + v153 - 420, 0x7Eu, dword_F8B168[v55]);
+            v125 = v55 + 1;
+            v59 = v60 + v153 + 80220;
+          }
+          else
+          {
+            v57 = 98 - v56->uTextureHeight;
+            v58 = dword_F8B168[v55];
+            v152 = 86 - ((signed int)v56->uTextureWidth >> 1);
+            pRenderer->DrawTextureTransparent(v153 + v152, v57, v58);
+            v125 = v55 + 1;
+            v59 = v153 + v152 + 640 * v57;
+          }
+          ZBuffer_DoFill(&pRenderer->pActiveZBuffer[v59], dword_F8B168[v55], v125);
+        }
+        v153 += 105;
+        ++v55;
+      }
+      while ( v55 < 8 );
+      v11 = 0;
+    }
+    else
+    {
+      v11 = 0;
+      v61 = 0;
+      v153 = 0;
+      do
+      {
+        if ( (char *)pParty->field_C59C[9 * (v61 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] != v11 )
+        {
+          v62 = dword_F8B168[v61];
+          if ( v61 >= 4 )
+          {
+            v67 = 90 - ((signed int)v62->uTextureWidth >> 1);
+            pRenderer->DrawTextureTransparent(v153 + v67 - 420, 0x7Eu, dword_F8B168[v61]);
+            v126 = v61 + 1;
+            v66 = v153 + v67 + 80220;
+          }
+          else
+          {
+            v63 = 98 - v62->uTextureHeight;
+            v64 = dword_F8B168[v61];
+            v65 = 98 - v62->uTextureHeight;
+            v152 = 86 - ((signed int)v62->uTextureWidth >> 1);
+            pRenderer->DrawTextureTransparent(v152 + v153, v65, v64);
+            v126 = v61 + 1;
+            v66 = v152 + v153 + 640 * v63;
+          }
+          ZBuffer_DoFill(&pRenderer->pActiveZBuffer[v66], dword_F8B168[v61], v126);
+          v11 = 0;
+        }
+        v153 += 105;
+        ++v61;
+      }
+      while ( v61 < 8 );
+    }
+    if ( !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+      return;
+    v68 = 0;
+    v149 = (__int32)v11;
+    if ( dword_F8B19C == 2 )
+    {
+      do
+      {
+        if ( (char *)pParty->field_777C[9 * (v68 + 12 * (unsigned int)ptr_507BC0->ptr_1C)] != v11 )
+          ++v149;
+        ++v68;
+      }
+      while ( v68 < 6 );
+    }
+    else
+    {
+      do
+      {
+        if ( (char *)pParty->field_C59C[9 * (v68 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] != v11 )
+          ++v149;
+        ++v68;
+      }
+      while ( v68 < 6 );
+    }
+    v69 = GetAsyncKeyState(17);
+    v70 = _this->CanSteal();
+    Str = (char *)v70;
+    if ( v69 == (short)v11 || (char *)v70 == v11 )
+    {
+      v71 = pGlobalTXT_LocalizationStrings[195];
+      if ( dword_F8B19C != 2 )
+        v71 = pGlobalTXT_LocalizationStrings[196];
+    }
+    else
+    {
+      v71 = pGlobalTXT_LocalizationStrings[185];
+    }
+    sub_4B46A5(v71, 0);
+    if ( (char *)v149 != v11 )
+    {
+      v73 = pMouse->GetCursorPos(&v136);
+      v74 = pRenderer->pActiveZBuffer[v73->x + pSRZBufferLineOffsets[pMouse->GetCursorPos((POINT *)&v134)->y]] & 0xFFFF;
+      if ( !v74 )
+        return;
+      v149 = v74 - 1;
+      v75 = (int)ptr_507BC0->ptr_1C;
+      v76 = 9 * (v74 - 1 + 12 * v75);
+      if ( dword_F8B19C == 2 )
+        v77 = (ItemGen *)&pParty->field_777C[v76];
+      else
+        v77 = (ItemGen *)&pParty->field_C59C[v76 + 724];
+      if ( v69 == (short)v11 || Str == v11 )
+      {
+        v124 = (__int64 *)v11;
+        v122 = 2;
+        v120 = ptr_507BC0->ptr_1C;
+        v116 = v77;
+        v78 = uActiveCharacter - 1;
+        v15 = (char *)pMerchantsBuyPhrases[_this->_490EEE(v77, 2, v75, 2)];
+        v14 = v78;
+      }
+      else
+      {
+        v124 = (__int64 *)v11;
+        v122 = 2;
+        v120 = ptr_507BC0->ptr_1C;
+        v116 = v77;
+        v15 = pGlobalTXT_LocalizationStrings[181];
+        v14 = uActiveCharacter - 1;
+      }
+LABEL_36:
+      v36 = sub_495461(v15, v14, v116, (char *)v120, v122, v124);
+      v123 = 3;
+      v121 = v36;
+      v119 = v148;
+      v117 = (int)v11;
+      v113 = (int)v11;
+      v111 = &v144;
+      goto LABEL_63;
+    }
+    v72 = ptr_507BC0->ptr_1C;
+LABEL_96:
+    v144._4B1854(
+      __PAIR__(pParty->field_3C.field_50[2 * (int)v72 + 1], pParty->field_3C.field_50[2 * (int)v72])
+    - pParty->uTimePlayed);
+    return;
+  }
+  if ( dword_F8B19C == 5 )
+  {
+    draw_leather();
+    CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+    sub_4B46A5(pGlobalTXT_LocalizationStrings[198], 0);
+    if ( !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win()
+      || (v31 = pMouse->GetCursorPos(&v135)->x - 14,
+          v149 = (v31 >> 5) + 14 * ((pMouse->GetCursorPos(&v142)->y - 17) >> 5),
+          pMouse->GetCursorPos(&v140)->x <= 13)
+      || pMouse->GetCursorPos(&v138)->x >= 462
+      || (v32 = v0->GetItemIDAtInventoryIndex((int *)&v149), v11 = 0, !v32)
+      || (v33 = 9 * v32, !(v0->field_1F5[4 * v33 + 15] & 2)) )
+      return;
+    v124 = 0;
+    v122 = 5;
+    v120 = ptr_507BC0->ptr_1C;
+    v116 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * v33 + 5];
+    v34 = (int)ptr_507BC0->ptr_1C;
+    uPlayerID = uActiveCharacter - 1;
+    v35 = v0->_490EEE((ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * v33 + 5], 2, v34, 5);
+    v14 = uPlayerID;
+    v15 = (char *)pMerchantsRepairPhrases[v35];
+    goto LABEL_36;
+  }
+  if ( dword_F8B19C == 1 )
+  {
+    if ( sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+    {
+      v16 = pShopOptions;
+      pShopOptions[0] = pGlobalTXT_LocalizationStrings[134];
+      pShopOptions[1] = pGlobalTXT_LocalizationStrings[152];
+      pShopOptions[2] = pGlobalTXT_LocalizationStrings[159];
+      v17 = 0;
+      pShopOptions[3] = pGlobalTXT_LocalizationStrings[160];
+      v18 = pShopOptions;
+      do
+      {
+        v19 = pFontArrus->CalcTextHeight(*v18, &v144, 0, 0);
+        ++v18;
+        v17 += v19;
+      }
+      while ( (signed int)v18 < (signed int)&unk_F8B1C8 );
+      v20 = pDialogueWindow;
+      v146 = (174 - v17) / 4;
+      v21 = pDialogueWindow->pStartingPosActiveItem;
+      v22 = v21 + pDialogueWindow->pNumPresenceButton;
+      v23 = (174 - 4 * (174 - v17) / 4 - v17) / 2 - (174 - v17) / 4 / 2 + 138;
+      v24 = -pDialogueWindow->pNumPresenceButton < 0;
+      v152 = pDialogueWindow->pStartingPosActiveItem;
+      if ( v24 ^ __OFSUB__(v21, v22) )
+      {
+        _this = (Player *)2;
+        do
+        {
+          v25 = v20->GetControl(v152);
+          v26 = v25;
+          v25->uY = v146 + v23;
+          v27 = pFontArrus->CalcTextHeight(*v16, &v144, 0, 0);
+          v28 = v26->uY;
+          v29 = _this;
+          v26->uHeight = v27;
+          v23 = v28 + v27 - 1;
+          v26->uW = v23;
+          v30 = v147;
+          if ( (Player *)pDialogueWindow->pCurrentPosActiveItem != v29 )
+            v30 = v148;
+          v144.DrawTitleText(pFontArrus, 0, v28, v30, *v16, 3u);
+          v20 = pDialogueWindow;
+          _this = (Player *)((char *)_this + 1);
+          ++v16;
+          ++v152;
+        }
+        while ( v152 < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem );
+      }
+    }
+    return;
+  }
+  if ( dword_F8B19C == 2 )
+    goto LABEL_64;
+  if ( dword_F8B19C == 3 )
+  {
+    draw_leather();
+    CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+    sub_4B46A5(pGlobalTXT_LocalizationStrings[199], 0);
+    if ( !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win()
+      || (v9 = pMouse->GetCursorPos(&v139)->x - 14,
+          v149 = (v9 >> 5) + 14 * ((pMouse->GetCursorPos(&v133)->y - 17) >> 5),
+          pMouse->GetCursorPos(&v137)->x <= 13)
+      || pMouse->GetCursorPos(&v129)->x >= 462
+      || (v10 = v0->GetItemIDAtInventoryIndex((int *)&v149), v11 = 0, !v10) )
+      return;
+    v124 = 0;
+    v122 = 3;
+    v120 = ptr_507BC0->ptr_1C;
+    v116 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5];
+    v12 = (int)ptr_507BC0->ptr_1C;
+    uPlayerID = uActiveCharacter - 1;
+    v13 = v0->_490EEE(v116, 2, v12, 3);
+    v14 = uPlayerID;
+    v15 = (char *)pMerchantsSellPhrases[v13];
+    goto LABEL_36;
+  }
+  if ( dword_F8B19C == 4 )
+  {
+    draw_leather();
+    CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+    sub_4B46A5(pGlobalTXT_LocalizationStrings[197], 0);
+    if ( sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+    {
+      v1 = pMouse->GetCursorPos(&a2)->x - 14;
+      v149 = (v1 >> 5) + 14 * ((pMouse->GetCursorPos(&v128)->y - 17) >> 5);
+      if ( pMouse->GetCursorPos(&v141)->x > 13 )
+      {
+        if ( pMouse->GetCursorPos(&v143)->x < 462 )
+        {
+          v2 = v0->GetItemIDAtInventoryIndex((int *)&v149);
+          if ( v2 )
+          {
+            v3 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
+            if ( v3->uAttributes & 1 )
+            {
+              v118 = ptr_507BC0->ptr_1C;
+              v4 = uActiveCharacter - 1;
+              v5 = "%24";
+              v114 = v3;
+            }
+            else
+            {
+              v118 = ptr_507BC0->ptr_1C;
+              v114 = v3;
+              v7 = (int)ptr_507BC0->ptr_1C;
+              uPlayerID = uActiveCharacter - 1;
+              v8 = v0->_490EEE(v3, 2, v7, 4);
+              v4 = uPlayerID;
+              v5 = (char *)pMerchantsIdentifyPhrases[v8];
+            }
+            v6 = sub_495461(v5, v4, v114, (char *)v118, 4, 0);
+            v123 = 3;
+            v121 = v6;
+            v119 = v148;
+            v115 = (174 - pFontArrus->CalcTextHeight(v6, &v144, 0, 0)) / 2 + 138;
+            v112 = 0;
+            goto LABEL_14;
+          }
+        }
+      }
+    }
+  }
+}
+
+//----- (004BB756) --------------------------------------------------------
+signed int __fastcall sub_4BB756(signed int a1)
+{
+  unsigned int v1; // esi@8
+  unsigned int v3; // ecx@10
+  char *v4; // esi@15
+  int v5; // ebx@16
+  int v6; // ST38_4@16
+  char *v7; // esi@18
+  int v8; // ebx@19
+  int v9; // ST30_4@19
+  int v10; // ST44_4@19
+  int v11; // ST48_4@19
+  int v12; // ST4C_4@19
+  int v13; // ST50_4@19
+  int v14; // ST3C_4@19
+  int v15; // ST40_4@19
+  int v16; // ST34_4@19
+  int v17; // ST38_4@19
+  Player *v18; // esi@21
+  int v19; // eax@26
+  int v20; // eax@39
+  SoundID v21; // [sp-20h] [bp-54h]@25
+  signed int v22; // [sp-1Ch] [bp-50h]@25
+  unsigned int v23; // [sp-18h] [bp-4Ch]@25
+  signed int v24; // [sp-14h] [bp-48h]@25
+  signed int v25; // [sp-10h] [bp-44h]@25
+  int v26; // [sp-10h] [bp-44h]@32
+  int v27; // [sp-Ch] [bp-40h]@25
+  unsigned int v28; // [sp-Ch] [bp-40h]@32
+  unsigned int v29; // [sp-8h] [bp-3Ch]@25
+  __int16 v30; // [sp-8h] [bp-3Ch]@32
+  int v31; // [sp-4h] [bp-38h]@25
+  int v32; // [sp-4h] [bp-38h]@32
+
+  if ( a1 > 39 )
+  {
+    if ( a1 != 40 )
+    {
+      if ( a1 == 41 )
+      {
+        if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+        {
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+          *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+          ++pMessageQueue_50CBD0->uNumMessages;
+        }
+        dword_50C9DC = 195;
+        ptr_50C9E0 = GetNPCData(uDialogue_SpeakingActorNPC_ID);
+        return 0;
+      }
+      if ( a1 == 42 )
+      {
+        v32 = 0;
+        v30 = 0;
+        v28 = 133;
+        v26 = 46;
+      }
+      else
+      {
+        if ( a1 == 43 )
+        {
+          v32 = 0;
+          v30 = 0;
+          v28 = 133;
+          v26 = 51;
+        }
+        else
+        {
+          if ( a1 != 52 )
+            return 0;
+          v32 = 0;
+          v30 = 0;
+          v28 = 133;
+          v26 = 86;
+        }
+      }
+      _42777D_CastSpell_UseWand_ShootArrow(v26, 0, v28, v30, v32);
+      return 0;
+    }
+    v20 = pOtherOverlayList->_4418B1(10005, 201, 0, 65536);
+    pParty->pPartyBuffs[18].Apply(pParty->uTimePlayed + 46080, 3u, 0, v20, 0);
+    pParty->pPartyBuffs[18].uFlags |= 1u;
+    v31 = 0;
+    v29 = 0;
+    v27 = 0;
+    v25 = 0;
+    v24 = -1;
+    v23 = 0;
+    v22 = 0;
+    v21 = (SoundID)12040;
+LABEL_40:
+    pAudioPlayer->PlaySound(v21, v22, v23, v24, v25, v27, v29, v31);
+    return 0;
+  }
+  if ( a1 == 39 )
+  {
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    {
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[494], 2u);
+      v31 = 0;
+      v29 = 0;
+      v27 = 0;
+      v25 = 0;
+      v24 = -1;
+      v23 = 0;
+      v22 = 0;
+      v21 = (SoundID)203;
+    }
+    else
+    {
+      v19 = pOtherOverlayList->_4418B1(10008, 203, 0, 65536);
+      pParty->pPartyBuffs[7].Apply(pParty->uTimePlayed + 30720, 3u, 1u, v19, 0);
+      pParty->pPartyBuffs[7].uFlags |= 1u;
+      v31 = 0;
+      v29 = 0;
+      v27 = 0;
+      v25 = 0;
+      v24 = -1;
+      v23 = 0;
+      v22 = 0;
+      v21 = (SoundID)11090;
+    }
+    goto LABEL_40;
+  }
+  if ( a1 == 10 )
+  {
+    v18 = pParty->pPlayers;
+    do
+    {
+      v18->sHealth = v18->GetMaxHealth();
+      ++v18;
+    }
+    while ( (signed int)v18 < (signed int)pParty->pHirelings );
+    return 0;
+  }
+  if ( a1 == 11 )
+  {
+    v7 = (char *)&pParty->pPlayers[0].pConditions[15];
+    do
+    {
+      v8 = *((int *)v7 - 2);
+      v9 = *((int *)v7 - 1);
+      v10 = *(int *)v7;
+      v11 = *((int *)v7 + 1);
+      v12 = *((int *)v7 + 2);
+      v13 = *((int *)v7 + 3);
+      v14 = *((int *)v7 + 8);
+      v15 = *((int *)v7 + 9);
+      v16 = *((int *)v7 + 4);
+      v17 = *((int *)v7 + 5);
+      memset(v7 - 120, 0, 0xA0u);
+      *((int *)v7 + 2) = v12;
+      *((int *)v7 + 3) = v13;
+      *(int *)v7 = v10;
+      *((int *)v7 + 1) = v11;
+      *((int *)v7 - 1) = v9;
+      *((int *)v7 + 8) = v14;
+      *((int *)v7 + 9) = v15;
+      *((int *)v7 + 4) = v16;
+      *((int *)v7 - 2) = v8;
+      *((int *)v7 + 5) = v17;
+      *((int *)v7 + 1585) = ((Player *)(v7 - 120))->GetMaxHealth();
+      v7 += 6972;
+    }
+    while ( (signed int)v7 < (signed int)&pParty->pHirelings[1].evtb );
+    return 0;
+  }
+  if ( a1 == 12 )
+  {
+    v4 = (char *)&pParty->pPlayers[0].pActiveSkills[8];
+    do
+    {
+      v5 = *((int *)v4 - 32);
+      v6 = *((int *)v4 - 31);
+      memset(v4 - 280, 0, 0xA0u);
+      *(int *)v4 = v5;
+      *((int *)v4 + 1) = v6;
+      *((int *)v4 + 1545) = ((Player *)(v4 - 280))->GetMaxHealth();
+      v4 += 6972;
+    }
+    while ( (signed int)v4 < (signed int)&pParty->field_777C[22] );
+    return 0;
+  }
+  if ( a1 == 33 )
+  {
+    v1 = 14;
+    if ( pParty->uNumFoodRations >= 0xE )
+      return 1;
+    v3 = 1;
+LABEL_13:
+    Party::GiveFood(v3);
+    if ( pParty->uNumFoodRations > v1 )
+      pParty->uNumFoodRations = v1;
+    return 0;
+  }
+  if ( a1 == 34 )
+  {
+    v1 = 14;
+    if ( pParty->uNumFoodRations >= 0xE )
+      return 1;
+    v3 = 2;
+    goto LABEL_13;
+  }
+  return 0;
+}
+// 50C9DC: using guessed type int dword_50C9DC;
+
+//----- (004BBA85) --------------------------------------------------------
+const char *sub_4BBA85_bounties()
+{
+  int v0; // edi@1
+  signed __int64 v1; // qax@2
+  int i; // eax@2
+  int v3; // edx@3
+  int v4; // edi@14
+  __int16 v5; // ax@14
+  char v6; // zf@14
+  Player *v7; // ebx@16
+  const char *result; // eax@19
+
+  uDialogueType = 83;
+  pDialogueWindow->Release();
+  pDialogueWindow = GUIWindow::Create(0, 0, 640, 350, WINDOW_MainMenu, 0, 0);
+  pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                 471u,
+                 445u,
+                 169u,
+                 35u,
+                 1,
+                 0,
+                 0x71u,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[34],// "Cancel"
+                 (Texture *)(uTextureID_506438 != -1 ? &pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                 0);
+  pDialogueWindow->CreateButton(0, 0, 0, 0, 1, 0, 0x51u, 0, 0, "", 0);
+  pDialogueWindow->CreateButton(480u, 160u, 140u, 30u, 1, 0, 0, 0x53u, 0, "", 0);
+  pDialogueWindow->_41D08F(1, 1, 0, 2);
+  dword_F8B19C = -1;
+  v0 = (int)((char *)ptr_507BC0->ptr_1C - 102);
+  if ( (signed __int64)__PAIR__(pParty->field_3C.field_0[2 * v0 + 1], pParty->field_3C.field_0[2 * v0]) < (signed __int64)pParty->uTimePlayed )
+  {
+    pParty->field_75A[v0] = 0;
+    v1 = (signed __int64)((double)(0x12750000 * (pParty->uCurrentMonth + 12i64 * pParty->uCurrentYear - 14015))
+                        * 0.033333335);
+    pParty->field_3C.field_0[2 * v0] = v1;
+    pParty->field_3C.field_0[2 * v0 + 1] = HIDWORD(v1);
+    for ( i = rand(); ; i = rand() )
+    {
+      v3 = i % 258 + 1;
+      pParty->field_750[v0] = v3;
+      if ( (unsigned __int16)v3 < 0x73u || (unsigned __int16)v3 > 0x84u )
+      {
+        if ( ((unsigned __int16)v3 < 0xEBu || (unsigned __int16)v3 > 0xFCu)
+          && ((unsigned __int16)v3 < 0x85u || (unsigned __int16)v3 > 0x96u)
+          && ((unsigned __int16)v3 < 0x97u || (unsigned __int16)v3 > 0xBAu)
+          && ((unsigned __int16)v3 < 0xC4u || (unsigned __int16)v3 > 0xC6u) )
+          break;
+      }
+    }
+  }
+  v4 = v0;
+  v5 = pParty->field_750[v4];
+  v6 = pParty->field_75A[v4] == 0;
+  word_F8B1A0 = pParty->field_750[v4];
+  if ( v6 )
+  {
+    v6 = v5 == 0;
+    result = pNPCTopics[351].pText;
+    if ( v6 )
+      result = pNPCTopics[353].pText;
+  }
+  else
+  {
+    if ( v5 )
+    {
+      party_finds_gold(100 * pMonsterStats->pInfos[(unsigned __int16)v5].uLevel, 0);
+      v7 = pParty->pPlayers;
+      do
+      {
+        v7->SetVariable(VAR_Award, 86);
+        ++v7;
+      }
+      while ( (signed int)v7 < (signed int)pParty->pHirelings );
+      pParty->uNumBountiesCollected += 100 * pMonsterStats->pInfos[pParty->field_750[v4]].uLevel;
+      pParty->field_750[v4] = 0;
+      pParty->field_75A[v4] = 0;
+    }
+    result = pNPCTopics[352].pText;
+  }
+  dword_F8B1A4 = (char *)result;
+  return result;
+}
+
+//----- (004BBCDD) --------------------------------------------------------
+void __cdecl sub_4BBCDD()
+{
+  signed int v0; // ebp@3
+  char *v1; // eax@4
+  __int16 v2; // cx@5
+  int v3; // esi@8
+  Player *v4; // esi@14
+  GUIButton *v5; // eax@18
+  GUIButton *v6; // esi@19
+  size_t v7; // [sp+10h] [bp-4h]@4
+
+  if ( pParty->field_7B5_in_arena_quest )
+  {
+    if ( pParty->field_7B5_in_arena_quest == -1 )
+    {
+      uDialogueType = 92;
+    }
+    else
+    {
+      v0 = 0;
+      if ( (signed int)uNumActors <= 0 )
+        goto LABEL_23;
+      v1 = (char *)&pActors[0].uAIState;
+      v7 = uNumActors;
+      do
+      {
+        v2 = *(short *)v1;
+        if ( *(short *)v1 == 5 || v2 == 11 || v2 == 19 || (v3 = *((int *)v1 + 159)) != 0 && (v3 & 7) == 4 )
+          ++v0;
+        v1 += 836;
+        --v7;
+      }
+      while ( v7 );
+      if ( v0 >= (signed int)uNumActors )
+      {
+LABEL_23:
+        uDialogueType = 91;
+        v4 = pParty->pPlayers;
+        ++*((char *)&pParty->field_75A[3] + (unsigned __int8)pParty->field_7B5_in_arena_quest + 1);
+        do
+        {
+          v4->SetVariable(VAR_Award, (unsigned __int8)pParty->field_7B5_in_arena_quest + 3);
+          ++v4;
+        }
+        while ( (signed int)v4 < (signed int)pParty->pHirelings );
+        party_finds_gold(dword_F8B1B4, 0);
+        pAudioPlayer->PlaySound((SoundID)14060, 0, 0, -1, 0, 0, 0, 0);
+        pParty->field_7B5_in_arena_quest = -1;
+      }
+      else
+      {
+        uDialogueType = 90;
+        pParty->vPosition.x = 3849;
+        pParty->vPosition.y = 5770;
+        pParty->vPosition.z = 1;
+        pParty->uFallStartY = 1;
+        pParty->sRotationY = 512;
+        pParty->sRotationX = 0;
+        pParty->uFallSpeed = 0;
+        pAudioPlayer->PlaySound((SoundID)14060, 0, 0, -1, 0, 0, 0, 0);
+      }
+    }
+  }
+  else
+  {
+    uDialogueType = 89;
+    v5 = pDialogueWindow->pControlsHead;
+    if ( v5 )
+    {
+      do
+      {
+        v6 = v5->pNext;
+        pAllocator->FreeChunk(v5);
+        v5 = v6;
+      }
+      while ( v6 );
+    }
+    pDialogueWindow->pControlsHead = 0;
+    pDialogueWindow->pControlsTail = 0;
+    pDialogueWindow->uNumControls = 0;
+    pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                   0x1D7u,
+                   0x1BDu,
+                   0xA9u,
+                   0x23u,
+                   1,
+                   0,
+                   0x71u,
+                   0,
+                   0,
+                   pGlobalTXT_LocalizationStrings[79],
+                   (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                   0);
+    pDialogueWindow->CreateButton(0x1E0u, 0xA0u, 0x8Cu, 0x1Eu, 1, 0, 0x88u, 0x55u, 0, "", 0);
+    pDialogueWindow->CreateButton(0x1E0u, 0xBEu, 0x8Cu, 0x1Eu, 1, 0, 0x88u, 0x56u, 0, "", 0);
+    pDialogueWindow->CreateButton(0x1E0u, 0xDCu, 0x8Cu, 0x1Eu, 1, 0, 0x88u, 0x57u, 0, "", 0);
+    pDialogueWindow->CreateButton(0x1E0u, 0xFAu, 0x8Cu, 0x1Eu, 1, 0, 0x88u, 0x58u, 0, "", 0);
+    pDialogueWindow->_41D08F(4, 1, 0, 1);
+  }
+}
+// F8B1B4: using guessed type int dword_F8B1B4;
+
+//----- (004BBF61) --------------------------------------------------------
+void __fastcall _4BBF61_summon_actor(int a1, __int16 x, int y, int z)
+{
+  size_t v4; // esi@1
+  int monster_id; // edi@1
+  __int16 v6; // ax@4
+  Actor *v7; // esi@5
+  int v8; // eax@5
+  MonsterInfo *v9; // edi@5
+  MonsterDesc *v10; // ebx@5
+  unsigned __int16 *v11; // ebx@5
+  int v12; // ebx@7
+  int v13; // eax@8
+  __int16 x_; // [sp+8h] [bp-Ch]@1
+  __int16 v15; // [sp+Ch] [bp-8h]@1
+  __int16 v16; // [sp+10h] [bp-4h]@3
+  signed int ya; // [sp+1Ch] [bp+8h]@5
+
+  v4 = uNumActors;
+  monster_id = a1;
+  x_ = x;
+  v15 = a1;
+  if ( (signed int)uNumActors < 500
+    && ((signed int)pAllocator->uBigBufferSizeAligned >> 10) - ((signed int)pAllocator->uNextFreeOffsetInBigBuffer >> 10) >= 2000 )
+  {
+    v16 = 0;
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    {
+      v6 = pIndoor->GetSector(x, y, z);
+      v4 = uNumActors;
+      v16 = v6;
+    }
+    v7 = &pActors[v4];
+    v7->Reset();
+    v8 = monster_id;
+    v9 = &pMonsterStats->pInfos[monster_id];
+    v10 = &pMonsterList->pMonsters[v8 - 1];
+    strcpy(v7->pActorName, v9->pName);
+    v7->sCurrentHP = LOWORD(v9->uHP);
+    memcpy(&v7->pMonsterInfo, v9, 0x58u);
+    v7->word_000086_some_monster_id = v15;
+    v7->uActorRadius = v10->uMonsterRadius;
+    v7->uActorHeight = v10->uMonsterHeight;
+    v7->uMovementSpeed = v10->uMovementSpeed;
+    v7->vInitialPosition.x = x_;
+    v7->vPosition.x = x_;
+    BYTE2(v7->uAttributes) |= 8u;
+    v7->pMonsterInfo.uTreasureType = 0;
+    v7->pMonsterInfo.uTreasureLevel = 0;
+    v7->pMonsterInfo.uTreasureDiceSides = 0;
+    v7->pMonsterInfo.uTreasureDiceRolls = 0;
+    v7->pMonsterInfo.uTreasureDropChance = 0;
+    v7->vInitialPosition.y = y;
+    v7->vPosition.y = y;
+    v7->vInitialPosition.z = z;
+    v7->vPosition.z = z;
+    v7->uTetherDistance = 256;
+    v7->uSectorID = v16;
+    v7->uGroup = 1;
+    v7->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Long;
+    v7->PrepareSprites(0);
+    v11 = v10->pSoundSampleIDs;
+    ya = 4;
+    do
+    {
+      pSoundList->LoadSound((signed __int16)*v11, 0);
+      ++v11;
+      --ya;
+    }
+    while ( ya );
+    v12 = 0;
+    do
+      LOWORD(v13) = pSoundList->LoadSound(v12++ + word_4EE088_sound_ids[v9->uSpell1ID], 1u);
+    while ( v13 );
+    ++uNumActors;
+  }
+}
+// 4EE088: using guessed type __int16 word_4EE088_sound_ids[];
+
+//----- (004BC109) --------------------------------------------------------
+void __cdecl ArenaFight()
+{
+  int v0; // edi@1
+  char *v1; // eax@7
+  Player *v2; // edi@9
+  int v3; // eax@10
+  signed int v4; // esi@10
+  signed __int64 v5; // qax@18
+  signed int v6; // ebx@34
+  char *v7; // edi@34
+  int v8; // eax@37
+  int v9; // esi@43
+  int v10; // eax@44
+  unsigned __int8 v11; // sf@44
+  unsigned __int8 v12; // of@44
+  signed int v13; // eax@49
+  int v14; // esi@49
+  int v15; // edx@50
+  int v16; // eax@51
+  signed int v17; // ecx@51
+  int v18; // edx@53
+  int i; // edi@55
+  int monster_y; // ST18_4@56
+  int v21; // eax@56
+  signed int v22; // [sp-4h] [bp-144h]@51
+  __int16 v23[100]; // [sp+Ch] [bp-134h]@39
+  GUIWindow window; // [sp+D4h] [bp-6Ch]@1
+  __int16 monster_ids[6]; // [sp+128h] [bp-18h]@56
+  int v26; // [sp+134h] [bp-Ch]@1
+  int v27; // [sp+138h] [bp-8h]@23
+  int num_monsters; // [sp+13Ch] [bp-4h]@17
+
+  v26 = 0;
+  pParty->field_7B5_in_arena_quest = uDialogueType;
+  memcpy(&window, pDialogueWindow, sizeof(window));
+  window.uFrameWidth = 460;
+  window.uFrameZ = 452;
+  v0 = pFontArrus->CalcTextHeight(pGlobalTXT_LocalizationStrings[575], &window, 13, 0) + 7;
+  pRenderer->BeginSceneD3D();
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    pIndoor->Draw();
+  else if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+      pOutdoor->Draw();
+
+  pRenderer->DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene();
+  pRenderer->BeginScene();
+  if ( pRenderer->pRenderD3D )
+    pRenderer->FillRectFast(
+      pViewport->uViewportX,
+      pViewport->uViewportY,
+      pViewport->uViewportZ - pViewport->uViewportX,
+      pViewport->uViewportW - pViewport->uViewportY + 1,
+      pRenderer->uTargetGMask | pRenderer->uTargetBMask);
+
+  auto pTex = (uTextureID_Leather != -1 ? &pIcons_LOD->pTextures[uTextureID_Leather] : nullptr);
+  pRenderer->_4A6A68(
+    8u,
+    352 - v0,
+    pTex,
+    (pTex ? pTex->uTextureHeight : 26) - v0);
+
+  pRenderer->DrawTextureIndexed(8u, 347 - v0, pTexture_591428);
+  v1 = FitTextInAWindow(pGlobalTXT_LocalizationStrings[575], pFontArrus, &window, 0xDu, 0);
+  pDialogueWindow->DrawText(pFontArrus, 13, 354 - v0, 0, v1, 0, 0, 0);
+  pRenderer->EndScene();
+  pRenderer->Present();
+  pParty->vPosition.x = 3849;
+  pParty->vPosition.y = 5770;
+  pParty->vPosition.z = 1;
+  pParty->uFallStartY = 1;
+  pParty->sRotationY = 512;
+  pParty->sRotationX = 0;
+  pParty->uFallSpeed = 0;
+  if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+  {
+    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+    *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+    ++pMessageQueue_50CBD0->uNumMessages;
+  }
+  v2 = pParty->pPlayers;
+  do
+  {
+    v3 = v2->GetActualLevel();
+    v4 = v26;
+    if ( v3 > v26 )
+    {
+      v26 = v2->GetActualLevel();
+      v4 = v26;
+    }
+    ++v2;
+  }
+  while ( (signed int)v2 < (signed int)pParty->pHirelings );
+  if ( uDialogueType == 85 )
+  {
+    num_monsters = v4;
+    goto LABEL_22;
+  }
+  if ( uDialogueType == 86 )
+  {
+    v5 = (signed __int64)((double)v26 * 1.5);
+    goto LABEL_20;
+  }
+  if ( uDialogueType == 87 )
+  {
+    LODWORD(v5) = 2 * v4;
+LABEL_20:
+    num_monsters = v5;
+LABEL_22:
+    v4 /= 2;
+    goto LABEL_24;
+  }
+  if ( uDialogueType == 88 )
+    num_monsters = 2 * v4;
+  else
+    v4 = v27;
+LABEL_24:
+  if ( v4 < 1 )
+    v4 = 1;
+  if ( v4 > 100 )
+    v4 = 100;
+  if ( num_monsters > 100 )
+    num_monsters = 100;
+  if ( v4 < 2 )
+    v4 = 2;
+  if ( num_monsters < 2 )
+    num_monsters = 2;
+  v6 = 0;
+  v27 = 1;
+  v7 = (char *)&pMonsterStats->pInfos[1].uLevel;
+  do
+  {
+    if ( v7[8] != 1 )
+    {
+      if ( !MonsterStats::BelongsToSupertype(*((short *)v7 + 22), MONSTER_SUPERTYPE_8) )
+      {
+        v8 = (unsigned __int8)*v7;
+        if ( v8 >= v4 )
+        {
+          if ( v8 <= num_monsters )
+            v23[v6++] = v27;
+        }
+      }
+    }
+    ++v27;
+    v7 += 88;
+  }
+  while ( (signed int)v7 <= (signed int)&pMonsterStats->pInfos[258].uLevel );
+  num_monsters = 6;
+  if ( v6 < 6 )
+    num_monsters = v6;
+  v9 = 0;
+  if ( num_monsters > 0 )
+  {
+    do
+    {
+      v10 = rand();
+      ++v9;
+      v12 = __OFSUB__(v9, num_monsters);
+      v11 = v9 - num_monsters < 0;
+      *((short *)&window.pControlsTail + v9 + 1) = v23[v10 % v6];
+    }
+    while ( v11 ^ v12 );
+  }
+  if ( uDialogueType == 85 )
+  {
+    v16 = rand();
+    v17 = 3;
+    v22 = 50;
+    goto LABEL_53;
+  }
+  if ( uDialogueType == 86 )
+  {
+    v16 = rand();
+    v17 = 7;
+    v22 = 100;
+LABEL_53:
+    v18 = v16 % v17;
+    v13 = v22;
+    v14 = v18 + 6;
+    goto LABEL_55;
+  }
+  if ( uDialogueType == 87 )
+  {
+    v15 = rand() % 11;
+    v13 = 200;
+    v14 = v15 + 10;
+  }
+  else
+  {
+    if ( uDialogueType == 88 )
+    {
+      v13 = 500;
+      v14 = 20;
+    }
+    else
+    {
+      v14 = v27;
+      v13 = dword_F8B1B4;
+    }
+  }
+LABEL_55:
+  i = 0;
+  for ( dword_F8B1B4 = v26 * v13; i < v14; ++i )
+  {
+    monster_y = pMonsterArenaPlacements[i].y;
+    v21 = rand();
+    _4BBF61_summon_actor((unsigned __int16)monster_ids[v21 % num_monsters], pMonsterArenaPlacements[i].x, monster_y, 1);
+  }
+  pAudioPlayer->PlaySound((SoundID)14060, 0, 0, -1, 0, 0, 0, 0);
+}
+
+
+
+
+
+//----- (004BC8D5) --------------------------------------------------------
+Texture *__cdecl sub_4BC8D5()
+{
+  int v0; // esi@1
+  char *v1; // ebx@1
+  signed int v2; // edi@1
+  signed int v3; // eax@2
+  int v4; // esi@7
+  GUIWindow *v5; // ebp@15
+  Texture *result; // eax@15
+  int v7; // [sp+10h] [bp-4h]@0
+
+  v0 = v7;
+  v1 = (char *)ptr_507BC0->ptr_1C - 139;
+  v2 = 0;
+  do
+  {
+    //v3 = p2DEvents_minus1___00[26 * (unsigned int)ptr_507BC0->ptr_1C];
+    v3 = p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].uType;
+    if ( v3 < 5 )
+      goto LABEL_12;
+    if ( v3 <= 13 )
+    {
+      v0 = rand() % word_4F0F30[(signed int)v1]
+         //+ 11 * p2DEvents_minus1___00[26 * (unsigned int)ptr_507BC0->ptr_1C]
+         + 11 * p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].uType
+         + 345;
+    }
+    else
+    {
+      if ( v3 == 14 )
+      {
+        v4 = rand() % 4;
+      }
+      else
+      {
+        if ( v3 == 15 )
+        {
+          v4 = rand() % 3 + 4;
+        }
+        else
+        {
+          if ( v3 != 16 )
+            goto LABEL_12;
+          v4 = rand() % 2 + 7;
+        }
+      }
+      v0 = rand() % word_4F0F30[(signed int)v1] + 11 * v4 + 400;
+    }
+LABEL_12:
+    if ( v0 == 487 )
+    {
+      if ( !(unsigned __int16)_449B57_test_bit(pParty->_award_bits, 239) )
+        v0 = 486;
+    }
+    v5 = ptr_507BC0;
+
+    auto _u = (ItemGen *)&pParty->pPlayers[1].pInstalledBeacons[0].field_18 + v2 + 12 * (unsigned int)ptr_507BC0->ptr_1C;
+    _u->Reset();
+    *(&pParty->pPlayers[1].pInstalledBeacons[0].field_18 + 9 * (v2 + 12 * (unsigned int)v5->ptr_1C)) = v0;
+    *(&pParty->pPlayers[1].pInstalledBeacons[1].field_10 + 9 * (v2++ + 12 * (unsigned int)v5->ptr_1C)) = 1;
+    result = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pItemsTable->pItems[v0].pIconName, TEXTURE_16BIT_PALETTE)];
+    *(&dword_F8B164 + v2) = result;
+  }
+  while ( v2 < 12 );
+  return result;
+}
+
+
+//----- (004BCA33) --------------------------------------------------------
+GUIButton *__cdecl sub_4BCA33()
+{
+  pDialogueWindow->Release();
+  pDialogueWindow = GUIWindow::Create(0, 0, 640, 0x159u, WINDOW_MainMenu, 0, 0);
+  pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                 0x1D7u,
+                 0x1BDu,
+                 0xA9u,
+                 0x23u,
+                 1,
+                 0,
+                 0x71u,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[74],
+                 (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                 0);
+  return pDialogueWindow->CreateButton(8u, 8u, 0x1C2u, 0x140u, 1, 0, 0x51u, 0, 0, "", 0);
+}
+
+//----- (004BCACC) --------------------------------------------------------
+void __fastcall sub_4BCACC_bounties(signed int a1)
+{
+  unsigned int v1; // edi@1
+  signed int v2; // ebx@1
+  signed int v3; // ecx@2
+  int v4; // eax@5
+  signed int v5; // esi@5
+  Player *v6; // ecx@5
+  signed int v7; // edx@5
+  GUIWindow *v8; // esi@10
+  unsigned int v9; // eax@12
+  int v10; // esi@31
+  int v11; // edi@31
+  int v12; // esi@32
+  __int16 v13; // bp@32
+  int v14; // edx@32
+  GUIWindow *v15; // eax@32
+  int v16; // eax@32
+  int v17; // eax@33
+  int v18; // eax@34
+  int v19; // eax@35
+  __int16 v20; // ax@37
+  __int16 v21; // ax@76
+  __int16 v22; // ax@107
+  __int16 v23; // ax@132
+  __int16 v24; // ax@163
+  int v25; // esi@190
+  __int16 v26; // ax@190
+  char v27; // zf@190
+  Player *v28; // edi@192
+  int v29; // eax@204
+  void *v30; // esi@208
+  unsigned __int64 v31; // qax@208
+  signed int v32; // edi@209
+  int v33; // eax@210
+  unsigned int v34; // eax@211
+  Player *v35; // edi@227
+  signed int v36; // esi@227
+  int v37; // ecx@227
+  int v38; // esi@230
+  int v39; // edx@235
+  void *v40; // edi@243
+  unsigned __int64 v41; // qax@243
+  void *v42; // eax@244
+  signed int v43; // edi@244
+  int v44; // edx@244
+  int v45; // eax@246
+  unsigned int v46; // eax@247
+  void *v47; // eax@250
+  signed int v48; // edi@250
+  int v49; // eax@252
+  int v50; // eax@256
+  unsigned int v51; // eax@257
+  void *v52; // eax@260
+  signed int v53; // edi@260
+  int v54; // eax@262
+  signed int v55; // [sp+10h] [bp-10h]@1
+  int v56; // [sp+14h] [bp-Ch]@31
+
+  v1 = 0;
+  v2 = a1;
+  v55 = a1;
+  if ( !pDialogueWindow->pNumPresenceButton )
+    return;
+  pRenderer->ClearZBuffer(0, 479);
+  v3 = dword_F8B198;
+  if ( dword_F8B19C != 1 )
+    goto LABEL_13;
+  if ( dword_F8B198 == 30 )
+  {
+    if ( v2 == 17 )
+    {
+      v4 = 0;
+      v5 = 0;
+      v6 = pPlayers[uActiveCharacter];
+      v7 = v6->uLevel;
+      if ( v7 > 0 )
+      {
+        do
+          v4 += v5++ + 1;
+        while ( v5 < v7 );
+      }
+      if ( v7 < (unsigned __int16)word_4F0866[(unsigned int)ptr_507BC0->ptr_1C]
+        && (signed __int64)v6->uExperience < 1000 * v4 )
+        return;
+    }
+    goto LABEL_9;
+  }
+  v8 = ptr_507BC0;
+  if ( (dword_F8B198 == 27 || dword_F8B198 == 28)
+    && (v1 = 0,
+        *(&byte_4F09B1[32 * (unsigned __int8)*(&byte_4F0CCF[4 * (unsigned int)ptr_507BC0->ptr_1C] + v2)]
+        + pParty->uDaysPlayed % 7))
+    || dword_F8B198 != 23
+    || v55 != 10 )
+  {
+LABEL_9:
+    pDialogueWindow->Release();
+    pDialogueWindow = GUIWindow::Create(0, 0, 640, 0x159u, WINDOW_MainMenu, v1, v1);
+    pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                   526,
+                   445,
+                   75,
+                   33,
+                   1,
+                   v1,
+                   0x71u,
+                   v1,
+                   v1,
+                   pGlobalTXT_LocalizationStrings[74],// "End Conversation"
+                   (Texture *)(uTextureID_BUTTDESC2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTDESC2] : 0),
+                   v1);
+    pDialogueWindow->CreateButton(8u, 8u, 0x1C2u, 0x140u, 1, v1, 0x51u, v1, v1, "", (Texture *)v1);
+LABEL_10:
+    v3 = dword_F8B198;
+    v8 = ptr_507BC0;
+    goto LABEL_11;
+  }
+  if ( uActiveCharacter != v1 )
+  {
+    if ( !pPlayers[uActiveCharacter]->_4B6FF9() )
+      return;
+    goto LABEL_10;
+  }
+LABEL_11:
+  dword_F8B19C = v55;
+  if ( v3 < 19 )
+  {
+    v9 = pIcons_LOD->LoadTexture(off_4F03B8[v3], TEXTURE_16BIT_PALETTE);
+    v3 = dword_F8B198;
+    dword_F8B164 = &pIcons_LOD->pTextures[v9];
+LABEL_13:
+    v8 = ptr_507BC0;
+  }
+  if ( v3 > 21 )
+  {
+    if ( v3 == 22 )
+    {
+      if ( dword_F8B19C >= 7 && dword_F8B19C <= 8 )
+        pKeyActionMap->_459E5A(1, 10, v8);
+      return;
+    }
+    if ( v3 != 23 && v3 != 30 )
+      return;
+  }
+  else
+  {
+    if ( v3 != 21 )
+    {
+      if ( v3 <= (signed int)v1 )
+        return;
+      if ( v3 > 4 )
+      {
+        if ( v3 <= 16 )
+        {
+          if ( (signed __int64)__PAIR__(
+                                 *(int *)&stru_AA1058[3].pSounds[8 * (unsigned int)v8->ptr_1C + 44472],
+                                 *(int *)&stru_AA1058[3].pSounds[8 * (unsigned int)v8->ptr_1C + 44468]) >= (signed __int64)pParty->uTimePlayed )
+          {
+            v32 = 0;
+            do
+            {
+              v33 = *(&pParty->pPlayers[1].pInstalledBeacons[0].field_18 + 9 * (v32 + 12 * (unsigned int)v8->ptr_1C));
+              if ( v33 )
+              {
+                v34 = pIcons_LOD->LoadTexture(
+                        pItemsTable->pItems[v33].pIconName,
+                        TEXTURE_16BIT_PALETTE);
+                v8 = ptr_507BC0;
+                dword_F8B168[v32] = &pIcons_LOD->pTextures[v34];
+              }
+              ++v32;
+            }
+            while ( v32 < 12 );
+          }
+          else
+          {
+            sub_4BC8D5();
+            v30 = ptr_507BC0->ptr_1C;
+            v31 = pParty->uTimePlayed
+                + (signed __int64)((double)(0xA8C000
+                                          //* (signed int)p2DEvents_minus1[26 * (unsigned int)ptr_507BC0->ptr_1C])
+                                          * (signed int)p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].field_1C)
+                                 * 0.033333335);
+            *(int *)&stru_AA1058[3].pSounds[8 * (int)v30 + 44468] = v31;
+            *(int *)&stru_AA1058[3].pSounds[8 * (int)v30 + 44472] = HIDWORD(v31);
+          }
+          return;
+        }
+        if ( v3 != 17 )
+          return;
+        if ( v55 == 99 )
+        {
+          v10 = (int)((char *)v8->ptr_1C - 102);
+          v56 = v10;
+          v11 = 8 * v10 + 11325428;
+          if ( (signed __int64)__PAIR__(pParty->field_3C.field_0[2 * v10 + 1], pParty->field_3C.field_0[2 * v10]) >= (signed __int64)pParty->uTimePlayed )
+          {
+            v13 = 0;
+          }
+          else
+          {
+            v12 = v10;
+            v13 = 0;
+            pParty->field_75A[v12] = 0;
+            *(_QWORD *)v11 = (signed __int64)((double)(309657600
+                                                     * (pParty->uCurrentMonth + 12i64 * pParty->uCurrentYear - 14015))
+                                            * 0.033333335);
+            v14 = rand() % 258;
+            v15 = ptr_507BC0;
+            pParty->field_750[v12] = v14 + 1;
+            v16 = (int)((char *)v15->ptr_1C - 102);
+            if ( v16 )
+            {
+              v17 = v16 - 1;
+              if ( v17 )
+              {
+                v18 = v17 - 1;
+                if ( v18 )
+                {
+                  v19 = v18 - 1;
+                  if ( v19 )
+                  {
+                    if ( v19 == 1 )
+                    {
+                      while ( 1 )
+                      {
+                        v20 = pParty->field_750[v12];
+                        if ( (unsigned __int16)v20 < 0x73u || (unsigned __int16)v20 > 0x84u )
+                        {
+                          if ( ((unsigned __int16)v20 < 0xE8u || (unsigned __int16)v20 > 0xF9u)
+                            && ((unsigned __int16)v20 < 0x85u || (unsigned __int16)v20 > 0x96u)
+                            && ((unsigned __int16)v20 < 0x97u || (unsigned __int16)v20 > 0xBAu)
+                            && ((unsigned __int16)v20 < 0xBEu || (unsigned __int16)v20 > 0xC0u)
+                            && ((unsigned __int16)v20 < 0xC4u || (unsigned __int16)v20 > 0xC6u)
+                            && ((unsigned __int16)v20 < 0x2Bu || (unsigned __int16)v20 > 0x2Du)
+                            && ((unsigned __int16)v20 < 0x6Du || (unsigned __int16)v20 > 0x6Fu)
+                            && ((unsigned __int16)v20 < 0x46u || (unsigned __int16)v20 > 0x48u)
+                            && ((unsigned __int16)v20 < 0x100u || (unsigned __int16)v20 > 0x102u)
+                            && ((unsigned __int16)v20 < 0xD9u || (unsigned __int16)v20 > 0xDBu)
+                            && ((unsigned __int16)v20 < 0xC7u || (unsigned __int16)v20 > 0xC9u)
+                            && ((unsigned __int16)v20 < 0xE5u || (unsigned __int16)v20 > 0xE7u)
+                            && ((unsigned __int16)v20 < 0xDFu || (unsigned __int16)v20 > 0xE1u)
+                            && ((unsigned __int16)v20 < 0x5Bu || (unsigned __int16)v20 > 0x5Du)
+                            && ((unsigned __int16)v20 < 0x49u || (unsigned __int16)v20 > 0x4Bu)
+                            && ((unsigned __int16)v20 < 0xFDu || (unsigned __int16)v20 > 0xFFu)
+                            && ((unsigned __int16)v20 < 0x61u || (unsigned __int16)v20 > 0x63u)
+                            && ((unsigned __int16)v20 < 0x10u || (unsigned __int16)v20 > 0x12u) )
+                            break;
+                        }
+                        pParty->field_750[v12] = rand() % 258 + 1;
+                      }
+                    }
+                  }
+                  else
+                  {
+                    while ( 1 )
+                    {
+                      v21 = pParty->field_750[v12];
+                      if ( (unsigned __int16)v21 < 0x73u || (unsigned __int16)v21 > 0x84u )
+                      {
+                        if ( ((unsigned __int16)v21 < 0xE8u || (unsigned __int16)v21 > 0xF9u)
+                          && ((unsigned __int16)v21 < 0x85u || (unsigned __int16)v21 > 0x96u)
+                          && ((unsigned __int16)v21 < 0x97u || (unsigned __int16)v21 > 0xBAu)
+                          && ((unsigned __int16)v21 < 0xBEu || (unsigned __int16)v21 > 0xC0u)
+                          && ((unsigned __int16)v21 < 0xC4u || (unsigned __int16)v21 > 0xC6u)
+                          && ((unsigned __int16)v21 < 0x2Bu || (unsigned __int16)v21 > 0x2Du)
+                          && ((unsigned __int16)v21 < 0x5Eu || (unsigned __int16)v21 > 0x60u)
+                          && ((unsigned __int16)v21 < 0x43u || (unsigned __int16)v21 > 0x45u)
+                          && ((unsigned __int16)v21 < 0x4Fu || (unsigned __int16)v21 > 0x51u)
+                          && ((unsigned __int16)v21 < 0xC1u || (unsigned __int16)v21 > 0xC3u)
+                          && ((unsigned __int16)v21 < 0x13u || (unsigned __int16)v21 > 0x15u)
+                          && ((unsigned __int16)v21 < 0xFDu || (unsigned __int16)v21 > 0xFFu)
+                          && ((unsigned __int16)v21 < 0x61u || (unsigned __int16)v21 > 0x63u)
+                          && ((unsigned __int16)v21 < 0x6Au || (unsigned __int16)v21 > 0x6Cu) )
+                          break;
+                      }
+                      pParty->field_750[v12] = rand() % 258 + 1;
+                    }
+                  }
+                }
+                else
+                {
+                  while ( 1 )
+                  {
+                    v22 = pParty->field_750[v12];
+                    if ( (unsigned __int16)v22 < 0x73u || (unsigned __int16)v22 > 0x84u )
+                    {
+                      if ( ((unsigned __int16)v22 < 0xE8u || (unsigned __int16)v22 > 0xF9u)
+                        && ((unsigned __int16)v22 < 0x85u || (unsigned __int16)v22 > 0x96u)
+                        && ((unsigned __int16)v22 < 0x97u || (unsigned __int16)v22 > 0xBAu)
+                        && ((unsigned __int16)v22 < 0xBEu || (unsigned __int16)v22 > 0xC0u)
+                        && ((unsigned __int16)v22 < 0xC4u || (unsigned __int16)v22 > 0xC6u)
+                        && ((unsigned __int16)v22 < 0x2Bu || (unsigned __int16)v22 > 0x2Du)
+                        && ((unsigned __int16)v22 < 0x31u || (unsigned __int16)v22 > 0x33u)
+                        && ((unsigned __int16)v22 < 0x34u || (unsigned __int16)v22 > 0x36u)
+                        && ((unsigned __int16)v22 < 0xFDu || (unsigned __int16)v22 > 0xFFu)
+                        && ((unsigned __int16)v22 < 0x61u || (unsigned __int16)v22 > 0x63u)
+                        && ((unsigned __int16)v22 < 0x1Cu || (unsigned __int16)v22 > 0x1Eu) )
+                        break;
+                    }
+                    pParty->field_750[v12] = rand() % 258 + 1;
+                  }
+                }
+              }
+              else
+              {
+                while ( 1 )
+                {
+                  v23 = pParty->field_750[v12];
+                  if ( (unsigned __int16)v23 < 0x73u || (unsigned __int16)v23 > 0x84u )
+                  {
+                    if ( ((unsigned __int16)v23 < 0xE8u || (unsigned __int16)v23 > 0xF9u)
+                      && ((unsigned __int16)v23 < 0x85u || (unsigned __int16)v23 > 0x96u)
+                      && ((unsigned __int16)v23 < 0x97u || (unsigned __int16)v23 > 0xBAu)
+                      && ((unsigned __int16)v23 < 0xBEu || (unsigned __int16)v23 > 0xC0u)
+                      && ((unsigned __int16)v23 < 0xC4u || (unsigned __int16)v23 > 0xC6u)
+                      && ((unsigned __int16)v23 < 0x2Bu || (unsigned __int16)v23 > 0x2Du)
+                      && ((unsigned __int16)v23 < 0x52u || (unsigned __int16)v23 > 0x54u)
+                      && ((unsigned __int16)v23 < 4u || (unsigned __int16)v23 > 6u)
+                      && ((unsigned __int16)v23 < 0x37u || (unsigned __int16)v23 > 0x39u)
+                      && ((unsigned __int16)v23 < 0x3Au || (unsigned __int16)v23 > 0x3Cu)
+                      && ((unsigned __int16)v23 < 0x3Du || (unsigned __int16)v23 > 0x3Fu)
+                      && ((unsigned __int16)v23 < 0xFDu || (unsigned __int16)v23 > 0xFFu)
+                      && ((unsigned __int16)v23 < 0x61u || (unsigned __int16)v23 > 0x63u)
+                      && ((unsigned __int16)v23 < 0xCDu || (unsigned __int16)v23 > 0xCFu) )
+                      break;
+                  }
+                  pParty->field_750[v12] = rand() % 258 + 1;
+                }
+              }
+            }
+            else
+            {
+              while ( 1 )
+              {
+                v24 = pParty->field_750[v12];
+                if ( (unsigned __int16)v24 < 0x73u || (unsigned __int16)v24 > 0x84u )
+                {
+                  if ( ((unsigned __int16)v24 < 0xEBu || (unsigned __int16)v24 > 0xFCu)
+                    && ((unsigned __int16)v24 < 0x85u || (unsigned __int16)v24 > 0x96u)
+                    && ((unsigned __int16)v24 < 0x97u || (unsigned __int16)v24 > 0xBAu)
+                    && ((unsigned __int16)v24 < 0xBEu || (unsigned __int16)v24 > 0xC0u)
+                    && ((unsigned __int16)v24 < 0xC4u || (unsigned __int16)v24 > 0xC6u)
+                    && ((unsigned __int16)v24 < 0x2Bu || (unsigned __int16)v24 > 0x2Du)
+                    && ((unsigned __int16)v24 < 0xCDu || (unsigned __int16)v24 > 0xCFu)
+                    && ((unsigned __int16)v24 < 0x5Eu || (unsigned __int16)v24 > 0x60u)
+                    && ((unsigned __int16)v24 < 0xFDu || (unsigned __int16)v24 > 0xFFu)
+                    && ((unsigned __int16)v24 < 0x6Du || (unsigned __int16)v24 > 0x6Fu)
+                    && ((unsigned __int16)v24 < 0x61u || (unsigned __int16)v24 > 0x63u) )
+                    break;
+                }
+                pParty->field_750[v12] = rand() % 258 + 1;
+              }
+            }
+            v10 = v56;
+          }
+          v25 = v10;
+          v26 = pParty->field_750[v25];
+          v27 = pParty->field_75A[v25] == v13;
+          word_F8B1A0 = pParty->field_750[v25];
+          if ( v27 )
+          {
+            v1 = 0;
+            v27 = v26 == v13;
+            v29 = (int)pNPCTopics[351].pText;
+            if ( v27 )
+              v29 = (int)pNPCTopics[353].pText;
+            dword_F8B1A4 = (char *)v29;
+          }
+          else
+          {
+            if ( v26 != v13 )
+            {
+              party_finds_gold(100 * pMonsterStats->pInfos[(unsigned __int16)v26].uLevel, 0);
+              v28 = pParty->pPlayers;
+              do
+              {
+                v28->SetVariable(VAR_Award, 86);
+                ++v28;
+              }
+              while ( (signed int)v28 < (signed int)pParty->pHirelings );
+              pParty->uNumBountiesCollected += 100 * pMonsterStats->pInfos[pParty->field_750[v25]].uLevel;
+              pParty->field_750[v25] = v13;
+              pParty->field_75A[v25] = v13;
+            }
+            v1 = 0;
+            dword_F8B1A4 = pNPCTopics[352].pText;
+          }
+          goto LABEL_196;
+        }
+        if ( v55 == 100 )
+        {
+          pKeyActionMap->_459E5A(1, 10, v8);
+          goto LABEL_196;
+        }
+      }
+    }
+  }
+  if ( v55 > 95 )
+  {
+LABEL_196:
+    switch ( v55 )
+    {
+      case 96:
+        pDialogueWindow->eWindowType = WINDOW_MainMenu;
+        sub_4BCA33();
+        sub_4B3703((void *)dword_F8B198);
+        break;
+      case 101:
+        pDialogueWindow->eWindowType = WINDOW_MainMenu;
+        sub_4BCA33();
+        sub_4B3A72(dword_F8B198);
+        break;
+      case 102:
+        dword_F8B19C = 102;
+        break;
+      case 103:
+        dword_F8B19C = 103;
+        break;
+      case 104:
+        if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+        {
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)29;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v1;
+          *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = v1;
+          ++pMessageQueue_50CBD0->uNumMessages;
+        }
+        dword_F8B19C = 104;
+        break;
+    }
+    return;
+  }
+  if ( v55 != 95 && v55 != 2 )
+  {
+    if ( v55 == 3 )
+    {
+      dword_F8B19C = 3;
+    }
+    else
+    {
+      if ( v55 == 4 )
+      {
+        dword_F8B19C = 4;
+      }
+      else
+      {
+        if ( v55 != 5 )
+        {
+          if ( v55 > 35 )
+          {
+            if ( v55 <= 72 )
+            {
+              v35 = pPlayers[uActiveCharacter];
+              //v36 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (unsigned int)v8->ptr_1C] * 500.0);
+              v36 = (signed __int64)(p2DEvents[(unsigned int)v8->ptr_1C - 1].flt_24 * 500.0);
+              v37 = v36 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
+              if ( v37 < v36 / 3 )
+                v37 = v36 / 3;
+              
+              __debugbreak();
+              //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+              // or
+              //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+              // or
+              //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+
+              if (false)
+              //if ( *(&byte_4ED94C[37 * v35->uClass] + v55) )
+              {
+                v38 = (int)(&v35->uIntelligence + v55);
+                if ( !*(short *)v38 )
+                {
+                  if ( pParty->uNumGold < v37 )
+                  {
+                    ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
+                    if ( dword_F8B198 == 30 || dword_F8B198 == 21 )
+                      v39 = 4;
+                    else
+                      v39 = 2;
+                    HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, v39);
+                  }
+                  else
+                  {
+                    Party::TakeGold(v37);
+                    dword_F8B1E4 = 1;
+                    *(short *)v38 = 1;
+                    v35->PlaySound(78, 0);
+                  }
+                }
+              }
+            }
+            else
+            {
+              if ( v55 == 94 )
+              {
+                pDialogueWindow->eWindowType = WINDOW_MainMenu;
+                sub_4BCA33();
+                sub_4B3AD4(dword_F8B198);
+              }
+            }
+          }
+          return;
+        }
+        dword_F8B19C = 5;
+      }
+    }
+    sub_421B2C_PlaceInInventory_or_DropPickedItem();
+    return;
+  }
+  if ( (signed __int64)__PAIR__(
+                         pParty->field_3C.field_50[2 * (unsigned int)v8->ptr_1C + 1],
+                         pParty->field_3C.field_50[2 * (unsigned int)v8->ptr_1C]) < (signed __int64)pParty->uTimePlayed )
+  {
+    GenerateShopItems();
+    sub_4B8F94();
+    v8 = ptr_507BC0;
+    v40 = ptr_507BC0->ptr_1C;
+    v3 = dword_F8B198;
+    v41 = pParty->uTimePlayed
+        //+ (signed __int64)((double)(11059200 * (signed int)p2DEvents_minus1[26 * (unsigned int)ptr_507BC0->ptr_1C])
+        + (signed __int64)((double)(11059200 * (signed int)p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].field_1C)
+                         * 0.033333335);
+    pParty->field_3C.field_50[2 * (int)v40] = v41;
+    pParty->field_3C.field_50[2 * (int)v40 + 1] = HIDWORD(v41);
+  }
+  v42 = v8->ptr_1C;
+  v43 = 0;
+  //v44 = p2DEvents_minus1___00[26 * (unsigned int)v8->ptr_1C];
+  v44 = p2DEvents[(unsigned int)v8->ptr_1C - 1].uType;
+  if ( v55 == 2 )
+  {
+    if ( _4F063C_smthn_by_2da_uType[v44] )
+    {
+      do
+      {
+        v45 = pParty->field_777C[9 * (v43 + 12 * (int)v42)];
+        if ( v45 )
+        {
+          v46 = pIcons_LOD->LoadTexture(pItemsTable->pItems[v45].pIconName, TEXTURE_16BIT_PALETTE);
+          v3 = dword_F8B198;
+          v8 = ptr_507BC0;
+          dword_F8B168[v43] = &pIcons_LOD->pTextures[v46];
+        }
+        v42 = v8->ptr_1C;
+        ++v43;
+      }
+      //while ( v43 < (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)v8->ptr_1C]] );
+      while ( v43 < (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)v8->ptr_1C - 1].uType] );
+    }
+    if ( v3 == 1 )
+    {
+      v47 = v8->ptr_1C;
+      v48 = 0;
+      //if ( _4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)v8->ptr_1C]] )
+      if ( _4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)v8->ptr_1C - 1].uType] )
+      {
+        do
+        {
+          if ( pParty->field_777C[9 * (v48 + 12 * (int)v47)] )
+          {
+            v49 = rand();
+            v8 = ptr_507BC0;
+            word_F8B158[v48] = v49 % (300 - dword_F8B168[v48]->uTextureHeight);
+          }
+          v47 = v8->ptr_1C;
+          ++v48;
+        }
+        //while ( v48 < (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)v8->ptr_1C]] );
+        while ( v48 < (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)v8->ptr_1C - 1].uType] );
+      }
+    }
+  }
+  else
+  {
+    if ( _4F063C_smthn_by_2da_uType[v44] )
+    {
+      do
+      {
+        v50 = pParty->field_C59C[9 * (v43 + 12 * (int)v42) + 724];
+        if ( v50 )
+        {
+          v51 = pIcons_LOD->LoadTexture(pItemsTable->pItems[v50].pIconName, TEXTURE_16BIT_PALETTE);
+          v3 = dword_F8B198;
+          v8 = ptr_507BC0;
+          dword_F8B168[v43] = &pIcons_LOD->pTextures[v51];
+        }
+        v42 = v8->ptr_1C;
+        ++v43;
+      }
+      //while ( v43 < (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)v8->ptr_1C]] );
+      while ( v43 < (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)v8->ptr_1C - 1].uType] );
+    }
+    if ( v3 == 1 )
+    {
+      v52 = v8->ptr_1C;
+      v53 = 0;
+      //if ( _4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)v8->ptr_1C]] )
+      if ( _4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)v8->ptr_1C - 1].uType] )
+      {
+        do
+        {
+          if ( pParty->field_C59C[9 * (v53 + 12 * (int)v52) + 724] )
+          {
+            v54 = rand();
+            v8 = ptr_507BC0;
+            word_F8B158[v53] = v54 % (300 - dword_F8B168[v53]->uTextureHeight);
+          }
+          v52 = v8->ptr_1C;
+          ++v53;
+        }
+        //while ( v53 < (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)v8->ptr_1C]] );
+        while ( v53 < (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)v8->ptr_1C - 1].uType ] );
+      }
+    }
+  }
+}
+
+//----- (004BD8B5) --------------------------------------------------------
+signed int __cdecl sub_4BD8B5()
+{
+  int v0; // eax@4
+  int v1; // eax@29
+  unsigned int v2; // esi@30
+  const char *v3; // ebx@31
+
+  if ( pMessageQueue_50CBD0->uNumMessages )
+    pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+  pKeyActionMap->_459ED1(3);
+  pKeyActionMap->ResetKeys();
+  _5C3420_pDecoration = 0;
+  ptr_F8B1E8 = 0;
+  if ( array_5913D8[6] )
+  {
+    v0 = dword_F8B19C;
+    if ( dword_F8B19C != 2
+      && dword_F8B19C != 3
+      && dword_F8B19C != 97
+      && dword_F8B19C != 5
+      && dword_F8B19C != 4
+      && dword_F8B164 )
+    {
+      dword_F8B164->Release();
+      v0 = dword_F8B19C;
+      dword_F8B164 = 0;
+    }
+    if ( v0 && v0 != 1 )
+    {
+      if ( v0 == -1 )
+      {
+        _4B4224_UpdateNPCTopics((int)((char *)array_5913D8[6] - 1));
+LABEL_33:
+        pVideoPlayer->_4BF5B2();
+        return 1;
+      }
+      if ( v0 != 94 && v0 != 96 && v0 != 101 )
+      {
+        if ( v0 == 3 || v0 == 5 || v0 == 4 )
+        {
+          sub_4BCA33();
+          dword_F8B19C = 94;
+          sub_4B3AD4(dword_F8B198);
+        }
+        else
+        {
+          if ( v0 != 102 && v0 != 103 && v0 != 104 )
+          {
+            pVideoPlayer->_4BF5B2();
+LABEL_28:
+            dword_F8B19C = 1;
+            sub_4B3B42(dword_F8B198);
+            return 1;
+          }
+          pVideoPlayer->_4BF5B2();
+          sub_4BCA33();
+          dword_F8B19C = 101;
+          sub_4B3A72(dword_F8B198);
+        }
+        return 1;
+      }
+      pVideoPlayer->_4BF5B2();
+      sub_4BCA33();
+      goto LABEL_28;
+    }
+    array_5913D8[6] = 0;
+    pDialogueWindow->Release();
+    dword_F8B19C = 0;
+    pDialogueWindow = 0;
+    pIcons_LOD->_40F9C5();
+    v1 = uNumDialogueNPCPortraits;
+    if ( uNumDialogueNPCPortraits != 1 )
+    {
+      v2 = 0;
+      pBtn_ExitCancel = ptr_507BC0->pControlsHead;
+      if ( uNumDialogueNPCPortraits > 0 )
+      {
+        v3 = byte_591180;
+        do
+        {
+          array_5913D8[v2 + 7] = (NPCData *)ptr_507BC0->CreateButton(
+                                              *(&_4E5E50_transui_x + v2 + 6 * v1 - 6),
+                                              *(&_4E5EE0_transui_y + v2 + 6 * v1 - 6),
+                                              0x3Fu,
+                                              0x49u,
+                                              1,
+                                              0,
+                                              0x19Au,
+                                              v2,
+                                              0,
+                                              v3,
+                                              0,
+                                              0,
+                                              0);
+          v1 = uNumDialogueNPCPortraits;
+          ++v2;
+          v3 += 100;
+        }
+        while ( (signed int)v2 < uNumDialogueNPCPortraits );
+      }
+      goto LABEL_33;
+    }
+  }
+  return 0;
+}
+
+
+
+
+
+//----- (004BDB56) --------------------------------------------------------
+void __cdecl sub_4BDB56_buy_skill____()
+{
+  Player *v0; // edi@1
+  signed int v1; // esi@9
+  unsigned int v2; // eax@11
+  int v3; // esi@12
+  float v4; // ST1C_4@12
+  signed int v5; // eax@12
+  signed int v6; // eax@12
+  char v7; // zf@12
+  int v8; // eax@15
+  const char *v9; // ecx@15
+  signed int v10; // esi@18
+  unsigned int v11; // esi@20
+  int v12; // esi@21
+  void *v13; // ecx@26
+  signed int v14; // esi@31
+  unsigned int v15; // eax@33
+  GUIWindow *v16; // esi@34
+  POINT *v17; // esi@37
+  int v18; // ecx@37
+  void *v19; // eax@38
+  ItemGen *v20; // esi@38
+  float v21; // ST1C_4@38
+  signed int v22; // eax@38
+  int v23; // ebx@38
+  int v24; // edx@39
+  int v25; // eax@40
+  int v26; // ebx@41
+  Player *v27; // ecx@43
+  POINT *v28; // esi@49
+  int v29; // ecx@49
+  void *v30; // eax@50
+  int v31; // ecx@50
+  ItemGen *v32; // esi@51
+  float v33; // ST1C_4@53
+  signed int v34; // eax@53
+  int v35; // eax@53
+  bool v36; // eax@53
+  unsigned int v37; // eax@53
+  int v38; // eax@55
+  int v39; // eax@63
+  int v40; // eax@64
+  int v41; // edx@66
+  int v42; // esi@74
+  signed int v43; // ebx@74
+  int v44; // ecx@74
+  unsigned __int16 *pSkill; // esi@77
+  signed int v46; // [sp-18h] [bp-CCh]@36
+  unsigned int v47; // [sp-14h] [bp-C8h]@36
+  signed int v48; // [sp-10h] [bp-C4h]@36
+  signed int v49; // [sp-Ch] [bp-C0h]@36
+  int v50; // [sp-8h] [bp-BCh]@36
+  int v51; // [sp-4h] [bp-B8h]@28
+  unsigned int v52; // [sp-4h] [bp-B8h]@36
+  int v53; // [sp+0h] [bp-B4h]@16
+  unsigned int v54; // [sp+0h] [bp-B4h]@25
+  int v55; // [sp+0h] [bp-B4h]@26
+  int v56; // [sp+0h] [bp-B4h]@36
+  POINT v57; // [sp+10h] [bp-A4h]@49
+  POINT v58; // [sp+18h] [bp-9Ch]@18
+  POINT v59; // [sp+20h] [bp-94h]@49
+  POINT v60; // [sp+28h] [bp-8Ch]@9
+  POINT v61; // [sp+30h] [bp-84h]@37
+  POINT v62; // [sp+38h] [bp-7Ch]@18
+  POINT v63; // [sp+40h] [bp-74h]@37
+  POINT v64; // [sp+48h] [bp-6Ch]@19
+  POINT v65; // [sp+50h] [bp-64h]@32
+  POINT v66; // [sp+58h] [bp-5Ch]@18
+  POINT v67; // [sp+60h] [bp-54h]@31
+  POINT a2; // [sp+68h] [bp-4Ch]@9
+  POINT v69; // [sp+70h] [bp-44h]@31
+  POINT v70; // [sp+78h] [bp-3Ch]@9
+  POINT v71; // [sp+80h] [bp-34h]@31
+  POINT v72; // [sp+88h] [bp-2Ch]@10
+  bool v73; // [sp+90h] [bp-24h]@53
+  int v74; // [sp+94h] [bp-20h]@53
+  int a6; // [sp+98h] [bp-1Ch]@57
+  int a3; // [sp+9Ch] [bp-18h]@53
+  Player *v77; // [sp+A0h] [bp-14h]@1
+  unsigned int uNumSeconds; // [sp+A4h] [bp-10h]@53
+  unsigned int v79; // [sp+A8h] [bp-Ch]@9
+  int v80; // [sp+ACh] [bp-8h]@12
+  ItemGen *_this; // [sp+B0h] [bp-4h]@13
+
+  v0 = pPlayers[uActiveCharacter];
+  v77 = pPlayers[uActiveCharacter];
+  if ( pCurrentScreen == 14 )
+    goto LABEL_73;
+  if ( !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+  {
+    v56 = 0;
+    v52 = 0;
+    v50 = 0;
+    v49 = 0;
+    v48 = -1;
+    v47 = 0;
+    v46 = 0;
+    goto LABEL_87;
+  }
+  if ( dword_F8B19C > 18 )
+  {
+    if ( dword_F8B19C < 36 )
+      return;
+    if ( dword_F8B19C <= 72 )
+    {
+      v42 = dword_F8B19C - 36;
+      //v43 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (unsigned int)ptr_507BC0->ptr_1C] * 500.0);
+      v43 = (signed __int64)(p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].flt_24 * 500.0);
+      v44 = v43 * (100 - v0->GetMerchant()) / 100;
+      if ( v44 < v43 / 3 )
+        v44 = v43 / 3;
+      if ( byte_4ED970_skill_learn_ability_by_class_table[v0->uClass][v42] )
+      {
+        pSkill = &v0->pActiveSkills[v42];
+        if ( !*pSkill )
+        {
+          if ( pParty->uNumGold < v44 )
+          {
+            ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);// "You don't have enough gold"
+            v13 = ptr_507BC0->ptr_1C;
+            if ( dword_F8B198 == 30 )
+              v55 = 4;
+            else
+              v55 = 2;
+            goto LABEL_84;
+          }
+          Party::TakeGold(v44);
+          v53 = 0;
+          dword_F8B1E4 = 1;
+          *pSkill = 1;
+          v51 = 78;
+          goto LABEL_80;
+        }
+      }
+      return;
+    }
+    if ( dword_F8B19C != 94 )
+    {
+      if ( dword_F8B19C != 95 )
+        return;
+      goto LABEL_49;
+    }
+    pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
+LABEL_73:
+    sub_421EA6_OnInventoryLeftClick();
+    return;
+  }
+  if ( dword_F8B19C == 18 )
+  {
+    v17 = pMouse->GetCursorPos(&v63);
+    v18 = pRenderer->pActiveZBuffer[v17->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v61)->y]] & 0xFFFF;
+    if ( !v18 )
+      return;
+    v19 = ptr_507BC0->ptr_1C;
+    v20 = (ItemGen *)(&pParty->pPlayers[1].uExpressionTimeLength + 18 * (v18 + 12 * (int)v19));
+    //v21 = p2DEvents_minus1__20[13 * (signed int)v19];
+    v21 = p2DEvents[(signed int)v19 - 1].fPriceMultiplier;
+    _this = v20;
+    v22 = v20->GetValue();
+    v23 = v0->_4B8142(v22, v21);
+    v80 = v23;
+    GetAsyncKeyState(VK_CONTROL);
+    if ( pParty->uNumGold < v23 )
+    {
+      v24 = 2;
+LABEL_62:
+      HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, v24);
+      v9 = pGlobalTXT_LocalizationStrings[155];
+      v54 = 2;
+      goto LABEL_71;
+    }
+    v25 = v0->AddItem(0xFFFFFFFFu, v20->uItemID);
+    if ( v25 )
+    {
+      v26 = 1;
+      v20->uAttributes |= 1u;
+      memcpy(&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v25 + 5], v20, 0x24u);
+      goto LABEL_42;
+    }
+    v0->PlaySound(15, 0);
+    v54 = 5;
+LABEL_70:
+    v9 = pGlobalTXT_LocalizationStrings[563];   // "Pack is Full!"
+    goto LABEL_71;
+  }
+  if ( dword_F8B19C == 2 )
+  {
+LABEL_49:
+    v28 = pMouse->GetCursorPos(&v59);
+    v29 = pRenderer->pActiveZBuffer[v28->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v57)->y]] & 0xFFFF;
+    if ( !v29 )
+      return;
+    v30 = ptr_507BC0->ptr_1C;
+    v31 = 9 * (v29 - 1 + 12 * (int)v30);
+    if ( dword_F8B19C == 2 )
+    {
+      v32 = (ItemGen *)&pParty->field_777C[v31];
+      _this = (ItemGen *)&pParty->field_777C[v31];
+    }
+    else
+    {
+      _this = (ItemGen *)&pParty->field_C59C[v31 + 724];
+      v32 = (ItemGen *)&pParty->field_C59C[v31 + 724];
+    }
+    //v33 = p2DEvents_minus1__20[13 * (signed int)v30];
+    v33 = p2DEvents[(signed int)v30 - 1].fPriceMultiplier;
+    v34 = v32->GetValue();
+    v80 = v0->_4B8142(v34, v33);
+    LOWORD(v35) = GetAsyncKeyState(VK_CONTROL);
+    v74 = v35;
+    v36 = v0->CanSteal();
+    uNumSeconds = 0;
+    a3 = 0;
+    v73 = v36;
+    v37 = pMapStats->GetMapInfo(pCurrentMapName);
+    if ( v37 )
+      a3 = pMapStats->pInfos[v37]._steal_perm;
+    v38 = GetPartyReputation();
+    v26 = 1;
+    if ( v73 == 1 )
+    {
+      if ( (short)v74 )
+      {
+        uNumSeconds = v0->StealFromShop(v32, a3, v38, 0, &a6);
+        if ( !uNumSeconds )
+        {
+          sub_4B1447_party_fine((int)ptr_507BC0->ptr_1C, 0, a6);
+          return;
+        }
+      }
+    }
+    if ( pParty->uNumGold < v80 )
+    {
+      v24 = 2;
+      if ( uNumSeconds != 2 )
+      {
+        if ( uNumSeconds != 1 )
+          goto LABEL_62;
+      }
+    }
+    v39 = v0->AddItem(0xFFFFFFFFu, v32->uItemID);
+    if ( v39 )
+    {
+      v32->uAttributes |= 1u;
+      v7 = v73 == 1;
+      v40 = (int)((char *)v0 + 36 * v39);
+      memcpy((void *)(v40 + 496), v32, 0x24u);
+      if ( v7 )
+      {
+        if ( (short)v74 )
+        {
+          v41 = uNumSeconds;
+          if ( uNumSeconds == 1 || uNumSeconds == 2 )
+          {
+            *(char *)(v40 + 517) |= 1u;
+            sub_4B1447_party_fine((int)ptr_507BC0->ptr_1C, v41, a6);
+            goto LABEL_43;
+          }
+        }
+      }
+LABEL_42:
+      dword_F8B1E4 = v26;
+      Party::TakeGold(v80);
+LABEL_43:
+      viewparams->bRedrawGameUI = v26;
+      _this->Reset();
+      pRenderer->ClearZBuffer(0, 479);
+      v27 = v77;
+      v53 = 0;
+      v51 = 75;
+LABEL_81:
+      v27->PlaySound(v51, v53);
+      return;
+    }
+    v0->PlaySound(15, 0);
+    v54 = 2;
+    goto LABEL_70;
+  }
+  if ( dword_F8B19C == 3 )
+  {
+    v14 = pMouse->GetCursorPos(&v71)->x - 14;
+    v79 = (v14 >> 5) + 14 * ((pMouse->GetCursorPos(&v69)->y - 17) >> 5);
+    if ( pMouse->GetCursorPos(&v67)->x <= 13
+      || pMouse->GetCursorPos(&v65)->x >= 462
+      || (v15 = v0->GetItemIDAtInventoryIndex((int *)&v79), (v77 = (Player *)v15) == 0) )
+      return;
+    v16 = ptr_507BC0;
+    if ( sub_4BDAAF((ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5], (int)ptr_507BC0->ptr_1C) )
+    {
+      dword_F8B1E4 = 1;
+      v0->_4BE2DD(v79, (int)((char *)v77 - 1), (int)v16->ptr_1C);
+      viewparams->bRedrawGameUI = 1;
+      pRenderer->ClearZBuffer(0, 479);
+      v53 = 0;
+      v51 = 77;
+      goto LABEL_80;
+    }
+    v0->PlaySound(79, 0);
+    v56 = 0;
+    v52 = 0;
+    v50 = 0;
+    v49 = 0;
+    v48 = -1;
+    v47 = 0;
+    v46 = 0;
+LABEL_87:
+    pAudioPlayer->PlaySound(SOUND_27, v46, v47, v48, v49, v50, v52, v56);
+    return;
+  }
+  if ( dword_F8B19C == 4 )
+  {
+    v10 = pMouse->GetCursorPos(&v62)->x - 14;
+    v79 = (v10 >> 5) + 14 * ((pMouse->GetCursorPos(&v66)->y - 17) >> 5);
+    if ( pMouse->GetCursorPos(&v58)->x > 13 )
+    {
+      if ( pMouse->GetCursorPos(&v64)->x < 462 )
+      {
+        v11 = v0->GetItemIDAtInventoryIndex((int *)&v79);
+        if ( v11 )
+        {
+          //v80 = v0->_4B8179(p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C]);
+          v80 = v0->_4B8179(p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].fPriceMultiplier);
+          v12 = (int)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v11 + 5];
+          if ( !(*(char *)(v12 + 20) & 1) )
+          {
+            _this = (ItemGen *)ptr_507BC0->ptr_1C;
+            if ( sub_4BDAAF((ItemGen *)v12, (int)_this) )
+            {
+              if ( pParty->uNumGold >= v80 )
+              {
+                dword_F8B1E4 = 1;
+                Party::TakeGold(v80);
+                *(int *)(v12 + 20) |= 1u;
+                v0->PlaySound(73, 0);
+                v9 = pGlobalTXT_LocalizationStrings[569];
+                goto LABEL_25;
+              }
+              goto LABEL_26;
+            }
+            pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+            v53 = 0;
+            goto LABEL_28;
+          }
+          v53 = 0;
+LABEL_30:
+          v51 = 76;
+          goto LABEL_80;
+        }
+      }
+    }
+  }
+  else
+  {
+    if ( dword_F8B19C == 5 )
+    {
+      v1 = pMouse->GetCursorPos(&a2)->x - 14;
+      v79 = (v1 >> 5) + 14 * ((pMouse->GetCursorPos(&v70)->y - 17) >> 5);
+      if ( pMouse->GetCursorPos(&v60)->x > 13 )
+      {
+        if ( pMouse->GetCursorPos(&v72)->x < 462 )
+        {
+          v2 = v0->GetItemIDAtInventoryIndex((int *)&v79);
+          if ( v2 )
+          {
+            v3 = (int)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
+            //v4 = p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C];
+            v4 = p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].fPriceMultiplier;
+
+            auto _v = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
+            v5 = _v->GetValue();
+
+            v6 = v0->_4B81C3(v5, v4);
+            v7 = (*(char *)(v3 + 20) & 2) == 0;
+            v80 = v6;
+            if ( !v7 )
+            {
+              _this = (ItemGen *)ptr_507BC0->ptr_1C;
+              if ( sub_4BDAAF((ItemGen *)v3, (int)_this) )
+              {
+                if ( pParty->uNumGold >= v80 )
+                {
+                  dword_F8B1E4 = 1;
+                  Party::TakeGold(v80);
+                  v8 = *(int *)(v3 + 20);
+                  LOBYTE(v8) = v8 & 0xFD;
+                  *(int *)(v3 + 20) = v8 | 1;
+                  v0->PlaySound(74, 0);
+                  v9 = pGlobalTXT_LocalizationStrings[570];
+LABEL_25:
+                  v54 = 2;
+LABEL_71:
+                  ShowStatusBarString(v9, v54);
+                  return;
+                }
+LABEL_26:
+                v13 = _this;
+                v55 = 2;
+LABEL_84:
+                HousePlaySomeSound((unsigned int)v13, v55);
+                return;
+              }
+              pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+              v53 = 0;
+LABEL_28:
+              v51 = 79;
+LABEL_80:
+              v27 = v0;
+              goto LABEL_81;
+            }
+            v53 = 0;
+            goto LABEL_30;
+          }
+        }
+      }
+    }
+  }
+}
+
+
+
+//----- (004BE386) --------------------------------------------------------
+void __fastcall log_error(const char *pMessage)
+{
+  const char *v1; // edi@1
+  FILE *f; // eax@1
+  FILE *v3; // esi@1
+
+  v1 = pMessage;
+  f = fopen("errorlog.txt", "a");
+  v3 = f;
+  if ( f )
+  {
+    fprintf(f, "%s\n", v1);
+    fclose(v3);
+    fflush(v3);
+  }
+}
+
+//----- (004BE3BF) --------------------------------------------------------
+FrameTableTxtLine *texture_frame_table_txt_parser(const char *_this, FrameTableTxtLine *a2)
+{
+  char *v2; // eax@3
+  signed int v3; // edx@3
+  unsigned int v4; // edi@3
+  char v5; // cl@4
+  FrameTableTxtLine *result; // eax@21
+  signed int v7; // [sp+Ch] [bp-4h]@3
+
+  static struct FrameTableTxtLine static_stru_F8BA58; // weak
+  static_stru_F8BA58.field_0 = 0;
+  if ( _this && *_this )
+  {
+    v2 = (char *)&unk_F8B668;
+    v3 = 1;
+    v7 = 0;
+    v4 = _this - (char *)&unk_F8B668;
+    do
+    {
+      v5 = v2[v4];
+      *v2 = v5;
+      if ( !v5 )
+        break;
+      if ( v5 != 32 && v5 != 44 && v5 != 9 || v7 )
+      {
+        if ( v5 == 34 )
+        {
+          *v2 = 0;
+          v3 = 1;
+          if ( v7 )
+          {
+            v7 = 0;
+          }
+          else
+          {
+            v7 = 1;
+            if ( v2[v4 + 1] == 34 )
+            {
+              static_stru_F8BA58.pProperties[static_stru_F8BA58.field_0] = v2;
+              ++static_stru_F8BA58.field_0;
+            }
+          }
+        }
+        else
+        {
+          if ( v3 )
+          {
+            static_stru_F8BA58.pProperties[static_stru_F8BA58.field_0] = v2;
+            ++static_stru_F8BA58.field_0;
+          }
+          v3 = 0;
+        }
+      }
+      else
+      {
+        *v2 = 0;
+        v3 = 1;
+      }
+      if ( static_stru_F8BA58.field_0 >= 30 )
+        break;
+      ++v2;
+    }
+    while ( (unsigned int)v2 < (unsigned int)&unk_F8BA50 );
+    *v2 = 0;
+  }
+  result = a2;
+  memcpy(a2, &static_stru_F8BA58, 0x7Cu);
+  return result;
+}
+// F8BA58: using guessed type FrameTableTxtLine static_stru_F8BA58;
+
+//----- (004BE485) --------------------------------------------------------
+FrameTableTxtLine *__thiscall frame_table_txt_parser(const char *pString, FrameTableTxtLine *a2)
+{
+  char *v2; // eax@3
+  signed int v3; // edi@3
+  signed int v4; // edx@3
+  char v5; // cl@4
+  FrameTableTxtLine *result; // eax@24
+  unsigned int v7; // [sp+Ch] [bp-4h]@3
+
+  stru_F8B5E8.field_0 = 0;
+  if ( pString && *pString )
+  {
+    v2 = (char *)&unk_F8B1F8;
+    v3 = 0;
+    v7 = pString - (const char *)&unk_F8B1F8;
+    v4 = 1;
+    while ( 1 )
+    {
+      v5 = v2[v7];
+      *v2 = v5;
+      if ( !v5 )
+      {
+LABEL_23:
+        *v2 = 0;
+        break;
+      }
+      if ( v5 == ',' )
+      {
+        if ( v3 )
+          goto LABEL_18;
+        *v2 = 0;
+      }
+      else
+      {
+        if ( v5 != '\t' )
+        {
+          if ( v5 == '"' )
+          {
+            *v2 = 0;
+            v4 = 1;
+            if ( v3 )
+            {
+              v3 = 0;
+            }
+            else
+            {
+              v3 = 1;
+              if ( v2[v7 + 1] == 34 )
+              {
+                stru_F8B5E8.pProperties[stru_F8B5E8.field_0] = v2;
+                ++stru_F8B5E8.field_0;
+              }
+            }
+            goto LABEL_21;
+          }
+LABEL_18:
+          if ( v4 )
+          {
+            stru_F8B5E8.pProperties[stru_F8B5E8.field_0] = v2;
+            ++stru_F8B5E8.field_0;
+          }
+          v4 = 0;
+          goto LABEL_21;
+        }
+        if ( v3 )
+          goto LABEL_18;
+        *v2 = 0;
+        if ( v4 )
+        {
+          stru_F8B5E8.pProperties[stru_F8B5E8.field_0] = v2;
+          ++stru_F8B5E8.field_0;
+        }
+      }
+      v4 = 1;
+LABEL_21:
+      if ( stru_F8B5E8.field_0 < 30 )
+      {
+        ++v2;
+        if ( (unsigned int)v2 < (unsigned int)&unk_F8B5E0 )
+          continue;
+      }
+      goto LABEL_23;
+    }
+  }
+  result = a2;
+  memcpy(a2, &stru_F8B5E8, 0x7Cu);
+  return result;
+}
+// F8B5E8: using guessed type FrameTableTxtLine stru_F8B5E8;
+
+//----- (004BE571) --------------------------------------------------------
+int __fastcall sub_4BE571(int a1, int *a2, int a3, int a4)
+{
+  int result; // eax@1
+  int i; // esi@3
+
+  result = a3;
+  if ( a3 < a4 )
+  {
+    for ( i = 0; i < a3; ++i )
+    {
+      if ( a1 == a2[i] )
+        break;
+    }
+    if ( i == a3 )
+    {
+      a2[a3] = a1;
+      result = a3 + 1;
+    }
+  }
+  else
+  {
+    result = a4;
+  }
+  return result;
+}
+
+
+
+//----- (004BF91E) --------------------------------------------------------
+unsigned int __thiscall GameOverMenu(void *ecx0)
+{
+  char *v1; // eax@2
+  unsigned int result; // eax@3
+  char *v3; // eax@7
+  char *v4; // ST24_4@9
+  int v5; // eax@9
+  char *v6; // eax@10
+  char *v7; // edx@10
+  char *v8; // ecx@12
+  char *v9; // eax@14
+  unsigned int v10; // eax@25
+  GUIWindow pWindow; // [sp+34h] [bp-9Ch]@1
+  MSG Msg; // [sp+88h] [bp-48h]@22
+  unsigned int v14; // [sp+A4h] [bp-2Ch]@5
+  void *v15; // [sp+A8h] [bp-28h]@1
+  char *pInString; // [sp+ACh] [bp-24h]@5
+  unsigned int v17; // [sp+B0h] [bp-20h]@5
+  unsigned int v18; // [sp+B4h] [bp-1Ch]@5
+  unsigned int v19; // [sp+B8h] [bp-18h]@5
+  int v20; // [sp+BCh] [bp-14h]@7
+  int i; // [sp+C0h] [bp-10h]@7
+  GUIFont *pFont; // [sp+C4h] [bp-Ch]@1
+  unsigned __int64 v23; // [sp+C8h] [bp-8h]@5
+
+  v15 = ecx0;
+
+  RGBTexture _this; // [sp+Ch] [bp-C4h]@1
+  //RGBTexture::RGBTexture(&this);
+
+  BYTE1(dword_6BE364_game_settings_1) &= 0xBFu;
+  bGameoverLoop = 1;
+  pVideoPlayer->bStopBeforeSchedule = 0;
+  pAudioPlayer->StopChannels(-1, -1);
+  pRenderer->BeginScene();
+  pRenderer->ClearBlack();
+  pRenderer->EndScene();
+  pRenderer->Present();
+  pVideoPlayer->field_40 = 0;
+  _449B57_test_bit(pParty->_award_bits, 99);
+  _this.Load("winbg.pcx", 2);
+  pRenderer->BeginScene();
+  pRenderer->DrawTextureRGB(0, 0, &_this);
+  pRenderer->EndScene();
+  free(_this.pPixels);
+  _this.pPixels = 0;
+  ptr_507BC0 = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0);
+  pWindow.uFrameX = 75;
+  pWindow.uFrameY = 60;
+  pWindow.uFrameWidth = 469;
+  pWindow.uFrameHeight = 338;
+  pWindow.uFrameZ = 543;
+  pWindow.uFrameW = 397;
+  pFont = LoadFont("endgame.fnt", "FONTPAL", 0);
+  if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 99) )
+  {
+    v1 = pGlobalTXT_LocalizationStrings[675];
+  }
+  else
+  {
+    result = _449B57_test_bit(pParty->_award_bits, 100);
+    if ( !(short)result )
+      return result;
+    v1 = pGlobalTXT_LocalizationStrings[676];
+  }
+  pInString = v1;
+  v23 = pParty->uTimePlayed - 138240;
+  v19 = (unsigned int)((signed __int64)((double)(pParty->uTimePlayed - 138240) * 0.234375) / 60 / 60) / 0x18;
+  v14 = (unsigned int)((signed __int64)((double)(pParty->uTimePlayed - 138240) * 0.234375) / 60 / 60) / 0x18 / 0x1C / 0xC;
+  v18 = (unsigned int)((signed __int64)((double)(pParty->uTimePlayed - 138240) * 0.234375) / 60 / 60) / 0x18 / 0x1C % 0xC;
+  v17 = v19 % 0x1C;
+  if ( !v19 )
+    v19 = 1;
+  pRenderer->BeginScene();
+  pWindow.DrawTitleText(pFont, 1u, 0x23u, 1u, pGlobalTXT_LocalizationStrings[9], 3u);
+  v3 = pParty->pPlayers[0].pName;
+  v23 = 0i64;
+  v20 = 0;
+  for ( i = (int)pParty->pPlayers[0].pName; ; v3 = (char *)i )
+  {
+    v4 = pClassNames[(unsigned __int8)v3[17]];
+    v5 = ((Player *)(v3 - 168))->GetBaseLevel();
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[129], i, v5, v4);
+    pWindow.DrawTitleText(
+      pFont,
+      1u,
+      v20 * (LOBYTE(pFont->uFontHeight) - 2) + LOBYTE(pFont->uFontHeight) + 46,
+      1u,
+      pTmpBuf,
+      3u);
+    v23 += __PAIR__(*(int *)(i - 4), *(int *)(i - 8));
+    ++v20;
+    i += 6972;
+    if ( i >= (signed int)&pParty->pPickedItem.uNumCharges )
+      break;
+  }
+  v23 = (signed __int64)v23 / v19;
+  v6 = FitTextInAWindow(pInString, pFont, &pWindow, 0xCu, 0);
+  pWindow.DrawTitleText(pFont, 1u, 5 * (LOBYTE(pFont->uFontHeight) + 11), 1u, v6, 0);
+  strcpy(pTmpBuf, pGlobalTXT_LocalizationStrings[37]);
+  v7 = pGlobalTXT_LocalizationStrings[56];
+  if ( v17 != 1 )
+    v7 = pGlobalTXT_LocalizationStrings[57];
+  v8 = pGlobalTXT_LocalizationStrings[146];
+  if ( v18 != 1 )
+    v8 = pGlobalTXT_LocalizationStrings[148];
+  v9 = pGlobalTXT_LocalizationStrings[245];
+  if ( v14 != 1 )
+    v9 = pGlobalTXT_LocalizationStrings[132];
+  sprintf(pTmpBuf2, " %lu %s, %lu %s, %lu %s ", v14, v9, v18, v8, v17, v7);
+  strcat(pTmpBuf, pTmpBuf2);
+  pWindow.DrawTitleText(pFont, 1u, pWindow.uFrameHeight - 2 * LOBYTE(pFont->uFontHeight) - 5, 1u, pTmpBuf, 3u);
+  sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[94], v23);
+  pWindow.DrawTitleText(pFont, 1u, pWindow.uFrameHeight, 1u, pTmpBuf, 3u);
+  BYTE1(dword_6BE364_game_settings_1) |= 0x40u;
+  pRenderer->EndScene();
+  pRenderer->Present();
+  if ( pRenderer->pRenderD3D )
+    pRenderer->pBeforePresentFunction();
+  pRenderer->_49F1BC("MM7_Win.Pcx");
+  pAllocator->FreeChunk(pFont);
+  ptr_507BC0->Release();
+  ptr_507BC0 = 0;
+  if ( v15 == (void *)2 )
+  {
+    result = pMessageQueue_50CBD0->uNumMessages;
+  }
+  else
+  {
+    LODWORD(v23) = GetTickCount() + 5000;
+    while ( (unsigned int)v23 > GetTickCount() )
+      ;
+    while ( 1 )
+    {
+      v10 = PeekMessageA(&Msg, 0, 0, 0, 1u);
+      if ( !v10 )
+        break;
+      if ( Msg.message == 18 )
+        Game_DeinitializeAndTerminate(0);
+      TranslateMessage(&Msg);
+      DispatchMessageA(&Msg);
+    }
+    if ( pMessageQueue_50CBD0->uNumMessages )
+    {
+      LOBYTE(v10) = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+      pMessageQueue_50CBD0->uNumMessages = v10;
+    }
+    pKeyActionMap->ResetKeys();
+    pKeyActionMap->uLastKeyPressed = 0;
+    do
+    {
+      while ( PeekMessageA(&Msg, 0, 0, 0, 1u) )
+      {
+        if ( Msg.message == 18 )
+          Game_DeinitializeAndTerminate(0);
+        TranslateMessage(&Msg);
+        DispatchMessageA(&Msg);
+      }
+    }
+    while ( !pKeyActionMap->uLastKeyPressed );
+    result = pMessageQueue_50CBD0->uNumMessages;
+    if ( pMessageQueue_50CBD0->uNumMessages )
+    {
+      result = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+      pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+    }
+  }
+  if ( v15 )
+  {
+    if ( (signed int)result < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[result].eType = (UIMessageType)132;
+      goto LABEL_42;
+    }
+  }
+  else
+  {
+    if ( (signed int)result < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[result].eType = (UIMessageType)197;
+LABEL_42:
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+      result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
+      *(&pMessageQueue_50CBD0->uNumMessages + result) = 0;
+      ++pMessageQueue_50CBD0->uNumMessages;
+      goto LABEL_43;
+    }
+  }
+LABEL_43:
+  bGameoverLoop = 0;
+  return result;
+}
+
+
+//----- (004C0262) --------------------------------------------------------
+void Viewport::SetScreen(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW)
+{
+  unsigned int x; // edx@1
+  unsigned int z; // esi@1
+  unsigned int y; // edi@3
+  unsigned int w; // eax@3
+  char no_3d; // zf@5
+  int v10; // eax@7
+
+  x = uX;
+  z = uZ;
+  if ( (signed int)uX > (signed int)uZ )
+  {
+    z = uZ ^ uX ^ uZ;                           // swap x and z
+    x = z ^ uZ ^ uX;
+  }
+  y = uY;
+  w = uW;
+  if ( (signed int)uY > (signed int)uW )
+  {
+    w = uW ^ uY ^ uW;                           // swap y and w
+    y = w ^ uW ^ uY;
+  }
+  this->uScreenX = x;
+  this->uScreenY = y;
+  this->uScreenZ = z;
+  this->uScreenW = w;
+  no_3d = pRenderer->pRenderD3D == 0;
+  this->uScreenWidth = z - x + 1;
+  this->uScreenCenterX = (signed int)(z + x) >> 1;
+  if ( no_3d )
+  {
+    v10 = w - y + 1;
+    this->uScreenHeight = v10;
+    this->uScreenCenterY = this->uScreenW - ((unsigned __int64)(this->field_30 * (signed __int64)v10) >> 16);
+  }
+  else
+  {
+    this->uScreenHeight = w - y + 1;
+    this->uScreenCenterY = (signed int)(w + y) >> 1;
+  }
+  SetViewport(this->uScreenX, this->uScreenY, this->uScreenZ, this->uScreenW);
+}
+
+//----- (004C02F8) --------------------------------------------------------
+void Viewport::_4C02F8(int a2)
+{
+  unsigned int v2; // ST0C_4@1
+
+  v2 = this->uScreenW;
+  this->field_30 = a2;
+  SetScreen(this->uScreenX, this->uScreenY, this->uScreenZ, v2);
+}
+
+//----- (004C0312) --------------------------------------------------------
+void Viewport::SetViewport(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW)
+{
+  unsigned int x; // ebx@1
+  unsigned int y; // edi@3
+  unsigned int z; // edx@5
+  unsigned int w; // eax@7
+
+  x = uX;
+  if ( (signed int)uX < (signed int)this->uScreenX )
+    x = this->uScreenX;
+  y = uY;
+  if ( (signed int)uY < (signed int)this->uScreenY )
+    y = this->uScreenY;
+  z = uZ;
+  if ( (signed int)uZ > (signed int)this->uScreenZ )
+    z = this->uScreenZ;
+  w = uW;
+  if ( (signed int)uW > (signed int)this->uScreenW )
+    w = this->uScreenW;
+  this->uViewportY = y;
+  this->uViewportX = x;
+  this->uViewportZ = z;
+  this->uViewportW = w;
+}
+
+
+
+
+
+
+//----- (004D6FB0) --------------------------------------------------------
+int /*__usercall*/ sr_sub_4D6FB0/*<eax>*/(stru315 *a1/*<ebp>*/)
+{
+  int v1; // ebp@1
+  unsigned int v2; // esi@1
+  unsigned int v3; // edi@1
+  int result; // eax@1
+  int v5; // ebx@2
+  int v6; // edx@2
+  int v7; // ebx@3
+  __int16 v8; // cx@3
+  int v9; // ebx@4
+  unsigned __int8 v10; // sf@5
+  unsigned __int8 v11; // of@5
+
+  v1 = a1->field_8;
+  v2 = *(int *)(v1 + 48);
+  v3 = *(int *)(v1 + 44);
+  result = *(int *)(v1 + 64);
+  if ( !(*(int *)(v1 + 40) & 1) )
+    goto LABEL_5;
+  --*(int *)(v1 + 40);
+  result -= 2;
+  v5 = *(int *)(v1 + 60);
+  v6 = *(int *)(v1 + 36);
+  *(int *)(v1 + 60) += 4;
+  while ( 1 )
+  {
+    *(int *)v5 = v6;
+    v9 = *(char *)(*(int *)(v1 + 56)
+                  + (*(int *)(v1 + 12) & (v2 >> 16))
+                  + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16)));
+    result += 4;
+    v2 += *(int *)(v1 + 4);
+    v3 += *(int *)v1;
+    *(short *)(result - 2) = *(short *)(*(int *)(v1 + 52) + 2 * v9);
+LABEL_5:
+    v11 = __OFSUB__(*(int *)(v1 + 40), 2);
+    v10 = *(int *)(v1 + 40) - 2 < 0;
+    *(int *)(v1 + 40) -= 2;
+    if ( v10 ^ v11 )
+      break;
+    v7 = *(char *)(*(int *)(v1 + 56)
+                  + (*(int *)(v1 + 12) & (v2 >> 16))
+                  + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16)));
+    v2 += *(int *)(v1 + 4);
+    v8 = *(short *)(*(int *)(v1 + 52) + 2 * v7);
+    v3 += *(int *)v1;
+    v5 = *(int *)(v1 + 60);
+    v6 = *(int *)(v1 + 36);
+    *(short *)result = v8;
+    *(int *)(v1 + 60) += 8;
+    *(int *)(v5 + 4) = v6;
+  }
+  *(int *)(v1 + 64) = result;
+  *(int *)(v1 + 48) = v2;
+  *(int *)(v1 + 44) = v3;
+  return result;
+}
+
+//----- (004D705A) --------------------------------------------------------
+int /*__usercall*/ sr_sub_4D705A/*<eax>*/(stru315 *a1/*<ebp>*/)
+{
+  int v1; // ebp@1
+  unsigned int v2; // esi@1
+  unsigned int v3; // edi@1
+  int result; // eax@1
+  int v5; // ebx@2
+  int v6; // edx@2
+  unsigned int v7; // ebx@3
+  unsigned int v8; // edx@3
+  __int16 v9; // cx@11
+  unsigned int v10; // ebx@12
+  unsigned int v11; // edx@12
+  unsigned __int8 v12; // sf@21
+  unsigned __int8 v13; // of@21
+
+  v1 = a1->field_8;
+  v2 = *(int *)(v1 + 48);
+  v3 = *(int *)(v1 + 44);
+  result = *(int *)(v1 + 64);
+  if ( !(*(int *)(v1 + 40) & 1) )
+    goto LABEL_21;
+  --*(int *)(v1 + 40);
+  result -= 2;
+  v5 = *(int *)(v1 + 60);
+  v6 = *(int *)(v1 + 36);
+  *(int *)(v1 + 60) += 4;
+  while ( 1 )
+  {
+    *(int *)v5 = v6;
+    v10 = v3;
+    v11 = v2;
+    if ( (signed int)v2 < *(int *)(v1 + 20) )
+      v11 = *(int *)(v1 + 20);
+    if ( (signed int)v3 < *(int *)(v1 + 28) )
+      v10 = *(int *)(v1 + 28);
+    if ( (signed int)v11 > *(int *)(v1 + 24) )
+      v11 = *(int *)(v1 + 24);
+    if ( (signed int)v10 > *(int *)(v1 + 32) )
+      v10 = *(int *)(v1 + 32);
+    result += 4;
+    v2 += *(int *)(v1 + 4);
+    v3 += *(int *)v1;
+    *(short *)(result - 2) = *(short *)(*(int *)(v1 + 52)
+                                      + 2
+                                      * *(char *)(*(int *)(v1 + 56)
+                                                 + (*(int *)(v1 + 12) & (v11 >> 16))
+                                                 + ((*(int *)(v1 + 8) & v10) >> *(char *)(v1 + 16))));
+LABEL_21:
+    v13 = __OFSUB__(*(int *)(v1 + 40), 2);
+    v12 = *(int *)(v1 + 40) - 2 < 0;
+    *(int *)(v1 + 40) -= 2;
+    if ( v12 ^ v13 )
+      break;
+    v7 = v3;
+    v8 = v2;
+    if ( (signed int)v2 < *(int *)(v1 + 20) )
+      v8 = *(int *)(v1 + 20);
+    if ( (signed int)v3 < *(int *)(v1 + 28) )
+      v7 = *(int *)(v1 + 28);
+    if ( (signed int)v8 > *(int *)(v1 + 24) )
+      v8 = *(int *)(v1 + 24);
+    if ( (signed int)v7 > *(int *)(v1 + 32) )
+      v7 = *(int *)(v1 + 32);
+    v2 += *(int *)(v1 + 4);
+    v9 = *(short *)(*(int *)(v1 + 52)
+                  + 2
+                  * *(char *)(*(int *)(v1 + 56)
+                             + (*(int *)(v1 + 12) & (v8 >> 16))
+                             + ((*(int *)(v1 + 8) & v7) >> *(char *)(v1 + 16))));
+    v3 += *(int *)v1;
+    v5 = *(int *)(v1 + 60);
+    v6 = *(int *)(v1 + 36);
+    *(short *)result = v9;
+    *(int *)(v1 + 60) += 8;
+    *(int *)(v5 + 4) = v6;
+  }
+  *(int *)(v1 + 64) = result;
+  *(int *)(v1 + 48) = v2;
+  *(int *)(v1 + 44) = v3;
+  return result;
+}
+
+//----- (004D714C) --------------------------------------------------------
+int __cdecl sr_sub_4D714C(stru315 *a1)
+{
+  stru315 *v1; // ebp@0
+  stru315 *v2; // ebp@1
+  unsigned int v3; // esi@1
+  int v4; // edi@1
+  int result; // eax@1
+  unsigned int *v6; // ebx@2
+  int v7; // edx@2
+  int v8; // ebx@3
+  unsigned __int16 v9; // cx@3
+  unsigned int *v10; // ebx@3
+  int v11; // edx@3
+  int v12; // ebx@4
+  unsigned __int8 v13; // sf@5
+  unsigned __int8 v14; // of@5
+
+  v2 = (stru315 *)v1->field_8;
+  v3 = v2->field_30;
+  v4 = v2->field_2C;
+  result = (int)v2->pColorBuffer;
+  if ( !(v2->field_28 & 1) )
+    goto LABEL_5;
+  --v2->field_28;
+  result += 2;
+  v6 = v2->pDepthBuffer;
+  v7 = v2->field_24;
+  --v2->pDepthBuffer;
+  *v6 = v7;
+  while ( 1 )
+  {
+    v12 = *((char *)v2->pTextureLOD
+          + (v2->field_C & (v3 >> 16))
+          + ((v2->field_8 & (unsigned int)v4) >> LOBYTE(v2->field_10)));
+    result -= 4;
+    v3 += v2->field_4;
+    v4 += v2->field_0;
+    *(short *)(result + 2) = v2->field_34_palette[v12];
+LABEL_5:
+    v14 = __OFSUB__(v2->field_28, 2);
+    v13 = v2->field_28 - 2 < 0;
+    v2->field_28 -= 2;
+    if ( v13 ^ v14 )
+      break;
+    v8 = *((char *)v2->pTextureLOD
+         + (v2->field_C & (v3 >> 16))
+         + ((v2->field_8 & (unsigned int)v4) >> LOBYTE(v2->field_10)));
+    v3 += v2->field_4;
+    v9 = v2->field_34_palette[v8];
+    v4 += v2->field_0;
+    v10 = v2->pDepthBuffer;
+    v11 = v2->field_24;
+    *(short *)result = v9;
+    v2->pDepthBuffer -= 2;
+    *v10 = v11;
+    *(v10 - 1) = v11;
+  }
+  v2->pColorBuffer = (unsigned __int16 *)result;
+  v2->field_30 = v3;
+  v2->field_2C = v4;
+  return result;
+}
+// 4D714C: inconsistent function type and number of purged bytes
+
+//----- (004D71F8) --------------------------------------------------------
+int __cdecl sr_sub_4D71F8(stru315 *a1)
+{
+  stru315 *v1; // ebp@0
+  stru315 *v2; // ebp@1
+  int v3; // esi@1
+  int v4; // edi@1
+  int result; // eax@1
+  unsigned int *v6; // ebx@2
+  int v7; // edx@2
+  int v8; // ebx@3
+  unsigned int v9; // edx@3
+  unsigned __int16 v10; // cx@11
+  unsigned int *v11; // ebx@11
+  int v12; // edx@11
+  int v13; // ebx@12
+  unsigned int v14; // edx@12
+  unsigned __int8 v15; // sf@21
+  unsigned __int8 v16; // of@21
+
+  v2 = (stru315 *)v1->field_8;
+  v3 = v2->field_30;
+  v4 = v2->field_2C;
+  result = (int)v2->pColorBuffer;
+  if ( !(v2->field_28 & 1) )
+    goto LABEL_21;
+  --v2->field_28;
+  result += 2;
+  v6 = v2->pDepthBuffer;
+  v7 = v2->field_24;
+  --v2->pDepthBuffer;
+  *v6 = v7;
+  while ( 1 )
+  {
+    v13 = v4;
+    v14 = v3;
+    if ( v3 < v2->field_14 )
+      v14 = v2->field_14;
+    if ( v4 < v2->field_1C )
+      v13 = v2->field_1C;
+    if ( (signed int)v14 > v2->field_18 )
+      v14 = v2->field_18;
+    if ( v13 > v2->field_20 )
+      v13 = v2->field_20;
+    result -= 4;
+    v3 += v2->field_4;
+    v4 += v2->field_0;
+    *(short *)(result + 2) = v2->field_34_palette[*((char *)v2->pTextureLOD
+                                                  + (v2->field_C & (v14 >> 16))
+                                                  + ((v2->field_8 & (unsigned int)v13) >> LOBYTE(v2->field_10)))];
+LABEL_21:
+    v16 = __OFSUB__(v2->field_28, 2);
+    v15 = v2->field_28 - 2 < 0;
+    v2->field_28 -= 2;
+    if ( v15 ^ v16 )
+      break;
+    v8 = v4;
+    v9 = v3;
+    if ( v3 < v2->field_14 )
+      v9 = v2->field_14;
+    if ( v4 < v2->field_1C )
+      v8 = v2->field_1C;
+    if ( (signed int)v9 > v2->field_18 )
+      v9 = v2->field_18;
+    if ( v8 > v2->field_20 )
+      v8 = v2->field_20;
+    v3 += v2->field_4;
+    v10 = v2->field_34_palette[*((char *)v2->pTextureLOD
+                               + (v2->field_C & (v9 >> 16))
+                               + ((v2->field_8 & (unsigned int)v8) >> LOBYTE(v2->field_10)))];
+    v4 += v2->field_0;
+    v11 = v2->pDepthBuffer;
+    v12 = v2->field_24;
+    *(short *)result = v10;
+    v2->pDepthBuffer -= 2;
+    *v11 = v12;
+    *(v11 - 1) = v12;
+  }
+  v2->pColorBuffer = (unsigned __int16 *)result;
+  v2->field_30 = v3;
+  v2->field_2C = v4;
+  return result;
+}
+// 4D71F8: inconsistent function type and number of purged bytes
+
+//----- (004D72EC) --------------------------------------------------------
+int /*__usercall*/ sr_sub_4D72EC/*<eax>*/(int a1/*<ebp>*/)
+{
+  int v1; // ebp@1
+  unsigned int v2; // esi@1
+  unsigned int v3; // edi@1
+  int result; // eax@1
+  int v5; // ebx@2
+  int v6; // edx@2
+  unsigned int v7; // edx@3
+  unsigned int v8; // ebx@3
+  int v9; // ebx@11
+  unsigned int v10; // edx@14
+  unsigned int v11; // ebx@14
+  int v12; // ebx@22
+  unsigned __int8 v13; // sf@25
+  unsigned __int8 v14; // of@25
+
+  v1 = *(int *)(a1 + 8);
+  v2 = *(int *)(v1 + 48);
+  v3 = *(int *)(v1 + 44);
+  result = *(int *)(v1 + 64);
+  if ( !(*(int *)(v1 + 40) & 1) )
+    goto LABEL_25;
+  --*(int *)(v1 + 40);
+  result -= 2;
+  v5 = *(int *)(v1 + 60);
+  v6 = *(int *)(v1 + 36);
+  *(int *)(v1 + 60) += 4;
+  while ( 1 )
+  {
+    *(int *)v5 = v6;
+    v10 = v2;
+    v11 = v3;
+    if ( (signed int)v2 < *(int *)(v1 + 20) )
+      v10 = *(int *)(v1 + 20);
+    if ( (signed int)v3 < *(int *)(v1 + 28) )
+      v11 = *(int *)(v1 + 28);
+    if ( (signed int)v10 > *(int *)(v1 + 24) )
+      v10 = *(int *)(v1 + 24);
+    if ( (signed int)v11 > *(int *)(v1 + 32) )
+      v11 = *(int *)(v1 + 32);
+    v12 = *(char *)(*(int *)(v1 + 56)
+                   + (*(int *)(v1 + 12) & (v10 >> 16))
+                   + ((*(int *)(v1 + 8) & v11) >> *(char *)(v1 + 16)));
+    result += 4;
+    v2 += *(int *)(v1 + 4);
+    if ( v12 )
+      *(short *)(result - 2) = *(short *)(*(int *)(v1 + 52) + 2 * v12);
+    v3 += *(int *)v1;
+LABEL_25:
+    v14 = __OFSUB__(*(int *)(v1 + 40), 2);
+    v13 = *(int *)(v1 + 40) - 2 < 0;
+    *(int *)(v1 + 40) -= 2;
+    if ( v13 ^ v14 )
+      break;
+    v7 = v2;
+    v8 = v3;
+    if ( (signed int)v2 < *(int *)(v1 + 20) )
+      v7 = *(int *)(v1 + 20);
+    if ( (signed int)v3 < *(int *)(v1 + 28) )
+      v8 = *(int *)(v1 + 28);
+    if ( (signed int)v7 > *(int *)(v1 + 24) )
+      v7 = *(int *)(v1 + 24);
+    if ( (signed int)v8 > *(int *)(v1 + 32) )
+      v8 = *(int *)(v1 + 32);
+    v9 = *(char *)(*(int *)(v1 + 56)
+                  + (*(int *)(v1 + 12) & (v7 >> 16))
+                  + ((*(int *)(v1 + 8) & v8) >> *(char *)(v1 + 16)));
+    v2 += *(int *)(v1 + 4);
+    if ( v9 )
+      *(short *)result = *(short *)(*(int *)(v1 + 52) + 2 * v9);
+    v3 += *(int *)v1;
+    v5 = *(int *)(v1 + 60);
+    v6 = *(int *)(v1 + 36);
+    *(int *)(v1 + 60) += 8;
+    *(int *)(v5 + 4) = v6;
+  }
+  return result;
+}
+
+//----- (004D73DF) --------------------------------------------------------
+int /*__usercall*/ sr_sub_4D73DF/*<eax>*/(int a1/*<ebp>*/)
+{
+  int v1; // ebp@1
+  unsigned int v2; // esi@1
+  unsigned int v3; // edi@1
+  int result; // eax@1
+  int v5; // ebx@2
+  int v6; // edx@2
+  int v7; // edx@3
+  int v8; // edx@6
+  unsigned __int8 v9; // sf@9
+  unsigned __int8 v10; // of@9
+
+  v1 = *(int *)(a1 + 8);
+  v2 = *(int *)(v1 + 48);
+  v3 = *(int *)(v1 + 44);
+  result = *(int *)(v1 + 64);
+  if ( !(*(int *)(v1 + 40) & 1) )
+    goto LABEL_9;
+  --*(int *)(v1 + 40);
+  result -= 2;
+  v5 = *(int *)(v1 + 60);
+  v6 = *(int *)(v1 + 36);
+  *(int *)(v1 + 60) += 4;
+  while ( 1 )
+  {
+    *(int *)v5 = v6;
+    v8 = *(int *)(v1 + 12) & (v2 >> 16);
+    result += 4;
+    v2 += *(int *)(v1 + 4);
+    if ( *(char *)(*(int *)(v1 + 56) + v8 + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16))) )
+      *(short *)(result - 2) = *(short *)(*(int *)(v1 + 52)
+                                        + 2
+                                        * *(char *)(*(int *)(v1 + 56)
+                                                   + v8
+                                                   + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16))));
+    v3 += *(int *)v1;
+LABEL_9:
+    v10 = __OFSUB__(*(int *)(v1 + 40), 2);
+    v9 = *(int *)(v1 + 40) - 2 < 0;
+    *(int *)(v1 + 40) -= 2;
+    if ( v9 ^ v10 )
+      break;
+    v7 = *(int *)(v1 + 12) & (v2 >> 16);
+    v2 += *(int *)(v1 + 4);
+    if ( *(char *)(*(int *)(v1 + 56) + v7 + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16))) )
+      *(short *)result = *(short *)(*(int *)(v1 + 52)
+                                  + 2
+                                  * *(char *)(*(int *)(v1 + 56)
+                                             + v7
+                                             + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16))));
+    v3 += *(int *)v1;
+    v5 = *(int *)(v1 + 60);
+    v6 = *(int *)(v1 + 36);
+    *(int *)(v1 + 60) += 8;
+    *(int *)(v5 + 4) = v6;
+  }
+  return result;
+}
+
+//----- (004D754B) --------------------------------------------------------
+void __cdecl sr_sub_4D754B(stru315 *a1, stru316 *a2)
+{
+  int v2; // ecx@1
+  unsigned int v3; // eax@2
+  int v4; // ecx@2
+  int v5; // eax@10
+  unsigned __int16 *v6; // edx@10
+  int v7; // ebx@11
+  int v8; // ecx@13
+  unsigned __int16 v9; // bx@16
+  int v10; // ecx@16
+  unsigned __int16 *v11; // eax@16
+  unsigned int *v12; // edx@16
+  int v13; // ecx@16
+  int v14; // eax@16
+  int v15; // ebx@16
+  int v16; // [sp-4h] [bp-Ch]@2
+
+  v2 = a1->field_28;
+  if ( v2 )
+  {
+    do
+    {
+      v16 = v2;
+      v3 = a1->field_30;
+      v4 = a1->field_2C;
+      if ( (signed int)v3 >= a1->field_18 )
+        v3 = a1->field_18;
+      if ( (signed int)v3 <= a1->field_14 )
+        v3 = a1->field_14;
+      if ( v4 >= a1->field_20 )
+        v4 = a1->field_20;
+      if ( v4 <= a1->field_1C )
+        v4 = a1->field_1C;
+      v5 = *((char *)a1->pTextureLOD + (a1->field_C & (v3 >> 16)) + (((unsigned int)v4 & a1->field_8) >> a1->field_10));
+      v6 = a1->field_34_palette;
+      if ( a2->field_20 )
+      {
+        v7 = (unsigned int)a2->field_10 >> 16;
+        if ( v7 >= a2->field_C )
+          v7 = a2->field_C;
+        v8 = 0;
+        if ( a2->field_8 - v7 >= 0 )
+          v8 = a2->field_8 - v7;
+        v5 += v8 << 8;
+        v6 = a2->field_24_palette;
+      }
+      v9 = v6[v5];
+      v10 = a1->field_24;
+      v11 = a1->pColorBuffer;
+      v12 = a1->pDepthBuffer;
+      *v11 = v9;
+      *v12 = v10;
+      a1->pColorBuffer = v11 + 1;
+      a1->pDepthBuffer = v12 + 1;
+      v13 = a1->field_30;
+      a2->field_10 += a2->field_18;
+      v14 = a1->field_2C;
+      v15 = a1->field_0;
+      a1->field_30 = a1->field_4 + v13;
+      a1->field_2C = v15 + v14;
+      v2 = v16 - 1;
+    }
+    while ( v16 != 1 );
+  }
+}
+
+//----- (004D7630) --------------------------------------------------------
+void __cdecl sr_sub_4D7630(stru315 *a1, stru316 *a2)
+{
+  int v2; // ecx@1
+  int v3; // eax@2
+  unsigned __int16 *v4; // edx@2
+  int v5; // ebx@3
+  int v6; // ecx@5
+  unsigned __int16 v7; // bx@8
+  int v8; // ecx@8
+  unsigned __int16 *v9; // eax@8
+  unsigned int *v10; // edx@8
+  int v11; // ecx@8
+  int v12; // eax@8
+  int v13; // ebx@8
+  int v14; // [sp-4h] [bp-Ch]@2
+
+  v2 = a1->field_28;
+  if ( v2 )
+  {
+    do
+    {
+      v14 = v2;
+      v3 = *((char *)a1->pTextureLOD
+           + (a1->field_C & ((unsigned int)a1->field_30 >> 16))
+           + ((unsigned int)(a1->field_2C & a1->field_8) >> a1->field_10));
+      v4 = a1->field_34_palette;
+      if ( a2->field_20 )
+      {
+        v5 = (unsigned int)a2->field_14 >> 16;
+        if ( v5 >= a2->field_C )
+          v5 = a2->field_C;
+        v6 = 0;
+        if ( a2->field_8 - v5 >= 0 )
+          v6 = a2->field_8 - v5;
+        v3 += v6 << 8;
+        v4 = a2->field_24_palette;
+      }
+      v7 = v4[v3];
+      v8 = a1->field_24;
+      v9 = a1->pColorBuffer;
+      v10 = a1->pDepthBuffer;
+      *v9 = v7;
+      *v10 = v8;
+      a1->pColorBuffer = v9 - 1;
+      a1->pDepthBuffer = v10 - 1;
+      v11 = a1->field_30;
+      a2->field_14 -= a2->field_18;
+      v12 = a1->field_2C;
+      v13 = a1->field_0;
+      a1->field_30 = a1->field_4 + v11;
+      a1->field_2C = v13 + v12;
+      v2 = v14 - 1;
+    }
+    while ( v14 != 1 );
+  }
+}
+
+//----- (004D76ED) --------------------------------------------------------
+void __cdecl sr_sub_4D76ED(stru315 *a1, stru316 *a2)
+{
+  int v2; // ecx@1
+  unsigned int v3; // eax@2
+  int v4; // ecx@2
+  int v5; // eax@10
+  unsigned __int16 *v6; // edx@10
+  int v7; // ebx@11
+  int v8; // ecx@13
+  unsigned __int16 v9; // bx@16
+  int v10; // ecx@16
+  unsigned __int16 *v11; // eax@16
+  unsigned int *v12; // edx@16
+  int v13; // ecx@16
+  int v14; // eax@16
+  int v15; // ebx@16
+  int v16; // [sp-4h] [bp-Ch]@2
+
+  v2 = a1->field_28;
+  if ( v2 )
+  {
+    do
+    {
+      v16 = v2;
+      v3 = a1->field_30;
+      v4 = a1->field_2C;
+      if ( (signed int)v3 >= a1->field_18 )
+        v3 = a1->field_18;
+      if ( (signed int)v3 <= a1->field_14 )
+        v3 = a1->field_14;
+      if ( v4 >= a1->field_20 )
+        v4 = a1->field_20;
+      if ( v4 <= a1->field_1C )
+        v4 = a1->field_1C;
+      v5 = *((char *)a1->pTextureLOD + (a1->field_C & (v3 >> 16)) + (((unsigned int)v4 & a1->field_8) >> a1->field_10));
+      v6 = a1->field_34_palette;
+      if ( a2->field_20 )
+      {
+        v7 = (unsigned int)a2->field_14 >> 16;
+        if ( v7 >= a2->field_C )
+          v7 = a2->field_C;
+        v8 = 0;
+        if ( a2->field_8 - v7 >= 0 )
+          v8 = a2->field_8 - v7;
+        v5 += v8 << 8;
+        v6 = a2->field_24_palette;
+      }
+      v9 = v6[v5];
+      v10 = a1->field_24;
+      v11 = a1->pColorBuffer;
+      v12 = a1->pDepthBuffer;
+      *v11 = v9;
+      *v12 = v10;
+      a1->pColorBuffer = v11 - 1;
+      a1->pDepthBuffer = v12 - 1;
+      v13 = a1->field_30;
+      a2->field_14 -= a2->field_18;
+      v14 = a1->field_2C;
+      v15 = a1->field_0;
+      a1->field_30 = a1->field_4 + v13;
+      a1->field_2C = v15 + v14;
+      v2 = v16 - 1;
+    }
+    while ( v16 != 1 );
+  }
+}
+
+//----- (004D77D2) --------------------------------------------------------
+void __cdecl sr_sub_4D77D2(stru315 *a1, stru316 *a2)
+{
+  int v2; // ecx@1
+  unsigned __int16 *v3; // ebx@2
+  int v4; // eax@2
+  unsigned __int16 *v5; // edx@2
+  int v6; // ebx@4
+  int v7; // ecx@6
+  unsigned __int16 v8; // bx@9
+  int v9; // ecx@9
+  unsigned int *v10; // edx@9
+  unsigned int *v11; // edx@10
+  int v12; // ecx@10
+  int v13; // eax@10
+  int v14; // ebx@10
+  int v15; // [sp-4h] [bp-Ch]@2
+
+  v2 = a1->field_28;
+  if ( v2 )
+  {
+    do
+    {
+      v15 = v2;
+      v3 = a1->pTextureLOD;
+      v4 = *((char *)v3
+           + (a1->field_C & ((unsigned int)a1->field_30 >> 16))
+           + ((unsigned int)(a1->field_2C & a1->field_8) >> a1->field_10));
+      v5 = a1->field_34_palette;
+      if ( *((char *)v3
+           + (a1->field_C & ((unsigned int)a1->field_30 >> 16))
+           + ((unsigned int)(a1->field_2C & a1->field_8) >> a1->field_10)) )
+      {
+        if ( a2->field_20 )
+        {
+          v6 = (unsigned int)a2->field_10 >> 16;
+          if ( v6 >= a2->field_C )
+            v6 = a2->field_C;
+          v7 = 0;
+          if ( a2->field_8 - v6 >= 0 )
+            v7 = a2->field_8 - v6;
+          v4 += v7 << 8;
+          v5 = a2->field_24_palette;
+        }
+        v8 = v5[v4];
+        v9 = a1->field_24;
+        v10 = a1->pDepthBuffer;
+        *a1->pColorBuffer = v8;
+        *v10 = v9;
+      }
+      v11 = a1->pDepthBuffer + 1;
+      ++a1->pColorBuffer;
+      a1->pDepthBuffer = v11;
+      v12 = a1->field_30;
+      a2->field_10 += a2->field_18;
+      v13 = a1->field_2C;
+      v14 = a1->field_0;
+      a1->field_30 = a1->field_4 + v12;
+      a1->field_2C = v14 + v13;
+      v2 = v15 - 1;
+    }
+    while ( v15 != 1 );
+  }
+}
+
+//----- (004D789A) --------------------------------------------------------
+void __cdecl sr_sub_4D789A(stru315 *a1, stru316 *a2)
+{
+  int v2; // ecx@1
+  unsigned int v3; // eax@2
+  int v4; // ecx@2
+  int v5; // eax@10
+  unsigned __int16 *v6; // edx@10
+  int v7; // ebx@12
+  int v8; // ecx@14
+  unsigned __int16 v9; // bx@17
+  int v10; // ecx@17
+  unsigned int *v11; // edx@17
+  unsigned int *v12; // edx@18
+  int v13; // ecx@18
+  int v14; // eax@18
+  int v15; // ebx@18
+  int v16; // [sp-4h] [bp-Ch]@2
+
+  v2 = a1->field_28;
+  if ( v2 )
+  {
+    do
+    {
+      v16 = v2;
+      v3 = a1->field_30;
+      v4 = a1->field_2C;
+      if ( (signed int)v3 >= a1->field_18 )
+        v3 = a1->field_18;
+      if ( (signed int)v3 <= a1->field_14 )
+        v3 = a1->field_14;
+      if ( v4 >= a1->field_20 )
+        v4 = a1->field_20;
+      if ( v4 <= a1->field_1C )
+        v4 = a1->field_1C;
+      v5 = *((char *)a1->pTextureLOD + (a1->field_C & (v3 >> 16)) + (((unsigned int)v4 & a1->field_8) >> a1->field_10));
+      v6 = a1->field_34_palette;
+      if ( v5 )
+      {
+        if ( a2->field_20 )
+        {
+          v7 = (unsigned int)a2->field_10 >> 16;
+          if ( v7 >= a2->field_C )
+            v7 = a2->field_C;
+          v8 = 0;
+          if ( a2->field_8 - v7 >= 0 )
+            v8 = a2->field_8 - v7;
+          v5 += v8 << 8;
+          v6 = a2->field_24_palette;
+        }
+        v9 = v6[v5];
+        v10 = a1->field_24;
+        v11 = a1->pDepthBuffer;
+        *a1->pColorBuffer = v9;
+        *v11 = v10;
+      }
+      v12 = a1->pDepthBuffer + 1;
+      ++a1->pColorBuffer;
+      a1->pDepthBuffer = v12;
+      v13 = a1->field_30;
+      a2->field_10 += a2->field_18;
+      v14 = a1->field_2C;
+      v15 = a1->field_0;
+      a1->field_30 = a1->field_4 + v13;
+      a1->field_2C = v15 + v14;
+      v2 = v16 - 1;
+    }
+    while ( v16 != 1 );
+  }
+}
+
+
+
+
+//----- (00451007) --------------------------------------------------------
+int stru350::sub_451007_scale_image_bicubic(unsigned short *pSrc, int srcWidth, int srcHeight, int srcPitch,
+                                            unsigned short *pDst, int dstWidth, int dstHeight, int dstPitch,
+                                            int a10, int a11)
+{
+  int v11; // esi@1
+  int result; // eax@1
+  int v13; // edi@8
+  int v14; // ecx@10
+  double v15; // st7@11
+  double v16; // st6@11
+  float v17; // ST3C_4@12
+  float v18; // ST38_4@12
+  unsigned int v19; // esi@12
+  int v20; // eax@16
+  int v21; // eax@18
+  unsigned int v22; // ecx@25
+  unsigned int v23; // eax@29
+  unsigned __int16 *v24; // ecx@29
+  int v25; // edi@33
+  int v26; // ecx@35
+  double v27; // st7@36
+  double v28; // st6@36
+  float v29; // ST34_4@37
+  float v30; // ST30_4@37
+  unsigned int v31; // esi@37
+  int v32; // eax@41
+  int v33; // eax@43
+  unsigned int v34; // ecx@50
+  unsigned __int16 v35; // ax@54
+  unsigned __int16 *v36; // ecx@54
+  int v37; // edi@58
+  int v38; // ecx@60
+  double v39; // st7@61
+  double v40; // st6@61
+  float v41; // ST34_4@62
+  float v42; // ST30_4@62
+  unsigned int v43; // esi@62
+  int v44; // eax@66
+  int v45; // eax@68
+  unsigned int v46; // ecx@75
+  char v47; // al@79
+  unsigned __int16 *v48; // ecx@79
+  int v49; // edi@86
+  int v50; // ecx@88
+  double v51; // st7@89
+  double v52; // st6@89
+  float v53; // ST34_4@90
+  float v54; // ST30_4@90
+  unsigned int v55; // esi@90
+  int v56; // eax@94
+  int v57; // eax@96
+  unsigned int v58; // ecx@103
+  unsigned int v59; // eax@107
+  unsigned __int16 *v60; // ecx@107
+  int v61; // edi@111
+  int v62; // ecx@113
+  double v63; // st7@114
+  double v64; // st6@114
+  float v65; // ST34_4@115
+  float v66; // ST30_4@115
+  unsigned int v67; // esi@115
+  int v68; // eax@119
+  int v69; // eax@121
+  unsigned int v70; // ecx@128
+  unsigned __int16 v71; // ax@132
+  unsigned __int16 *v72; // ecx@132
+  int v73; // edi@136
+  int v74; // ecx@138
+  double v75; // st7@139
+  double v76; // st6@139
+  float v77; // ST34_4@140
+  float v78; // ST30_4@140
+  unsigned int v79; // esi@140
+  int v80; // eax@144
+  int v81; // eax@146
+  unsigned int v82; // ecx@153
+  char v83; // al@157
+  unsigned __int16 *v84; // ecx@157
+  int v85; // edi@164
+  int v86; // ecx@166
+  double v87; // st7@167
+  double v88; // st6@167
+  float v89; // ST34_4@168
+  float v90; // ST30_4@168
+  unsigned int v91; // esi@168
+  signed int v92; // eax@170
+  int v93; // eax@171
+  int v94; // eax@173
+  unsigned int v95; // ecx@181
+  unsigned int v96; // eax@185
+  unsigned __int16 *v97; // ecx@185
+  int v98; // edi@189
+  int v99; // ecx@191
+  double v100; // st7@192
+  double v101; // st6@192
+  float v102; // ST34_4@193
+  float v103; // ST30_4@193
+  unsigned int v104; // esi@193
+  signed int v105; // eax@195
+  int v106; // eax@196
+  int v107; // eax@198
+  unsigned int v108; // ecx@206
+  unsigned __int16 v109; // ax@210
+  unsigned __int16 *v110; // ecx@210
+  int v111; // edi@214
+  int v112; // ecx@216
+  double v113; // st7@217
+  double v114; // st6@217
+  float v115; // ST34_4@218
+  float v116; // ST30_4@218
+  unsigned int v117; // esi@218
+  signed int v118; // eax@220
+  int v119; // eax@221
+  int v120; // eax@223
+  unsigned int v121; // ecx@231
+  char v122; // al@235
+  unsigned __int16 *v123; // ecx@235
+  double v124; // [sp+Ch] [bp-7Ch]@12
+  double v125; // [sp+Ch] [bp-7Ch]@37
+  double v126; // [sp+Ch] [bp-7Ch]@62
+  double v127; // [sp+Ch] [bp-7Ch]@90
+  //double v128; // [sp+Ch] [bp-7Ch]@115
+  uint _v128;
+  double v129; // [sp+Ch] [bp-7Ch]@140
+  double v130; // [sp+Ch] [bp-7Ch]@168
+  double v131; // [sp+Ch] [bp-7Ch]@193
+  double v132; // [sp+Ch] [bp-7Ch]@218
+  double v133; // [sp+14h] [bp-74h]@12
+  double v134; // [sp+14h] [bp-74h]@37
+  double v135; // [sp+14h] [bp-74h]@62
+  double v136; // [sp+14h] [bp-74h]@90
+  //double v137; // [sp+14h] [bp-74h]@115
+  uint _v137;
+  double v138; // [sp+14h] [bp-74h]@140
+  double v139; // [sp+14h] [bp-74h]@168
+  double v140; // [sp+14h] [bp-74h]@193
+  double v141; // [sp+14h] [bp-74h]@218
+  double v142; // [sp+1Ch] [bp-6Ch]@12
+  double v143; // [sp+1Ch] [bp-6Ch]@37
+  double v144; // [sp+1Ch] [bp-6Ch]@62
+  double v145; // [sp+1Ch] [bp-6Ch]@90
+  //double v146; // [sp+1Ch] [bp-6Ch]@115
+  uint _v146;
+  double v147; // [sp+1Ch] [bp-6Ch]@140
+  double v148; // [sp+1Ch] [bp-6Ch]@168
+  double v149; // [sp+1Ch] [bp-6Ch]@193
+  double v150; // [sp+1Ch] [bp-6Ch]@218
+  double v151; // [sp+24h] [bp-64h]@12
+  double v152; // [sp+24h] [bp-64h]@37
+  double v153; // [sp+24h] [bp-64h]@62
+  double v154; // [sp+24h] [bp-64h]@90
+  //double v155; // [sp+24h] [bp-64h]@115
+  uint _v155;
+  double v156; // [sp+24h] [bp-64h]@140
+  double v157; // [sp+24h] [bp-64h]@168
+  double v158; // [sp+24h] [bp-64h]@193
+  double v159; // [sp+24h] [bp-64h]@218
+  int v160; // [sp+3Ch] [bp-4Ch]@13
+  int v161; // [sp+40h] [bp-48h]@15
+  int v162; // [sp+44h] [bp-44h]@40
+  int v163; // [sp+44h] [bp-44h]@65
+  int v164; // [sp+44h] [bp-44h]@93
+  int v165; // [sp+44h] [bp-44h]@118
+  int v166; // [sp+44h] [bp-44h]@143
+  int v167; // [sp+44h] [bp-44h]@169
+  int v168; // [sp+44h] [bp-44h]@194
+  int v169; // [sp+44h] [bp-44h]@219
+  int v170; // [sp+48h] [bp-40h]@38
+  int v171; // [sp+48h] [bp-40h]@63
+  int v172; // [sp+48h] [bp-40h]@91
+  int v173; // [sp+48h] [bp-40h]@116
+  int v174; // [sp+48h] [bp-40h]@141
+  unsigned __int16 *v175; // [sp+4Ch] [bp-3Ch]@13
+  int *v176; // [sp+50h] [bp-38h]@15
+  int *v177; // [sp+50h] [bp-38h]@40
+  int *v178; // [sp+50h] [bp-38h]@65
+  int *v179; // [sp+50h] [bp-38h]@93
+  int *v180; // [sp+50h] [bp-38h]@118
+  int *v181; // [sp+50h] [bp-38h]@143
+  char *v182; // [sp+50h] [bp-38h]@169
+  char *v183; // [sp+50h] [bp-38h]@194
+  char *v184; // [sp+50h] [bp-38h]@219
+  unsigned __int16 *v185; // [sp+54h] [bp-34h]@38
+  unsigned __int16 *v186; // [sp+54h] [bp-34h]@63
+  unsigned __int16 *v187; // [sp+54h] [bp-34h]@91
+  unsigned __int16 *v188; // [sp+54h] [bp-34h]@116
+  unsigned __int16 *v189; // [sp+54h] [bp-34h]@141
+  signed int v190; // [sp+54h] [bp-34h]@170
+  signed int v191; // [sp+54h] [bp-34h]@195
+  signed int v192; // [sp+54h] [bp-34h]@220
+  unsigned __int16 *v193; // [sp+5Ch] [bp-2Ch]@7
+  unsigned __int16 *v194; // [sp+5Ch] [bp-2Ch]@32
+  unsigned __int16 *v195; // [sp+5Ch] [bp-2Ch]@57
+  unsigned __int16 *v196; // [sp+5Ch] [bp-2Ch]@85
+  unsigned __int16 *v197; // [sp+5Ch] [bp-2Ch]@110
+  unsigned __int16 *v198; // [sp+5Ch] [bp-2Ch]@135
+  unsigned __int16 *v199; // [sp+5Ch] [bp-2Ch]@163
+  unsigned __int16 *v200; // [sp+5Ch] [bp-2Ch]@188
+  unsigned __int16 *v201; // [sp+5Ch] [bp-2Ch]@213
+  //stru350 *v202; // [sp+60h] [bp-28h]@1
+  int v203; // [sp+64h] [bp-24h]@12
+  int v204; // [sp+64h] [bp-24h]@37
+  int v205; // [sp+64h] [bp-24h]@62
+  int v206; // [sp+64h] [bp-24h]@90
+  int v207; // [sp+64h] [bp-24h]@115
+  int v208; // [sp+64h] [bp-24h]@140
+  int v209; // [sp+64h] [bp-24h]@168
+  int v210; // [sp+64h] [bp-24h]@193
+  int v211; // [sp+64h] [bp-24h]@218
+  float v212; // [sp+6Ch] [bp-1Ch]@11
+  float v213; // [sp+6Ch] [bp-1Ch]@36
+  float v214; // [sp+6Ch] [bp-1Ch]@61
+  float v215; // [sp+6Ch] [bp-1Ch]@89
+  float v216; // [sp+6Ch] [bp-1Ch]@114
+  float v217; // [sp+6Ch] [bp-1Ch]@139
+  float v218; // [sp+6Ch] [bp-1Ch]@167
+  float v219; // [sp+6Ch] [bp-1Ch]@192
+  float v220; // [sp+6Ch] [bp-1Ch]@217
+  float v221; // [sp+70h] [bp-18h]@11
+  float v222; // [sp+70h] [bp-18h]@36
+  float v223; // [sp+70h] [bp-18h]@61
+  float v224; // [sp+70h] [bp-18h]@89
+  float v225; // [sp+70h] [bp-18h]@114
+  float v226; // [sp+70h] [bp-18h]@139
+  float v227; // [sp+70h] [bp-18h]@167
+  float v228; // [sp+70h] [bp-18h]@192
+  float v229; // [sp+70h] [bp-18h]@217
+  signed int v230; // [sp+74h] [bp-14h]@1
+  signed int v231; // [sp+78h] [bp-10h]@7
+  signed int v232; // [sp+78h] [bp-10h]@32
+  signed int v233; // [sp+78h] [bp-10h]@57
+  signed int v234; // [sp+78h] [bp-10h]@85
+  signed int v235; // [sp+78h] [bp-10h]@110
+  signed int v236; // [sp+78h] [bp-10h]@135
+  signed int v237; // [sp+78h] [bp-10h]@163
+  signed int v238; // [sp+78h] [bp-10h]@188
+  signed int v239; // [sp+78h] [bp-10h]@213
+  __int64 v240; // [sp+7Ch] [bp-Ch]@12
+  __int64 v241; // [sp+7Ch] [bp-Ch]@37
+  __int64 v242; // [sp+7Ch] [bp-Ch]@62
+  __int64 v243; // [sp+7Ch] [bp-Ch]@90
+  __int64 v244; // [sp+7Ch] [bp-Ch]@115
+  __int64 v245; // [sp+7Ch] [bp-Ch]@140
+  unsigned int v246; // [sp+7Ch] [bp-Ch]@168
+  unsigned int v247; // [sp+7Ch] [bp-Ch]@193
+  unsigned int v248; // [sp+7Ch] [bp-Ch]@218
+  unsigned int v249; // [sp+80h] [bp-8h]@168
+  unsigned int v250; // [sp+80h] [bp-8h]@193
+  unsigned int v251; // [sp+80h] [bp-8h]@218
+  unsigned int v252; // [sp+84h] [bp-4h]@12
+  unsigned int v253; // [sp+84h] [bp-4h]@37
+  unsigned int v254; // [sp+84h] [bp-4h]@62
+  unsigned int v255; // [sp+84h] [bp-4h]@90
+  unsigned int v256; // [sp+84h] [bp-4h]@115
+  unsigned int v257; // [sp+84h] [bp-4h]@140
+  unsigned int v258; // [sp+84h] [bp-4h]@168
+  unsigned int v259; // [sp+84h] [bp-4h]@193
+  unsigned int v260; // [sp+84h] [bp-4h]@218
+  signed int a6a; // [sp+A0h] [bp+18h]@10
+  float a6s; // [sp+A0h] [bp+18h]@12
+  float a6t; // [sp+A0h] [bp+18h]@12
+  unsigned int a6b; // [sp+A0h] [bp+18h]@12
+  signed int a6c; // [sp+A0h] [bp+18h]@35
+  float a6u; // [sp+A0h] [bp+18h]@37
+  float a6v; // [sp+A0h] [bp+18h]@37
+  unsigned int a6d; // [sp+A0h] [bp+18h]@37
+  signed int a6e; // [sp+A0h] [bp+18h]@60
+  float a6w; // [sp+A0h] [bp+18h]@62
+  float a6x; // [sp+A0h] [bp+18h]@62
+  unsigned int a6f; // [sp+A0h] [bp+18h]@62
+  signed int a6g; // [sp+A0h] [bp+18h]@88
+  float a6y; // [sp+A0h] [bp+18h]@90
+  float a6z; // [sp+A0h] [bp+18h]@90
+  unsigned int a6h; // [sp+A0h] [bp+18h]@90
+  signed int a6i; // [sp+A0h] [bp+18h]@113
+  float a6ba; // [sp+A0h] [bp+18h]@115
+  float a6bb; // [sp+A0h] [bp+18h]@115
+  unsigned int a6j; // [sp+A0h] [bp+18h]@115
+  signed int a6k; // [sp+A0h] [bp+18h]@138
+  float a6bc; // [sp+A0h] [bp+18h]@140
+  float a6bd; // [sp+A0h] [bp+18h]@140
+  unsigned int a6l; // [sp+A0h] [bp+18h]@140
+  signed int a6m; // [sp+A0h] [bp+18h]@166
+  float a6be; // [sp+A0h] [bp+18h]@168
+  float a6bf; // [sp+A0h] [bp+18h]@168
+  unsigned int a6n; // [sp+A0h] [bp+18h]@168
+  signed int a6o; // [sp+A0h] [bp+18h]@191
+  float a6bg; // [sp+A0h] [bp+18h]@193
+  float a6bh; // [sp+A0h] [bp+18h]@193
+  unsigned int a6p; // [sp+A0h] [bp+18h]@193
+  signed int a6q; // [sp+A0h] [bp+18h]@216
+  float a6bi; // [sp+A0h] [bp+18h]@218
+  float a6bj; // [sp+A0h] [bp+18h]@218
+  unsigned int a6r; // [sp+A0h] [bp+18h]@218
+  int a9a; // [sp+ACh] [bp+24h]@8
+  int a9b; // [sp+ACh] [bp+24h]@33
+  int a9c; // [sp+ACh] [bp+24h]@86
+  int a9d; // [sp+ACh] [bp+24h]@111
+  int a9e; // [sp+ACh] [bp+24h]@164
+  int a9f; // [sp+ACh] [bp+24h]@189
+
+  v11 = 0;
+  result = this->field_0.field_C;
+  //v202 = this;
+  v230 = 0;
+  if ( result != 8 )
+  {
+    if ( result != 16 )
+    {
+      if ( result != 32 )
+        return result;
+      result = this->field_20.field_C;
+      if ( result != 8 )
+      {
+        if ( result != 16 )
+        {
+          if ( result != 32 || (result = (int)pDst, v193 = pDst, v231 = 0, dstHeight <= 0) )
+            return result;
+          v13 = dstWidth;
+          a9a = 4 * (dstPitch - dstWidth);
+          while ( 1 )
+          {
+            v14 = 0;
+            a6a = 0;
+            if ( dstWidth > v11 )
+              break;
+LABEL_30:
+            v193 = (unsigned __int16 *)((char *)v193 + a9a);
+            ++v231;
+            result = v231;
+            if ( v231 >= dstHeight )
+              return result;
+            v11 = 0;
+          }
+          v221 = (double)dstWidth;
+          v212 = (double)srcWidth;
+          v15 = (double)dstHeight;
+          v16 = (double)srcHeight;
+          while ( 1 )
+          {
+            a6s = (double)a6a / v221 * v212;
+            v151 = floorf(a6s + 0.5f);//a6s + 6.7553994e15;
+            v203 = v14 + 1;
+            a6t = (double)(v14 + 1) / v221 * v212;
+            v142 = floorf(a6t + 0.5f);//a6t + 6.7553994e15;
+            v17 = (double)v231 / v15 * v16;
+            v133 = floorf(v17 + 0.5f);//v17 + 6.7553994e15;
+            v18 = (double)(v231 + 1) / v15 * v16;
+            v124 = floorf(v18 + 0.5f);//v18 + 6.7553994e15;
+            v19 = (LODWORD(v124) - LODWORD(v133)) * (LODWORD(v142) - LODWORD(v151));
+            v252 = 0;
+            a6b = 0;
+            v240 = 0i64;
+            if ( SLODWORD(v133) < SLODWORD(v124) )
+              break;
+LABEL_25:
+            v22 = (unsigned int)v240 / ((LODWORD(v124) - LODWORD(v133)) * (LODWORD(v142) - LODWORD(v151)));
+            if ( v19 )
+            {
+              a6b /= v19;
+              v252 /= v19;
+              HIDWORD(v240) /= v19;
+            }
+            if ( v22 != 255 )
+              v22 &= 0x7FFFFFFFu;
+            v23 = _450F55(HIDWORD(v240) | ((v252 | ((a6b | (v22 << 8)) << 8)) << 8));
+            v24 = v193;
+            v193 += 2;
+            *(_DWORD *)v24 = v23;
+            v14 = v203;
+            a6a = v203;
+            if ( v203 >= dstWidth )
+              goto LABEL_30;
+          }
+          v160 = LODWORD(v124) - LODWORD(v133);
+          v175 = &pSrc[2 * (LODWORD(v151) + srcPitch * LODWORD(v133))];
+          while ( SLODWORD(v151) >= SLODWORD(v142) )
+          {
+LABEL_24:
+            v175 += 2 * srcPitch;
+            --v160;
+            if ( !v160 )
+              goto LABEL_25;
+          }
+          v176 = (int *)v175;
+          v161 = LODWORD(v142) - LODWORD(v151);
+          while ( 1 )
+          {
+            v20 = *v176;
+            if ( a10 )
+            {
+              v230 = 1;
+              v13 = v20 != a11 ? 0xFF : 0;
+            }
+            v21 = _450FB1(v20);
+            if ( !v230 )
+              break;
+            LODWORD(v240) = v13 + v240;
+            v230 = 0;
+            if ( v13 )
+              goto LABEL_22;
+            --v19;
+LABEL_23:
+            ++v176;
+            --v161;
+            if ( !v161 )
+              goto LABEL_24;
+          }
+          LODWORD(v240) = ((unsigned int)v21 >> 24) + v240;
+LABEL_22:
+          a6b += BYTE2(v21);
+          v252 += BYTE1(v21);
+          HIDWORD(v240) += (unsigned __int8)v21;
+          goto LABEL_23;
+        }
+        result = (int)pDst;
+        v194 = pDst;
+        v232 = 0;
+        if ( dstHeight <= 0 )
+          return result;
+        v25 = dstWidth;
+        a9b = 2 * (dstPitch - dstWidth);
+        while ( 1 )
+        {
+          v26 = 0;
+          a6c = 0;
+          if ( dstWidth > v11 )
+            break;
+LABEL_55:
+          v194 = (unsigned __int16 *)((char *)v194 + a9b);
+          ++v232;
+          result = v232;
+          if ( v232 >= dstHeight )
+            return result;
+          v11 = 0;
+        }
+        v222 = (double)dstWidth;
+        v213 = (double)srcWidth;
+        v27 = (double)dstHeight;
+        v28 = (double)srcHeight;
+        while ( 1 )
+        {
+          a6u = (double)a6c / v222 * v213;
+          v125 = a6u + 6.7553994e15;
+          v204 = v26 + 1;
+          a6v = (double)(v26 + 1) / v222 * v213;
+          v134 = a6v + 6.7553994e15;
+          v29 = (double)v232 / v27 * v28;
+          v143 = v29 + 6.7553994e15;
+          v30 = (double)(v232 + 1) / v27 * v28;
+          v152 = v30 + 6.7553994e15;
+          v31 = (LODWORD(v152) - LODWORD(v143)) * (LODWORD(v134) - LODWORD(v125));
+          v253 = 0;
+          a6d = 0;
+          v241 = 0i64;
+          if ( SLODWORD(v143) < SLODWORD(v152) )
+            break;
+LABEL_50:
+          v34 = (unsigned int)v241 / ((LODWORD(v152) - LODWORD(v143)) * (LODWORD(v134) - LODWORD(v125)));
+          if ( v31 )
+          {
+            a6d /= v31;
+            v253 /= v31;
+            HIDWORD(v241) /= v31;
+          }
+          if ( v34 != 255 )
+            v34 &= 0x7FFFFFFFu;
+          v35 = _450F55(HIDWORD(v241) | ((v253 | ((a6d | (v34 << 8)) << 8)) << 8));
+          v36 = v194;
+          ++v194;
+          *v36 = v35;
+          v26 = v204;
+          a6c = v204;
+          if ( v204 >= dstWidth )
+            goto LABEL_55;
+        }
+        v170 = LODWORD(v152) - LODWORD(v143);
+        v185 = &pSrc[2 * (LODWORD(v125) + srcPitch * LODWORD(v143))];
+        while ( SLODWORD(v125) >= SLODWORD(v134) )
+        {
+LABEL_49:
+          v185 += 2 * srcPitch;
+          --v170;
+          if ( !v170 )
+            goto LABEL_50;
+        }
+        v177 = (int *)v185;
+        v162 = LODWORD(v134) - LODWORD(v125);
+        while ( 1 )
+        {
+          v32 = *v177;
+          if ( a10 )
+          {
+            v230 = 1;
+            v25 = v32 != a11 ? 0xFF : 0;
+          }
+          v33 = _450FB1(v32);
+          if ( !v230 )
+            break;
+          LODWORD(v241) = v25 + v241;
+          v230 = 0;
+          if ( v25 )
+            goto LABEL_47;
+          --v31;
+LABEL_48:
+          ++v177;
+          --v162;
+          if ( !v162 )
+            goto LABEL_49;
+        }
+        LODWORD(v241) = ((unsigned int)v33 >> 24) + v241;
+LABEL_47:
+        a6d += BYTE2(v33);
+        v253 += BYTE1(v33);
+        HIDWORD(v241) += (unsigned __int8)v33;
+        goto LABEL_48;
+      }
+      result = (int)pDst;
+      v195 = pDst;
+      v233 = 0;
+      if ( dstHeight <= 0 )
+        return result;
+      v37 = dstWidth;
+      while ( 1 )
+      {
+        v38 = 0;
+        a6e = 0;
+        if ( dstWidth > v11 )
+          break;
+LABEL_80:
+        v195 = (unsigned __int16 *)((char *)v195 + dstPitch - dstWidth);
+        ++v233;
+        result = v233;
+        if ( v233 >= dstHeight )
+          return result;
+        v11 = 0;
+      }
+      v223 = (double)dstWidth;
+      v214 = (double)srcWidth;
+      v39 = (double)dstHeight;
+      v40 = (double)srcHeight;
+      while ( 1 )
+      {
+        a6w = (double)a6e / v223 * v214;
+        v126 = a6w + 6.7553994e15;
+        v205 = v38 + 1;
+        a6x = (double)(v38 + 1) / v223 * v214;
+        v135 = a6x + 6.7553994e15;
+        v41 = (double)v233 / v39 * v40;
+        v144 = v41 + 6.7553994e15;
+        v42 = (double)(v233 + 1) / v39 * v40;
+        v153 = v42 + 6.7553994e15;
+        v43 = (LODWORD(v153) - LODWORD(v144)) * (LODWORD(v135) - LODWORD(v126));
+        v254 = 0;
+        a6f = 0;
+        v242 = 0i64;
+        if ( SLODWORD(v144) < SLODWORD(v153) )
+          break;
+LABEL_75:
+        v46 = (unsigned int)v242 / ((LODWORD(v153) - LODWORD(v144)) * (LODWORD(v135) - LODWORD(v126)));
+        if ( v43 )
+        {
+          a6f /= v43;
+          v254 /= v43;
+          HIDWORD(v242) /= v43;
+        }
+        if ( v46 != 255 )
+          v46 &= 0x7FFFFFFFu;
+        v47 = _450F55(HIDWORD(v242) | ((v254 | ((a6f | (v46 << 8)) << 8)) << 8));
+        v48 = v195;
+        v195 = (unsigned __int16 *)((char *)v195 + 1);
+        *(_BYTE *)v48 = v47;
+        v38 = v205;
+        a6e = v205;
+        if ( v205 >= dstWidth )
+          goto LABEL_80;
+      }
+      v171 = LODWORD(v153) - LODWORD(v144);
+      v186 = &pSrc[2 * (LODWORD(v126) + srcPitch * LODWORD(v144))];
+      while ( SLODWORD(v126) >= SLODWORD(v135) )
+      {
+LABEL_74:
+        v186 += 2 * srcPitch;
+        --v171;
+        if ( !v171 )
+          goto LABEL_75;
+      }
+      v178 = (int *)v186;
+      v163 = LODWORD(v135) - LODWORD(v126);
+      while ( 1 )
+      {
+        v44 = *v178;
+        if ( a10 )
+        {
+          v230 = 1;
+          v37 = v44 != a11 ? 0xFF : 0;
+        }
+        v45 = _450FB1(v44);
+        if ( !v230 )
+          break;
+        LODWORD(v242) = v37 + v242;
+        v230 = 0;
+        if ( v37 )
+          goto LABEL_72;
+        --v43;
+LABEL_73:
+        ++v178;
+        --v163;
+        if ( !v163 )
+          goto LABEL_74;
+      }
+      LODWORD(v242) = ((unsigned int)v45 >> 24) + v242;
+LABEL_72:
+      a6f += BYTE2(v45);
+      v254 += BYTE1(v45);
+      HIDWORD(v242) += (unsigned __int8)v45;
+      goto LABEL_73;
+    }
+    result = this->field_20.field_C;
+    if ( result != 8 )
+    {
+      if ( result != 16 )
+      {
+        if ( result != 32 || (result = (int)pDst, v196 = pDst, v234 = 0, dstHeight <= 0) )
+          return result;
+        v49 = dstWidth;
+        a9c = 4 * (dstPitch - dstWidth);
+        while ( 1 )
+        {
+          v50 = 0;
+          a6g = 0;
+          if ( dstWidth > v11 )
+            break;
+LABEL_108:
+          v196 = (unsigned __int16 *)((char *)v196 + a9c);
+          ++v234;
+          result = v234;
+          if ( v234 >= dstHeight )
+            return result;
+          v11 = 0;
+        }
+        v224 = (double)dstWidth;
+        v215 = (double)srcWidth;
+        v51 = (double)dstHeight;
+        v52 = (double)srcHeight;
+        while ( 1 )
+        {
+          a6y = (double)a6g / v224 * v215;
+          v127 = a6y + 6.7553994e15;
+          v206 = v50 + 1;
+          a6z = (double)(v50 + 1) / v224 * v215;
+          v136 = a6z + 6.7553994e15;
+          v53 = (double)v234 / v51 * v52;
+          v145 = v53 + 6.7553994e15;
+          v54 = (double)(v234 + 1) / v51 * v52;
+          v154 = v54 + 6.7553994e15;
+          v55 = (LODWORD(v154) - LODWORD(v145)) * (LODWORD(v136) - LODWORD(v127));
+          v255 = 0;
+          a6h = 0;
+          v243 = 0i64;
+          if ( SLODWORD(v145) < SLODWORD(v154) )
+            break;
+LABEL_103:
+          v58 = (unsigned int)v243 / ((LODWORD(v154) - LODWORD(v145)) * (LODWORD(v136) - LODWORD(v127)));
+          if ( v55 )
+          {
+            a6h /= v55;
+            v255 /= v55;
+            HIDWORD(v243) /= v55;
+          }
+          if ( v58 != 255 )
+            v58 &= 0x7FFFFFFFu;
+          v59 = _450F55(HIDWORD(v243) | ((v255 | ((a6h | (v58 << 8)) << 8)) << 8));
+          v60 = v196;
+          v196 += 2;
+          *(_DWORD *)v60 = v59;
+          v50 = v206;
+          a6g = v206;
+          if ( v206 >= dstWidth )
+            goto LABEL_108;
+        }
+        v172 = LODWORD(v154) - LODWORD(v145);
+        v187 = &pSrc[LODWORD(v127) + srcPitch * LODWORD(v145)];
+        while ( SLODWORD(v127) >= SLODWORD(v136) )
+        {
+LABEL_102:
+          v187 += srcPitch;
+          --v172;
+          if ( !v172 )
+            goto LABEL_103;
+        }
+        v179 = (int *)v187;
+        v164 = LODWORD(v136) - LODWORD(v127);
+        while ( 1 )
+        {
+          v56 = *(_WORD *)v179;
+          if ( a10 )
+          {
+            v230 = 1;
+            v49 = v56 != a11 ? 0xFF : 0;
+          }
+          v57 = _450FB1(v56);
+          if ( !v230 )
+            break;
+          LODWORD(v243) = v49 + v243;
+          v230 = 0;
+          if ( v49 )
+            goto LABEL_100;
+          --v55;
+LABEL_101:
+          v179 = (int *)((char *)v179 + 2);
+          --v164;
+          if ( !v164 )
+            goto LABEL_102;
+        }
+        LODWORD(v243) = ((unsigned int)v57 >> 24) + v243;
+LABEL_100:
+        a6h += BYTE2(v57);
+        v255 += BYTE1(v57);
+        HIDWORD(v243) += (unsigned __int8)v57;
+        goto LABEL_101;
+      }
+      result = (int)pDst;
+      v197 = pDst;
+      v235 = 0;
+      if ( dstHeight <= 0 )
+        return result;
+      v61 = dstWidth;
+      a9d = 2 * (dstPitch - dstWidth);
+      while ( 1 )
+      {
+        v62 = 0;
+        a6i = 0;
+        if ( dstWidth > v11 )
+          break;
+LABEL_133:
+        v197 = (unsigned __int16 *)((char *)v197 + a9d);
+        ++v235;
+        result = v235;
+        if ( v235 >= dstHeight )
+          return result;
+        v11 = 0;
+      }
+      v225 = (double)dstWidth;
+      v216 = (double)srcWidth;
+      v63 = (double)dstHeight;
+      v64 = (double)srcHeight;
+      while ( 1 )
+      {
+        a6ba = (double)a6i / v225 * v216;
+        _v128 = floorf(a6ba + 0.5f);
+        //v128 = a6ba + 6.7553994e15;
+        v207 = v62 + 1;
+        a6bb = (double)(v62 + 1) / v225 * v216;
+        //v137 = a6bb + 6.7553994e15;
+        _v137 = floorf(a6bb + 0.5f);
+        v65 = (double)v235 / v63 * v64;
+        //v146 = v65 + 6.7553994e15;
+        _v146 = floorf(v65 + 0.5f);
+        v66 = (double)(v235 + 1) / v63 * v64;
+        //v155 = v66 + 6.7553994e15;
+        _v155 = floorf(v66 + 0.5f);
+        //v67 = (LODWORD(v155) - LODWORD(v146)) * (LODWORD(v137) - LODWORD(v128));
+        v67 = (_v155 - _v146) * (_v137 - _v128);
+        v256 = 0;
+        a6j = 0;
+        v244 = 0i64;
+        //if ( SLODWORD(v146) < SLODWORD(v155) )
+        if (_v146 < _v155)
+          break;
+LABEL_128:
+        //v70 = (unsigned int)v244 / ((LODWORD(v155) - LODWORD(v146)) * (LODWORD(v137) - LODWORD(v128)));
+        v70 = (unsigned int)v244 / ((_v155 - _v146) * (_v137 - _v128));
+        if ( v67 )
+        {
+          a6j /= v67;
+          v256 /= v67;
+          HIDWORD(v244) /= v67;
+        }
+        if ( v70 != 255 )
+          v70 &= 0x7FFFFFFFu;
+        v71 = _450F55(HIDWORD(v244) | ((v256 | ((a6j | (v70 << 8)) << 8)) << 8));
+        v72 = v197;
+        ++v197;
+        *v72 = v71;
+        v62 = v207;
+        a6i = v207;
+        if ( v207 >= dstWidth )
+          goto LABEL_133;
+      }
+      //v173 = LODWORD(v155) - LODWORD(v146);
+      v173 = _v155 - _v146;
+      //v188 = &pSrc[LODWORD(v128) + srcPitch * LODWORD(v146)];
+      v188 = &pSrc[_v128 + srcPitch * _v146];
+      //while ( SLODWORD(v128) >= SLODWORD(v137) )
+      while (_v128 >= _v137)
+      {
+LABEL_127:
+        v188 += srcPitch;
+        --v173;
+        if ( !v173 )
+          goto LABEL_128;
+      }
+      v180 = (int *)v188;
+      //v165 = LODWORD(v137) - LODWORD(v128);
+      v165 = _v137 - _v128;
+      while ( 1 )
+      {
+        v68 = *(_WORD *)v180;
+        if ( a10 )
+        {
+          v230 = 1;
+          v61 = v68 != a11 ? 0xFF : 0;
+        }
+        v69 = _450FB1(v68);
+        if ( !v230 )
+          break;
+        LODWORD(v244) = v61 + v244;
+        v230 = 0;
+        if ( v61 )
+          goto LABEL_125;
+        --v67;
+LABEL_126:
+        v180 = (int *)((char *)v180 + 2);
+        --v165;
+        if ( !v165 )
+          goto LABEL_127;
+      }
+      LODWORD(v244) = ((unsigned int)v69 >> 24) + v244;
+LABEL_125:
+      a6j += BYTE2(v69);
+      v256 += BYTE1(v69);
+      HIDWORD(v244) += (unsigned __int8)v69;
+      goto LABEL_126;
+    }
+    result = (int)pDst;
+    v198 = pDst;
+    v236 = 0;
+    if ( dstHeight <= 0 )
+      return result;
+    v73 = dstWidth;
+    while ( 1 )
+    {
+      v74 = 0;
+      a6k = 0;
+      if ( dstWidth > v11 )
+        break;
+LABEL_158:
+      v198 = (unsigned __int16 *)((char *)v198 + dstPitch - dstWidth);
+      ++v236;
+      result = v236;
+      if ( v236 >= dstHeight )
+        return result;
+      v11 = 0;
+    }
+    v226 = (double)dstWidth;
+    v217 = (double)srcWidth;
+    v75 = (double)dstHeight;
+    v76 = (double)srcHeight;
+    while ( 1 )
+    {
+      a6bc = (double)a6k / v226 * v217;
+      v129 = a6bc + 6.7553994e15;
+      v208 = v74 + 1;
+      a6bd = (double)(v74 + 1) / v226 * v217;
+      v138 = a6bd + 6.7553994e15;
+      v77 = (double)v236 / v75 * v76;
+      v147 = v77 + 6.7553994e15;
+      v78 = (double)(v236 + 1) / v75 * v76;
+      v156 = v78 + 6.7553994e15;
+      v257 = 0;
+      v79 = (LODWORD(v156) - LODWORD(v147)) * (LODWORD(v138) - LODWORD(v129));
+      a6l = 0;
+      v245 = 0i64;
+      if ( SLODWORD(v147) < SLODWORD(v156) )
+        break;
+LABEL_153:
+      v82 = (unsigned int)v245 / ((LODWORD(v156) - LODWORD(v147)) * (LODWORD(v138) - LODWORD(v129)));
+      if ( v79 )
+      {
+        a6l /= v79;
+        v257 /= v79;
+        HIDWORD(v245) /= v79;
+      }
+      if ( v82 != 255 )
+        v82 &= 0x7FFFFFFFu;
+      v83 = _450F55(HIDWORD(v245) | ((v257 | ((a6l | (v82 << 8)) << 8)) << 8));
+      v84 = v198;
+      v198 = (unsigned __int16 *)((char *)v198 + 1);
+      *(_BYTE *)v84 = v83;
+      v74 = v208;
+      a6k = v208;
+      if ( v208 >= dstWidth )
+        goto LABEL_158;
+    }
+    v174 = LODWORD(v156) - LODWORD(v147);
+    v189 = &pSrc[LODWORD(v129) + srcPitch * LODWORD(v147)];
+    while ( SLODWORD(v129) >= SLODWORD(v138) )
+    {
+LABEL_152:
+      v189 += srcPitch;
+      --v174;
+      if ( !v174 )
+        goto LABEL_153;
+    }
+    v166 = LODWORD(v138) - LODWORD(v129);
+    v181 = (int *)v189;
+    while ( 1 )
+    {
+      v80 = *(_WORD *)v181;
+      if ( a10 )
+      {
+        v230 = 1;
+        v73 = v80 != a11 ? 0xFF : 0;
+      }
+      v81 = _450FB1(v80);
+      if ( !v230 )
+        break;
+      LODWORD(v245) = v73 + v245;
+      v230 = 0;
+      if ( v73 )
+        goto LABEL_150;
+      --v79;
+LABEL_151:
+      v181 = (int *)((char *)v181 + 2);
+      --v166;
+      if ( !v166 )
+        goto LABEL_152;
+    }
+    LODWORD(v245) = ((unsigned int)v81 >> 24) + v245;
+LABEL_150:
+    a6l += BYTE2(v81);
+    v257 += BYTE1(v81);
+    HIDWORD(v245) += (unsigned __int8)v81;
+    goto LABEL_151;
+  }
+  result = this->field_20.field_C;
+  if ( result == 8 )
+  {
+    result = (int)pDst;
+    v201 = pDst;
+    v239 = 0;
+    if ( dstHeight <= 0 )
+      return result;
+    v111 = dstWidth;
+    while ( 1 )
+    {
+      v112 = 0;
+      a6q = 0;
+      if ( dstWidth <= v11 )
+        goto LABEL_236;
+      v229 = (double)dstWidth;
+      v220 = (double)srcWidth;
+      v113 = (double)dstHeight;
+      v114 = (double)srcHeight;
+      do
+      {
+        a6bi = (double)a6q / v229 * v220;
+        v132 = a6bi + 6.7553994e15;
+        v211 = v112 + 1;
+        a6bj = (double)(v112 + 1) / v229 * v220;
+        v141 = a6bj + 6.7553994e15;
+        v115 = (double)v239 / v113 * v114;
+        v150 = v115 + 6.7553994e15;
+        v116 = (double)(v239 + 1) / v113 * v114;
+        v159 = v116 + 6.7553994e15;
+        v251 = 0;
+        v117 = (LODWORD(v159) - LODWORD(v150)) * (LODWORD(v141) - LODWORD(v132));
+        v260 = 0;
+        a6r = 0;
+        v248 = 0;
+        if ( SLODWORD(v150) >= SLODWORD(v159) )
+          goto LABEL_231;
+        v169 = LODWORD(v159) - LODWORD(v150);
+        v184 = (char *)pSrc + srcPitch * LODWORD(v150);
+        do
+        {
+          v118 = LODWORD(v132);
+          v192 = LODWORD(v132);
+          while ( v118 < SLODWORD(v141) )
+          {
+            v119 = (unsigned __int8)v184[v192];
+            if ( a10 )
+            {
+              v230 = 1;
+              v111 = v119 != a11 ? 0xFF : 0;
+            }
+            v120 = _450FB1(v119);
+            if ( v230 )
+            {
+              v248 += v111;
+              v230 = 0;
+              if ( !v111 )
+              {
+                --v117;
+                goto LABEL_228;
+              }
+            }
+            else
+            {
+              v248 += (unsigned int)v120 >> 24;
+            }
+            a6r += BYTE2(v120);
+            v260 += BYTE1(v120);
+            v251 += (unsigned __int8)v120;
+LABEL_228:
+            ++v192;
+            v118 = v192;
+          }
+          v184 += srcPitch;
+          --v169;
+        }
+        while ( v169 );
+LABEL_231:
+        v121 = v248 / ((LODWORD(v159) - LODWORD(v150)) * (LODWORD(v141) - LODWORD(v132)));
+        if ( v117 )
+        {
+          a6r /= v117;
+          v260 /= v117;
+          v251 /= v117;
+        }
+        if ( v121 != 255 )
+          v121 &= 0x7FFFFFFFu;
+        v122 = _450F55(v251 | ((v260 | ((a6r | (v121 << 8)) << 8)) << 8));
+        v123 = v201;
+        v201 = (unsigned __int16 *)((char *)v201 + 1);
+        *(_BYTE *)v123 = v122;
+        v112 = v211;
+        a6q = v211;
+      }
+      while ( v211 < dstWidth );
+LABEL_236:
+      v201 = (unsigned __int16 *)((char *)v201 + dstPitch - dstWidth);
+      ++v239;
+      result = v239;
+      if ( v239 >= dstHeight )
+        return result;
+      v11 = 0;
+    }
+  }
+  if ( result == 16 )
+  {
+    result = (int)pDst;
+    v200 = pDst;
+    v238 = 0;
+    if ( dstHeight <= 0 )
+      return result;
+    v98 = dstWidth;
+    a9f = 2 * (dstPitch - dstWidth);
+    while ( 1 )
+    {
+      v99 = 0;
+      a6o = 0;
+      if ( dstWidth <= v11 )
+        goto LABEL_211;
+      v228 = (double)dstWidth;
+      v219 = (double)srcWidth;
+      v100 = (double)dstHeight;
+      v101 = (double)srcHeight;
+      do
+      {
+        a6bg = (double)a6o / v228 * v219;
+        v131 = a6bg + 6.7553994e15;
+        v210 = v99 + 1;
+        a6bh = (double)(v99 + 1) / v228 * v219;
+        v140 = a6bh + 6.7553994e15;
+        v102 = (double)v238 / v100 * v101;
+        v149 = v102 + 6.7553994e15;
+        v103 = (double)(v238 + 1) / v100 * v101;
+        v158 = v103 + 6.7553994e15;
+        v250 = 0;
+        v104 = (LODWORD(v158) - LODWORD(v149)) * (LODWORD(v140) - LODWORD(v131));
+        v259 = 0;
+        a6p = 0;
+        v247 = 0;
+        if ( SLODWORD(v149) >= SLODWORD(v158) )
+          goto LABEL_206;
+        v168 = LODWORD(v158) - LODWORD(v149);
+        v183 = (char *)pSrc + srcPitch * LODWORD(v149);
+        do
+        {
+          v105 = LODWORD(v131);
+          v191 = LODWORD(v131);
+          while ( v105 < SLODWORD(v140) )
+          {
+            v106 = (unsigned __int8)v183[v191];
+            if ( a10 )
+            {
+              v230 = 1;
+              v98 = v106 != a11 ? 0xFF : 0;
+            }
+            v107 = _450FB1(v106);
+            if ( v230 )
+            {
+              v247 += v98;
+              v230 = 0;
+              if ( !v98 )
+              {
+                --v104;
+                goto LABEL_203;
+              }
+            }
+            else
+            {
+              v247 += (unsigned int)v107 >> 24;
+            }
+            a6p += BYTE2(v107);
+            v259 += BYTE1(v107);
+            v250 += (unsigned __int8)v107;
+LABEL_203:
+            ++v191;
+            v105 = v191;
+          }
+          v183 += srcPitch;
+          --v168;
+        }
+        while ( v168 );
+LABEL_206:
+        v108 = v247 / ((LODWORD(v158) - LODWORD(v149)) * (LODWORD(v140) - LODWORD(v131)));
+        if ( v104 )
+        {
+          a6p /= v104;
+          v259 /= v104;
+          v250 /= v104;
+        }
+        if ( v108 != 255 )
+          v108 &= 0x7FFFFFFFu;
+        v109 = _450F55(v250 | ((v259 | ((a6p | (v108 << 8)) << 8)) << 8));
+        v110 = v200;
+        ++v200;
+        *v110 = v109;
+        v99 = v210;
+        a6o = v210;
+      }
+      while ( v210 < dstWidth );
+LABEL_211:
+      v200 = (unsigned __int16 *)((char *)v200 + a9f);
+      ++v238;
+      result = v238;
+      if ( v238 >= dstHeight )
+        return result;
+      v11 = 0;
+    }
+  }
+  if ( result != 32 || (result = (int)pDst, v199 = pDst, v237 = 0, dstHeight <= 0) )
+    return result;
+  v85 = dstWidth;
+  a9e = 4 * (dstPitch - dstWidth);
+  while ( 2 )
+  {
+    v86 = 0;
+    a6m = 0;
+    if ( dstWidth <= v11 )
+      goto LABEL_186;
+    v227 = (double)dstWidth;
+    v218 = (double)srcWidth;
+    v87 = (double)dstHeight;
+    v88 = (double)srcHeight;
+    do
+    {
+      a6be = (double)a6m / v227 * v218;
+      v130 = a6be + 6.7553994e15;
+      v209 = v86 + 1;
+      a6bf = (double)(v86 + 1) / v227 * v218;
+      v139 = a6bf + 6.7553994e15;
+      v89 = (double)v237 / v87 * v88;
+      v148 = v89 + 6.7553994e15;
+      v90 = (double)(v237 + 1) / v87 * v88;
+      v157 = v90 + 6.7553994e15;
+      v249 = 0;
+      v91 = (LODWORD(v157) - LODWORD(v148)) * (LODWORD(v139) - LODWORD(v130));
+      v258 = 0;
+      a6n = 0;
+      v246 = 0;
+      if ( SLODWORD(v148) >= SLODWORD(v157) )
+        goto LABEL_181;
+      v167 = LODWORD(v157) - LODWORD(v148);
+      v182 = (char *)pSrc + srcPitch * LODWORD(v148);
+      do
+      {
+        v92 = LODWORD(v130);
+        v190 = LODWORD(v130);
+        while ( v92 < SLODWORD(v139) )
+        {
+          v93 = (unsigned __int8)v182[v190];
+          if ( a10 )
+          {
+            v230 = 1;
+            v85 = v93 != a11 ? 0xFF : 0;
+          }
+          v94 = _450FB1(v93);
+          if ( v230 )
+          {
+            v246 += v85;
+            v230 = 0;
+            if ( !v85 )
+            {
+              --v91;
+              goto LABEL_178;
+            }
+          }
+          else
+          {
+            v246 += (unsigned int)v94 >> 24;
+          }
+          a6n += BYTE2(v94);
+          v258 += BYTE1(v94);
+          v249 += (unsigned __int8)v94;
+LABEL_178:
+          ++v190;
+          v92 = v190;
+        }
+        v182 += srcPitch;
+        --v167;
+      }
+      while ( v167 );
+LABEL_181:
+      v95 = v246 / ((LODWORD(v157) - LODWORD(v148)) * (LODWORD(v139) - LODWORD(v130)));
+      if ( v91 )
+      {
+        a6n /= v91;
+        v258 /= v91;
+        v249 /= v91;
+      }
+      if ( v95 != 255 )
+        v95 &= 0x7FFFFFFFu;
+      v96 = _450F55(v249 | ((v258 | ((a6n | (v95 << 8)) << 8)) << 8));
+      v97 = v199;
+      v199 += 2;
+      *(_DWORD *)v97 = v96;
+      v86 = v209;
+      a6m = v209;
+    }
+    while ( v209 < dstWidth );
+LABEL_186:
+    v199 = (unsigned __int16 *)((char *)v199 + a9e);
+    ++v237;
+    result = v237;
+    if ( v237 < dstHeight )
+    {
+      v11 = 0;
+      continue;
+    }
+    return result;
+  }
+}
+
+
+
+
+
+
+
+//----- (0044E1EC) --------------------------------------------------------
+int TextureFrameTable::FromFileTxt(const char *Args)
+{
+  TextureFrameTable *v2; // ebx@1
+  FILE *v3; // eax@1
+  int v4; // esi@3
+  const void *v5; // ST0C_4@10
+  void *v6; // eax@10
+  FILE *v7; // ST0C_4@12
+  char *i; // eax@12
+  signed int v9; // esi@15
+  int v10; // eax@17
+  int v11; // edx@22
+  int v12; // ecx@23
+  int v13; // eax@24
+  signed int j; // eax@27
+  TextureFrame *v15; // edx@28
+  int v16; // esi@28
+  int k; // ecx@29
+  char Buf; // [sp+Ch] [bp-2F8h]@3
+  FrameTableTxtLine v20; // [sp+200h] [bp-104h]@4
+  int v21; // [sp+27Ch] [bp-88h]@4
+  char *Str1; // [sp+280h] [bp-84h]@5
+  char *Str; // [sp+284h] [bp-80h]@15
+  int v24; // [sp+2F8h] [bp-Ch]@3
+  int v25; // [sp+2FCh] [bp-8h]@3
+  FILE *File; // [sp+300h] [bp-4h]@1
+  int Argsa; // [sp+30Ch] [bp+8h]@28
+
+  v2 = this;
+  v3 = fopen(Args, "r");
+  File = v3;
+  if ( !v3 )
+    Abortf("CTextureFrameTable::load - Unable to open file: %s.", Args);
+  v4 = 0;
+  v24 = 0;
+  v25 = 1;
+  if ( fgets(&Buf, 490, v3) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v21, texture_frame_table_txt_parser(&Buf, &v20), 0x7Cu);
+      if ( v21 && *Str1 != 47 )
+      {
+        if ( v21 < 2 )
+          Abortf("CTextureFrameTable::load, too few arguments, %s line %i.", Args, v25);
+        ++v24;
+      }
+      ++v25;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v4 = v24;
+  }
+  v5 = v2->pTextures;
+  v2->uNumTextures = v4;
+  v6 = pAllocator->AllocNamedChunk(v5, 20 * v4, "Txt Frames");
+  v2->pTextures = (TextureFrame *)v6;
+  if ( !v6 )
+    Abortf("CTextureFrameTable::load - Out of Memory!");
+  v7 = File;
+  v2->uNumTextures = 0;
+  fseek(v7, 0, 0);
+  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v21, texture_frame_table_txt_parser(&Buf, &v20), 0x7Cu);
+    if ( v21 && *Str1 != 47 )
+    {
+      strcpy(v2->pTextures[v2->uNumTextures].pTextureName, Str1);
+      v2->pTextures[v2->uNumTextures].uAnimTime = atoi(Str);
+      v9 = 2;
+      for ( v2->pTextures[v2->uNumTextures].uFlags = 0; v9 < v21; ++v9 )
+      {
+        if ( !_strcmpi((&Str1)[4 * v9], "New") )
+        {
+          v10 = (int)&v2->pTextures[v2->uNumTextures].uFlags;
+          *(char *)v10 |= 2u;
+        }
+      }
+      ++v2->uNumTextures;
+    }
+  }
+  fclose(File);
+  v11 = 0;
+  if ( (signed int)(v2->uNumTextures - 1) > 0 )
+  {
+    v12 = 0;
+    do
+    {
+      v13 = (int)&v2->pTextures[v12];
+      if ( !(*(char *)(v13 + 38) & 2) )
+        *(char *)(v13 + 18) |= 1u;
+      ++v11;
+      ++v12;
+    }
+    while ( v11 < (signed int)(v2->uNumTextures - 1) );
+  }
+  for ( j = 0; j < (signed int)v2->uNumTextures; *(short *)(Argsa + 16) = v16 )
+  {
+    v15 = v2->pTextures;
+    Argsa = (int)&v15[j];
+    v16 = *(short *)(Argsa + 14);
+    if ( *(char *)(Argsa + 18) & 1 )
+    {
+      ++j;
+      for ( k = (int)&v15[j]; *(char *)(k + 18) & 1; k += 20 )
+      {
+        v16 += *(short *)(k + 14);
+        ++j;
+      }
+      LOWORD(v16) = v15[j].uAnimTime + v16;
+    }
+    ++j;
+  }
+  return 1;
+}
+
+
+
+
+
+
+
+
+//----- (0044F57C) --------------------------------------------------------
+void SpawnEncounter(MapInfo *pMapInfo, SpawnPointMM7 *spawn, int a3, int a4, int a5)
+{
+  //MapInfo *v5; // esi@1
+  //SpawnPointMM7 *v6; // ebx@1
+  int v7; // eax@2
+  char v8; // zf@5
+  int v9; // edi@9
+  int v10; // eax@9
+  int v11; // ecx@9
+  int v12; // edx@9
+  int v13; // eax@9
+  int v14; // eax@14
+  int v15; // ecx@14
+  int v16; // eax@19
+  int v17; // ecx@19
+  int v18; // esi@31
+  //int pPosX; // ecx@32
+  //int v20; // edx@32
+  //int v21; // eax@32
+  Actor *pMonster; // esi@35
+  int v23; // edx@36
+  signed int v24; // edi@36
+  int v25; // ecx@36
+  unsigned __int16 v26; // ax@47
+  MonsterDesc *v27; // edi@48
+  signed int v28; // eax@48
+  __int16 v29; // cx@50
+  __int16 v30; // ax@50
+  __int16 v31; // ax@50
+  int v32; // eax@50
+  int v33; // edi@50
+  int v34; // eax@50
+  int v35; // eax@50
+  int v36; // eax@50
+  int v37; // eax@51
+  int v38; // eax@52
+  int v39; // edi@52
+  std::string v40; // [sp-18h] [bp-100h]@60
+  void *v41; // [sp-14h] [bp-FCh]@50
+  //void *v42; // [sp-10h] [bp-F8h]@50
+  //size_t v43; // [sp-Ch] [bp-F4h]@50
+  const char *v44; // [sp-8h] [bp-F0h]@13
+  char *pTexture; // [sp-4h] [bp-ECh]@9
+  char Str[32]; // [sp+Ch] [bp-DCh]@60
+  char Str2[120]; // [sp+2Ch] [bp-BCh]@29
+  unsigned int uFaceID; // [sp+A4h] [bp-44h]@52
+  MonsterInfo *Src; // [sp+A8h] [bp-40h]@50
+  int v50; // [sp+ACh] [bp-3Ch]@47
+  char Source[32]; // [sp+B0h] [bp-38h]@20
+  int v52; // [sp+D0h] [bp-18h]@34
+  int v53; // [sp+D4h] [bp-14h]@34
+  int pSector; // [sp+D8h] [bp-10h]@32
+  int pPosX; // [sp+DCh] [bp-Ch]@32
+  int v56; // [sp+E0h] [bp-8h]@8
+  int v57; // [sp+E4h] [bp-4h]@1
+
+  //auto a2 = spawn;
+  v57 = 0;
+  //v5 = pMapInfo;
+  //v6 = spawn;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    v7 = pOutdoor->ddm.field_C_alert;
+  else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    v7 = pIndoor->dlv.field_C_alert;
+  else
+    v7 = 0;
+  if (v7)
+    v8 = (spawn->uAttributes & 1) == 0;
+  else
+    v8 = (spawn->uAttributes & 1) == 1;
+  if (v8)
+    return;
+    //result = (void *)(spawn->uIndex - 1);
+  v56 = 1;
+  switch (spawn->uIndex - 1)
+  {
+    case 0u:
+        v9 = pMapInfo->uEncounterMonster1AtLeast;
+        v10 = rand();
+        v11 = pMapInfo->uEncounterMonster1AtMost;
+        pTexture = pMapInfo->pEncounterMonster1Texture;
+        v12 = v10 % (v11 - v9 + 1);
+        v13 = pMapInfo->field_34;
+        goto LABEL_20;
+    case 3u:
+        pTexture = pMapInfo->pEncounterMonster1Texture;
+        v44 = "%s A";
+        goto LABEL_25;
+    case 4u:
+        pTexture = pMapInfo->pEncounterMonster2Texture;
+        v44 = "%s A";
+        goto LABEL_25;
+    case 5u:
+        pTexture = pMapInfo->pEncounterMonster3Texture;
+        v44 = "%s A";
+        goto LABEL_25;
+    case 1u:
+        v9 = pMapInfo->uEncounterMonster2AtLeast;
+        v14 = rand();
+        v15 = pMapInfo->uEncounterMonster2AtMost;
+        pTexture = pMapInfo->pEncounterMonster2Texture;
+        v12 = v14 % (v15 - v9 + 1);
+        v13 = pMapInfo->field_37;
+        goto LABEL_20;
+    case 6u:
+        pTexture = pMapInfo->pEncounterMonster1Texture;
+        v44 = "%s B";
+        goto LABEL_25;
+    case 7u:
+        pTexture = pMapInfo->pEncounterMonster2Texture;
+        v44 = "%s B";
+        goto LABEL_25;
+    case 8u:
+        pTexture = pMapInfo->pEncounterMonster3Texture;
+        v44 = "%s B";
+        goto LABEL_25;
+    case 2u:
+        v9 = pMapInfo->uEncounterMonster3AtLeast;
+        v16 = rand();
+        v17 = pMapInfo->uEncounterMonster3AtMost;
+        pTexture = pMapInfo->pEncounterMonster3Texture;
+        v12 = v16 % (v17 - v9 + 1);
+        v13 = pMapInfo->field_3A;
+LABEL_20:
+        v57 = v13;
+        v56 = v9 + v12;
+        strcpy(Source, pTexture);
+        goto LABEL_26;
+    case 9u:
+        pTexture = pMapInfo->pEncounterMonster1Texture;
+        v44 = "%s C";
+        goto LABEL_25;
+    case 0xAu:
+        pTexture = pMapInfo->pEncounterMonster2Texture;
+        v44 = "%s C";
+        goto LABEL_25;
+    case 0xBu:
+        pTexture = pMapInfo->pEncounterMonster3Texture;
+        v44 = "%s C";
+LABEL_25:
+        sprintf(Source, v44, pTexture);
+LABEL_26:
+        if (Source[0] == '0')
+          return;
+        v57 += a3;
+        if ( v57 > 4 )
+          v57 = 4;
+        strcpy(Str2, Source);
+        if ( a4 )
+          v56 = a4;
+        v18 = v56;
+        if ( (signed int)(v56 + uNumActors) >= 500 )
+          return;
+        pSector = 0;
+        pPosX = spawn->vPosition.x;
+        a4 = spawn->vPosition.y;
+        a3 = spawn->vPosition.z;
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+          pSector = pIndoor->GetSector(spawn->vPosition.x, spawn->vPosition.y, spawn->vPosition.z);
+        v53 = 0;
+        v52 = (((uCurrentlyLoadedLevelType != LEVEL_Outdoor) - 1) & 0x40) + 64;
+        if ( v18 <= 0 )
+          return;
+        break;
+      default:
+        return;
+  }
+  for (uint i = v53; i < v56; ++i)
+  {
+      pMonster = &pActors[uNumActors];
+      pActors[uNumActors].Reset();
+      if ( v57 )
+      {
+        v23 = rand() % 100;
+        v24 = 3;
+        v25 = (unsigned __int16)word_4E8152[3 * v57];
+        if ( v23 >= v25 )
+        {
+          if ( v23 < v25 + (unsigned __int16)word_4E8152[3 * v57 + 1] )
+            v24 = 2;
+        }
+        else
+        {
+          v24 = 1;
+        }
+        if ( v24 == 1 )
+        {
+          pTexture = Source;
+          v44 = "%s A";
+        }
+        else
+        {
+          if ( v24 == 2 )
+          {
+            pTexture = Source;
+            v44 = "%s B";
+          }
+          else
+          {
+            if ( v24 != 3 )
+              goto LABEL_58;
+            pTexture = Source;
+            v44 = "%s C";
+          }
+        }
+        sprintf(Str2, v44, pTexture);
+      }
+      v26 = pMonsterList->GetMonsterByName(Str2);
+      v50 = (signed __int16)v26;
+      pTexture = Str2;
+      if ( (signed __int16)v26 == -1 )
+      {
+        sprintf(Str, "Can't create random monster: '%s'! See MapStats.txt and Monsters.txt!", pTexture);
+        MessageBoxA(nullptr, Str, nullptr, 0);
+        ExitProcess(0);
+      }
+      v27 = &pMonsterList->pMonsters[(signed __int16)v26];
+      v28 = pMonsterStats->_4563FF(pTexture);
+      if ( !v28 )
+        v28 = 1;
+      Src = &pMonsterStats->pInfos[v28];
+      strcpy(pMonster->pActorName, Src->pName);
+      pMonster->sCurrentHP = Src->uHP;
+      assert(sizeof(MonsterInfo) == 88);
+      memcpy(&pMonster->pMonsterInfo, Src, sizeof(MonsterInfo));
+      pMonster->word_000086_some_monster_id = v50 + 1;
+      pMonster->uActorRadius = v27->uMonsterRadius;
+      pMonster->uActorHeight = v27->uMonsterHeight;
+      pMonster->uMovementSpeed = v27->uMovementSpeed;
+      pMonster->vInitialPosition.x = spawn->vPosition.x;
+      pMonster->vPosition.x = spawn->vPosition.x;
+      pMonster->uTetherDistance = 256;
+      pMonster->vInitialPosition.y = a4;
+      pMonster->vPosition.y = a4;
+      pTexture = 0;
+      pMonster->vInitialPosition.z = a3;
+      pMonster->vPosition.z = a3;
+      pMonster->uSectorID = pSector;
+      pMonster->uGroup = spawn->uGroup;
+      pMonster->PrepareSprites((char)pTexture);
+      pMonster->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+      v32 = rand();
+      v33 = v32 % 2048;
+      v34 = stru_5C6E00->SinCos(v32 % 2048);
+      a4 = v34;
+      a3 = (unsigned __int64)(v34 * (signed __int64)v52) >> 16;
+      pPosX = a3 + spawn->vPosition.x;
+      v35 = stru_5C6E00->SinCos(v33 - stru_5C6E00->uIntegerHalfPi);
+      a4 = v35;
+      a3 = (unsigned __int64)(v35 * (signed __int64)v52) >> 16;
+      a4 = a3 + spawn->vPosition.y;
+      v36 = spawn->vPosition.z;
+      a3 = spawn->vPosition.z;
+      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+        goto LABEL_55;
+      v37 = pIndoor->GetSector(pPosX, a4, v36);
+      if ( v37 == pSector )
+      {
+        v38 = _46CEC3_get_floor_level(pPosX, a4, a3, v37, &uFaceID);
+        v39 = v38;
+        if ( v38 != -30000 )
+        {
+          if ( abs(v38 - a3) <= 1024 )
+          {
+            a3 = v39;
+LABEL_55:
+            if ( a5 )
+              pMonster->uAttributes |= 0x080000;
+            ++uNumActors;
+            goto LABEL_58;
+          }
+        }
+      }
+LABEL_58:
+      ;
+      //v53 = (char *)v53 + 1;
+      //result = v53;
+    }
+    //while ( (signed int)v53 < v56 );
+}
+
+
+
+
+//----- (0044FA4C) --------------------------------------------------------
+signed int __fastcall sub_44FA4C_spawn_light_elemental(int a1, int a2, int a3)
+{
+  signed int v3; // ecx@6
+  char *v4; // edx@7
+  signed int result; // eax@13
+  Actor *v6; // esi@16
+  char *v7; // ebx@16
+  MonsterDesc *v8; // edi@16
+  unsigned __int16 v9; // ax@16
+  int v10; // ebx@16
+  int v11; // edi@16
+  int v12; // eax@16
+  int v13; // ecx@16
+  int v14; // ebx@16
+  const char *v15; // [sp-4h] [bp-24h]@2
+  unsigned __int16 v16; // [sp+0h] [bp-20h]@1
+  int v17; // [sp+4h] [bp-1Ch]@1
+  unsigned int uFaceID; // [sp+8h] [bp-18h]@16
+  int v19; // [sp+Ch] [bp-14h]@16
+  size_t v20; // [sp+10h] [bp-10h]@6
+  int v21; // [sp+14h] [bp-Ch]@14
+  int v22; // [sp+18h] [bp-8h]@14
+  unsigned int v23; // [sp+1Ch] [bp-4h]@6
+
+  v16 = a2;
+  v17 = a1;
+  if ( a2 == 4 )
+  {
+    v15 = "Elemental Light C";
+  }
+  else
+  {
+    if ( a2 == 3 )
+      v15 = "Elemental Light B";
+    else
+      v15 = "Elemental Light A";
+  }
+  v23 = (signed __int16)pMonsterList->GetMonsterByName(v15);
+  v3 = 0;
+  v20 = uNumActors;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v4 = (char *)&pActors[0].uAIState;
+    while ( *(short *)v4 != Removed )
+    {
+      ++v3;
+      v4 += 836;
+      if ( v3 >= (signed int)uNumActors )
+        goto LABEL_12;
+    }
+    v20 = v3;
+  }
+LABEL_12:
+  if ( v20 != uNumActors || (result = uNumActors + 1, (signed int)(uNumActors + 1) < 500) )
+  {
+    v21 = 0;
+    v22 = pParty->vPosition.z;
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+      v21 = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
+    v6 = &pActors[v20];
+    v7 = (char *)&pMonsterStats->pInfos[v23 + 1];
+    v19 = (((uCurrentlyLoadedLevelType != LEVEL_Outdoor) - 1) & 0x40) + 64;
+    v6->Reset();
+    v8 = &pMonsterList->pMonsters[v23];
+    strcpy(v6->pActorName, *(const char **)v7);
+    v6->sCurrentHP = *((short *)v7 + 32);
+    memcpy(&v6->pMonsterInfo, v7, 0x58u);
+    v6->word_000086_some_monster_id = v23 + 1;
+    v6->uActorRadius = v8->uMonsterRadius;
+    v6->uActorHeight = v8->uMonsterHeight;
+    v9 = v8->uMovementSpeed;
+    v6->pMonsterInfo.uTreasureDiceRolls = 0;
+    v6->pMonsterInfo.uTreasureType = 0;
+    v6->pMonsterInfo.uExp = 0;
+    v6->uMovementSpeed = v9;
+    v10 = rand() % 2048;
+    v11 = ((unsigned __int64)(stru_5C6E00->SinCos(v10) * (signed __int64)v19) >> 16) + pParty->vPosition.x;
+    uFaceID = stru_5C6E00->SinCos(v10 - stru_5C6E00->uIntegerHalfPi);
+    v23 = (unsigned __int64)(uFaceID * (signed __int64)v19) >> 16;
+    v12 = pParty->vPosition.y;
+    v13 = (unsigned __int64)(uFaceID * (signed __int64)v19) >> 16;
+    v6->vInitialPosition.x = v11;
+    v14 = v13 + v12;
+    LOWORD(v12) = v22;
+    v6->vInitialPosition.z = v22;
+    v6->vPosition.z = v12;
+    LOWORD(v12) = v21;
+    v6->vPosition.x = v11;
+    v6->vInitialPosition.y = v14;
+    v6->vPosition.y = v14;
+    v6->uTetherDistance = 256;
+    v6->uSectorID = v12;
+    v6->PrepareSprites(0);
+    v6->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+    v6->uAlly = 9999;
+    v6->uGroup = 0;
+    v6->uCurrentActionTime = 0;
+    v6->uAIState = Summoned;
+    v6->uCurrentActionLength = 256;
+    v6->UpdateAnimation();
+    if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor
+      || (v22 = pParty->vPosition.z,
+          result = pIndoor->GetSector(v11, v14, pParty->vPosition.z),
+          result == v21)
+      && (result = _46CEC3_get_floor_level(v11, v14, v22, result, &uFaceID), result != -30000)
+      && (result = abs(result - v22), result <= 1024) )
+    {
+      if ( v20 == uNumActors )
+        ++uNumActors;
+      v6->uSummonerID = 8 * v17 | 4;
+      result = v6->pActorBuffs[2].Apply(
+                 pParty->uTimePlayed + (signed __int64)((double)(a3 << 7) * 0.033333335),
+                 v16,
+                 v17,
+                 0,
+                 0);
+    }
+  }
+  return result;
+}
+
+
+//----- (0044FFD8) --------------------------------------------------------
+int MapInfo::SpawnRandomTreasure(SpawnPointMM7 *a2)
+{
+  MapInfo *v2; // ebx@1
+  SpawnPointMM7 *v3; // esi@1
+  int v4; // eax@1
+  int v5; // edx@1
+  int v6; // eax@1
+  int v7; // ecx@1
+  int v8; // ebx@1
+  int v9; // eax@1
+  signed int v10; // ebx@1
+  signed int result; // eax@1
+  signed __int64 v12; // qtt@1
+  int v13; // ebx@1
+  int v14; // edx@10
+  signed int v15; // ebx@20
+  unsigned __int16 v16; // dx@20
+  char *v17; // ecx@21
+  unsigned __int16 v18; // ax@24
+  int v19; // ST0C_4@27
+  int v20; // ST08_4@27
+  int v21; // ST04_4@27
+  int v22; // eax@27
+  signed int v23; // ebx@29
+  unsigned __int16 v24; // dx@29
+  char *v25; // ecx@30
+  unsigned __int16 v26; // ax@33
+  int v27; // ecx@35
+  int v28; // eax@35
+  int v29; // esi@35
+  __int16 v30; // ax@35
+  LayingItem a1a; // [sp+Ch] [bp-7Ch]@1
+  int v32; // [sp+7Ch] [bp-Ch]@1
+  int v33; // [sp+80h] [bp-8h]@1
+  int v34; // [sp+84h] [bp-4h]@1
+
+  __debugbreak();
+
+  auto a1 = this;
+
+  v2 = a1;
+  v3 = a2;
+  v4 = rand();
+  v34 = 0;
+  v5 = v4 % 100;
+  v6 = 2 * (v2->field_2F + 7 * v3->uIndex) - 14;
+  v7 = (unsigned __int8)byte_4E8168[v6 + 16];
+  v8 = (unsigned __int8)byte_4E8168[v6 + 17];
+  v32 = v5;
+  v33 = v7;
+  v9 = rand();
+  v10 = v8 - v33 + 1;
+  v12 = v9;
+  result = v9 / v10;
+  v13 = v33 + (unsigned __int64)(v12 % v10);
+  if ( v13 < 7 )
+  {
+    if ( v32 < 20 )
+      return result;
+    if ( v32 >= 60 )
+    {
+      v19 = v3->vPosition.z;
+      v20 = v3->vPosition.y;
+      v21 = v3->vPosition.x;
+      v22 = rand();
+      return sub_450521_ProllyDropItemAt(v13, v22 % 27 + 20, v21, v20, v19, 0);
+    }
+    if ( v3->uIndex == 1 )
+    {
+      v14 = rand() % 51 + 50;
+    }
+    else
+    {
+      if ( v3->uIndex != 2 )
+      {
+        if ( v3->uIndex == 3 )
+        {
+          v14 = rand() % 301 + 200;
+        }
+        else
+        {
+          if ( v3->uIndex != 4 )
+          {
+            if ( v3->uIndex == 5 )
+            {
+              v14 = rand() % 1001 + 1000;
+            }
+            else
+            {
+              if ( v3->uIndex != 6 )
+              {
+LABEL_20:
+                v15 = 0;
+                v16 = pItemsTable->pItems[a1a.stru_24.uItemID].uSpriteID;
+                a1a.uItemType = pItemsTable->pItems[a1a.stru_24.uItemID].uSpriteID;
+                if ( (signed int)pObjectList->uNumObjects <= 0 )
+                {
+LABEL_24:
+                  v18 = 0;
+                }
+                else
+                {
+                  v17 = (char *)&pObjectList->pObjects->uObjectID;
+                  while ( v16 != *(short *)v17 )
+                  {
+                    ++v15;
+                    v17 += 56;
+                    if ( v15 >= (signed int)pObjectList->uNumObjects )
+                      goto LABEL_24;
+                  }
+                  v18 = v15;
+                }
+                a1a.stru_24.uAttributes |= 1u;
+                a1a.uObjectDescID = v18;
+                a1a.stru_24.uAdditionalValue = v34;
+                goto LABEL_35;
+              }
+              v14 = rand() % 3001 + 2000;
+            }
+            a1a.stru_24.uItemID = 199;
+LABEL_19:
+            v34 = v14;
+            goto LABEL_20;
+          }
+          v14 = rand() % 501 + 500;
+        }
+        a1a.stru_24.uItemID = 198;
+        goto LABEL_19;
+      }
+      v14 = rand() % 101 + 100;
+    }
+    a1a.stru_24.uItemID = 197;
+    goto LABEL_19;
+  }
+  result = a1a.stru_24.GenerateArtifact();
+  if ( !result )
+    return result;
+  v23 = 0;
+  v24 = pItemsTable->pItems[a1a.stru_24.uItemID].uSpriteID;
+  a1a.uItemType = pItemsTable->pItems[a1a.stru_24.uItemID].uSpriteID;
+  if ( (signed int)pObjectList->uNumObjects <= 0 )
+  {
+LABEL_33:
+    v26 = 0;
+  }
+  else
+  {
+    v25 = (char *)&pObjectList->pObjects->uObjectID;
+    while ( v24 != *(short *)v25 )
+    {
+      ++v23;
+      v25 += 56;
+      if ( v23 >= (signed int)pObjectList->uNumObjects )
+        goto LABEL_33;
+    }
+    v26 = v23;
+  }
+  a1a.uObjectDescID = v26;
+  a1a.stru_24.Reset();
+LABEL_35:
+  v27 = v3->vPosition.y;
+  v28 = v3->vPosition.x;
+  v29 = v3->vPosition.z;
+  a1a.vPosition.y = v27;
+  a1a.uAttributes = 0;
+  a1a.uSoundID = 0;
+  a1a.uFacing = 0;
+  a1a.vPosition.z = v29;
+  a1a.vPosition.x = v28;
+  a1a.field_50 = 0;
+  a1a.field_4C = 0;
+  a1a.field_48 = 0;
+  v30 = pIndoor->GetSector(v28, v27, v29);
+  a1a.field_5C = 0;
+  a1a.field_58 = 0;
+  a1a.uSpriteFrameID = 0;
+  a1a.uSectorID = v30;
+  return a1a.Create(0, 0, 0, 0);
+}
+
+//----- (00450218) --------------------------------------------------------
+void __cdecl sub_450218_prolly_generate_chests_loot()
+{
+  unsigned int v0; // eax@1
+  Chest *v1; // ebx@1
+  MapInfo *v2; // esi@1
+  ItemGen *v3; // ebx@2
+  int v4; // ebp@4
+  int v5; // edi@4
+  int v6; // esi@4
+  int v7; // eax@4
+  signed int v8; // esi@4
+  int v9; // edx@4
+  int v10; // esi@8
+  int v11; // ebp@25
+  int v12; // esi@25
+  signed int v13; // ebp@27
+  ItemGen *v14; // edi@28
+  signed int v15; // edx@32
+  signed __int64 v16; // qtt@32
+  int v17; // esi@34
+  signed int v18; // [sp+10h] [bp-18h]@1
+  int v19; // [sp+14h] [bp-14h]@4
+  MapInfo *v20; // [sp+18h] [bp-10h]@1
+  Chest *v21; // [sp+1Ch] [bp-Ch]@1
+  int v22; // [sp+20h] [bp-8h]@26
+  signed int v23; // [sp+24h] [bp-4h]@2
+
+  v18 = rand() % 100;
+  v0 = pMapStats->GetMapInfo(pCurrentMapName);
+  v1 = pChests;
+  v2 = &pMapStats->pInfos[v0];
+  v21 = pChests;
+  v20 = &pMapStats->pInfos[v0];
+  do
+  {
+    v3 = v1->mm7__vector_pItems;
+    v23 = 140;
+    do
+    {
+      if ( (v3->uItemID & 0x80000000u) == 0 )
+        goto LABEL_56;
+      v4 = rand() % 5 + 1;
+      v5 = (unsigned __int8)byte_4E8168[2 * (v2->field_2F + 7 * abs((int)v3->uItemID)) + 2];
+      v6 = (unsigned __int8)byte_4E8168[2 * (v2->field_2F + 7 * abs((int)v3->uItemID)) + 3];
+      v7 = rand();
+      v8 = v6 - v5 + 1;
+      v9 = v5 + v7 % v8;
+      v19 = v5 + v7 % v8;
+      if ( v9 < 7 )
+      {
+        if ( v18 < 20 )
+        {
+          v3->Reset();
+          goto LABEL_25;
+        }
+        if ( v18 < 60 )
+        {
+          v10 = 0;
+          v3->Reset();
+          if ( v19 == 1 )
+          {
+            v10 = rand() % 51 + 50;
+          }
+          else
+          {
+            if ( v19 != 2 )
+            {
+              if ( v19 == 3 )
+              {
+                v10 = rand() % 301 + 200;
+              }
+              else
+              {
+                if ( v19 != 4 )
+                {
+                  if ( v19 == 5 )
+                  {
+                    v10 = rand() % 1001 + 1000;
+LABEL_15:
+                    v3->uItemID = 199;
+                  }
+                  else
+                  {
+                    if ( v19 == 6 )
+                    {
+                      v10 = rand() % 3001 + 2000;
+                      goto LABEL_15;
+                    }
+                  }
+LABEL_23:
+                  v3->uAttributes |= 1u;
+                  v3->uAdditionalValue = v10;
+LABEL_25:
+                  v11 = v4 - 1;
+                  v12 = 0;
+                  if ( v11 > 0 )
+                  {
+                    v22 = v11;
+                    while ( 1 )
+                    {
+                      v13 = v12;
+                      if ( v12 >= 140 )
+                        goto LABEL_52;
+                      v14 = &v21->mm7__vector_pItems[v12];
+                      while ( v14->uItemID )
+                      {
+                        ++v13;
+                        ++v14;
+                        if ( v13 >= 140 )
+                          goto LABEL_52;
+                      }
+                      v16 = rand();
+                      v15 = v16 % 100;
+                      v18 = v16 % 100;
+                      if ( v15 < 20 )
+                        goto LABEL_52;
+                      if ( v15 >= 60 )
+                      {
+                        pItemsTable->GenerateItem(v19, 0, v14);
+                        goto LABEL_51;
+                      }
+                      v17 = 0;
+                      v14->Reset();
+                      if ( v19 == 1 )
+                      {
+                        v17 = rand() % 51 + 50;
+                        goto LABEL_48;
+                      }
+                      if ( v19 == 2 )
+                      {
+                        v17 = rand() % 101 + 100;
+LABEL_48:
+                        v14->uItemID = 197;
+                        goto LABEL_49;
+                      }
+                      if ( v19 == 3 )
+                      {
+                        v17 = rand() % 301 + 200;
+                        goto LABEL_44;
+                      }
+                      if ( v19 == 4 )
+                      {
+                        v17 = rand() % 501 + 500;
+LABEL_44:
+                        v14->uItemID = 198;
+                        goto LABEL_49;
+                      }
+                      if ( v19 == 5 )
+                        break;
+                      if ( v19 == 6 )
+                      {
+                        v17 = rand() % 3001 + 2000;
+LABEL_41:
+                        v14->uItemID = 199;
+                      }
+LABEL_49:
+                      v14->uAdditionalValue = v17;
+LABEL_51:
+                      v12 = v13 + 1;
+LABEL_52:
+                      --v22;
+                      if ( !v22 )
+                        goto LABEL_55;
+                    }
+                    v17 = rand() % 1001 + 1000;
+                    goto LABEL_41;
+                  }
+                  goto LABEL_55;
+                }
+                v10 = rand() % 501 + 500;
+              }
+              v3->uItemID = 198;
+              goto LABEL_23;
+            }
+            v10 = rand() % 101 + 100;
+          }
+          v3->uItemID = 197;
+          goto LABEL_23;
+        }
+        pItemsTable->GenerateItem(v9, 0, v3);
+        goto LABEL_25;
+      }
+      v3->GenerateArtifact();
+LABEL_55:
+      v2 = v20;
+LABEL_56:
+      ++v3;
+      --v23;
+    }
+    while ( v23 );
+    v1 = v21 + 1;
+    ++v21;
+  }
+  while ( (signed int)v21 < (signed int)&uNumChests );
+}
+
+//----- (00450521) --------------------------------------------------------
+signed int __fastcall sub_450521_ProllyDropItemAt(int ecx0, signed int a2, int a3, int a4, int a5, unsigned __int16 a6)
+{
+  int v6; // edi@1
+  int v7; // esi@1
+  signed int v8; // edi@1
+  unsigned __int16 v9; // cx@1
+  char *v10; // edx@2
+  unsigned __int16 v11; // ax@5
+  LayingItem a1; // [sp+8h] [bp-70h]@1
+
+  v6 = ecx0;
+  v7 = a2;
+  pItemsTable->GenerateItem(v6, v7, &a1.stru_24);
+  v8 = 0;
+  v9 = pItemsTable->pItems[a1.stru_24.uItemID].uSpriteID;
+  a1.uItemType = pItemsTable->pItems[a1.stru_24.uItemID].uSpriteID;
+  if ( (signed int)pObjectList->uNumObjects <= 0 )
+  {
+LABEL_5:
+    v11 = 0;
+  }
+  else
+  {
+    v10 = (char *)&pObjectList->pObjects->uObjectID;
+    while ( v9 != *(short *)v10 )
+    {
+      ++v8;
+      v10 += 56;
+      if ( v8 >= (signed int)pObjectList->uNumObjects )
+        goto LABEL_5;
+    }
+    v11 = v8;
+  }
+  a1.uObjectDescID = v11;
+  a1.vPosition.y = a4;
+  a1.vPosition.x = a3;
+  a1.vPosition.z = a5;
+  a1.uFacing = a6;
+  a1.uAttributes = 0;
+  a1.uSectorID = pIndoor->GetSector(a3, a4, a5);
+  a1.uSpriteFrameID = 0;
+  return a1.Create(0, 0, 0, 0);
+}
+
+
+
+
+//----- (0045063B) --------------------------------------------------------
+int __fastcall sub_45063B(MapInfo *a1, int a2)
+{
+  signed int v2; // edi@1
+  Actor *v3; // esi@2
+  signed __int64 v4; // qax@3
+  int result; // eax@8
+  int v6; // edi@11
+  int v7; // ebx@11
+  int v8; // edi@11
+  int v9; // ebx@12
+  int v10; // eax@12
+  char v11; // zf@16
+  int v12; // edi@20
+  int v13; // eax@20
+  int v14; // ebx@20
+  int v15; // eax@20
+  int v16; // eax@20
+  int v17; // eax@20
+  int v18; // eax@21
+  SpawnPointMM7 v19; // [sp+Ch] [bp-38h]@1
+  int v20; // [sp+24h] [bp-20h]@11
+  MapInfo *v21; // [sp+28h] [bp-1Ch]@1
+  int v22; // [sp+2Ch] [bp-18h]@3
+  int v23; // [sp+30h] [bp-14h]@11
+  int v24; // [sp+34h] [bp-10h]@1
+  unsigned int uFaceID; // [sp+38h] [bp-Ch]@10
+  int v26; // [sp+3Ch] [bp-8h]@11
+  int v27; // [sp+40h] [bp-4h]@11
+
+  v21 = a1;
+  v24 = a2;
+  v2 = 0;
+  if ( (signed int)uNumActors <= 0 )
+    goto LABEL_8;
+  v3 = pActors;
+  while ( 1 )
+  {
+    v22 = v3->pMonsterInfo.uID - 1;
+    v4 = (signed __int64)((double)v22 * 0.3333333333333333);
+    if ( (int)v4 != 40 )
+    {
+      if ( (int)v4 != 41 && (int)v4 != 44 && v3->CanAct() )
+        break;
+    }
+    ++v2;
+    ++v3;
+    if ( v2 >= (signed int)uNumActors )
+      goto LABEL_8;
+  }
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+  {
+    v22 = 0;
+    uFaceID = 0;
+    while ( 1 )
+    {
+      ++uFaceID;
+      v6 = rand() % 1024 + 512;
+      v7 = rand() % (signed int)stru_5C6E00->uIntegerDoublePi;
+      v20 = stru_5C6E00->SinCos(v7);
+      v23 = (unsigned __int64)(v20 * (signed __int64)v6) >> 16;
+      v19.vPosition.x = pParty->vPosition.x + v23;
+      v20 = stru_5C6E00->SinCos(v7 - stru_5C6E00->uIntegerHalfPi);
+      v23 = (unsigned __int64)(v20 * (signed __int64)v6) >> 16;
+      v8 = 0;
+      v19.uIndex = v24;
+      v19.vPosition.y = v23 + pParty->vPosition.y;
+      v19.vPosition.z = pParty->vPosition.z;
+      v26 = 0;
+      v27 = 0;
+      v19.vPosition.z = sub_46D49E_prolly_get_world_y_under_party(
+                          v19.vPosition.x,
+                          v23 + pParty->vPosition.y,
+                          pParty->vPosition.z,
+                          0,
+                          &v26,
+                          &v27,
+                          0);
+      v23 = 0;
+      if ( (signed int)pOutdoor->uNumBModels > 0 )
+      {
+        while ( 1 )
+        {
+          v9 = abs(v19.vPosition.y - pOutdoor->pBModels[v8].vBoundingCenter.y);
+          v10 = abs(v19.vPosition.x - pOutdoor->pBModels[v8].vBoundingCenter.x);
+          if ( sub_4621DA(v10, v9, 0) < pOutdoor->pBModels[v8].sBoundingRadius + 256 )
+            break;
+          ++v23;
+          ++v8;
+          if ( v23 >= (signed int)pOutdoor->uNumBModels )
+            goto LABEL_16;
+        }
+        v22 = 1;
+      }
+LABEL_16:
+      v11 = uFaceID == 100;
+      if ( uFaceID >= 100 )
+        break;
+      if ( v22 )
+      {
+        v11 = uFaceID == 100;
+        break;
+      }
+    }
+  }
+  else
+  {
+    v26 = 0;
+    v22 = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
+    do
+    {
+      ++v26;
+      v12 = rand() % 512 + 256;
+      v13 = rand();
+      v14 = v13 % (signed int)stru_5C6E00->uIntegerDoublePi;
+      v15 = stru_5C6E00->SinCos(v13 % (signed int)stru_5C6E00->uIntegerDoublePi);
+      v20 = v15;
+      v23 = (unsigned __int64)(v15 * (signed __int64)v12) >> 16;
+      v19.vPosition.x = pParty->vPosition.x + v23;
+      v16 = stru_5C6E00->SinCos(v14 - stru_5C6E00->uIntegerHalfPi);
+      v20 = v16;
+      v23 = (unsigned __int64)(v16 * (signed __int64)v12) >> 16;
+      v19.vPosition.y = v23 + pParty->vPosition.y;
+      v19.vPosition.z = pParty->vPosition.z;
+      v19.uIndex = v24;
+      v17 = pIndoor->GetSector(v19.vPosition.x, v23 + pParty->vPosition.y, pParty->vPosition.z);
+      if ( v17 == v22 )
+      {
+        v18 = _46CEC3_get_floor_level(v19.vPosition.x, v19.vPosition.y, v19.vPosition.z, v17, &uFaceID);
+        v19.vPosition.z = v18;
+        if ( v18 != -30000 )
+        {
+          if ( abs(v18 - pParty->vPosition.z) <= 1024 )
+            break;
+        }
+      }
+    }
+    while ( v26 < 100 );
+    v11 = v26 == 100;
+  }
+  if ( v11 )
+  {
+LABEL_8:
+    result = 0;
+  }
+  else
+  {
+    SpawnEncounter(v21, &v19, 0, 0, 1);
+    result = v24;
+  }
+  return result;
+}
+
+
+
+//----- (00450929) --------------------------------------------------------
+int LevelDecoration::GetGlobalEvent()
+{
+  LevelDecoration *v1; // esi@1
+  signed int v2; // eax@1
+  int v3; // eax@5
+  int v4; // eax@6
+  int v5; // eax@7
+  int v6; // eax@8
+  int v7; // eax@9
+  int result; // eax@14
+  int v9; // eax@18
+  int v10; // eax@19
+  int v11; // eax@20
+  int v12; // eax@21
+  int v13; // eax@22
+
+  v1 = this;
+  rand();
+  v2 = v1->uDecorationDescID;
+  if ( v2 > 208 )
+  {
+    switch ( v2 )
+    {
+      case 209:
+        result = rand() % 7 + 183;
+        break;
+      case 210:
+        result = 150;
+        break;
+      case 211:
+        result = 151;
+        break;
+      case 212:
+        result = 152;
+        break;
+      case 213:
+        result = 153;
+        break;
+      case 214:
+        result = 154;
+        break;
+      case 215:
+        result = 155;
+        break;
+      case 216:
+        result = 156;
+        break;
+      case 217:
+        result = 157;
+        break;
+      case 218:
+        result = 158;
+        break;
+      case 219:
+        result = 159;
+        break;
+      case 220:
+        result = 160;
+        break;
+      case 221:
+        result = 161;
+        break;
+      default:
+        goto LABEL_45;
+    }
+  }
+  else
+  {
+    if ( v2 == 208 )
+    {
+      result = rand() % 7 + 176;
+    }
+    else
+    {
+      if ( v2 > 24 )
+      {
+        v9 = v2 - 34;
+        if ( !v9 )
+          return rand() % 6 + 4;
+        v10 = v9 - 150;
+        if ( !v10 )
+          return 33;
+        v11 = v10 - 3;
+        if ( !v11 || (v12 = v11 - 3) == 0 )
+          return 37;
+        v13 = v12 - 16;
+        if ( !v13 )
+          return rand() % 7 + 162;
+        if ( v13 == 1 )
+          return rand() % 7 + 169;
+      }
+      else
+      {
+        if ( v2 == 24 )
+          return 36;
+        v3 = v2 - 4;
+        if ( !v3 )
+          return 16;
+        v4 = v3 - 1;
+        if ( !v4 )
+          return 32;
+        v5 = v4 - 1;
+        if ( !v5 )
+          return rand() % 4 + 12;
+        v6 = v5 - 5;
+        if ( !v6 )
+          return 34;
+        v7 = v6 - 2;
+        if ( !v7 )
+          return 17;
+        if ( v7 == 1 )
+          return 18;
+      }
+LABEL_45:
+      result = 0;
+    }
+  }
+  return result;
+}
+
+//----- (00450AAA) --------------------------------------------------------
+void RespawnGlobalDecorations()
+{
+  memset(stru_5E4C90._decor_events, 0, 125);
+
+  uint decorEventIdx = 0;
+  for (uint i = 0; i < uNumLevelDecorations; ++i)
+  {
+    auto decor = pLevelDecorations + i;
+
+    if (!decor->field_16_event_id)
+    {
+      if (decor->IsInteractive())
+      {
+        if (decorEventIdx < 124)
+        {
+          decor->_idx_in_stru123 = decorEventIdx + 75;
+          stru_5E4C90._decor_events[decorEventIdx++] = decor->GetGlobalEvent();
+        }
+      }
+    }
+  }
+}
+
+//----- (00450B0A) --------------------------------------------------------
+bool __fastcall SpawnActor(unsigned int uMonsterID)
+{
+  unsigned int v1; // ebx@1
+  bool result; // eax@2
+  MonsterDesc *v3; // esi@5
+  MonsterInfo *v4; // edi@5
+  Vec3_int_ v5; // ST08_12@5
+  unsigned int v6; // ecx@5
+  Actor *v7; // eax@7
+  Actor actor; // [sp+4h] [bp-350h]@5
+  Vec3_int_ pOut; // [sp+348h] [bp-Ch]@5
+
+  v1 = uMonsterID;
+  if ( uNumActors == 499 )
+  {
+    result = 0;
+  }
+  else
+  {
+    if ( (signed int)uMonsterID >= (signed int)pMonsterList->uNumMonsters )
+      v1 = 0;
+    v3 = &pMonsterList->pMonsters[v1];
+    v4 = &pMonsterStats->pInfos[v1 + 1];
+    memset(&actor, 0, 0x344u);
+    strcpy(actor.pActorName, v4->pName);
+    actor.sCurrentHP = LOWORD(v4->uHP);
+    memcpy(&actor.pMonsterInfo, &pMonsterStats->pInfos[v1 + 1], 0x58u);
+    actor.word_000086_some_monster_id = v1 + 1;
+    actor.uActorRadius = v3->uMonsterRadius;
+    actor.uActorHeight = v3->uMonsterHeight;
+    actor.uMovementSpeed = v3->uMovementSpeed;
+    v5 = pParty->vPosition;
+    Vec3_int_::Rotate(200, pParty->sRotationY, 0, v5, &pOut.x, &pOut.z, &pOut.y);
+    actor.vInitialPosition.x = pOut.x;
+    actor.vPosition.x = pOut.x;
+    actor.uTetherDistance = 256;
+    actor.vInitialPosition.y = LOWORD(pOut.z);
+    actor.vPosition.y = LOWORD(pOut.z);
+    actor.vInitialPosition.z = LOWORD(pOut.y);
+    actor.vPosition.z = LOWORD(pOut.y);
+    pSprites_LOD->DeleteSomeSprites();
+    pPaletteManager->ResetNonTestLocked();
+    v6 = uNumActors - 1;
+    if ( dword_5C6DF8 == 1 )
+    {
+      dword_5C6DF8 = 0;
+      v6 = uNumActors++;
+    }
+    v7 = &pActors[v6];
+    memcpy(v7, &actor, 0x344u);
+    v7->PrepareSprites(1);
+    result = 1;
+  }
+  return result;
+}
+// 5C6DF8: using guessed type int dword_5C6DF8;
+
+
+//----- (00450DA3) --------------------------------------------------------
+int __cdecl GetAlertStatus()
+{
+  int result; // eax@2
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    result = pOutdoor->ddm.field_C_alert;
+  else
+    result = uCurrentlyLoadedLevelType == LEVEL_Outdoor ? pIndoor->dlv.field_C_alert : 0;
+  return result;
+}
+
+
+
+//----- (00450DDE) --------------------------------------------------------
+stru350 *stru350::_450DDE()
+{
+  _450DF1(&stru_4E82A4, &stru_4E82A4);
+  return this;
+}
+
+
+//----- (00450DF1) --------------------------------------------------------
+bool stru350::_450DF1(const stru355 *p1, const stru355 *p2)
+{
+  //stru350 *v3; // esi@1
+  //void *result; // eax@1
+  unsigned int v5; // ecx@2
+  int v6; // edi@2
+  int v7; // edx@2
+  unsigned int v8; // ecx@8
+  int v9; // edi@8
+  int v10; // edx@8
+  int v11; // ecx@12
+  int v12; // edi@12
+  unsigned int v13; // ecx@12
+  int v14; // edx@12
+  int v15; // ecx@16
+  unsigned int v16; // edx@16
+  int v17; // ecx@16
+  int v18; // edi@16
+  char v19; // zf@20
+  unsigned int v20; // ecx@21
+  int v21; // edi@21
+  int v22; // edx@21
+  unsigned int v23; // ecx@27
+  int v24; // edi@27
+  int v25; // edx@27
+  int v26; // ecx@31
+  int v27; // edi@31
+  unsigned int v28; // ecx@31
+  int v29; // edx@31
+  int v30; // ebx@35
+  int v31; // ecx@35
+  int v32; // edi@35
+  int v33; // edx@35
+  unsigned int i; // ecx@35
+  int v35; // ecx@39
+  unsigned int v36; // edx@39
+  int v37; // ecx@39
+  int v38; // ebx@39
+
+  //v3 = this;
+  memcpy(&field_0, p1, sizeof(stru355));
+  memcpy(&field_20, p2, sizeof(stru355));
+  //result = memcpy(&v3->field_20, p2, 0x20u);
+  //LOBYTE(result) = 1;
+  if (field_0.field_4 & 1)
+  {
+    v5 = field_0.field_1C;
+    v6 = 0;
+    v7 = 0;
+    while ( !(v5 & 1) )
+    {
+      ++v6;
+      v5 >>= 1;
+    }
+    do
+    {
+      v5 >>= 1;
+      ++v7;
+    }
+    while ( v5 & 1 );
+    field_40 = 32 - v7 - v6;
+  }
+  else
+  {
+    field_40 = 0;
+  }
+  v8 = field_0.field_10;
+  v9 = 0;
+  v10 = 0;
+  while ( !(v8 & 1) )
+  {
+    ++v9;
+    v8 >>= 1;
+  }
+  do
+  {
+    v8 >>= 1;
+    ++v10;
+  }
+  while ( v8 & 1 );
+  v11 = 24 - v10 - v9;
+  v12 = 0;
+  field_48 = v11;
+  v13 = field_0.field_14;
+  v14 = 0;
+  while ( !(v13 & 1) )
+  {
+    ++v12;
+    v13 >>= 1;
+  }
+  do
+  {
+    v13 >>= 1;
+    ++v14;
+  }
+  while ( v13 & 1 );
+  v15 = 16 - v14;
+  v16 = field_0.field_18;
+  field_50 = v15 - v12;
+  v17 = 0;
+  v18 = 0;
+  while ( !(v16 & 1) )
+  {
+    ++v17;
+    v16 >>= 1;
+  }
+  do
+  {
+    v16 >>= 1;
+    ++v18;
+  }
+  while ( v16 & 1 );
+  v19 = (field_20.field_4 & 1) == 0;
+  field_58 = v17 - v18 + 8;
+  if ( v19 )
+  {
+    field_44 = 0;
+  }
+  else
+  {
+    v20 = field_20.field_1C;
+    v21 = 0;
+    v22 = 0;
+    while ( !(v20 & 1) )
+    {
+      ++v21;
+      v20 >>= 1;
+    }
+    do
+    {
+      v20 >>= 1;
+      ++v22;
+    }
+    while ( v20 & 1 );
+    field_44 = 32 - v22 - v21;
+  }
+  v23 = field_20.field_10;
+  v24 = 0;
+  v25 = 0;
+  while ( !(v23 & 1) )
+  {
+    ++v24;
+    v23 >>= 1;
+  }
+  do
+  {
+    v23 >>= 1;
+    ++v25;
+  }
+  while ( v23 & 1 );
+  v26 = 24 - v25 - v24;
+  v27 = 0;
+  field_4C = v26;
+  v28 = field_20.field_14;
+  v29 = 0;
+  while ( !(v28 & 1) )
+  {
+    ++v27;
+    v28 >>= 1;
+  }
+  do
+  {
+    v28 >>= 1;
+    ++v29;
+  }
+  while ( v28 & 1 );
+  v30 = 0;
+  v31 = 16 - v29 - v27;
+  v32 = field_20.field_18;
+  field_54 = v31;
+  v33 = 0;
+  for ( i = v32; !(i & 1); i >>= 1 )
+    ++v30;
+  do
+  {
+    i >>= 1;
+    ++v33;
+  }
+  while ( i & 1 );
+  v35 = 32 - v33;
+  v36 = v32;
+  field_5C = v35 - v30;
+  v37 = 0;
+  v38 = 0;
+  while ( !(v36 & 1) )
+  {
+    ++v37;
+    v36 >>= 1;
+  }
+  do
+  {
+    v36 >>= 1;
+    ++v38;
+  }
+  while ( v36 & 1 );
+  field_5C = v37 - v38 + 8;
+  return true;
+}
+
+
+
+
+//----- (00450F55) --------------------------------------------------------
+unsigned int stru350::_450F55(int a2)
+{
+  int v2 = a2 & stru_4E82A4.field_1C;
+  if (field_20.field_4 & 1)
+    v2 = (unsigned int)v2 >> this->field_44;
+  return v2 & field_20.field_1C |
+         field_20.field_10 & ((a2 & (unsigned int)stru_4E82A4.field_10) >> field_4C) |
+         field_20.field_14 & ((a2 & (unsigned int)stru_4E82A4.field_14) >> field_54) |
+         field_20.field_18 & ((a2 & (unsigned int)stru_4E82A4.field_18) >> field_5C);
+}
+
+//----- (00450FB1) --------------------------------------------------------
+int stru350::_450FB1(int a2)
+{
+  int v2 = 0;
+  int v4 = field_0.field_4 & 1;
+  if ( v4 )
+    v2 = a2 & field_0.field_1C;
+  if ( v4 )
+    v2 <<= field_40;
+  return v2 | ((a2 & field_0.field_10) << field_48) | ((a2 & field_0.field_14) << field_50) | ((a2 & field_0.field_18) << field_58);
+}
+
+
+//----- (00452442) --------------------------------------------------------
+unsigned int __fastcall sub_452442(unsigned __int16 a1, unsigned __int16 a2, int a3, int a4)
+{
+  int v4; // ebx@0
+  __int16 v5; // ST14_2@1
+  __int16 v6; // dx@1
+  int v7; // ecx@1
+  __int16 v8; // ST10_2@1
+  int v9; // edi@1
+  unsigned __int16 v10; // dh@1@1
+  int v11; // ebx@1
+  int v12; // ebx@1
+  __int16 a3a; // [sp+1Ch] [bp+8h]@1
+
+  v5 = a2 >> 2;
+  v6 = (unsigned __int16)a4 >> 2;
+  v8 = a1 >> 2;
+  a3a = (unsigned __int16)a3 >> 2;
+  LOWORD(v7) = a3a;
+  v9 = v7;
+  LOWORD(v4) = ((unsigned __int16)a4 >> 2) & 0xE0;
+  LOWORD(v7) = a3a & 0xE0;
+  LOWORD(v9) = v9 & 0x1C00;
+  v11 = v7 + v4;
+  LOWORD(v7) = v5 & 0xE0;
+  v12 = v7 + v11;
+  LOWORD(v7) = v8 & 0xE0;
+  return ((v8 & 7) + (v5 & 7) + (a3a & 7) + (v6 & 7)) | (v7 + v12) | ((v8 & 0x1C00)
+                                                                    + (v5 & 0x1C00)
+                                                                    + v9
+                                                                    + (__PAIR__(v10, (unsigned __int16)a4 >> 2) & 0x1C00));
+}
+
+
+
+//----- (0045281E) --------------------------------------------------------
+//    Calculates atan2(y/x)
+// return value: angle in integer format (multiplier of Pi/1024)  
+unsigned int stru193_math::Atan2(int x, int y)
+{
+  signed int quadrant;
+  __int64 dividend;
+  int quotient;
+  int lowIdx;
+  int highIdx;
+  int angle;
+
+  auto X = x;
+  auto Y = y;
+
+  if ( abs(X) < 65536 )
+  {
+    if ( (abs(Y) >> 15) >= abs(X) )
+      X = 0;
+  }
+
+  if ( !X )
+  {
+    if ( Y > 0 )
+    {
+      return uIntegerHalfPi;   //Pi/2
+    }
+    else
+    {
+      return uIntegerHalfPi + uIntegerPi; //3*(Pi/2)
+    }
+  }
+
+  if ( Y )
+  {
+    if ( X < 0 )
+    {
+      X = -X;
+      if ( Y > 0 )
+      {
+        quadrant = 4;        
+      }
+      else
+      {
+        quadrant = 3;        
+      }      
+    }
+    else
+    {
+      if ( Y > 0 )
+      {
+        quadrant = 1;       
+      }
+      else
+      {
+        quadrant = 2;
+      }      
+    }
+
+    if ( Y < 0 )
+      Y = -Y;
+
+    LODWORD(dividend) = Y << 16;
+    HIDWORD(dividend) = Y >> 16;
+    quotient = dividend / X;        
+
+    //looks like binary search
+    {
+      int i;
+      highIdx = uIntegerHalfPi;
+      lowIdx = 0;
+
+      for (i = 0; i < 6; ++i)
+      {        
+        if (quotient <= pTanTable[(lowIdx + highIdx) / 2])      
+          highIdx = (lowIdx + highIdx) / 2;
+        else
+          lowIdx = (lowIdx + highIdx) / 2;    
+      }
+    }
+
+    angle = lowIdx + 1;
+    while ( angle < (highIdx - 1) && quotient >= pTanTable[angle] )
+      ++angle;
+
+    switch (quadrant)
+    {
+    case 1: //X > 0, Y > 0
+      return angle;        
+
+    case 2: //X > 0, Y < 0
+      return uIntegerDoublePi - angle;   //2*Pi - angle
+
+    case 3: //X > 0, Y < 0
+      return uIntegerPi + angle;        //Pi + angle 
+
+    case 4: //X < 0, Y > 0
+      return uIntegerPi - angle;        //Pi - angle  
+    }
+
+    //should newer get here
+    return 0;
+  }
+
+  if ( X < 0 )    //Y == 0, X < 0
+    return uIntegerPi;  
+
+  return 0;
+}
+
+
+
+
+//----- (00452969) --------------------------------------------------------
+stru193_math::stru193_math()
+{
+  stru193_math *v1; // esi@1
+  char *v2; // edi@1
+  double v3; // ST18_8@2
+  signed int v4; // edx@3
+  int v5; // eax@4
+  int v6; // ecx@4
+  signed int v7; // [sp+20h] [bp-4h]@1
+
+  v1 = this;
+  this->uIntegerDoublePi = 2048;
+  this->uIntegerPi = 1024;
+  this->uIntegerHalfPi = 512;
+  this->uDoublePiMask = 2047;
+  this->uPiMask = 1023;
+  this->uHalfPiMask = 511;
+  this->pTanTable[0] = 0;
+  this->pCosTable[0] = 65536;
+  this->pInvCosTable[0] = 65536;
+  v7 = 1;
+  v2 = (char *)&this->pInvCosTable[1];
+  do
+  {
+    v3 = (double)v7 * 3.141592653589793 * 0.0009765625;
+    *((int *)v2 - 1040) = (signed __int64)(tan(v3) * (double)v1->pCosTable[0] + 0.5);
+    *((int *)v2 - 520) = (signed __int64)(cos(v3) * (double)v1->pCosTable[0] + 0.5);
+    ++v7;
+    *(int *)v2 = (signed __int64)(1.0 / cos(v3) * (double)v1->pCosTable[0] + 0.5);
+    v2 += 4;
+  }
+  while ( v7 < (signed int)v1->uIntegerHalfPi );
+  v4 = v1->uIntegerHalfPi;
+  if ( v4 < 520 )
+  {
+    v5 = (int)&v1->pCosTable[v4];
+    v6 = 520 - v4;
+    do
+    {
+      *(int *)v5 = 0;
+      *(int *)(v5 + 2080) = 0xEFFFFFFFu;
+      *(int *)(v5 - 2080) = 0xEFFFFFFFu;
+      v5 += 4;
+      --v6;
+    }
+    while ( v6 );
+  }
+}
+
+//----- (00452A9E) --------------------------------------------------------
+signed int __fastcall sub_452A9E(signed int a1)
+{
+  signed int result; // eax@2
+  int v2; // edx@3
+  signed int v3; // edi@3
+  signed int v4; // ebx@3
+  int v5; // esi@4
+
+  if ( a1 > 1 )
+  {
+    v2 = 0;
+    v3 = a1;
+    result = 0;
+    v4 = 16;
+    do
+    {
+      result *= 2;
+      v2 = ((unsigned int)v3 >> 30) | 4 * v2;
+      v5 = 2 * result + 1;
+      v3 *= 4;
+      if ( v2 >= (unsigned int)v5 )
+      {
+        ++result;
+        v2 -= v5;
+      }
+      --v4;
+    }
+    while ( v4 );
+    if ( a1 - result * result >= (unsigned int)(result - 1) )
+      ++result;
+  }
+  else
+  {
+    result = a1;
+  }
+  return result;
+}
+
+//----- (00452AE2) --------------------------------------------------------
+int __fastcall MakeColorMaskFromBitDepth(int a1)
+{
+  signed __int64 v1; // qax@1
+
+  v1 = 4294967296i64;
+  if ( a1 > 0 )
+  {
+    do
+    {
+      LODWORD(v1) = HIDWORD(v1) + v1;
+      HIDWORD(v1) *= 2;
+      --a1;
+    }
+    while ( a1 );
+  }
+  return v1;
+}
+
+//----- (00452AF3) --------------------------------------------------------
+void __fastcall fill_pixels_fast(unsigned int a1, unsigned __int16 *pPixels, unsigned int uNumPixels)
+{
+  void *v3; // edi@1
+  unsigned int v4; // eax@1
+  unsigned __int16 *v5; // edi@3
+  unsigned int i; // ecx@3
+
+  v3 = pPixels;
+  v4 = a1 | (a1 << 16);
+  if ( (unsigned __int8)pPixels & 2 )           // first 2 pixels
+  {
+    *pPixels = v4;
+    v3 = pPixels + 1;
+    --uNumPixels;
+  }
+  memset32(v3, v4, uNumPixels >> 1);            // 4 pixels at once
+  v5 = (unsigned __int16 *)((char *)v3 + 4 * (uNumPixels >> 1));
+  for ( i = uNumPixels & 1; i; --i )            // leftover pixels
+  {
+    *v5 = v4;
+    ++v5;
+  }
+}
+
+//----- (00452B2E) --------------------------------------------------------
+int __fastcall GetDiceResult(unsigned int uNumDice, unsigned int uDiceSides)
+{
+  signed int v2; // edi@1
+  int v3; // esi@1
+  int result; // eax@2
+  unsigned int v5; // ebx@4
+
+  v2 = uDiceSides;
+  v3 = 0;
+  if ( uDiceSides )
+  {
+    if ( (signed int)uNumDice > 0 )
+    {
+      v5 = uNumDice;
+      do
+      {
+        --v5;
+        v3 += rand() % v2 + 1;
+      }
+      while ( v5 );
+    }
+    result = v3;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+
+//----- (00452B95) --------------------------------------------------------
+void __cdecl SetSomeItemsNames()
+{
+  pSomeItemsNames[0] = pGlobalTXT_LocalizationStrings[568];
+  pSomeItemsNames[1] = pGlobalTXT_LocalizationStrings[271];
+  pSomeItemsNames[2] = pGlobalTXT_LocalizationStrings[272];
+  pSomeItemsNames[3] = pGlobalTXT_LocalizationStrings[273];
+  pSomeItemsNames[4] = pGlobalTXT_LocalizationStrings[274];
+  pSomeItemsNames[5] = pGlobalTXT_LocalizationStrings[275];
+  pSomeItemsNames[6] = pGlobalTXT_LocalizationStrings[276];
+  pSomeItemsNames[7] = pGlobalTXT_LocalizationStrings[277];
+  pSomeItemsNames[8] = pGlobalTXT_LocalizationStrings[278];
+  pSomeItemsNames[9] = pGlobalTXT_LocalizationStrings[279];
+  pSomeItemsNames[10] = pGlobalTXT_LocalizationStrings[280];
+  pSomeItemsNames[11] = pGlobalTXT_LocalizationStrings[281];
+  pSomeItemsNames[12] = pGlobalTXT_LocalizationStrings[282];
+  pSomeItemsNames[13] = pGlobalTXT_LocalizationStrings[143];
+  memset(&stru_5E4C50, 0, sizeof(stru_5E4C50));
+}
+
+//----- (00452C30) --------------------------------------------------------
+char *RemoveQuotes(char *Str)
+{
+  char *v1; // esi@1
+
+  v1 = Str;
+  if ( *Str == '"' )
+  {
+    Str[strlen(Str) - 1] = 0;
+    v1 = Str + 1;
+  }
+  return v1;
+}
+
+//----- (00452C49) --------------------------------------------------------
+void InitializeGameText()
+{
+  //char *v0; // ebx@1
+  char *v1; // eax@3
+  int v2; // ebp@4
+  char v3; // dl@5
+  char *v4; // ecx@5
+  int v5; // esi@9
+  //char **v6; // [sp+10h] [bp-8h]@3
+  signed int v7; // [sp+14h] [bp-4h]@4
+
+  //v0 = 0;
+  if (pGlobalTXT_Raw)
+    pAllocator->FreeChunk(pGlobalTXT_Raw);
+
+  pGlobalTXT_Raw = nullptr;
+  pGlobalTXT_Raw = (char *)pEvents_LOD->LoadRaw("global.txt", 0);
+
+  strtok(pGlobalTXT_Raw, "\r");
+  strtok(nullptr, "\r");
+  v1 = strtok(nullptr, "\r") + 1;
+
+  for (uint i = 0; i < 677; ++i)
+  {
+    char *p = v1;
+    while (*++p != '\t' && *p);
+
+    pGlobalTXT_LocalizationStrings[i] = RemoveQuotes(p + 1);
+
+    v1 = strtok(nullptr, "\r") + 1;
+  }
+
+  aMonthNames[0] = pGlobalTXT_LocalizationStrings[415];
+  aMonthNames[1] = pGlobalTXT_LocalizationStrings[416];
+  aMonthNames[2] = pGlobalTXT_LocalizationStrings[417];
+  pSomeItemsNames[10] = pGlobalTXT_LocalizationStrings[280];
+  aMonthNames[3] = pGlobalTXT_LocalizationStrings[418];
+  pSomeItemsNames[11] = pGlobalTXT_LocalizationStrings[281];
+  aMonthNames[4] = pGlobalTXT_LocalizationStrings[419];
+  pSomeItemsNames[12] = pGlobalTXT_LocalizationStrings[282];
+  aMonthNames[5] = pGlobalTXT_LocalizationStrings[420];
+  pSomeItemsNames[13] = pGlobalTXT_LocalizationStrings[143];
+  aMonthNames[6] = pGlobalTXT_LocalizationStrings[421];
+  aCharacterConditionNames[0] = pGlobalTXT_LocalizationStrings[52];
+  aMonthNames[7] = pGlobalTXT_LocalizationStrings[422];
+  aCharacterConditionNames[1] = pGlobalTXT_LocalizationStrings[241];
+  aMonthNames[8] = pGlobalTXT_LocalizationStrings[423];
+  aCharacterConditionNames[2] = pGlobalTXT_LocalizationStrings[14];
+  aMonthNames[9] = pGlobalTXT_LocalizationStrings[424];
+  aCharacterConditionNames[3] = pGlobalTXT_LocalizationStrings[4];
+  aMonthNames[10] = pGlobalTXT_LocalizationStrings[425];
+  aCharacterConditionNames[4] = pGlobalTXT_LocalizationStrings[69];
+  aMonthNames[11] = pGlobalTXT_LocalizationStrings[426];
+  aCharacterConditionNames[5] = pGlobalTXT_LocalizationStrings[117];
+  pSomeItemsNames[0] = pGlobalTXT_LocalizationStrings[568];
+  aCharacterConditionNames[6] = pGlobalTXT_LocalizationStrings[166];
+  aCharacterConditionNames[8] = pGlobalTXT_LocalizationStrings[166];
+  aCharacterConditionNames[10] = pGlobalTXT_LocalizationStrings[166];
+  pSomeItemsNames[5] = pGlobalTXT_LocalizationStrings[275];
+  aCharacterConditionNames[12] = pGlobalTXT_LocalizationStrings[162];
+  pSomeItemsNames[6] = pGlobalTXT_LocalizationStrings[276];
+  aCharacterConditionNames[13] = pGlobalTXT_LocalizationStrings[231];
+  pSomeItemsNames[7] = pGlobalTXT_LocalizationStrings[277];
+  aCharacterConditionNames[14] = pGlobalTXT_LocalizationStrings[58];
+  pSomeItemsNames[8] = pGlobalTXT_LocalizationStrings[278];
+  aCharacterConditionNames[15] = pGlobalTXT_LocalizationStrings[220];
+  pSomeItemsNames[1] = pGlobalTXT_LocalizationStrings[271];
+  pSomeItemsNames[2] = pGlobalTXT_LocalizationStrings[272];
+  pSomeItemsNames[3] = pGlobalTXT_LocalizationStrings[273];
+  pSomeItemsNames[4] = pGlobalTXT_LocalizationStrings[274];
+  pSomeItemsNames[9] = pGlobalTXT_LocalizationStrings[279];
+  aCharacterConditionNames[7] = pGlobalTXT_LocalizationStrings[65];
+  aCharacterConditionNames[9] = pGlobalTXT_LocalizationStrings[65];
+  aCharacterConditionNames[11] = pGlobalTXT_LocalizationStrings[65];
+  aCharacterConditionNames[16] = pGlobalTXT_LocalizationStrings[76];
+  pClassNames[9] = pGlobalTXT_LocalizationStrings[26];
+  pClassNames[10] = pGlobalTXT_LocalizationStrings[432];
+  pClassNames[11] = pGlobalTXT_LocalizationStrings[27];
+  pClassNames[12] = pGlobalTXT_LocalizationStrings[262];
+  pClassNames[13] = pGlobalTXT_LocalizationStrings[263];
+  pClassNames[14] = pGlobalTXT_LocalizationStrings[264];
+  pClassNames[15] = pGlobalTXT_LocalizationStrings[28];
+  pClassNames[16] = pGlobalTXT_LocalizationStrings[265];
+  pClassNames[17] = pGlobalTXT_LocalizationStrings[267];
+  pClassNames[18] = pGlobalTXT_LocalizationStrings[119];
+  pClassNames[19] = pGlobalTXT_LocalizationStrings[124];
+  pClassNames[20] = pGlobalTXT_LocalizationStrings[31];
+  pClassNames[21] = pGlobalTXT_LocalizationStrings[370];
+  pClassNames[22] = pGlobalTXT_LocalizationStrings[33];
+  aCharacterConditionNames[17] = pGlobalTXT_LocalizationStrings[601];
+  pClassNames[23] = pGlobalTXT_LocalizationStrings[40];
+  aCharacterConditionNames[18] = pGlobalTXT_LocalizationStrings[98];
+  pClassNames[24] = pGlobalTXT_LocalizationStrings[256];
+  pClassNames[0] = pGlobalTXT_LocalizationStrings[253];
+  pClassNames[25] = pGlobalTXT_LocalizationStrings[257];
+  pClassNames[1] = pGlobalTXT_LocalizationStrings[254];
+  pClassNames[26] = pGlobalTXT_LocalizationStrings[44];
+  pClassNames[2] = pGlobalTXT_LocalizationStrings[255];
+  pClassNames[27] = pGlobalTXT_LocalizationStrings[46];
+  pClassNames[3] = pGlobalTXT_LocalizationStrings[2];
+  pClassNames[28] = pGlobalTXT_LocalizationStrings[268];
+  pClassNames[4] = pGlobalTXT_LocalizationStrings[307];
+  pClassNames[29] = pGlobalTXT_LocalizationStrings[269];
+  pClassNames[5] = pGlobalTXT_LocalizationStrings[114];
+  pClassNames[30] = pGlobalTXT_LocalizationStrings[270];
+  pClassNames[6] = pGlobalTXT_LocalizationStrings[3];
+  pClassNames[31] = pGlobalTXT_LocalizationStrings[48];
+  pClassNames[7] = pGlobalTXT_LocalizationStrings[13];
+  pClassNames[32] = pGlobalTXT_LocalizationStrings[259];
+  pClassNames[8] = pGlobalTXT_LocalizationStrings[21];
+  pClassNames[33] = pGlobalTXT_LocalizationStrings[260];
+  pClassNames[34] = pGlobalTXT_LocalizationStrings[261];
+  pClassNames[35] = pGlobalTXT_LocalizationStrings[49];
+  pSkillNames[0] = pGlobalTXT_LocalizationStrings[271];
+  pSkillNames[1] = pGlobalTXT_LocalizationStrings[272];
+  pSkillNames[2] = pGlobalTXT_LocalizationStrings[273];
+  pSkillNames[3] = pGlobalTXT_LocalizationStrings[274];
+  pSkillNames[4] = pGlobalTXT_LocalizationStrings[275];
+  pSkillNames[5] = pGlobalTXT_LocalizationStrings[276];
+  pSkillNames[6] = pGlobalTXT_LocalizationStrings[277];
+  pSkillNames[7] = pGlobalTXT_LocalizationStrings[278];
+  pSkillNames[23] = pGlobalTXT_LocalizationStrings[294];
+  pSkillNames[9] = pGlobalTXT_LocalizationStrings[280];
+  pSkillNames[24] = pGlobalTXT_LocalizationStrings[295];
+  pSkillNames[10] = pGlobalTXT_LocalizationStrings[281];
+  pSkillNames[25] = pGlobalTXT_LocalizationStrings[296];
+  pSkillNames[11] = pGlobalTXT_LocalizationStrings[282];
+  pSkillNames[26] = pGlobalTXT_LocalizationStrings[297];
+  pSkillNames[12] = pGlobalTXT_LocalizationStrings[283];
+  pSkillNames[27] = pGlobalTXT_LocalizationStrings[298];
+  pSkillNames[13] = pGlobalTXT_LocalizationStrings[284];
+  pSkillNames[28] = pGlobalTXT_LocalizationStrings[299];
+  pSkillNames[14] = pGlobalTXT_LocalizationStrings[285];
+  pSkillNames[29] = pGlobalTXT_LocalizationStrings[300];
+  pSkillNames[15] = pGlobalTXT_LocalizationStrings[286];
+  pSkillNames[30] = pGlobalTXT_LocalizationStrings[50];
+  pSkillNames[16] = pGlobalTXT_LocalizationStrings[289];
+  pSkillNames[31] = pGlobalTXT_LocalizationStrings[77];
+  aDayNames[0] = pGlobalTXT_LocalizationStrings[145];
+  pSkillNames[17] = pGlobalTXT_LocalizationStrings[290];
+  pSkillNames[32] = pGlobalTXT_LocalizationStrings[88];
+  aDayNames[1] = pGlobalTXT_LocalizationStrings[230];
+  pSkillNames[18] = pGlobalTXT_LocalizationStrings[291];
+  pSkillNames[33] = pGlobalTXT_LocalizationStrings[89];
+  aDayNames[2] = pGlobalTXT_LocalizationStrings[243];
+  pSkillNames[19] = pGlobalTXT_LocalizationStrings[287];
+  pSkillNames[34] = pGlobalTXT_LocalizationStrings[90];
+  aDayNames[3] = pGlobalTXT_LocalizationStrings[227];
+  pSkillNames[20] = pGlobalTXT_LocalizationStrings[288];
+  pSkillNames[35] = pGlobalTXT_LocalizationStrings[95];
+  aDayNames[4] = pGlobalTXT_LocalizationStrings[91];
+  pSkillNames[21] = pGlobalTXT_LocalizationStrings[292];
+  pSkillNames[36] = pGlobalTXT_LocalizationStrings[301];
+  aDayNames[5] = pGlobalTXT_LocalizationStrings[188];
+  pSkillNames[8] = pGlobalTXT_LocalizationStrings[279];
+  pSkillNames[22] = pGlobalTXT_LocalizationStrings[293];
+  pSkillNames[37] = pGlobalTXT_LocalizationStrings[153];
+  aDayNames[6] = pGlobalTXT_LocalizationStrings[222];
+  aNPCProfessionNames[0] = pGlobalTXT_LocalizationStrings[153];
+  aNPCProfessionNames[1] = pGlobalTXT_LocalizationStrings[308];
+  aNPCProfessionNames[2] = pGlobalTXT_LocalizationStrings[309];
+  aNPCProfessionNames[3] = pGlobalTXT_LocalizationStrings[7];
+  aNPCProfessionNames[4] = pGlobalTXT_LocalizationStrings[306];
+  aNPCProfessionNames[5] = pGlobalTXT_LocalizationStrings[310];
+  aNPCProfessionNames[6] = pGlobalTXT_LocalizationStrings[311];
+  aNPCProfessionNames[7] = pGlobalTXT_LocalizationStrings[312];
+  aSpellSchoolNames[0] = pGlobalTXT_LocalizationStrings[87];
+  aNPCProfessionNames[8] = pGlobalTXT_LocalizationStrings[313];
+  aSpellSchoolNames[1] = pGlobalTXT_LocalizationStrings[6];
+  aNPCProfessionNames[9] = pGlobalTXT_LocalizationStrings[314];
+  aNPCProfessionNames[21] = pGlobalTXT_LocalizationStrings[293];
+  aNPCProfessionNames[10] = pGlobalTXT_LocalizationStrings[105];
+  aSpellSchoolNames[2] = pGlobalTXT_LocalizationStrings[240];
+  aNPCProfessionNames[11] = pGlobalTXT_LocalizationStrings[315];
+  aNPCProfessionNames[22] = pGlobalTXT_LocalizationStrings[324];
+  aNPCProfessionNames[12] = pGlobalTXT_LocalizationStrings[316];
+  aSpellSchoolNames[3] = pGlobalTXT_LocalizationStrings[70];
+  aNPCProfessionNames[13] = pGlobalTXT_LocalizationStrings[317];
+  aNPCProfessionNames[23] = pGlobalTXT_LocalizationStrings[498];
+  aSpellSchoolNames[4] = pGlobalTXT_LocalizationStrings[214];
+  aNPCProfessionNames[14] = pGlobalTXT_LocalizationStrings[115];
+  aNPCProfessionNames[24] = pGlobalTXT_LocalizationStrings[525];
+  aSpellSchoolNames[5] = pGlobalTXT_LocalizationStrings[142];
+  aNPCProfessionNames[15] = pGlobalTXT_LocalizationStrings[318];
+  aNPCProfessionNames[25] = pGlobalTXT_LocalizationStrings[327];
+  aSpellSchoolNames[6] = pGlobalTXT_LocalizationStrings[29];
+  aNPCProfessionNames[16] = pGlobalTXT_LocalizationStrings[319];
+  aNPCProfessionNames[26] = pGlobalTXT_LocalizationStrings[328];
+  aSpellSchoolNames[7] = pGlobalTXT_LocalizationStrings[133];
+  aNPCProfessionNames[17] = pGlobalTXT_LocalizationStrings[320];
+  aNPCProfessionNames[27] = pGlobalTXT_LocalizationStrings[329];
+  aSpellSchoolNames[8] = pGlobalTXT_LocalizationStrings[54];
+  aNPCProfessionNames[18] = pGlobalTXT_LocalizationStrings[321];
+  aNPCProfessionNames[28] = pGlobalTXT_LocalizationStrings[330];
+  aAMPMNames[0] = pGlobalTXT_LocalizationStrings[472];
+  aNPCProfessionNames[19] = pGlobalTXT_LocalizationStrings[322];
+  aNPCProfessionNames[29] = pGlobalTXT_LocalizationStrings[331];
+  aAMPMNames[1] = pGlobalTXT_LocalizationStrings[473];
+  aNPCProfessionNames[20] = pGlobalTXT_LocalizationStrings[323];
+  aNPCProfessionNames[30] = pGlobalTXT_LocalizationStrings[332];
+  aNPCProfessionNames[31] = pGlobalTXT_LocalizationStrings[333];
+  aNPCProfessionNames[32] = pGlobalTXT_LocalizationStrings[334];
+  aNPCProfessionNames[33] = pGlobalTXT_LocalizationStrings[335];
+  aNPCProfessionNames[34] = pGlobalTXT_LocalizationStrings[336];
+  aNPCProfessionNames[35] = pGlobalTXT_LocalizationStrings[337];
+  aNPCProfessionNames[36] = pGlobalTXT_LocalizationStrings[338];
+  aNPCProfessionNames[37] = pGlobalTXT_LocalizationStrings[339];
+  aNPCProfessionNames[38] = pGlobalTXT_LocalizationStrings[340];
+  aNPCProfessionNames[39] = pGlobalTXT_LocalizationStrings[341];
+  aNPCProfessionNames[40] = pGlobalTXT_LocalizationStrings[342];
+  aNPCProfessionNames[56] = pGlobalTXT_LocalizationStrings[21];
+  aNPCProfessionNames[41] = pGlobalTXT_LocalizationStrings[343];
+  aNPCProfessionNames[57] = pGlobalTXT_LocalizationStrings[600];
+  aNPCProfessionNames[42] = pGlobalTXT_LocalizationStrings[596];
+  aNPCProfessionNames[58] = pGlobalTXT_LocalizationStrings[370];
+  aNPCProfessionNames[43] = pGlobalTXT_LocalizationStrings[345];
+  aMoonPhaseNames[0] = pGlobalTXT_LocalizationStrings[150];
+  aNPCProfessionNames[44] = pGlobalTXT_LocalizationStrings[346];
+  aMoonPhaseNames[1] = pGlobalTXT_LocalizationStrings[171];
+  aNPCProfessionNames[45] = pGlobalTXT_LocalizationStrings[347];
+  aMoonPhaseNames[2] = pGlobalTXT_LocalizationStrings[102];
+  aNPCProfessionNames[46] = pGlobalTXT_LocalizationStrings[348];
+  aMoonPhaseNames[3] = pGlobalTXT_LocalizationStrings[169];
+  aNPCProfessionNames[47] = pGlobalTXT_LocalizationStrings[349];
+  aMoonPhaseNames[4] = pGlobalTXT_LocalizationStrings[92];
+  aNPCProfessionNames[48] = pGlobalTXT_LocalizationStrings[350];
+  aAttributeNames[0] = pGlobalTXT_LocalizationStrings[144];
+  aNPCProfessionNames[49] = pGlobalTXT_LocalizationStrings[597];
+  aAttributeNames[1] = pGlobalTXT_LocalizationStrings[116];
+  aNPCProfessionNames[50] = pGlobalTXT_LocalizationStrings[352];
+  aAttributeNames[2] = pGlobalTXT_LocalizationStrings[163];
+  aNPCProfessionNames[51] = pGlobalTXT_LocalizationStrings[353];
+  aAttributeNames[3] = pGlobalTXT_LocalizationStrings[75];
+  aNPCProfessionNames[52] = pGlobalTXT_LocalizationStrings[598];
+  aAttributeNames[4] = pGlobalTXT_LocalizationStrings[1];
+  aNPCProfessionNames[53] = pGlobalTXT_LocalizationStrings[344];
+  aAttributeNames[5] = pGlobalTXT_LocalizationStrings[211];
+  aNPCProfessionNames[54] = pGlobalTXT_LocalizationStrings[26];
+  aAttributeNames[6] = pGlobalTXT_LocalizationStrings[136];
+  aNPCProfessionNames[55] = pGlobalTXT_LocalizationStrings[599];
+  aSpellNames[14] = pGlobalTXT_LocalizationStrings[279];
+  aSpellNames[33] = pGlobalTXT_LocalizationStrings[279];
+  aSpellNames[9] = pGlobalTXT_LocalizationStrings[440];
+  aSpellNames[34] = pGlobalTXT_LocalizationStrings[442];
+  aSpellNames[0] = pGlobalTXT_LocalizationStrings[202];
+  aSpellNames[10] = pGlobalTXT_LocalizationStrings[218];
+  aSpellNames[20] = pGlobalTXT_LocalizationStrings[202];
+  aSpellNames[35] = pGlobalTXT_LocalizationStrings[235];
+  aSpellNames[11] = pGlobalTXT_LocalizationStrings[217];
+  aSpellNames[21] = pGlobalTXT_LocalizationStrings[443];
+  aSpellNames[36] = pGlobalTXT_LocalizationStrings[246];
+  aSpellNames[12] = pGlobalTXT_LocalizationStrings[213];
+  aSpellNames[24] = pGlobalTXT_LocalizationStrings[221];
+  aSpellNames[37] = pGlobalTXT_LocalizationStrings[247];
+  aSpellNames[13] = pGlobalTXT_LocalizationStrings[462];
+  aSpellNames[26] = pGlobalTXT_LocalizationStrings[228];
+  aSpellNames[38] = pGlobalTXT_LocalizationStrings[248];
+  aSpellNames[15] = pGlobalTXT_LocalizationStrings[442];
+  aSpellNames[28] = pGlobalTXT_LocalizationStrings[440];
+  aSpellNames[39] = pGlobalTXT_LocalizationStrings[674];
+  aSpellNames[16] = pGlobalTXT_LocalizationStrings[452];
+  aSpellNames[29] = pGlobalTXT_LocalizationStrings[213];
+  aSpellNames[40] = pGlobalTXT_LocalizationStrings[249];
+  aSpellNames[2] = pGlobalTXT_LocalizationStrings[219];
+  aSpellNames[17] = pGlobalTXT_LocalizationStrings[194];
+  aSpellNames[30] = pGlobalTXT_LocalizationStrings[229];
+  aSpellNames[41] = pGlobalTXT_LocalizationStrings[258];
+  aSpellNames[5] = pGlobalTXT_LocalizationStrings[454];
+  aSpellNames[3] = pGlobalTXT_LocalizationStrings[215];
+  aSpellNames[7] = pGlobalTXT_LocalizationStrings[455];
+  aSpellNames[18] = pGlobalTXT_LocalizationStrings[456];
+  aSpellNames[31] = pGlobalTXT_LocalizationStrings[233];
+  aSpellNames[42] = pGlobalTXT_LocalizationStrings[194];
+  aSpellNames[6] = pGlobalTXT_LocalizationStrings[24];
+  aSpellNames[25] = pGlobalTXT_LocalizationStrings[24];
+  aSpellNames[1] = pGlobalTXT_LocalizationStrings[204];
+  aSpellNames[4] = pGlobalTXT_LocalizationStrings[208];
+  aSpellNames[8] = pGlobalTXT_LocalizationStrings[441];
+  aSpellNames[19] = pGlobalTXT_LocalizationStrings[453];
+  aSpellNames[22] = pGlobalTXT_LocalizationStrings[204];
+  aSpellNames[23] = pGlobalTXT_LocalizationStrings[208];
+  aSpellNames[27] = pGlobalTXT_LocalizationStrings[441];
+  aSpellNames[32] = pGlobalTXT_LocalizationStrings[234];
+  aSpellNames[43] = pGlobalTXT_LocalizationStrings[657];
+}
+
+
+
+
+
+
+
+//----- (00453E6D) --------------------------------------------------------
+void StorylineText::Initialize()
+{
+  char *v1; // ebx@1
+  StorylineText *v2; // esi@1
+  char *v3; // ecx@4
+  char v4; // dl@5
+  char *v5; // eax@5
+  int v6; // esi@9
+  int v7; // [sp+Ch] [bp-10h]@3
+  int v8; // [sp+10h] [bp-Ch]@4
+  char *v9; // [sp+14h] [bp-8h]@4
+  int Str; // [sp+18h] [bp-4h]@3
+
+  v1 = 0;
+  v2 = this;
+  if ( pHistoryTXT_Raw )
+    pAllocator->FreeChunk(pHistoryTXT_Raw);
+  pHistoryTXT_Raw = 0;
+  pHistoryTXT_Raw = (char *)pEvents_LOD->LoadRaw("history.txt", 0);
+  strtok(pHistoryTXT_Raw, "\r");
+  Str = (int)&v2->field_4[4];
+  v7 = 29;
+  do
+  {
+    v9 = v1;
+    v8 = (signed int)v1;
+    v3 = strtok(v1, "\r");
+    do
+    {
+      v4 = *v3;
+      v5 = 0;
+      if ( *v3 != 9 )
+      {
+        v1 = 0;
+        do
+        {
+          if ( !v4 )
+            break;
+          ++v5;
+          v4 = v3[(int)v5];
+        }
+        while ( v4 != 9 );
+      }
+      v6 = (int)&v3[(int)v5];
+      if ( v3[(int)v5] == (char)v1 )
+        v8 = 1;
+      *(char *)v6 = (char)v1;
+      if ( v5 == v1 )
+      {
+        v8 = 1;
+      }
+      else
+      {
+        if ( v9 == (char *)1 )
+        {
+          *(char **)(Str - 8) = RemoveQuotes(v3);
+        }
+        else
+        {
+          if ( v9 == (char *)2 )
+          {
+            *(char *)Str = atoi(v3);
+          }
+          else
+          {
+            if ( v9 - 2 == (char *)1 )
+              *(char * *)(Str - 4) = RemoveQuotes(v3);
+          }
+        }
+      }
+      ++v9;
+      v3 = (char *)(v6 + 1);
+    }
+    while ( (signed int)(v9 - 1) <= 3 && (char *)v8 == v1 );
+    Str += 12;
+    --v7;
+  }
+  while ( v7 );
+}
+
+//----- (00453F62) --------------------------------------------------------
+void MapStats::Initialize()
+{
+  MapStats *v1; // esi@1
+  unsigned int v2; // ebx@3
+  char *v3; // eax@4
+  char *v4; // edi@4
+  char v5; // cl@5
+  int v6; // eax@5
+  size_t v7; // eax@32
+  size_t v8; // eax@35
+  size_t v9; // eax@42
+  size_t v10; // eax@45
+  size_t v11; // eax@52
+  size_t v12; // eax@55
+  char Str[32]; // [sp+Ch] [bp-34h]@30
+  char *v14; // [sp+2Ch] [bp-14h]@9
+  int v15; // [sp+30h] [bp-10h]@4
+  int v16; // [sp+34h] [bp-Ch]@4
+  unsigned int v17; // [sp+38h] [bp-8h]@30
+  MapStats *v18; // [sp+3Ch] [bp-4h]@30
+
+  v1 = this;
+  if ( pMapStatsTXT_Raw )
+    pAllocator->FreeChunk(pMapStatsTXT_Raw);
+  pMapStatsTXT_Raw = 0;
+  pMapStatsTXT_Raw = (char *)pEvents_LOD->LoadRaw("MapStats.txt", 0);
+  strtok(pMapStatsTXT_Raw, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  v2 = 1;
+  v1->uNumMaps = 77;
+  do
+  {
+    v3 = strtok(0, "\r");
+    v16 = 0;
+    v15 = 0;
+    v4 = v3;
+    do
+    {
+      v5 = *v4;
+      v6 = 0;
+      while ( v5 != 9 && v5 )
+      {
+        ++v6;
+        v5 = v4[v6];
+      }
+      v14 = &v4[v6];
+      if ( !v4[v6] )
+        v15 = 1;
+      v4[v6] = 0;
+      if ( v6 )
+      {
+        switch ( v16 )
+        {
+          case 1:
+            v1->pInfos[v2].pName = (char *)RemoveQuotes(v4);
+            break;
+          case 2:
+            v1->pInfos[v2].pFilename = (char *)RemoveQuotes(v4);
+            break;
+          case 3:
+            v1->pInfos[v2].uNumResets = atoi(v4);
+            break;
+          case 4:
+            v1->pInfos[v2].uFirstVisitedAt = atoi(v4);
+            break;
+          case 5:
+            v1->pInfos[v2]._per = atoi(v4);
+            break;
+          case 6:
+            v1->pInfos[v2].uRespawnIntervalDays = atoi(v4);
+            break;
+          case 7:
+            v1->pInfos[v2]._alert_days = atoi(v4);
+            break;
+          case 8:
+            v1->pInfos[v2]._steal_perm = atoi(v4);
+            break;
+          case 9:
+            v1->pInfos[v2].field_2D = atoi(v4);
+            break;
+          case 10:
+            v1->pInfos[v2].field_2E = atoi(v4);
+            break;
+          case 11:
+            v1->pInfos[v2].field_2F = atoi(v4);
+            break;
+          case 12:
+            v1->pInfos[v2].field_30 = atoi(v4);
+            break;
+          case 13:
+            v1->pInfos[v2].field_31 = atoi(v4);
+            break;
+          case 14:
+            v1->pInfos[v2].field_32 = atoi(v4);
+            break;
+          case 15:
+            v1->pInfos[v2].field_33 = atoi(v4);
+            break;
+          case 16:
+            v1->pInfos[v2].pEncounterMonster1Texture = (char *)RemoveQuotes(v4);
+            break;
+          case 18:
+            v1->pInfos[v2].field_34 = atoi(v4);
+            break;
+          case 19:
+            v18 = (MapStats *)((char *)v1 + 68 * v2);
+            v18->pInfos[0].uEncounterMonster1AtLeast = 1;
+            strcpy(Str, v4);
+            v17 = 0;
+            if ( strlen(Str) )
+            {
+              while ( Str[v17] != 45 )
+              {
+                ++v17;
+                v7 = strlen(Str);
+                if ( v17 >= v7 )
+                  goto LABEL_35;
+              }
+              Str[v17] = 0;
+              v18->pInfos[0].uEncounterMonster1AtLeast = atoi(Str);
+            }
+LABEL_35:
+            v8 = strlen(Str);
+            if ( v17 == v8 )
+              v18->pInfos[0].uEncounterMonster1AtMost = atoi(&v4[v17 + 1]);
+            else
+              v18->pInfos[0].uEncounterMonster1AtMost = v18->pInfos[0].uEncounterMonster1AtLeast;
+            break;
+          case 20:
+            v1->pInfos[v2].pEncounterMonster2Texture = (char *)RemoveQuotes(v4);
+            break;
+          case 22:
+            v1->pInfos[v2].field_37 = atoi(v4);
+            break;
+          case 23:
+            v18 = (MapStats *)((char *)v1 + 68 * v2);
+            v18->pInfos[0].uEncounterMonster2AtLeast = 1;
+            strcpy(Str, v4);
+            v17 = 0;
+            if ( strlen(Str) )
+            {
+              while ( Str[v17] != 45 )
+              {
+                ++v17;
+                v9 = strlen(Str);
+                if ( v17 >= v9 )
+                  goto LABEL_45;
+              }
+              Str[v17] = 0;
+              v18->pInfos[0].uEncounterMonster2AtLeast = atoi(Str);
+            }
+LABEL_45:
+            v10 = strlen(Str);
+            if ( v17 == v10 )
+              v18->pInfos[0].uEncounterMonster2AtMost = atoi(&v4[v17 + 1]);
+            else
+              v18->pInfos[0].uEncounterMonster2AtMost = v18->pInfos[0].uEncounterMonster2AtLeast;
+            break;
+          case 24:
+            v1->pInfos[v2].pEncounterMonster3Texture = (char *)RemoveQuotes(v4);
+            break;
+          case 26:
+            v1->pInfos[v2].field_3A = atoi(v4);
+            break;
+          case 27:
+            v18 = (MapStats *)((char *)v1 + 68 * v2);
+            v18->pInfos[0].uEncounterMonster3AtLeast = 1;
+            strcpy(Str, v4);
+            v17 = 0;
+            if ( strlen(Str) )
+            {
+              while ( Str[v17] != 45 )
+              {
+                ++v17;
+                v11 = strlen(Str);
+                if ( v17 >= v11 )
+                  goto LABEL_55;
+              }
+              Str[v17] = 0;
+              v18->pInfos[0].uEncounterMonster3AtLeast = atoi(Str);
+            }
+LABEL_55:
+            v12 = strlen(Str);
+            if ( v17 == v12 )
+              v18->pInfos[0].uEncounterMonster3AtMost = atoi(&v4[v17 + 1]);
+            else
+              v18->pInfos[0].uEncounterMonster3AtMost = v18->pInfos[0].uEncounterMonster3AtLeast;
+            break;
+          case 28:
+            v1->pInfos[v2].uRedbookTrackID = atoi(v4);
+            break;
+          case 29:
+            if ( strcmp(v4, "GENERIC") )
+            {
+              if ( strcmp(v4, "PADDEDCELL") )
+              {
+                if ( strcmp(v4, "ROOM") )
+                {
+                  if ( strcmp(v4, "BATHROOM") )
+                  {
+                    if ( strcmp(v4, "LIVINGROOM") )
+                    {
+                      if ( strcmp(v4, "STONEROOM") )
+                      {
+                        if ( strcmp(v4, "AUDITORIUM") )
+                        {
+                          if ( strcmp(v4, "CONCERTHALL") )
+                          {
+                            if ( strcmp(v4, "CAVE") )
+                            {
+                              if ( strcmp(v4, "ARENA") )
+                              {
+                                if ( strcmp(v4, "HANGAR") )
+                                {
+                                  if ( strcmp(v4, "CARPETEDHALLWAY") )
+                                  {
+                                    if ( strcmp(v4, "HALLWAY") )
+                                    {
+                                      if ( strcmp(v4, "STONECORRIDOR") )
+                                      {
+                                        if ( strcmp(v4, "ALLEY") )
+                                        {
+                                          if ( strcmp(v4, "FOREST") )
+                                          {
+                                            if ( strcmp(v4, "CITY") )
+                                            {
+                                              if ( strcmp(v4, "MOUNTAINS") )
+                                              {
+                                                if ( strcmp(v4, "QUARRY") )
+                                                {
+                                                  if ( strcmp(v4, "PLAIN") )
+                                                  {
+                                                    if ( strcmp(v4, "PARKINGLOT") )
+                                                    {
+                                                      if ( strcmp(v4, "SEWERPIPE") )
+                                                      {
+                                                        if ( strcmp(v4, "UNDERWATER") )
+                                                        {
+                                                          if ( strcmp(v4, "DRUGGED") )
+                                                          {
+                                                            if ( strcmp(v4, "DIZZY") )
+                                                            {
+                                                              if ( strcmp(v4, "PSYCHOTIC") )
+                                                                v1->pInfos[v2].uEAXEnv = 26;
+                                                              else
+                                                                v1->pInfos[v2].uEAXEnv = 25;
+                                                            }
+                                                            else
+                                                            {
+                                                              v1->pInfos[v2].uEAXEnv = 24;
+                                                            }
+                                                          }
+                                                          else
+                                                          {
+                                                            v1->pInfos[v2].uEAXEnv = 23;
+                                                          }
+                                                        }
+                                                        else
+                                                        {
+                                                          v1->pInfos[v2].uEAXEnv = 22;
+                                                        }
+                                                      }
+                                                      else
+                                                      {
+                                                        v1->pInfos[v2].uEAXEnv = 21;
+                                                      }
+                                                    }
+                                                    else
+                                                    {
+                                                      v1->pInfos[v2].uEAXEnv = 20;
+                                                    }
+                                                  }
+                                                  else
+                                                  {
+                                                    v1->pInfos[v2].uEAXEnv = 19;
+                                                  }
+                                                }
+                                                else
+                                                {
+                                                  v1->pInfos[v2].uEAXEnv = 18;
+                                                }
+                                              }
+                                              else
+                                              {
+                                                v1->pInfos[v2].uEAXEnv = 17;
+                                              }
+                                            }
+                                            else
+                                            {
+                                              v1->pInfos[v2].uEAXEnv = 16;
+                                            }
+                                          }
+                                          else
+                                          {
+                                            v1->pInfos[v2].uEAXEnv = 15;
+                                          }
+                                        }
+                                        else
+                                        {
+                                          v1->pInfos[v2].uEAXEnv = 14;
+                                        }
+                                      }
+                                      else
+                                      {
+                                        v1->pInfos[v2].uEAXEnv = 13;
+                                      }
+                                    }
+                                    else
+                                    {
+                                      v1->pInfos[v2].uEAXEnv = 12;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    v1->pInfos[v2].uEAXEnv = 11;
+                                  }
+                                }
+                                else
+                                {
+                                  v1->pInfos[v2].uEAXEnv = 10;
+                                }
+                              }
+                              else
+                              {
+                                v1->pInfos[v2].uEAXEnv = 9;
+                              }
+                            }
+                            else
+                            {
+                              v1->pInfos[v2].uEAXEnv = 8;
+                            }
+                          }
+                          else
+                          {
+                            v1->pInfos[v2].uEAXEnv = 7;
+                          }
+                        }
+                        else
+                        {
+                          v1->pInfos[v2].uEAXEnv = 6;
+                        }
+                      }
+                      else
+                      {
+                        v1->pInfos[v2].uEAXEnv = 5;
+                      }
+                    }
+                    else
+                    {
+                      v1->pInfos[v2].uEAXEnv = 4;
+                    }
+                  }
+                  else
+                  {
+                    v1->pInfos[v2].uEAXEnv = 3;
+                  }
+                }
+                else
+                {
+                  v1->pInfos[v2].uEAXEnv = 2;
+                }
+              }
+              else
+              {
+                v1->pInfos[v2].uEAXEnv = 1;
+              }
+            }
+            else
+            {
+              v1->pInfos[v2].uEAXEnv = 0;
+            }
+            break;
+          default:
+            break;
+        }
+      }
+      else
+      {
+        v15 = 1;
+      }
+      ++v16;
+      v4 = v14 + 1;
+    }
+    while ( v16 - 1 <= 29 && !v15 );
+    ++v2;
+  }
+  while ( (signed int)v2 < 77 );
+  v1->uNumMaps = v2;
+}
+// 453F62: using guessed type char Str[32];
+
+
+
+
+
+
+//----- (004547A3) --------------------------------------------------------
+unsigned int MapStats::GetMapInfo(const char *Str2)
+{
+  MapStats *v2; // esi@1
+  unsigned int v3; // edi@1
+  const char **v4; // ebx@2
+  unsigned int result; // eax@6
+
+  v2 = this;
+  v3 = 1;
+  if ( (signed int)this->uNumMaps <= 1 )
+  {
+LABEL_6:
+    result = 0;
+  }
+  else
+  {
+    v4 = (const char **)&this->pInfos[1].pFilename;
+    while ( !*v4 || _strcmpi(*v4, Str2) )
+    {
+      ++v3;
+      v4 += 17;
+      if ( (signed int)v3 >= (signed int)v2->uNumMaps )
+        goto LABEL_6;
+    }
+    result = v3;
+  }
+  return result;
+}
+
+//----- (004547E4) --------------------------------------------------------
+void FactionTable::Initialize()
+{
+  char *v1; // ebx@1
+  char *v2; // eax@4
+  signed int v3; // edi@4
+  int v4; // ebp@4
+  char v5; // dl@5
+  char *v6; // ecx@5
+  int v7; // esi@9
+  signed int v8; // [sp+4h] [bp-Ch]@3
+  signed int v9; // [sp+8h] [bp-8h]@4
+  FactionTable *v10; // [sp+Ch] [bp-4h]@1
+
+  v1 = 0;
+  v10 = this;
+  if ( pHostileTXT_Raw )
+    pAllocator->FreeChunk(pHostileTXT_Raw);
+  pHostileTXT_Raw = 0;
+  pHostileTXT_Raw = (char *)pEvents_LOD->LoadRaw("hostile.txt", 0);
+  strtok(pHostileTXT_Raw, "\r");
+  v8 = 0;
+  do
+  {
+    v2 = strtok(v1, "\r") + 1;
+    v3 = 0;
+    v9 = (signed int)v1;
+    v4 = (int)((char *)&v10[-7] + v8 - 5);
+    do
+    {
+      v5 = *v2;
+      v6 = 0;
+      if ( *v2 != 9 )
+      {
+        v1 = 0;
+        do
+        {
+          if ( !v5 )
+            break;
+          ++v6;
+          v5 = v2[(int)v6];
+        }
+        while ( v5 != 9 );
+      }
+      v7 = (int)&v2[(int)v6];
+      if ( v2[(int)v6] == (char)v1 )
+        v9 = 1;
+      *(char *)v7 = (char)v1;
+      if ( v6 == v1 )
+      {
+        v9 = 1;
+      }
+      else
+      {
+        if ( v3 >= 1 && v3 <= 90 )
+          *(char *)v4 = atoi(v2);
+      }
+      ++v3;
+      v4 += 89;
+      v2 = (char *)(v7 + 1);
+    }
+    while ( v3 - 1 <= 90 && (char *)v9 == v1 );
+    ++v8;
+  }
+  while ( v8 < 89 );
+
+  if ( pHostileTXT_Raw != v1 )
+  {
+    pAllocator->FreeChunk(pHostileTXT_Raw);
+    pHostileTXT_Raw = v1;
+  }
+}
+
+//----- (004548E2) --------------------------------------------------------
+unsigned int __fastcall ParseSpellType(FrameTableTxtLine *a1, int a2)
+{
+  int v2; // edi@1
+  int v3; // esi@1
+  unsigned int result; // eax@1
+  std::string v5; // [sp-18h] [bp-28h]@75
+  const char *v6; // [sp-8h] [bp-18h]@75
+  signed int v7; // [sp-4h] [bp-14h]@3
+  std::string *v8; // [sp+8h] [bp-8h]@75
+  int a3; // [sp+Fh] [bp-1h]@75
+
+  v2 = (int)a1;
+  v3 = a2;
+  result = (int)a1->pProperties[0];
+  if ( result )
+  {
+    if ( !_strcmpi((const char *)result, "Dispel") )
+    {
+      v7 = 80;
+LABEL_71:
+      result = v7;
+LABEL_76:
+      ++*(int *)v3;
+      return result;
+    }
+    if ( _strcmpi(*(const char **)(v2 + 4), "Day") )
+    {
+      if ( _strcmpi(*(const char **)(v2 + 4), "Hour") )
+      {
+        if ( _strcmpi(*(const char **)(v2 + 4), "Shield") )
+        {
+          if ( !_strcmpi(*(const char **)(v2 + 4), "Spirit") )
+          {
+            v7 = 52;
+            goto LABEL_71;
+          }
+          if ( !_strcmpi(*(const char **)(v2 + 4), "Power") )
+          {
+            v7 = 77;
+            goto LABEL_71;
+          }
+          if ( !_strcmpi(*(const char **)(v2 + 4), "Meteor") )
+          {
+            v7 = 9;
+            goto LABEL_71;
+          }
+          if ( !_strcmpi(*(const char **)(v2 + 4), "Lightning") )
+          {
+            v7 = 18;
+            goto LABEL_71;
+          }
+          if ( _strcmpi(*(const char **)(v2 + 4), "Implosion") )
+          {
+            if ( !_strcmpi(*(const char **)(v2 + 4), "Stone") )
+            {
+              v7 = 38;
+              goto LABEL_71;
+            }
+            if ( _strcmpi(*(const char **)(v2 + 4), "Haste") )
+            {
+              if ( _strcmpi(*(const char **)(v2 + 4), "Heroism") )
+              {
+                if ( !_strcmpi(*(const char **)(v2 + 4), "Pain") )
+                {
+                  v7 = 95;
+                  goto LABEL_71;
+                }
+                if ( _strcmpi(*(const char **)(v2 + 4), "Sparks") )
+                {
+                  if ( !_strcmpi(*(const char **)(v2 + 4), "Light") )
+                  {
+                    v7 = 78;
+                    goto LABEL_71;
+                  }
+                  if ( !_strcmpi(*(const char **)(v2 + 4), "Toxic") )
+                  {
+                    v7 = 90;
+                    goto LABEL_71;
+                  }
+                  if ( _strcmpi(*(const char **)(v2 + 4), "ShrapMetal") )
+                  {
+                    if ( _strcmpi(*(const char **)(v2 + 4), "Paralyze") )
+                    {
+                      if ( _strcmpi(*(const char **)(v2 + 4), "Fireball") )
+                      {
+                        if ( _strcmpi(*(const char **)(v2 + 4), "Incinerate") )
+                        {
+                          if ( !_strcmpi(*(const char **)(v2 + 4), "Fire") )
+                          {
+                            v7 = 2;
+                            goto LABEL_71;
+                          }
+                          if ( !_strcmpi(*(const char **)(v2 + 4), "Rock") )
+                          {
+                            v7 = 41;
+                            goto LABEL_71;
+                          }
+                          if ( !_strcmpi(*(const char **)(v2 + 4), "Mass") )
+                          {
+                            v7 = 44;
+                            goto LABEL_71;
+                          }
+                          if ( !_strcmpi(*(const char **)(v2 + 4), "Ice") )
+                          {
+                            v7 = 26;
+                            goto LABEL_71;
+                          }
+                          if ( !_strcmpi(*(const char **)(v2 + 4), "Acid") )
+                          {
+                            v7 = 29;
+                            goto LABEL_71;
+                          }
+                          if ( _strcmpi(*(const char **)(v2 + 4), "Bless") )
+                          {
+                            if ( !_strcmpi(*(const char **)(v2 + 4), "Dragon") )
+                            {
+                              v7 = 97;
+                              goto LABEL_71;
+                            }
+                            if ( _strcmpi(*(const char **)(v2 + 4), "Reanimate") )
+                            {
+                              if ( !_strcmpi(*(const char **)(v2 + 4), "Summon") )
+                              {
+                                v7 = 82;
+                                goto LABEL_71;
+                              }
+                              if ( _strcmpi(*(const char **)(v2 + 4), "Fate") )
+                              {
+                                if ( _strcmpi(*(const char **)(v2 + 4), "Harm") )
+                                {
+                                  if ( !_strcmpi(*(const char **)(v2 + 4), "Mind") )
+                                  {
+                                    v7 = 57;
+                                    goto LABEL_71;
+                                  }
+                                  if ( _strcmpi(*(const char **)(v2 + 4), "Blades") )
+                                  {
+                                    if ( !_strcmpi(*(const char **)(v2 + 4), "Psychic") )
+                                    {
+                                      v7 = 65;
+                                      goto LABEL_71;
+                                    }
+                                    if ( _strcmpi(*(const char **)(v2 + 4), "Hammerhands") )
+                                    {
+                                      sprintf(pTmpBuf, "Unknown monster spell %s", *(int *)(v2 + 4));
+                                      MessageBoxA(nullptr, pTmpBuf, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Itemdata.cpp:1562", 0);
+                                      result = 0;
+                                      goto LABEL_76;
+                                    }
+                                    v7 = 73;
+                                  }
+                                  else
+                                  {
+                                    v7 = 39;
+                                  }
+                                }
+                                else
+                                {
+                                  v7 = 70;
+                                }
+                              }
+                              else
+                              {
+                                v7 = 47;
+                              }
+                            }
+                            else
+                            {
+                              v7 = 89;
+                            }
+                          }
+                          else
+                          {
+                            v7 = 46;
+                          }
+                        }
+                        else
+                        {
+                          v7 = 11;
+                        }
+                      }
+                      else
+                      {
+                        v7 = 6;
+                      }
+                    }
+                    else
+                    {
+                      v7 = 81;
+                    }
+                  }
+                  else
+                  {
+                    v7 = 93;
+                  }
+                }
+                else
+                {
+                  v7 = 15;
+                }
+              }
+              else
+              {
+                v7 = 51;
+              }
+            }
+            else
+            {
+              v7 = 5;
+            }
+          }
+          else
+          {
+            v7 = 20;
+          }
+        }
+        else
+        {
+          v7 = 17;
+        }
+        return v7;
+      }
+      v7 = 86;
+    }
+    else
+    {
+      v7 = 85;
+    }
+    *(int *)v3 += 2;
+    result = v7;
+  }
+  return result;
+}
+
+//----- (00454CB4) --------------------------------------------------------
+int __thiscall ParseAttackType(unsigned __int8 *a1)
+{
+  unsigned __int8 *v1; // esi@1
+  int result; // eax@4
+  int v3; // eax@15
+  int v4; // eax@18
+
+  v1 = a1;
+  if ( !a1 )
+    return 4;
+  if ( tolower(*a1) == 'f' )
+    return 0;
+  if ( tolower(*v1) == 'a' )
+    return 1;
+  if ( tolower(*v1) == 'w' )
+    return 2;
+  if ( tolower(*v1) == 'e' )
+  {
+    tolower(v1[1]);
+    return 3;
+  }
+  if ( tolower(*v1) == 's' )
+    return 6;
+  if ( tolower(*v1) == 'm' )
+  {
+    v3 = -(tolower(v1[1]) != 'i');
+    LOBYTE(v3) = v3 & 0xFE;
+    result = v3 + 7;
+  }
+  else
+  {
+    if ( tolower(*v1) == 'l' )
+      return 9;
+    v4 = -(tolower(*v1) != 'd');
+    LOBYTE(v4) = v4 & 0xFA;
+    result = v4 + 10;
+  }
+  return result;
+}
+
+//----- (00454D7D) --------------------------------------------------------
+char __fastcall ParseDamage(const char *Str, int a2, int a3, int a4)
+{
+  int v4; // esi@1
+  const char *v5; // edi@1
+  signed int v6; // ebx@1
+  int *v7; // esi@2
+  int v8; // eax@3
+  size_t v10; // [sp+Ch] [bp-Ch]@1
+  int v11; // [sp+10h] [bp-8h]@1
+  signed int v12; // [sp+14h] [bp-4h]@1
+
+  v4 = a2;
+  v5 = Str;
+  *(char *)a2 = 0;
+  *(char *)a3 = 1;
+  v11 = a2;
+  *(char *)a4 = 0;
+  v6 = 0;
+  v10 = strlen(Str);
+  v12 = 0;
+  if ( (signed int)v10 <= 0 )
+  {
+LABEL_9:
+    LOBYTE(v8) = *v5;
+    if ( (unsigned __int8)*v5 >= 0x30u && (unsigned __int8)v8 <= 0x39u )
+    {
+      *(char *)v4 = atoi(v5);
+      LOBYTE(v8) = a3;
+      *(char *)a3 = 1;
+    }
+    return v8;
+  }
+  do
+  {
+    v7 = (int *)&v5[v6];
+    if ( tolower((unsigned __int8)v5[v6]) == 100 )
+    {
+      *(char *)v7 = 0;
+      *(char *)v11 = atoi(v5);
+      LOBYTE(v8) = atoi(&v5[v6 + 1]);
+      v12 = 1;
+      *(char *)a3 = v8;
+      *(char *)v7 = 100;
+    }
+    else
+    {
+      v8 = tolower(*(char *)v7);
+      if ( v8 == 43 )
+      {
+        LOBYTE(v8) = atoi(&v5[v6 + 1]);
+        *(char *)a4 = v8;
+      }
+    }
+    ++v6;
+  }
+  while ( v6 < (signed int)v10 );
+  if ( !v12 )
+  {
+    v4 = v11;
+    goto LABEL_9;
+  }
+  return v8;
+}
+
+//----- (00454E3A) --------------------------------------------------------
+int __fastcall ParseMissleAttackType(const char *Str1)
+{
+  const char *v1; // esi@1
+  int v2; // edi@1
+  int v4; // [sp-4h] [bp-Ch]@4
+
+  v1 = Str1;
+  v2 = 0;
+  if ( _strcmpi(Str1, "ARROW") )
+  {
+    if ( _strcmpi(v1, "ARROWF") )
+    {
+      if ( _strcmpi(v1, "FIRE") )
+      {
+        if ( _strcmpi(v1, "AIR") )
+        {
+          if ( _strcmpi(v1, "WATER") )
+          {
+            if ( _strcmpi(v1, "EARTH") )
+            {
+              if ( _strcmpi(v1, "SPIRIT") )
+              {
+                if ( _strcmpi(v1, "MIND") )
+                {
+                  if ( _strcmpi(v1, "BODY") )
+                  {
+                    if ( _strcmpi(v1, "LIGHT") )
+                    {
+                      if ( _strcmpi(v1, "DARK") )
+                      {
+                        if ( _strcmpi(v1, "ENER") )
+                          return v2;
+                        v4 = 13;
+                      }
+                      else
+                      {
+                        v4 = 11;
+                      }
+                    }
+                    else
+                    {
+                      v4 = 10;
+                    }
+                  }
+                  else
+                  {
+                    v4 = 9;
+                  }
+                }
+                else
+                {
+                  v4 = 8;
+                }
+              }
+              else
+              {
+                v4 = 7;
+              }
+            }
+            else
+            {
+              v4 = 6;
+            }
+          }
+          else
+          {
+            v4 = 5;
+          }
+        }
+        else
+        {
+          v4 = 4;
+        }
+      }
+      else
+      {
+        v4 = 3;
+      }
+    }
+    else
+    {
+      v4 = 2;
+    }
+    return v4;
+  }
+  return 1;
+}
+
+
+
+
+
+
+//----- (00458244) --------------------------------------------------------
+unsigned int __fastcall SkillToMastery(unsigned __int16 a1)
+{
+  unsigned int result; // eax@1
+
+  result = 1;                                   // Normal
+  if ( HIBYTE(a1) & 1 )
+  {
+    result = 4;                                 // Grandmaster
+  }
+  else
+  {
+    if ( (a1 & 0x80u) == 0 )
+    {
+      if ( a1 & 0x40 )
+        result = 2;                             // Expert
+    }
+    else
+    {
+      result = 3;                               // Master
+    }
+  }
+  return result;
+}
+
+
+//----- (0045828B) --------------------------------------------------------
+unsigned int __fastcall GetSpellColor(signed int a1)
+{
+  unsigned __int16 v1; // dx@3
+  unsigned __int16 v2; // cx@6
+  unsigned __int16 v4; // [sp-4h] [bp-4h]@3
+
+  if ( a1 < 1 )
+  {
+    if ( a1 < 12 )
+    {
+      if ( a1 < 23 )
+      {
+        if ( a1 < 34 )
+        {
+          if ( a1 < 45 )
+          {
+            if ( a1 < 56 )
+            {
+              if ( a1 < 67 )
+              {
+                if ( a1 < 78 )
+                {
+                  if ( a1 < 89 )
+                    goto LABEL_31;
+                  goto LABEL_28;
+                }
+LABEL_25:
+                if ( a1 < 89 )
+                {
+                  v4 = 155;
+                  v2 = 255;
+                  goto LABEL_30;
+                }
+LABEL_28:
+                if ( a1 < 100 )
+                {
+                  v4 = 240;
+                  v2 = 192;
+                  goto LABEL_30;
+                }
+LABEL_31:
+                v4 = 0;
+                v1 = 0;
+                goto LABEL_32;
+              }
+LABEL_21:
+              if ( a1 < 78 )
+              {
+                v4 = 0;
+                v1 = 128;
+                goto LABEL_23;
+              }
+              goto LABEL_25;
+            }
+LABEL_18:
+            if ( a1 < 67 )
+            {
+              v4 = 255;
+              v1 = 15;
+              v2 = 235;
+              return GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v2, v1, v4);
+            }
+            goto LABEL_21;
+          }
+LABEL_15:
+          if ( a1 < 56 )
+          {
+            v2 = 225;
+            goto LABEL_13;
+          }
+          goto LABEL_18;
+        }
+LABEL_11:
+        if ( a1 < 45 )
+        {
+          v2 = 128;
+LABEL_13:
+          v4 = v2;
+LABEL_30:
+          v1 = v2;
+          return GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v2, v1, v4);
+        }
+        goto LABEL_15;
+      }
+LABEL_8:
+      if ( a1 < 34 )
+      {
+        v4 = 255;
+        v1 = 128;
+LABEL_32:
+        v2 = 0;
+        return GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v2, v1, v4);
+      }
+      goto LABEL_11;
+    }
+  }
+  else
+  {
+    if ( a1 < 12 )
+    {
+      v4 = 0;
+      v1 = 85;
+LABEL_23:
+      v2 = 255;
+      return GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v2, v1, v4);
+    }
+  }
+  if ( a1 >= 23 )
+    goto LABEL_8;
+  v4 = 255;
+  v1 = 212;
+  v2 = 150;
+  return GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v2, v1, v4);
+}
+
+
+//----- (004583B0) --------------------------------------------------------
+LevelDecoration::LevelDecoration()
+{
+  this->field_1A = 0;
+  this->field_18 = 0;
+  this->vPosition.z = 0;
+  this->vPosition.y = 0;
+  this->vPosition.x = 0;
+  this->uDecorationDescID = 0;
+  this->field_2 = 0;
+  this->field_16_event_id = 0;
+  this->uCog = 0;
+}
+
+
+
+
+
+
+
+
+
+//----- (00458600) --------------------------------------------------------
+void DecorationList::ToFile()
+{
+  DecorationList *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  v1 = this;
+  v2 = fopen("data\\ddeclist.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save ddeclist.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pDecorations, 0x54u, v1->uNumDecorations, v3);
+  fclose(v3);
+}
+
+//----- (0045864C) --------------------------------------------------------
+void DecorationList::FromFile(void *pSerialized)
+{
+  uNumDecorations = *(int *)pSerialized;
+  pDecorations = (DecorationDesc *)pAllocator->AllocNamedChunk(pDecorations,
+                           84 * uNumDecorations, "Dec Descrip");
+  memcpy(pDecorations, (char *)pSerialized + 4, 84 * uNumDecorations);
+}
+
+//----- (00458693) --------------------------------------------------------
+void DecorationList::InitializeDecorationSprite(unsigned int uDecID)
+{
+  pSpriteFrameTable->InitializeSprite(this->pDecorations[uDecID].uSpriteID);
+}
+
+//----- (004586B0) --------------------------------------------------------
+bool DecorationList::FromFileTxt(const char *Args)
+{
+  DecorationList *v2; // ebx@1
+  FILE *v3; // eax@1
+  unsigned int v4; // esi@3
+  void *v5; // eax@10
+  FILE *v6; // ST18_4@12
+  char *i; // eax@12
+  unsigned __int16 v8; // ax@16
+  const char *v9; // ST20_4@16
+  const char *v10; // ST18_4@16
+  __int16 v11; // ax@16
+  const char *v12; // ST14_4@16
+  unsigned __int16 v13; // ax@16
+  const char *v14; // ST10_4@16
+  __int16 v15; // ax@16
+  const char *v16; // ST0C_4@16
+  unsigned __int8 v17; // al@16
+  const char *v18; // ST08_4@16
+  unsigned __int8 v19; // al@16
+  const char *v20; // ST04_4@16
+  unsigned __int8 v21; // al@16
+  const char *v22; // ST00_4@16
+  unsigned __int8 v23; // zf@16
+  char v24; // sf@16
+  unsigned __int8 v25; // of@16
+  int j; // edi@17
+  const char *v27; // esi@18
+  int v28; // eax@19
+  int v29; // eax@21
+  int v30; // eax@23
+  int v31; // eax@25
+  int v32; // eax@27
+  int v33; // eax@29
+  int v34; // eax@31
+  int v35; // eax@33
+  FrameTableTxtLine v37; // [sp+Ch] [bp-460h]@17
+  FrameTableTxtLine v38; // [sp+88h] [bp-3E4h]@13
+  char Dest; // [sp+104h] [bp-368h]@17
+  char Buf; // [sp+17Ch] [bp-2F0h]@3
+  FrameTableTxtLine v41; // [sp+370h] [bp-FCh]@4
+  FrameTableTxtLine v42; // [sp+3ECh] [bp-80h]@4
+  FILE *File; // [sp+468h] [bp-4h]@1
+  unsigned int Argsa; // [sp+474h] [bp+8h]@3
+
+  v2 = this;
+  v3 = fopen(Args, "r");
+  File = v3;
+  if ( !v3 )
+    Abortf("DecorationDescriptionList::load - Unable to open file: %s.");
+  v4 = 0;
+  Argsa = 0;
+  if ( fgets(&Buf, 490, v3) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v42, frame_table_txt_parser(&Buf, &v41), sizeof(v42));
+      if ( v42.field_0 && *v42.pProperties[0] != 47 && v42.field_0 >= 3 )
+        ++Argsa;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v4 = Argsa;
+  }
+  v2->uNumDecorations = v4;
+  v5 = pAllocator->AllocNamedChunk(v2->pDecorations, 84 * v4, "Dec Descrip");
+  v2->pDecorations = (DecorationDesc *)v5;
+  if ( !v5 )
+    Abortf("DecorationDescriptionList::load - Out of Memory!");
+  v6 = File;
+  v2->uNumDecorations = 0;
+  fseek(v6, 0, 0);
+  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v42, frame_table_txt_parser(&Buf, &v38), sizeof(v42));
+    if ( v42.field_0 && *v42.pProperties[0] != 47 && v42.field_0 >= 3 )
+    {
+      strcpy(v2->pDecorations[v2->uNumDecorations].pName, v42.pProperties[1]);
+      v8 = pSpriteFrameTable->FastFindSprite(v2->pDecorations[v2->uNumDecorations].pName);
+      v9 = v42.pProperties[2];
+      v2->pDecorations[v2->uNumDecorations].uSpriteID = v8;
+      strcpy(v2->pDecorations[v2->uNumDecorations].field_20, v9);
+      v10 = v42.pProperties[3];
+      v2->pDecorations[v2->uNumDecorations].uType = 0;
+      v11 = atoi(v10);
+      v12 = v42.pProperties[4];
+      v2->pDecorations[v2->uNumDecorations].uRadius = v11;
+      v13 = atoi(v12);
+      v14 = v42.pProperties[5];
+      v2->pDecorations[v2->uNumDecorations].uDecorationHeight = v13;
+      v15 = atoi(v14);
+      v16 = v42.pProperties[6];
+      v2->pDecorations[v2->uNumDecorations].uLightRadius = v15;
+      v17 = atoi(v16);
+      v18 = v42.pProperties[7];
+      v2->pDecorations[v2->uNumDecorations].uColoredLightRed = v17;
+      v19 = atoi(v18);
+      v20 = v42.pProperties[8];
+      v2->pDecorations[v2->uNumDecorations].uColoredLightGreen = v19;
+      v21 = atoi(v20);
+      v22 = v42.pProperties[9];
+      v2->pDecorations[v2->uNumDecorations].uColoredLightBlue = v21;
+      v2->pDecorations[v2->uNumDecorations].uSoundID = atoi(v22);
+      v25 = __OFSUB__(v42.field_0, 10);
+      v23 = v42.field_0 == 10;
+      v24 = v42.field_0 - 10 < 0;
+      v2->pDecorations[v2->uNumDecorations].uFlags = 0;
+      if ( !((unsigned __int8)(v24 ^ v25) | v23) )
+      {
+        strcpy(&Dest, v42.pProperties[10]);
+        memcpy(&v41, frame_table_txt_parser(&Dest, &v37), sizeof(v41));
+        for ( j = 0; j < v41.field_0; ++j )
+        {
+          v27 = v41.pProperties[j];
+          if ( _strcmpi(v41.pProperties[j], "NBM") )
+          {
+            if ( _strcmpi(v27, "Invisible") )
+            {
+              if ( _strcmpi(v27, "FS") )
+              {
+                if ( _strcmpi(v27, "FM") )
+                {
+                  if ( _strcmpi(v27, "FF") )
+                  {
+                    if ( _strcmpi(v27, "Marker") )
+                    {
+                      if ( _strcmpi(v27, "LoopSlow") )
+                      {
+                        if ( _strcmpi(v27, "EmitFire") )
+                        {
+                          if ( _strcmpi(v27, "Dawn") )
+                          {
+                            if ( !_strcmpi(v27, "Dusk") )
+                              HIBYTE(v2->pDecorations[v2->uNumDecorations].uFlags) |= 2u;
+                          }
+                          else
+                          {
+                            HIBYTE(v2->pDecorations[v2->uNumDecorations].uFlags) |= 1u;
+                          }
+                        }
+                        else
+                        {
+                          v35 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
+                          *(char *)v35 |= 0x80u;
+                        }
+                      }
+                      else
+                      {
+                        v34 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
+                        *(char *)v34 |= 0x40u;
+                      }
+                    }
+                    else
+                    {
+                      v33 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
+                      *(char *)v33 |= 0x20u;
+                    }
+                  }
+                  else
+                  {
+                    v32 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
+                    *(char *)v32 |= 0x10u;
+                  }
+                }
+                else
+                {
+                  v31 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
+                  *(char *)v31 |= 8u;
+                }
+              }
+              else
+              {
+                v30 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
+                *(char *)v30 |= 4u;
+              }
+            }
+            else
+            {
+              v29 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
+              *(char *)v29 |= 2u;
+            }
+          }
+          else
+          {
+            v28 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
+            *(char *)v28 |= 1u;
+          }
+        }
+      }
+      ++v2->uNumDecorations;
+    }
+  }
+  fclose(File);
+  return 1;
+}
+
+
+
+
+
+//----- (00459064) --------------------------------------------------------
+void ObjectList::InitializeSprites()
+{
+  for (uint i = 0; i < uNumObjects; ++i)
+    pSpriteFrameTable->InitializeSprite(pObjects[i].uSpriteID);
+}
+
+//----- (00459090) --------------------------------------------------------
+void ObjectList::ToFile()
+{
+  ObjectList *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  v1 = this;
+  v2 = fopen("data\\dobjlist.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dobjlist.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pObjects, 0x38u, v1->uNumObjects, v3);
+  fclose(v3);
+}
+
+//----- (004590DC) --------------------------------------------------------
+void ObjectList::FromFile(void *pSerialized)
+{
+  uNumObjects = *(int *)pSerialized;
+  pObjects = (ObjectDesc *)pAllocator->AllocNamedChunk(pObjects, 56 * uNumObjects, "Obj Descrip");
+  memcpy(pObjects, (char *)pSerialized + 4, 56 * uNumObjects);
+}
+
+//----- (00459123) --------------------------------------------------------
+bool ObjectList::FromFileTxt(const char *Args)
+{
+  ObjectList *v2; // ebx@1
+  __int32 v3; // edi@1
+  FILE *v4; // eax@1
+  unsigned int v5; // esi@3
+  void *v6; // eax@9
+  FILE *v7; // ST0C_4@11
+  char *i; // eax@11
+  unsigned __int16 v9; // ax@14
+  const char *v10; // ST20_4@14
+  __int16 v11; // ax@14
+  const char *v12; // ST1C_4@14
+  __int16 v13; // ax@14
+  const char *v14; // ST18_4@14
+  __int16 v15; // ax@14
+  const char *v16; // ST14_4@14
+  __int16 v17; // ax@14
+  const char *v18; // ST10_4@14
+  __int16 v19; // ax@14
+  const char *v20; // ST0C_4@14
+  int v21; // esi@16
+  const char *v22; // edi@16
+  int v23; // eax@17
+  int v24; // eax@19
+  int v25; // eax@21
+  int v26; // eax@21
+  int v27; // eax@21
+  int v28; // eax@23
+  int v29; // eax@25
+  int v30; // eax@27
+  int v31; // eax@29
+  const char *v32; // edi@30
+  const char *v33; // ST20_4@35
+  int v34; // eax@35
+  char v35; // al@35
+  const char *v36; // ST1C_4@35
+  char v37; // al@35
+  const char *v38; // ST18_4@35
+  FrameTableTxtLine v40; // [sp+8h] [bp-460h]@14
+  FrameTableTxtLine v41; // [sp+84h] [bp-3E4h]@12
+  char Dest; // [sp+100h] [bp-368h]@14
+  char Buf; // [sp+178h] [bp-2F0h]@3
+  FrameTableTxtLine v44; // [sp+36Ch] [bp-FCh]@4
+  FrameTableTxtLine v45; // [sp+3E8h] [bp-80h]@4
+  FILE *File; // [sp+464h] [bp-4h]@1
+  unsigned int Argsa; // [sp+470h] [bp+8h]@3
+  int Argsb; // [sp+470h] [bp+8h]@15
+
+  v2 = this;
+  pAllocator->FreeChunk(this->pObjects);
+  v3 = 0;
+  v2->pObjects = 0;
+  v2->uNumObjects = 0;
+  v4 = fopen(Args, "r");
+  File = v4;
+  if ( !v4 )
+    Abortf("ObjectDescriptionList::load - Unable to open file: %s.");
+  v5 = 0;
+  Argsa = 0;
+  if ( fgets(&Buf, 490, v4) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v45, frame_table_txt_parser(&Buf, &v44), sizeof(v45));
+      if ( v45.field_0 && *v45.pProperties[0] != '/' )
+        ++Argsa;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v5 = Argsa;
+    v3 = 0;
+  }
+  v2->uNumObjects = v5;
+  v6 = pAllocator->AllocNamedChunk(v2->pObjects, 56 * v5, "Obj Descrip");
+  v2->pObjects = (ObjectDesc *)v6;
+  if ( v6 == (void *)v3 )
+    Abortf("ObjectDescriptionList::load - Out of Memory!");
+  memset(v6, v3, 56 * v2->uNumObjects);
+  v7 = File;
+  v2->uNumObjects = v3;
+  fseek(v7, v3, v3);
+  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v45, frame_table_txt_parser(&Buf, &v41), sizeof(v45));
+    if ( v45.field_0 && *v45.pProperties[0] != 47 )
+    {
+      strcpy(v2->pObjects[v2->uNumObjects].field_0, v45.pProperties[0]);
+      v9 = pSpriteFrameTable->FastFindSprite((char *)v45.pProperties[1]);
+      v10 = v45.pProperties[2];
+      v2->pObjects[v2->uNumObjects].uSpriteID = v9;
+      v11 = atoi(v10);
+      v12 = v45.pProperties[3];
+      v2->pObjects[v2->uNumObjects].uObjectID = v11;
+      v13 = atoi(v12);
+      v14 = v45.pProperties[4];
+      v2->pObjects[v2->uNumObjects].uRadius = v13;
+      v15 = atoi(v14);
+      v16 = v45.pProperties[5];
+      v2->pObjects[v2->uNumObjects].uHeight = v15;
+      v17 = atoi(v16);
+      v18 = v45.pProperties[6];
+      v2->pObjects[v2->uNumObjects].uLifetime = v17;
+      v19 = atoi(v18);
+      v20 = v45.pProperties[7];
+      v2->pObjects[v2->uNumObjects].uSpeed = v19;
+      strcpy(&Dest, v20);
+      memcpy(&v44, frame_table_txt_parser(&Dest, &v40), sizeof(v44));
+      if ( v45.field_0 > 7 )
+      {
+        for ( Argsb = 0; Argsb < v44.field_0; ++Argsb )
+        {
+          v21 = Argsb;
+          v22 = v44.pProperties[Argsb];
+          if ( !_strcmpi(v44.pProperties[Argsb], "NoDraw") )
+          {
+            v23 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)v23 |= 1u;
+          }
+          if ( !_strcmpi(v22, "Lifetime") )
+          {
+            v24 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)v24 |= 4u;
+          }
+          if ( !_strcmpi(v22, "FTLifetime") )
+          {
+            v25 = (int)&v2->pObjects[v2->uNumObjects];
+            *(short *)(v25 + 42) = 8 * pSpriteFrameTable->pSpriteSFrames[*(short *)(v25 + 40)].uAnimLength;
+            v26 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)v26 |= 8u;
+            v27 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)v27 |= 4u;
+          }
+          if ( !_strcmpi(v22, "NoPickup") )
+          {
+            v28 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)v28 |= 0x10u;
+          }
+          if ( !_strcmpi(v22, "NoGravity") )
+          {
+            v29 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)v29 |= 0x20u;
+          }
+          if ( !_strcmpi(v22, "FlagOnIntercept") )
+          {
+            v30 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)v30 |= 0x40u;
+          }
+          if ( !_strcmpi(v22, "Bounce") )
+          {
+            v31 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)v31 |= 0x80u;
+          }
+          v32 = v45.pProperties[v21];
+          if ( !_strcmpi(v45.pProperties[v21], "Fire") )
+            HIBYTE(v2->pObjects[v2->uNumObjects].uFlags) |= 2u;
+          if ( !_strcmpi(v32, "Lines") )
+            HIBYTE(v2->pObjects[v2->uNumObjects].uFlags) |= 4u;
+          if ( !_strcmpi(v44.pProperties[v21], "bits") )
+          {
+            v33 = v44.pProperties[v21 + 1];
+            v34 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
+            *(char *)(v34 + 1) |= 1u;
+            v35 = atoi(v33);
+            v36 = v44.pProperties[v21 + 2];
+            v2->pObjects[v2->uNumObjects].uParticleTrailColorR = v35;
+            v37 = atoi(v36);
+            v38 = v44.pProperties[v21 + 3];
+            v2->pObjects[v2->uNumObjects].uParticleTrailColorG = v37;
+            v2->pObjects[v2->uNumObjects].uParticleTrailColorB = atoi(v38);
+          }
+        }
+      }
+      ++v2->uNumObjects;
+    }
+  }
+  fclose(File);
+  return 1;
+}
+
+
+//----- (0045E03A) --------------------------------------------------------
+unsigned __int16 *__fastcall MakeScreenshot(signed int width, signed int height)
+{
+  signed int v2; // edi@1
+  unsigned __int16 *v3; // ebx@1
+  int v4; // edx@7
+  unsigned __int8 v5; // cf@9
+  unsigned int v6; // ecx@9
+  unsigned __int16 *v7; // edi@9
+  int j; // ecx@9
+  unsigned __int16 *v9; // edi@15
+  int v10; // ecx@15
+  LONG v11; // esi@15
+  signed __int64 v12; // qax@18
+  unsigned int v13; // ST10_4@21
+  HRESULT v14; // eax@21
+  int v15; // edi@29
+  signed __int64 v16; // qax@30
+  signed int v17; // edx@34
+  unsigned __int16 *v18; // edi@36
+  int k; // ecx@36
+  DDSURFACEDESC2 Dst; // [sp+4h] [bp-A0h]@6
+  unsigned __int16 *pPixels; // [sp+80h] [bp-24h]@1
+  float v23; // [sp+84h] [bp-20h]@1
+  unsigned __int16 *_this; // [sp+88h] [bp-1Ch]@21
+  float v25; // [sp+8Ch] [bp-18h]@1
+  unsigned int v26; // [sp+90h] [bp-14h]@17
+  int v27; // [sp+94h] [bp-10h]@1
+  int v28; // [sp+98h] [bp-Ch]@16
+  int i; // [sp+9Ch] [bp-8h]@15
+  int v30; // [sp+A0h] [bp-4h]@1
+
+  v30 = width;
+  v2 = height;
+  v27 = height;
+  v23 = 452.0 / (double)width;
+  v25 = 336.0 / (double)height;
+  pPixels = (unsigned __int16 *)malloc(2 * height * width);
+  v3 = pPixels;
+  if ( pRenderer->pRenderD3D )
+  {
+    pRenderer->BeginSceneD3D();
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    {
+      pIndoor->Draw();
+    }
+    else
+    {
+      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+        pOutdoor->Draw();
+    }
+    pRenderer->DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene();
+    memset(&Dst, 0, 0x7Cu);
+    Dst.dwSize = 124;
+    if ( pRenderer->LockSurface_DDraw4(pRenderer->pBackBuffer4, &Dst, 1u) )
+    {
+      v9 = (unsigned __int16 *)Dst.lpSurface;
+      v10 = 0;
+      v11 = Dst.lPitch >> 1;
+      for ( i = 0; i < v27; ++i )
+      {
+        v28 = v10;
+        if ( v30 > v10 )
+        {
+          v26 = v11 * (unsigned __int64)(signed __int64)((double)i * v25 + 8.0);
+          do
+          {
+            v12 = (signed __int64)((double)v28++ * v23 + 8.0);
+            *v3 = v9[v26 + (int)v12];
+            ++v3;
+          }
+          while ( v28 < v30 );
+          v10 = 0;
+        }
+      }
+      v13 = v10;
+      ErrD3D(pRenderer->pBackBuffer4->Unlock(0));
+    }
+    else
+    {
+      v4 = v27;
+      if ( v27 > 0 )
+      {
+        do
+        {
+          if ( v30 > 0 )
+          {
+            v5 = v30 & 1;
+            v6 = (unsigned int)v30 >> 1;
+            memset(v3, 0, 4 * ((unsigned int)v30 >> 1));
+            v7 = &v3[2 * v6];
+            for ( j = v5; j; --j )
+            {
+              *v7 = 0;
+              ++v7;
+            }
+            v3 += v30;
+          }
+          --v4;
+        }
+        while ( v4 );
+      }
+    }
+  }
+  else
+  {
+    pRenderer->BeginScene();
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    {
+      pIndoor->Draw();
+    }
+    else
+    {
+      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+        pOutdoor->Draw();
+    }
+    _this = pRenderer->pTargetSurface;
+    v26 = pRenderer->uTargetSurfacePitch;
+    if ( pRenderer->pTargetSurface )
+    {
+      i = 0;
+      if ( v2 > 0 )
+      {
+        do
+        {
+          v28 = 0;
+          if ( v30 > 0 )
+          {
+            v15 = v26 * (unsigned __int64)(signed __int64)((double)i * v25 + 8.0);
+            do
+            {
+              v16 = (signed __int64)((double)v28++ * v23 + 8.0);
+              *v3 = _this[v15 + (int)v16];
+              ++v3;
+            }
+            while ( v28 < v30 );
+          }
+          ++i;
+        }
+        while ( i < v27 );
+      }
+    }
+    else
+    {
+      if ( v2 > 0 )
+      {
+        v17 = v2;
+        do
+        {
+          if ( v30 > 0 )
+          {
+            memset(v3, 0, 4 * ((unsigned int)v30 >> 1));
+            v18 = &v3[2 * ((unsigned int)v30 >> 1)];
+            for ( k = v30 & 1; k; --k )
+            {
+              *v18 = 0;
+              ++v18;
+            }
+            v3 += v30;
+          }
+          --v17;
+        }
+        while ( v17 );
+      }
+    }
+    pRenderer->EndScene();
+  }
+  return pPixels;
+}
+
+//----- (0045E26C) --------------------------------------------------------
+void __thiscall SaveScreenshot(const char *pFilename)
+{
+  const char *v1; // edi@1
+  unsigned __int16 *v2; // esi@1
+
+  v1 = pFilename;
+  v2 = MakeScreenshot(92, 68);
+  pRenderer->SavePCXImage(v1, (char *)v2, 92, 68);
+  free(v2);
+}
+
+
+
+
+//----- (004601B7) --------------------------------------------------------
+void GameUI_MainMenu_DoDrawLoad(int a1)
+{
+  unsigned __int16 v1; // bx@1
+  unsigned int v2; // edi@4
+  unsigned int v3; // eax@4
+  unsigned int v4; // eax@8
+  int v5; // edi@8
+  unsigned int v6; // eax@8
+  unsigned int pMapID; // eax@10
+  signed __int64 v8; // qax@10
+  unsigned int v9; // ebx@10
+  unsigned __int64 v10; // qax@10
+  __int64 v11; // qax@10
+  char v12; // di@10
+  unsigned __int64 v13; // qtt@10
+  unsigned int v14; // ecx@10
+  __int64 pOurHour; // qax@10
+  int v16; // edi@10
+  signed int pHour; // ebx@22
+  //const char *v18; // ST14_4@32
+  int v19; // eax@32
+  const char *v20; // ST18_4@32
+  int v21; // eax@32
+  //const char *v22; // ST14_4@32
+  int v23; // eax@32
+  const char *pSlotName; // edi@36
+  int v25; // eax@43
+  GUIWindow pWindow; // [sp+Ch] [bp-78h]@8
+  /*unsigned int Dst; // [sp+Ch] [bp-78h]@8
+  unsigned int v27; // [sp+10h] [bp-74h]@8
+  int v28; // [sp+14h] [bp-70h]@8
+  int v29; // [sp+18h] [bp-6Ch]@8
+  unsigned int v30; // [sp+1Ch] [bp-68h]@8
+  unsigned int v31; // [sp+20h] [bp-64h]@8*/
+  int pMinutes; // [sp+60h] [bp-24h]@10
+  int pMonthNum; // [sp+68h] [bp-1Ch]@10
+  unsigned int pSaveFiles; // [sp+70h] [bp-14h]@10
+  __int64 pAMPM2; // [sp+74h] [bp-10h]@10
+  int pYear; // [sp+7Ch] [bp-8h]@10
+  int a4; // [sp+80h] [bp-4h]@1
+  int pFilesID;
+
+  v1 = 255;
+  a4 = a1;
+  GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFF, 0xFF, 0xFF);
+  GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFF, 0xFF, 0x9B);
+  pRenderer->BeginScene();
+  if ( GetCurrentMenuID() != MENU_SAVELOAD && GetCurrentMenuID() != MENU_LOAD )
+  {
+    pRenderer->DrawTextureIndexed(8, 8, uTextureID_loadsave != -1 ? &pIcons_LOD->pTextures[uTextureID_loadsave] : 0);
+    if ( a4 )
+    {
+      v2 = uTextureID_save_up;
+      v3 = uTextureID_LS_saveU;
+    }
+    else
+    {
+      v2 = uTextureID_load_up;
+      v3 = uTextureID_LS_loadU;
+    }
+    pRenderer->DrawTextureIndexed(241, 302, (Texture *)(v3 != -1 ? &pIcons_LOD->pTextures[v3] : 0));
+    pRenderer->DrawTextureIndexed(18, 139, (Texture *)(v2 != -1 ? &pIcons_LOD->pTextures[v2] : 0));
+    pRenderer->DrawTextureIndexed(351, 302, (Texture *)(uTextureID_x_u != -1 ? &pIcons_LOD->pTextures[uTextureID_x_u] : 0));
+    v1 = 255;
+  }
+  if ( pSavegameUsedSlots[uLoadGameUI_SelectedSlot] )
+  {
+    memset(&pWindow, 0, 0x54);
+    pWindow.uFrameX = pGUIWindow_CurrentMenu->uFrameX + 240;
+    v4 = pGUIWindow_CurrentMenu->uFrameY - pFontSmallnum->uFontHeight;
+    pWindow.uFrameWidth = 220;
+    v4 += 157;
+    pWindow.uFrameY = v4;
+    v5 = pFontSmallnum->uFontHeight;
+    pWindow.uFrameZ = pWindow.uFrameX + 219;
+    pWindow.uFrameHeight = v5;
+    pWindow.uFrameW = v5 + v4 - 1;
+    v6 = uLoadGameUI_SelectedSlot;
+    if (pSavegameThumbnails[uLoadGameUI_SelectedSlot].pPixels)
+    {
+      pRenderer->DrawTextureRGB(pGUIWindow_CurrentMenu->uFrameX + 276, pGUIWindow_CurrentMenu->uFrameY + 171, pSavegameThumbnails + uLoadGameUI_SelectedSlot);
+      v6 = uLoadGameUI_SelectedSlot;
+    }
+    pMapID = pMapStats->GetMapInfo(pSavegameHeader[v6].pLocationName);
+    pWindow.DrawTitleText(pFontSmallnum, 0, 0, 0, pMapStats->pInfos[pMapID].pName, 3);
+    v8 = (signed __int64)(pSavegameHeader[uLoadGameUI_SelectedSlot].uWordTime * 0.234375) / 60;
+    pMinutes = (int)((signed __int64)(pSavegameHeader[uLoadGameUI_SelectedSlot].uWordTime * 0.234375) / 60) >> 32;
+    v9 = v8;
+    v8 /= 60i64;
+    pAMPM2 = v8;
+    v10 = (unsigned int)v8 / 24;
+    pSaveFiles = v10;
+    v11 = (unsigned int)(v10 / 7);
+    v12 = v11;
+    LODWORD(v13) = (unsigned int)v11 >> 2;
+    HIDWORD(v13) = HIDWORD(v11);
+    pMonthNum = v13 % 12;
+    pYear = v13 / 12;
+    pMinutes = (int)__PAIR__(pMinutes, v9) % 60;
+    pOurHour = pAMPM2 % 24;
+    v14 = (unsigned __int64)(pAMPM2 % 24) >> 32;
+    LODWORD(pAMPM2) = pAMPM2 % 24;
+    HIDWORD(pOurHour) = pSaveFiles % 28;
+    pYear += 1168;//ãîä íà÷àëà
+    v16 = v12 & 3;
+    pWindow.uFrameY = pGUIWindow_CurrentMenu->uFrameY + 261;
+    HIDWORD(pAMPM2) = v14 == 0 && ((signed int)v14 > 0 || (unsigned int)pOurHour >= 12)
+                && (signed int)v14 <= 0 && (v14 != 0 || (unsigned int)pOurHour < 24);
+    if ( v14  != 0 || (signed int)v14 <= 0 && (unsigned int)pOurHour <= 12 )
+    {
+      if ( !(v14 | (unsigned int)pOurHour) )
+      {
+        pSaveFiles = 0;
+        pHour = 12;
+        goto LABEL_23;
+      }
+    }
+    else
+    {
+      v14 = (__PAIR__(v14, (unsigned int)pOurHour) - 12) >> 32;
+      LODWORD(pOurHour) = pOurHour - 12;
+    }
+    pHour = pOurHour;
+    pSaveFiles = v14;
+LABEL_23:
+    auto day = aDayNames[HIDWORD(pOurHour) % 7];
+    auto ampm = aAMPMNames[HIDWORD(pAMPM2)];
+    auto month = aMonthNames[pMonthNum];
+    //sprintf(pTmpBuf, "%s %d:%02d%s\n%d %s %d", _d, v17, (int)32, _a, 3, _m, pFilesID);
+    sprintf(pTmpBuf, "%s %d:%02d%s\n%d %s %d", day, pHour, pMinutes, ampm, 7 * v16 + HIDWORD(pOurHour) % 7 + 1, month, pYear);
+    pWindow.DrawTitleText(pFontSmallnum, 0, 0, 0, pTmpBuf, 3u);
+    v1 = 255;
+  }
+  if ( pGUIWindow_CurrentMenu->field_40 == 2 )
+  {
+    pGUIWindow_CurrentMenu->field_40 = 0;
+    strcpy((char *)&pSavegameHeader + 100 * uLoadGameUI_SelectedSlot, (const char *)pKeyActionMap->pPressedKeysBuffer);
+    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)83;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+      *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+  }
+  else
+  {
+    if ( pGUIWindow_CurrentMenu->field_40 == 3 )
+      pGUIWindow_CurrentMenu->field_40 = 0;
+  }
+  if (GetCurrentMenuID() == MENU_LOAD)
+  {
+    //v18 = pGlobalTXT_LocalizationStrings[135];
+    v19 = pFontSmallnum->AlignText_Center(0xBA, pGlobalTXT_LocalizationStrings[135]);//"Çàãðóçêà"
+    pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, v19 + 25, 220, 0, pGlobalTXT_LocalizationStrings[135], 0, 0, 0);
+    v20 = (const char *)(pSavegameHeader + uLoadGameUI_SelectedSlot);
+    v21 = pFontSmallnum->AlignText_Center(0xBA, (const char *)pSavegameHeader + 100 * uLoadGameUI_SelectedSlot);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontSmallnum, v21 + 25, 0x106, 0, v20, 185, 0);
+    //v22 = pGlobalTXT_LocalizationStrings[165];
+    v23 = pFontSmallnum->AlignText_Center(0xBA, pGlobalTXT_LocalizationStrings[165]);//"Ïîæàëóéñòà, ïîæîæäèòå"
+    pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, v23 + 25, 304, 0, pGlobalTXT_LocalizationStrings[165], 0, 0, 0);
+  }
+  else
+  {
+    if ( a4 )
+      pSaveFiles = 40;
+    else
+      pSaveFiles = uNumSavegameFiles;
+    a4 = 199;
+    pFilesID = dword_6A0C9C;
+    pSlotName = (const char *)(&pSavegameHeader[dword_6A0C9C]);//draw name for save slot
+    do
+    {
+      if ( pFilesID >= (signed int)pSaveFiles )
+        break;
+      short clr;
+      HIDWORD(pAMPM2) = clr = (pFilesID == uLoadGameUI_SelectedSlot ? GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v1, v1, 0x64) : 0);
+      if ( pGUIWindow_CurrentMenu->field_40 != 1 || pFilesID != uLoadGameUI_SelectedSlot )
+      {
+        pGUIWindow_CurrentMenu->DrawTextInRect(pFontSmallnum, 0x1B, a4, clr, pSlotName, 185, 0);
+      }
+      else
+      {
+        v25 = pGUIWindow_CurrentMenu->DrawTextInRect(pFontSmallnum, 0x1B, a4, clr, (const char *)pKeyActionMap->pPressedKeysBuffer, 175, 1);
+        pGUIWindow_CurrentMenu->DrawFlashingInputCursor(v25 + 27, a4, pFontSmallnum);
+      }
+      a4 += 21;
+      ++pFilesID;
+      pSlotName += 100;
+    }
+    while ( a4 < 346 );
+  }
+  pRenderer->EndScene();
+}
+// 6A0C9C: using guessed type int dword_6A0C9C;
+
+//----- (004606F7) --------------------------------------------------------
+void __cdecl GameUI_MainMenu_DrawLoad()
+{
+  GameUI_MainMenu_DoDrawLoad(0);
+}
+
+//----- (004606FE) --------------------------------------------------------
+void __cdecl sub_4606FE()
+{
+  GameUI_MainMenu_DoDrawLoad(1);
+}
+
+//----- (00460706) --------------------------------------------------------
+void TryLoadLevelFromLOD()
+{
+  FILE *v0; // eax@1
+  FILE *v1; // esi@1
+  __int32 v2; // edi@2
+  char Ext[256]; // [sp+4h] [bp-40Ch]@1
+  char Dir[256]; // [sp+104h] [bp-30Ch]@1
+  char Filename[256]; // [sp+204h] [bp-20Ch]@1
+  char a1[260]; // [sp+304h] [bp-10Ch]@1
+  char Drive[4]; // [sp+408h] [bp-8h]@1
+  int DstBuf; // [sp+40Ch] [bp-4h]@2
+
+  strcpy(a1, pCurrentMapName);
+  _splitpath(a1, Drive, Dir, Filename, Ext);
+  sprintf(a1, "levels\\%s%s", Filename, ".lod");
+  v0 = fopen(a1, "rb");
+  v1 = v0;
+  if ( v0 )
+  {
+    fseek(v0, 0, 2);
+    v2 = ftell(v1);
+    rewind(v1);
+    ptr_6A0D08 = pAllocator->AllocNamedChunk(ptr_6A0D08, v2, "LevelLod");
+    fread(ptr_6A0D08, v2, 1u, v1);
+    fseek(v1, v2 - 6, 0);
+    DstBuf = 0;
+    fread(&DstBuf, 4u, 1u, v1);
+    fread(&_6A0D10_txt_lod_loading__unused, 2u, 1u, v1);
+    _6A0D0C_txt_lod_loading = (int)((char *)ptr_6A0D08 + DstBuf);
+    fclose(v1);
+  }
+}
+
+//----- (0046080D) --------------------------------------------------------
+void __cdecl sub_46080D()
+{
+  pAllocator->FreeChunk(ptr_6A0D08);
+  ptr_6A0D08 = 0;
+  _6A0D0C_txt_lod_loading = 0;
+}
+
+//----- (0046082C) --------------------------------------------------------
+bool Initialize_GamesLOD_NewLOD()
+{
+  pGames_LOD = new LODWriteableFile;
+  pGames_LOD->AllocSubIndicesAndIO(300, 0);
+  if (pGames_LOD->LoadFile("data\\games.lod", 1))
+  {
+    pNew_LOD = new LODWriteableFile;
+    pNew_LOD->AllocSubIndicesAndIO(300, 0x186A0u);
+    return true;
+  }
+  return false;
+}
+
+
+
+
+
+//----- (0046086A) --------------------------------------------------------
+bool Autosave()
+{
+  int flag; // esi@3
+  FILE *v3; // eax@7
+  LOD::FileHeader this_; // [sp+Ch] [bp-16Ch]@3
+  LOD::Directory pDir; // [sp+10Ch] [bp-6Ch]@4
+  LOD::Directory v7; // [sp+12Ch] [bp-4Ch]@9
+  LOD::Directory a3; // [sp+14Ch] [bp-2Ch]@3
+  void *pSave; // [sp+170h] [bp-8h]@3
+
+  if ( pVideoPlayer->AnyMovieLoaded() )
+    pVideoPlayer->Unload();
+  flag = 0;
+  pSave = pAllocator->AllocNamedChunk(0, 0xF4240, 0);
+  pNew_LOD->CloseWriteFile();
+  remove("data\\new.lod");
+  this_.Reset();
+  strcpy(this_.LodVersion, "MMVII");
+  strcpy(this_.LodDescription, "newmaps for MMVII");
+  this_.LODSize = 100;
+  this_.dword_0000A8 = 0;
+  a3.dword_000018 = 0;
+  a3.word_00001E = 0;
+  strcpy(a3.pFilename, "current");
+  pNew_LOD->_461492(&this_, &a3, "data\\new.lod");
+  if ( pNew_LOD->LoadFile("data\\new.lod", 0) )
+  {
+    pNew_LOD->CreateTempFile();
+    pNew_LOD->uNumSubIndices = 0;
+    pDir.Reset();
+
+    for (int i = pGames_LOD->uNumSubIndices / 2; i < pGames_LOD->uNumSubIndices; ++i)
+    {
+      memcpy(&pDir, &pGames_LOD->pSubIndices[i], sizeof(pDir));
+      v3 = pGames_LOD->FindContainer(pGames_LOD->pSubIndices[i].pFilename, 1);
+      fread(pSave, pGames_LOD->pSubIndices[i].uDataSize, 1, v3);
+      pNew_LOD->AppendDirectory(&pDir, pSave);
+    }
+    v7.Reset();
+    strcpy(pSavegameHeader->pLocationName, "out01.odm");
+    strcpy(v7.pFilename, "header.bin");
+    v7.uDataSize = 100;
+    pNew_LOD->AppendDirectory(&v7, &pSavegameHeader);
+    pNew_LOD->Save();
+    pParty->vPrevPosition.y = 0;
+    pParty->vPrevPosition.x = 12552;
+    pParty->vPosition.x = 12552;
+    pParty->vPosition.z = 0;
+    pParty->uFallStartY = 0;
+    pParty->sPrevRotationX = 0;
+    pParty->sRotationX = 0;
+    pParty->vPrevPosition.z = 1816;
+    pParty->vPosition.y = 1816;
+    flag = 1;
+    pParty->sPrevRotationY = 512;
+    pParty->sRotationY = 512;
+    SaveGame(1, (__int16 *)1);
+  }
+  pAllocator->FreeChunk(pSave);
+  return flag;
+}
+
+
+//----- (004610AA) --------------------------------------------------------
+void __fastcall PrepareToLoadODM(unsigned int bLoading, OutdoorCamera *a2)
+{
+  unsigned int v2; // edi@1
+  OutdoorCamera *v3; // esi@1
+
+  v2 = bLoading;
+  v3 = a2;
+  pGameLoadingUI_ProgressBar->Reset(0x1Bu);
+  pSoundList->_4A9D79(0);
+  uCurrentlyLoadedLevelType = (LEVEL_TYPE)2;
+  ODM_LoadAndInitialize(pCurrentMapName, v3);
+  if ( !v2 )
+    TeleportToStartingPoint(uLevel_StartingPointType);
+  viewparams->_443365();
+  PlayLevelMusic();
+}
+// 6BE35C: using guessed type int uLevel_StartingPointType;
+
+//----- (00461103) --------------------------------------------------------
+void __cdecl sub_461103()
+{
+  //GUIProgressBar *v0; // ebx@1
+  //signed int v1; // ebp@1
+  //char *v2; // esi@2
+  __int16 v3; // cx@3
+  int v4; // edx@8
+  //size_t v5; // edi@14
+  signed int v6; // esi@14
+  //char *v7; // edx@15
+  signed int v8; // ecx@16
+  int v9; // ecx@23
+  MonsterInfo *v10; // ebx@23
+  //int *v11; // esi@23
+  int v12; // esi@25
+  int v13; // eax@26
+  __int16 v14; // ax@41
+  //signed int v15; // [sp+10h] [bp-4Ch]@1
+  //signed int v16; // [sp+10h] [bp-4Ch]@14
+  signed int v17; // [sp+14h] [bp-48h]@3
+  signed int v18; // [sp+14h] [bp-48h]@23
+  int v19; // [sp+18h] [bp-44h]@1
+  signed int v20; // [sp+18h] [bp-44h]@14
+  int v21[16]; // [sp+1Ch] [bp-40h]@17
+
+  sub_450218_prolly_generate_chests_loot();
+  //v0 = pGameLoadingUI_ProgressBar;
+  pGameLoadingUI_ProgressBar->Progress();
+  pParty->uFlags |= 2u;
+  pParty->field_7B5_in_arena_quest = 0;
+  //v1 = 0;
+  dword_5C6DF8 = 1;
+  pNPCStats->field_17FC0 = 0;
+  v19 = pMapStats->GetMapInfo(pCurrentMapName);
+
+  //v15 = 0;
+  for (uint i = 0; i < uNumActors; ++i)
+  //if ( (signed int)uNumActors > 0 )
+  {
+    auto pActor = pActors + i;
+    //v2 = (char *)&pActors[0].uNPC_ID;
+    //do
+    //{
+      v3 = pActor->pMonsterInfo.uID;
+      v17 = 0;
+      if ( v3 >= 115 && v3 <= 186 || v3 >= 232 && v3 <= 249 )
+        v17 = 1;
+      //v1 = 0;
+      v4 = (v3 - 1) % 3;
+      if ( 2 == v4 )
+      {
+        if ( pActor->uNPC_ID && pActor->uNPC_ID < 5000 )
+          continue;
+      }
+      else
+      {
+        if ( v4 != 1 )
+        {
+          if ( v4 != 0 || pActor->uNPC_ID )
+            continue;
+          goto LABEL_12;
+        }
+      }
+      if ( pActor->uNPC_ID > 0 && pActor->uNPC_ID < 5000 )
+        continue;
+      if ( v17 )
+      {
+        pNPCStats->InitializeAdditionalNPCs(&pNPCStats->array_13EF4[pNPCStats->field_17FC0], v3, 0, v19);
+        v14 = LOWORD(pNPCStats->field_17FC0) + 5000;
+        ++pNPCStats->field_17FC0;
+        pActor->uNPC_ID = v14;
+        continue;
+      }
+LABEL_12:
+      pActor->uNPC_ID = 0;
+//LABEL_13:
+      //++v15;
+      //v2 += 836;
+    //}
+    //while ( v15 < (signed int)uNumActors );
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  //v5 = uNumActors;
+  v6 = 0;
+  v20 = 0;
+  //v16 = v1;
+
+  for (uint i = 0; i < uNumActors; ++i)
+  {
+    auto pActor = pActors + i;
+    //v7 = (char *)&pActors[0].pMonsterInfo;
+    //do
+    //{
+      v8 = 0;
+      if ( v6 > 0 )
+      {
+        do
+        {
+          if ( v21[v8] == pActor->pMonsterInfo.uID - 1 )
+            break;
+          ++v8;
+        }
+        while ( v8 < v6 );
+      }
+
+      if ( v8 == v6 )
+      {
+        v21[v6++] = pActor->pMonsterInfo.uID - 1;
+        v20 = v6;
+        if ( v6 == 16 )
+          break;
+      }
+      //++v16;
+      //v7 += 836;
+    //}
+    //while ( v16 < (signed int)v5 );
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  if ( v6 > 0 )
+  {
+    int _v0 = 0;
+    do
+    {
+      v9 = v21[_v0];
+      v18 = 4;
+      v10 = &pMonsterStats->pInfos[v9 + 1];
+      //v11 = (int *)pMonsterList->pMonsters[v9].pSoundSampleIDs;
+      auto v11 = &pMonsterList->pMonsters[v9];
+      do
+      {
+        pSoundList->LoadSound(v11->pSoundSampleIDs[4 - v18], 0);
+        //v11 = (int *)((char *)v11 + 2);
+        --v18;
+      }
+      while ( v18 );
+      v12 = 0;
+      do
+        v13 = pSoundList->LoadSound(v12++ + word_4EE088_sound_ids[v10->uSpell1ID], 1);
+      while ( v13 );
+      ++_v0;
+    }
+    while ( _v0 < v6 );
+    //v0 = pGameLoadingUI_ProgressBar;
+    //v1 = 0;
+  }
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  if ( dword_6BE368_debug_settings_2 & 4 )
+    uNumActors = 0;
+  if ( dword_6BE368_debug_settings_2 & 8 )
+    uNumLevelDecorations = 0;
+  sub_4613C4();
+
+  pGameLoadingUI_ProgressBar->Progress();
+
+  pIndoorCamera->pos.y = 0;
+  pIndoorCamera->pos.x = 0;
+  pIndoorCamera->pos.z = 100;
+  pIndoorCamera->sRotationY = 0;
+  pIndoorCamera->sRotationX = 0;
+  viewparams->bRedrawGameUI = 1;
+  uLevel_StartingPointType = 0;
+  pSprites_LOD->_461397();
+  pPaletteManager->LockTestAll();
+  if ( pParty->pPickedItem.uItemID != 0 )
+    pMouse->SetCursorBitmapFromItemID(pParty->pPickedItem.uItemID);
+}
+
+
+
+//----- (004613C4) --------------------------------------------------------
+int __cdecl sub_4613C4()
+{
+  unsigned __int16 v0; // ax@1
+  size_t v1; // ecx@1
+  int v2; // esi@1
+  int result; // eax@1
+  LevelDecoration *v4; // edx@2
+  int v5; // edi@4
+
+  _6836C8_num_decorations_6807E8 = 0;
+  v0 = pDecorationList->GetDecorIdByName("Event Trigger");
+  v1 = uNumLevelDecorations;
+  v2 = (signed __int16)v0;
+  result = 0;
+  if ( (signed int)uNumLevelDecorations > 0 )
+  {
+    v4 = pLevelDecorations;
+    do
+    {
+      if ( v4->uDecorationDescID == v2 )
+      {
+        v5 = _6836C8_num_decorations_6807E8++;
+        _6807E8_level_decorations_ids[v5] = result;
+      }
+      ++result;
+      ++v4;
+    }
+    while ( result < (signed int)v1 );
+  }
+  return result;
+}
+// 6836C8: using guessed type int 6836C8_num_decorations_6807E8;
+
+
+
+
+
+
+
+
+
+
+
+
+
+//----- (004621DA) --------------------------------------------------------
+int __fastcall sub_4621DA(signed int a1, signed int a2, signed int a3)
+{
+  signed int v3; // eax@2
+  signed int v4; // eax@3
+  signed int v5; // esi@4
+  signed int v6; // esi@6
+
+  if ( a1 < a2 )
+  {
+    v3 = a1;
+    a1 = a2;
+    a2 = v3;
+  }
+  v4 = a3;
+  if ( a1 < a3 )
+  {
+    v5 = a1;
+    a1 = a3;
+    v4 = v5;
+  }
+  if ( a2 < v4 )
+  {
+    v6 = a2;
+    a2 = v4;
+    v4 = v6;
+  }
+  return (11 * a2 >> 5) + a1 + (v4 >> 2);
+}
+
+
+
+
+
+
+OPENFILENAMEA ofn;
+//----- (0046271C) --------------------------------------------------------
+void __cdecl crt_init_globals_46271C()
+{
+  ofn.lStructSize = 0x4Cu;
+  ofn.hwndOwner = hWnd;
+  ofn.hInstance = 0;
+  ofn.lpstrFilter = "Indoor  BLV Files (*.blv)";
+  ofn.lpstrCustomFilter = 0;
+  ofn.nMaxCustFilter = 0;
+  ofn.nFilterIndex = 0;
+  ofn.lpstrFile = 0;
+  ofn.nMaxFile = 260;
+  ofn.nMaxFileTitle = 512;
+  ofn.lpstrInitialDir = "levels";
+  ofn.lpstrTitle = "Might and Magic® VII - Load Which Level?";
+  ofn.Flags = 4;
+  ofn.nFileOffset = 0;
+  ofn.nFileExtension = 0;
+  ofn.lpstrDefExt = "blv";
+  ofn.lCustData = 0;
+  ofn.lpfnHook = 0;
+  ofn.lpTemplateName = 0;
+  ofn.lpstrFileTitle = pTmpBuf;
+}
+
+//----- (004627B7) --------------------------------------------------------
+void __cdecl MainMenu_Loop()
+{
+  GUIButton *pButton; // eax@27
+  unsigned int pControlParam; // ecx@35
+  int v10; // ecx@36
+  int v11; // ecx@37
+  unsigned int pY; // [sp-18h] [bp-54h]@39
+  Texture *pTexture; // [sp-14h] [bp-50h]@39
+  GUIButton *pButton2; // [sp+0h] [bp-3Ch]@27
+  GUIWindow *pWindow; // [sp+4h] [bp-38h]@11
+  
+  pCurrentScreen = 0; // îêíî Ãëàâíîå ìåíþ
+  if (pAsyncMouse)
+    pAsyncMouse->Resume();
+  if ( LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) && pAsyncKeyboard )
+    pAsyncKeyboard->Resume();
+  pGUIWindow2 = 0;
+  pAudioPlayer->StopChannels(-1, -1);
+  pMouse->RemoveHoldingItem();
+  ++pIcons_LOD->uTexturePacksCount;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  pWindow_MainMenu = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0); // ñîçäàíèå îêíà
+  auto pNew = pIcons_LOD->LoadTexturePtr("title_new", TEXTURE_16BIT_PALETTE); // ñîçäàíèå êíîïîê
+  pMainMenu_BtnNew = pWindow_MainMenu->CreateButton(495, 172, pNew->uTextureWidth, pNew->uTextureHeight, 1, 0, 
+                                                    UIMSG_MainMenu_ShowPartyCreationWnd, 0, 78, "", pNew, 0);
+  auto pLoad = pIcons_LOD->LoadTexturePtr("title_load", TEXTURE_16BIT_PALETTE);
+  pMainMenu_BtnLoad = pWindow_MainMenu->CreateButton(495, 227, pLoad->uTextureWidth, pLoad->uTextureHeight, 1, 0, 
+                                                     UIMSG_MainMenu_ShowLoadWindow, 1, 76, "", pLoad, 0);
+  auto pCredits = pIcons_LOD->LoadTexturePtr("title_cred", TEXTURE_16BIT_PALETTE);
+  pMainMenu_BtnCredits = pWindow_MainMenu->CreateButton(495, 282, pCredits->uTextureWidth, pCredits->uTextureHeight, 1, 0, 
+                                                         UIMSG_ShowCredits, 2, 67, "", pCredits, 0);
+  auto pExit = pIcons_LOD->LoadTexturePtr("title_exit", TEXTURE_16BIT_PALETTE);
+  pMainMenu_BtnExit = pWindow_MainMenu->CreateButton(495, 337, pExit->uTextureWidth, pExit->uTextureHeight, 1, 0, 
+                                                        UIMSG_ExitToWindows, 3, 0, "", pExit, 0);
+  pTexture_PCX.Release();
+  pTexture_PCX.Load("title.pcx", 0);
+  SetCurrentMenuID(MENU_MAIN);
+  SetForegroundWindow(hWnd);
+  SendMessageW(hWnd, WM_ACTIVATEAPP, 1, 0);
+  while (GetCurrentMenuID() == MENU_MAIN || GetCurrentMenuID() == MENU_SAVELOAD)
+  {
+    POINT pt;
+    pMouse->GetCursorPos(&pt);
+    pWindow = pWindow_MainMenu;
+    if ( GetCurrentMenuID() == MENU_SAVELOAD)//åñëè ìåíþ çàãðóçêè
+    {
+      if ( pCurrentScreen != 12 )//åñëè íå îêíî çàãðóçêè èãðû
+      {
+        pTexture_PCX.Release();
+        pTexture_PCX.Load("lsave640.pcx", 0);
+        pGUIWindow2 = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0);
+        pCurrentScreen = 12; //îêíî çàãðóçêè èãðû
+        GameUI_DrawLoadMenu(0);//ïðîöåññ ïðîðèñîâêè îêíà Çàãðóçêà
+      }
+      pWindow = pGUIWindow_CurrentMenu;
+    }
+
+    MSG msg;
+    while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) )//îæèäàíèå ñîîáùåíèÿ èç âíåøíåãî èñòî÷íèêà
+    {
+      if (msg.message == WM_QUIT)
+        Game_DeinitializeAndTerminate(0);
+      TranslateMessage(&msg);
+      DispatchMessageA(&msg);
+    }
+    if (dword_6BE364_game_settings_1 & 0x0100)
+    {
+      WaitMessage();
+    }
+    else
+    {
+      pRenderer->BeginScene();
+      pRenderer->DrawTextureRGB(0, 0, &pTexture_PCX);
+      if (pAsyncMouse)
+        pAsyncMouse->_46B736_consume_click_lists(1);
+      GUI_MainMenuMessageProc();//ïðîöåäóðà ïðîâåðêè ñîîáùåíèé ïîñòóïàþùèõ èç âíåøíèõ óñòðîéñòâ äëÿ âñåé ãðóïïû âñòóïèòåëüíûõ îêîí
+      GUI_UpdateWindows();
+      if (pAsyncMouse)
+        pAsyncMouse->_46B736_consume_click_lists(1);
+      if (GetCurrentMenuID() != MENU_MAIN)// åñëè íå Ãëàâíîå ìåíþ
+      {
+        if (GetCurrentMenuID() == MENU_LOAD)// åñëè ìåíþ Çàãðóçêà
+        {
+          pIcons_LOD->_4114F2();
+          pGUIWindow_CurrentMenu->Release();
+          pGUIWindow_CurrentMenu = 0;
+          pCurrentScreen = 0;
+          viewparams->bRedrawGameUI = 1;
+        }
+      }
+      else
+      {
+        if ( !ptr_507BDC )// ???
+        {
+          pButton = pWindow->pControlsHead;
+          for ( pButton = pWindow->pControlsHead; pButton; pButton = pButton->pNext )
+          {
+           if ( pt.x >= (signed int)pButton->uX && pt.x <= (signed int)pButton->uZ
+                && pt.y >= (signed int)pButton->uY && pt.y <= (signed int)pButton->uW
+                && pWindow == pWindow_MainMenu )
+           {
+            pControlParam = pButton->uControlParam;
+            switch (pControlParam) // ïîäñâåòêà êíîïîê
+            {
+              case 0:
+              pTexture = pNew;
+              pY = 172;
+              break;
+              case 1:
+              pTexture = pLoad;
+              pY = 227;
+              break;
+              case 2:
+              pTexture = pCredits;
+              pY = 282;
+              break;
+              case 3:
+              pTexture = pExit;
+              pY = 337;
+              break;
+            }
+            pRenderer->DrawTextureIndexed(495, pY, pTexture); //ïîäñâåòêà êíîïîê
+           }
+          }
+        }
+      }
+      pRenderer->EndScene();
+      pRenderer->Present();
+    }
+  }
+  /*GUI_MainMenuMessageProc(); //Ritor1: unknow
+  pRenderer->BeginScene();
+  GUI_UpdateWindows();
+  pRenderer->EndScene();
+  pRenderer->Present();
+  pTexture_PCX.Release();*/
+  if ( pGUIWindow2 )
+  {
+    pGUIWindow2->Release();
+    pGUIWindow2 = 0;
+  }
+  pWindow_MainMenu->Release();
+  pIcons_LOD->_4114F2();
+}
+
+
+
+
+//----- (004637EB) --------------------------------------------------------
+int __stdcall aWinProc(HWND hWnd, UINT Msg, WPARAM wParam, unsigned int lParam)
+{
+  unsigned int v4; // esi@1
+  Render *v5; // ecx@14
+  HANDLE v6; // eax@32
+  Keyboard *v7; // eax@33
+  //HDC v9; // edi@41
+  HDC v10; // edi@50
+  int v11; // esi@50
+  char v12; // zf@132
+  signed int v13; // eax@135
+  int v14; // eax@139
+  int v15; // eax@140
+  int v16; // eax@141
+  int v17; // eax@142
+  int v18; // eax@150
+  int v19; // eax@151
+  int v20; // eax@152
+  int v21; // eax@161
+  int v22; // eax@162
+  int v23; // eax@163
+  int v24; // eax@170
+  int v25; // eax@171
+  int v26; // eax@172
+  char v27; // al@174
+  bool v28; // ebx@201
+  char v29; // dl@209
+  char v30; // cl@210
+  bool v31; // ebx@211
+  void *v32; // ebx@214
+  float v33; // ST04_4@246
+  float v34; // ST04_4@254
+  HWND v35; // [sp+8h] [bp-64h]@103
+  UINT v36; // [sp+Ch] [bp-60h]@103
+  WPARAM v37; // [sp+10h] [bp-5Ch]@103
+  LPARAM v38; // [sp+14h] [bp-58h]@103
+  struct tagPAINTSTRUCT Paint; // [sp+24h] [bp-48h]@13
+  int pXY[2]; // [sp+64h] [bp-8h]@261
+  int a2; // [sp+7Ch] [bp+10h]@50
+
+  switch (Msg)
+  {
+    case WM_SETTEXT: return DefWindowProcW(hWnd, Msg, wParam, lParam);
+  };
+
+  v4 = lParam;
+  if ( Msg > WM_SYSCOMMAND )
+  {
+    switch ( Msg )
+    {
+      default:
+        goto _def_wnd_proc;
+      case WM_DEVICECHANGE:
+        if ( wParam == 0x8000 )
+          PostMessageA(hInsertCDWindow, WM_CHOOSEFONT_GETLOGFONT, 0, 0);
+        return 0;
+      case WM_SIZING:
+        return 1;
+      case WM_LBUTTONDOWN:
+        v28 = 0;
+        if ( pArcomageGame->bGameInProgress )
+        {
+          if (pAsyncMouse)
+            goto _def_wnd_proc;
+          pArcomageGame->stru1.field_0 = 7;
+          v29 = 1;
+LABEL_210:
+          v30 = 0;
+          goto LABEL_263;
+        }
+        if ( pVideoPlayer->pVideoFrame.pPixels )
+          pVideoPlayer->bStopBeforeSchedule = 1;
+        if ( !pAsyncMouse )
+          pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
+        if (GetCurrentMenuID() != MENU_CREATEPARTY)
+          goto LABEL_230;
+        goto LABEL_229;
+      case WM_RBUTTONDOWN:
+        v31 = 0;
+        if ( !pArcomageGame->bGameInProgress )
+          goto LABEL_240;
+        if (pAsyncMouse)
+          goto _def_wnd_proc;
+        pArcomageGame->stru1.field_0 = 8;
+        v29 = 1;
+        goto LABEL_262;
+      case WM_LBUTTONUP:
+        v32 = 0;
+        if ( !pArcomageGame->bGameInProgress )
+          goto LABEL_218;
+        if (pAsyncMouse)
+          goto _def_wnd_proc;
+        pArcomageGame->stru1.field_0 = 3;
+        v29 = 0;
+        goto LABEL_210;
+      case WM_RBUTTONUP:
+        v32 = 0;
+        if ( !pArcomageGame->bGameInProgress )
+        {
+LABEL_218:
+          if ( pAsyncMouse != v32 )
+            goto _def_wnd_proc;
+          back_to_game();
+          return DefWindowProcA(hWnd, Msg, wParam, v4);
+        }
+        if (pAsyncMouse)
+          goto _def_wnd_proc;
+        pArcomageGame->stru1.field_0 = 4;
+        v29 = 0;
+        goto LABEL_262;
+      case WM_LBUTTONDBLCLK:
+        v28 = 0;
+        if ( pArcomageGame->bGameInProgress )
+        {
+          if (pAsyncMouse)
+            goto _def_wnd_proc;
+          pArcomageGame->stru1.field_0 = 7;
+          return DefWindowProcA(hWnd, Msg, wParam, v4);
+        }
+        if ( pVideoPlayer->pVideoFrame.pPixels )
+          pVideoPlayer->bStopBeforeSchedule = 1;
+        if ( !pAsyncMouse )
+          pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
+        if ( uCurrentMenuID != 6 )
+          goto LABEL_230;
+        if ( !pAsyncMouse )
+        {
+LABEL_229:
+          sub_41CD4F(0x29u);
+LABEL_230:
+          if ( pAsyncMouse == (void *)v28 )
+            pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
+        }
+        if ( pGame != (Game *)v28 )
+        {
+          if ( pAsyncMouse != (void *)v28 )
+            goto _def_wnd_proc;
+          pGame->PickMouse(512.0, (unsigned __int16)lParam, lParam >> 16, v28, &a3, &a4);
+        }
+        if ( pAsyncMouse == (void *)v28 )
+        {
+          UI_OnMouseLeftClick(0);
+          return DefWindowProcA(hWnd, Msg, wParam, v4);
+        }
+        goto _def_wnd_proc;
+      case WM_RBUTTONDBLCLK:
+        v31 = 0;
+        if ( !pArcomageGame->bGameInProgress )
+        {
+LABEL_240:
+          if ( pVideoPlayer->pVideoFrame.pPixels != (unsigned __int16 *)v31 )
+            pVideoPlayer->bStopBeforeSchedule = 1;
+          if (!pAsyncMouse)
+            pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
+          if (pGame)
+          {
+            if (pAsyncMouse)
+              goto _def_wnd_proc;
+            v33 = GetPickDepth();
+            pGame->PickMouse(v33, (unsigned __int16)lParam, lParam >> 16, v31, &stru_F93E30, &a4);
+          }
+          if (!pAsyncMouse)
+          {
+            sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(0);
+            return DefWindowProcA(hWnd, Msg, wParam, v4);
+          }
+          goto _def_wnd_proc;
+        }
+        if (pAsyncMouse)
+          goto _def_wnd_proc;
+        pArcomageGame->stru1.field_0 = 8;
+        return DefWindowProcA(hWnd, Msg, wParam, v4);
+      case WM_MBUTTONDOWN:
+        if ( pRenderer->pRenderD3D )
+        {
+          if ( pGame && !pAsyncMouse )
+          {
+            v34 = GetPickDepth();
+            pGame->PickMouse(v34, (unsigned __int16)lParam, lParam >> 16, 1, &a3, &a5);
+            return DefWindowProcA(hWnd, Msg, wParam, v4);
+          }
+          goto _def_wnd_proc;
+        }
+        if ( !pGame )
+          goto _def_wnd_proc;
+        sub_417871(0);
+        return DefWindowProcA(hWnd, Msg, wParam, v4);
+      case WM_MOUSEMOVE:
+        if ( pArcomageGame->bGameInProgress )
+        {
+          if (pAsyncMouse)
+            goto _def_wnd_proc;
+          pXY[0] = (unsigned __int16)lParam;
+          pXY[1] = lParam >> 16;
+          ArcomageGame::OnMouseMove((POINT *)pXY);
+          ArcomageGame::OnMouseClick(0, wParam & 1);
+          v29 = (wParam >> 1) & 1;
+LABEL_262:
+          v30 = 1;
+LABEL_263:
+          ArcomageGame::OnMouseClick(v30, v29);
+        }
+        else
+        {
+          if (pAsyncMouse)
+            goto _def_wnd_proc;
+          pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
+        }
+        return DefWindowProcA(hWnd, Msg, wParam, v4);
+    }
+  }
+  if ( Msg == WM_SYSCOMMAND )
+  {
+    if ( wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER )
+      return 0;
+    goto _def_wnd_proc;
+  }
+  if ( Msg > WM_ACTIVATEAPP )
+  {
+    if ( Msg == WM_WINDOWPOSCHANGED )
+    {
+      if (pVideoPlayer)
+      {
+        if (pVideoPlayer->AnyMovieLoaded() && pVideoPlayer->pBinkBuffer)
+        {
+          BinkBufferSetOffset(pVideoPlayer->pBinkBuffer, 0, 0);
+          return DefWindowProcA(hWnd, Msg, wParam, v4);
+        }
+      }
+      goto _def_wnd_proc;
+    }
+    if ( Msg != WM_KEYFIRST )
+    {
+      if ( Msg == WM_KEYUP )
+      {
+        if ( wParam == VK_CONTROL )
+        {
+          dword_507B98_ctrl_pressed = 0;
+          return DefWindowProcA(hWnd, Msg, wParam, v4);
+        }
+        goto _def_wnd_proc;
+      }
+      if ( Msg == WM_CHAR )
+      {
+        if ( !pKeyActionMap->_459F10(wParam) && !viewparams->field_4C )
+        {
+          GUI_HandleHotkey(wParam);
+          return DefWindowProcA(hWnd, Msg, wParam, v4);
+        }
+        goto _def_wnd_proc;
+      }
+      if ( Msg != WM_COMMAND )
+        goto _def_wnd_proc;
+      if ( wParam != 101 )
+      {
+        if ( wParam == 103 )
+        {
+          pRenderer->SavePCXScreenshot();
+          return 0;
+        }
+        if ( wParam == 104 )
+        {
+          pRenderer->ChangeBetweenWinFullscreenModes();
+          if ( pArcomageGame->bGameInProgress )
+            pArcomageGame->field_F6 = 1;
+          return 0;
+        }
+        if ( wParam != 40001 )
+          return DefWindowProcA(hWnd, Msg, wParam, v4);
+      }
+      v38 = 0;
+      v37 = 0;
+      v36 = 2;
+      v35 = ::hWnd;
+LABEL_104:
+      SendMessageA(v35, v36, v37, v38);
+      return 0;
+    }
+    if ( dword_506E68 != -1 )
+    {
+      pKeyActionMap->_459F10(wParam);
+      return DefWindowProcA(hWnd, Msg, wParam, v4);
+    }
+    if ( !pArcomageGame->bGameInProgress )
+    {
+      if ( pVideoPlayer->pVideoFrame.pPixels )
+        pVideoPlayer->bStopBeforeSchedule = 1;
+      if ( wParam != 13 )
+      {
+        if ( wParam == 17 )
+        {
+          dword_507B98_ctrl_pressed = 1;
+          return 0;
+        }
+        if ( wParam == 27 )
+        {
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+          {
+            v12 = ptr_507BC0 == 0;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = !v12;
+            *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+          return 0;
+        }
+        if ( wParam <= 0x24 )
+          return 0;
+        if ( wParam > 0x28 )
+        {
+          if ( wParam != 115 || pVideoPlayer->AnyMovieLoaded() )
+            return 0;
+          v38 = 0;
+          v37 = 104;
+LABEL_126:
+          v36 = 273;
+          v35 = hWnd;
+          goto LABEL_104;
+        }
+        if ( pCurrentScreen
+          && pCurrentScreen != 21 )
+          return 0;
+      }
+      if ( !viewparams->field_4C )
+        sub_41CD4F(wParam);
+      return 0;
+    }
+    pArcomageGame->stru1.field_0 = 1;
+    if ( (unsigned __int16)GetAsyncKeyState(VK_SHIFT) >> 8 >= 0 )
+    {
+      v27 = MapVirtualKeyA((unsigned __int16)wParam, 2u);
+    }
+    else
+    {
+      v13 = (unsigned __int16)MapVirtualKeyA((unsigned __int16)wParam, 2u);
+      if ( (signed int)(unsigned __int16)v13 > 54 )
+      {
+        if ( v13 > 61 )
+        {
+          v24 = v13 - 91;
+          if ( !v24 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 123;
+            goto LABEL_181;
+          }
+          v25 = v24 - 1;
+          if ( !v25 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 124;
+            goto LABEL_181;
+          }
+          v26 = v25 - 1;
+          if ( !v26 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 125;
+            goto LABEL_181;
+          }
+          if ( v26 == 3 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 126;
+            goto LABEL_181;
+          }
+        }
+        else
+        {
+          if ( v13 == 61 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 43;
+            goto LABEL_181;
+          }
+          v21 = v13 - 55;
+          if ( !v21 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 38;
+            goto LABEL_181;
+          }
+          v22 = v21 - 1;
+          if ( !v22 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 42;
+            goto LABEL_181;
+          }
+          v23 = v22 - 1;
+          if ( !v23 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 40;
+            goto LABEL_181;
+          }
+          if ( v23 == 2 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 58;
+            goto LABEL_181;
+          }
+        }
+      }
+      else
+      {
+        if ( (unsigned __int16)v13 == 54 )
+        {
+          LOBYTE(pArcomageGame->stru1.field_8) = 94;
+          goto LABEL_181;
+        }
+        if ( v13 > 49 )
+        {
+          v18 = v13 - 50;
+          if ( !v18 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 64;
+            goto LABEL_181;
+          }
+          v19 = v18 - 1;
+          if ( !v19 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 35;
+            goto LABEL_181;
+          }
+          v20 = v19 - 1;
+          if ( !v20 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 36;
+            goto LABEL_181;
+          }
+          if ( v20 == 1 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 37;
+            goto LABEL_181;
+          }
+        }
+        else
+        {
+          if ( v13 == 49 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 33;
+            goto LABEL_181;
+          }
+          v14 = v13 - 39;
+          if ( !v14 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 34;
+            goto LABEL_181;
+          }
+          v15 = v14 - 5;
+          if ( !v15 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 60;
+            goto LABEL_181;
+          }
+          v16 = v15 - 2;
+          if ( !v16 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 62;
+            goto LABEL_181;
+          }
+          v17 = v16 - 1;
+          if ( !v17 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 63;
+            goto LABEL_181;
+          }
+          if ( v17 == 1 )
+          {
+            LOBYTE(pArcomageGame->stru1.field_8) = 41;
+LABEL_181:
+            if ( wParam == 27 )
+            {
+              pArcomageGame->field_F5 = 1;
+              pArcomageGame->field_F4 = 1;
+              pArcomageGame->uGameResult = 2;
+              pArcomageGame->field_B0 = -2;
+              goto _def_wnd_proc;
+            }
+            if ( wParam != 114 )
+            {
+              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
+                SendMessageA(hWnd, 0x111u, 0x68u, 0);
+              goto _def_wnd_proc;
+            }
+            v38 = 0;
+            v37 = 103;
+            goto LABEL_126;
+          }
+        }
+      }
+      v27 = MapVirtualKeyA((unsigned __int16)wParam, 2u);
+    }
+    LOBYTE(pArcomageGame->stru1.field_8) = v27;
+    goto LABEL_181;
+  }
+  if ( Msg == WM_ACTIVATEAPP )
+  {
+    if ( wParam && (GetForegroundWindow() == hWnd || GetForegroundWindow() == hInsertCDWindow) )
+    {
+      if ( BYTE1(dword_6BE364_game_settings_1) & 1 )
+      {
+        dword_4E98BC_bApplicationActive = 1;
+        if ( pRenderer->bWindowMode )
+        {
+          v10 = GetDC(0);
+          a2 = GetDeviceCaps(v10, BITSPIXEL);
+          v11 = GetDeviceCaps(v10, PLANES);
+          ReleaseDC(0, v10);
+          if ( a2 != 16 || v11 != 1 )
+            Abortf(pGlobalTXT_LocalizationStrings[62]);
+        }
+        BYTE1(dword_6BE364_game_settings_1) &= 0xFEu;
+        if (pAsyncMouse)
+          pAsyncMouse->Resume();
+        if ( pArcomageGame->bGameInProgress )
+        {
+          pArcomageGame->field_F9 = 1;
+        }
+        else
+        {
+          if ( BYTE1(dword_6BE364_game_settings_1) & 2 )
+            BYTE1(dword_6BE364_game_settings_1) &= 0xFDu;
+          else
+            pEventTimer->Resume();
+          if ( BYTE1(dword_6BE364_game_settings_1) & 4 )
+            BYTE1(dword_6BE364_game_settings_1) &= 0xFBu;
+          else
+            pMiscTimer->Resume();
+          if ( LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) && pAsyncKeyboard )
+            pAsyncKeyboard->Resume();
+          viewparams->bRedrawGameUI = 1;
+          if ( pVideoPlayer->pSmackerMovie )
+          {
+            pRenderer->RestoreFrontBuffer();
+            pRenderer->_4A184C();
+            pVideoPlayer->_4BF5B2();
+          }
+        }
+        if ( pAudioPlayer->hAILRedbook && !bGameoverLoop && !pVideoPlayer->pSmackerMovie )
+          AIL_redbook_resume(pAudioPlayer->hAILRedbook);
+      }
+    }
+    else
+    {
+      if ( !(dword_6BE364_game_settings_1 & 0x100) )
+      {
+        dword_4E98BC_bApplicationActive = 0;
+        if ( (pVideoPlayer->pSmackerMovie || pVideoPlayer->pBinkMovie) && pVideoPlayer->bPlayingMovie )
+          pVideoPlayer->bStopBeforeSchedule = 1;
+        if (pAsyncMouse)
+          pAsyncMouse->Suspend();
+        if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
+          SetWindowPos(::hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
+        ClipCursor(0);
+        dword_6BE364_game_settings_1 |= 0x100u;
+        if ( pEventTimer->bPaused )
+          BYTE1(dword_6BE364_game_settings_1) |= 2u;
+        else
+          pEventTimer->Pause();
+        if ( pMiscTimer->bPaused )
+          BYTE1(dword_6BE364_game_settings_1) |= 4u;
+        else
+          pMiscTimer->Pause();
+        if ( pGame && LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) && pAsyncKeyboard )
+          pAsyncKeyboard->Suspend();
+        pAudioPlayer->StopChannels(-1, -1);
+        if ( pAudioPlayer->hAILRedbook )
+          AIL_redbook_pause(pAudioPlayer->hAILRedbook);
+      }
+    }
+    return 0;
+  }
+  if (Msg == WM_CREATE)
+  {
+    auto hDC = GetDC(hWnd);
+    {
+      if (GetDeviceCaps(hDC, BITSPIXEL) < 8)
+      {
+        ReleaseDC(hWnd, hDC);
+        Log::Warning(L"You must be running in 256 color mode or higher.");
+        Abortf("You must be running in 256 color mode or higher. You can change the screen depth with the control panel display icon.");
+      }
+    }
+    ReleaseDC(hWnd, hDC);
+    return 0;
+  }
+  if ( Msg == WM_DESTROY )
+  {
+    v6 = GetCurrentProcess();
+    SetPriorityClass(v6, 0x20u);
+    if ( pGame )
+    {
+      v7 = pGame->pKeyboardInstance;
+      if ( v7 )
+      {
+        if ( LOBYTE(v7->bUsingAsynKeyboard) && pAsyncKeyboard )
+          pAsyncKeyboard->_45B3A4();
+      }
+    }
+    if (pAsyncMouse)
+      pAsyncMouse->_46B1DD();
+    PostQuitMessage(0);
+    return 0;
+  }
+  if ( Msg == WM_SETFOCUS )
+  {
+    if ( ::hWnd == (HWND)wParam )
+    {
+      dword_4E98BC_bApplicationActive = 0;
+      if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
+        SetWindowPos(::hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
+      ClipCursor(0);
+      if (pAsyncMouse)
+      {
+        pAsyncMouse->Suspend();
+        return DefWindowProcA(hWnd, Msg, wParam, v4);
+      }
+    }
+_def_wnd_proc:
+    v4 = lParam;
+    return DefWindowProcA(hWnd, Msg, wParam, v4);
+  }
+  if ( Msg != WM_KILLFOCUS )
+  {
+    if ( Msg == WM_PAINT )
+    {
+      if ( !GetUpdateRect(hWnd, 0, 0) || !dword_4E98BC_bApplicationActive && !pRenderer->bWindowMode )
+        return 0;
+      BeginPaint(hWnd, &Paint);
+      if ( pArcomageGame->bGameInProgress )
+      {
+        pArcomageGame->field_F9 = 1;
+        v5 = pRenderer;
+      }
+      else
+      {
+        if ( !pRenderer->pRenderD3D && !pRenderer->UsingDirect3D() || !AreRenderSurfacesOk() )
+          goto LABEL_20;
+        v5 = pRenderer;
+      }
+      pRenderer->Present();
+LABEL_20:
+      EndPaint(hWnd, &Paint);
+      return 0;
+    }
+    goto _def_wnd_proc;
+  }
+  if ( ::hWnd != (HWND)wParam || (dword_4E98BC_bApplicationActive = 1, pRenderer->bWindowMode) || !pAsyncMouse )
+    return DefWindowProcA(hWnd, Msg, wParam, v4);
+  pAsyncMouse->Resume();
+  if ( !pAsyncMouse )
+    goto _def_wnd_proc;
+  pAsyncMouse->Clip();
+  return DefWindowProcA(hWnd, Msg, wParam, v4);
+}
+
+//----- (00464479) --------------------------------------------------------
+void __cdecl ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows()
+{
+  int v0; // esi@9
+
+  if (pMouse)
+    pMouse->SetCursorBitmap("MICON1");
+
+  pPaletteManager->ResetNonLocked();
+  pBitmaps_LOD->ReleaseAll2();
+  pSprites_LOD->DeleteSomeOtherSprites();
+  pIcons_LOD->ReleaseAll2();
+  if (pRenderer->pRenderD3D)
+  {
+    pRenderer->field_1036B8 = 0;
+    pRenderer->_gpu_memory_used = 0;
+  }
+  sub_46080D();
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    pIndoor->Release();
+  else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    pOutdoor->Release2();
+
+  pAudioPlayer->StopChannels(-1, -1);
+  pSoundList->_4A9D79(0);
+  uCurrentlyLoadedLevelType = LEVEL_null;
+  pSpriteFrameTable->ResetSomeSpriteFlags();
+  v0 = uNumVisibleWindows;
+  pParty->field_1613C = 0;
+  while ( v0 > 0 )
+    pWindowList[pVisibleWindowsIdxs[v0--] - 1].Release();
+}
+
+
+
+//----- (004646F0) --------------------------------------------------------
+void PrepareWorld(unsigned int this_)
+{
+  unsigned int v1; // ebx@1
+
+  v1 = this_;
+  if ( pRenderer->pRenderD3D )
+    pGame->pVisInstance->_4C1A02();
+  pEventTimer->Pause();
+  pMiscTimer->Pause();
+  pParty->uFlags = 2;
+  pStru277->_427D48(1);
+  ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
+  DoPrepareWorld(0, (v1 == 0) + 1);
+  pMiscTimer->Resume();
+  pEventTimer->Resume();
+}
+
+//----- (00464761) --------------------------------------------------------
+void __thiscall Game_DeinitializeAndTerminate(int exitCode)
+{
+  int v1; // esi@1
+  HANDLE v2; // eax@1
+
+  v1 = exitCode;
+  v2 = GetCurrentProcess();
+  SetPriorityClass(v2, 0x20u);
+  ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
+  pGame->Deinitialize();
+  pRenderer->Release2();
+  if ( !DestroyWindow(hWnd) )
+    GetLastError();
+  hWnd = 0;
+  exit(v1);
+}
+
+//----- (004647AB) --------------------------------------------------------
+void __cdecl FinalInitialization()
+{
+  pViewport->SetScreen(viewparams->uSomeX, viewparams->uSomeY, viewparams->uSomeZ, viewparams->uSomeW);
+  pViewport->_4C02F8((signed __int64)(flt_6BE3A0 * 65536.0));
+
+  pIndoorCamera = new IndoorCamera;
+  pIndoorCamera->Initialize(
+    65,
+    viewparams->uScreenZ - viewparams->uScreenX + 1,
+    viewparams->uScreenW - viewparams->uScreenY + 1);
+
+  InitializeTurnBasedAnimations(&stru_50C198);
+  pBitmaps_LOD->dword_11B84 = pBitmaps_LOD->uNumLoadedFiles;
+  pSprites_LOD->field_ECA0 = pSprites_LOD->uNumLoadedSprites;
+  pIcons_LOD->dword_11B84 = pIcons_LOD->uNumLoadedFiles;
+}
+// 6BE3A0: using guessed type float flt_6BE3A0;
+
+//----- (00464839) --------------------------------------------------------
+char __cdecl Is_out15odm_underwater()
+{
+  return _strcmpi(pCurrentMapName, "out15.odm") == 0;
+}
+
+//----- (00464851) --------------------------------------------------------
+void __cdecl SetUnderwaterFog()
+{
+  day_fogrange_1 = 50;
+  day_fogrange_2 = 5000;
+}
+
+
+
+//----- (00464866) --------------------------------------------------------
+void __fastcall DoPrepareWorld(unsigned int bLoading, int a2)
+{
+  int v2; // esi@1
+  char *v3; // eax@1
+  //char *v4; // eax@1
+  unsigned int v5; // eax@3
+  //size_t v6; // ecx@10
+  //char *v7; // eax@11
+  char Str1[20]; // [sp+Ch] [bp-18h]@1
+  unsigned int v9; // [sp+20h] [bp-4h]@1
+
+  v2 = a2;
+  v9 = bLoading;
+  ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
+  pDecalBuilder->Reset(0);
+  pGameLoadingUI_ProgressBar->_443484((GUIProgressBar::Type)v2);
+  strcpy(Str1, pCurrentMapName);
+  v3 = strtok(Str1, ".");
+  strcpy(Str1, v3);
+  Level_LoadEvtAndStr(Str1);
+  LoadLevel_InitializeLevelEvt();
+  strcpy(Str1, pCurrentMapName);
+  _strrev(Str1);
+  strtok(Str1, ".");
+  _strrev(Str1);
+
+  for (uint i = 0; i < 1000; ++i)
+    pLayingItems[i].uObjectDescID = 0;
+
+  v5 = pMapStats->GetMapInfo(pCurrentMapName);
+  bUnderwater = 0;
+  uLevelMapStatsID = v5;
+  pGame->uFlags2 &= 0xFFFFFFF7u;
+  if ( !_strcmpi(pCurrentMapName, "out15.odm") )
+  {
+    bUnderwater = 1;
+    pGame->uFlags2 |= 8u;
+  }
+  pParty->field_6F4_packedid = 0;
+  if ( _strcmpi(Str1, "blv") )
+    PrepareToLoadODM(v9, 0);
+  else
+    PrepareToLoadBLV(v9);
+  pAudioPlayer->SetMapEAX();
+  sub_461103();
+  if ( !_strcmpi(pCurrentMapName, "d11.blv") || !_strcmpi(pCurrentMapName, "d10.blv") )
+  {
+    //spawning grounds & good analogue - no loot & exp from monsters
+
+    for (uint i = 0; i < uNumActors; ++i)
+    {
+      pActors[i].pMonsterInfo.uTreasureType = 0;
+      pActors[i].pMonsterInfo.uTreasureDiceRolls = 0;
+      pActors[i].pMonsterInfo.uExp = 0;
+    }
+  }
+  bDialogueUI_InitializeActor_NPC_ID = 0;
+  OnMapLoad();
+  pGameLoadingUI_ProgressBar->Progress();
+  pGameLoadingUI_ProgressBar->Release();
+  _flushall();
+}
+
+
+//----- (004649EF) --------------------------------------------------------
+int __fastcall ReadWindowsRegistryInt(const char *pKey, int uDefValue)
+{
+  int v3; // [sp+4h] [bp-24h]@1
+  DWORD cbData; // [sp+8h] [bp-20h]@1
+  LPCSTR lpValueName; // [sp+Ch] [bp-1Ch]@1
+  DWORD dwDisposition; // [sp+10h] [bp-18h]@2
+  BYTE Data[4]; // [sp+14h] [bp-14h]@5
+  HKEY hKey; // [sp+18h] [bp-10h]@1
+  HKEY phkResult; // [sp+1Ch] [bp-Ch]@1
+  HKEY v10; // [sp+20h] [bp-8h]@1
+  HKEY v11; // [sp+24h] [bp-4h]@1
+
+  v3 = uDefValue;
+  lpValueName = pKey;
+  v11 = 0;
+  v10 = 0;
+  hKey = 0;
+  phkResult = 0;
+  cbData = 4;
+  if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hKey) )
+  {
+    if ( !RegCreateKeyExA(hKey, "New World Computing", 0, "", 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
+    {
+      if ( !RegCreateKeyExA(phkResult, "Might and Magic VII", 0, "", 0, 0xF003Fu, 0, &v10, &dwDisposition) )
+      {
+        if ( !RegCreateKeyExA(v10, "1.0", 0, "", 0, 0xF003Fu, 0, &v11, &dwDisposition) )
+        {
+          if ( RegQueryValueExA(v11, lpValueName, 0, 0, Data, &cbData) )
+          {
+            *(int *)Data = v3;
+            RegSetValueExA(v11, lpValueName, 0, 4u, Data, 4u);
+          }
+          RegCloseKey(v11);
+        }
+        RegCloseKey(v10);
+      }
+      RegCloseKey(phkResult);
+    }
+    RegCloseKey(hKey);
+  }
+  return *(int *)Data;
+}
+
+//----- (00464B02) --------------------------------------------------------
+void __fastcall WriteWindowsRegistryString(const char *pKey, const char *pString)
+{
+  size_t v2; // eax@5
+  const char *lpValueName; // [sp+4h] [bp-1Ch]@1
+  const char *Str; // [sp+8h] [bp-18h]@1
+  DWORD dwDisposition; // [sp+Ch] [bp-14h]@2
+  HKEY hKey; // [sp+10h] [bp-10h]@1
+  HKEY phkResult; // [sp+14h] [bp-Ch]@1
+  HKEY v8; // [sp+18h] [bp-8h]@1
+  HKEY v9; // [sp+1Ch] [bp-4h]@1
+
+  Str = pString;
+  lpValueName = pKey;
+  v9 = 0;
+  v8 = 0;
+  hKey = 0;
+  phkResult = 0;
+  if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hKey) )
+  {
+    if ( !RegCreateKeyExA(hKey, "New World Computing", 0, "", 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
+    {
+      if ( !RegCreateKeyExA(phkResult, "Might and Magic VII", 0, "", 0, 0xF003Fu, 0, &v8, &dwDisposition) )
+      {
+        if ( !RegCreateKeyExA(v8, "1.0", 0, "", 0, 0xF003Fu, 0, &v9, &dwDisposition) )
+        {
+          v2 = strlen(Str);
+          RegSetValueExA(v9, lpValueName, 0, 1u, (const BYTE *)Str, v2 + 1);
+          RegCloseKey(v9);
+        }
+        RegCloseKey(v8);
+      }
+      RegCloseKey(phkResult);
+    }
+    RegCloseKey(hKey);
+  }
+}
+
+//----- (00464BEF) --------------------------------------------------------
+void __fastcall ReadWindowsRegistryString(const char *pKeyName, char *pOutString, int uBufLen, const char *pDefaultValue)
+{
+  LSTATUS (__stdcall *v4)(HKEY); // esi@1
+  LSTATUS result; // eax@7
+  DWORD Type; // [sp+Ch] [bp-24h]@5
+  LPCSTR lpValueName; // [sp+10h] [bp-20h]@1
+  DWORD cbData; // [sp+14h] [bp-1Ch]@1
+  LPBYTE Dest; // [sp+18h] [bp-18h]@1
+  DWORD dwDisposition; // [sp+1Ch] [bp-14h]@2
+  HKEY phkResult; // [sp+20h] [bp-10h]@1
+  HKEY hKey; // [sp+24h] [bp-Ch]@1
+  HKEY v13; // [sp+28h] [bp-8h]@1
+  HKEY v14; // [sp+2Ch] [bp-4h]@1
+
+  cbData = uBufLen;
+  Dest = (LPBYTE)pOutString;
+  lpValueName = pKeyName;
+  v14 = 0;
+  v13 = 0;
+  hKey = 0;
+  phkResult = 0;
+  v4 = RegCloseKey;
+  if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hKey)
+    || RegCreateKeyExA(hKey, "New World Computing", 0, "", 0, 0xF003Fu, 0, &phkResult, &dwDisposition)
+    || RegCreateKeyExA(phkResult, "Might and Magic VII", 0, "", 0, 0xF003Fu, 0, &v13, &dwDisposition)
+    || RegCreateKeyExA(v13, "1.0", 0, "", 0, 0xF003Fu, 0, &v14, &dwDisposition) )
+    goto LABEL_7;
+  if ( RegQueryValueExA(v14, lpValueName, 0, &Type, Dest, &cbData) )
+  {
+    RegCloseKey(v14);
+    v14 = 0;
+LABEL_7:
+    result = (LSTATUS)strncpy((char *)Dest, pDefaultValue, uBufLen);
+    goto LABEL_8;
+  }
+  v4 = RegCloseKey;
+  RegCloseKey(v14);
+  v14 = 0;
+  RegCloseKey(v13);
+  v13 = 0;
+  RegCloseKey(phkResult);
+  phkResult = 0;
+  result = RegCloseKey(hKey);
+  hKey = 0;
+LABEL_8:
+  if ( v14 )
+    result = v4(v14);
+  if ( v13 )
+    result = v4(v13);
+  if ( hKey )
+    result = v4(hKey);
+  if ( phkResult )
+    result = v4(phkResult);
+}
+
+//----- (00464D32) --------------------------------------------------------
+void __fastcall WriteWindowsRegistryInt(const char *pKey, int val)
+{
+  const char *lpValueName; // [sp+4h] [bp-1Ch]@1
+  BYTE Data[4]; // [sp+8h] [bp-18h]@1
+  DWORD dwDisposition; // [sp+Ch] [bp-14h]@2
+  HKEY hKey; // [sp+10h] [bp-10h]@1
+  HKEY phkResult; // [sp+14h] [bp-Ch]@1
+  HKEY v7; // [sp+18h] [bp-8h]@1
+  HKEY v8; // [sp+1Ch] [bp-4h]@1
+
+  *(int *)Data = val;
+  lpValueName = pKey;
+  v8 = 0;
+  v7 = 0;
+  hKey = 0;
+  phkResult = 0;
+  if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hKey) )
+  {
+    if ( !RegCreateKeyExA(hKey, "New World Computing", 0, "", 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
+    {
+      if ( !RegCreateKeyExA(phkResult, "Might and Magic VII", 0, "", 0, 0xF003Fu, 0, &v7, &dwDisposition) )
+      {
+        if ( !RegCreateKeyExA(v7, "1.0", 0, "", 0, 0xF003Fu, 0, &v8, &dwDisposition) )
+        {
+          RegSetValueExA(v8, lpValueName, 0, 4u, Data, 4u);
+          RegCloseKey(v8);
+        }
+        RegCloseKey(v7);
+      }
+      RegCloseKey(phkResult);
+    }
+    RegCloseKey(hKey);
+  }
+}
+
+//----- (00464E17) --------------------------------------------------------
+bool __fastcall CheckMM7CD(char c)
+{
+  char DstBuf[256]; // [sp+Ch] [bp-218h]@1
+  char strCommand[256]; // [sp+10Ch] [bp-118h]@1
+  char Filename[20]; // [sp+20Ch] [bp-18h]@1
+
+
+  wchar_t pMagicPath[1024];
+  swprintf(pMagicPath, L"%C:\\anims\\magic7.vid", c);
+  if (GetFileAttributesW(pMagicPath) == -1)
+    return false;
+
+  wsprintfA(strCommand, "open %c: type cdaudio alias CD", c);
+  if (!mciSendStringA(strCommand, DstBuf, 0xFFu, 0))
+  {
+    wsprintfA(strCommand, "info CD UPC wait");
+    mciSendStringA(strCommand, DstBuf, 0xFFu, 0);
+    wsprintfA(strCommand, "close CD");
+    mciSendStringA(strCommand, DstBuf, 0xFFu, 0);
+  }
+
+  memcpy(Filename, "X:\\anims\\magic7.vid", sizeof(Filename));
+  *Filename = c;
+
+  auto f = fopen(Filename, "rb");
+  if (!f)
+    return false;
+
+  if (!fseek(f, 0, SEEK_END))
+  {
+    if (!fseek(f, -100, SEEK_CUR))
+      fread(DstBuf, 1u, 0x64u, f);
+
+    fclose(f);
+    return true;
+  }
+  fclose(f);
+  return false;
+}
+
+//----- (00464F1B) --------------------------------------------------------
+signed int __stdcall InsertMM7CDDialogFunc(HWND hDlg, int a2, __int16 a3, int a4)
+{
+  char v4; // zf@3
+  int v6; // eax@10
+  int v7; // eax@11
+  int v8; // eax@12
+  int v9; // eax@13
+  BOOL (__stdcall *v10)(HWND, int, LPCSTR); // edi@15
+  const CHAR *v11; // [sp-Ch] [bp-Ch]@15
+  INT_PTR v12; // [sp-4h] [bp-4h]@5
+
+  if ( a2 == 272 )
+  {
+    hInsertCDWindow = hDlg;
+    v6 = (GetUserDefaultLangID() & 0x3FF) - 7;
+    if ( v6 )
+    {
+      v7 = v6 - 3;
+      if ( v7 )
+      {
+        v8 = v7 - 2;
+        if ( v8 )
+        {
+          v9 = v8 - 4;
+          if ( v9 )
+          {
+            if ( v9 != 5 )
+              return 0;
+            SetWindowTextA(hDlg, "Wloz CD-ROM numer 2");
+            v10 = SetDlgItemTextA;
+            SetDlgItemTextA(hDlg, 1010, "Wloz CD-ROM numer 2 Might and Magic® VII.");
+            v11 = "Odwolaj";
+          }
+          else
+          {
+            SetWindowTextA(hDlg, "Inserire il secondo CD");
+            v10 = SetDlgItemTextA;
+            SetDlgItemTextA(hDlg, 1010, "Inserire il secondo CD di Might and Magic® VII.");
+            v11 = "Annulla";
+          }
+        }
+        else
+        {
+          SetWindowTextA(hDlg, "Insérez le CD 2");
+          v10 = SetDlgItemTextA;
+          SetDlgItemTextA(hDlg, 1010, "Insérez Might & Magic® VII CD 2.");
+          v11 = "Supprimer";
+        }
+      }
+      else
+      {
+        SetWindowTextA(hDlg, "Por favor, inserte disco 2");
+        v10 = SetDlgItemTextA;
+        SetDlgItemTextA(hDlg, 1010, "Por favor, inserte disco 2 de Might & Magic® VII.");
+        v11 = "Cancelar";
+      }
+    }
+    else
+    {
+      SetWindowTextA(hDlg, "Bitte CD 2 einlegen");
+      v10 = SetDlgItemTextA;
+      SetDlgItemTextA(hDlg, 1010, "Bitte CD 2 von Might and Magic® VII einlegen.");
+      v11 = "Abbrechen";
+    }
+    v10(hDlg, 2, v11);
+    return 0;
+  }
+  if ( a2 == 273 )
+  {
+    if ( a3 == 2 )
+    {
+      v12 = 0;
+LABEL_9:
+      EndDialog(hDlg, v12);
+      return 1;
+    }
+    v4 = a3 == 1;
+  }
+  else
+  {
+    v4 = a2 == 1025;
+  }
+  if ( v4 )
+  {
+    v12 = 1;
+    goto LABEL_9;
+  }
+  return 0;
+}
+
+//----- (00465061) --------------------------------------------------------
+bool __fastcall FindMM7CD(HWND hWnd, char *pCDDrive)
+{
+  char drive[4] = {'X', ':', '\\', 0};
+
+  bool bGotCDFromRegistry = false;
+
+  HKEY hSoftware = nullptr,
+       hNWC = nullptr,
+       hMM7 = nullptr,
+       hVersion = nullptr;
+  if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hSoftware))
+  {
+    if (!RegOpenKeyExA(hSoftware, "New World Computing", 0, 0x2001Fu, &hNWC))
+    {
+      if (!RegOpenKeyExA(hNWC, "Might and Magic VII", 0, 0x2001Fu, &hMM7))
+      {
+        if (!RegOpenKeyExA(hMM7, "1.0", 0, 0x2001Fu, &hVersion))
+        {
+          DWORD cbData = 3;
+          if (!RegQueryValueExA(hVersion, "CDDrive", 0, 0, (BYTE *)drive, &cbData))
+            bGotCDFromRegistry = true;
+        }
+        RegCloseKey(hVersion);
+      }
+      RegCloseKey(hMM7);
+    }
+    RegCloseKey(hNWC);
+  }
+  RegCloseKey(hSoftware);
+
+  if (bGotCDFromRegistry)
+    if (CheckMM7CD(*drive))
+    {
+      cMM7GameCDDriveLetter = *drive;
+      return true;
+    }
+
+  while (true)
+  {
+    for (uint i = 0; i < 26; ++i)
+    {
+      drive[0] = 'A' + i;
+
+      if (GetDriveTypeA(drive) == DRIVE_CDROM)
+        if (CheckMM7CD(*drive))
+        {
+          cMM7GameCDDriveLetter = *drive;
+          WriteWindowsRegistryString("CDDrive", drive);
+          return true;
+        }
+    }
+
+    if (DialogBoxParamA(GetModuleHandleW(nullptr), "InsertCD", ::hWnd, (DLGPROC)InsertMM7CDDialogFunc, 0))
+      continue;
+    return false;
+  }
+}
+
+//----- (004651F4) --------------------------------------------------------
+bool MM7_Initialize()
+{
+  wchar_t pCurrentDir[1024];
+  _wgetcwd(pCurrentDir, 1024);
+
+  wchar_t pMM6IniFile[1024];
+  wsprintf(pMM6IniFile, L"%s\\mm6.ini", pCurrentDir);
+
+  bCanLoadFromCD = GetPrivateProfileIntW(L"settings", L"use_cd", 1, pMM6IniFile);
+  if (bNoCD)
+    bCanLoadFromCD = false;
+  if (bCanLoadFromCD)
+  {
+    if (!FindMM7CD(hWnd, &cMM7GameCDDriveLetter))
+      return false;
+  }
+
+
+
+  srand(GetTickCount());
+  /*GetDiskFreeSpaceA(0, &SectorsPerCluster, &BytesPerSector, &hdc, &TotalNumberOfClusters);
+  v4 = hdc * BytesPerSector * SectorsPerCluster;
+  if ( (unsigned int)v4 < 0x1E00000 )
+  {
+    sprintfex(
+      pTmpBuf,
+      "Due to Window Virtual Memory requirements Might and Magic® VII\nrequires 30MB of free hard drive space to operate properly.\n\nAvailable on Current Drive = %luk",
+      (unsigned int)v4 / 1024i64);
+    v41 = 48;
+    v40 = "More Hard Drive Space Required";
+    v39 = pTmpBuf;
+*/
+  
+  WNDCLASSEXW wcxw;
+  {
+    wcxw.cbSize = sizeof(wcxw);
+    wcxw.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
+    wcxw.lpfnWndProc = (WNDPROC)aWinProc;
+    wcxw.cbClsExtra = 0;
+    wcxw.cbWndExtra = 0;
+    wcxw.hInstance = GetModuleHandleW(nullptr);
+    wcxw.hCursor = 0;
+    wcxw.hIcon = wcxw.hIconSm = LoadIconW(wcxw.hInstance, L"MM7_ICON");
+    wcxw.lpszMenuName = nullptr;
+    wcxw.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
+    wcxw.lpszClassName = L"M&MTrilogy";
+  }
+  if (!RegisterClassExW(&wcxw))
+  {
+    Log::Warning(L"Cannot register window class");
+    return false;
+  }
+
+  auto hDesktopDC = GetDC(nullptr);
+  uint uDesktopWidth = GetDeviceCaps(hDesktopDC, HORZRES);
+  uint uDesktopHeight = GetDeviceCaps(hDesktopDC, VERTRES);
+
+  if (GetDeviceCaps(hDesktopDC, BITSPIXEL) != 16 ||
+      GetDeviceCaps(hDesktopDC, PLANES) != 1 )
+    dword_6BE364_game_settings_1 |= 2;
+
+  ReleaseDC(nullptr, hDesktopDC);
+
+
+  uint uTotalWinWidth = 2 * GetSystemMetrics(SM_CXFRAME) + 640;
+  uint uTotalWinHeight = GetSystemMetrics(SM_CYCAPTION) + 2 * GetSystemMetrics(SM_CYFRAME) + 480;
+
+  uint uWinCenteredPosX = (uDesktopWidth - uTotalWinWidth) / 2;
+  uint uWinCenteredPosY = (uDesktopHeight - uTotalWinHeight) / 2;
+
+  uWindowX = ReadWindowsRegistryInt("window X", uWinCenteredPosX);
+  uWindowX = 0;
+  WriteWindowsRegistryInt("window X", uWindowX);
+
+  uWindowY = ReadWindowsRegistryInt("window Y", uWinCenteredPosY);
+  uWindowY = 0;
+  WriteWindowsRegistryInt("window Y", uWindowY);
+
+  hWnd = CreateWindowExW(0, wcxw.lpszClassName, L"Might and Magic® VII",
+                         uWindowStyle = WS_SYSMENU | WS_GROUP | WS_DLGFRAME | WS_BORDER,
+                         uWindowX, uWindowY,
+                         640, 480,
+                         nullptr,
+                         hOSMenu = nullptr,
+                         wcxw.hInstance,
+                         nullptr);
+  SetWindowTextW(hWnd, L"Might and Magic® VII");
+
+  SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+
+  pRenderer = Render::Create();
+  if (!pRenderer)
+  {
+    Log::Warning(L"Render creation failed");
+    return false;
+  }
+  else
+  {
+    bool bWindowMode = ReadWindowsRegistryInt("startinwindow", false);
+    uint uDefaultDevice = ReadWindowsRegistryInt("D3D Device", 1);
+    bool bColoredLights = ReadWindowsRegistryInt("Colored Lights", false);
+    uint uLevelOfDetail = ReadWindowsRegistryInt("Detail Level", 1);
+    uint bTinting = ReadWindowsRegistryInt("Tinting", 1) != 0;
+
+    if (!pRenderer->Initialize(bWindowMode, uDefaultDevice, bColoredLights, uLevelOfDetail, bTinting))
+    {
+      Log::Warning(L"Render failed to initialize");
+      return false;
+    }
+  }
+
+  pAllocator = Allocator::Create();
+  if (!pAllocator->Initialize(26 * 1024))
+  {
+    MessageBoxW(nullptr,
+                L"Unable to Allocate 26Mb of RAM",
+                L"More RAM Memory Required", MB_ICONEXCLAMATION);
+    return false;
+  }
+  
+
+  pParty = new Party;
+  pParty->uWalkSpeed = GetPrivateProfileIntW(L"debug", L"walkspeed", 384, pMM6IniFile);
+  pParty->uDefaultEyelevel = GetPrivateProfileIntW(L"party", L"eyelevel", 160, pMM6IniFile);
+  pParty->sEyelevel = pParty->uDefaultEyelevel;
+  pParty->uDefaultPartyHeight = GetPrivateProfileIntW(L"party", L"height", 192, pMM6IniFile);
+  pParty->uPartyHeight = pParty->uDefaultPartyHeight;
+  
+  bUseRegistry = GetPrivateProfileIntW(L"settings", L"registry", 1, pMM6IniFile);
+  MM6_Initialize(pMM6IniFile);
+
+  pKeyActionMap = new KeyboardActionMapping;
+
+  pEventTimer = Timer::Create();
+  pEventTimer->Initialize();
+
+  OnTimer(1);
+  GameUI_StatusBar_UpdateTimedString(1);
+  pGame = Game::Create();
+  pMouse = pGame->pMouseInstance;
+  
+
+  RECT rcWindow;
+  GetWindowRect(hWnd, &rcWindow);
+
+  RECT rcClient;
+  GetClientRect(hWnd, &rcClient);
+  uWindowWidth = rcClient.left - rcClient.right - rcWindow.left + rcWindow.right + 640;
+  uWindowHeight = rcClient.top - rcClient.bottom - rcWindow.top + rcWindow.bottom + 480;
+  MoveWindow(hWnd, uWindowX, uWindowY,
+    rcClient.left - rcClient.right - rcWindow.left + rcWindow.right + 640,
+    rcClient.top - rcClient.bottom - rcWindow.top + rcWindow.bottom + 480, 0);
+  ShowWindow(hWnd, SW_SHOWNORMAL);
+
+  pIcons_LOD = new LODFile_IconsBitmaps;
+  if (!pIcons_LOD->LoadIconsOrEvents("data\\icons.lod"))
+  {
+    MessageBoxW(nullptr,
+                L"Some files are missing\n\nPlease Reinstall.",
+                L"Files Missing", MB_ICONEXCLAMATION);
+    return false;
+  }
+  pIcons_LOD->dword_011BA4 = 0;
+  
+  pEvents_LOD = new LODFile_IconsBitmaps;
+  if (!pEvents_LOD->LoadIconsOrEvents("data\\events.lod"))
+  {
+    MessageBoxW(nullptr,
+                L"Some files are missing\n\nPlease Reinstall.",
+                L"Files Missing", MB_ICONEXCLAMATION);
+    return false;
+  }
+
+  InitializeGameText();
+  
+  pBitmaps_LOD = new LODFile_IconsBitmaps;
+  if (!pBitmaps_LOD->LoadBitmaps("data\\bitmaps.lod"))
+  {
+    MessageBoxA(nullptr,
+                pGlobalTXT_LocalizationStrings[63],
+                pGlobalTXT_LocalizationStrings[184], MB_ICONEXCLAMATION);
+    return false;
+  }
+
+  if (bUseRegistry)
+    bUseLoResSprites = ReadWindowsRegistryInt("resolution", 0);
+  else
+    bUseLoResSprites = GetPrivateProfileIntW(L"settings", L"resolution", 0, pMM6IniFile);
+
+  const char *pSpritesFile = nullptr;
+  if (bUseLoResSprites)
+    pSpritesFile = "data\\spriteLO.lod";
+  else
+    pSpritesFile = "data\\sprites.lod";
+
+  pSprites_LOD = new LODFile_Sprites;
+  if (!pSprites_LOD->LoadSprites(pSpritesFile))
+  {
+    MessageBoxA(nullptr,
+                pGlobalTXT_LocalizationStrings[63],
+                pGlobalTXT_LocalizationStrings[184], MB_ICONEXCLAMATION);
+    return false;
+  }
+
+  if (bDebugResouces)
+  {
+    pSpriteFrameTable = new SpriteFrameTable;
+    if (!pSpriteFrameTable->FromFileTxt("data\\sft.txt"))
+      Abortf("Unable to open sft.txt");
+
+    pDecorationList = new DecorationList;
+    if (!pDecorationList->FromFileTxt("data\\declist.txt"))
+      Abortf("Unable to open declist.txt");
+
+    pObjectList = new ObjectList;
+    if (!pObjectList->FromFileTxt("data\\objlist.txt"))
+      Abortf("Unable to open objlist.txt");
+
+    pMonsterList = new MonsterList;
+    if (!pMonsterList->FromFileTxt("data\\monlist.txt"))
+      Abortf("Unable to open monlist.txt");
+
+    pIconsFrameTable = new IconFrameTable;
+    if (!pIconsFrameTable->FromFileTxt("data\\ift.txt"))
+      Abortf("Unable to open ift.txt");
+
+    pTextureFrameTable = new TextureFrameTable;
+    if (!pTextureFrameTable->FromFileTxt("data\\tft.def"))
+      Abortf("Unable to open tft.def");
+
+    pTileTable = new TileTable;
+    if (!pTileTable->FromFileTxt("data\\tile.def"))
+      Abortf("Unable to open tile.def");
+
+    pPlayerFrameTable = new PlayerFrameTable;
+    if (!pPlayerFrameTable->FromFileTxt("data\\pft.def"))
+      Abortf("Unable to open pft.def");
+
+    pChestList = new ChestList;
+    if (!pChestList->FromFileTxt("data\\chest.def"))
+      Abortf("Unable to open chest.def");
+
+    pOverlayList = new OverlayList;
+    if (!pOverlayList->FromFileTxt("data\\overlay.def"))
+      Abortf("Unable to open overlay.def");
+
+    pSoundList = new SoundList;
+    if (!pSoundList->FromFileTxt("data\\sounds.def"))
+      Abortf("Unable to open sounds.def");
+  }
+  else
+  {
+    auto pSFT = pEvents_LOD->LoadRaw("dsft.bin", 1);
+    pSpriteFrameTable = new SpriteFrameTable;
+    pSpriteFrameTable->FromFile(pSFT);
+    free(pSFT);
+
+    auto pTFT = pEvents_LOD->LoadRaw("dtft.bin", 1);
+    pTextureFrameTable = new TextureFrameTable;
+    pTextureFrameTable->FromFile(pTFT);
+    free(pTFT);
+
+    auto pTiles = pEvents_LOD->LoadRaw("dtile.bin", 1);
+    pTileTable = new TileTable;
+    pTileTable->FromFile(pTiles);
+    free(pTiles);
+
+    auto pPFT = pEvents_LOD->LoadRaw("dpft.bin", 1);
+    pPlayerFrameTable = new PlayerFrameTable;
+    pPlayerFrameTable->FromFile(pPFT);
+    free(pPFT);
+
+    auto pIFT = pEvents_LOD->LoadRaw("dift.bin", 1);
+    pIconsFrameTable = new IconFrameTable;
+    pIconsFrameTable->FromFile(pIFT);
+    free(pIFT);
+
+    auto pDecs = pEvents_LOD->LoadRaw("ddeclist.bin", 1);
+    pDecorationList = new DecorationList;
+    pDecorationList->FromFile(pDecs);
+    free(pDecs);
+
+    auto pObjs = pEvents_LOD->LoadRaw("dobjlist.bin", 1);
+    pObjectList = new ObjectList;
+    pObjectList->FromFile(pObjs);
+    free(pObjs);
+
+    auto pMons = pEvents_LOD->LoadRaw("dmonlist.bin", 1);
+    pMonsterList = new MonsterList;
+    pMonsterList->FromFile(pMons);
+    free(pMons);
+
+    auto pChests = pEvents_LOD->LoadRaw("dchest.bin", 1);
+    pChestList = new ChestList;
+    pChestList->FromFile(pChests);
+    free(pChests);
+
+    auto pOverlays = pEvents_LOD->LoadRaw("doverlay.bin", 1);
+    pOverlayList = new OverlayList;
+    pOverlayList->FromFile(pOverlays);
+    free(pOverlays);
+
+    auto pSounds = pEvents_LOD->LoadRaw("dsounds.bin", 1);
+    pSoundList = new SoundList;
+    pSoundList->FromFile(pSounds);
+    free(pSounds);
+  }
+
+
+  if (bDebugResouces)
+  {
+    pSpriteFrameTable->ToFile();
+    pDecorationList->ToFile();
+    pObjectList->ToFile();
+    pMonsterList->ToFile();
+    pIconsFrameTable->ToFile();
+    pTextureFrameTable->ToFile();
+    pTileTable->ToFile();
+    pPlayerFrameTable->ToFile();
+    pChestList->ToFile();
+    pOverlayList->ToFile();
+    pSoundList->ToFile();
+  }
+
+
+  if (dword_6BE364_game_settings_1 & 2 || !(dword_6BE368_debug_settings_2 & 1))// 
+                                                //   color depth != 16
+                                                // or
+                                                //   not in window
+  {
+    SetMenu(hWnd, 0);
+    SetWindowLongA(hWnd, GWL_EXSTYLE, 0);
+    SetWindowLongA(hWnd, GWL_STYLE, WS_VISIBLE);
+    if (pAsyncMouse)
+      pAsyncMouse->Clip();
+    pRenderer->InitializeFullscreen(hWnd);
+  }
+  else
+  {
+    ClipCursor(nullptr);
+    pRenderer->SwitchToWindow(hWnd);
+  }
+
+  uSoundVolumeMultiplier = ReadWindowsRegistryInt("soundflag", 9);
+  if (uSoundVolumeMultiplier > 9)
+    uSoundVolumeMultiplier = 9;
+  uMusicVolimeMultiplier = ReadWindowsRegistryInt("musicflag", 9);
+  if (uMusicVolimeMultiplier > 9)
+    uMusicVolimeMultiplier = 9;
+  uVoicesVolumeMultiplier = ReadWindowsRegistryInt("CharVoices", 9);
+  if (uVoicesVolumeMultiplier > 9)
+    uVoicesVolumeMultiplier = 9;
+  bShowDamage = ReadWindowsRegistryInt("ShowDamage", 1) != 0;
+  byte_6BE388_graphicsmode = ReadWindowsRegistryInt("graphicsmode", 1);
+  if (byte_6BE388_graphicsmode < 0 || byte_6BE388_graphicsmode > 2)
+    byte_6BE388_graphicsmode = 0;
+
+  uGammaPos = ReadWindowsRegistryInt("GammaPos", 4);
+  if (uGammaPos < 0 || uGammaPos > 9)
+    uGammaPos = 4;
+  pGame->pGammaController->Initialize(uGammaPos * 0.1 + 0.6);
+
+  if ( ReadWindowsRegistryInt("Bloodsplats", 1) )
+    pGame->uFlags2 |= 0x20u;
+  else
+    pGame->uFlags2 &= 0xFFFFFFDFu;
+
+  uTurnSpeed = ReadWindowsRegistryInt("TurnDelta", 0);
+  dword_6BE384_2dacceloff = ReadWindowsRegistryInt("2dacceloff", 0);
+
+  if (!bNoSound)
+    pAudioPlayer->Initialize(hWnd);
+
+  pVideoPlayer = new VideoPlayer;
+  pVideoPlayer->Initialize();
+
+  dword_6BE364_game_settings_1 |= 0x4000;
+
+  if ( uTurnSpeed )
+  {
+    switch ( uTurnSpeed )
+    {
+      case 1u:
+        uTurnSpeed = 128;
+        break;
+      case 2u:
+        uTurnSpeed = 64;
+        break;
+      case 3u:
+        uTurnSpeed = 0;
+        break;
+    }
+  }
+  else
+  {
+    uTurnSpeed = (unsigned int)uCPUSpeed < 0xC7 ? 128 : 64;
+  }
+  return true;
+}
+
+
+
+
+//----- (00465D0B) --------------------------------------------------------
+void __cdecl SecondaryInitialization()
+{
+  __int16 v4; // ax@4
+  signed int v5; // esi@5
+  int v6; // ecx@6
+  int v7; // edx@7
+  ObjectDesc *v8; // eax@7
+  char pContainer[32]; // [sp+10h] [bp-Ch]@9
+
+  pMouse->Initialize(hWnd);
+  CreateAsyncMouse();
+  CreateAsyncKeyboard();
+
+  pItemsTable = new ItemsTable;
+  pItemsTable->Initialize();
+
+  pBitmaps_LOD->dword_011BA8 = 1;
+  pBitmaps_LOD->SetupPalettes(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);
+  pIcons_LOD->SetupPalettes(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);
+  pPaletteManager->SetColorChannelInfo(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);
+  pPaletteManager->pPalette_mistColor[0] = 128;
+  pPaletteManager->pPalette_mistColor[1] = 128;
+  pPaletteManager->pPalette_mistColor[2] = 128;
+  pPaletteManager->RecalculateAll();
+  pSprites_LOD->field_ECAC = 1;
+  pObjectList->InitializeSprites();
+  pOverlayList->InitializeSprites();
+  if (!bNoSound)
+    pSoundList->Initialize();
+
+  static const char *pUIAnimNames[4] =
+  {
+    "glow03", "glow05",
+    "torchA", "wizeyeA"
+  };
+  static unsigned short _4E98D0[4][4] =
+  {
+    {479, 0, 329, 0},
+    {585, 0, 332, 0},
+    {468, 0,   0, 0},
+    {606, 0,   0, 0}
+  };
+
+
+  for (uint i = 0; i < 4; ++i)
+  {
+    pUIAnims[i]->uIconID = pIconsFrameTable->FindIcon(pUIAnimNames[i]);
+    pIconsFrameTable->InitializeAnimation(pUIAnims[i]->uIconID);
+
+    pUIAnims[i]->uAnimLength = 0;
+    pUIAnims[i]->uAnimTime = 0;
+    pUIAnims[i]->x = _4E98D0[i][0];
+    pUIAnims[i]->y = _4E98D0[i][2];
+  }
+
+  v5 = 0;
+  if ( (signed int)pObjectList->uNumObjects > 0 )
+  {
+    v6 = 0;
+    do
+    {
+      BYTE3(v7) = 0;
+      v8 = &pObjectList->pObjects[v6];
+      ++v6;
+      *(short *)((char *)&v7 + 1) = v8->uParticleTrailColorR;
+      LOBYTE(v7) = v8->uParticleTrailColorG;
+      ++v5;
+      v8->uParticleTrailColor = v8->uParticleTrailColorB | (v7 << 8);
+    }
+    while ( v5 < (signed int)pObjectList->uNumObjects );
+  }
+  flt_6BE3A0 = 0.55000001f;
+  MainMenuUI_Create();
+  pGame->pStru6Instance->LoadAnimations();
+
+  for (uint i = 0; i < 7; ++i)
+  {
+    sprintf(pContainer, "HDWTR%03u", i);
+    pRenderer->pHDWaterBitmapIDs[i] = pBitmaps_LOD->LoadTexture(pContainer);
+  }
+
+  pNPCStats = new NPCStats;
+  pNPCStats->Initialize();
+
+  Initialize_GlobalEVT();
+  pBitmaps_LOD->dword_11B80 = pBitmaps_LOD->uNumLoadedFiles;
+  if ( pBitmaps_LOD->dword_11B84 < (signed int)pBitmaps_LOD->uNumLoadedFiles )
+    pBitmaps_LOD->dword_11B84 = pBitmaps_LOD->uNumLoadedFiles;
+  pSprites_LOD->field_ECA4 = pSprites_LOD->uNumLoadedSprites;
+  if ( pSprites_LOD->field_ECA0 < (signed int)pSprites_LOD->uNumLoadedSprites )
+    pSprites_LOD->field_ECA0 = pSprites_LOD->uNumLoadedSprites;
+  pPaletteManager->LockAll();
+
+  _mkdir("Saves");
+  for (uint i = 0; i < 5; ++i)
+    for (uint j = 0; j < 6; ++j)
+    {
+      sprintf(pTmpBuf, "data\\lloyd%d%d.pcx", i, j);
+      remove(pTmpBuf);
+    }
+  /*do
+  {
+    v11 = 1;
+    do
+    {
+      sprintfex(pTmpBuf, "data\\lloyd%d%d.pcx", v10, v11);
+      remove(pTmpBuf);
+      ++v11;
+    }
+    while ( v11 < 6 );
+    ++v10;
+  }
+  while ( v10 < 5 );*/
+
+  Initialize_GamesLOD_NewLOD();
+  dword_576E2C = 512;
+  dword_576E28 = 9;
+}
+
+
+
+
+
+
+
+
+
+//----- (00462C94) --------------------------------------------------------
+bool MM_Main(const wchar_t *pCmdLine)
+{
+  HWND hPrevWnd; // eax@1
+  HWND hPrevWnd_; // esi@1
+  HWND v6; // eax@4
+  int v8; // eax@15
+  //bool v9; // edx@16
+  //OtherOverlay *v10; // esi@44
+  //signed int v11; // edi@44
+  unsigned int v12; // ecx@56
+  HANDLE v13; // eax@68
+  unsigned int startms; // [sp+8h] [bp-24h]@55
+  RECT Rect; // [sp+Ch] [bp-20h]@15
+  int a2[4]; // [sp+1Ch] [bp-10h]@15
+
+  auto mm7text_dll = LoadLibraryW(L"mm7text.dll");
+  sprintfex = (int (__cdecl *)(char *a1, const char *a2, ...))GetProcAddress(mm7text_dll, "_sprintfex");
+
+  if (pCmdLine && *pCmdLine)
+  {
+    if (wcsstr(pCmdLine, L"-usedefs"))
+      bDebugResouces = 1;
+    if (wcsstr(pCmdLine, L"-window"))
+      dword_6BE368_debug_settings_2 |= 1u;
+
+    if (wcsstr(pCmdLine, L"-nointro"))
+      bNoIntro = true;//dword_6BE364_game_settings_1 |= 4;
+    if (wcsstr(pCmdLine, L"-nologo"))
+      bNoLogo = true;//dword_6BE364_game_settings_1 |= 8;
+    if (wcsstr(pCmdLine, L"-nosound"))
+      bNoSound = true; //dword_6BE364_game_settings_1 |= 0x10;
+
+    bWalkSound = ReadWindowsRegistryInt("WalkSound", 1) != 0;
+    if (wcsstr(pCmdLine, L"-nowalksound"))
+      bWalkSound = false;//dword_6BE364_game_settings_1 |= 0x20;
+    if (wcsstr(pCmdLine, L"-noanim"))
+    {
+      dword_6BE364_game_settings_1 |= 0x40;
+      bNoVideo = true;
+    }
+    if (wcsstr(pCmdLine, L"-nocd"))
+      bNoCD = true;
+  }
+  stru_51076C.registry_debug_flags = ReadWindowsRegistryInt("debug flags", 0);
+
+
+  v8 = sub_4AC1C9(0, (Vec4_int_ *)a2);
+  Rect.left = *(int *)v8;
+  Rect.top = *(int *)(v8 + 4);
+  Rect.right = *(int *)(v8 + 8);
+  Rect.bottom = *(int *)(v8 + 12);
+  uCPUSpeed = Rect.bottom;
+  
+  if (MM7_Initialize())
+  {
+    Log::Warning(L"MM init: ok");
+
+    pEventTimer->Pause();
+    if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
+    {
+      SetWindowPos(hWnd, (HWND)((int)HWND_MESSAGE|0x2), 320, 240, 640, 480, 0);
+      Rect.left = 325;
+      Rect.top = 245;
+      Rect.right = 326;
+      Rect.bottom = 246;
+      ClipCursor(&Rect);
+    }
+    SetUserInterface(1, false);
+    ShowIntroVideo_and_LoadingScreen();
+    WriteWindowsRegistryInt("Ran once", 1);
+    dword_6BE364_game_settings_1 |= 0x4000;
+    pGame->InitializeGammaController();
+    SecondaryInitialization();
+    pRenderer->Clip_v2(0, 0, 639u, 479u);
+    FinalInitialization();
+
+    Log::Warning(L"MM: entering main loop");
+    while ( 1 )
+    {
+      MainMenu_Loop(); // ïðîðèñîâêà Ãëàâíîãî ìåíþ è òóò æå ïðîðèñîâêà ìåíþ Çàãðóçêà
+      uGameState = 0;
+//LABEL_21:
+      while ( 1 )
+      {
+        switch (uGameState)
+        {
+          case GAME_FINISHED: // âûõîä èç èãðû
+            pGame->Deinitialize();
+            return true; // âûõîä èç ôóíêöèè MM_Main â Win_Main
+        }
+        if (GetCurrentMenuID() == MENU_FINISHED) // ìåíþ Âûõîä
+        {
+          uGameState = GAME_FINISHED;
+          continue; // â íà÷àëî öèêëà
+        }
+        if (GetCurrentMenuID() == MENU_NEWGAME)                // ìåíþ Íîâàÿ èãðà
+        {
+          if ( pAudioPlayer->hAILRedbook )
+            AIL_redbook_stop(pAudioPlayer->hAILRedbook);      // îñòàíîâèòü ìóçûêó
+          pParty->Reset();                                    // ñáðîñ ãðóïïû
+          for (uint k = 0; k < 50; ++k)
+            pOtherOverlayList->pOverlays[k].Reset();
+          strcpy(pCurrentMapName, pStartingMapName);         // òåêóùàÿ êàðòà
+          pParty->CreateDefaultParty(0);                     // ñîçäàòü ãðóïïó ïî óìîë÷àíèþ
+          PlayerCreationUI_Initialize();
+          if ( PlayerCreationUI_Loop() )                    //ïðîöåññ ñîçäàíèÿ ãðóïïû
+          {
+            DeleteCCharFont();
+            break;// âûõîä èç öèêëà
+          }
+          DeleteCCharFont();
+          bFlashQuestBook = true;
+          pGame->pCShow->PlayMovie(MOVIE_Emerald, 0);       //çàñòàâêà
+          Autosave();                                       //àâòîñîõðàíåíèå
+          //goto LABEL_48;
+          pGame->Loop(); // ïðîöåññ èãðû
+          break; // âûõîä èç öèêëà
+        }
+        if (GetCurrentMenuID() == MENU_CREDITS) // ìåíþ Ñîçäàòåëè
+        {
+         if ( pAudioPlayer->hAILRedbook )
+          AIL_redbook_stop(pAudioPlayer->hAILRedbook);// îòêëþ÷èòü çâóê
+         extern MENU_STATE __cdecl CreditsMenu__Loop();
+         CreditsMenu__Loop(); // ïðîöåññ âîñïðîèçâåäåíèÿ îêíà Ñîçäàòåëè
+         break;
+        }
+        if (GetCurrentMenuID() == MENU_5 || GetCurrentMenuID() == MENU_LOAD) //??? íåèçâåñòíî ÷òî ýòî
+          __debugbreak();
+        /*{
+          uGameState = 0;
+        }*/
+        else
+         __debugbreak();// ïîêà áðÿêïîèíòû
+        /*{
+          if (GetCurrentMenuID() != MENU_10)
+            goto LABEL_49;
+          pMouse->Activate(0);
+          if (pAsyncMouse)
+            pAsyncMouse->Suspend();
+          if ( LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) && pAsyncKeyboard )
+            pAsyncKeyboard->Suspend();
+          pParty->Reset();
+          pParty->CreateDefaultParty(1);
+          crt_init_globals_46271C();
+          extern OPENFILENAMEA ofn;
+          if ( !GetOpenFileNameA((LPOPENFILENAMEA)&ofn) )
+          {
+            pMouse->Activate(1);
+            if (pAsyncMouse)
+              pAsyncMouse->Resume();
+            if ( LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) && pAsyncKeyboard )
+              pAsyncKeyboard->Resume();
+            break;
+          }
+          _chdir("..\\");
+          strcpy(pCurrentMapName, ofn.lpstrFileTitle);
+          pMouse->Activate(1);
+          if (pAsyncMouse)
+            pAsyncMouse->Resume();
+          if ( LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) && pAsyncKeyboard )
+            pAsyncKeyboard->Resume();
+        }
+//LABEL_48:
+//        pGame->Loop(); //game
+LABEL_49:*/
+        if ( uGameState == 3 )
+          __debugbreak();
+        /*{
+          v12 = 5;
+          SetCurrentMenuID((MENU_STATE)v12);
+          //goto LABEL_21;
+          uGameState = 0;
+          continue;
+        }*/
+        if ( uGameState == 4 )
+          __debugbreak();
+        /*{
+          v12 = 1;
+          SetCurrentMenuID((MENU_STATE)v12);
+          //goto LABEL_21;
+          uGameState = 0;
+          continue;
+        }*/
+        if ( uGameState == 7 )
+          __debugbreak();
+        /*{
+          pAudioPlayer->StopChannels(-1, -1);
+          uGameState = 0;
+          break;
+        }*/
+      }
+      if (!bNoSound && pAudioPlayer->hAILRedbook)
+      {
+        pAudioPlayer->SetMusicVolume((pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0));
+        AIL_redbook_stop(pAudioPlayer->hAILRedbook);
+        unsigned int end_ms;
+        AIL_redbook_track_info(pAudioPlayer->hAILRedbook, 0xE, &startms, &end_ms);
+        AIL_redbook_play(pAudioPlayer->hAILRedbook, startms + 1, end_ms);
+      }
+    }
+  }
+  else
+  Log::Warning(L"MM init: failed");
+  pGame->Deinitialize();
+}
+
+
+
+
+
+//----- (004637E0) --------------------------------------------------------
+char __cdecl sub_4637E0_is_there_popup_onscreen()
+{
+  return dword_507BF0_is_there_popup_onscreen == 1;
+}
+// 507BF0: using guessed type int dword_507BF0_is_there_popup_onscreen;
+
+
+
+//----- (00465F5A) --------------------------------------------------------
+void __cdecl CreateAsyncMouse()
+{
+  LOG_DECOMPILATION_WARNING();
+  /*
+  if (!pAsyncMouse &&
+      pRenderer->bUserDirect3D &&
+      pRenderer->uAcquiredDirect3DDevice == 1)
+  {
+    pAsyncMouse = new AsyncMouse(&pRenderer->pDirectDraw4);
+    if (pAsyncMouse)
+      pAsyncMouse->Resume();
+  }*/
+}
+
+//----- (00465FF0) --------------------------------------------------------
+void __cdecl CreateAsyncKeyboard()
+{
+  LOG_DECOMPILATION_WARNING();
+  /*
+  if (!pAsyncKeyboard &&
+      pGame->pKeyboardInstance->bUsingAsynKeyboard)
+  {
+    pAsyncKeyboard = new AsyncKeyboard;
+    if (pAsyncKeyboard)
+      pAsyncKeyboard->Resume();
+  }*/
+}
+
+//----- (00466082) --------------------------------------------------------
+void MM6_Initialize(const wchar_t *pIniFilename)
+{
+  //int v0; // eax@1
+  UINT v1; // eax@18
+  size_t v2; // eax@31
+  size_t v3; // ebx@32
+  size_t v4; // edi@36
+  //char v5[120]; // [sp+Ch] [bp-17Ch]@1
+  //char String[120]; // [sp+84h] [bp-104h]@32
+  char pDefaultGroundTexture[16]; // [sp+FCh] [bp-8Ch]@32
+  //char pIniFilename[120]; // [sp+10Ch] [bp-7Ch]@1
+  unsigned int v9; // [sp+184h] [bp-4h]@28
+
+  //_getcwd(v5, 120);
+  //sprintfex(pIniFilename, "%s\\mm6.ini", v5);
+  viewparams = new ViewingParams;
+  viewparams->uScreenX = GetPrivateProfileIntW(L"screen", L"vx1", 8, pIniFilename);
+  viewparams->uScreenY = GetPrivateProfileIntW(L"screen", L"vy1", 8, pIniFilename);
+  viewparams->uScreenZ = GetPrivateProfileIntW(L"screen", L"vx2", 468, pIniFilename);
+  viewparams->uScreenW = GetPrivateProfileIntW(L"screen", L"vy2", 351, pIniFilename);
+
+
+  pAudioPlayer = new AudioPlayer;
+  pAudioPlayer->uMixerChannels = GetPrivateProfileIntW(L"settings", L"mixerchannels", 16, pIniFilename);
+  if ( pAudioPlayer->uMixerChannels > 16 )
+    pAudioPlayer->uMixerChannels = 16;
+
+
+  if (GetPrivateProfileIntW(L"debug", L"nomonster", 0, pIniFilename))
+    dword_6BE368_debug_settings_2 |= 4;
+  if (bUseRegistry)
+    v1 = ReadWindowsRegistryInt("startinwindow", 0);
+  else
+    v1 = GetPrivateProfileIntW(L"debug", L"startinwindow", 0, pIniFilename);
+  if (v1)
+    dword_6BE368_debug_settings_2 |= 1;
+  if (GetPrivateProfileIntW(L"debug", L"showFR", 0, pIniFilename))
+    dword_6BE368_debug_settings_2 |= 2;
+  if (GetPrivateProfileIntW(L"debug", L"nodamage", 0, pIniFilename))
+    dword_6BE368_debug_settings_2 |= 0x10;
+  if (GetPrivateProfileIntW(L"debug", L"nodecoration", 0, pIniFilename))
+    dword_6BE368_debug_settings_2 |= 8;
+
+  wchar_t pStartingMapNameW[1024];
+  GetPrivateProfileStringW(L"file", L"startmap", L"out01.odm", pStartingMapNameW, 0x20u, pIniFilename);
+  sprintf(pStartingMapName, "%S", pStartingMapNameW);
+
+  v9 = 0;
+  if ( strlen(pStartingMapName) )
+  {
+    do
+    {
+      if ( pStartingMapName[v9] == 32 )
+        pStartingMapName[v9] = 0;
+      ++v9;
+      v2 = strlen(pStartingMapName);
+    }
+    while ( v9 < v2 );
+  }
+
+  pOutdoorCamera = new OutdoorCamera;
+  outdoor_day_top_r      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.r", 81, pIniFilename);
+  outdoor_day_top_g      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.g", 121, pIniFilename);
+  outdoor_day_top_b      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.b", 236, pIniFilename);
+  outdoor_day_bottom_r   = GetPrivateProfileIntW(L"outdoor", L"RGBDayBottom.r", 153, pIniFilename);
+  outdoor_day_bottom_g   = GetPrivateProfileIntW(L"outdoor", L"RGBDayBottom.g", 193, pIniFilename);
+  outdoor_day_bottom_b   = GetPrivateProfileIntW(L"outdoor", L"RGBDayBottom.b", 237, pIniFilename);
+  outdoor_night_top_r    = GetPrivateProfileIntW(L"outdoor", L"RGBNightTop.r", 0, pIniFilename);
+  outdoor_night_top_g    = GetPrivateProfileIntW(L"outdoor", L"RGBNightTop.g", 0, pIniFilename);
+  outdoor_night_top_b    = GetPrivateProfileIntW(L"outdoor", L"RGBNightTop.b", 0, pIniFilename);
+  outdoor_night_bottom_r = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.r", 11, pIniFilename);
+  outdoor_night_bottom_g = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.g", 41, pIniFilename);
+  outdoor_night_bottom_b = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.b", 129, pIniFilename);
+  pOutdoorCamera->outdoor_no_mist = GetPrivateProfileIntW(L"debug", L"noMist", 0, pIniFilename);
+  pOutdoorCamera->bNoSky          = GetPrivateProfileIntW(L"outdoor", L"nosky", 0, pIniFilename);
+  pOutdoorCamera->bDoNotRenderDecorations = GetPrivateProfileIntW(L"render", L"nodecorations", 0, pIniFilename);
+  pOutdoorCamera->outdoor_no_wavy_water   = GetPrivateProfileIntW(L"outdoor", L"nowavywater", 0, pIniFilename);
+  outdoor_grid_band_1 = GetPrivateProfileIntW(L"outdoor", L"gridband1", 10, pIniFilename);
+  outdoor_grid_band_2 = GetPrivateProfileIntW(L"outdoor", L"gridband2", 15, pIniFilename);
+  outdoor_grid_band_3 = GetPrivateProfileIntW(L"outdoor", L"gridband3", 25, pIniFilename);
+  pOutdoorCamera->terrain_gamma  = GetPrivateProfileIntW(L"outdoor", L"ter_gamma", 0, pIniFilename);
+  pOutdoorCamera->building_gamme = GetPrivateProfileIntW(L"outdoor", L"bld_gamma", 0, pIniFilename);
+  mipmapping_terrain_mm1  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm1", 2048, pIniFilename);
+  mipmapping_terrain_mm2  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm2", 4096, pIniFilename);
+  mipmapping_terrain_mm3  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm3", 8192, pIniFilename);
+  mipmapping_building_mm1 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm1", 1024, pIniFilename);
+  mipmapping_building_mm2 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm2", 2048, pIniFilename);
+  mipmapping_building_mm3 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm3", 4096, pIniFilename);
+  pOutdoorCamera->shading_dist_shade     = GetPrivateProfileIntW(L"shading", L"dist_shade", 2048, pIniFilename);
+  pOutdoorCamera->shading_dist_shademist = GetPrivateProfileIntW(L"shading", L"dist_shademist", 4096, pIniFilename);
+  pOutdoorCamera->shading_dist_mist      = GetPrivateProfileIntW(L"shading", L"dist_mist", 8192, pIniFilename);
+
+  wchar_t pDefaultSkyTextureW[1024];
+  GetPrivateProfileStringW(L"textures", L"sky", L"plansky1", pDefaultSkyTextureW, 0x10u, pIniFilename);
+  sprintf(pDefaultSkyTexture, "%S", pDefaultSkyTextureW);
+
+  wchar_t pDefaultGroundTextureW[1024];
+  GetPrivateProfileStringW(L"textures", L"default", L"dirt", pDefaultGroundTextureW, 0x10u, pIniFilename);
+  sprintf(pDefaultGroundTexture, "%S", pDefaultGroundTextureW);
+
+  wchar_t pFloat[1024];
+  GetPrivateProfileStringW(L"debug", L"recmod1", L"1.0", pFloat, 0x10u, pIniFilename);
+  swscanf(pFloat, L"%f", &flt_6BE3A4_debug_recmod1);
+
+  GetPrivateProfileStringW(L"debug", L"recmod2", L"1.0", pFloat, 0x10u, pIniFilename);
+  swscanf(pFloat, L"%f", &flt_6BE3A8_debug_recmod2);
+
+  flt_6BE3AC_debug_recmod1_x_1_6 = flt_6BE3A4_debug_recmod1 * 1.666666666666667;
+
+  v3 = 0;
+  if ( strlen(pDefaultSkyTexture) )
+  {
+    do
+    {
+      if ( pDefaultSkyTexture[v3] == ' ' )
+        pDefaultSkyTexture[v3] = 0;
+      ++v3;
+    }
+    while ( v3 < strlen(pDefaultSkyTexture) );
+  }
+  v4 = 0;
+  if ( strlen(pDefaultGroundTexture) )
+  {
+    do
+    {
+      if ( pDefaultGroundTexture[v4] == ' ' )
+        pDefaultGroundTexture[v4] = 0;
+      ++v4;
+    }
+    while ( v4 < strlen(pDefaultGroundTexture) );
+  }
+
+  texmapping_terrain_subdivsize  = GetPrivateProfileIntW(L"texmapping", L"terrain_subdivsize", 16, pIniFilename);
+  texmapping_terrain_subdivpow2  = GetPrivateProfileIntW(L"texmapping", L"terrain_subdivpow2", 4, pIniFilename);
+  texmapping_building_subdivsize = GetPrivateProfileIntW(L"texmapping", L"building_subdivsize", 32, pIniFilename);
+  texmapping_building_subdivpow2 = GetPrivateProfileIntW(L"texmapping", L"building_subdivpow2", 5, pIniFilename);
+
+  MM7Initialization();
+}
+
+//----- (004666D5) --------------------------------------------------------
+void __cdecl MM7Initialization()
+{
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+  {
+    if ( !byte_6BE388_graphicsmode )
+    {
+      outdoor_grid_band_1 = 10;
+      outdoor_grid_band_2 = 15;
+      outdoor_grid_band_3 = 20;
+      pOutdoorCamera->shading_dist_mist = 8192;
+      pOutdoorCamera->bNoSky = 0;
+      LOBYTE(viewparams->field_20) = 0;
+    }
+    mipmapping_terrain_mm1 = 1024;
+    mipmapping_terrain_mm2 = 2048;
+    mipmapping_building_mm1 = 1024;
+    mipmapping_building_mm2 = 2048;
+    pOutdoorCamera->shading_dist_shade = 2048;
+    pOutdoorCamera->terrain_gamma = 0;
+    pOutdoorCamera->building_gamme = 0;
+    mipmapping_terrain_mm3 = 4096;
+    mipmapping_building_mm3 = 4096;
+    pOutdoorCamera->shading_dist_shademist = 4096;
+    pOutdoorCamera->outdoor_no_wavy_water = 0;
+    sub_47F4D3(outdoor_grid_band_1, outdoor_grid_band_2, outdoor_grid_band_3);
+  }
+  else
+  {
+    LOBYTE(viewparams->field_20) = 0;
+  }
+  pParty->uFlags |= 2u;
+  viewparams->uSomeY = viewparams->uScreenY;
+  viewparams->uSomeX = viewparams->uScreenX;
+  viewparams->uSomeZ = viewparams->uScreenZ;
+  viewparams->uSomeW = viewparams->uScreenW;
+
+  pViewport->SetScreen(viewparams->uScreenX, viewparams->uScreenY, viewparams->uScreenZ, viewparams->uScreenW);
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+    pOutdoorCamera->_485F64();
+}
+
+
+//----- (00466B8C) --------------------------------------------------------
+int __cdecl AbortWithError()
+{
+  if ( !aborting_app )
+  {
+    ClipCursor(0);
+    aborting_app = 1;
+    if ( !pRenderer->bWindowMode )
+      pRenderer->ChangeBetweenWinFullscreenModes();
+    if ( MessageBoxA(0, pGlobalTXT_LocalizationStrings[176], pGlobalTXT_LocalizationStrings[59], 0x34u) == 6 )
+      SaveGame(1, 0);                           // "Internal Error"
+                                                // "Might and Magic VII has detected an internal error and will be forced to close.  Would you like us to autosave your game before closing?"
+    Game_DeinitializeAndTerminate(1);
+  }
+  return 0;
+}
+// 720018: using guessed type int aborting_app;
+
+//----- (00466BE5) --------------------------------------------------------
+void Abortf(const char *Format, ...)
+{
+  va_list va; // [sp+8h] [bp+8h]@1
+
+  va_start(va, Format);
+  if ( !pRenderer->bWindowMode )
+    pRenderer->ChangeBetweenWinFullscreenModes();
+  vsprintf(pTmpBuf, Format, va);
+  if ( pMouse )
+    pMouse->Activate(0);
+  ClipCursor(0);
+  MessageBoxA(0, pTmpBuf, "Error", 0x30u);
+  Game_DeinitializeAndTerminate(1);
+}
+
+//----- (00466C40) --------------------------------------------------------
+const wchar_t *MENU_STATE_to_string(MENU_STATE m)
+{
+  switch (m)
+  {
+    case -1:               return L"-1";
+    case MENU_MAIN:        return L"MENU_MAIN";
+    case MENU_NEWGAME:     return L"MENU_NEWGAME";
+    case MENU_CREDITS:     return L"MENU_CREDITS";
+    case MENU_SAVELOAD:    return L"MENU_SAVELOAD";
+    case MENU_FINISHED:    return L"MENU_FINISHED";
+    case MENU_5:           return L"MENU_5";
+    case MENU_CREATEPARTY: return L"MENU_CREATEPARTY";
+    case MENU_7:           return L"MENU_7";
+    case MENU_Credits:     return L"MENU_Credits";
+    case MENU_LOAD:        return L"MENU_LOAD";
+    case MENU_10:          return L"MENU_10";
+    default:               return L"unk";
+  };
+};
+void SetCurrentMenuID(MENU_STATE uMenu)
+{
+  if ((int)uCurrentMenuID != -1)
+  {
+    if (pGame->pKeyboardInstance->bUsingAsynKeyboard && pAsyncKeyboard)
+      pAsyncKeyboard->Resume();
+  }
+  uCurrentMenuID = uMenu;
+
+  Log::Warning(L"CurrentMenu = %s", MENU_STATE_to_string(uMenu));
+}
+
+//----- (00466CA0) --------------------------------------------------------
+MENU_STATE GetCurrentMenuID()
+{
+  return uCurrentMenuID;
+}
+
+
+
+
+
+/*
+    v17 = 0;
+    if ( v4 > -2005532222 )
+    {
+      switch ( v4 + 2005532212 )
+      {
+        case 0:
+          v7 = "DDERR_SURFACENOTATTACHED";
+          goto LABEL_173;
+        case 10:
+          v7 = "DDERR_TOOBIGHEIGHT";
+          goto LABEL_173;
+        case 20:
+          v7 = "DDERR_TOOBIGSIZE";
+          goto LABEL_173;
+        case 30:
+          v7 = "DDERR_TOOBIGWIDTH";
+          goto LABEL_173;
+        case 50:
+          v7 = "DDERR_UNSUPPORTEDFORMAT";
+          goto LABEL_173;
+        case 60:
+          v7 = "DDERR_UNSUPPORTEDMASK";
+          goto LABEL_173;
+        case 61:
+          v7 = "DDERR_INVALIDSTREAM";
+          goto LABEL_173;
+        case 77:
+          v7 = "DDERR_VERTICALBLANKINPROGRESS";
+          goto LABEL_173;
+        case 80:
+          v7 = "DDERR_WASSTILLDRAWING";
+          goto LABEL_173;
+        case 100:
+          v7 = "DDERR_XALIGN";
+          goto LABEL_173;
+        case 101:
+          v7 = "DDERR_INVALIDDIRECTDRAWGUID";
+          goto LABEL_173;
+        case 102:
+          v7 = "DDERR_DIRECTDRAWALREADYCREATED";
+          goto LABEL_173;
+        case 103:
+          v7 = "DDERR_NODIRECTDRAWHW";
+          goto LABEL_173;
+        case 104:
+          v7 = "DDERR_PRIMARYSURFACEALREADYEXISTS";
+          goto LABEL_173;
+        case 105:
+          v7 = "DDERR_NOEMULATION";
+          goto LABEL_173;
+        case 106:
+          v7 = "DDERR_REGIONTOOSMALL";
+          goto LABEL_173;
+        case 107:
+          v7 = "DDERR_CLIPPERISUSINGHWND";
+          goto LABEL_173;
+        case 108:
+          v7 = "DDERR_NOCLIPPERATTACHED";
+          goto LABEL_173;
+        case 109:
+          v7 = "DDERR_NOHWND";
+          goto LABEL_173;
+        case 110:
+          v7 = "DDERR_HWNDSUBCLASSED";
+          goto LABEL_173;
+        case 111:
+          v7 = "DDERR_HWNDALREADYSET";
+          goto LABEL_173;
+        case 112:
+          v7 = "DDERR_NOPALETTEATTACHED";
+          goto LABEL_173;
+        case 113:
+          v7 = "DDERR_NOPALETTEHW";
+          goto LABEL_173;
+        case 114:
+          v7 = "DDERR_BLTFASTCANTCLIP";
+          goto LABEL_173;
+        case 115:
+          v7 = "DDERR_NOBLTHW";
+          goto LABEL_173;
+        case 116:
+          v7 = "DDERR_NODDROPSHW";
+          goto LABEL_173;
+        case 117:
+          v7 = "DDERR_OVERLAYNOTVISIBLE";
+          goto LABEL_173;
+        case 118:
+          v7 = "DDERR_NOOVERLAYDEST";
+          goto LABEL_173;
+        case 119:
+          v7 = "DDERR_INVALIDPOSITION";
+          goto LABEL_173;
+        case 120:
+          v7 = "DDERR_NOTAOVERLAYSURFACE";
+          goto LABEL_173;
+        case 121:
+          v7 = "DDERR_EXCLUSIVEMODEALREADYSET";
+          goto LABEL_173;
+        case 122:
+          v7 = "DDERR_NOTFLIPPABLE";
+          goto LABEL_173;
+        case 123:
+          v7 = "DDERR_CANTDUPLICATE";
+          goto LABEL_173;
+        case 125:
+          v7 = "DDERR_CANTCREATEDC";
+          goto LABEL_173;
+        case 126:
+          v7 = "DDERR_NODC";
+          goto LABEL_173;
+        case 127:
+          v7 = "DDERR_WRONGMODE";
+          goto LABEL_173;
+        case 128:
+          v7 = "DDERR_IMPLICITLYCREATED";
+          goto LABEL_173;
+        case 129:
+          v7 = "DDERR_NOTPALETTIZED";
+          goto LABEL_173;
+        case 130:
+          v7 = "DDERR_UNSUPPORTEDMODE";
+          goto LABEL_173;
+        case 131:
+          v7 = "DDERR_NOMIPMAPHW";
+          goto LABEL_173;
+        case 132:
+          v7 = "DDERR_INVALIDSURFACETYPE";
+          goto LABEL_173;
+        case 140:
+          v7 = "DDERR_NOOPTIMIZEHW";
+          goto LABEL_173;
+        case 141:
+          v7 = "DDERR_NOTLOADED";
+          goto LABEL_173;
+        case 142:
+          v7 = "DDERR_NOFOCUSWINDOW";
+          goto LABEL_173;
+        case 160:
+          v7 = "DDERR_DCALREADYCREATED";
+          goto LABEL_173;
+        case 170:
+          v7 = "DDERR_NONONLOCALVIDMEM";
+          goto LABEL_173;
+        case 180:
+          v7 = "DDERR_CANTPAGELOCK";
+          goto LABEL_173;
+        case 200:
+          v7 = "DDERR_CANTPAGEUNLOCK";
+          goto LABEL_173;
+        case 220:
+          v7 = "DDERR_NOTPAGELOCKED";
+          goto LABEL_173;
+        case 230:
+          v7 = "DDERR_MOREDATA";
+          goto LABEL_173;
+        case 231:
+          v7 = "DDERR_EXPIRED";
+          goto LABEL_173;
+        case 235:
+          v7 = "DDERR_VIDEONOTACTIVE";
+          goto LABEL_173;
+        case 239:
+          v7 = "DDERR_DEVICEDOESNTOWNSURFACE";
+          goto LABEL_173;
+        default:
+          goto LABEL_174;
+        case 124:
+          goto LABEL_176;
+      }
+      goto LABEL_176;
+    }
+    if ( v4 != -2005532222 )
+    {
+      if ( v4 > -2005532447 )
+      {
+        if ( v4 <= -2005532337 )
+        {
+          if ( v4 == -2005532337 )
+          {
+            v7 = "DDERR_NOVSYNCHW";
+            goto LABEL_173;
+          }
+          if ( v4 > -2005532392 )
+          {
+            if ( v4 == -2005532382 )
+            {
+              v7 = "DDERR_NOROTATIONHW";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532362 )
+            {
+              v7 = "DDERR_NOSTRETCHHW";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532356 )
+            {
+              v7 = "DDERR_NOT4BITCOLOR";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532355 )
+            {
+              v7 = "DDERR_NOT4BITCOLORINDEX";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532352 )
+            {
+              v7 = "DDERR_NOT8BITCOLOR";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532342 )
+            {
+              v7 = "DDERR_NOTEXTUREHW";
+              goto LABEL_173;
+            }
+          }
+          else
+          {
+            if ( v4 == -2005532392 )
+            {
+              v7 = "DDERR_NORASTEROPHW";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532442 )
+            {
+              v7 = "DDERR_NOFLIPHW";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532432 )
+            {
+              v7 = "DDERR_NOGDI";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532422 )
+            {
+              v7 = "DDERR_NOMIRRORHW";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532417 )
+            {
+              v7 = "DDERR_NOTFOUND";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532412 )
+            {
+              v7 = "DDERR_NOOVERLAYHW";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532402 )
+            {
+              v7 = "DDERR_OVERLAPPINGRECTS";
+              goto LABEL_173;
+            }
+          }
+          goto LABEL_174;
+        }
+        if ( v4 <= -2005532285 )
+        {
+          if ( v4 == -2005532285 )
+          {
+            v7 = "DDERR_PALETTEBUSY";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532332 )
+          {
+            v7 = "DDERR_NOZBUFFERHW";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532322 )
+          {
+            v7 = "DDERR_NOZOVERLAYHW";
+            goto LABEL_173;
+          }
+          if ( v4 == DDERR_OUTOFCAPS )
+          {
+            v7 = "DDERR_OUTOFCAPS";
+            goto LABEL_173;
+          }
+          if ( v4 == DDERR_OUTOFVIDEOMEMORY )
+          {
+            v7 = "DDERR_OUTOFVIDEOMEMORY";
+            goto LABEL_173;
+          }
+          if ( v4 == DDERR_OVERLAYCANTCLIP )
+          {
+            v7 = "DDERR_OVERLAYCANTCLIP";
+            goto LABEL_173;
+          }
+          if ( v4 == DDERR_OVERLAYCOLORKEYONLYONEACTIVE )
+          {
+            v7 = "DDERR_OVERLAYCOLORKEYONLYONEACTIVE";
+            goto LABEL_173;
+          }
+          goto LABEL_174;
+        }
+        if ( v4 == -2005532272 )
+        {
+          v7 = "DDERR_COLORKEYNOTSET";
+          goto LABEL_173;
+        }
+        if ( v4 == -2005532262 )
+        {
+          v7 = "DDERR_SURFACEALREADYATTACHED";
+          goto LABEL_173;
+        }
+        if ( v4 == -2005532252 )
+        {
+          v7 = "DDERR_SURFACEALREADYDEPENDENT";
+          goto LABEL_173;
+        }
+        if ( v4 != -2005532242 )
+        {
+          if ( v4 == -2005532237 )
+          {
+            v7 = "DDERR_CANTLOCKSURFACE";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532232 )
+          {
+            v7 = "DDERR_SURFACEISOBSCURED";
+            goto LABEL_173;
+          }
+          goto LABEL_174;
+        }
+      }
+      else
+      {
+        if ( v4 == -2005532447 )
+        {
+          v7 = "DDERR_NOEXCLUSIVEMODE";
+          goto LABEL_173;
+        }
+        if ( v4 <= -2005532562 )
+        {
+          if ( v4 == -2005532562 )
+          {
+            v7 = "DDERR_INVALIDCLIPLIST";
+            goto LABEL_173;
+          }
+          if ( v4 > -2005532662 )
+          {
+            if ( v4 == -2005532652 )
+            {
+              v7 = "DDERR_CANNOTDETACHSURFACE";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532632 )
+            {
+              v7 = "DDERR_CURRENTLYNOTAVAIL";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532617 )
+            {
+              v7 = "DDERR_EXCEPTION";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532582 )
+            {
+              v7 = "DDERR_HEIGHTALIGN";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532577 )
+            {
+              v7 = "DDERR_INCOMPATIBLEPRIMARY";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532572 )
+            {
+              v7 = "DDERR_INVALIDCAPS";
+              goto LABEL_173;
+            }
+          }
+          else
+          {
+            if ( v4 == -2005532662 )
+            {
+              v7 = "DDERR_CANNOTATTACHSURFACE";
+              goto LABEL_173;
+            }
+            if ( v4 == -2147467263 )
+            {
+              v7 = "DDERR_UNSUPPORTED";
+              goto LABEL_173;
+            }
+            if ( v4 == -2147467259 )
+            {
+              v7 = "DDERR_GENERIC";
+              goto LABEL_173;
+            }
+            if ( v4 == -2147221008 )
+            {
+              v7 = "DDERR_NOTINITIALIZED";
+              goto LABEL_173;
+            }
+            if ( v4 == -2147024882 )
+            {
+              v7 = "DDERR_OUTOFMEMORY";
+              goto LABEL_173;
+            }
+            if ( v4 == -2147024809 )
+            {
+              v7 = "DDERR_INVALIDPARAMS";
+              goto LABEL_173;
+            }
+            if ( v4 == -2005532667 )
+            {
+              v7 = "DDERR_ALREADYINITIALIZED";
+LABEL_173:
+              v13 = strlen(v7);
+              v12 = (char *)v7;
+LABEL_175:
+              std::stringoperator_assign__const_char_ptr__(&a1, v12, v13);
+              v13 = a3;
+              pRenderer->field_40110 = 0;
+              v15 = &v11;
+              std::string40E2C8(&v11, Str, (int)((char *)&hr + 3));
+              v10 = 48;
+              LOBYTE(v17) = 1;
+              Str = (char *)&v9;
+              std::string40E2C8(&v9, "Direct Draw Error", (int)((char *)&a3 + 3));
+              LOBYTE(v17) = 0;
+              CheckHRESULT_stru0::ShowMessageBox(v6, &a1, v9, v10, v11, v13);
+              v5 = 1;
+              goto LABEL_176;
+            }
+          }
+LABEL_174:
+          sprintfex(&Src, "Unknown DirectDraw/Direct3D error number %X", v4);
+          v13 = strlen(&Src);
+          v12 = &Src;
+          goto LABEL_175;
+        }
+        if ( v4 > -2005532492 )
+        {
+          if ( v4 == -2005532467 )
+          {
+            v7 = "DDERR_NOCLIPLIST";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532462 )
+          {
+            v7 = "DDERR_NOCOLORCONVHW";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532460 )
+          {
+            v7 = "DDERR_NOCOOPERATIVELEVELSET";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532457 )
+          {
+            v7 = "DDERR_NOCOLORKEY";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532452 )
+          {
+            v7 = "DDERR_NOCOLORKEYHW";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532450 )
+          {
+            v7 = "DDERR_NODIRECTDRAWSUPPORT";
+            goto LABEL_173;
+          }
+          goto LABEL_174;
+        }
+        if ( v4 == -2005532492 )
+        {
+          v7 = "DDERR_NOALPHAHW";
+          goto LABEL_173;
+        }
+        if ( v4 == -2005532552 )
+        {
+          v7 = "DDERR_INVALIDMODE";
+          goto LABEL_173;
+        }
+        if ( v4 == -2005532542 )
+        {
+          v7 = "DDERR_INVALIDOBJECT";
+          goto LABEL_173;
+        }
+        if ( v4 == -2005532527 )
+        {
+          v7 = "DDERR_INVALIDPIXELFORMAT";
+          goto LABEL_173;
+        }
+        if ( v4 != -2005532522 )
+        {
+          if ( v4 == -2005532512 )
+          {
+            v7 = "DDERR_LOCKEDSURFACES";
+            goto LABEL_173;
+          }
+          if ( v4 == -2005532502 )
+          {
+            v7 = "DDERR_NO3D";
+            goto LABEL_173;
+          }
+          goto LABEL_174;
+        }
+      }*/
+
+
+
+//----- (00467D5D) --------------------------------------------------------
+int __thiscall sub_467D5D(int _this)
+{
+  return *(int *)(_this + 7204);
+}
+
+
+
+//----- (00467E7F) --------------------------------------------------------
+void __thiscall sub_467E7F_EquipBody(unsigned int uEquipType)
+{
+  unsigned int v1; // esi@1
+  int v2; // ebx@1
+  Player *v3; // eax@1
+  int v4; // edx@1
+  int v5; // esi@2
+  int v6; // eax@2
+  unsigned int v7; // eax@3
+  ItemGen _this; // [sp+Ch] [bp-30h]@1
+  Player *v9; // [sp+30h] [bp-Ch]@1
+  int v10; // [sp+34h] [bp-8h]@1
+  int *v11; // [sp+38h] [bp-4h]@1
+
+  v1 = uEquipType;
+  _this.Reset();
+  v2 = (unsigned __int8)byte_4E8394[v1 + 4];
+  v3 = pPlayers[uActiveCharacter];
+  v9 = v3;
+  v11 = (int *)((char *)&v3->pEquipment + 4 * v2);
+  v4 = *v11;
+  v10 = *v11;
+  if ( v10 )
+  {
+    memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
+    v5 = (int)((char *)v3 + 4 * (9 * v4 - 9));
+    *(char *)(v5 + 556) = 0;
+    pParty->pPickedItem.Reset();
+    pParty->SetHoldingItem((ItemGen *)(v5 + 532));
+    v6 = v10;
+    _this.uBodyAnchor = v2 + 1;
+    memcpy((void *)(v5 + 532), &_this, 0x24u);
+    *v11 = v6;
+  }
+  else
+  {
+    v7 = v3->FindFreeInventorySlot();
+    if ( (v7 & 0x80000000u) == 0 )
+    {
+      pParty->pPickedItem.uBodyAnchor = v2 + 1;
+      memcpy(&v9->pInventoryItems[v7], &pParty->pPickedItem, sizeof(v9->pInventoryItems[v7]));
+      *v11 = v7 + 1;
+      pMouse->RemoveHoldingItem();
+    }
+  }
+}
+
+//----- (00467F48) --------------------------------------------------------
+void __fastcall sub_467F48(signed int a1)
+{
+  signed int v1; // esi@1
+
+  v1 = a1;
+  if ( !pGUIWindow_ScrollWindow && a1 >= 700 )
+  {
+    if ( a1 <= 782 )
+    {
+      uTextureID_720980 = pIcons_LOD->LoadTexture("leather", TEXTURE_16BIT_PALETTE);
+      pGUIWindow_ScrollWindow = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)30, v1 - 700, 0);
+    }
+  }
+}
+// 720980: using guessed type int uTextureID_720980;
+
+//----- (00467F9F) --------------------------------------------------------
+void __cdecl free_book_subwindow()
+{
+  if ( pGUIWindow_ScrollWindow )
+  {
+    pGUIWindow_ScrollWindow->Release();
+    pGUIWindow_ScrollWindow = 0;
+  }
+}
+
+//----- (00467FB6) --------------------------------------------------------
+char __cdecl sub_467FB6()
+{
+  unsigned int v0; // eax@1
+  char *v1; // ST18_4@3
+  unsigned int v2; // eax@3
+  GUIWindow a1; // [sp+Ch] [bp-54h]@1
+
+  memcpy(&a1, pGUIWindow_ScrollWindow, sizeof(a1));
+  a1.Hint = 0;
+  a1.uFrameX = 1;
+  a1.uFrameY = 1;
+  a1.uFrameWidth = 468;
+  v0 = pFontSmallnum->CalcTextHeight(pScrolls[(unsigned int)pGUIWindow_ScrollWindow->ptr_1C], &a1, 0, 0)
+     + 2 * LOBYTE(pFontCreate->uFontHeight)
+     + 24;
+  a1.uFrameHeight = v0;
+  if ( (signed int)(v0 + a1.uFrameY) > 479 )
+  {
+    v0 = 479 - a1.uFrameY;
+    a1.uFrameHeight = 479 - a1.uFrameY;
+  }
+  a1.uFrameZ = a1.uFrameWidth + a1.uFrameX - 1;
+  a1.uFrameW = v0 + a1.uFrameY - 1;
+  a1.DrawMessageBox(0);
+  a1.uFrameX += 12;
+  a1.uFrameWidth -= 24;
+  a1.uFrameY += 12;
+  a1.uFrameHeight -= 12;
+  a1.uFrameZ = a1.uFrameWidth + a1.uFrameX - 1;
+  a1.uFrameW = a1.uFrameHeight + a1.uFrameY - 1;
+  v1 = pItemsTable->pItems[(unsigned int)pGUIWindow_ScrollWindow->ptr_1C + 700].pName;
+  v2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  sprintf(pTmpBuf, format_4E2D80, v2, v1);
+  a1.DrawTitleText(pFontCreate, 0, 0, 0, pTmpBuf, 3u);
+  return a1.DrawText(
+           pFontSmallnum,
+           1,
+           LOBYTE(pFontCreate->uFontHeight) - 3,
+           0,
+           pScrolls[(unsigned int)pGUIWindow_ScrollWindow->ptr_1C],
+           0,
+           0,
+           0);
+}
+
+
+
+
+//----- (00468F8A) --------------------------------------------------------
+void __cdecl OnPaperdollLeftClick()
+{
+  Player *v0; // ebx@1
+  int v1; // ecx@1
+  unsigned int v2; // edi@1
+  unsigned int v3; // edx@4
+  unsigned int v4; // esi@5
+  unsigned __int16 v5; // ax@7
+  unsigned int v6; // edi@19
+  int v7; // esi@27
+  unsigned int v8; // eax@29
+  int v9; // edx@32
+  int v10; // esi@34
+  int v11; // eax@34
+  int v12; // esi@38
+  int v13; // eax@38
+  char v14; // zf@38
+  int v15; // esi@42
+  int v16; // eax@42
+  int v17; // eax@44
+  unsigned int v18; // ecx@55
+  unsigned int v19; // eax@55
+  int v20; // esi@60
+  int v21; // eax@60
+  unsigned int v22; // eax@61
+  unsigned int v23; // eax@62
+  int v24; // esi@65
+  int v25; // eax@65
+  unsigned int v26; // eax@69
+  int v27; // esi@81
+  int v28; // eax@81
+  int v29; // esi@84
+  int v30; // eax@84
+  int v31; // eax@85
+  unsigned int v32; // ecx@88
+  unsigned int v33; // eax@88
+  int v34; // esi@90
+  unsigned int v35; // eax@91
+  int v36; // esi@93
+  int v37; // edi@93
+  ItemGen *v38; // edi@93
+  __int16 v39; // dx@99
+  signed int v40; // [sp-1Ch] [bp-68h]@80
+  unsigned int v41; // [sp-18h] [bp-64h]@80
+  signed int v42; // [sp-14h] [bp-60h]@80
+  signed int v43; // [sp-10h] [bp-5Ch]@80
+  int v44; // [sp-Ch] [bp-58h]@80
+  unsigned int v45; // [sp-8h] [bp-54h]@80
+  int v46; // [sp-4h] [bp-50h]@80
+  ItemGen _this; // [sp+Ch] [bp-40h]@1
+  unsigned int v48; // [sp+30h] [bp-1Ch]@88
+  unsigned int v49; // [sp+34h] [bp-18h]@57
+  unsigned int v50; // [sp+38h] [bp-14h]@50
+  int v51; // [sp+3Ch] [bp-10h]@1
+  unsigned int v52; // [sp+40h] [bp-Ch]@5
+  int v53; // [sp+44h] [bp-8h]@1
+  unsigned int v54; // [sp+48h] [bp-4h]@1
+
+  v51 = 0;
+  _this.Reset();
+  v0 = pPlayers[uActiveCharacter];
+  v1 = v0->pEquipment.uMainHand;
+  v2 = v0->pEquipment.uOffHand;
+  v54 = v0->pEquipment.uOffHand;
+  v53 = v1;
+  if ( v1 && pItemsTable->pItems[*(int *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v1 + 5]].uEquipType == 1 )
+    v51 = v1;
+  v3 = pParty->pPickedItem.uItemID;
+  if ( pParty->pPickedItem.uItemID )
+  {
+    v52 = pItemsTable->pItems[pParty->pPickedItem.uItemID].uEquipType;
+    v4 = pItemsTable->pItems[pParty->pPickedItem.uItemID].uSkillType;
+    if ( v4 == 4 )
+    {
+      if ( v2 )
+      {
+LABEL_7:
+        LOBYTE(v5) = v0->GetActualSkillLevel(PLAYER_SKILL_SPEAR);
+        if ( (signed int)SkillToMastery(v5) < 3 )
+        {
+LABEL_8:
+          v0->PlaySound(39, 0);
+          return;
+        }
+        v3 = pParty->pPickedItem.uItemID;
+        goto LABEL_16;
+      }
+    }
+    else
+    {
+      if ( (v4 == 8 || v4 == 1 || v4 == 2)
+        && v1
+        && pItemsTable->pItems[*(int *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v1 + 5]].uSkillType == 4 )
+        goto LABEL_7;
+    }
+LABEL_16:
+    if ( !v0->CanEquip_RaceAndAlignmentCheck(v3) )
+      goto LABEL_8;
+    if ( pParty->pPickedItem.uItemID == 604 )
+    {
+      sub_467E7F_EquipBody(3u);
+      WetsuitOn(uActiveCharacter);
+      return;
+    }
+    v6 = v52;
+    switch ( v52 )
+    {
+      case 2u:
+      case 3u:
+      case 5u:
+      case 6u:
+      case 7u:
+      case 8u:
+      case 9u:
+      case 0xBu:
+        if ( !v0->HasSkill(v4) )
+          goto LABEL_8;
+        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) && (v6 != 3 || bUnderwater) )
+          goto LABEL_95;
+        sub_467E7F_EquipBody(v6);
+        if ( pParty->pPickedItem.uItemID == 604 )
+          WetsuitOff(uActiveCharacter);
+        return;
+      case 0xAu:
+        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) )
+          goto LABEL_95;
+        v52 = 10;
+        v7 = (int)&v0->pEquipment.field_28;
+        while ( 1 )
+        {
+          if ( !*(int *)v7 )
+          {
+            v8 = v0->FindFreeInventorySlot();
+            if ( (v8 & 0x80000000u) == 0 )
+              break;
+          }
+          ++v52;
+          v7 += 4;
+          if ( (signed int)v52 > 15 )
+            goto LABEL_33;
+        }
+        v9 = v52;
+        pParty->pPickedItem.uBodyAnchor = v52 + 1;
+        memcpy(&v0->pInventoryItems[v8], &pParty->pPickedItem, sizeof(v0->pInventoryItems[v8]));
+        *(&v0->pEquipment.uOffHand + v9) = v8 + 1;
+        pMouse->RemoveHoldingItem();
+LABEL_33:
+        if ( v52 == 16 )
+        {
+          v52 = v0->pEquipment.field_3C - 1;
+          memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
+          v10 = (int)((char *)v0 + 36 * v52);
+          *(char *)(v10 + 556) = 0;
+          pParty->pPickedItem.Reset();
+          pParty->SetHoldingItem((ItemGen *)(v10 + 532));
+          _this.uBodyAnchor = 16;
+          v11 = v52 + 1;
+          memcpy((void *)(v10 + 532), &_this, 0x24u);
+          v0->pEquipment.field_3C = v11;
+        }
+        return;
+      case 4u:
+        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) )
+          goto LABEL_95;
+        if ( !v0->HasSkill(v4) )
+          goto LABEL_8;
+        if ( v54 )
+        {
+          --v54;
+          memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
+          v12 = (int)((char *)v0 + 36 * v54);
+          *(char *)(v12 + 556) = 0;
+          pParty->pPickedItem.Reset();
+          pParty->SetHoldingItem((ItemGen *)(v12 + 532));
+          _this.uBodyAnchor = 1;
+          v13 = v54 + 1;
+          v14 = v51 == 0;
+          memcpy((void *)(v12 + 532), &_this, 0x24u);
+          v0->pEquipment.uOffHand = v13;
+          if ( v14 )
+            return;
+        }
+        else
+        {
+          v52 = v0->FindFreeInventorySlot();
+          if ( (v52 & 0x80000000u) != 0 )
+            return;
+          if ( !v51 )
+          {
+            pParty->pPickedItem.uBodyAnchor = 1;
+            v17 = v52 + 1;
+            memcpy(&v0->pInventoryItems[v52], &pParty->pPickedItem, sizeof(v0->pInventoryItems[v52]));
+            v0->pEquipment.uOffHand = v17;
+            goto LABEL_45;
+          }
+          memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
+          v15 = (int)((char *)v0 + 36 * (v53 - 1));
+          *(char *)(v15 + 556) = 0;
+          pParty->pPickedItem.Reset();
+          pParty->SetHoldingItem((ItemGen *)(v15 + 532));
+          _this.uBodyAnchor = 1;
+          v16 = v52 + 1;
+          memcpy(&v0->pInventoryItems[v52], &_this, sizeof(v0->pInventoryItems[v52]));
+          v0->pEquipment.uOffHand = v16;
+        }
+        v0->pEquipment.uMainHand = 0;
+        return;
+      case 0u:
+      case 0xCu:
+        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter)
+          && pParty->pPickedItem.uItemID != 64
+          && pParty->pPickedItem.uItemID != 65 )
+          goto LABEL_95;
+        if ( !v0->HasSkill(v4) )
+          goto LABEL_8;
+        v50 = 0;
+        if ( v4 == 2 && (unsigned __int16)(v0->pActiveSkills[2] & 0xFFC0)
+          || v4 == 1 && (signed int)SkillToMastery(v0->pActiveSkills[1]) >= 3 )
+        {
+          if (pAsyncMouse)
+          {
+            v18 = *((int *)pAsyncMouse + 6);
+            v19 = *((int *)pAsyncMouse + 7);
+          }
+          else
+          {
+            v18 = pMouse->uMouseClickX;
+            v19 = pMouse->uMouseClickY;
+          }
+          v49 = v19;
+          if ( (signed int)v18 >= 560 )
+          {
+            if ( !v51 )
+            {
+              if ( v54 )
+              {
+                --v54;
+                memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
+                v20 = (int)((char *)v0 + 36 * v54);
+                *(char *)(v20 + 556) = 0;
+                pParty->pPickedItem.Reset();
+                pParty->SetHoldingItem((ItemGen *)(v20 + 532));
+                _this.uBodyAnchor = 1;
+                v21 = v54 + 1;
+                v14 = v52 == 12;
+                memcpy((void *)(v20 + 532), &_this, 0x24u);
+                v0->pEquipment.uOffHand = v21;
+                if ( !v14 )
+                  return;
+                v22 = _this.uItemID;
+LABEL_73:
+                v50 = v22;
+                goto LABEL_74;
+              }
+              v23 = v0->FindFreeInventorySlot();
+              if ( (v23 & 0x80000000u) != 0 )
+                return;
+              pParty->pPickedItem.uBodyAnchor = 1;
+              v50 = (unsigned int)&v0->pInventoryItems[v23];
+              memcpy(&v0->pInventoryItems[v23], &pParty->pPickedItem, sizeof(v0->pInventoryItems[v23]));
+              v0->pEquipment.uOffHand = v23 + 1;
+LABEL_71:
+              pMouse->RemoveHoldingItem();
+              if ( v52 != 12 )
+                return;
+              v22 = *(int *)v50;
+              goto LABEL_73;
+            }
+          }
+        }
+        if ( !v53 )
+        {
+          v26 = v0->FindFreeInventorySlot();
+          if ( (v26 & 0x80000000u) != 0 )
+            return;
+          pParty->pPickedItem.uBodyAnchor = 2;
+          v50 = (unsigned int)&v0->pInventoryItems[v26];
+          memcpy(&v0->pInventoryItems[v26], &pParty->pPickedItem, sizeof(v0->pInventoryItems[v26]));
+          v0->pEquipment.uMainHand = v26 + 1;
+          goto LABEL_71;
+        }
+        --v53;
+        memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
+        v24 = (int)((char *)v0 + 36 * v53);
+        *(char *)(v24 + 556) = 0;
+        pParty->pPickedItem.Reset();
+        pParty->SetHoldingItem((ItemGen *)(v24 + 532));
+        _this.uBodyAnchor = 2;
+        v25 = v53 + 1;
+        v14 = v52 == 12;
+        memcpy((void *)(v24 + 532), &_this, 0x24u);
+        v0->pEquipment.uMainHand = v25;
+        if ( v14 )
+          v50 = _this.uItemID;
+        if ( v51 )
+          v0->pEquipment.uOffHand = 0;
+LABEL_74:
+        if ( v50 )
+          stru_A750F8[uActiveCharacter - 1]._494836(
+            *((int *)&pSpellDatas[66].field_8 + v50),
+            uActiveCharacter - 1 + 9);
+        break;
+      case 1u:
+        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) )
+          goto LABEL_95;
+        if ( !v0->HasSkill(v4) )
+          goto LABEL_8;
+        if ( v53 )
+        {
+          if ( v54 )
+          {
+            v46 = 0;
+            v45 = 0;
+            v44 = 0;
+            v43 = 0;
+            v42 = -1;
+            v41 = 0;
+            v40 = 0;
+            goto LABEL_96;
+          }
+          --v53;
+          memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
+          v27 = (int)((char *)v0 + 36 * v53);
+          *(char *)(v27 + 556) = 0;
+          pParty->pPickedItem.Reset();
+          pParty->SetHoldingItem((ItemGen *)(v27 + 532));
+          _this.uBodyAnchor = 2;
+          v28 = v53 + 1;
+          memcpy((void *)(v27 + 532), &_this, 0x24u);
+          v0->pEquipment.uMainHand = v28;
+        }
+        else
+        {
+          v52 = v0->FindFreeInventorySlot();
+          if ( (v52 & 0x80000000u) == 0 )
+          {
+            if ( v54 )
+            {
+              memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
+              v29 = (int)((char *)v0 + 36 * (v54 - 1));
+              *(char *)(v29 + 556) = 0;
+              pParty->pPickedItem.Reset();
+              pParty->SetHoldingItem((ItemGen *)(v29 + 532));
+              _this.uBodyAnchor = 2;
+              v30 = v52 + 1;
+              memcpy(&v0->pInventoryItems[v52], &_this, sizeof(v0->pInventoryItems[v52]));
+              v0->pEquipment.uOffHand = 0;
+              v0->pEquipment.uMainHand = v30;
+            }
+            else
+            {
+              pParty->pPickedItem.uBodyAnchor = 2;
+              v31 = v52 + 1;
+              memcpy(&v0->pInventoryItems[v52], &pParty->pPickedItem, sizeof(v0->pInventoryItems[v52]));
+              v0->pEquipment.uMainHand = v31;
+LABEL_45:
+              pMouse->RemoveHoldingItem();
+            }
+          }
+        }
+        return;
+      default:
+        v0->UseItem_DrinkPotion_etc(uActiveCharacter, 0);
+        return;
+    }
+    return;
+  }
+  if (pAsyncMouse)
+  {
+    v32 = *((int *)pAsyncMouse + 6);
+    v33 = *((int *)pAsyncMouse + 7);
+    v49 = *((int *)pAsyncMouse + 7);
+    v48 = v32;
+  }
+  else
+  {
+    v32 = pMouse->uMouseClickX;
+    v33 = pMouse->uMouseClickY;
+  }
+  v34 = pRenderer->pActiveZBuffer[v32 + pSRZBufferLineOffsets[v33]] & 0xFFFF;
+  if ( v34 )
+  {
+    v36 = v34 - 1;
+    v37 = (int)((char *)v0 + 36 * v36);
+    v50 = v37;
+    v38 = (ItemGen *)(v37 + 532);
+    v14 = v38->uItemID == 604;
+    v52 = pItemsTable->pItems[v38->uItemID].uEquipType;
+    if ( v14 )
+    {
+      if ( bUnderwater )
+      {
+LABEL_95:
+        v46 = 0;
+        v45 = 0;
+        v44 = 0;
+        v43 = 0;
+        v42 = -1;
+        v41 = 0;
+        v40 = 0;
+LABEL_96:
+        pAudioPlayer->PlaySound(SOUND_27, v40, v41, v42, v43, v44, v45, v46);
+        return;
+      }
+      WetsuitOff(uActiveCharacter);
+    }
+    if ( unk_50C9A0 )
+    {
+      *((char *)pGUIWindow_Settings->ptr_1C + 8) &= 0x7Fu;
+      *((short *)pGUIWindow_Settings->ptr_1C + 2) = uActiveCharacter - 1;
+      v39 = v52;
+      *((int *)pGUIWindow_Settings->ptr_1C + 3) = v36;
+      *((short *)pGUIWindow_Settings->ptr_1C + 3) = v39;
+      ptr_50C9A4 = v38;
+      unk_50C9A0 = 0;
+      if ( pMessageQueue_50CBD0->uNumMessages )
+        pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+      pMouse->SetCursorBitmap("MICON1");
+      dword_50C9D4 = 0;
+      dword_50C9D0 = 113;
+      dword_50C9D8 = 256;
+    }
+    else
+    {
+      if ( !ptr_50C9A4 )
+      {
+        pParty->SetHoldingItem(v38);
+        *(&v0->uBirthYear + *(char *)(v50 + 556)) = 0;
+        v38->Reset();
+      }
+    }
+  }
+  else
+  {
+    v35 = v0->pEquipment.uBow;
+    if ( v35 )
+    {
+      auto _a = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v35 + 5];
+      pParty->SetHoldingItem(_a);
+      _a->Reset();
+      v0->pEquipment.uBow = 0;
+    }
+  }
+}
+
+
+
+
+//----- (0046A0A1) --------------------------------------------------------
+int __thiscall UnprojectX(int x)
+{
+  double v1; // st7@3
+  int v3; // [sp-4h] [bp-8h]@5
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    if ( pRenderer->pRenderD3D )
+      v1 = pGame->pIndoorCameraD3D->fov;
+    else
+      v1 = pIndoorCamera->flt_1C_fov;
+    v3 = (signed __int64)v1;
+  }
+  else
+  {
+    v3 = pOutdoorCamera->int_fov_rad;
+  }
+  return stru_5C6E00->Atan2(x - pViewport->uScreenCenterX, v3) - stru_5C6E00->uIntegerHalfPi;
+}
+
+//----- (0046A0F6) --------------------------------------------------------
+int __thiscall UnprojectY(int _this)
+{
+  double v1; // st7@3
+  int v3; // [sp-4h] [bp-8h]@5
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    if ( pRenderer->pRenderD3D )
+      v1 = pGame->pIndoorCameraD3D->fov;
+    else
+      v1 = pIndoorCamera->flt_1C_fov;
+    v3 = (signed __int64)v1;
+  }
+  else
+  {
+    v3 = pOutdoorCamera->int_fov_rad;
+  }
+  return stru_5C6E00->Atan2(_this - pViewport->uScreenCenterY, v3) - stru_5C6E00->uIntegerHalfPi;
+}
+
+//----- (0046A14B) --------------------------------------------------------
+char __cdecl OnPressSpace()
+{
+  SHORT v0; // ax@2
+  int *v1; // eax@2
+  char *v2; // ebx@5
+  unsigned int v3; // esi@5
+  signed int v4; // edi@7
+  unsigned int v5; // edx@7
+  int v6; // ecx@8
+  int v7; // eax@8
+  int v8; // ecx@17
+  int *v9; // esi@22
+  signed int v10; // ebx@22
+  int i; // edi@23
+  int v12; // edx@24
+  int v13; // ecx@24
+  int j; // esi@28
+  int v16; // [sp+4h] [bp-1Ch]@0
+  char *v17; // [sp+8h] [bp-18h]@5
+  unsigned int v18; // [sp+Ch] [bp-14h]@5
+  int v19; // [sp+10h] [bp-10h]@8
+  int *v20; // [sp+14h] [bp-Ch]@5
+  int *v21; // [sp+18h] [bp-8h]@7
+  int v22; // [sp+1Ch] [bp-4h]@4
+
+  if ( pRenderer->pRenderD3D )
+  {
+    v0 = GetAsyncKeyState(17);
+    pGame->_44EB12((v0 & 0x8001) != 0, &a3, &a4);
+    v1 = (int *)pGame->pVisInstance->get_picked_object_zbuf_val();
+    if ( v1 != (int *)-1 )
+      LOBYTE(v1) = DoInteractionWithTopmostZObject((unsigned __int16)v1, (signed int)(unsigned __int16)v1 >> 3);
+    return (char)v1;
+  }
+  v22 = 0;
+  v1 = (int *)((signed int)(viewparams->uScreenZ + viewparams->uScreenX) >> 1);
+  if ( (signed int)viewparams->uScreenY >= (signed int)viewparams->uScreenW )
+    goto LABEL_21;
+  v2 = (char *)v1 - 50;
+  v1 = (int *)((char *)v1 + 50);
+  v3 = 640 * viewparams->uScreenY;
+  v17 = v2;
+  v20 = v1;
+  v18 = ((viewparams->uScreenW - viewparams->uScreenY - 1) >> 1) + 1;
+  do
+  {
+    if ( (signed int)v2 >= (signed int)v20 )
+      goto LABEL_20;
+    v1 = &pRenderer->pActiveZBuffer[(int)&v2[v3]];
+    v21 = &pRenderer->pActiveZBuffer[(int)&v2[v3]];
+    v4 = v22;
+    v5 = (((char *)v20 - v2 - 1) >> 1) + 1;
+    do
+    {
+      v6 = 0;
+      v7 = *v1 & 0xFFFF;
+      v19 = 0;
+      if ( v4 > 0 )
+      {
+        do
+        {
+          if ( dword_7207F0[v6] == v7 )
+            break;
+          ++v6;
+          v19 = v6;
+        }
+        while ( v6 < v22 );
+      }
+      if ( (v7 & 7) == 5 )
+      {
+        v16 = (unsigned int)v7 >> 3;
+        if ( (signed int)(((unsigned int)*v21 >> 16)
+                        - pDecorationList->pDecorations[pLevelDecorations[(unsigned int)v7 >> 3].uDecorationDescID].uRadius) > 512 )
+          goto LABEL_18;
+      }
+      else
+      {
+        if ( (unsigned int)*v21 > 0x2000000 )
+          goto LABEL_18;
+      }
+      if ( v19 == v22 && v4 < 100 )
+      {
+        ++v22;
+        ++v4;
+        v8 = *v21;
+        dword_7207EC[v4] = v7;
+        dword_72065C[v4] = v8;
+      }
+LABEL_18:
+      v1 = v21 + 2;
+      --v5;
+      v21 += 2;
+    }
+    while ( v5 );
+    v2 = v17;
+LABEL_20:
+    v3 += 1280;
+    --v18;
+  }
+  while ( v18 );
+LABEL_21:
+  if ( v22 > 0 )
+  {
+    v9 = dword_720660;
+    v10 = 1;
+    do
+    {
+      for ( i = v10; i < v22; ++i )
+      {
+        v12 = *v9;
+        v13 = dword_720660[i];
+        if ( v13 < *v9 )
+        {
+          *v9 = v13;
+          dword_720660[i] = v12;
+        }
+      }
+      ++v10;
+      ++v9;
+      LOBYTE(v1) = v10 - 1;
+    }
+    while ( v10 - 1 < v22 );
+  }
+  for ( j = 0; j < v22; ++j )
+  {
+    LOBYTE(v1) = DoInteractionWithTopmostZObject(dword_720660[j] & 0xFFFF, v16);
+    if ( !(char)v1 )
+      break;
+  }
+  return (char)v1;
+}
+// 72065C: using guessed type int dword_72065C[];
+// 7207EC: using guessed type int dword_7207EC[];
+
+//----- (0046A334) --------------------------------------------------------
+char __fastcall DoInteractionWithTopmostZObject(int a1, int a2)
+{
+  int v2; // edx@1
+  BLVFace *v4; // eax@9
+  unsigned int v5; // ecx@9
+  unsigned __int16 v6; // ax@11
+  ODMFace *v7; // eax@16
+  LevelDecoration *v8; // esi@19
+  __int16 v9; // ax@19
+  int v10; // eax@22
+  int v11; // ecx@22
+  int v12; // edi@23
+  Actor *v13; // esi@23
+  unsigned __int16 v14; // ax@23
+  unsigned __int16 v15; // ax@33
+  const char *v16; // eax@34
+  int v17; // edi@36
+  int v18; // eax@36
+  ItemGen *v19; // esi@39
+  unsigned int v20; // eax@39
+  int v21; // ecx@40
+  std::string v22; // [sp-18h] [bp-2Ch]@5
+  const char *v23; // [sp-8h] [bp-1Ch]@5
+  int v24; // [sp-4h] [bp-18h]@5
+  char v25; // [sp+8h] [bp-Ch]@5
+  int v26; // [sp+Ch] [bp-8h]@1
+  int a3; // [sp+13h] [bp-1h]@5
+
+  v26 = a2;
+  v2 = a1;
+  switch ( a1 & 7 )
+  {
+    case 2:
+      v17 = a1 >> 3;
+      v26 = a1 >> 3;
+      v18 = a1 >> 3;
+      if ( pObjectList->pObjects[pLayingItems[v18].uObjectDescID].uFlags & 0x10
+        || v17 >= 1000
+        || !pLayingItems[v18].uObjectDescID )
+        return 1;
+      v19 = &pLayingItems[v18].stru_24;
+      v20 = pLayingItems[v18].stru_24.uItemID;
+      if ( pItemsTable->pItems[v20].uEquipType == 18 )
+      {
+        party_finds_gold(v19->uAdditionalValue, 0);
+        viewparams->bRedrawGameUI = 1;
+        v21 = v17;
+      }
+      else
+      {
+        if ( pParty->pPickedItem.uItemID )
+          return 1;
+        v24 = (int)pItemsTable->pItems[v20].pUnidentifiedName;
+        sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[471], v24);
+        ShowStatusBarString(pTmpBuf2, 2u);
+        if ( v19->uItemID == 506 )
+          _449B7E_toggle_bit(pParty->_award_bits, 184, 1u);
+        if ( v19->uItemID == 455 )
+          _449B7E_toggle_bit(pParty->_award_bits, 185, 1u);
+        if ( !pParty->AddItem(v19) )
+          pParty->SetHoldingItem(v19);
+        v21 = v26;
+      }
+      LayingItem::_42F933(v21);
+      break;
+    case 3:
+      v12 = a1 >> 3;
+      v13 = &pActors[a1 >> 3];
+      v14 = v13->uAIState;
+      if ( v14 == 4 || v14 == 17 )
+        return 1;
+      if ( v14 == 5 )
+      {
+        stru_50C198.LootActor(&pActors[a1 >> 3]);
+      }
+      else
+      {
+        if ( !v13->GetActorsRelation(0) && !(BYTE2(v13->uAttributes) & 8) && v13->CanAct() )
+        {
+          Actor::FaceObject(v12, 4u, 0, 0);
+          if ( v13->uNPC_ID )
+          {
+            if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+            {
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)161;
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v12;
+              *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+              ++pMessageQueue_50CBD0->uNumMessages;
+            }
+          }
+          else
+          {
+            v15 = pNPCStats->pGroups_copy[v13->uGroup];
+            if ( v15 )
+            {
+              v16 = pNPCStats->pCatchPhrases[v15];
+              if ( v16 )
+              {
+                pParty->uFlags |= 2u;
+                strcpy(byte_5B0938, v16);
+                sub_4451A8_press_any_key(0, 0, 0);
+              }
+            }
+          }
+        }
+      }
+      break;
+    case 5:
+      v8 = &pLevelDecorations[a1 >> 3];
+      v9 = v8->field_16_event_id;
+      if ( v9 )
+      {
+        EventProcessor(v9, a1, 1);
+        LOBYTE(v8->field_2) |= 8u;
+      }
+      else
+      {
+        if ( !pLevelDecorations[a1 >> 3].IsInteractive() )
+          return 1;
+        v10 = v8->_idx_in_stru123;
+        v24 = 1;
+        v11 = stru_5E4C90._decor_events[v10 - 75] + 380;
+        _5C3420_pDecoration = v8;
+        EventProcessor(v11, 0, 1);
+        _5C3420_pDecoration = 0;
+      }
+      break;
+    default:
+      if ( (a1 & 7) != 6 )
+      {
+    MessageBoxW(nullptr, L"Warning: Invalid ID reached!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Mouse.cpp:2020", 0);
+        return 1;
+      }
+      if ( uCurrentlyLoadedLevelType != LEVEL_Indoor )
+      {
+        if ( a1 >> 9 >= pOutdoor->uNumBModels
+          || (v7 = &pOutdoor->pBModels[a1 >> 9].pFaces[(a1 >> 3) & 0x3F], BYTE2(v7->uAttributes) & 0x10)
+          || (v6 = v7->sCogTriggeredID) == 0 )
+          return 1;
+LABEL_13:
+        EventProcessor((signed __int16)v6, v2, 1);
+        return 0;
+      }
+      v4 = &pIndoor->pFaces[a1 >> 3];
+      v5 = v4->uAttributes;
+      if ( !(v5 & 0x2000000) )
+      {
+        ShowNothingHereStatus();
+        return 1;
+      }
+      if ( v5 & 0x100000 || (v6 = pIndoor->pFaceExtras[v4->uFaceExtraID].uEventID) == 0 )
+        return 1;
+      if ( pCurrentScreen != 19 )
+        goto LABEL_13;
+      break;
+  }
+  return 0;
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (0046A6AC) --------------------------------------------------------
+int __fastcall sub_46A6AC(int a1, int a2, int a3)
+{
+  int result; // eax@2
+  unsigned int v4; // edx@3
+  int *v5; // esi@6
+  unsigned int v6; // ebx@6
+  signed int v7; // edi@9
+  unsigned __int16 v8; // ax@9
+  int i; // eax@14
+  int v10; // ecx@19
+  int v11; // [sp+0h] [bp-18h]@1
+  unsigned int v12; // [sp+4h] [bp-14h]@3
+  unsigned int v13; // [sp+8h] [bp-10h]@4
+  int v14; // [sp+Ch] [bp-Ch]@1
+  int *v15; // [sp+10h] [bp-8h]@4
+  int v16; // [sp+14h] [bp-4h]@3
+
+  v11 = a2;
+  v14 = a1;
+  if ( pRenderer->pRenderD3D )
+  {
+    result = sub_46A7C8(a1, a2, a3);
+  }
+  else
+  {
+    v16 = 0;
+    v4 = viewparams->uScreenX;
+    v12 = viewparams->uScreenZ;
+    if ( (signed int)viewparams->uScreenY < (signed int)viewparams->uScreenW )
+    {
+      v15 = &pRenderer->pActiveZBuffer[viewparams->uScreenX + 640 * viewparams->uScreenY];
+      v13 = ((viewparams->uScreenW - viewparams->uScreenY - 1) >> 1) + 1;
+      do
+      {
+        if ( (signed int)v4 < (signed int)v12 )
+        {
+          v5 = v15;
+          v6 = ((v12 - v4 - 1) >> 1) + 1;
+          do
+          {
+            if ( (*(char *)v5 & 7) == 3 )
+            {
+              if ( *v5 <= a3 << 16 )
+              {
+                v7 = (signed int)(unsigned __int16)*v5 >> 3;
+                v8 = pActors[v7].uAIState;
+                if ( v8 != 5 )
+                {
+                  if ( v8 != 4 && v8 != 11 && v8 != 17 && v8 != 19 )
+                  {
+                    for ( i = 0; i < v16; ++i )
+                    {
+                      if ( *(int *)(v14 + 4 * i) == v7 )
+                        break;
+                    }
+                    if ( i == v16 )
+                    {
+                      if ( i < v11 - 1 )
+                      {
+                        v10 = v16++;
+                        *(int *)(v14 + 4 * v10) = v7;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+            v5 += 2;
+            --v6;
+          }
+          while ( v6 );
+        }
+        v15 += 1280;
+        --v13;
+      }
+      while ( v13 );
+    }
+    result = v16;
+  }
+  return result;
+}
+
+//----- (0046A7C8) --------------------------------------------------------
+int __fastcall sub_46A7C8(int a1, int a2, signed int a3)
+{
+  unsigned int v3; // eax@2
+  int v4; // ecx@2
+  unsigned int v5; // eax@2
+  unsigned int v6; // eax@4
+  unsigned int v7; // edi@4
+  unsigned __int16 v8; // ax@4
+  float v9; // ST00_4@9
+  int v10; // ecx@11
+  unsigned int v12; // [sp+10h] [bp-14h]@1
+  int v13; // [sp+14h] [bp-10h]@1
+  int v14; // [sp+18h] [bp-Ch]@1
+  int v15; // [sp+1Ch] [bp-8h]@1
+  unsigned int a1a; // [sp+20h] [bp-4h]@1
+
+  v13 = a1;
+  v14 = a2;
+  v15 = 0;
+  a1a = 0;
+  v12 = pRenderer->GetBillboardDrawListSize();
+  if ( (signed int)v12 > 0 )
+  {
+    do
+    {
+      v3 = pRenderer->GetParentBillboardID(a1a);
+      v4 = pBillboardRenderList[v3].sZValue;
+      v5 = (unsigned __int16)pBillboardRenderList[v3].sZValue;
+      if ( (v5 & 7) == 3 )
+      {
+        if ( v4 <= (unsigned int)(a3 << 16) )
+        {
+          v6 = v5 >> 3;
+          v7 = v6;
+          v8 = pActors[v6].uAIState;
+          if ( v8 != 5 )
+          {
+            if ( v8 != 4 )
+            {
+              if ( v8 != 11 )
+              {
+                if ( v8 != 19 )
+                {
+                  if ( v8 != 17 )
+                  {
+                    v9 = (double)a3;
+                    if ( pGame->pVisInstance->DoesRayIntersectBillboard(v9, a1a) )
+                    {
+                      if ( v15 < v14 - 1 )
+                      {
+                        v10 = v15++;
+                        *(int *)(v13 + 4 * v10) = v7;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      ++a1a;
+    }
+    while ( (signed int)a1a < (signed int)v12 );
+  }
+  return v15;
+}
+
+//----- (0046A89E) --------------------------------------------------------
+int __fastcall sub_46A89E(int a1, int a2, signed int a3)
+{
+  signed int v3; // edi@1
+  char *v4; // esi@2
+  int v5; // ebx@3
+  int v6; // eax@3
+  int v7; // ebx@3
+  unsigned int v8; // ecx@3
+  int v9; // edx@4
+  unsigned int v10; // edx@6
+  unsigned int v11; // edx@8
+  __int16 v12; // ax@10
+  int v13; // ecx@15
+  int v15; // [sp+4h] [bp-18h]@1
+  int v16; // [sp+8h] [bp-14h]@1
+  int v17; // [sp+Ch] [bp-10h]@3
+  int v18; // [sp+10h] [bp-Ch]@3
+  int v19; // [sp+18h] [bp-4h]@1
+
+  v3 = 0;
+  v15 = a2;
+  v16 = a1;
+  v19 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v4 = (char *)&pActors[0].uAIState;
+    do
+    {
+      v5 = abs(*((short *)v4 - 17) - pParty->vPosition.x);
+      v17 = abs(*((short *)v4 - 16) - pParty->vPosition.y);
+      v18 = abs(*((short *)v4 - 15) - pParty->vPosition.z);
+      v6 = v5;
+      v7 = v17;
+      v8 = v18;
+      if ( v6 < v17 )
+      {
+        v9 = v6;
+        v6 = v17;
+        v7 = v9;
+      }
+      if ( v6 < v18 )
+      {
+        v10 = v6;
+        v6 = v18;
+        v8 = v10;
+      }
+      if ( v7 < (signed int)v8 )
+      {
+        v11 = v8;
+        v8 = v7;
+        v7 = v11;
+      }
+      if ( (signed int)(((unsigned int)(11 * v7) >> 5) + (v8 >> 2) + v6) <= a3 )
+      {
+        v12 = *(short *)v4;
+        if ( *(short *)v4 != 5 )
+        {
+          if ( v12 != 4 )
+          {
+            if ( v12 != 11 )
+            {
+              if ( v12 != 19 )
+              {
+                if ( v12 != 17 )
+                {
+                  v13 = v19++;
+                  *(int *)(v16 + 4 * v13) = v3;
+                  if ( v19 >= v15 - 1 )
+                    break;
+                }
+              }
+            }
+          }
+        }
+      }
+      ++v3;
+      v4 += 836;
+    }
+    while ( v3 < (signed int)uNumActors );
+  }
+  return v19;
+}
+
+//----- (0046A99B) --------------------------------------------------------
+int __cdecl sub_46A99B()
+{
+  int v0; // ebx@1
+  signed int v1; // ecx@1
+  signed int v2; // esi@1
+  int v3; // edx@1
+  signed int v4; // eax@1
+  int v5; // ecx@2
+  int *v6; // eax@3
+  int v7; // ecx@3
+  int v8; // edx@5
+  int v9; // edi@6
+  unsigned __int8 v10; // zf@14
+  char v11; // sf@14
+  char v12; // of@14
+  int *v14; // esi@19
+  signed int v15; // ebx@19
+  int i; // edi@20
+  int v17; // ecx@21
+  int v18; // edi@26
+  int v19; // esi@27
+  unsigned int v20; // ecx@27
+  BLVFace *v21; // eax@32
+  unsigned int v22; // ecx@33
+  const char *v23; // eax@35
+  const char *v24; // ecx@36
+  LevelDecoration *v25; // ecx@43
+  LevelDecoration *v26; // edi@43
+  __int16 v27; // ax@43
+  int v28; // [sp+Ch] [bp-18h]@1
+  int v29; // [sp+14h] [bp-10h]@2
+  int v30; // [sp+18h] [bp-Ch]@1
+  signed int v31; // [sp+1Ch] [bp-8h]@3
+  int v32; // [sp+20h] [bp-4h]@1
+
+  v0 = 0;
+  v1 = (signed int)(viewparams->uScreenW + viewparams->uScreenY) >> 1;
+  v2 = (signed int)(viewparams->uScreenX + viewparams->uScreenZ) >> 1;
+  v3 = v1 - 50;
+  v32 = 0;
+  v4 = 100;
+  v30 = v1 - 50;
+  v28 = v1 + 50;
+  if ( v1 - 50 >= v1 + 50 )
+    return 0;
+  v5 = 640 * v3;
+  v29 = 640 * v3;
+  while ( 2 )
+  {
+    v31 = 100;
+    v6 = &pRenderer->pActiveZBuffer[v2 + v5 - v4 / 2];
+    v7 = v0;
+    while ( 1 )
+    {
+      v8 = *v6;
+      --v31;
+      if ( (unsigned int)*v6 <= 0x2000000 )
+      {
+        v9 = 0;
+        if ( v7 > 0 )
+        {
+          do
+          {
+            if ( dword_7201B0_zvalues[v9] == (unsigned __int16)v8 )
+              break;
+            ++v9;
+          }
+          while ( v9 < v0 );
+        }
+        if ( v9 == v0 )
+        {
+          if ( v8 & 7 )
+          {
+            dword_720020_zvalues[v7] = v8;
+            dword_7201B0_zvalues[v7] = (unsigned __int16)v8;
+            ++v7;
+            ++v0;
+            v32 = v0;
+            if ( v7 == 99 )
+            {
+              v12 = 0;
+              v10 = v0 == 0;
+              v11 = v0 < 0;
+              goto LABEL_18;
+            }
+          }
+        }
+      }
+      if ( !v31 )
+        break;
+      ++v6;
+    }
+    v4 = -1;
+    ++v30;
+    v5 = v29 + 640;
+    v29 += 640;
+    if ( v30 < v28 )
+      continue;
+    break;
+  }
+  v12 = 0;
+  v10 = v0 == 0;
+  v11 = v0 < 0;
+  if ( !v0 )
+    return 0;
+LABEL_18:
+  if ( !((unsigned __int8)(v11 ^ v12) | v10) )
+  {
+    v14 = dword_720020_zvalues;
+    v15 = 1;
+    do
+    {
+      for ( i = v15; i < v32; ++i )
+      {
+        v17 = dword_720020_zvalues[i];
+        if ( v17 < *v14 )
+        {
+          dword_720020_zvalues[i] = *v14;
+          *v14 = v17;
+        }
+      }
+      ++v15;
+      ++v14;
+    }
+    while ( v15 - 1 < v32 );
+    v0 = v32;
+  }
+  v18 = 0;
+  if ( v0 <= 0 )
+    return 0;
+  while ( 1 )
+  {
+    v19 = dword_720020_zvalues[v18] & 0xFFFF;
+    v20 = (dword_720020_zvalues[v18] & 0xFFFFu) >> 3;
+    if ( (dword_720020_zvalues[v18] & 7) == 2 )
+    {
+      if ( v20 >= 0x3E8 )
+        return 0;
+      if ( !(pLayingItems[v20].uAttributes & 0x10) )
+      {
+        v23 = pLayingItems[v20].stru_24.GetDisplayName();
+LABEL_36:
+        v24 = v23;
+        goto LABEL_51;
+      }
+      goto LABEL_41;
+    }
+    if ( (dword_720020_zvalues[v18] & 7) == 3 )
+    {
+      if ( v20 >= 0xBB8 )
+        return 0;
+      v24 = (const char *)&pActors[v20];
+      goto LABEL_51;
+    }
+    if ( (dword_720020_zvalues[v18] & 7) == 5 )
+      break;
+    if ( (dword_720020_zvalues[v18] & 7) == 6 )
+    {
+      if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+      {
+        v21 = &pIndoor->pFaces[v20];
+        if ( !(BYTE3(v21->uAttributes) & 2) )
+          goto LABEL_41;
+        v22 = pIndoor->pFaceExtras[v21->uFaceExtraID].uEventID;
+      }
+      else
+      {
+        if ( (dword_720020_zvalues[v18] & 0xFFFFu) >> 9 >= pOutdoor->uNumBModels )
+          goto LABEL_41;
+        v22 = pOutdoor->pBModels[(dword_720020_zvalues[v18] & 0xFFFFu) >> 9].pFaces[((dword_720020_zvalues[v18] & 0xFFFFu) >> 3) & 0x3F].sCogTriggeredID;
+      }
+      if ( v22 )
+      {
+        v23 = _444732_GetEventHintString(v22);
+        if ( v23 )
+          goto LABEL_36;
+      }
+    }
+LABEL_41:
+    ++v18;
+    if ( v18 >= v0 )
+      return 0;
+  }
+  v25 = &pLevelDecorations[v20];
+  v26 = v25;
+  v27 = v25->field_16_event_id;
+  if ( v27 )
+  {
+    v23 = _444732_GetEventHintString(v27);
+    if ( !v23 )
+      return v19;
+    goto LABEL_36;
+  }
+  if ( v25->IsInteractive() )
+    v24 = pNPCTopics[stru_5E4C90._decor_events[v26->_idx_in_stru123 - 75] + 379].pTopic;
+  else
+    v24 = pDecorationList->pDecorations[v26->uDecorationDescID].field_20;
+LABEL_51:
+  sub_41C0B8_set_status_string(v24);
+  return v19;
+}
+
+
+//----- (0046BDA8) --------------------------------------------------------
+unsigned int __cdecl GetGravityStrength()
+{
+  int v0; // eax@1
+
+  v0 = ~LOBYTE(pGame->uFlags2) & 8;
+  LOBYTE(v0) = v0 | 2;
+  return (unsigned int)v0 >> 1;
+}
+
+//----- (0046BDC0) --------------------------------------------------------
+void __cdecl sub_46BDC0_UpdateUserInput_and_MapSpecificStuff()
+{
+  if ( dword_6BE364_game_settings_1 & 0x80 )
+  {
+    LOBYTE(dword_6BE364_game_settings_1) = dword_6BE364_game_settings_1 & 0x7F;
+  }
+  else
+  {
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    {
+      BLV_UpdateUserInputAndOther();
+    }
+    else
+    {
+      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+        ODM_UpdateUserInputAndOther();
+    }
+    _438F8F_area_of_effect__damage_evaluate();
+  }
+}
+
+
+
+//----- (0046BDF1) --------------------------------------------------------
+void __cdecl BLV_UpdateUserInputAndOther()
+{
+  UpdateObjects();
+  BLV_ProcessPartyActions();
+  UpdateActors_BLV();
+  BLV_UpdateDoors();
+  _46CC4B_check_event_triggers();
+}
+
+//----- (0046BE0A) --------------------------------------------------------
+void __cdecl ODM_UpdateUserInputAndOther()
+{
+  bool v0; // eax@5
+  int pOut; // [sp+8h] [bp-20h]@5
+
+  UpdateObjects();
+  ODM_ProcessPartyActions();
+  if ( pParty->vPosition.x < -22528
+    || pParty->vPosition.x > 22528
+    || pParty->vPosition.y < -22528
+    || pParty->vPosition.y > 22528 )
+  {
+    strcpy(pOutdoor->pLevelFilename, pCurrentMapName);
+    v0 = pOutdoor->GetTravelDestination(pParty->vPosition.x, pParty->vPosition.y, (char *)&pOut, 32);
+    if ( !bUnderwater && (pParty->uFlags & 0x8C || BYTE1(pParty->uFlags) & 2 || pParty->bFlying) || !v0 )
+    {
+      if ( pParty->vPosition.x < -22528 )
+        pParty->vPosition.x = -22528;
+      if ( pParty->vPosition.x > 22528 )
+        pParty->vPosition.x = 22528;
+      if ( pParty->vPosition.y < -22528 )
+        pParty->vPosition.y = -22528;
+      if ( pParty->vPosition.y > 22528 )
+        pParty->vPosition.y = 22528;
+    }
+    else
+    {
+      pAudioPlayer->StopChannels(-1, -1);
+      UI_CreateTravelDialogue();
+    }
+  }
+  //UpdateActors_ODM();Ritor1: it's temporarily
+  _46CC4B_check_event_triggers();
+}
+
+
+
+
+//----- (0046BEF1) --------------------------------------------------------
+void LayingItem::_46BEF1_apply_spells()
+{
+  LayingItem *v1; // edi@1
+  char *v2; // esi@2
+  __int16 v3; // fps@4
+  unsigned __int8 v4; // c0@4
+  unsigned __int8 v5; // c3@4
+  signed int v6; // [sp+8h] [bp-4h]@1
+
+  v6 = 0;
+  v1 = this;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v2 = (char *)&pActors[0].vPosition.y;
+    do
+    {
+      if ( ((Actor *)(v2 - 144))->CanAct() )
+      {
+        //UNDEF(v3);
+        if ( !(v4 | v5) )
+        {
+          if ( stru_50C198.GetMagicalResistance((Actor *)(v2 - 144), 0xAu) )
+          {
+            ((SpellBuff *)&v2[16 * v1->field_48 + 68])->Apply(
+              pParty->uTimePlayed + (signed int)(signed __int64)((double)(v1->field_4C << 7) * 0.033333335),
+              v1->field_50,
+              4u,
+              0,
+              0);
+            *(v2 - 106) |= 8u;
+          }
+        }
+      }
+      ++v6;
+      v2 += 836;
+    }
+    while ( v6 < (signed int)uNumActors );
+  }
+}
+
+
+//----- (0046BFFA) --------------------------------------------------------
+bool __fastcall _46BFFA_check_object_intercept(unsigned int uLayingItemID, signed int a2)
+{
+  LayingItem *v2; // esi@1
+  ObjectDesc *v3; // ebx@1
+  unsigned __int16 v5; // cx@9
+  unsigned __int16 v6; // cx@14
+  signed int v7; // edx@14
+  unsigned int v8; // eax@19
+  unsigned int v9; // edi@19
+  signed int v10; // ebx@19
+  char *v11; // edx@20
+  unsigned __int16 v12; // ax@23
+  int v13; // eax@27
+  unsigned int v14; // ebx@33
+  unsigned __int16 v15; // ax@35
+  int v16; // eax@36
+  unsigned int v17; // eax@37
+  __int16 v18; // di@37
+  signed int v19; // edx@37
+  unsigned __int8 v20; // sf@37
+  char *v21; // ecx@38
+  unsigned __int16 v22; // ax@41
+  unsigned int v23; // eax@46
+  signed int v24; // ebx@46
+  char *v25; // edx@47
+  int v26; // edx@54
+  int v27; // edx@55
+  int v28; // edx@56
+  int v29; // edx@57
+  unsigned __int16 v30; // ax@60
+  unsigned int v31; // ecx@60
+  int v32; // edi@60
+  unsigned int v33; // eax@65
+  signed int v34; // edx@65
+  char *v35; // ecx@66
+  unsigned __int16 v36; // ax@69
+  int v37; // ST14_4@72
+  int v38; // eax@72
+  int v39; // ST10_4@72
+  int v40; // ST0C_4@72
+  int v41; // edx@76
+  int v42; // edx@77
+  int v43; // edx@78
+  unsigned __int8 v44; // zf@79
+  int v45; // edx@79
+  unsigned __int16 v46; // ax@80
+  int v47; // eax@81
+  int v48; // edx@87
+  int v49; // edx@88
+  int v50; // edx@89
+  unsigned int v51; // eax@93
+  signed int v52; // ebx@93
+  char *v53; // edx@94
+  unsigned __int16 v54; // ax@98
+  unsigned int v55; // ecx@98
+  signed int v56; // ebx@98
+  char *v57; // edx@99
+  unsigned __int16 v58; // ax@102
+  unsigned __int16 v59; // ax@107
+  unsigned int v60; // ecx@107
+  signed int v61; // ebx@107
+  char *v62; // edx@108
+  unsigned __int16 v63; // ax@111
+  int v64; // ebx@114
+  signed int v65; // eax@114
+  unsigned int v66; // edi@123
+  unsigned __int16 v67; // ax@124
+  unsigned int v68; // ecx@124
+  signed int v69; // ebx@124
+  char *v70; // edx@125
+  unsigned __int16 v71; // ax@128
+  unsigned int v72; // ebx@131
+  int v73; // ST14_4@132
+  int v74; // ST10_4@132
+  int v75; // ebx@132
+  int v76; // ST0C_4@132
+  unsigned __int16 v77; // ax@132
+  int v78; // eax@133
+  char v79; // zf@139
+  unsigned int v80; // eax@140
+  signed int v81; // edx@140
+  char *v82; // ecx@141
+  unsigned __int16 v83; // ax@144
+  unsigned __int16 v84; // ax@151
+  unsigned int v85; // ecx@151
+  signed int v86; // ebx@151
+  char *v87; // edx@152
+  unsigned __int16 v88; // ax@155
+  unsigned int v89; // eax@158
+  int v90; // ST34_4@159
+  int v91; // eax@159
+  unsigned int v92; // eax@163
+  unsigned int v93; // eax@177
+  char *v94; // ecx@178
+  unsigned __int16 v95; // ax@181
+  unsigned __int16 v96; // ax@184
+  int v97; // eax@185
+  unsigned __int16 v98; // ax@191
+  unsigned int v99; // ecx@191
+  char v100; // ST18_1@198
+  int v101; // ST14_4@198
+  int v102; // eax@198
+  int v103; // ST10_4@198
+  int v104; // ST0C_4@198
+  unsigned __int16 v105; // ax@200
+  signed int v106; // eax@208
+  unsigned int v107; // edx@220
+  signed int v108; // ebx@225
+  unsigned int v109; // eax@234
+  signed int v110; // ebx@234
+  char *v111; // ecx@235
+  unsigned __int16 v112; // ax@238
+  unsigned __int16 v113; // si@241
+  int v114; // eax@242
+  int v115; // eax@245
+  signed int v116; // eax@245
+  unsigned __int16 v117; // ax@251
+  unsigned int v118; // ecx@251
+  signed int v119; // ebx@251
+  char *v120; // edx@252
+  unsigned __int16 v121; // ax@255
+  unsigned int v122; // eax@260
+  char *v123; // edx@261
+  int v124; // eax@267
+  int v125; // [sp-20h] [bp-4Ch]@28
+  signed int v126; // [sp-1Ch] [bp-48h]@27
+  unsigned int v127; // [sp-18h] [bp-44h]@27
+  signed int v128; // [sp-14h] [bp-40h]@27
+  signed int v129; // [sp-10h] [bp-3Ch]@27
+  int v130; // [sp-Ch] [bp-38h]@27
+  unsigned int v131; // [sp-8h] [bp-34h]@27
+  char v132; // [sp-8h] [bp-34h]@131
+  int v133; // [sp-4h] [bp-30h]@27
+  char v134; // [sp-4h] [bp-30h]@131
+  signed int v135; // [sp-4h] [bp-30h]@217
+  int v136; // [sp+Ch] [bp-20h]@208
+  int v137; // [sp+10h] [bp-1Ch]@208
+  signed int v138; // [sp+14h] [bp-18h]@207
+  signed int v139; // [sp+18h] [bp-14h]@208
+  char *v140; // [sp+1Ch] [bp-10h]@61
+  signed int v141; // [sp+1Ch] [bp-10h]@117
+  unsigned int v142; // [sp+1Ch] [bp-10h]@158
+  signed int v143; // [sp+1Ch] [bp-10h]@172
+  char *v144; // [sp+1Ch] [bp-10h]@192
+  signed int v145; // [sp+20h] [bp-Ch]@1
+  signed int v146; // [sp+20h] [bp-Ch]@60
+  int v147; // [sp+20h] [bp-Ch]@72
+  signed int v148; // [sp+20h] [bp-Ch]@158
+  int v149; // [sp+20h] [bp-Ch]@198
+  unsigned __int16 v150; // [sp+20h] [bp-Ch]@208
+  int v151; // [sp+24h] [bp-8h]@1
+  signed int v152; // [sp+24h] [bp-8h]@208
+  unsigned int v153; // [sp+28h] [bp-4h]@1
+
+  v153 = uLayingItemID;
+  v2 = &pLayingItems[uLayingItemID];
+  v3 = &pObjectList->pObjects[v2->uObjectDescID];
+  v145 = a2;
+  v151 = a2 & 7;
+  if ( (a2 & 7) == 3 )
+  {
+    if ( (v2->field_58 & 7) == 3 && !pActors[v2->field_58 >> 3].GetActorsRelation(&pActors[a2 >> 3]) )
+      return 1;
+  }
+  else
+  {
+    if ( (a2 & 7) == 4 && (v2->field_58 & 7) == 4 )
+      return 1;
+  }
+  if ( pParty->bTurnBasedModeOn == 1 )
+  {
+    v5 = v2->uAttributes;
+    if ( v5 & 4 )
+    {
+      --pTurnEngine->field_1C;
+      v2->uAttributes = v5 & 0xFFFB;
+    }
+  }
+  if ( v151 == 6 && (v2->field_58 & 7) != 4 )
+    BYTE2(pActors[v2->field_58 >> 3].uAttributes) |= 4u;
+  v6 = v2->uItemType;
+  v7 = v2->uItemType;
+  if ( v7 > 3060 )
+  {
+    if ( v7 > 6090 )
+    {
+      if ( v7 > 8090 )
+      {
+        if ( v7 == 9010 )
+          goto LABEL_247;
+        if ( v7 != 9030 )
+        {
+          if ( v7 != 9040 )
+          {
+            if ( v7 != 9080 )
+              return 0;
+LABEL_191:
+            v98 = v6 + 1;
+            v99 = pObjectList->uNumObjects;
+            v32 = 0;
+            v2->uItemType = v98;
+            v146 = 0;
+            if ( (signed int)v99 > 0 )
+            {
+              v144 = (char *)&pObjectList->pObjects->uObjectID;
+              while ( v98 != *(short *)v144 )
+              {
+                ++v146;
+                v144 += 56;
+                if ( v146 >= (signed int)v99 )
+                  goto LABEL_195;
+              }
+              goto LABEL_80;
+            }
+LABEL_195:
+            v46 = 0;
+            goto LABEL_196;
+          }
+          goto LABEL_93;
+        }
+LABEL_172:
+        v143 = 17030;
+        switch ( v6 )
+        {
+          case 0x1798u:
+            v143 = 15040;
+            break;
+          case 0xFAAu:
+            v143 = 13010;
+            break;
+          case 0x2346u:
+            v143 = 18030;
+            break;
+        }
+        v138 = 1;
+        if ( v151 != 3 )
+        {
+          if ( v6 != 9030 || v2->field_50 != 4 )
+            goto LABEL_246;
+          v2->_46BEF1_apply_spells();
+LABEL_233:
+          if ( !v138 )
+          {
+            v109 = pObjectList->uNumObjects;
+            ++v2->uItemType;
+            v110 = 0;
+            if ( (signed int)v109 <= 0 )
+            {
+LABEL_238:
+              v112 = 0;
+            }
+            else
+            {
+              v111 = (char *)&pObjectList->pObjects->uObjectID;
+              while ( v2->uItemType != *(short *)v111 )
+              {
+                ++v110;
+                v111 += 56;
+                if ( v110 >= (signed int)v109 )
+                  goto LABEL_238;
+              }
+              v112 = v110;
+            }
+            v2->uObjectDescID = v112;
+            if ( !v112 )
+              LayingItem::_42F933(v153);
+            v2->vVelocity.z = 0;
+            v2->vVelocity.y = 0;
+            v2->vVelocity.x = 0;
+            v2->uSpriteFrameID = 0;
+            v113 = v2->uSoundID;
+            if ( v113 )
+              v114 = (signed __int16)v113 + 4;
+            else
+              v114 = 0;
+            v133 = 0;
+            v131 = 0;
+            v130 = v114;
+            v115 = 8 * v153;
+            v129 = 0;
+            v128 = -1;
+            LOBYTE(v115) = 8 * v153 | 2;
+            v127 = 0;
+            v126 = v115;
+            v116 = v143;
+            goto LABEL_269;
+          }
+LABEL_246:
+          LayingItem::_42F933(v153);
+          return 0;
+        }
+        v106 = v145;
+        v150 = 0;
+        v139 = v106 >> 3;
+        v137 = v2->field_4C;
+        v152 = v2->field_50;
+        v136 = v2->field_48;
+        if ( v6 == 9030 )
+        {
+          v150 = 2;
+          if ( v152 == 2 )
+          {
+            v150 = 3;
+          }
+          else
+          {
+            if ( v152 >= 3 )
+              v150 = 4;
+          }
+          BYTE2(pActors[v139].uAttributes) |= 8u;
+        }
+        if ( v7 == 6040 )
+        {
+          v135 = 7;
+        }
+        else
+        {
+          if ( v7 == 8030 )
+          {
+            v135 = 9;
+          }
+          else
+          {
+            if ( v7 != 9030 )
+            {
+              v107 = v136;
+LABEL_222:
+              if ( v6 != 9030 || v152 != 4 )
+              {
+                v108 = v139;
+                if ( stru_50C198.GetMagicalResistance(&pActors[v139], v107) )
+                {
+                  v138 = 0;
+                  if ( v2->uItemType == 8030 )
+                  {
+                    pActors[v108].uAIState = Standing;
+                    pActors[v108].UpdateAnimation();
+                  }
+                  ((SpellBuff *)((char *)&pActors[0].pActorBuffs[v136] + v108 * 836))->Apply(
+                    pParty->uTimePlayed + (signed int)(signed __int64)((double)(v137 << 7) * 0.033333335),
+                    v152,
+                    v150,
+                    0,
+                    0);
+                }
+              }
+              else
+              {
+                v2->_46BEF1_apply_spells();
+              }
+              v2->field_4C = 0;
+              v2->field_50 = 0;
+              v2->field_48 = 0;
+              goto LABEL_233;
+            }
+            v135 = 10;
+          }
+        }
+        v107 = v135;
+        goto LABEL_222;
+      }
+      if ( v7 == 8090 || v7 == 7030 || v7 == 7090 || v7 == 8000 )
+        goto LABEL_93;
+      if ( v7 == 8010 )
+      {
+        if ( v151 == 3
+          && MonsterStats::BelongsToSupertype(pActors[v145 >> 3].pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD) )
+          sub_43A97E(v153, v145);
+        v93 = pObjectList->uNumObjects;
+        ++v2->uItemType;
+        v9 = 0;
+        v52 = 0;
+        if ( (signed int)v93 > 0 )
+        {
+          v94 = (char *)&pObjectList->pObjects->uObjectID;
+          while ( v2->uItemType != *(short *)v94 )
+          {
+            ++v52;
+            v94 += 56;
+            if ( v52 >= (signed int)v93 )
+              goto LABEL_181;
+          }
+          goto LABEL_202;
+        }
+        goto LABEL_181;
+      }
+      v79 = v7 == 8030;
+    }
+    else
+    {
+      if ( v7 == 6090 )
+        goto LABEL_93;
+      if ( v7 <= 4070 )
+      {
+        if ( v7 != 4070 )
+        {
+          v48 = v7 - 3090;
+          if ( v48 )
+          {
+            v49 = v48 - 2;
+            if ( v49 )
+            {
+              v50 = v49 - 908;
+              if ( !v50 )
+                goto LABEL_93;
+              v45 = v50 - 30;
+              v44 = v45 == 0;
+              goto LABEL_91;
+            }
+            v54 = v6 - 1;
+            v55 = pObjectList->uNumObjects;
+            v9 = 0;
+            v56 = 0;
+            v44 = pObjectList->uNumObjects == 0;
+            v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+            v2->uItemType = v54;
+            if ( v20 | v44 )
+            {
+LABEL_102:
+              v58 = 0;
+            }
+            else
+            {
+              v57 = (char *)&pObjectList->pObjects->uObjectID;
+              while ( v54 != *(short *)v57 )
+              {
+                ++v56;
+                v57 += 56;
+                if ( v56 >= (signed int)v55 )
+                  goto LABEL_102;
+              }
+              v58 = v56;
+            }
+            v2->uObjectDescID = v58;
+            if ( !v58 )
+              LayingItem::_42F933(v153);
+            v14 = v153;
+            v2->vVelocity.z = 0;
+            v2->vVelocity.y = 0;
+            v2->vVelocity.x = 0;
+            v2->uSpriteFrameID = 0;
+            sub_43A97E(v153, v145);
+LABEL_35:
+            v15 = v2->uSoundID;
+            if ( v15 == (short)v9 )
+              v16 = 0;
+            else
+              v16 = (signed __int16)v15 + 4;
+            v133 = v9;
+            v131 = v9;
+            v130 = v16;
+            v92 = v14;
+LABEL_267:
+            v124 = 8 * v92;
+            v129 = v9;
+            v128 = -1;
+            LOBYTE(v124) = v124 | 2;
+            v127 = v9;
+            v126 = v124;
+LABEL_268:
+            v116 = word_4EE088_sound_ids[v2->field_48];
+LABEL_269:
+            v125 = v116 + 1;
+            goto LABEL_29;
+          }
+          v59 = v6 + 2;
+          v60 = pObjectList->uNumObjects;
+          v9 = 0;
+          v61 = 0;
+          v44 = pObjectList->uNumObjects == 0;
+          v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+          v2->uItemType = v59;
+          if ( v20 | v44 )
+          {
+LABEL_111:
+            v63 = 0;
+          }
+          else
+          {
+            v62 = (char *)&pObjectList->pObjects->uObjectID;
+            while ( v59 != *(short *)v62 )
+            {
+              ++v61;
+              v62 += 56;
+              if ( v61 >= (signed int)v60 )
+                goto LABEL_111;
+            }
+            v63 = v61;
+          }
+          v2->uObjectDescID = v63;
+          if ( !v63 )
+            LayingItem::_42F933(v153);
+          v64 = v2->uFacing - stru_5C6E00->uIntegerDoublePi;
+          v44 = v2->field_50 == 4;
+          v2->vVelocity.z = 0;
+          v2->vVelocity.y = 0;
+          v2->vVelocity.x = 0;
+          v65 = 7;
+          if ( v44 )
+            v65 = 9;
+          if ( v65 > 0 )
+          {
+            v141 = v65;
+            do
+            {
+              v64 += (signed int)stru_5C6E00->uIntegerHalfPi >> 1;
+              v2->Create(v64, 0, 1000, 0);
+              --v141;
+            }
+            while ( v141 );
+          }
+LABEL_160:
+          v14 = v153;
+LABEL_34:
+          LayingItem::_42F933(v14);
+          goto LABEL_35;
+        }
+        if ( v151 == 6 || v151 == 5 || (v66 = 0, !v151) )
+          return 1;
+        v67 = v6 + 1;
+        v68 = pObjectList->uNumObjects;
+        v69 = 0;
+        v44 = pObjectList->uNumObjects == 0;
+        v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+        v2->uItemType = v67;
+        if ( v20 | v44 )
+        {
+LABEL_128:
+          v71 = 0;
+        }
+        else
+        {
+          v70 = (char *)&pObjectList->pObjects->uObjectID;
+          while ( v67 != *(short *)v70 )
+          {
+            ++v69;
+            v70 += 56;
+            if ( v69 >= (signed int)v68 )
+              goto LABEL_128;
+          }
+          v71 = v69;
+        }
+        v2->uObjectDescID = v71;
+        if ( !v71 )
+          LayingItem::_42F933(v153);
+        v134 = 0;
+        v72 = v153;
+        v132 = 0;
+LABEL_132:
+        v73 = v2->vPosition.z;
+        v74 = v2->vPosition.y;
+        v75 = 8 * v72 | 2;
+        v2->vVelocity.z = v66;
+        v2->vVelocity.y = v66;
+        v76 = v2->vPosition.x;
+        v2->vVelocity.x = v66;
+        v2->uSpriteFrameID = v66;
+        stru_50FE08.Add(v75, 512, v76, v74, v73, v132, v134);
+        v77 = v2->uSoundID;
+        if ( v77 == (short)v66 )
+          v78 = 0;
+        else
+          v78 = (signed __int16)v77 + 4;
+        v133 = v66;
+        v131 = v66;
+        v130 = v78;
+        v129 = v66;
+        v128 = -1;
+        v127 = v66;
+        v126 = v75;
+        goto LABEL_268;
+      }
+      if ( v7 == 4090 )
+      {
+        v84 = v6 + 2;
+        v85 = pObjectList->uNumObjects;
+        v9 = 0;
+        v86 = 0;
+        v44 = pObjectList->uNumObjects == 0;
+        v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+        v2->uItemType = v84;
+        if ( v20 | v44 )
+        {
+LABEL_155:
+          v88 = 0;
+        }
+        else
+        {
+          v87 = (char *)&pObjectList->pObjects->uObjectID;
+          while ( v84 != *(short *)v87 )
+          {
+            ++v86;
+            v87 += 56;
+            if ( v86 >= (signed int)v85 )
+              goto LABEL_155;
+          }
+          v88 = v86;
+        }
+        v2->uObjectDescID = v88;
+        if ( !v88 )
+          LayingItem::_42F933(v153);
+        v89 = v2->uFacing - stru_5C6E00->uIntegerDoublePi;
+        v2->vVelocity.z = 0;
+        v2->vVelocity.y = 0;
+        v2->vVelocity.x = 0;
+        v142 = v89;
+        v148 = 7;
+        do
+        {
+          pRnd->SetRange(-128, 128);
+          v90 = pRnd->GetInRange();
+          pRnd->SetRange(5, 500);
+          v91 = pRnd->GetInRange();
+          v142 += (signed int)stru_5C6E00->uIntegerHalfPi >> 1;
+          v2->Create(v90 + v142, 0, v91, 0);
+          --v148;
+        }
+        while ( v148 );
+        goto LABEL_160;
+      }
+      if ( v7 == 4092 )
+      {
+        v80 = pObjectList->uNumObjects;
+        v66 = 0;
+        v81 = 0;
+        v44 = pObjectList->uNumObjects == 0;
+        v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+        v2->uItemType = 4091;
+        if ( v20 | v44 )
+        {
+LABEL_144:
+          v83 = 0;
+        }
+        else
+        {
+          v82 = (char *)&pObjectList->pObjects->uObjectID;
+          while ( *(short *)v82 != 4091 )
+          {
+            ++v81;
+            v82 += 56;
+            if ( v81 >= (signed int)v80 )
+              goto LABEL_144;
+          }
+          v83 = v81;
+        }
+        v2->uObjectDescID = v83;
+        if ( !v83 )
+          LayingItem::_42F933(v153);
+        v134 = 0;
+        v72 = v153;
+        v132 = v2->field_61;
+        goto LABEL_132;
+      }
+      if ( v7 == 4100 || v7 == 6010 )
+        goto LABEL_93;
+      v79 = v7 == 6040;
+    }
+    if ( !v79 )
+      return 0;
+    goto LABEL_172;
+  }
+  if ( v7 == 3060 )
+    goto LABEL_93;
+  if ( v7 <= 555 )
+  {
+    if ( v7 == 555 )
+    {
+      sub_43A97E(v153, v145);
+      v23 = pObjectList->uNumObjects;
+      ++v2->uItemType;
+      v18 = 0;
+      v24 = 0;
+      if ( (signed int)v23 <= 0 )
+      {
+LABEL_41:
+        v22 = 0;
+      }
+      else
+      {
+        v25 = (char *)&pObjectList->pObjects->uObjectID;
+        while ( v2->uItemType != *(short *)v25 )
+        {
+          ++v24;
+          v25 += 56;
+          if ( v24 >= (signed int)v23 )
+            goto LABEL_41;
+        }
+        v22 = v24;
+      }
+LABEL_42:
+      v2->uObjectDescID = v22;
+      if ( v22 == v18 )
+        LayingItem::_42F933(v153);
+      v2->vVelocity.z = v18;
+      v2->vVelocity.y = v18;
+      v2->vVelocity.x = v18;
+      v2->uSpriteFrameID = v18;
+    }
+    else
+    {
+      switch ( v7 )
+      {
+        case 500:
+        case 505:
+        case 510:
+        case 515:
+        case 520:
+        case 525:
+        case 530:
+        case 535:
+        case 540:
+          sub_43A97E(v153, v145);
+          v8 = pObjectList->uNumObjects;
+          ++v2->uItemType;
+          v9 = 0;
+          v10 = 0;
+          if ( (signed int)v8 <= 0 )
+            goto LABEL_23;
+          v11 = (char *)&pObjectList->pObjects->uObjectID;
+          break;
+        case 545:
+        case 550:
+          if ( v2->stru_24.uItemID != 405 && v2->stru_24.uAdditionalValue != 3 )
+          {
+            v14 = v153;
+            v9 = 0;
+            v2->vVelocity.z = 0;
+            v2->vVelocity.y = 0;
+            v2->vVelocity.x = 0;
+            v2->uSpriteFrameID = 0;
+            sub_43A97E(v153, v145);
+            goto LABEL_34;
+          }
+          v17 = pObjectList->uNumObjects;
+          v18 = 0;
+          v19 = 0;
+          v44 = pObjectList->uNumObjects == 0;
+          v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+          v2->uItemType = 600;
+          if ( v20 | v44 )
+            goto LABEL_41;
+          v21 = (char *)&pObjectList->pObjects->uObjectID;
+          while ( *(short *)v21 != 600 )
+          {
+            ++v19;
+            v21 += 56;
+            if ( v19 >= (signed int)v17 )
+              goto LABEL_41;
+          }
+          v22 = v19;
+          goto LABEL_42;
+        default:
+          return 0;
+      }
+      while ( v2->uItemType != *(short *)v11 )
+      {
+        ++v10;
+        v11 += 56;
+        if ( v10 >= (signed int)v8 )
+        {
+LABEL_23:
+          v12 = 0;
+          goto LABEL_24;
+        }
+      }
+      v12 = v10;
+LABEL_24:
+      v2->uObjectDescID = v12;
+      if ( !v12 )
+        LayingItem::_42F933(v153);
+      v44 = v2->uItemType == 555;
+      v2->vVelocity.z = 0;
+      v2->vVelocity.y = 0;
+      v2->vVelocity.x = 0;
+      v2->uSpriteFrameID = 0;
+      if ( !v44 )
+        goto LABEL_27;
+    }
+    return 0;
+  }
+  if ( v7 > 1100 )
+  {
+    v41 = v7 - 2030;
+    if ( !v41 )
+      goto LABEL_247;
+    v42 = v41 - 30;
+    if ( v42 )
+    {
+      v43 = v42 - 40;
+      if ( !v43 )
+        goto LABEL_59;
+      v45 = v43 - 910;
+      v44 = v45 == 0;
+LABEL_91:
+      if ( !v44 && v45 != 20 )
+        return 0;
+    }
+LABEL_93:
+    sub_43A97E(v153, v145);
+    v51 = pObjectList->uNumObjects;
+    ++v2->uItemType;
+    v9 = 0;
+    v52 = 0;
+    if ( (signed int)v51 > 0 )
+    {
+      v53 = (char *)&pObjectList->pObjects->uObjectID;
+      while ( v2->uItemType != *(short *)v53 )
+      {
+        ++v52;
+        v53 += 56;
+        if ( v52 >= (signed int)v51 )
+          goto LABEL_181;
+      }
+      goto LABEL_202;
+    }
+LABEL_181:
+    v95 = 0;
+LABEL_182:
+    v2->uObjectDescID = v95;
+    if ( v95 == (short)v9 )
+      LayingItem::_42F933(v153);
+    v96 = v2->uSoundID;
+    v2->vVelocity.z = v9;
+    v2->vVelocity.y = v9;
+    v2->vVelocity.x = v9;
+    v2->uSpriteFrameID = v9;
+    if ( v96 == (short)v9 )
+      v97 = 0;
+    else
+      v97 = (signed __int16)v96 + 4;
+    v133 = v9;
+    v131 = v9;
+    v130 = v97;
+    v92 = v153;
+    goto LABEL_267;
+  }
+  if ( v7 == 1100 )
+    goto LABEL_93;
+  v26 = v7 - 600;
+  if ( !v26 )
+  {
+    v33 = pObjectList->uNumObjects;
+    v34 = 0;
+    v44 = pObjectList->uNumObjects == 0;
+    v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+    v2->uItemType = 601;
+    if ( v20 | v44 )
+    {
+LABEL_69:
+      v36 = 0;
+    }
+    else
+    {
+      v35 = (char *)&pObjectList->pObjects->uObjectID;
+      while ( *(short *)v35 != 601 )
+      {
+        ++v34;
+        v35 += 56;
+        if ( v34 >= (signed int)v33 )
+          goto LABEL_69;
+      }
+      v36 = v34;
+    }
+    v2->uObjectDescID = v36;
+    if ( !v36 )
+      LayingItem::_42F933(v153);
+    v37 = v2->vPosition.z;
+    v2->vVelocity.z = 0;
+    v38 = 8 * v153;
+    v39 = v2->vPosition.y;
+    LOBYTE(v38) = 8 * v153 | 2;
+    v2->vVelocity.y = 0;
+    v2->vVelocity.x = 0;
+    v40 = v2->vPosition.x;
+    v2->uSpriteFrameID = 0;
+    v147 = v38;
+    stru_50FE08.Add(v38, 512, v40, v39, v37, 0, 0);
+    if ( HIBYTE(v3->uFlags) & 1 )
+      array_5118E8._440E91(v2->vPosition.x, v2->vPosition.y, v2->vPosition.z, 0, v3->uParticleTrailColor);
+    v133 = 0;
+    v131 = 0;
+    v130 = 0;
+    v129 = 0;
+    v128 = -1;
+    v127 = 0;
+    v126 = v147;
+    goto LABEL_28;
+  }
+  v27 = v26 - 410;
+  if ( !v27 )
+    goto LABEL_93;
+  v28 = v27 - 40;
+  if ( !v28 )
+    goto LABEL_191;
+  v29 = v28 - 10;
+  if ( v29 )
+  {
+    if ( v29 != 20 )
+      return 0;
+LABEL_59:
+    if ( v151 != 3 )
+    {
+      v30 = v6 + 1;
+      v31 = pObjectList->uNumObjects;
+      v32 = 0;
+      v2->uItemType = v30;
+      v146 = 0;
+      if ( (signed int)v31 > 0 )
+      {
+        v140 = (char *)&pObjectList->pObjects->uObjectID;
+        while ( v30 != *(short *)v140 )
+        {
+          ++v146;
+          v140 += 56;
+          if ( v146 >= (signed int)v31 )
+            goto LABEL_195;
+        }
+LABEL_80:
+        v46 = v146;
+LABEL_196:
+        v2->uObjectDescID = v46;
+        if ( v46 == (short)v32 )
+          LayingItem::_42F933(v153);
+        v100 = v2->field_61;
+        v101 = v2->vPosition.z;
+        v2->uSpriteFrameID = v32;
+        v102 = 8 * v153;
+        v103 = v2->vPosition.y;
+        LOBYTE(v102) = 8 * v153 | 2;
+        v2->vVelocity.x = v32;
+        v2->vVelocity.y = v32;
+        v104 = v2->vPosition.x;
+        v2->vVelocity.z = v32;
+        v149 = v102;
+        stru_50FE08.Add(v102, 512, v104, v103, v101, v100, v32);
+        if ( HIBYTE(v3->uFlags) & 1 )
+          array_5118E8._440E91(
+            v2->vPosition.x,
+            v2->vPosition.y,
+            v2->vPosition.z,
+            v32,
+            v3->uParticleTrailColor);
+        v105 = v2->uSoundID;
+        if ( v105 == (short)v32 )
+          v47 = 0;
+        else
+          v47 = (signed __int16)v105 + 4;
+        v133 = v32;
+        v131 = v32;
+        v130 = v47;
+        v129 = v32;
+        v128 = -1;
+        v127 = v32;
+        v126 = v149;
+        goto LABEL_268;
+      }
+      goto LABEL_195;
+    }
+    return 1;
+  }
+LABEL_247:
+  if ( v151 == 6 || v151 == 5 || (v9 = 0, !v151) )
+    return 1;
+  if ( v151 != 2 )
+  {
+    sub_43A97E(v153, v145);
+    v122 = pObjectList->uNumObjects;
+    ++v2->uItemType;
+    v52 = 0;
+    if ( (signed int)v122 > 0 )
+    {
+      v123 = (char *)&pObjectList->pObjects->uObjectID;
+      while ( v2->uItemType != *(short *)v123 )
+      {
+        ++v52;
+        v123 += 56;
+        if ( v52 >= (signed int)v122 )
+          goto LABEL_181;
+      }
+LABEL_202:
+      v95 = v52;
+      goto LABEL_182;
+    }
+    goto LABEL_181;
+  }
+  v117 = v6 + 1;
+  v118 = pObjectList->uNumObjects;
+  v119 = 0;
+  v44 = pObjectList->uNumObjects == 0;
+  v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
+  v2->uItemType = v117;
+  if ( v20 | v44 )
+  {
+LABEL_255:
+    v121 = 0;
+  }
+  else
+  {
+    v120 = (char *)&pObjectList->pObjects->uObjectID;
+    while ( v117 != *(short *)v120 )
+    {
+      ++v119;
+      v120 += 56;
+      if ( v119 >= (signed int)v118 )
+        goto LABEL_255;
+    }
+    v121 = v119;
+  }
+  v2->uObjectDescID = v121;
+  if ( !v121 )
+    LayingItem::_42F933(v153);
+  v2->vVelocity.z = 0;
+  v2->vVelocity.y = 0;
+  v2->vVelocity.x = 0;
+  v2->uSpriteFrameID = 0;
+LABEL_27:
+  v133 = v9;
+  v131 = v9;
+  v130 = v9;
+  v13 = 8 * v153;
+  v129 = v9;
+  v128 = -1;
+  LOBYTE(v13) = 8 * v153 | 2;
+  v127 = v9;
+  v126 = v13;
+LABEL_28:
+  v125 = 8;
+LABEL_29:
+  pAudioPlayer->PlaySound((SoundID)v125, v126, v127, v128, v129, v130, v131, v133);
+  return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mm7_3.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,21428 @@
+#include "MapInfo.h"
+#include "Game.h"
+#include "GUIWindow.h"
+#include "GUIFont.h"
+#include "GUIButton.h"
+#include "GUIProgressBar.h"
+#include "Party.h"
+#include "AudioPlayer.h"
+#include "Outdoor.h"
+#include "IndoorCamera.h"
+#include "Overlays.h"
+#include "Monsters.h"
+#include "Arcomage.h"
+#include "LOD.h"
+#include "Actor.h"
+#include "Allocator.h"
+#include "Events.h"
+#include "Viewport.h"
+#include "FrameTableInc.h"
+#include "Math.h"
+#include "LayingItem.h"
+#include "ObjectList.h"
+#include "Chest.h"
+#include "PaletteManager.h"
+#include "DecorationList.h"
+#include "SaveLoad.h"
+#include "stru123.h"
+#include "stru287.h"
+#include "Time.h"
+#include "IconFrameTable.h"
+#include "TurnEngine.h"
+#include "Awards.h"
+#include "Autonotes.h"
+#include "stru160.h"
+#include "stru279.h"
+#include "Weather.h"
+#include "stru220.h"
+#include "Events2D.h"
+#include "stru176.h"
+#include "stru159.h"
+#include "stru298.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+
+
+//----- (0046E44E) --------------------------------------------------------
+int __thiscall _46E44E_collide_against_faces_and_portals(unsigned int b1)
+{
+  BLVSector *v1; // edi@1
+  signed int v2; // ebx@1
+  BLVFace *v3; // esi@2
+  __int16 v4; // si@10
+  int v5; // ecx@12
+  unsigned __int8 v6; // sf@12
+  unsigned __int8 v7; // of@12
+  int result; // eax@14
+  BLVSector *v9; // ebx@15
+  int v10; // ecx@15
+  int v11; // eax@16
+  BLVFace *v12; // ebp@16
+  int v13; // eax@24
+  int v14; // esi@24
+  int v15; // eax@24
+  int v16; // edx@25
+  int v17; // eax@29
+  unsigned int v18; // eax@33
+  int v19; // eax@35
+  int v20; // edx@35
+  int v21; // eax@35
+  int v22; // ecx@36
+  int v23; // eax@40
+  unsigned int v24; // eax@44
+  int a3; // [sp+10h] [bp-48h]@28
+  int v26; // [sp+14h] [bp-44h]@15
+  int i; // [sp+18h] [bp-40h]@1
+  int a10; // [sp+1Ch] [bp-3Ch]@1
+  int v29; // [sp+20h] [bp-38h]@14
+  int v30; // [sp+24h] [bp-34h]@35
+  int v31; // [sp+28h] [bp-30h]@24
+  int v32; // [sp+2Ch] [bp-2Ch]@15
+  int v33[10]; // [sp+30h] [bp-28h]@1
+
+  v1 = &pIndoor->pSectors[stru_721530.uSectorID];
+  v2 = 0;
+  a10 = b1;
+  v33[0] = stru_721530.uSectorID;
+  for ( i = 1; v2 < v1->uNumPortals; ++v2 )
+  {
+    v3 = &pIndoor->pFaces[v1->pPortals[v2]];
+    if ( stru_721530.sMaxX <= v3->pBounding.x2
+      && stru_721530.sMinX >= v3->pBounding.x1
+      && stru_721530.sMaxY <= v3->pBounding.y2
+      && stru_721530.sMinY >= v3->pBounding.y1
+      && stru_721530.sMaxZ <= v3->pBounding.z2
+      && stru_721530.sMinZ >= v3->pBounding.z1
+      && abs((v3->pFacePlane_old.dist
+            + stru_721530.normal.x * v3->pFacePlane_old.vNormal.x
+            + stru_721530.normal.y * v3->pFacePlane_old.vNormal.y
+            + stru_721530.normal.z * v3->pFacePlane_old.vNormal.z) >> 16) <= stru_721530.field_6C + 16 )
+    {
+      v4 = v3->uSectorID == stru_721530.uSectorID ? v3->uBackSectorID : v3->uSectorID;
+      v5 = i++;
+      v7 = __OFSUB__(i, 10);
+      v6 = i - 10 < 0;
+      v33[v5] = v4;
+      if ( !(v6 ^ v7) )
+        break;
+    }
+  }
+  result = 0;
+  v29 = 0;
+  if ( i > 0 )
+  {
+    while ( 1 )
+    {
+      v9 = &pIndoor->pSectors[v33[result]];
+      v10 = 0;
+      v32 = v9->uNumFloors + v9->field_C + v9->field_14;
+      v26 = 0;
+      if ( v32 > 0 )
+        break;
+LABEL_46:
+      result = v29++ + 1;
+      if ( v29 >= i )
+        return result;
+    }
+    while ( 1 )
+    {
+      v11 = v9->pFloors[v10];
+      v12 = &pIndoor->pFaces[v11];
+      if ( v12->uAttributes & 1
+        || stru_721530.sMaxX > v12->pBounding.x2
+        || stru_721530.sMinX < v12->pBounding.x1
+        || stru_721530.sMaxY > v12->pBounding.y2
+        || stru_721530.sMinY < v12->pBounding.y1
+        || stru_721530.sMaxZ > v12->pBounding.z2
+        || stru_721530.sMinZ < v12->pBounding.z1
+        || v11 == stru_721530.field_84 )
+        goto LABEL_45;
+      v13 = v12->pFacePlane_old.vNormal.y;
+      v14 = v12->pFacePlane_old.dist;
+      v31 = v13;
+      v15 = (stru_721530.normal.x * v12->pFacePlane_old.vNormal.x
+           + v14
+           + stru_721530.normal.y * v13
+           + stru_721530.normal.z * v12->pFacePlane_old.vNormal.z) >> 16;
+      if ( v15 > 0 )
+      {
+        v16 = (stru_721530.normal2.y * v31
+             + v12->pFacePlane_old.dist
+             + stru_721530.normal2.z * v12->pFacePlane_old.vNormal.z
+             + stru_721530.normal2.x * v12->pFacePlane_old.vNormal.x) >> 16;
+        if ( v15 <= stru_721530.prolly_normal_d || v16 <= stru_721530.prolly_normal_d )
+        {
+          if ( v16 <= v15 )
+          {
+            a3 = stru_721530.field_6C;
+            if ( sub_47531C(
+                   stru_721530.prolly_normal_d,
+                   &a3,
+                   stru_721530.normal.x,
+                   stru_721530.normal.y,
+                   stru_721530.normal.z,
+                   stru_721530.field_58.x,
+                   stru_721530.field_58.y,
+                   stru_721530.field_58.z,
+                   v12,
+                   a10) )
+            {
+              v17 = a3;
+            }
+            else
+            {
+              a3 = stru_721530.field_6C + stru_721530.prolly_normal_d;
+              if ( !sub_475D85(&stru_721530.normal, &stru_721530.field_58, &a3, v12) )
+                goto LABEL_34;
+              v17 = a3 - stru_721530.prolly_normal_d;
+              a3 -= stru_721530.prolly_normal_d;
+            }
+            if ( v17 < stru_721530.field_7C )
+            {
+              stru_721530.field_7C = v17;
+              v18 = 8 * v9->pFloors[v26];
+              LOBYTE(v18) = v18 | 6;
+              stru_721530.uFaceID = v18;
+            }
+          }
+        }
+      }
+LABEL_34:
+      if ( !(stru_721530.field_0 & 1)
+        || (v19 = v12->pFacePlane_old.vNormal.x,
+            v20 = v12->pFacePlane_old.vNormal.y,
+            v30 = v19,
+            v21 = (stru_721530.field_34.x * v19
+                 + v12->pFacePlane_old.dist
+                 + stru_721530.field_34.y * v20
+                 + stru_721530.field_34.z * v12->pFacePlane_old.vNormal.z) >> 16,
+            v21 <= 0)
+        || (v22 = (stru_721530.field_4C * v30
+                 + v12->pFacePlane_old.dist
+                 + stru_721530.field_50 * v20
+                 + stru_721530.field_54 * v12->pFacePlane_old.vNormal.z) >> 16,
+            v21 > stru_721530.prolly_normal_d)
+        && v22 > stru_721530.prolly_normal_d
+        || v22 > v21 )
+        goto LABEL_45;
+      a3 = stru_721530.field_6C;
+      if ( sub_47531C(
+             stru_721530.field_8,
+             &a3,
+             stru_721530.field_34.x,
+             stru_721530.field_34.y,
+             stru_721530.field_34.z,
+             stru_721530.field_58.x,
+             stru_721530.field_58.y,
+             stru_721530.field_58.z,
+             v12,
+             a10) )
+      {
+        v23 = a3;
+        goto LABEL_43;
+      }
+      a3 = stru_721530.field_6C + stru_721530.field_8;
+      if ( sub_475D85(&stru_721530.field_34, &stru_721530.field_58, &a3, v12) )
+      {
+        v23 = a3 - stru_721530.prolly_normal_d;
+        a3 -= stru_721530.prolly_normal_d;
+LABEL_43:
+        if ( v23 < stru_721530.field_7C )
+        {
+          stru_721530.field_7C = v23;
+          v24 = 8 * v9->pFloors[v26];
+          LOBYTE(v24) = v24 | 6;
+          stru_721530.uFaceID = v24;
+        }
+      }
+LABEL_45:
+      v10 = v26++ + 1;
+      if ( v26 >= v32 )
+        goto LABEL_46;
+    }
+  }
+  return result;
+}
+// 46E44E: using guessed type int var_28[10];
+
+//----- (0046E889) --------------------------------------------------------
+int __fastcall _46E889_collide_against_bmodels(unsigned int ecx0)
+{
+  int result; // eax@1
+  BSPModel *v2; // ecx@3
+  int v3; // ebx@9
+  ODMFace *v4; // eax@11
+  int v5; // edi@17
+  int v6; // esi@17
+  unsigned int v7; // ecx@17
+  int v8; // eax@19
+  int v9; // ecx@20
+  int v10; // eax@24
+  int v11; // ST18_4@25
+  int v12; // ST1C_4@25
+  int v13; // ST0C_4@25
+  unsigned int v14; // eax@28
+  int v15; // eax@30
+  int v16; // ecx@31
+  unsigned int v17; // eax@36
+  int v18; // ST18_4@41
+  int v19; // ST1C_4@41
+  int v20; // ST0C_4@41
+  int v21; // eax@42
+  unsigned int v22; // eax@43
+  //BLVFace f; // [sp+Ch] [bp-7Ch]@1
+  int v24; // [sp+6Ch] [bp-1Ch]@9
+  int a11; // [sp+70h] [bp-18h]@1
+  unsigned int v26; // [sp+74h] [bp-14h]@2
+  unsigned int v27; // [sp+78h] [bp-10h]@10
+  BSPModel *v28; // [sp+7Ch] [bp-Ch]@3
+  int a10; // [sp+80h] [bp-8h]@1
+  int a2; // [sp+84h] [bp-4h]@23
+
+  a11 = ecx0;
+
+  BLVFace f; // [sp+Ch] [bp-7Ch]@1
+  //BLVFace::BLVFace(&f);
+
+  result = 0;
+  a10 = 0;
+  if ( (signed int)pOutdoor->uNumBModels > 0 )
+  {
+    v26 = 0;
+    while ( 1 )
+    {
+      v2 = &pOutdoor->pBModels[v26 / 0xBC];
+      v28 = &pOutdoor->pBModels[v26 / 0xBC];
+      if ( stru_721530.sMaxX <= pOutdoor->pBModels[v26 / 0xBC].sMaxX )
+      {
+        if ( stru_721530.sMinX >= v2->sMinX )
+        {
+          if ( stru_721530.sMaxY <= v2->sMaxY )
+          {
+            if ( stru_721530.sMinY >= v2->sMinY )
+            {
+              if ( stru_721530.sMaxZ <= v2->sMaxZ )
+              {
+                if ( stru_721530.sMinZ >= v2->sMinZ )
+                {
+                  v3 = 0;
+                  v24 = v2->uNumFaces;
+                  if ( v24 > 0 )
+                    break;
+                }
+              }
+            }
+          }
+        }
+      }
+LABEL_39:
+      ++a10;
+      v26 += 188;
+      result = a10;
+      if ( a10 >= (signed int)pOutdoor->uNumBModels )
+        return result;
+    }
+    v27 = 0;
+    while ( 1 )
+    {
+      v4 = &v2->pFaces[v27 / 0x134];
+      if ( stru_721530.sMaxX > v4->pBoundingBox.x2
+        || stru_721530.sMinX < v4->pBoundingBox.x1
+        || stru_721530.sMaxY > v4->pBoundingBox.y2
+        || stru_721530.sMinY < v4->pBoundingBox.y1
+        || stru_721530.sMaxZ > v4->pBoundingBox.z2
+        || stru_721530.sMinZ < v4->pBoundingBox.z1 )
+        goto LABEL_38;
+      f.pFacePlane_old.vNormal.x = v4->pFacePlane.vNormal.x;
+      f.pFacePlane_old.vNormal.y = v4->pFacePlane.vNormal.y;
+      v5 = v4->pFacePlane.vNormal.z;
+      f.pFacePlane_old.vNormal.z = v4->pFacePlane.vNormal.z;
+      v6 = v4->pFacePlane.dist;
+      f.pFacePlane_old.dist = v4->pFacePlane.dist;
+      v7 = v4->uAttributes;
+      f.uAttributes = v7;
+      f.pBounding.x1 = v4->pBoundingBox.x1;
+      f.pBounding.y1 = v4->pBoundingBox.y1;
+      f.pBounding.z1 = v4->pBoundingBox.z1;
+      f.pBounding.x2 = v4->pBoundingBox.x2;
+      f.pBounding.y2 = v4->pBoundingBox.y2;
+      f.pBounding.z2 = v4->pBoundingBox.z2;
+      f.zCalc1 = v4->zCalc1;
+      f.zCalc2 = v4->zCalc2;
+      f.zCalc3 = v4->zCalc3;
+      f.pXInterceptDisplacements = v4->pXInterceptDisplacements;
+      f.pYInterceptDisplacements = v4->pYInterceptDisplacements;
+      f.pZInterceptDisplacements = v4->pZInterceptDisplacements;
+      f.uPolygonType = (PolygonType)v4->uPolygonType;
+      f.uNumVertices = v4->uNumVertices;
+      f.uBitmapID = v4->uTextureID;
+      f.pVertexIDs = v4->pVertexIDs;
+      if ( !(v7 & 0x20000000) )
+      {
+        if ( !(v7 & 1) )
+          break;
+      }
+LABEL_37:
+      v2 = v28;
+LABEL_38:
+      v27 += 308;
+      ++v3;
+      if ( v3 >= v24 )
+        goto LABEL_39;
+    }
+    v8 = (v5 * stru_721530.normal.z
+        + v6
+        + f.pFacePlane_old.vNormal.y * stru_721530.normal.y
+        + f.pFacePlane_old.vNormal.x * stru_721530.normal.x) >> 16;
+    if ( v8 > 0 )
+    {
+      v9 = (v5 * stru_721530.normal2.z
+          + v6
+          + f.pFacePlane_old.vNormal.y * stru_721530.normal2.y
+          + f.pFacePlane_old.vNormal.x * stru_721530.normal2.x) >> 16;
+      if ( v8 <= stru_721530.prolly_normal_d || v9 <= stru_721530.prolly_normal_d )
+      {
+        if ( v9 <= v8 )
+        {
+          a2 = stru_721530.field_6C;
+          if ( sub_4754BF(
+                 stru_721530.prolly_normal_d,
+                 &a2,
+                 stru_721530.normal.x,
+                 stru_721530.normal.y,
+                 stru_721530.normal.z,
+                 stru_721530.field_58.x,
+                 stru_721530.field_58.y,
+                 stru_721530.field_58.z,
+                 &f,
+                 a10,
+                 a11) )
+          {
+            v10 = a2;
+          }
+          else
+          {
+            v11 = stru_721530.field_58.y;
+            v12 = stru_721530.field_58.z;
+            v13 = stru_721530.normal.y;
+            a2 = stru_721530.prolly_normal_d + stru_721530.field_6C;
+            if ( !sub_475F30(
+                    &a2,
+                    &f,
+                    stru_721530.normal.x,
+                    v13,
+                    stru_721530.normal.z,
+                    stru_721530.field_58.x,
+                    v11,
+                    v12,
+                    a10) )
+              goto LABEL_29;
+            v10 = a2 - stru_721530.prolly_normal_d;
+            a2 -= stru_721530.prolly_normal_d;
+          }
+          if ( v10 < stru_721530.field_7C )
+          {
+            stru_721530.field_7C = v10;
+            v14 = 8 * (v3 | (a10 << 6));
+            LOBYTE(v14) = v14 | 6;
+            stru_721530.uFaceID = v14;
+          }
+        }
+      }
+    }
+LABEL_29:
+    if ( stru_721530.field_0 & 1 )
+    {
+      v15 = (f.pFacePlane_old.vNormal.z * stru_721530.field_34.z
+           + f.pFacePlane_old.dist
+           + f.pFacePlane_old.vNormal.y * stru_721530.field_34.y
+           + f.pFacePlane_old.vNormal.x * stru_721530.field_34.x) >> 16;
+      if ( v15 > 0 )
+      {
+        v16 = (f.pFacePlane_old.vNormal.z * stru_721530.field_54
+             + f.pFacePlane_old.dist
+             + f.pFacePlane_old.vNormal.y * stru_721530.field_50
+             + f.pFacePlane_old.vNormal.x * stru_721530.field_4C) >> 16;
+        if ( v15 <= stru_721530.prolly_normal_d || v16 <= stru_721530.prolly_normal_d )
+        {
+          if ( v16 <= v15 )
+          {
+            a2 = stru_721530.field_6C;
+            if ( sub_4754BF(
+                   stru_721530.field_8,
+                   &a2,
+                   stru_721530.field_34.x,
+                   stru_721530.field_34.y,
+                   stru_721530.field_34.z,
+                   stru_721530.field_58.x,
+                   stru_721530.field_58.y,
+                   stru_721530.field_58.z,
+                   &f,
+                   a10,
+                   a11) )
+            {
+              if ( a2 < stru_721530.field_7C )
+              {
+                stru_721530.field_7C = a2;
+                v17 = 8 * (v3 | (a10 << 6));
+                LOBYTE(v17) = v17 | 6;
+                stru_721530.uFaceID = v17;
+              }
+            }
+            else
+            {
+              v18 = stru_721530.field_58.y;
+              v19 = stru_721530.field_58.z;
+              v20 = stru_721530.field_34.y;
+              a2 = stru_721530.field_6C + stru_721530.field_8;
+              if ( sub_475F30(
+                     &a2,
+                     &f,
+                     stru_721530.field_34.x,
+                     v20,
+                     stru_721530.field_34.z,
+                     stru_721530.field_58.x,
+                     v18,
+                     v19,
+                     a10) )
+              {
+                v2 = v28;
+                v21 = a2 - stru_721530.prolly_normal_d;
+                a2 -= stru_721530.prolly_normal_d;
+                if ( a2 < stru_721530.field_7C )
+                {
+                  stru_721530.field_7C = v21;
+                  v22 = 8 * (v3 | (a10 << 6));
+                  LOBYTE(v22) = v22 | 6;
+                  stru_721530.uFaceID = v22;
+                }
+                goto LABEL_38;
+              }
+            }
+          }
+        }
+      }
+    }
+    goto LABEL_37;
+  }
+  return result;
+}
+
+
+
+//----- (0046ED1B) --------------------------------------------------------
+int _46ED1B_collide_against_floor(int x, int y, int z, unsigned int *pSectorID, unsigned int *pFaceID)
+{
+  uint uFaceID = -1;
+  int floor_level = _46CEC3_get_floor_level(x, y, z, *pSectorID, &uFaceID);
+
+  if (floor_level != -30000 && floor_level <= z + 50)
+  {
+    *pFaceID = uFaceID;
+    return floor_level;
+  }
+
+  uint uSectorID = pIndoor->GetSector(x, y, z);
+  *pSectorID = uSectorID;
+
+  floor_level = _46CEC3_get_floor_level(x, y, z, uSectorID, &uFaceID);
+  if (uSectorID && floor_level != -30000)
+    *pFaceID = uFaceID;
+  else return -30000;
+  return floor_level;
+}
+
+//----- (0046ED8A) --------------------------------------------------------
+void __fastcall _46ED8A_collide_against_layingItems(unsigned int _this)
+{
+  int v1; // ebx@2
+  ObjectDesc *v2; // edx@4
+  int v3; // esi@5
+  int v4; // ecx@5
+  int v5; // eax@7
+  int v6; // edi@9
+  int v7; // edx@9
+  int v8; // edi@11
+  int v9; // ebx@11
+  int v10; // ecx@12
+  int v11; // esi@13
+  signed int v12; // [sp+0h] [bp-14h]@1
+  int v13; // [sp+4h] [bp-10h]@9
+  char *v14; // [sp+8h] [bp-Ch]@2
+  unsigned int v15; // [sp+10h] [bp-4h]@1
+
+  v15 = 0;
+  v12 = _this;
+  if ( (signed int)uNumLayingItems > 0 )
+  {
+    v1 = (int)&pLayingItems[0].uObjectDescID;
+    v14 = (char *)&pLayingItems[0].uObjectDescID;
+    do
+    {
+      if ( *(short *)v1 )
+      {
+        v2 = &pObjectList->pObjects[*(short *)v1];
+        if ( !(v2->uFlags & 2) )
+        {
+          v3 = v2->uRadius;
+          v4 = *(int *)(v1 + 2);
+          if ( stru_721530.sMaxX <= v4 + v3 )
+          {
+            if ( stru_721530.sMinX >= v4 - v3 )
+            {
+              v5 = *(int *)(v1 + 6);
+              if ( stru_721530.sMaxY <= v5 + v3 )
+              {
+                if ( stru_721530.sMinY >= v5 - v3 )
+                {
+                  v6 = v2->uHeight;
+                  v7 = *(int *)(v1 + 10);
+                  v13 = v6;
+                  if ( stru_721530.sMaxZ <= v7 + v6 )
+                  {
+                    if ( stru_721530.sMinZ >= v7 )
+                    {
+                      v8 = v4 - stru_721530.normal.x;
+                      v9 = v5 - stru_721530.normal.y;
+                      if ( abs(((v4 - stru_721530.normal.x) * stru_721530.field_58.y
+                              - (v5 - stru_721530.normal.y) * stru_721530.field_58.x) >> 16) <= v3
+                                                                                              + stru_721530.prolly_normal_d )
+                      {
+                        v10 = (v8 * stru_721530.field_58.x + v9 * stru_721530.field_58.y) >> 16;
+                        if ( v10 > 0 )
+                        {
+                          v11 = stru_721530.normal.z
+                              + ((unsigned __int64)(stru_721530.field_58.z * (signed __int64)v10) >> 16);
+                          if ( v11 >= *(int *)(v14 + 10) - stru_721530.prolly_normal_d )
+                          {
+                            if ( v11 <= v13 + stru_721530.prolly_normal_d + *(int *)(v14 + 10) )
+                            {
+                              if ( v10 < stru_721530.field_7C )
+                                sub_46DEF2(v12, v15);
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      ++v15;
+      v1 = (int)(v14 + 112);
+      v14 += 112;
+    }
+    while ( (signed int)v15 < (signed int)uNumLayingItems );
+  }
+}
+
+//----- (0046EF01) --------------------------------------------------------
+int __thiscall _46EF01_collision_chech_player(int a1)
+{
+  int v1; // edx@1
+  int result; // eax@1
+  int v3; // ebx@7
+  int v4; // esi@7
+  int v5; // edi@8
+  int v6; // ecx@9
+  int v7; // edi@12
+  int v8; // [sp+Ch] [bp-10h]@1
+  unsigned int v9; // [sp+10h] [bp-Ch]@1
+  int v10; // [sp+14h] [bp-8h]@7
+  int v11; // [sp+18h] [bp-4h]@7
+
+  v8 = a1;
+  v1 = 2 * pParty->field_14;
+  result = pParty->vPosition.x;
+  v9 = pParty->uPartyHeight;
+  if ( stru_721530.sMaxX <= pParty->vPosition.x + 2 * pParty->field_14 )
+  {
+    if ( stru_721530.sMinX >= pParty->vPosition.x - v1 )
+    {
+      if ( stru_721530.sMaxY <= pParty->vPosition.y + v1 )
+      {
+        if ( stru_721530.sMinY >= pParty->vPosition.y - v1 )
+        {
+          if ( stru_721530.sMaxZ <= (signed int)(pParty->vPosition.z + pParty->uPartyHeight) )
+          {
+            if ( stru_721530.sMinZ >= pParty->vPosition.z )
+            {
+              v3 = stru_721530.prolly_normal_d + v1;
+              v11 = pParty->vPosition.x - stru_721530.normal.x;
+              v4 = ((pParty->vPosition.x - stru_721530.normal.x) * stru_721530.field_58.y
+                  - (pParty->vPosition.y - stru_721530.normal.y) * stru_721530.field_58.x) >> 16;
+              v10 = pParty->vPosition.y - stru_721530.normal.y;
+              result = abs(((pParty->vPosition.x - stru_721530.normal.x) * stru_721530.field_58.y
+                          - (pParty->vPosition.y - stru_721530.normal.y) * stru_721530.field_58.x) >> 16);
+              if ( result <= v3 )
+              {
+                result = v10 * stru_721530.field_58.y;
+                v5 = (v10 * stru_721530.field_58.y + v11 * stru_721530.field_58.x) >> 16;
+                if ( v5 > 0 )
+                {
+                  v6 = ((unsigned __int64)(stru_721530.field_58.z * (signed __int64)v5) >> 16) + stru_721530.normal.z;
+                  result = pParty->vPosition.z;
+                  if ( v6 >= pParty->vPosition.z )
+                  {
+                    result = v9 + pParty->vPosition.z;
+                    if ( v6 <= (signed int)(v9 + pParty->vPosition.z) || v8 )
+                    {
+                      result = sub_452A9E(v3 * v3 - v4 * v4);
+                      v7 = v5 - result;
+                      if ( v7 < 0 )
+                        v7 = 0;
+                      if ( v7 < stru_721530.field_7C )
+                      {
+                        stru_721530.field_7C = v7;
+                        stru_721530.uFaceID = 4;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return result;
+}
+
+//----- (0046F04E) --------------------------------------------------------
+signed int __cdecl _46F04E_collide_against_portals()
+{
+  BLVSector *v0; // ecx@1
+  unsigned int v1; // eax@1
+  int v2; // eax@2
+  BLVFace *v3; // eax@3
+  int v4; // ecx@9
+  int v5; // edx@9
+  signed int result; // eax@21
+  BLVFace *v7; // eax@22
+  signed int v8; // [sp+0h] [bp-14h]@1
+  BLVSector *v9; // [sp+4h] [bp-10h]@1
+  unsigned int v10; // [sp+8h] [bp-Ch]@1
+  int a3; // [sp+Ch] [bp-8h]@13
+  int v12; // [sp+10h] [bp-4h]@15
+
+  v8 = 0;
+  v0 = &pIndoor->pSectors[stru_721530.uSectorID];
+  v1 = 0xFFFFFFu;
+  v10 = 0xFFFFFFu;
+  v9 = v0;
+  if ( v0->uNumPortals > 0 )
+  {
+    do
+    {
+      v2 = v0->pPortals[v8];
+      if ( v2 != stru_721530.field_80 )
+      {
+        v3 = &pIndoor->pFaces[v2];
+        if ( stru_721530.sMaxX <= v3->pBounding.x2 )
+        {
+          if ( stru_721530.sMinX >= v3->pBounding.x1
+            && stru_721530.sMaxY <= v3->pBounding.y2
+            && stru_721530.sMinY >= v3->pBounding.y1
+            && stru_721530.sMaxZ <= v3->pBounding.z2
+            && stru_721530.sMinZ >= v3->pBounding.z1 )
+          {
+            v4 = (stru_721530.normal.x * v3->pFacePlane_old.vNormal.x
+                + v3->pFacePlane_old.dist
+                + stru_721530.normal.y * v3->pFacePlane_old.vNormal.y
+                + stru_721530.normal.z * v3->pFacePlane_old.vNormal.z) >> 16;
+            v5 = (stru_721530.normal2.z * v3->pFacePlane_old.vNormal.z
+                + v3->pFacePlane_old.dist
+                + stru_721530.normal2.x * v3->pFacePlane_old.vNormal.x
+                + stru_721530.normal2.y * v3->pFacePlane_old.vNormal.y) >> 16;
+            if ( (v4 < stru_721530.prolly_normal_d || v5 < stru_721530.prolly_normal_d)
+              && (v4 > -stru_721530.prolly_normal_d || v5 > -stru_721530.prolly_normal_d)
+              && (a3 = stru_721530.field_6C, sub_475D85(&stru_721530.normal, &stru_721530.field_58, &a3, v3))
+              && a3 < (signed int)v10 )
+            {
+              v0 = v9;
+              v10 = a3;
+              v12 = v9->pPortals[v8];
+            }
+            else
+            {
+              v0 = v9;
+            }
+          }
+        }
+      }
+      ++v8;
+    }
+    while ( v8 < v0->uNumPortals );
+    v1 = v10;
+  }
+  if ( stru_721530.field_7C >= (signed int)v1 && (signed int)v1 <= stru_721530.field_6C )
+  {
+    stru_721530.field_80 = v12;
+    v7 = &pIndoor->pFaces[v12];
+    if ( v7->uSectorID == stru_721530.uSectorID )
+      stru_721530.uSectorID = v7->uBackSectorID;
+    else
+      stru_721530.uSectorID = v7->uSectorID;
+    stru_721530.field_7C = 268435455;
+    result = 0;
+  }
+  else
+  {
+    result = 1;
+  }
+  return result;
+}
+
+
+//----- (0047050A) --------------------------------------------------------
+int stru141::_47050A(int a2)
+{
+  stru141 *v2; // esi@1
+  signed int v3; // eax@1
+  int v4; // ecx@1
+  int v5; // edx@1
+  int v6; // edx@1
+  int v7; // eax@1
+  int v8; // eax@3
+  signed int result; // eax@4
+  int v10; // eax@5
+  int v11; // eax@5
+  int v12; // ebx@5
+  int v13; // edx@5
+  int v14; // edi@5
+  int v15; // ecx@5
+  int v16; // eax@5
+  int v17; // eax@5
+  int v18; // eax@7
+  int v19; // edx@9
+  int v20; // edi@9
+  int v21; // eax@9
+  int v22; // eax@11
+  int v23; // edx@13
+  int v24; // eax@13
+  int v25; // eax@14
+  int v26; // eax@16
+  int v27; // eax@17
+  int v28; // [sp+14h] [bp+8h]@5
+
+  v2 = this;
+  v3 = sub_452A9E(this->field_24 * this->field_24 + this->field_20 * this->field_20 + this->field_1C * this->field_1C);
+  v4 = v3 | 1;
+  v5 = v2->field_1C;
+  v2->field_64 = v3 | 1;
+  v2->field_58.x = 65536 / (v3 | 1) * v5;
+  v2->field_58.y = 65536 / (v3 | 1) * v2->field_20;
+  v6 = 65536 / (v3 | 1) * v2->field_24;
+  v2->field_68 = 65536 / (v3 | 1);
+  v7 = a2;
+  v2->field_58.z = v6;
+  if ( !a2 )
+    v7 = pEventTimer->dt_in_some_format;
+  v8 = ((unsigned __int64)(v7 * (signed __int64)v4) >> 16) - v2->field_70;
+  v2->field_6C = v8;
+  if ( v8 > 0 )
+  {
+    v10 = ((unsigned __int64)(v8 * (signed __int64)v2->field_58.x) >> 16) + v2->normal.x;
+    v2->field_4C = v10;
+    v2->normal2.x = v10;
+    v11 = ((unsigned __int64)(v2->field_6C * (signed __int64)v2->field_58.y) >> 16) + v2->normal.y;
+    v2->field_50 = v11;
+    v2->normal2.y = v11;
+    v2->normal2.z = ((unsigned __int64)(v2->field_6C * (signed __int64)v2->field_58.z) >> 16) + v2->normal.z;
+    v12 = v2->field_34.z;
+    v13 = v2->normal.x;
+    v14 = v2->normal2.x;
+    v15 = v2->prolly_normal_d;
+    v16 = v12 + ((unsigned __int64)(v2->field_6C * (signed __int64)v2->field_58.z) >> 16);
+    v28 = v16;
+    v2->field_54 = v16;
+    v17 = v13;
+    if ( v13 >= v14 )
+      v17 = v14;
+    v2->sMaxX = v17 - v15;
+    v18 = v15 + v13;
+    if ( v13 <= v14 )
+      v18 = v15 + v14;
+    v19 = v2->normal.y;
+    v20 = v2->normal2.y;
+    v2->sMinX = v18;
+    v21 = v19;
+    if ( v19 >= v20 )
+      v21 = v20;
+    v2->sMaxY = v21 - v15;
+    v22 = v15 + v19;
+    if ( v19 <= v20 )
+      v22 = v20 + v15;
+    v23 = v2->normal2.z;
+    v2->sMinY = v22;
+    v24 = v2->normal.z;
+    if ( v24 >= v23 )
+      v25 = v23 - v15;
+    else
+      v25 = v24 - v15;
+    v2->sMaxZ = v25;
+    v26 = v2->field_8;
+    if ( v12 <= v28 )
+      v27 = v28 + v26;
+    else
+      v27 = v12 + v26;
+    v2->uFaceID = 0;
+    v2->field_80 = -1;
+    v2->field_88 = -1;
+    v2->sMinZ = v27;
+    v2->field_7C = 0xFFFFFFu;
+    result = 0;
+  }
+  else
+  {
+    result = 1;
+  }
+  return result;
+}
+
+//----- (004706C6) --------------------------------------------------------
+void __cdecl UpdateActors_ODM()
+{
+  Actor *v0; // esi@2
+  unsigned __int16 v1; // ax@2
+  unsigned int v2; // ecx@6
+  int v3; // ebx@6
+  int v4; // eax@8
+  int v5; // eax@10
+  int v6; // ecx@10
+  signed int v7; // ebx@10
+  signed int v8; // ebx@17
+  unsigned __int8 v9; // zf@17
+  unsigned __int8 v10; // sf@17
+  unsigned __int16 v11; // ax@21
+  int v12; // eax@29
+  unsigned __int64 v13; // qax@29
+  int v14; // eax@30
+  unsigned __int64 v15; // qax@30
+  int v16; // eax@33
+  int v17; // edi@34
+  int v18; // edx@42
+  int v19; // ecx@42
+  __int16 v20; // ax@42
+  int v21; // ebx@42
+  int v22; // edi@42
+  int v23; // ecx@42
+  __int16 v24; // ax@42
+  int v25; // eax@45
+  signed int v26; // ecx@50
+  int v27; // eax@52
+  int v28; // eax@54
+  signed int v29; // ebx@57
+  signed int v30; // eax@57
+  int v31; // edi@57
+  signed int i; // ebx@57
+  unsigned int v33; // ecx@58
+  int v34; // ebx@64
+  int v35; // edi@64
+  int v36; // eax@64
+  unsigned __int16 v37; // cx@66
+  signed int v38; // edx@71
+  signed int v39; // edi@71
+  BSPModel *v40; // eax@75
+  ODMFace *v41; // edi@75
+  int v42; // ebx@76
+  int v43; // ecx@77
+  int v44; // edx@77
+  __int16 v45; // dx@82
+  int v46; // ecx@82
+  signed int v47; // ebx@85
+  int v48; // edi@85
+  int v49; // edi@85
+  int v50; // eax@85
+  unsigned __int64 v51; // qax@85
+  unsigned __int8 v52; // zf@87
+  unsigned __int8 v53; // sf@87
+  unsigned __int8 v54; // of@104
+  int v55; // eax@107
+  unsigned int v56; // edi@107
+  int v57; // ST10_4@107
+  unsigned int v58; // edi@107
+  unsigned int v59; // ebx@107
+  signed int v60; // eax@107
+  int v61; // eax@124
+  Vec3_int_ v62; // [sp+Ch] [bp-44h]@42
+  char v63; // [sp+18h] [bp-38h]@64
+  int v64; // [sp+1Ch] [bp-34h]@64
+  int v65; // [sp+20h] [bp-30h]@2
+  int v66; // [sp+24h] [bp-2Ch]@2
+  bool v67; // [sp+28h] [bp-28h]@10
+  unsigned int v68; // [sp+2Ch] [bp-24h]@10
+  unsigned int v69; // [sp+30h] [bp-20h]@6
+  unsigned int v70; // [sp+34h] [bp-1Ch]@10
+  int v71; // [sp+38h] [bp-18h]@62
+  int v72; // [sp+3Ch] [bp-14h]@10
+  int v73; // [sp+40h] [bp-10h]@17
+  int v74; // [sp+44h] [bp-Ch]@8
+  unsigned int v75; // [sp+48h] [bp-8h]@1
+  int v76; // [sp+4Ch] [bp-4h]@10
+
+  v75 = 0;
+  if ( (signed int)uNumActors <= 0 )
+    return;
+  do
+  {
+    v0 = &pActors[v75];
+    v66 = v0->vPosition.x;
+    v65 = v0->vPosition.y;
+    v1 = v0->uAIState;
+    if ( v1 == 11 || v1 == 19 || v1 == 17 || !v0->uMovementSpeed )
+      goto LABEL_121;
+    v2 = v0->pMonsterInfo.uID;
+    v3 = 0;
+    v69 = 0;
+    if ( MonsterStats::BelongsToSupertype(v2, MONSTER_SUPERTYPE_WATER_ELEMENTAL) )
+      v3 = 1;
+    v4 = v0->pMonsterInfo.uFlying;
+    v0->uSectorID = 0;
+    v74 = v4;
+    if ( !v0->CanAct() )
+      v74 = 0;
+    v70 = GetTerrainHeightsAroundParty(v0->vPosition.x, v0->vPosition.y);
+    v5 = sub_46D49E_prolly_get_world_y_under_party(
+           v0->vPosition.x,
+           v0->vPosition.y,
+           v0->vPosition.z,
+           v0->uActorHeight,
+           &v76,
+           (int *)&v69,
+           v3);
+    v6 = v0->vPosition.z;
+    v7 = v5;
+    v68 = v5;
+    v72 = 0;
+    v67 = v69 == 0;
+    if ( v6 > v5 + 1 )
+      v72 = 1;
+    if ( v0->uAIState == 5 && v76 && !v72 )
+    {
+      v0->uAIState = Removed;
+      goto LABEL_121;
+    }
+    if ( v0->uCurrentActionAnimation == 1 )
+    {
+      v8 = v0->uMovementSpeed;
+      v9 = HIDWORD(v0->pActorBuffs[7].uExpireTime) == 0;
+      v10 = SHIDWORD(v0->pActorBuffs[7].uExpireTime) < 0;
+      v73 = v0->uMovementSpeed;
+      if ( !v10 && (!(v10 | v9) || LODWORD(v0->pActorBuffs[7].uExpireTime) > 0) )
+      {
+        v8 = (signed __int64)((double)v73 * 0.5);
+        v73 = (signed __int64)((double)v73 * 0.5);
+      }
+      v11 = v0->uAIState;
+      if ( v11 == 7 || v11 == 6 )
+      {
+        v8 *= 2;
+        v73 = v8;
+      }
+      if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 1 )
+        v8 = (signed __int64)((double)v73 * flt_6BE3AC_debug_recmod1_x_1_6);
+      if ( v8 > 1000 )
+        v8 = 1000;
+      v12 = stru_5C6E00->SinCos(v0->uYawAngle);
+      v69 = v12;
+      v13 = v12 * (signed __int64)v8;
+      v73 = v13 >> 16;
+      v0->vVelocity.x = WORD1(v13);
+      v69 = stru_5C6E00->SinCos(v0->uYawAngle - stru_5C6E00->uIntegerHalfPi);
+      v73 = (unsigned __int64)((signed int)v69 * (signed __int64)v8) >> 16;
+      v9 = v74 == 0;
+      v0->vVelocity.y = v69 * v8 >> 16;
+      if ( !v9 )
+      {
+        v14 = stru_5C6E00->SinCos(v0->uPitchAngle - stru_5C6E00->uIntegerHalfPi);
+        v69 = v14;
+        v15 = v14 * (signed __int64)v8;
+        v73 = v15 >> 16;
+        v0->vVelocity.z = WORD1(v15);
+      }
+      v7 = v68;
+    }
+    else
+    {
+      v73 = v0->vVelocity.x;
+      v69 = 55000;
+      v73 = (unsigned __int64)(55000i64 * v73) >> 16;
+      v0->vVelocity.x = v73;
+      v73 = v0->vVelocity.y;
+      v73 = (unsigned __int64)((signed int)v69 * (signed __int64)v73) >> 16;
+      v9 = v74 == 0;
+      v0->vVelocity.y = v73;
+      if ( !v9 )
+      {
+        v69 = 55000;
+        v73 = v0->vVelocity.z;
+        v73 = (unsigned __int64)(55000i64 * v73) >> 16;
+        v0->vVelocity.z = v73;
+      }
+    }
+    if ( v0->vPosition.z < v7 )
+    {
+      v16 = v74;
+      v0->vPosition.z = v7;
+      v0->vVelocity.z = v16 != 0 ? 0x14 : 0;
+    }
+    v17 = 0;
+    if ( !v72 || v74 )
+    {
+      if ( v70 && !v72 && v67 )
+      {
+        v18 = v0->vPosition.y;
+        v19 = v0->vPosition.x;
+        v0->vPosition.z = v7;
+        _46DCC8_get_gravity_direction_outdoor(v19, v18, &v62);
+        v20 = GetGravityStrength();
+        v21 = v62.y;
+        v22 = v62.z;
+        v23 = v62.y * v0->vVelocity.y;
+        v0->vVelocity.z += -8 * LOWORD(pEventTimer->uTimeElapsed) * v20;
+        v73 = abs(v62.x * v0->vVelocity.x + v22 * v0->vVelocity.z + v23) >> 16;
+        v72 = v21;
+        v0->vVelocity.x += (unsigned int)(v73 * v62.x) >> 16;
+        v72 = (unsigned __int64)(v73 * (signed __int64)v72) >> 16;
+        v24 = v72;
+        v72 = v22;
+        v0->vVelocity.y += v24;
+        v72 = (unsigned __int64)(v73 * (signed __int64)v72) >> 16;
+        v0->vVelocity.z += v72;
+        v17 = 0;
+      }
+    }
+    else
+    {
+      v0->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
+    }
+    if ( pParty->field_1613C != v17 && v0->CanAct() )
+    {
+      v0->vVelocity.x += rand() % 100 - 50;
+      v0->vVelocity.y += rand() % 100 - 50;
+      v0->vVelocity.z += rand() % 100 - 20;
+      v25 = rand();
+      v0->uAIState = Stunned;
+      v0->uYawAngle += v25 % 32 - 16;
+      v0->UpdateAnimation();
+    }
+    if ( v0->vVelocity.x * v0->vVelocity.x + v0->vVelocity.y * v0->vVelocity.y < 400 && v70 == v17 )
+    {
+      v0->vVelocity.y = v17;
+      v0->vVelocity.x = v17;
+    }
+    v9 = v0->pMonsterInfo.uFlying == 0;
+    stru_721530.field_0 = 1;
+    if ( v9 )
+      v26 = 40;
+    else
+      v26 = v0->uActorRadius;
+    v27 = v0->uActorHeight;
+    stru_721530.field_84 = -1;
+    stru_721530.field_8 = v26;
+    stru_721530.prolly_normal_d = v26;
+    stru_721530.field_C = v27;
+    stru_721530.field_70 = v17;
+    v69 = v17;
+    while ( 1 )
+    {
+      stru_721530.field_34.x = v0->vPosition.x;
+      stru_721530.normal.x = stru_721530.field_34.x;
+      stru_721530.field_34.y = v0->vPosition.y;
+      stru_721530.normal.y = stru_721530.field_34.y;
+      v28 = v0->vPosition.z;
+      stru_721530.normal.z = v28 + v26 + 1;
+      stru_721530.field_34.z = v28 - v26 + stru_721530.field_C - 1;
+      if ( stru_721530.field_34.z < stru_721530.normal.z )
+        stru_721530.field_34.z = v28 + v26 + 1;
+      stru_721530.field_1C = v0->vVelocity.x;
+      stru_721530.uSectorID = 0;
+      stru_721530.field_20 = v0->vVelocity.y;
+      stru_721530.field_24 = v0->vVelocity.z;
+      if ( stru_721530._47050A(0) )
+        break;
+      _46E889_collide_against_bmodels(1u);
+      v29 = WorldPosToGridCellZ(v0->vPosition.y);
+      v30 = WorldPosToGridCellX(v0->vPosition.x);
+      _46E26D_collide_against_sprites(v30, v29);
+      _46EF01_collision_chech_player(0);
+      _46ED8A_collide_against_layingItems(8 * v75 | 3);
+      v31 = 0;
+      for ( i = 0; v31 < ai_arrays_size; ++v31 )
+      {
+        v33 = ai_array_4F7DB0_actor_ids[v31];
+        if ( v33 != v75 && _46DF1A_collide_against_actor(v33, 40) )
+          ++i;
+      }
+      v71 = i > 1;
+      if ( stru_721530.field_7C < stru_721530.field_6C )
+        v70 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
+      v34 = 0;
+      v35 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+      v36 = sub_46D49E_prolly_get_world_y_under_party(
+              stru_721530.normal2.x,
+              stru_721530.normal2.y,
+              stru_721530.normal2.z - stru_721530.prolly_normal_d - 1,
+              v0->uActorHeight,
+              (int *)&v63,
+              &v64,
+              0);
+      if ( v76 )
+      {
+        if ( v35 < v36 + 60 )
+        {
+          v37 = v0->uAIState;
+          if ( v37 == 5 || v37 == 4 || v37 == 11 || v37 == 19 )
+          {
+            if ( v64 )
+              v61 = v36 + 30;
+            else
+              v61 = v68 + 60;
+            sub_42F960_create_object(v0->vPosition.x, v0->vPosition.y, v61);
+            v0->uAIState = Removed;
+            return;
+          }
+        }
+      }
+      if ( stru_721530.field_7C >= stru_721530.field_6C )
+      {
+        v0->vPosition.x = LOWORD(stru_721530.normal2.x);
+        v0->vPosition.y = LOWORD(stru_721530.normal2.y);
+        v0->vPosition.z = LOWORD(stru_721530.normal2.z) - LOWORD(stru_721530.prolly_normal_d) - 1;
+        break;
+      }
+      v72 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
+      v0->vPosition.x += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.x) >> 16;
+      v72 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
+      v0->vPosition.y += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.y) >> 16;
+      v72 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
+      v38 = stru_721530.uFaceID;
+      v0->vPosition.z += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.z) >> 16;
+      stru_721530.field_70 += stru_721530.field_7C;
+      v39 = v38 >> 3;
+      switch ( v38 & 7 )
+      {
+        case 3:
+          if ( pParty->bTurnBasedModeOn != 1 )
+            goto LABEL_97;
+          if ( pTurnEngine->field_4 != 2 && pTurnEngine->field_4 != 3 )
+          {
+            v34 = 0;
+LABEL_97:
+            if ( v0->pMonsterInfo.uHostilityType )
+            {
+              if ( v71 == v34 )
+                goto LABEL_99;
+LABEL_101:
+              Actor::_403F58(v75, 4, v34, (AIDirection *)v34);
+              break;
+            }
+            if ( v71 != v34 )
+              goto LABEL_101;
+            if ( pActors[v39].pMonsterInfo.uHostilityType )
+            {
+LABEL_99:
+              Actor::_402968(v75, v38, v34, (AIDirection *)v34);
+              break;
+            }
+LABEL_103:
+            Actor::FaceObject(v75, v38, v34, (AIDirection *)v34);
+            break;
+          }
+          break;
+        case 4:
+          if ( !v0->GetActorsRelation(0) )
+          {
+            v38 = stru_721530.uFaceID;
+            goto LABEL_103;
+          }
+          v52 = HIDWORD(pParty->pPartyBuffs[11].uExpireTime) == 0;
+          v53 = SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) < 0;
+          v0->vVelocity.y = 0;
+          v0->vVelocity.x = 0;
+          if ( !v53 && (!(v53 | v52) || LODWORD(pParty->pPartyBuffs[11].uExpireTime) > 0) )
+            pParty->pPartyBuffs[11].Reset();
+          viewparams->bRedrawGameUI = 1;
+          break;
+        case 5:
+          v47 = sub_452A9E(v0->vVelocity.x * v0->vVelocity.x + v0->vVelocity.y * v0->vVelocity.y);
+          v48 = stru_5C6E00->Atan2(
+                  v0->vPosition.x - pLevelDecorations[v39].vPosition.x,
+                  v0->vPosition.y - pLevelDecorations[v39].vPosition.y);
+          v71 = stru_5C6E00->SinCos(v48);
+          v70 = (unsigned __int64)(v71 * (signed __int64)v47) >> 16;
+          v49 = v48 - stru_5C6E00->uIntegerHalfPi;
+          v0->vVelocity.x = (unsigned int)(v71 * v47) >> 16;
+          v50 = stru_5C6E00->SinCos(v49);
+          v71 = v50;
+          v51 = v50 * (signed __int64)v47;
+          v70 = v51 >> 16;
+          v0->vVelocity.y = WORD1(v51);
+          break;
+        case 6:
+          v40 = &pOutdoor->pBModels[v38 >> 9];
+          v41 = &v40->pFaces[v39 & 0x3F];
+          if ( !(BYTE3(v41->uAttributes) & 0x20) )
+          {
+            v42 = v41->uPolygonType;
+            if ( v42 == 3 )
+            {
+              v43 = v0->vVelocity.y;
+              v44 = v0->vVelocity.x;
+              v0->vVelocity.z = 0;
+              v0->vPosition.z = LOWORD(v40->pVertices.pVertices[v41->pVertexIDs[0]].z) + 1;
+              if ( v44 * v44 + v43 * v43 < 400 )
+              {
+                v0->vVelocity.y = 0;
+                v0->vVelocity.x = 0;
+              }
+            }
+            else
+            {
+              v72 = abs(v41->pFacePlane.vNormal.y * v0->vVelocity.y + v41->pFacePlane.vNormal.z * v0->vVelocity.z
+                                                                    + v41->pFacePlane.vNormal.x * v0->vVelocity.x) >> 16;
+              if ( stru_721530.field_64 >> 3 > v72 )
+                v72 = stru_721530.field_64 >> 3;
+              v73 = v41->pFacePlane.vNormal.x;
+              v73 = (unsigned __int64)(v72 * (signed __int64)v73) >> 16;
+              v71 = v41->pFacePlane.vNormal.y;
+              v71 = (unsigned __int64)(v72 * (signed __int64)v71) >> 16;
+              v70 = v41->pFacePlane.vNormal.z;
+              v70 = (unsigned __int64)(v72 * (signed __int64)(signed int)v70) >> 16;
+              v0->vVelocity.x += v73;
+              v0->vVelocity.y += v71;
+              v0->vVelocity.z += v70;
+              if ( v42 != 4 )
+              {
+                v45 = v0->vPosition.z;
+                v46 = stru_721530.prolly_normal_d
+                    - ((v41->pFacePlane.dist
+                      + v41->pFacePlane.vNormal.x * v0->vPosition.x
+                      + v41->pFacePlane.vNormal.y * v0->vPosition.y
+                      + v41->pFacePlane.vNormal.z * v0->vPosition.z) >> 16);
+                if ( v46 > 0 )
+                {
+                  v0->vPosition.x += (unsigned int)(v46 * v41->pFacePlane.vNormal.x) >> 16;
+                  v0->vPosition.y += (unsigned int)(v46 * v41->pFacePlane.vNormal.y) >> 16;
+                  v0->vPosition.z = v45 + ((unsigned int)(v46 * v41->pFacePlane.vNormal.z) >> 16);
+                }
+                v0->uYawAngle = stru_5C6E00->Atan2(v0->vVelocity.x, v0->vVelocity.y);
+              }
+            }
+          }
+          break;
+      }
+      v70 = v0->vVelocity.x;
+      v71 = 58500;
+      v70 = (unsigned __int64)(58500i64 * (signed int)v70) >> 16;
+      v0->vVelocity.x = v70;
+      v70 = v0->vVelocity.y;
+      v70 = (unsigned __int64)(v71 * (signed __int64)(signed int)v70) >> 16;
+      v71 = 58500;
+      v0->vVelocity.y = v70;
+      v70 = v0->vVelocity.z;
+      v70 = (unsigned __int64)(v71 * (signed __int64)(signed int)v70) >> 16;
+      ++v69;
+      v54 = __OFSUB__(v69, 100);
+      v10 = ((v69 - 100) & 0x80000000u) != 0;
+      v0->vVelocity.z = v70;
+      if ( !(v10 ^ v54) )
+        break;
+      v26 = stru_721530.prolly_normal_d;
+    }
+    v69 = WorldPosToGridCellX(v66);
+    v55 = WorldPosToGridCellZ(v65);
+    v56 = v55 - 1;
+    v57 = v0->vPosition.x;
+    v71 = v55 - 1;
+    v68 = WorldPosToGridCellX(v57);
+    v70 = WorldPosToGridCellZ(v0->vPosition.y) - 1;
+    v58 = ((unsigned int)~pOutdoor->ActuallyGetSomeOtherTileInfo(v69, v56) >> 1) & 1;
+    v59 = ((unsigned int)~pOutdoor->ActuallyGetSomeOtherTileInfo(v68, v70) >> 1) & 1;
+    v60 = 0;
+    if ( v69 == v68 && v71 == v70 && v58 )
+      v60 = 1;
+    if ( !v67 )
+      v60 = 1;
+    if ( !v60 )
+    {
+      if ( MonsterStats::BelongsToSupertype(v0->pMonsterInfo.uID, MONSTER_SUPERTYPE_WATER_ELEMENTAL) )
+      {
+        v58 = v58 == 0;
+        v59 = v59 == 0;
+      }
+      if ( !v74 && v58 && !v59 )
+      {
+        v0->vPosition.x = v66;
+        v0->vPosition.y = v65;
+        if ( v0->CanAct() )
+        {
+          v0->uYawAngle -= 32;
+          v0->uCurrentActionTime = 0;
+          v0->uCurrentActionLength = 128;
+          v0->uAIState = Fleeing;
+        }
+      }
+    }
+LABEL_121:
+    ++v75;
+  }
+  while ( (signed int)v75 < (signed int)uNumActors );
+}
+
+
+
+//----- (0047136C) --------------------------------------------------------
+void LayingItem::UpdateObject_fn0_BLV(unsigned int uLayingItemID)
+{
+  LayingItem *v1; // esi@1
+  ObjectDesc *v2; // edi@1
+  int v3; // ST08_4@1
+  __int16 v4; // ax@5
+  __int16 v5; // ax@7
+  BLVFace *v6; // ecx@11
+  BLVFace *v7; // eax@11
+  signed int v8; // ebx@12
+  int v9; // ecx@16
+  __int16 v10; // di@18
+  char v11; // al@19
+  int v12; // eax@25
+  int v13; // eax@31
+  int v14; // ebx@34
+  signed int v15; // ebx@46
+  BLVFace *v16; // edi@48
+  int v17; // eax@50
+  int v18; // eax@52
+  int v19; // ecx@52
+  Vec3_short_ *v20; // ecx@53
+  int v21; // ecx@57
+  __int16 v22; // ax@57
+  int v23; // edi@62
+  int v24; // edi@62
+  int v25; // eax@62
+  unsigned __int64 v26; // qax@62
+  unsigned __int8 v27; // sf@64
+  unsigned __int8 v28; // of@64
+  __int16 v29; // di@67
+  char v30; // al@68
+  const char *v31; // [sp-8h] [bp-98h]@19
+  const char *v32; // [sp-8h] [bp-98h]@68
+  enum TEXTURE_TYPE v33; // [sp-4h] [bp-94h]@19
+  enum TEXTURE_TYPE v34; // [sp-4h] [bp-94h]@68
+  Particle_ Dst; // [sp+Ch] [bp-84h]@18
+  unsigned int uLayingItemID_; // [sp+74h] [bp-1Ch]@1
+  ObjectDesc *v37; // [sp+78h] [bp-18h]@1
+  unsigned int uFaceID; // [sp+7Ch] [bp-14h]@4
+  int v39; // [sp+80h] [bp-10h]@33
+  int v40; // [sp+84h] [bp-Ch]@28
+  int v41; // [sp+88h] [bp-8h]@34
+  int v42; // [sp+8Ch] [bp-4h]@4
+
+  uLayingItemID_ = uLayingItemID;
+  v1 = &pLayingItems[uLayingItemID];
+  v2 = &pObjectList->pObjects[v1->uObjectDescID];
+  v3 = v1->vPosition.x;
+  v37 = &pObjectList->pObjects[v1->uObjectDescID];
+  if ( abs(v3) > 32767
+    || abs(v1->vPosition.y) > 32767
+    || abs(v1->vPosition.z) > 20000
+    || (v42 = _46CEC3_get_floor_level(v1->vPosition.x, v1->vPosition.y, v1->vPosition.z, v1->uSectorID, &uFaceID),
+        v42 <= -30000)
+    && ((v4 = pIndoor->GetSector(v1->vPosition.x, v1->vPosition.y, v1->vPosition.z),
+         (v1->uSectorID = v4) == 0)
+     || (v42 = _46CEC3_get_floor_level(v1->vPosition.x, v1->vPosition.y, v1->vPosition.z, v4, &uFaceID), v42 == -30000)) )
+  {
+    LayingItem::_42F933(uLayingItemID_);
+    return;
+  }
+  v5 = v2->uFlags;
+  if ( v5 & 0x20 )
+  {
+LABEL_24:
+    v8 = 0;
+LABEL_25:
+    stru_721530.field_0 = v8;
+    uFaceID = v8;
+    stru_721530.prolly_normal_d = v2->uRadius;
+    v12 = v2->uHeight;
+    stru_721530.field_84 = -1;
+    stru_721530.field_C = v12;
+    stru_721530.field_8 = v8;
+    stru_721530.field_70 = v8;
+    while ( 1 )
+    {
+      stru_721530.field_34.x = v1->vPosition.x;
+      stru_721530.normal.x = stru_721530.field_34.x;
+      stru_721530.field_34.y = v1->vPosition.y;
+      stru_721530.normal.y = stru_721530.field_34.y;
+      stru_721530.field_34.z = stru_721530.prolly_normal_d + v1->vPosition.z + 1;
+      stru_721530.normal.z = stru_721530.field_34.z;
+      stru_721530.field_1C = v1->vVelocity.x;
+      stru_721530.field_20 = v1->vVelocity.y;
+      stru_721530.field_24 = v1->vVelocity.z;
+      stru_721530.uSectorID = v1->uSectorID;
+      if ( stru_721530._47050A(v8) )
+        return;
+      v40 = v8;
+      do
+      {
+        _46E44E_collide_against_faces_and_portals(0);
+        _46E0B2_collide_against_decorations();
+        if ( (v1->field_58 & 7) != 4 )
+          _46EF01_collision_chech_player(1);
+        v13 = v1->field_58;
+        v42 = v8;
+        if ( (v13 & 7) == 3 )
+        {
+          if ( (signed int)uNumActors > v8 )
+          {
+            v39 = (int)&pActors[0].word_000086_some_monster_id;
+            do
+            {
+              v41 = pActors[v1->field_58 >> 3].pMonsterInfo.uID - 1;
+              v14 = (signed __int64)((double)v41 * 0.3333333333333333);
+              v41 = *(short *)(v39 - 38) - 1;
+              if ( v14 != (unsigned int)(signed __int64)((double)v41 * 0.3333333333333333) )
+                _46DF1A_collide_against_actor(v42, *((short *)&pMonsterList->pMonsters[*(short *)v39] - 73));
+              ++v42;
+              v39 += 836;
+            }
+            while ( v42 < (signed int)uNumActors );
+            v8 = 0;
+          }
+        }
+        else
+        {
+          if ( (signed int)uNumActors > v8 )
+          {
+            v39 = (int)&pActors[0].word_000086_some_monster_id;
+            do
+            {
+              _46DF1A_collide_against_actor(v42++, *((short *)&pMonsterList->pMonsters[*(short *)v39] - 73));
+              v39 += 836;
+            }
+            while ( v42 < (signed int)uNumActors );
+          }
+        }
+        if ( _46F04E_collide_against_portals() )
+          break;
+        ++v40;
+      }
+      while ( v40 < 100 );
+      if ( stru_721530.field_7C >= stru_721530.field_6C )
+      {
+        v1->vPosition.x = stru_721530.normal2.x;
+        v1->vPosition.y = stru_721530.normal2.y;
+        v1->vPosition.z = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+        v1->uSectorID = LOWORD(stru_721530.uSectorID);
+        if ( !(HIBYTE(v2->uFlags) & 1) )
+          return;
+        memset(&Dst, v8, 0x68u);
+        v29 = v2->uFlags;
+        Dst.x = (double)v1->vPosition.x;
+        Dst.y = (double)v1->vPosition.y;
+        Dst.z = (double)v1->vPosition.z;
+        Dst.flt_10 = 0.0;
+        Dst.flt_14 = 0.0;
+        Dst.flt_18 = 0.0;
+        if ( v29 & 0x200 )
+        {
+          Dst.bFree = 1036;
+          Dst.uDiffuse = 0xFF3C1Eu;
+          v30 = rand();
+          v34 = (TEXTURE_TYPE)v8;
+          v32 = "effpar01";
+        }
+        else
+        {
+          if ( v29 & 0x400 )
+            goto LABEL_70;
+          Dst.bFree = 1032;
+          Dst.uDiffuse = rand();
+          v30 = rand();
+          v34 = (TEXTURE_TYPE)v8;
+          v32 = "effpar03";
+        }
+        Dst.timeToLive = (unsigned __int8)(v30 & 0x80) + 128;
+        Dst.uTextureID = pBitmaps_LOD->LoadTexture(v32, v34);
+        goto LABEL_71;
+      }
+      v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
+      v1->vPosition.x += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
+      v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
+      v1->vPosition.y += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
+      v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
+      v1->vPosition.z += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
+      v1->uSectorID = LOWORD(stru_721530.uSectorID);
+      stru_721530.field_70 += stru_721530.field_7C;
+      if ( v2->uFlags & 0x40 && !_46BFFA_check_object_intercept(uLayingItemID_, stru_721530.uFaceID) )
+        return;
+      v15 = (signed int)stru_721530.uFaceID >> 3;
+      if ( (stru_721530.uFaceID & 7) == 5 )
+      {
+        v40 = sub_452A9E(v1->vVelocity.x * v1->vVelocity.x + v1->vVelocity.y * v1->vVelocity.y);
+        v23 = stru_5C6E00->Atan2(
+                v1->vPosition.x - pLevelDecorations[v15].vPosition.x,
+                v1->vPosition.y - pLevelDecorations[v15].vPosition.y);
+        v42 = stru_5C6E00->SinCos(v23);
+        v41 = (unsigned __int64)(v42 * (signed __int64)v40) >> 16;
+        v24 = v23 - stru_5C6E00->uIntegerHalfPi;
+        v1->vVelocity.x = (unsigned int)(v42 * v40) >> 16;
+        v25 = stru_5C6E00->SinCos(v24);
+        v42 = v25;
+        v26 = v25 * (signed __int64)v40;
+        v41 = v26 >> 16;
+        v1->vVelocity.y = WORD1(v26);
+      }
+      else
+      {
+        if ( (stru_721530.uFaceID & 7) != 6 )
+          goto LABEL_64;
+        stru_721530.field_84 = (signed int)stru_721530.uFaceID >> 3;
+        v16 = &pIndoor->pFaces[v15];
+        if ( v16->uPolygonType != 3 )
+        {
+          v42 = abs(v16->pFacePlane_old.vNormal.x * v1->vVelocity.x + v16->pFacePlane_old.vNormal.z * v1->vVelocity.z
+                                                                    + v16->pFacePlane_old.vNormal.y * v1->vVelocity.y) >> 16;
+          if ( stru_721530.field_64 >> 3 > v42 )
+            v42 = stru_721530.field_64 >> 3;
+          v40 = v16->pFacePlane_old.vNormal.x;
+          v40 = (unsigned __int64)(v42 * (signed __int64)v40) >> 16;
+          v41 = v16->pFacePlane_old.vNormal.y;
+          v41 = (unsigned __int64)(v42 * (signed __int64)v41) >> 16;
+          v39 = v16->pFacePlane_old.vNormal.z;
+          v39 = (unsigned __int64)(v42 * (signed __int64)v39) >> 16;
+          v1->vVelocity.x += 2 * v40;
+          v1->vVelocity.y += 2 * v41;
+          if ( v16->pFacePlane_old.vNormal.z <= 32000 )
+          {
+            v22 = 2 * v39;
+          }
+          else
+          {
+            v21 = v39;
+            v40 = 32000;
+            v1->vVelocity.z += v39;
+            v41 = (unsigned __int64)(v40 * (signed __int64)v21) >> 16;
+            v22 = (unsigned int)(v40 * v21) >> 16;
+          }
+          v1->vVelocity.z += v22;
+          goto LABEL_60;
+        }
+        if ( v37->uFlags & 0x80 )
+        {
+          v17 = -v1->vVelocity.z >> 1;
+          v1->vVelocity.z = v17;
+          if ( (signed __int16)v17 < 10 )
+            v1->vVelocity.z = 0;
+LABEL_60:
+          if ( BYTE3(v16->uAttributes) & 0x10 )
+            EventProcessor(pIndoor->pFaceExtras[v16->uFaceExtraID].uEventID, 0, 1);
+          goto LABEL_63;
+        }
+        v18 = v1->vVelocity.y;
+        v19 = v1->vVelocity.x;
+        v1->vVelocity.z = 0;
+        if ( v19 * v19 + v18 * v18 >= 400 )
+          goto LABEL_60;
+        v20 = pIndoor->pVertices;
+        v1->vVelocity.z = 0;
+        v1->vVelocity.y = 0;
+        v1->vVelocity.x = 0;
+        v1->vPosition.z = v20[*v16->pVertexIDs].z + 1;
+      }
+LABEL_63:
+      v2 = v37;
+LABEL_64:
+      v41 = v1->vVelocity.x;
+      v40 = 58500;
+      v41 = (unsigned __int64)(58500i64 * v41) >> 16;
+      v1->vVelocity.x = v41;
+      v41 = v1->vVelocity.y;
+      v41 = (unsigned __int64)(v40 * (signed __int64)v41) >> 16;
+      v40 = 58500;
+      v1->vVelocity.y = v41;
+      v41 = v1->vVelocity.z;
+      v41 = (unsigned __int64)(v40 * (signed __int64)v41) >> 16;
+      ++uFaceID;
+      v28 = __OFSUB__(uFaceID, 100);
+      v27 = uFaceID - 100 < 0;
+      v1->vVelocity.z = v41;
+      if ( !(v27 ^ v28) )
+        return;
+      v8 = 0;
+    }
+  }
+  if ( v42 <= v1->vPosition.z - 3 )
+  {
+    v1->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
+    goto LABEL_24;
+  }
+  if ( !(v5 & 0x40) || _46BFFA_check_object_intercept(uLayingItemID_, 0) )
+  {
+    v6 = pIndoor->pFaces;
+    v1->vPosition.z = v42 + 1;
+    v7 = &v6[uFaceID];
+    if ( v7->uPolygonType == 3 )
+    {
+      v8 = 0;
+      v1->vVelocity.z = 0;
+    }
+    else
+    {
+      if ( v7->pFacePlane_old.vNormal.z < 45000 )
+        v1->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
+      v8 = 0;
+    }
+    v42 = v1->vVelocity.x;
+    uFaceID = 58500;
+    v42 = (unsigned __int64)(58500i64 * v42) >> 16;
+    v1->vVelocity.x = v42;
+    v42 = v1->vVelocity.y;
+    v42 = (unsigned __int64)(uFaceID * (signed __int64)v42) >> 16;
+    uFaceID = 58500;
+    v1->vVelocity.y = v42;
+    v42 = v1->vVelocity.z;
+    v42 = (unsigned __int64)(uFaceID * (signed __int64)v42) >> 16;
+    v9 = v1->vVelocity.x;
+    v1->vVelocity.z = v42;
+    if ( v9 * v9 + v1->vVelocity.y * v1->vVelocity.y < 400 )
+    {
+      v1->vVelocity.z = v8;
+      v1->vVelocity.y = v8;
+      v1->vVelocity.x = v8;
+      if ( !(HIBYTE(v2->uFlags) & 1) )
+        return;
+      memset(&Dst, v8, 0x68u);
+      v10 = v2->uFlags;
+      Dst.x = (double)v1->vPosition.x;
+      Dst.y = (double)v1->vPosition.y;
+      Dst.z = (double)v1->vPosition.z;
+      Dst.flt_10 = 0.0;
+      Dst.flt_14 = 0.0;
+      Dst.flt_18 = 0.0;
+      if ( v10 & 0x200 )
+      {
+        Dst.bFree = 1036;
+        Dst.uDiffuse = 0xFF3C1Eu;
+        Dst.flt_28 = 1.0;
+        v11 = rand();
+        v33 = (TEXTURE_TYPE)v8;
+        v31 = "effpar01";
+      }
+      else
+      {
+        if ( v10 & 0x400 )
+        {
+LABEL_70:
+          Dst.bFree = 512;
+          Dst.uDiffuse = rand();
+          Dst.timeToLive = 64;
+          Dst.uTextureID = v8;
+LABEL_71:
+          Dst.flt_28 = 1.0;
+          goto LABEL_72;
+        }
+        Dst.bFree = 1032;
+        Dst.uDiffuse = rand();
+        Dst.flt_28 = 1.0;
+        v11 = rand();
+        v33 = (TEXTURE_TYPE)v8;
+        v31 = "effpar03";
+      }
+      Dst.timeToLive = (unsigned __int8)(v11 & 0x80) + 128;
+      Dst.uTextureID = pBitmaps_LOD->LoadTexture(v31, v33);
+LABEL_72:
+      pGame->pParticleEngine->AddParticle(&Dst);
+      return;
+    }
+    goto LABEL_25;
+  }
+}
+// 46DF1A: using guessed type int __fastcall 46DF1A_collide_against_actor(int, int);
+
+//----- (00471C03) --------------------------------------------------------
+void LayingItem::UpdateObject_fn0_ODM(unsigned int uLayingItemID)
+{
+  LayingItem *v1; // esi@1
+  ObjectDesc *v2; // ebx@1
+  signed int v3; // edx@1
+  int v4; // ecx@1
+  int v5; // ST04_4@1
+  int v6; // eax@1
+  int v7; // ecx@1
+  int v8; // edi@1
+  int v9; // eax@4
+  __int16 v10; // ax@7
+  int v11; // edx@11
+  int v12; // ecx@11
+  signed int v13; // edx@14
+  signed int v14; // edx@16
+  int v15; // eax@24
+  int v16; // eax@25
+  int v17; // ST10_4@25
+  signed int v18; // eax@25
+  signed int v19; // eax@28
+  Actor *v20; // edi@31
+  int v21; // eax@41
+  int v22; // ecx@43
+  __int16 v23; // bx@45
+  char v24; // al@46
+  signed int i; // edi@50
+  int v26; // edi@52
+  int v27; // eax@52
+  __int16 v28; // cx@55
+  int v29; // eax@55
+  signed int v30; // edi@59
+  BSPModel *v31; // ecx@61
+  ODMFace *v32; // edi@61
+  int v33; // eax@62
+  int v34; // ecx@62
+  int v35; // eax@63
+  Actor *v36; // ecx@67
+  __int16 v37; // ax@67
+  int v38; // eax@72
+  int v39; // eax@72
+  unsigned __int64 v40; // qax@72
+  int v41; // eax@72
+  unsigned __int8 v42; // sf@74
+  unsigned __int8 v43; // of@74
+  int v44; // eax@77
+  __int16 v45; // bx@81
+  int v46; // eax@85
+  const char *v47; // [sp-8h] [bp-B0h]@83
+  enum TEXTURE_TYPE v48; // [sp-4h] [bp-ACh]@46
+  int v49; // [sp+Ch] [bp-9Ch]@52
+  int v50; // [sp+10h] [bp-98h]@52
+  Vec3_int_ v51; // [sp+14h] [bp-94h]@11
+  Particle_ Dst; // [sp+20h] [bp-88h]@45
+  unsigned int uLayingItemID_; // [sp+88h] [bp-20h]@1
+  int v54; // [sp+8Ch] [bp-1Ch]@1
+  int v55; // [sp+90h] [bp-18h]@1
+  int v56; // [sp+94h] [bp-14h]@11
+  int v57; // [sp+98h] [bp-10h]@1
+  int v58; // [sp+9Ch] [bp-Ch]@1
+  int v59; // [sp+A0h] [bp-8h]@1
+  Actor *v60; // [sp+A4h] [bp-4h]@11
+
+  uLayingItemID_ = uLayingItemID;
+  v1 = &pLayingItems[uLayingItemID];
+  v58 = 0;
+  v2 = &pObjectList->pObjects[v1->uObjectDescID];
+  v57 = GetTerrainHeightsAroundParty(v1->vPosition.x, v1->vPosition.y);
+  v3 = v1->vPosition.y;
+  v4 = v1->vPosition.x;
+  v5 = v2->uHeight;
+  v55 = 0;
+  v6 = sub_46D49E_prolly_get_world_y_under_party(v4, v3, v1->vPosition.z, v5, &v59, &v55, 0);
+  v7 = v6;
+  v54 = v6;
+  v8 = v6 + 1;
+  if ( v1->vPosition.z <= v6 + 1 )
+  {
+    if ( v59 )
+    {
+      v9 = v6 + 60;
+      if ( v55 )
+        v9 = v7 + 30;
+      sub_42F960_create_object(v1->vPosition.x, v1->vPosition.y, v9);
+      LayingItem::_42F933(uLayingItemID_);
+      v7 = v54;
+    }
+  }
+  else
+  {
+    v58 = 1;
+  }
+  v10 = v2->uFlags;
+  if ( !(v10 & 0x20) )
+  {
+    if ( v58 )
+    {
+      v1->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
+      goto LABEL_13;
+    }
+    if ( v57 )
+    {
+      v11 = v1->vPosition.y;
+      v12 = v1->vPosition.x;
+      v1->vPosition.z = v8;
+      _46DCC8_get_gravity_direction_outdoor(v12, v11, &v51);
+      v1->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
+      v56 = abs(v51.y * v1->vVelocity.y + v51.z * v1->vVelocity.z + v51.x * v1->vVelocity.x) >> 16;
+      v60 = (Actor *)((unsigned __int64)(v56 * (signed __int64)v51.x) >> 16);
+      v1->vVelocity.x += (unsigned int)(v56 * v51.x) >> 16;
+      v60 = (Actor *)((unsigned __int64)(v56 * (signed __int64)v51.y) >> 16);
+      v1->vVelocity.y += (unsigned int)(v56 * v51.y) >> 16;
+      v60 = (Actor *)((unsigned __int64)(v56 * (signed __int64)v51.z) >> 16);
+      v1->vVelocity.z += (unsigned int)(v56 * v51.z) >> 16;
+LABEL_12:
+      v7 = v54;
+      goto LABEL_13;
+    }
+    if ( v10 & 0x40 )
+    {
+      if ( v1->vPosition.z < v7 )
+        v1->vPosition.z = v8;
+      if ( !_46BFFA_check_object_intercept(uLayingItemID_, 0) )
+        return;
+    }
+    v1->vPosition.z = v8;
+    if ( !(v2->uFlags & 0x80) || (v21 = -v1->vVelocity.z >> 1, v1->vVelocity.z = v21, (signed __int16)v21 < 10) )
+      v1->vVelocity.z = 0;
+    v60 = (Actor *)v1->vVelocity.x;
+    v55 = 58500;
+    v60 = (Actor *)((unsigned __int64)(58500i64 * (signed int)v60) >> 16);
+    v1->vVelocity.x = (signed __int16)v60;
+    v60 = (Actor *)v1->vVelocity.y;
+    v60 = (Actor *)((unsigned __int64)(v55 * (signed __int64)(signed int)v60) >> 16);
+    v55 = 58500;
+    v1->vVelocity.y = (signed __int16)v60;
+    v60 = (Actor *)v1->vVelocity.z;
+    v60 = (Actor *)((unsigned __int64)(v55 * (signed __int64)(signed int)v60) >> 16);
+    v22 = v1->vVelocity.x;
+    v1->vVelocity.z = (signed __int16)v60;
+    if ( v1->vVelocity.y * v1->vVelocity.y + v22 * v22 >= 400 )
+      goto LABEL_12;
+    v1->vVelocity.y = 0;
+    v1->vVelocity.x = 0;
+    if ( !(HIBYTE(v2->uFlags) & 1) )
+      return;
+    memset(&Dst, 0, 0x68u);
+    v23 = v2->uFlags;
+    Dst.x = (double)v1->vPosition.x;
+    Dst.y = (double)v1->vPosition.y;
+    Dst.z = (double)v1->vPosition.z;
+    Dst.flt_10 = 0.0;
+    Dst.flt_14 = 0.0;
+    Dst.flt_18 = 0.0;
+    if ( HIBYTE(v23) & 2 )
+    {
+      Dst.bFree = 1036;
+      Dst.uDiffuse = 16727070;
+      v24 = rand();
+      v48 = (TEXTURE_TYPE)0;
+LABEL_83:
+      v47 = "effpar01";
+    }
+    else
+    {
+      if ( HIBYTE(v23) & 4 )
+      {
+        Dst.bFree = 512;
+        Dst.uDiffuse = rand();
+        Dst.timeToLive = 64;
+        Dst.uTextureID = 0;
+LABEL_89:
+        Dst.flt_28 = 1.0;
+        pGame->pParticleEngine->AddParticle(&Dst);
+        return;
+      }
+      Dst.bFree = 1032;
+      Dst.uDiffuse = rand();
+      v24 = rand();
+      v48 = (TEXTURE_TYPE)0;
+LABEL_87:
+      v47 = "effpar03";
+    }
+    Dst.timeToLive = (unsigned __int8)(v24 & 0x80) + 128;
+    Dst.uTextureID = pBitmaps_LOD->LoadTexture(v47, v48);
+    goto LABEL_89;
+  }
+LABEL_13:
+  if ( v1->vPosition.z > v7
+    && (v13 = v1->vPosition.x, v13 >= -32768)
+    && v13 <= 32768
+    && (v14 = v1->vPosition.y, v14 >= -32768)
+    && v14 <= 32768
+    && v1->vPosition.z <= 13000
+    || !(v2->uFlags & 0x40) )
+    goto LABEL_92;
+  if ( v1->vPosition.z < v7 )
+    v1->vPosition.z = v8;
+  if ( _46BFFA_check_object_intercept(uLayingItemID_, 0) )
+  {
+LABEL_92:
+    stru_721530.field_0 = 0;
+    v55 = 0;
+    stru_721530.prolly_normal_d = v2->uRadius;
+    stru_721530.field_C = v2->uHeight;
+    stru_721530.field_8 = 0;
+    stru_721530.field_70 = 0;
+    while ( 1 )
+    {
+      stru_721530.field_34.x = v1->vPosition.x;
+      stru_721530.normal.x = stru_721530.field_34.x;
+      v15 = v1->vPosition.y;
+      stru_721530.uSectorID = 0;
+      stru_721530.field_34.y = v15;
+      stru_721530.normal.y = v15;
+      stru_721530.field_34.z = v1->vPosition.z + stru_721530.prolly_normal_d + 1;
+      stru_721530.normal.z = stru_721530.field_34.z;
+      stru_721530.field_1C = v1->vVelocity.x;
+      stru_721530.field_20 = v1->vVelocity.y;
+      stru_721530.field_24 = v1->vVelocity.z;
+      if ( stru_721530._47050A(0) )
+        return;
+      _46E889_collide_against_bmodels(0);
+      v16 = WorldPosToGridCellZ(v1->vPosition.y);
+      v17 = v1->vPosition.x;
+      v58 = v16;
+      v18 = WorldPosToGridCellX(v17);
+      _46E26D_collide_against_sprites(v18, v58);
+      if ( (v1->field_58 & 7) != 4 )
+        _46EF01_collision_chech_player(0);
+      if ( (v1->field_58 & 7) == 3 )
+      {
+        v19 = v1->field_58 >> 3;
+        if ( v19 >= 0 )
+        {
+          if ( v19 < (signed int)(uNumActors - 1) )
+          {
+            v56 = 0;
+            if ( (signed int)uNumActors > 0 )
+            {
+              v60 = pActors;
+              v20 = &pActors[v19];
+              do
+              {
+                if ( v20->GetActorsRelation(v60) )
+                  _46DF1A_collide_against_actor(v56, 0);
+                ++v56;
+                ++v60;
+              }
+              while ( v56 < (signed int)uNumActors );
+            }
+          }
+        }
+      }
+      else
+      {
+        for ( i = 0; i < (signed int)uNumActors; ++i )
+          _46DF1A_collide_against_actor(i, 0);
+      }
+      v26 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+      v27 = sub_46D49E_prolly_get_world_y_under_party(
+              stru_721530.normal2.x,
+              stru_721530.normal2.y,
+              stru_721530.normal2.z - stru_721530.prolly_normal_d - 1,
+              v2->uHeight,
+              &v49,
+              &v50,
+              0);
+      if ( v59 && v26 < v27 + 60 )
+      {
+        if ( v50 )
+          v44 = v27 + 30;
+        else
+          v44 = v54 + 60;
+        sub_42F960_create_object(v1->vPosition.x, v1->vPosition.y, v44);
+        LayingItem::_42F933(uLayingItemID_);
+        return;
+      }
+      if ( stru_721530.field_7C >= stru_721530.field_6C )
+      {
+        v1->vPosition.x = stru_721530.normal2.x;
+        v1->vPosition.y = stru_721530.normal2.y;
+        v1->vPosition.z = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+        v1->uSectorID = LOWORD(stru_721530.uSectorID);
+        if ( !(HIBYTE(v2->uFlags) & 1) )
+          return;
+        memset(&Dst, 0, 0x68u);
+        v45 = v2->uFlags;
+        Dst.x = (double)v1->vPosition.x;
+        Dst.y = (double)v1->vPosition.y;
+        Dst.z = (double)v1->vPosition.z;
+        Dst.flt_10 = 0.0;
+        Dst.flt_14 = 0.0;
+        Dst.flt_18 = 0.0;
+        if ( HIBYTE(v45) & 2 )
+        {
+          Dst.bFree = 1036;
+          Dst.uDiffuse = 16727070;
+          v24 = rand();
+          v48 = (TEXTURE_TYPE)0;
+          goto LABEL_83;
+        }
+        if ( HIBYTE(v45) & 4 )
+        {
+          Dst.bFree = 512;
+          v46 = rand();
+          Dst.uTextureID = 0;
+          Dst.uDiffuse = v46;
+          Dst.timeToLive = 64;
+          goto LABEL_89;
+        }
+        Dst.bFree = 1032;
+        Dst.uDiffuse = rand();
+        v24 = rand();
+        v48 = (TEXTURE_TYPE)0;
+        goto LABEL_87;
+      }
+      v60 = (Actor *)((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16);
+      v1->vPosition.x += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
+      v60 = (Actor *)((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16);
+      v1->vPosition.y += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
+      v60 = (Actor *)((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16);
+      v28 = LOWORD(stru_721530.uSectorID);
+      v1->vPosition.z += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
+      v29 = v1->vPosition.z;
+      v1->uSectorID = v28;
+      stru_721530.field_70 += stru_721530.field_7C;
+      if ( v2->uFlags & 0x40 )
+      {
+        if ( v29 < v54 )
+          v1->vPosition.z = v54 + 1;
+        if ( !_46BFFA_check_object_intercept(uLayingItemID_, stru_721530.uFaceID) )
+          return;
+      }
+      v30 = (signed int)stru_721530.uFaceID >> 3;
+      if ( (stru_721530.uFaceID & 7) == 5 )
+        break;
+      if ( (stru_721530.uFaceID & 7) == 6 )
+      {
+        v31 = &pOutdoor->pBModels[(signed int)stru_721530.uFaceID >> 9];
+        v32 = &v31->pFaces[v30 & 0x3F];
+        if ( v32->uPolygonType != 3 )
+        {
+          v56 = abs(v32->pFacePlane.vNormal.z * v1->vVelocity.z + v32->pFacePlane.vNormal.y * v1->vVelocity.y
+                                                                + v32->pFacePlane.vNormal.x * v1->vVelocity.x) >> 16;
+          if ( stru_721530.field_64 >> 3 > v56 )
+            v56 = stru_721530.field_64 >> 3;
+          v57 = v32->pFacePlane.vNormal.x;
+          v57 = (unsigned __int64)(v56 * (signed __int64)v57) >> 16;
+          v58 = v32->pFacePlane.vNormal.y;
+          v58 = (unsigned __int64)(v56 * (signed __int64)v58) >> 16;
+          v60 = (Actor *)v32->pFacePlane.vNormal.z;
+          v60 = (Actor *)((unsigned __int64)(v56 * (signed __int64)(signed int)v60) >> 16);
+          v1->vVelocity.x += 2 * v57;
+          v1->vVelocity.y += 2 * v58;
+          if ( v32->pFacePlane.vNormal.z <= 32000 )
+          {
+            v37 = 2 * (short)v60;
+          }
+          else
+          {
+            v36 = v60;
+            v57 = 32000;
+            v1->vVelocity.z += (signed __int16)v60;
+            v58 = (unsigned __int64)(v57 * (signed __int64)(signed int)v36) >> 16;
+            v37 = (unsigned int)(v57 * (int)v36) >> 16;
+          }
+          v1->vVelocity.z += v37;
+LABEL_70:
+          if ( BYTE3(v32->uAttributes) & 0x10 )
+            EventProcessor(v32->sCogTriggeredID, 0, 1);
+          goto LABEL_74;
+        }
+        v33 = v31->pVertices.pVertices[v32->pVertexIDs[0]].z;
+        v34 = v1->vVelocity.x;
+        v1->vPosition.z = v33 + 1;
+        if ( v1->vVelocity.y * v1->vVelocity.y + v34 * v34 >= 400 )
+          goto LABEL_70;
+        LOWORD(v35) = 0;
+        v1->vVelocity.z = 0;
+        v1->vVelocity.x = 0;
+        goto LABEL_73;
+      }
+LABEL_74:
+      v58 = v1->vVelocity.x;
+      v57 = 58500;
+      v58 = (unsigned __int64)(58500i64 * v58) >> 16;
+      v1->vVelocity.x = v58;
+      v58 = v1->vVelocity.y;
+      v58 = (unsigned __int64)(v57 * (signed __int64)v58) >> 16;
+      v57 = 58500;
+      v1->vVelocity.y = v58;
+      v58 = v1->vVelocity.z;
+      v58 = (unsigned __int64)(v57 * (signed __int64)v58) >> 16;
+      ++v55;
+      v43 = __OFSUB__(v55, 100);
+      v42 = v55 - 100 < 0;
+      v1->vVelocity.z = v58;
+      if ( !(v42 ^ v43) )
+        return;
+    }
+    v57 = sub_452A9E(v1->vVelocity.y * v1->vVelocity.y + v1->vVelocity.x * v1->vVelocity.x);
+    v38 = stru_5C6E00->Atan2(
+            v1->vPosition.x - pLevelDecorations[v30].vPosition.x,
+            v1->vPosition.y - pLevelDecorations[v30].vPosition.y);
+    v56 = v38;
+    v39 = stru_5C6E00->SinCos(v38);
+    v60 = (Actor *)v39;
+    v40 = v39 * (signed __int64)v57;
+    v58 = v40 >> 16;
+    v1->vVelocity.x = WORD1(v40);
+    v41 = stru_5C6E00->SinCos(v56 - stru_5C6E00->uIntegerHalfPi);
+    v60 = (Actor *)v41;
+    v35 = (unsigned __int64)(v41 * (signed __int64)v57) >> 16;
+    v58 = v35;
+LABEL_73:
+    v1->vVelocity.y = v35;
+    goto LABEL_74;
+  }
+}
+
+
+
+//----- (0047253E) --------------------------------------------------------
+void UpdateObjects()
+{
+  unsigned int v0; // ebx@0
+  //unsigned int v1; // edi@1
+  char *v2; // esi@2
+  //__int16 v3; // dx@5
+  ObjectDesc *v4; // eax@5
+  int v5; // ecx@6
+  __int16 v6; // cx@7
+  signed int v7; // eax@9
+  __int16 v8; // cx@14
+  __int16 v9; // dx@14
+  unsigned int v10; // ecx@16
+  signed int v11; // eax@17
+  int v12; // edi@27
+  int v13; // eax@27
+  int v14; // ebx@27
+  unsigned int v15; // ecx@27
+  unsigned int v16; // edx@30
+  unsigned int v17; // edx@32
+  int v18; // [sp+4h] [bp-10h]@27
+  int v19; // [sp+8h] [bp-Ch]@27
+  //signed int v20; // [sp+10h] [bp-4h]@1
+
+  //v1 = 0;
+  //v20 = 0;
+  for (uint i = 0; i < uNumLayingItems; ++i)
+  {
+    auto item = pLayingItems + i;
+    v2 = (char *)&item->uSpriteFrameID;
+    //do
+    //{
+      //LOWORD(v0) = item->uAttributes;
+    if (item->uAttributes & 0x40)
+      item->uAttributes &= 0xFFBF;
+    else
+    {
+              //v3 = item->uObjectDescID;
+      v4 = &pObjectList->pObjects[item->uObjectDescID];
+      if (item->uAttributes)
+      {
+          v5 = *(int *)(v2 + 62) >> 3;
+          *(int *)(v2 - 26) = pActors[v5].vPosition.x;
+          *(int *)(v2 - 22) = pActors[v5].vPosition.y;
+          *(int *)(v2 - 18) = pActors[v5].vPosition.z + pActors[v5].uActorHeight;
+          if ( !item->uObjectDescID || (v6 = LOWORD(pEventTimer->uTimeElapsed) + *(short *)v2, *(short *)v2 = v6, !(v4->uFlags & 4)) )
+            goto LABEL_36;
+          if ( v6 >= 0 )
+          {
+            v7 = v4->uLifetime;
+            if (item->uAttributes & 2)
+              v7 = *((short *)v2 + 1);
+            if ( v6 < v7 )
+              goto LABEL_36;
+          }
+          goto LABEL_34;
+      }
+
+        if ( item->uObjectDescID )
+        {
+          v8 = LOWORD(pEventTimer->uTimeElapsed) + item->uSpriteFrameID;
+          item->uSpriteFrameID = v8;
+          v9 = v4->uFlags;
+          if ( !(v9 & 4) )
+            goto LABEL_22;
+          if ( v8 < 0 )
+          {
+            v10 = i;
+LABEL_35:
+            LayingItem::_42F933(v10);
+            goto LABEL_36;
+          }
+          v11 = v4->uLifetime;
+          if ( item->uAttributes & 2 )
+            v11 = *((short *)v2 + 1);
+          if ( v8 < v11 )
+          {
+LABEL_22:
+            if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+              LayingItem::UpdateObject_fn0_BLV(i);
+            else
+              LayingItem::UpdateObject_fn0_ODM(i);
+            if ( pParty->bTurnBasedModeOn != 1 || !(*(v2 - 4) & 4) )
+              goto LABEL_36;
+            v12 = abs(pParty->vPosition.x - *(int *)(v2 - 26));
+            v18 = abs(pParty->vPosition.y - *(int *)(v2 - 22));
+            v19 = abs(pParty->vPosition.z - *(int *)(v2 - 18));
+            v13 = v12;
+            v14 = v18;
+            v15 = v19;
+            if ( v12 < v18 )
+            {
+              v13 = v18;
+              v14 = v12;
+            }
+            if ( v13 < v19 )
+            {
+              v16 = v13;
+              v13 = v19;
+              v15 = v16;
+            }
+            if ( v14 < (signed int)v15 )
+            {
+              v17 = v15;
+              v15 = v14;
+              v14 = v17;
+            }
+            v0 = (unsigned int)(11 * v14) >> 5;
+            if ( (signed int)(v0 + (v15 >> 2) + v13) <= 5120 )
+              goto LABEL_36;
+LABEL_34:
+            v10 = i;
+            goto LABEL_35;
+          }
+          v10 = i;
+          if ( !(v9 & 0x40) )
+            goto LABEL_35;
+          _46BFFA_check_object_intercept(i, 8 * i | OBJECT_Item);
+        }
+    }
+LABEL_36:
+    ;
+      //v2 += 112;
+      //v1 = v20++ + 1;
+    //}
+    //while ( v20 < (signed int)uNumLayingItems );
+  }
+}
+
+//----- (0047272C) --------------------------------------------------------
+int _47272C_collide_agains_some_secotors_floors(int x, int y, int z, unsigned int *pSectorID, unsigned int *pFaceID)
+{
+  signed int v5; // ebx@1
+  int result; // eax@1
+  int v7; // [sp+10h] [bp-8h]@1
+  signed int v8; // [sp+14h] [bp-4h]@1
+
+  __debugbreak();
+  v5 = x - 2;
+  v7 = x;
+  v8 = y;
+  *pSectorID = pIndoor->GetSector(x - 2, y, z + 40);
+  result = _46ED1B_collide_against_floor(v5, v8, z + 40, pSectorID, pFaceID);
+  if ( result == -30000 || !*pSectorID )
+  {
+    *pSectorID = pIndoor->GetSector(v7 + 2, v8, z + 40);
+    result = _46ED1B_collide_against_floor(v7 + 2, v8, z + 40, pSectorID, pFaceID);
+    if ( result == -30000 || !*pSectorID )
+    {
+      *pSectorID = pIndoor->GetSector(v7, v8 - 2, z + 40);
+      result = _46ED1B_collide_against_floor(v7, v8 - 2, z + 40, pSectorID, pFaceID);
+      if ( result == -30000 || !*pSectorID )
+      {
+        *pSectorID = pIndoor->GetSector(v7, v8 + 2, z + 40);
+        result = _46ED1B_collide_against_floor(v7, v8 + 2, z + 40, pSectorID, pFaceID);
+        if ( result == -30000 || !*pSectorID )
+        {
+          *pSectorID = pIndoor->GetSector(v7, v8, z + 140);
+          result = _46ED1B_collide_against_floor(v7, v8, z + 140, pSectorID, pFaceID);
+        }
+      }
+    }
+  }
+  return result;
+}
+
+//----- (00472866) --------------------------------------------------------
+void BLV_ProcessPartyActions()
+{
+  int v1; // ebx@1
+  int v2; // edi@1
+  int v6; // eax@18
+  signed __int64 v8; // qax@27
+  int v9; // eax@27
+  double v10; // st7@27
+  unsigned int v12; // eax@49
+  double v13; // st7@50
+  int v14; // eax@51
+  signed __int64 v15; // qax@53
+  double v16; // st7@54
+  int v17; // eax@62
+  double v18; // st7@62
+  int v19; // ST40_4@62
+  int v20; // eax@65
+  double v21; // st7@65
+  int v22; // ST40_4@65
+  int v23; // eax@66
+  double v24; // st7@66
+  int v25; // ST40_4@66
+  int v26; // eax@67
+  double v27; // st7@67
+  int v28; // ST40_4@67
+  unsigned int v35; // eax@74
+  int v36; // ecx@88
+  int new_party_z; // esi@96
+  int v38; // eax@96
+  int v39; // ecx@106
+  int v40; // eax@106
+  Player **v41; // esi@113
+  int v42; // eax@120
+  signed int v43; // ecx@123
+  BLVFace *v44; // esi@126
+  PolygonType v45; // al@126
+  int v46; // ecx@133
+  char v47; // zf@133
+  int v48; // eax@133
+  int v49; // ST40_4@136
+  int v50; // ST40_4@140
+  int v51; // eax@140
+  int v52; // eax@140
+  signed int v53; // edi@146
+  int v54; // ebx@146
+  int v55; // ST30_4@146
+  AudioPlayer *v56; // ecx@162
+  SoundID v57; // [sp-20h] [bp-80h]@163
+  signed int v58; // [sp-1Ch] [bp-7Ch]@161
+  unsigned int v59; // [sp-18h] [bp-78h]@161
+  signed int v60; // [sp-14h] [bp-74h]@161
+  signed int v61; // [sp-10h] [bp-70h]@161
+  int v62; // [sp-Ch] [bp-6Ch]@161
+  int v63; // [sp-8h] [bp-68h]@75
+  unsigned int v64; // [sp-8h] [bp-68h]@161
+  int v65; // [sp-4h] [bp-64h]@75
+  int v66; // [sp-4h] [bp-64h]@161
+  int v68; // [sp+10h] [bp-50h]@45
+  int v69; // [sp+10h] [bp-50h]@140
+  unsigned int uFaceEvent; // [sp+14h] [bp-4Ch]@1
+  signed int v71; // [sp+18h] [bp-48h]@1
+  signed int v72; // [sp+1Ch] [bp-44h]@1
+  signed int v73; // [sp+20h] [bp-40h]@100
+  int v74; // [sp+20h] [bp-40h]@140
+  bool bFeatherFall; // [sp+24h] [bp-3Ch]@15
+  unsigned int uSectorID; // [sp+28h] [bp-38h]@1
+  int v78; // [sp+2Ch] [bp-34h]@1
+  unsigned int uFaceID; // [sp+30h] [bp-30h]@1
+  int v80; // [sp+34h] [bp-2Ch]@1
+  int v81; // [sp+38h] [bp-28h]@47
+  int v82; // [sp+3Ch] [bp-24h]@47
+  int _view_angle; // [sp+40h] [bp-20h]@47
+  int bJumping; // [sp+44h] [bp-1Ch]@1
+  int new_party_y; // [sp+48h] [bp-18h]@1
+  int new_party_x; // [sp+4Ch] [bp-14h]@1
+  int party_z; // [sp+50h] [bp-10h]@1
+  int v89; // [sp+58h] [bp-8h]@1
+  int angle; // [sp+5Ch] [bp-4h]@47
+
+  uFaceEvent = 0;
+  v89 = pParty->uFallSpeed;
+  v1 = 0;
+  new_party_y = pParty->vPosition.y;
+  v2 = 0;
+  new_party_x = pParty->vPosition.x;
+  party_z = pParty->vPosition.z;
+  uSectorID = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
+  v72 = 0;
+  v78 = 0;
+  v71 = 0;
+  bJumping = 0;
+  v80 = _46ED1B_collide_against_floor(new_party_x, new_party_y, party_z + 40, &uSectorID, &uFaceID);
+  if ( pParty->bFlying )
+  {
+    pParty->bFlying = 0;
+    __debugbreak();
+    if (pParty->FlyActive())
+      stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[7].uOverlayID + 119] |= 1u;// 005E4D58 pOtherOverlayList [negindexing]
+  }
+  if ( v80 == -30000 )
+  {
+    v80 = _47272C_collide_agains_some_secotors_floors(new_party_x, new_party_y, party_z + 40, &uSectorID, &uFaceID);
+    if ( v80 == -30000 )
+    {
+      pParty->vPosition.x = blv_prev_party_x;
+      pParty->vPosition.y = blv_prev_party_z;
+      pParty->vPosition.z = blv_prev_party_y;
+      pParty->uFallStartY = blv_prev_party_y;
+      return;
+    }
+  }
+  blv_prev_party_x = pParty->vPosition.x;
+  blv_prev_party_z = pParty->vPosition.y;
+  blv_prev_party_y = pParty->vPosition.z;
+  if (!pParty->bTurnBasedModeOn)
+  {
+    auto v67 = GetTickCount() / 500;
+    if (dword_720CDC != v67 )
+    {
+      dword_4F8580[3 * dword_4F8580[0] + 1] = pParty->vPosition.x;
+      dword_4F8580[3 * dword_4F8580[0] + 2] = pParty->vPosition.y;
+      dword_4F8580[3 * dword_4F8580[0]++ + 3] = pParty->vPosition.z;
+      if ( dword_4F8580[0] > 60 )
+        dword_4F8580[0] = 1;
+    }
+    dword_720CDC = v67;
+  }
+  if (!pParty->FeatherFallActive())
+  {
+    bFeatherFall = false;
+    if (!pParty->pPlayers[0].WearsItem(536, 16) &&
+        !pParty->pPlayers[1].WearsItem(536, 16) &&
+        !pParty->pPlayers[2].WearsItem(536, 16) &&
+        !pParty->pPlayers[3].WearsItem(536, 16))
+    {
+      v6 = pParty->uFallStartY;
+    }
+  }
+  else
+  {
+    v6 = v80;
+    bFeatherFall = true;
+    pParty->uFallStartY = v80;
+  }
+LABEL_20:
+  if ( v6 - party_z > 512 && !bFeatherFall && party_z <= v80 + 1 )
+  {
+    if ( BYTE1(pParty->uFlags) & 1 )
+    {
+      BYTE1(pParty->uFlags) &= 0xFEu;
+    }
+    else for (uint i = 0; i < 4; ++i)
+    {                                      // receive falling damage
+      auto pPlayer = pParty->pPlayers + i;
+           
+      if (!pPlayer->HasEnchantedItemEquipped(72) &&
+          !pPlayer->WearsItem(529, 8))
+      {
+        v8 = (signed __int64)((double)pPlayer->GetMaxHealth() * 0.1);
+        pPlayer->ReceiveDamage((pParty->uFallStartY - party_z) * (signed int)v8 / 256, 4);
+        v9 = pPlayer->GetActualEndurance();
+        v10 = (double)(20 - pPlayer->_48EA1B_get_static_effect(v9)) * flt_6BE3A4_debug_recmod1 * 2.133333333333333;
+        pPlayer->SetRecoveryTime((signed __int64)v10);
+      }
+    }
+  }
+  if ( party_z > v80 + 1 )
+    bJumping = 1;
+  bFeatherFall = party_z - v80 <= 32;
+  if ( party_z - v80 <= 32 )
+    pParty->uFallStartY = party_z;
+  if ( bWalkSound && pParty->field_6F8 > 0 )
+    pParty->field_6F8 -= pEventTimer->uTimeElapsed;
+  if ( party_z > v80 + 1 )
+  {
+LABEL_43:
+    if ( bJumping )
+      goto LABEL_45;
+    goto LABEL_44;
+  }
+  party_z = v80 + 1;
+  pParty->uFallStartY = v80 + 1;
+  if ( bJumping )
+    goto LABEL_45;
+  if (pParty->field_6F4_packedid != uFaceID)
+  {
+    auto pFace = &pIndoor->pFaces[uFaceID];
+    if (pFace->uAttributes & 0x04000000 )
+    {
+      uFaceEvent = pIndoor->pFaceExtras[pFace->uFaceExtraID].uEventID;
+      goto LABEL_43;
+    }
+  }
+LABEL_44:
+  pParty->field_6F4_packedid = uFaceID;
+LABEL_45:
+  v68 = uFaceID;
+  if ( pIndoor->pFaces[uFaceID].uAttributes & 0x10 )
+    v71 = 1;
+  v81 = pParty->uWalkSpeed;
+  angle = pParty->sRotationY;
+  _view_angle = pParty->sRotationX;
+  v82 = (unsigned __int64)(pEventTimer->dt_in_some_format
+                         * (signed __int64)((signed int)(pParty->field_20_prolly_turn_speed * stru_5C6E00->uIntegerPi)
+                                          / 180)) >> 16;
+LABEL_87:
+  while ( pPartyActionQueue->uNumActions )
+  {
+    switch ( pPartyActionQueue->Next() )
+    {
+      case PARTY_TurnLeft:
+        __debugbreak();
+        v12 = uTurnSpeed;
+        if ( uTurnSpeed )
+          goto LABEL_58;
+        v13 = (double)v82 * fTurnSpeedMultiplier;
+        goto LABEL_51;
+      case PARTY_TurnRight:
+        __debugbreak();
+        LODWORD(v15) = uTurnSpeed;
+        if ( uTurnSpeed )
+          goto LABEL_56;
+        v16 = (double)v82 * fTurnSpeedMultiplier;
+        goto LABEL_55;
+      case PARTY_FastTurnLeft:
+        v12 = uTurnSpeed;
+        if ( uTurnSpeed )
+        {
+LABEL_58:
+          v14 = angle + v12;
+        }
+        else
+        {
+          v13 = (fTurnSpeedMultiplier + fTurnSpeedMultiplier) * (double)v82;
+LABEL_51:
+          v14 = angle + (unsigned __int64)(signed __int64)v13;
+        }
+        angle = stru_5C6E00->uDoublePiMask & v14;
+        goto LABEL_87;
+      case PARTY_FastTurnRight:
+        LODWORD(v15) = uTurnSpeed;
+        if ( !uTurnSpeed )
+        {
+          v16 = (fTurnSpeedMultiplier + fTurnSpeedMultiplier) * (double)v82;
+LABEL_55:
+          v15 = (signed __int64)v16;
+        }
+LABEL_56:
+        angle = stru_5C6E00->uDoublePiMask & (angle - v15);
+        goto LABEL_87;
+      case PARTY_StrafeLeft:
+        __debugbreak();
+        v17 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+        v18 = (double)v81;
+        //v88 = v18;
+        v78 = (unsigned __int64)(v17 * (signed __int64)((signed int)(signed __int64)(v18 * fWalkSpeedMultiplier) >> 1)) >> 16;
+        v2 -= v78;
+        v19 = stru_5C6E00->SinCos(angle);
+        v78 = (unsigned __int64)(v19 * (signed __int64)((signed int)(signed __int64)(v18 * fWalkSpeedMultiplier) >> 1)) >> 16;
+        goto LABEL_63;
+      case PARTY_StrafeRight:
+        __debugbreak();
+        v20 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+        v21 = (double)v81;
+        //v88 = v21;
+        v78 = (unsigned __int64)(v20 * (signed __int64)((signed int)(signed __int64)(v21 * fWalkSpeedMultiplier) >> 1)) >> 16;
+        v2 += v78;
+        v22 = stru_5C6E00->SinCos(angle);
+        v78 = (unsigned __int64)(v22 * (signed __int64)((signed int)(signed __int64)(v21 * fWalkSpeedMultiplier) >> 1)) >> 16;
+        goto LABEL_68;
+      case PARTY_WalkForward:
+        __debugbreak();
+        v23 = stru_5C6E00->SinCos(angle);
+        v24 = (double)v81;
+        //v88 = v24;
+        v78 = (unsigned __int64)(v23 * (signed __int64)(signed int)(signed __int64)(v24 * fWalkSpeedMultiplier)) >> 16;
+        v2 += v78;
+        v25 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+        v78 = (unsigned __int64)(v25 * (signed __int64)(signed int)(signed __int64)(v24 * fWalkSpeedMultiplier)) >> 16;
+LABEL_63:
+        v1 += v78;
+        goto LABEL_64;
+      case PARTY_WalkBackward:
+        __debugbreak();
+        v26 = stru_5C6E00->SinCos(angle);
+        v27 = (double)v81;
+        //v88 = v27;
+        v78 = (unsigned __int64)(v26
+                               * (signed __int64)(signed int)(signed __int64)(v27 * fBackwardWalkSpeedMultiplier)) >> 16;
+        v2 -= v78;
+        v28 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+        v78 = (unsigned __int64)(v28
+                               * (signed __int64)(signed int)(signed __int64)(v27 * fBackwardWalkSpeedMultiplier)) >> 16;
+LABEL_68:
+        v1 -= v78;
+LABEL_64:
+        v78 = 1;
+        goto LABEL_87;
+      case PARTY_RunForward:
+        //v29 = stru_5C6E00->SinCos(angle);
+        //v30 = (double)v81;
+        //v88 = (double)v81;
+        v2 += (unsigned __int64)(stru_5C6E00->SinCos(angle) * (signed __int64)(signed int)(2 * (unsigned __int64)(signed __int64)((double)v81 * fWalkSpeedMultiplier))) >> 16;
+        //v31 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+        v1 += (unsigned __int64)(stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi) * (signed __int64)(signed int)(2 * (unsigned __int64)(signed __int64)((double)v81 * fWalkSpeedMultiplier))) >> 16;
+        v72 = 1;
+        goto LABEL_87;
+      case PARTY_RunBackward:
+        //v32 = stru_5C6E00->SinCos(angle);
+        //v33 = (double)v81;
+        //v88 = (double)v81;
+        v2 -= (unsigned __int64)(stru_5C6E00->SinCos(angle) * (signed __int64)(signed int)(signed __int64)((double)v81 * fBackwardWalkSpeedMultiplier)) >> 16;
+        //v34 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+        v1 -= (unsigned __int64)(stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi) * (signed __int64)(signed int)(signed __int64)((double)v81 * fBackwardWalkSpeedMultiplier)) >> 16;
+//LABEL_70:
+        v72 = 1;
+        goto LABEL_87;
+      case PARTY_LookUp:
+        __debugbreak();
+        _view_angle += (signed __int64)(flt_6BE150_look_up_down_dangle * 25.0);
+        if ( _view_angle > 128 )
+          _view_angle = 128;
+        v35 = uActiveCharacter;
+        if ( !uActiveCharacter )
+          goto LABEL_87;
+        v65 = 0;
+        v63 = 63;
+        goto LABEL_76;
+      case PARTY_LookDown:
+        __debugbreak();
+        _view_angle += (signed __int64)(flt_6BE150_look_up_down_dangle * -25.0);
+        if ( _view_angle < -128 )
+          _view_angle = -128;
+        v35 = uActiveCharacter;
+        if ( uActiveCharacter )
+        {
+          v65 = 0;
+          v63 = 64;
+LABEL_76:
+          pPlayers[v35]->PlaySound(v63, v65);
+        }
+        break;
+      case PARTY_CenterView:
+        __debugbreak();
+        _view_angle = 0;
+        break;
+      case PARTY_Jump:
+        __debugbreak();
+        if ( (!bJumping || party_z <= v80 + 6 && v89 <= 0) && pParty->field_24 )
+        {
+          bJumping = 1;
+          v89 = (signed __int64)((double)(pParty->field_24 << 6) * 1.5 + (double)v89);
+        }
+        break;
+      default:
+        goto LABEL_87;
+    }
+  }
+  v36 = 0;
+  pParty->sRotationY = angle;
+  pParty->sRotationX = _view_angle;
+  if ( bJumping )
+  {
+    v89 += -2 * pEventTimer->uTimeElapsed * GetGravityStrength();
+  }
+  else
+  {
+    if ( pIndoor->pFaces[v68].pFacePlane_old.vNormal.z < 32768 )
+    {
+      v89 -= pEventTimer->uTimeElapsed * GetGravityStrength();
+      goto LABEL_92;
+    }
+    if ( BYTE1(pParty->uFlags) & 1 )
+      goto LABEL_92;
+    v89 = 0;
+  }
+  if ( bJumping != v36 && v89 <= v36 )
+  {
+    if ( v89 < -500 && !pParty->bFlying )
+    {
+      v41 = &pPlayers[1];
+      do
+      {
+        if ( !(*v41)->HasEnchantedItemEquipped(72) && !(*v41)->WearsItem(529, 8) )
+          (*v41)->PlayEmotion(46, 0);
+        ++v41;
+      }
+      while ( (signed int)v41 <= (signed int)&pPlayers[4] );
+    }
+    goto LABEL_93;
+  }
+LABEL_92:
+  pParty->uFallStartY = party_z;
+LABEL_93:
+  if ( v2 * v2 + v1 * v1 < 400 )
+  {
+    v1 = 0;
+    v2 = 0;
+  }
+  stru_721530.field_84 = -1;
+  stru_721530.field_70 = 0;
+  stru_721530.prolly_normal_d = pParty->field_14;
+  stru_721530.field_8 = pParty->field_14 >> 1;
+  auto v83 = 0;
+  stru_721530.field_0 = 1;
+  stru_721530.field_C = pParty->uPartyHeight - 32;
+  while ( 1 )
+  {
+    new_party_z = party_z;
+    stru_721530.field_34.x = new_party_x;
+    stru_721530.normal.x = new_party_x;
+    stru_721530.field_1C = v2;
+    stru_721530.field_34.y = new_party_y;
+    stru_721530.normal.y = new_party_y;
+    stru_721530.field_20 = v1;
+    stru_721530.normal.z = stru_721530.prolly_normal_d + party_z + 1;
+    stru_721530.field_34.z = stru_721530.field_C + party_z + 1;
+    stru_721530.field_24 = v89;
+    stru_721530.uSectorID = uSectorID;
+    v38 = 0;
+    if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 3 )
+      v38 = 13312;
+    if ( stru_721530._47050A(v38) )
+      break;
+    v73 = 0;
+    do
+    {
+      _46E44E_collide_against_faces_and_portals(1u);
+      _46E0B2_collide_against_decorations();
+      for ( v80 = 0; v80 < (signed int)uNumActors; ++v80 )
+        _46DF1A_collide_against_actor(v80, 0);
+      if ( _46F04E_collide_against_portals() )
+        break;
+      ++v73;
+    }
+    while ( v73 < 100 );
+    if ( stru_721530.field_7C >= stru_721530.field_6C )
+    {
+      v39 = stru_721530.normal2.x;
+      uSectorID = stru_721530.normal2.y;
+      v40 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+    }
+    else
+    {
+      v39 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16) + new_party_x;
+      uSectorID = new_party_y + ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16);
+      v40 = new_party_z + ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16);
+    }
+    v42 = _46ED1B_collide_against_floor(v39, uSectorID, v40 + 40, &stru_721530.uSectorID, &uFaceID);
+    if ( v42 == -30000 || v42 - new_party_z > 128 )
+      return;
+    if ( stru_721530.field_7C >= stru_721530.field_6C )
+    {
+      new_party_x = stru_721530.normal2.x;
+      new_party_y = stru_721530.normal2.y;
+      new_party_z = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+      break;
+    }
+    new_party_x += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
+    new_party_y += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
+    v43 = stru_721530.uFaceID;
+    uSectorID = stru_721530.uSectorID;
+    stru_721530.field_70 += stru_721530.field_7C;
+    auto v87 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16) + new_party_z;
+    if ( (stru_721530.uFaceID & 7) == 3 )
+    {
+      if ( SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) >= 0
+        && (SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[11].uExpireTime)) )
+        pParty->pPartyBuffs[11].Reset();
+      viewparams->bRedrawGameUI = 1;
+      goto LABEL_152;
+    }
+    if ( (stru_721530.uFaceID & 7) == 5 )
+    {
+      v53 = sub_452A9E(v2 * v2 + v1 * v1);
+      v80 = v53;
+      v54 = stru_5C6E00->Atan2(
+              new_party_x - pLevelDecorations[stru_721530.uFaceID >> 3].vPosition.x,
+              new_party_y - pLevelDecorations[stru_721530.uFaceID >> 3].vPosition.y);
+      v2 = (unsigned __int64)(stru_5C6E00->SinCos(v54) * (signed __int64)v53) >> 16;
+      v55 = stru_5C6E00->SinCos(v54 - stru_5C6E00->uIntegerHalfPi);
+      v1 = (unsigned __int64)(v55 * (signed __int64)v80) >> 16;
+    }
+    else
+    {
+      if ( (stru_721530.uFaceID & 7) == 6 )
+      {
+        v44 = &pIndoor->pFaces[(signed int)stru_721530.uFaceID >> 3];
+        v45 = v44->uPolygonType;
+        if ( v45 == 3 )
+        {
+          if ( v89 < 0 )
+            v89 = 0;
+          v87 = pIndoor->pVertices[*v44->pVertexIDs].z + 1;
+          if ( pParty->uFallStartY - v87 < 512 )
+            pParty->uFallStartY = v87;
+          if ( v2 * v2 + v1 * v1 < 400 )
+          {
+            v1 = 0;
+            v2 = 0;
+          }
+          goto LABEL_143;
+        }
+        v46 = v89 * v44->pFacePlane_old.vNormal.z;
+        v47 = v45 == 4;
+        v48 = v44->pFacePlane_old.vNormal.x;
+        if ( !v47 )
+        {
+          v80 = abs(v1 * v44->pFacePlane_old.vNormal.y + v46 + v2 * v48) >> 16;
+          if ( stru_721530.field_64 >> 3 > v80 )
+            v80 = stru_721530.field_64 >> 3;
+          v50 = (unsigned __int64)(v80 * (signed __int64)v44->pFacePlane_old.vNormal.x) >> 16;
+          v81 = v44->pFacePlane_old.vNormal.y;
+          v81 = (unsigned __int64)(v80 * (signed __int64)v81) >> 16;
+          v82 = v44->pFacePlane_old.vNormal.z;
+          v82 = (unsigned __int64)(v80 * (signed __int64)v82) >> 16;
+          v2 += v50;
+          v89 += v82;
+          v74 = v44->pFacePlane_old.vNormal.z;
+          v51 = v44->pFacePlane_old.vNormal.y;
+          v69 = v44->pFacePlane_old.vNormal.x;
+          v80 = v51;
+          v1 += v81;
+          v52 = stru_721530.prolly_normal_d - ((v44->pFacePlane_old.dist + v87 * v74 + new_party_y * v51 + new_party_x * v69) >> 16);
+          if ( v52 > 0 )
+          {
+            new_party_x += v52 * v69 >> 16;
+            new_party_y += v52 * v80 >> 16;
+            v87 += v52 * v74 >> 16;
+          }
+LABEL_142:
+          v43 = stru_721530.uFaceID;
+LABEL_143:
+          if ( pParty->field_6F4_packedid != v43 >> 3 && BYTE3(v44->uAttributes) & 4 )
+            uFaceEvent = pIndoor->pFaceExtras[v44->uFaceExtraID].uEventID;
+          goto LABEL_152;
+        }
+        v80 = abs(v1 * v44->pFacePlane_old.vNormal.y + v46 + v2 * v48) >> 16;
+        if ( stru_721530.field_64 >> 3 > v80 )
+          v80 = stru_721530.field_64 >> 3;
+        v49 = (unsigned __int64)(v80 * (signed __int64)v44->pFacePlane_old.vNormal.x) >> 16;
+        v81 = v44->pFacePlane_old.vNormal.y;
+        v81 = (unsigned __int64)(v80 * (signed __int64)v81) >> 16;
+        v82 = v44->pFacePlane_old.vNormal.z;
+        v82 = (unsigned __int64)(v80 * (signed __int64)v82) >> 16;
+        v2 += v49;
+        v1 += v81;
+        v89 += v82;
+        if ( v2 * v2 + v1 * v1 >= 400 )
+          goto LABEL_142;
+        v2 = 0;
+        v1 = 0;
+        v89 = 0;
+      }
+    }
+LABEL_152:
+    v2 = (unsigned __int64)(58500i64 * v2) >> 16;
+    v1 = (unsigned __int64)(58500i64 * v1) >> 16;
+    ++v83;
+    v89 = (unsigned __int64)(58500i64 * v89) >> 16;
+    if ( v83 >= 100 )
+    {
+      new_party_z = v87;
+      break;
+    }
+  }
+  if ( bWalkSound && pParty->field_6F8 <= 0 )
+  {
+    if ( sub_452A9E((pParty->vPosition.x - new_party_x) * (pParty->vPosition.x - new_party_x) + (pParty->vPosition.y - new_party_y)
+                                                                            * (pParty->vPosition.y - new_party_y)
+                                                                            + (pParty->vPosition.z - new_party_z)
+                                                                            * (pParty->vPosition.z - new_party_z)) <= 16 )
+      goto LABEL_188;
+    if ( v72 && (!bJumping || bFeatherFall) )
+    {
+      v66 = 0;
+      v64 = 0;
+      v62 = 0;
+      v61 = 0;
+      v60 = -1;
+      v59 = 1;
+      v58 = 804;
+      if ( !v71 )
+      {
+        v56 = pAudioPlayer;
+        if ( BYTE2(pIndoor->pFaces[uFaceID].uAttributes) & 0x20 )
+          v57 = (SoundID)50;
+        else
+          v57 = (SoundID)64;
+        goto LABEL_175;
+      }
+      v57 = (SoundID)63;
+LABEL_174:
+      v56 = pAudioPlayer;
+      goto LABEL_175;
+    }
+    if ( v78 && (!bJumping || bFeatherFall) )
+    {
+      v66 = 0;
+      v64 = 0;
+      v62 = 0;
+      v61 = 0;
+      v60 = -1;
+      v59 = 1;
+      v58 = 804;
+      if ( v71 )
+      {
+        v57 = (SoundID)102;
+        goto LABEL_174;
+      }
+      v56 = pAudioPlayer;
+      if ( BYTE2(pIndoor->pFaces[uFaceID].uAttributes) & 0x20 )
+        v57 = (SoundID)89;
+      else
+        v57 = (SoundID)103;
+LABEL_175:
+      pAudioPlayer->PlaySound(v57, v58, v59, v60, v61, v62, v64, v66);
+    }
+    else
+    {
+LABEL_188:
+      pAudioPlayer->_4AA258(804);
+      pParty->field_6F8 = 64;
+    }
+  }
+  if ( !bJumping || bFeatherFall )
+    pParty->uFlags &= 0xFFFFFFF7u;
+  else
+    pParty->uFlags |= 8u;
+  BYTE1(pParty->uFlags) &= 0xFDu;
+  pParty->vPosition.x = new_party_x;
+  pParty->vPosition.z = new_party_z;
+  pParty->vPosition.y = new_party_y;
+  pParty->uFallSpeed = v89;
+  if ( !bJumping && BYTE3(pIndoor->pFaces[uFaceID].uAttributes) & 0x40 )
+    BYTE1(pParty->uFlags) |= 2u;
+  if (uFaceEvent)
+    EventProcessor(uFaceEvent, 0, 1);
+}
+
+
+//----- (00473893) --------------------------------------------------------
+void __cdecl ODM_ProcessPartyActions()
+{
+  int _zero; // esi@1
+  int v1; // edi@1
+  int v2; // ebx@1
+  int v3; // eax@14
+  Player **v4; // esi@21
+  int v5; // eax@24
+  int v6; // esi@45
+  ODMFace *v7; // ecx@45
+  unsigned int v8; // eax@71
+  double v9; // st7@72
+  signed __int64 v10; // qax@74
+  double v11; // st7@75
+  int v12; // ecx@77
+  int v13; // eax@84
+  double v14; // st7@84
+  int v15; // eax@87
+  double v16; // st7@87
+  int v17; // eax@88
+  double v18; // st7@88
+  int v19; // eax@89
+  double v20; // st7@89
+  int v21; // eax@92
+  double v22; // st7@92
+  int v23; // eax@96
+  double v24; // st7@96
+  int v25; // eax@97
+  double v26; // st7@97
+  int v27; // eax@98
+  double v28; // st7@98
+  signed __int64 v29; // qax@98
+  unsigned int v30; // eax@103
+  int v31; // eax@130
+  int v32; // ecx@141
+  signed int v33; // eax@143
+  int v34; // esi@143
+  unsigned int v35; // esi@147
+  int v36; // eax@155
+  signed int v37; // esi@159
+  signed int v38; // eax@159
+  signed int i; // esi@159
+  int v40; // esi@162
+  Player **v41; // esi@172
+  bool v42; // eax@180
+  signed int v43; // ecx@184
+  signed int v44; // edx@184
+  int v45; // ecx@200
+  BSPModel *v46; // eax@203
+  ODMFace *v47; // esi@203
+  int v48; // eax@203
+  char v49; // zf@203
+  char v50; // sf@203
+  unsigned __int8 v51; // of@203
+  int v52; // eax@203
+  unsigned __int8 v53; // dl@205
+  BSPModel *v54; // eax@215
+  int v55; // eax@217
+  signed int v56; // ebx@228
+  int v57; // eax@228
+  BSPModel *v58; // eax@228
+  unsigned __int64 v59; // qax@228
+  BSPModel *v60; // eax@228
+  unsigned __int64 v61; // qax@228
+  int v62; // eax@241
+  signed int v63; // ST04_4@255
+  signed int v64; // eax@255
+  unsigned int v65; // ebx@263
+  unsigned int v66; // esi@263
+  int v67; // eax@263
+  signed int v68; // ecx@263
+  int v69; // eax@263
+  int v70; // ebx@271
+  int v71; // esi@271
+  int v72; // edi@271
+  int v73; // eax@271
+  Player **v74; // esi@283
+  int v75; // eax@284
+  unsigned int v76; // edi@293
+  bool v77; // edx@297
+  bool v78; // ecx@303
+  int v79; // ecx@314
+  __int16 v80; // dx@317
+  int v81; // ebx@318
+  int v82; // ecx@318
+  int v83; // eax@321
+  Player **v84; // esi@333
+  int v85; // eax@334
+  int v86; // [sp-20h] [bp-B4h]@246
+  int v87; // [sp-20h] [bp-B4h]@248
+  signed int v88; // [sp-1Ch] [bp-B0h]@246
+  unsigned int v89; // [sp-18h] [bp-ACh]@246
+  signed int v90; // [sp-14h] [bp-A8h]@246
+  signed int v91; // [sp-10h] [bp-A4h]@246
+  int v92; // [sp-Ch] [bp-A0h]@246
+  int v93; // [sp-8h] [bp-9Ch]@104
+  unsigned int v94; // [sp-8h] [bp-9Ch]@246
+  int v95; // [sp-4h] [bp-98h]@104
+  int v96; // [sp-4h] [bp-98h]@246
+  int v97; // [sp+Ch] [bp-88h]@180
+  int v98; // [sp+10h] [bp-84h]@147
+  int v99; // [sp+14h] [bp-80h]@147
+  int v100; // [sp+18h] [bp-7Ch]@147
+  bool v101; // [sp+1Ch] [bp-78h]@33
+  int v102; // [sp+20h] [bp-74h]@1
+  int v103; // [sp+24h] [bp-70h]@1
+  int bFeatherFall; // [sp+28h] [bp-6Ch]@4
+  int v105; // [sp+2Ch] [bp-68h]@24
+  int bWaterWalk; // [sp+30h] [bp-64h]@1
+  bool v107; // [sp+34h] [bp-60h]@30
+  int v108; // [sp+38h] [bp-5Ch]@1
+  int v109; // [sp+3Ch] [bp-58h]@28
+  int v110; // [sp+40h] [bp-54h]@180
+  int v111; // [sp+44h] [bp-50h]@14
+  int bJumping; // [sp+48h] [bp-4Ch]@1
+  int v113; // [sp+4Ch] [bp-48h]@1
+  unsigned int v114; // [sp+50h] [bp-44h]@1
+  int _walk_speed; // [sp+54h] [bp-40h]@48
+  int v116; // [sp+58h] [bp-3Ch]@1
+  int v117; // [sp+5Ch] [bp-38h]@1
+  int v118; // [sp+60h] [bp-34h]@1
+  Player **v119; // [sp+64h] [bp-30h]@4
+  int _angle_x; // [sp+68h] [bp-2Ch]@48
+  int v121; // [sp+6Ch] [bp-28h]@1
+  unsigned int v122; // [sp+70h] [bp-24h]@180
+  int v123; // [sp+74h] [bp-20h]@1
+  int v124; // [sp+78h] [bp-1Ch]@1
+  int _angle_y; // [sp+7Ch] [bp-18h]@48
+  int v126; // [sp+80h] [bp-14h]@48
+  BSPModel *v127; // [sp+84h] [bp-10h]@1
+  int v128; // [sp+88h] [bp-Ch]@1
+  int v129; // [sp+8Ch] [bp-8h]@92
+  int v130; // [sp+90h] [bp-4h]@14
+
+  v121 = pParty->uFallSpeed;
+  v123 = pParty->vPosition.z;
+  _zero = 0;
+  v1 = 0;
+  v103 = 0;
+  v2 = 0;
+  *(float *)&v128 = 0.0;
+  v116 = pParty->vPosition.x;
+  v117 = pParty->vPosition.y;
+  v113 = pParty->field_6F0;
+  bJumping = 0;
+  v118 = GetTerrainHeightsAroundParty(pParty->vPosition.x, pParty->vPosition.y);
+  v114 = 0;
+  v124 = 0;
+  v108 = 0;
+  v102 = 0;
+  v127 = 0;
+  bWaterWalk = 0;
+  if ( SHIDWORD(pParty->pPartyBuffs[5].uExpireTime) < 0
+    || SHIDWORD(pParty->pPartyBuffs[5].uExpireTime) <= 0 && LODWORD(pParty->pPartyBuffs[5].uExpireTime) <= 0 )
+  {
+    bFeatherFall = 0;
+    v119 = &pPlayers[1];
+    while ( !(*v119)->WearsItem(536, 16) )
+    {
+      ++v119;
+      if ( (signed int)v119 > (signed int)&pPlayers[4] )
+        goto LABEL_9;
+    }
+  }
+  bFeatherFall = 1;
+LABEL_9:
+  if ( (signed __int64)pParty->pPartyBuffs[18].uExpireTime <= 0 )
+  {
+    LOBYTE(pParty->uFlags) &= 0x7Fu;
+  }
+  else
+  {
+    LOBYTE(pParty->uFlags) &= 0x7Fu;
+    bWaterWalk = 1;
+    *(short *)&stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[18].uOverlayID + 119] |= 1u;
+    if ( !(pParty->pPartyBuffs[18].uFlags & 1)
+      && *(int *)&pParty->pArtifactsFound[6972 * pParty->pPartyBuffs[18].uCaster + 10] <= 0 )
+      bWaterWalk = 0;
+  }
+  v3 = sub_46D49E_prolly_get_world_y_under_party(v116, v117, v123, pParty->uPartyHeight, &v130, &v108, bWaterWalk);
+  v111 = v3;
+  if ( bFeatherFall )
+    pParty->uFallStartY = v3;
+  else
+    v3 = pParty->uFallStartY;
+  if ( v3 - v123 > 512 && !bFeatherFall && v123 <= v111 + 1 )
+  {
+    if ( BYTE1(pParty->uFlags) & 1 )
+    {
+      BYTE1(pParty->uFlags) &= 0xFEu;
+    }
+    else
+    {
+      v4 = &pPlayers[1];                        // receive falling damage
+      do
+      {
+        if ( !(*v4)->HasEnchantedItemEquipped(72) && !(*v4)->WearsItem(529, 8) )
+        {
+          v105 = (*v4)->GetMaxHealth();
+          (*v4)->ReceiveDamage(
+            (signed int)((pParty->uFallStartY - v123) * (unsigned __int64)(signed __int64)((double)v105 * 0.1)) / 256,
+            4);
+          v5 = (*v4)->GetActualEndurance();
+          v105 = 20 - (*v4)->_48EA1B_get_static_effect(v5);
+          (*v4)->SetRecoveryTime((signed __int64)((double)v105 * flt_6BE3A4_debug_recmod1 * 2.133333333333333));
+        }
+        ++v4;
+      }
+      while ( (signed int)v4 <= (signed int)&pPlayers[4] );
+      _zero = 0;
+    }
+  }
+  v109 = -1;
+  if ( pParty->bFlying != _zero )
+    v109 = sub_46D8E3(v116, v117, v123 + pParty->uPartyHeight, (int)&v102);
+  v107 = v108 == _zero;
+  v105 = v111 + 1;
+  if ( v123 <= v111 + 1 )
+  {
+    v109 = -1;
+    pParty->bFlying = _zero;
+  }
+  else
+  {
+    bJumping = 1;
+  }
+  v101 = v123 - v111 <= 32;
+  if ( bWalkSound != _zero && pParty->field_6F8 > _zero )
+    pParty->field_6F8 -= pEventTimer->uTimeElapsed;
+  if ( !bUnderwater
+    && SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) <= _zero
+    && (SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) < _zero || LODWORD(pParty->pPartyBuffs[7].uExpireTime) <= _zero) )
+    pParty->bFlying = _zero;
+  if ( bJumping == _zero )
+  {
+    if ( pParty->field_6F4_packedid != (8 * v108 | OBJECT_BModel) )
+    {
+      if ( v108 != _zero )
+      {
+        if ( v108 >> 6 < pOutdoor->uNumBModels )
+        {
+          v7 = (ODMFace *)&pOutdoor->pBModels[v108 >> 6].pFaces;
+          v6 = v108 & 0x3F;
+          if ( *(char *)(v7->pFacePlane.vNormal.x + 308 * v6 + 31) & 4 )
+          {
+            pParty->field_6F4_packedid = 8 * v108 | OBJECT_BModel;
+            v103 = *(short *)(v7->pFacePlane.vNormal.x + 308 * v6 + 292);
+          }
+        }
+      }
+    }
+    pParty->field_6F4_packedid = 8 * v108 | OBJECT_BModel;
+  }
+  _walk_speed = pParty->uWalkSpeed;
+  _angle_y = pParty->sRotationY;
+  _angle_x = pParty->sRotationX;
+  v126 = pEventTimer->dt_in_some_format;
+  v119 = (Player **)((unsigned __int64)(pEventTimer->dt_in_some_format
+                                      * (signed __int64)((signed int)(pParty->field_20_prolly_turn_speed
+                                                                    * stru_5C6E00->uIntegerPi)
+                                                       / 180)) >> 16);
+LABEL_118:
+  while ( pPartyActionQueue->uNumActions )
+  {
+    switch ( pPartyActionQueue->Next() )
+    {
+      case PARTY_FlyUp:
+        if ( (signed __int64)pParty->pPartyBuffs[7].uExpireTime > 0 || bUnderwater == 1 )
+        {
+          pParty->bFlying = 0;
+          if ( bUnderwater
+            || pParty->pPartyBuffs[7].uFlags & 1
+            || *(int *)&pParty->pArtifactsFound[6972 * pParty->pPartyBuffs[7].uCaster + 10] > 0 )
+          {
+            if ( pParty->vPosition.z < 4000 || bJumping )
+            {
+              v123 += 30;
+              v113 += 30;
+              pParty->bFlying = 1;
+              if ( v123 > 4000 )
+              {
+                v123 = 4000;
+                v113 = 4000;
+              }
+              v1 = 0;
+              v2 = 0;
+              v121 = 0;
+              *(float *)&v128 = 0.0;
+              if ( v102 && v123 < v109 && (signed int)(pParty->uPartyHeight + v123) >= v109 )
+              {
+                pParty->field_6E0 = 0;
+                pParty->field_6E4 = 0;
+                pPartyActionQueue->uNumActions = 0;
+                BYTE1(pParty->uFlags) |= 1u;
+                pParty->vPosition.z = v109 - pParty->uPartyHeight - 31;
+                pParty->field_6F0 = v123;
+                pParty->bFlying = 0;
+                v123 = v109 - pParty->uPartyHeight - 31;
+                v113 = pParty->field_6F0;
+              }
+              pParty->uFallSpeed = 0;
+              v127 = (BSPModel *)1;
+            }
+          }
+        }
+        goto LABEL_118;
+      case PARTY_FlyDown:
+        if ( (signed __int64)pParty->pPartyBuffs[7].uExpireTime > 0 || bUnderwater == 1 )
+        {
+          pParty->bFlying = 0;
+          if ( bUnderwater
+            || pParty->pPartyBuffs[7].uFlags & 1
+            || *(int *)&pParty->pArtifactsFound[6972 * pParty->pPartyBuffs[7].uCaster + 10] > 0 )
+          {
+            v123 -= 30;
+            v113 -= 30;
+            pParty->uFallSpeed = 0;
+            v121 = 0;
+            pParty->bFlying = 1;
+            v127 = (BSPModel *)1;
+            if ( v123 <= v111 )
+            {
+              pParty->bFlying = 0;
+              pPartyActionQueue->uNumActions = 0;
+            }
+          }
+        }
+        goto LABEL_118;
+      case PARTY_TurnLeft:
+        v8 = uTurnSpeed;
+        if ( uTurnSpeed )
+          goto LABEL_80;
+        v9 = (double)(signed int)v119 * fTurnSpeedMultiplier;
+        goto LABEL_73;
+      case PARTY_TurnRight:
+        LODWORD(v10) = uTurnSpeed;
+        if ( uTurnSpeed )
+          goto LABEL_77;
+        v11 = (double)(signed int)v119 * fTurnSpeedMultiplier;
+        goto LABEL_76;
+      case PARTY_FastTurnLeft:
+        v8 = uTurnSpeed;
+        if ( uTurnSpeed )
+        {
+LABEL_80:
+          v12 = v8 + _angle_y;
+LABEL_78:
+          _angle_y = stru_5C6E00->uDoublePiMask & v12;
+        }
+        else
+        {
+          v9 = (fTurnSpeedMultiplier + fTurnSpeedMultiplier) * (double)(signed int)v119;
+LABEL_73:
+          _angle_y = stru_5C6E00->uDoublePiMask & (_angle_y + (unsigned __int64)(signed __int64)v9);
+        }
+        goto LABEL_118;
+      case PARTY_FastTurnRight:
+        LODWORD(v10) = uTurnSpeed;
+        if ( !uTurnSpeed )
+        {
+          v11 = (fTurnSpeedMultiplier + fTurnSpeedMultiplier) * (double)(signed int)v119;
+LABEL_76:
+          v10 = (signed __int64)v11;
+        }
+LABEL_77:
+        v12 = _angle_y - v10;
+        goto LABEL_78;
+      case PARTY_StrafeLeft:
+        v13 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+        v14 = (double)_walk_speed;
+        v126 = v13;
+        *(float *)&v128 = v14;
+        v124 = (unsigned __int64)(v13 * (signed __int64)((signed int)(signed __int64)(v14 * fWalkSpeedMultiplier) >> 1)) >> 16;
+        v2 -= v124;
+        v126 = stru_5C6E00->SinCos(_angle_y);
+        v124 = (unsigned __int64)(v126
+                                * (signed __int64)((signed int)(signed __int64)(*(float *)&v128 * fWalkSpeedMultiplier) >> 1)) >> 16;
+        goto LABEL_85;
+      case PARTY_StrafeRight:
+        v15 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+        v16 = (double)_walk_speed;
+        v126 = v15;
+        *(float *)&v128 = v16;
+        v124 = (unsigned __int64)(v15 * (signed __int64)((signed int)(signed __int64)(v16 * fWalkSpeedMultiplier) >> 1)) >> 16;
+        v2 += v124;
+        v126 = stru_5C6E00->SinCos(_angle_y);
+        v124 = (unsigned __int64)(v126
+                                * (signed __int64)((signed int)(signed __int64)(*(float *)&v128 * fWalkSpeedMultiplier) >> 1)) >> 16;
+        goto LABEL_90;
+      case PARTY_WalkForward:
+        v17 = stru_5C6E00->SinCos(_angle_y);
+        v18 = (double)_walk_speed;
+        v126 = v17;
+        *(float *)&v128 = v18;
+        v124 = (unsigned __int64)(v17 * (signed __int64)(signed int)(signed __int64)(v18 * fWalkSpeedMultiplier)) >> 16;
+        v2 += v124;
+        v126 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+        v124 = (unsigned __int64)(v126
+                                * (signed __int64)(signed int)(signed __int64)(*(float *)&v128 * fWalkSpeedMultiplier)) >> 16;
+LABEL_85:
+        v1 += v124;
+        goto LABEL_86;
+      case PARTY_WalkBackward:
+        v19 = stru_5C6E00->SinCos(_angle_y);
+        v20 = (double)_walk_speed;
+        v126 = v19;
+        *(float *)&v128 = v20;
+        v124 = (unsigned __int64)(v19
+                                * (signed __int64)(signed int)(signed __int64)(v20 * fBackwardWalkSpeedMultiplier)) >> 16;
+        v2 -= v124;
+        v126 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+        v124 = (unsigned __int64)(v126
+                                * (signed __int64)(signed int)(signed __int64)(*(float *)&v128
+                                                                             * fBackwardWalkSpeedMultiplier)) >> 16;
+LABEL_90:
+        v1 -= v124;
+        goto LABEL_86;
+      case PARTY_RunForward:
+        if ( pParty->bFlying )
+        {
+          v21 = stru_5C6E00->SinCos(_angle_y);
+          v22 = (double)_walk_speed;
+          v126 = v21;
+          *(float *)&v128 = v22;
+          v129 = (unsigned __int64)(v21
+                                  * (signed __int64)(signed int)(4
+                                                               * (unsigned __int64)(signed __int64)(v22
+                                                                                                  * fWalkSpeedMultiplier))) >> 16;
+          v2 += v129;
+          v126 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+          v129 = (unsigned __int64)(v126
+                                  * (signed __int64)(signed int)(4
+                                                               * (unsigned __int64)(signed __int64)(*(float *)&v128
+                                                                                                  * fWalkSpeedMultiplier))) >> 16;
+          v1 += v129;
+          goto LABEL_93;
+        }
+        if ( v118 && !v108 )
+        {
+          v23 = stru_5C6E00->SinCos(_angle_y);
+          v24 = (double)_walk_speed;
+          v126 = v23;
+          *(float *)&v128 = v24;
+          v129 = (unsigned __int64)(v23 * (signed __int64)(signed int)(signed __int64)(v24 * fWalkSpeedMultiplier)) >> 16;
+          v2 += v129;
+          v126 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+          v129 = (unsigned __int64)(v126
+                                  * (signed __int64)(signed int)(signed __int64)(*(float *)&v128 * fWalkSpeedMultiplier)) >> 16;
+          v1 += v129;
+          goto LABEL_86;
+        }
+        v25 = stru_5C6E00->SinCos(_angle_y);
+        v26 = (double)_walk_speed;
+        v114 = v25;
+        *(float *)&v128 = v26;
+        v129 = (unsigned __int64)(v25
+                                * (signed __int64)(signed int)(2
+                                                             * (unsigned __int64)(signed __int64)(v26
+                                                                                                * fWalkSpeedMultiplier))) >> 16;
+        v2 += v129;
+        v114 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+        v129 = (unsigned __int64)((signed int)v114
+                                * (signed __int64)(signed int)(2
+                                                             * (unsigned __int64)(signed __int64)(*(float *)&v128
+                                                                                                * fWalkSpeedMultiplier))) >> 16;
+        v1 += v129;
+        v114 = 1;
+        v128 = v1;
+        break;
+      case PARTY_RunBackward:
+        v27 = stru_5C6E00->SinCos(_angle_y);
+        v28 = (double)_walk_speed;
+        v126 = v27;
+        *(float *)&v128 = v28;
+        v29 = (signed __int64)(v28 * fBackwardWalkSpeedMultiplier);
+        if ( pParty->bFlying )
+        {
+          v129 = (unsigned __int64)(v126 * (signed __int64)(4 * (signed int)v29)) >> 16;
+          v2 -= v129;
+          v126 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+          v129 = (unsigned __int64)(v126
+                                  * (signed __int64)(signed int)(4
+                                                               * (unsigned __int64)(signed __int64)(*(float *)&v128
+                                                                                                  * fBackwardWalkSpeedMultiplier))) >> 16;
+          v1 -= v129;
+LABEL_93:
+          v128 = v1;
+        }
+        else
+        {
+          v129 = (unsigned __int64)(v126 * (signed __int64)(signed int)v29) >> 16;
+          v2 -= v129;
+          v126 = stru_5C6E00->SinCos(_angle_y - stru_5C6E00->uIntegerHalfPi);
+          v129 = (unsigned __int64)(v126
+                                  * (signed __int64)(signed int)(signed __int64)(*(float *)&v128
+                                                                               * fBackwardWalkSpeedMultiplier)) >> 16;
+          v1 -= v129;
+LABEL_86:
+          v128 = v1;
+          v124 = 1;
+        }
+        break;
+      case PARTY_LookUp:
+        _angle_x += (signed __int64)(flt_6BE150_look_up_down_dangle * 25.0);
+        if ( _angle_x > 128 )
+          _angle_x = 128;
+        v30 = uActiveCharacter;
+        if ( !uActiveCharacter )
+          goto LABEL_118;
+        v95 = 0;
+        v93 = 63;
+        goto _play_player_sound;
+      case PARTY_LookDown:
+        _angle_x += (signed __int64)(flt_6BE150_look_up_down_dangle * -25.0);
+        if ( _angle_x < -128 )
+          _angle_x = -128;
+        v30 = uActiveCharacter;
+        if ( uActiveCharacter )
+        {
+          v95 = 0;
+          v93 = 64;
+_play_player_sound:
+          pPlayers[v30]->PlaySound(v93, v95);
+        }
+        goto LABEL_118;
+      case PARTY_CenterView:
+        _angle_x = 0;
+        goto LABEL_118;
+      case PARTY_Jump:
+        if ( (!v118 || v108) && !bJumping && pParty->field_24 && !(pParty->uFlags & 4) && !(BYTE1(pParty->uFlags) & 2) )
+        {
+          v126 = pParty->field_24 << 6;
+          bJumping = 1;
+          v121 = (signed __int64)((double)(pParty->field_24 << 6) * 1.5 + (double)v121);
+        }
+        goto LABEL_118;
+      default:
+        goto LABEL_118;
+      case PARTY_Land:
+        if ( pParty->bFlying )
+        {
+          BYTE1(pParty->uFlags) |= 1u;
+          pParty->uFallSpeed = 0;
+        }
+        pParty->bFlying = 0;
+        pPartyActionQueue->uNumActions = 0;
+        goto LABEL_123;
+    }
+  }
+LABEL_123:
+  pParty->sRotationY = _angle_y;
+  pParty->sRotationX = _angle_x;
+  if ( v123 < v111 )
+  {
+    if ( pParty->bFlying )
+    {
+LABEL_130:
+      v31 = GetTickCount();
+      v126 = stru_5C6E00->SinCos(v31);
+      v129 = (unsigned __int64)(4i64 * v126) >> 16;
+      v123 = v113 + v129;
+      if ( v127 )
+        v123 = v113;
+      if ( SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) >= 0
+        && (SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[7].uExpireTime)) )
+        stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[7].uOverlayID + 119] &= 0xFEu;
+      pParty->uFallStartY = v123;
+      goto LABEL_141;
+    }
+    if ( v130 && v121 )
+      sub_42F960_create_object(v116, v117, v111);
+    v121 = 0;
+    v123 = v111;
+    pParty->uFallStartY = v111;
+  }
+  if ( pParty->bFlying )
+    goto LABEL_130;
+  v113 = v123;
+  if ( SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) >= 0
+    && (SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[7].uExpireTime)) )
+    stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[7].uOverlayID + 119] |= 1u;
+LABEL_141:
+  v32 = 0;
+  if ( bJumping && !pParty->bFlying )
+  {
+    v33 = -(pEventTimer->uTimeElapsed * GetGravityStrength());
+    v34 = v121 + 2 * v33;
+    v121 += 2 * v33;
+    goto LABEL_149;
+  }
+  if ( !v118 )
+  {
+    v34 = v121;
+LABEL_149:
+    if ( bJumping == v32 )
+      goto LABEL_150;
+    goto LABEL_164;
+  }
+  if ( !bJumping )
+  {
+    if ( v108 )
+      goto LABEL_150;
+    v123 = v111;
+    _46DCC8_get_gravity_direction_outdoor(v116, v117, (Vec3_int_ *)&v98);
+    v35 = v121 + -8 * pEventTimer->uTimeElapsed * GetGravityStrength();
+    v129 = abs((signed __int64)v2 * (signed __int64)v98 + (signed __int64)v1 * (signed __int64)v99 + (signed __int64)v35 * (signed __int64)v100) >> 16;
+    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v98) >> 16);
+    v2 += (int)v127;
+    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v99) >> 16);
+    v1 += (int)v127;
+    v128 = v1;
+    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v100) >> 16);
+    v34 = (int)((char *)v127 + v35);
+    v32 = 0;
+    v121 = v34;
+    goto LABEL_149;
+  }
+  v34 = v121;
+LABEL_164:
+  if ( !bUnderwater && v34 <= v32 )
+  {
+    if ( v34 < -500
+      && !pParty->bFlying
+      && pParty->vPosition.z - v111 > 1000
+      && SHIDWORD(pParty->pPartyBuffs[5].uExpireTime) <= 0
+      && (SHIDWORD(pParty->pPartyBuffs[5].uExpireTime) < 0 || !LODWORD(pParty->pPartyBuffs[5].uExpireTime)) )
+    {
+      v41 = &pPlayers[1];
+      do
+      {
+        if ( !(*v41)->HasEnchantedItemEquipped(72) && !(*v41)->WearsItem(529, 8) && (*v41)->CanAct() )
+          (*v41)->PlaySound(66, 0);
+        ++v41;
+      }
+      while ( (signed int)v41 <= (signed int)&pPlayers[4] );
+    }
+    goto LABEL_151;
+  }
+LABEL_150:
+  pParty->uFallStartY = v123;
+LABEL_151:
+  if ( v2 * v2 + v1 * v1 < 400 && !v118 )
+  {
+    *(float *)&v128 = 0.0;
+    v2 = 0;
+  }
+  stru_721530.field_84 = -1;
+  stru_721530.field_70 = 0;
+  stru_721530.prolly_normal_d = pParty->field_14;
+  stru_721530.field_8 = pParty->field_14 >> 1;
+  v126 = 0;
+  stru_721530.field_0 = 1;
+  stru_721530.field_C = pParty->uPartyHeight - 32;
+  do
+  {
+    stru_721530.field_34.x = v116;
+    stru_721530.normal.x = v116;
+    stru_721530.field_1C = v2;
+    stru_721530.field_34.y = v117;
+    stru_721530.normal.y = v117;
+    stru_721530.normal.z = stru_721530.prolly_normal_d + v123 + 1;
+    stru_721530.field_34.z = stru_721530.field_C + v123 + 1;
+    stru_721530.field_20 = v128;
+    stru_721530.field_24 = v121;
+    v36 = 0;
+    stru_721530.uSectorID = 0;
+    if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 3 )
+      v36 = 13312;
+    if ( stru_721530._47050A(v36) )
+      break;
+    _46E889_collide_against_bmodels(1u);
+    v37 = WorldPosToGridCellZ(pParty->vPosition.y);
+    v38 = WorldPosToGridCellX(pParty->vPosition.x);
+    _46E26D_collide_against_sprites(v38, v37);
+    _46ED8A_collide_against_layingItems(4u);
+    for ( i = 0; i < (signed int)uNumActors; ++i )
+      _46DF1A_collide_against_actor(i, 0);
+    if ( stru_721530.field_7C >= stru_721530.field_6C )
+    {
+      _angle_x = stru_721530.normal2.x;
+      _angle_y = stru_721530.normal2.y;
+      v40 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+    }
+    else
+    {
+      _angle_x = v116 + ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16);
+      _angle_y = v117 + ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16);
+      v127 = (BSPModel *)((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16);
+      v40 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16) + v123;
+    }
+    v122 = v40;
+    sub_46D49E_prolly_get_world_y_under_party(_angle_x, _angle_y, v40, pParty->uPartyHeight, &v130, &v108, 0);
+    v129 = sub_46D49E_prolly_get_world_y_under_party(_angle_x, v117, v40, pParty->uPartyHeight, &v130, &v97, 0);
+    v119 = (Player **)sub_46D49E_prolly_get_world_y_under_party(
+                        v116,
+                        _angle_y,
+                        v40,
+                        pParty->uPartyHeight,
+                        &v130,
+                        &v110,
+                        0);
+    v127 = (BSPModel *)GetTerrainHeightsAroundParty(_angle_x, v117);
+    v42 = GetTerrainHeightsAroundParty(v116, _angle_y);
+    v107 = 0;
+    v118 = v42;
+    if ( !v97 && !v110 && !v108 )
+      v107 = 1;
+    v43 = 1;
+    v44 = 1;
+    if ( bUnderwater || !v107 )
+      goto LABEL_197;
+    if ( v127 && v129 > v123 )
+      v44 = 0;
+    if ( v118 && (signed int)v119 > v123 )
+      v43 = 0;
+    if ( v44 )
+      goto LABEL_197;
+    if ( v43 )
+      goto LABEL_198;
+    v127 = (BSPModel *)sub_46D49E_prolly_get_world_y_under_party(
+                         _angle_x,
+                         _angle_y,
+                         v40,
+                         pParty->uPartyHeight,
+                         &v130,
+                         &v108,
+                         0);
+    if ( GetTerrainHeightsAroundParty(_angle_x, _angle_y) && (signed int)v127 <= v123 )
+    {
+      v43 = 1;
+LABEL_197:
+      v116 = _angle_x;
+      if ( !v43 )
+        goto LABEL_199;
+LABEL_198:
+      v117 = _angle_y;
+    }
+LABEL_199:
+    if ( stru_721530.field_7C >= stru_721530.field_6C )
+    {
+      if ( !v107 )
+      {
+        v116 = stru_721530.normal2.x;
+        v117 = stru_721530.normal2.y;
+      }
+      v123 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
+      break;
+    }
+    stru_721530.field_70 += stru_721530.field_7C;
+    v116 = _angle_x;
+    v117 = _angle_y;
+    v45 = stru_721530.uFaceID;
+    v123 = v40;
+    if ( (stru_721530.uFaceID & 7) == 3 )
+    {
+      if ( SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) >= 0
+        && (SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[11].uExpireTime)) )
+        pParty->pPartyBuffs[11].Reset();
+      viewparams->bRedrawGameUI = 1;
+      goto LABEL_234;
+    }
+    if ( (stru_721530.uFaceID & 7) == 5 )
+    {
+      v56 = sub_452A9E(v2 * v2 + v128 * v128);
+      v118 = v56;
+      v57 = stru_5C6E00->Atan2(
+              _angle_x - pLevelDecorations[(signed int)stru_721530.uFaceID >> 3].vPosition.x,
+              _angle_y - pLevelDecorations[(signed int)stru_721530.uFaceID >> 3].vPosition.y);
+      v129 = v57;
+      v58 = (BSPModel *)stru_5C6E00->SinCos(v57);
+      v127 = v58;
+      v59 = (signed int)v58 * (signed __int64)v56;
+      v122 = v59 >> 16;
+      v2 = v59 >> 16;
+      v60 = (BSPModel *)stru_5C6E00->SinCos(v129 - stru_5C6E00->uIntegerHalfPi);
+      v127 = v60;
+      v61 = (signed int)v60 * (signed __int64)v118;
+      v122 = v61 >> 16;
+      v128 = v61 >> 16;
+    }
+    else
+    {
+      if ( (stru_721530.uFaceID & 7) == 6 )
+      {
+        pParty->bFlying = 0;
+        v46 = &pOutdoor->pBModels[(signed int)stru_721530.uFaceID >> 9];
+        v127 = v46;
+        v47 = &v46->pFaces[((signed int)stru_721530.uFaceID >> 3) & 0x3F];
+        v48 = v47->pBoundingBox.z2 - v47->pBoundingBox.z1;
+        v51 = __OFSUB__(v48, 32);
+        v49 = v48 == 32;
+        v50 = v48 - 32 < 0;
+        v52 = v47->pFacePlane.vNormal.z;
+        v129 = (unsigned __int8)(v50 ^ v51 | v49);
+        v119 = (Player **)(v52 < 46378);
+        if ( bUnderwater == 1 )
+          v119 = 0;
+        v53 = v47->uPolygonType;
+        if ( v53 == 3 )
+        {
+          if ( v121 < 0 )
+            v121 = 0;
+          v123 = v127->pVertices.pVertices[v47->pVertexIDs[0]].z + 1;
+          if ( v2 * v2 + v128 * v128 < 400 )
+          {
+            v2 = 0;
+            *(float *)&v128 = 0.0;
+          }
+          goto LABEL_221;
+        }
+        if ( !v129 && (v53 != 4 || v119) )
+        {
+          v118 = abs(v128 * v47->pFacePlane.vNormal.y + v121 * v52 + v2 * v47->pFacePlane.vNormal.x) >> 16;
+          if ( stru_721530.field_64 >> 3 > v118 )
+            v118 = stru_721530.field_64 >> 3;
+          v129 = v47->pFacePlane.vNormal.x;
+          v129 = (unsigned __int64)(v118 * (signed __int64)v129) >> 16;
+          _walk_speed = v47->pFacePlane.vNormal.y;
+          _walk_speed = (unsigned __int64)(v118 * (signed __int64)_walk_speed) >> 16;
+          v54 = 0;
+          if ( !v119 )
+          {
+            v127 = (BSPModel *)v47->pFacePlane.vNormal.z;
+            v127 = (BSPModel *)((unsigned __int64)(v118 * (signed __int64)(signed int)v127) >> 16);
+            v54 = v127;
+          }
+          v121 += (int)v54;
+          v128 += _walk_speed;
+          v2 += v129;
+          v55 = stru_721530.prolly_normal_d
+              - ((signed int)(v47->pFacePlane.dist
+                            + v122 * v47->pFacePlane.vNormal.z
+                            + _angle_y * v47->pFacePlane.vNormal.y
+                            + _angle_x * v47->pFacePlane.vNormal.x) >> 16);
+          if ( v55 > 0 )
+          {
+            v116 = _angle_x + (v47->pFacePlane.vNormal.x * v55 >> 16);
+            v117 = _angle_y + (v47->pFacePlane.vNormal.y * v55 >> 16);
+            if ( !v119 )
+              v123 = v122 + (v47->pFacePlane.vNormal.z * v55 >> 16);
+          }
+LABEL_220:
+          v45 = stru_721530.uFaceID;
+LABEL_221:
+          if ( pParty->field_6F4_packedid != v45 && BYTE3(v47->uAttributes) & 4 )
+          {
+            pParty->field_6F4_packedid = v45;
+            v103 = v47->sCogTriggeredID;
+          }
+          goto LABEL_234;
+        }
+        v118 = abs(v128 * v47->pFacePlane.vNormal.y + v121 * v52 + v2 * v47->pFacePlane.vNormal.x) >> 16;
+        if ( stru_721530.field_64 >> 3 > v118 )
+          v118 = stru_721530.field_64 >> 3;
+        v122 = v47->pFacePlane.vNormal.x;
+        v122 = (unsigned __int64)(v118 * (signed __int64)(signed int)v122) >> 16;
+        v127 = (BSPModel *)v47->pFacePlane.vNormal.y;
+        v127 = (BSPModel *)((unsigned __int64)(v118 * (signed __int64)(signed int)v127) >> 16);
+        v129 = v47->pFacePlane.vNormal.z;
+        v129 = (unsigned __int64)(v118 * (signed __int64)v129) >> 16;
+        v121 += v129;
+        v2 += v122;
+        v128 += (int)v127;
+        if ( v2 * v2 + v128 * v128 >= 400 )
+          goto LABEL_220;
+        v2 = 0;
+        v121 = 0;
+        *(float *)&v128 = 0.0;
+      }
+    }
+LABEL_234:
+    v2 = (unsigned __int64)(58500i64 * v2) >> 16;
+    v127 = (BSPModel *)58500;
+    v128 = (unsigned __int64)(58500i64 * v128) >> 16;
+    v122 = (unsigned __int64)(58500i64 * v121) >> 16;
+    ++v126;
+    v121 = (unsigned __int64)(58500i64 * v121) >> 16;
+  }
+  while ( v126 < 100 );
+  if ( bWalkSound && pParty->field_6F8 <= 0 )
+  {
+    v122 = abs(pParty->vPosition.x - v116);
+    v126 = abs(pParty->vPosition.y - v117);
+    v62 = abs(pParty->vPosition.z - v123);
+    if ( sub_452A9E(v122 * v122 + v126 * v126 + v62 * v62) < 8 )
+      goto LABEL_344;
+    if ( v114 && (!bJumping || v101) )
+    {
+      if ( !v107
+        && !(BYTE1(pOutdoor->pBModels[pParty->field_6F4_packedid >> 9].pFaces[(pParty->field_6F4_packedid >> 3) & 0x3F].uAttributes) & 0x20) )
+      {
+        v96 = 0;
+        v94 = 0;
+        v92 = 0;
+        v91 = 0;
+        v90 = -1;
+        v89 = 1;
+        v88 = 804;
+        v87 = 64;
+        goto LABEL_257;
+      }
+      v96 = 0;
+      v94 = 0;
+      v92 = 0;
+      v91 = 0;
+      v90 = -1;
+      v89 = 1;
+      v88 = 804;
+      v86 = 1;
+LABEL_255:
+      v63 = WorldPosToGridCellZ(pParty->vPosition.y) - 1;
+      v64 = WorldPosToGridCellX(pParty->vPosition.x);
+      v87 = pOutdoor->_47EE49(v64, v63, v86);
+      goto LABEL_257;
+    }
+    if ( v124 && (!bJumping || v101) )
+    {
+      if ( v107
+        || BYTE1(pOutdoor->pBModels[pParty->field_6F4_packedid >> 9].pFaces[(pParty->field_6F4_packedid >> 3) & 0x3F].uAttributes) & 0x20 )
+      {
+        v96 = 0;
+        v94 = 0;
+        v92 = 0;
+        v91 = 0;
+        v90 = -1;
+        v89 = 1;
+        v88 = 804;
+        v86 = 0;
+        goto LABEL_255;
+      }
+      v96 = 0;
+      v94 = 0;
+      v92 = 0;
+      v91 = 0;
+      v90 = -1;
+      v89 = 1;
+      v88 = 804;
+      v87 = 103;
+LABEL_257:
+      pAudioPlayer->PlaySound((SoundID)v87, v88, v89, v90, v91, v92, v94, v96);
+    }
+    else
+    {
+LABEL_344:
+      pAudioPlayer->_4AA258(804);
+      pParty->field_6F8 = 64;
+    }
+  }
+  if ( !bJumping || v101 )
+    pParty->uFlags &= 0xFFFFFFF7u;
+  else
+    pParty->uFlags |= 8u;
+  v126 = WorldPosToGridCellX(pParty->vPosition.x);
+  v65 = WorldPosToGridCellZ(pParty->vPosition.y) - 1;
+  v114 = WorldPosToGridCellX(v116);
+  v66 = WorldPosToGridCellZ(v117) - 1;
+  v127 = (BSPModel *)(((unsigned int)~pOutdoor->ActuallyGetSomeOtherTileInfo(v126, v65) >> 1) & 1);
+  v122 = ((unsigned int)~pOutdoor->ActuallyGetSomeOtherTileInfo(v114, v65) >> 1) & 1;
+  v67 = pOutdoor->ActuallyGetSomeOtherTileInfo(v126, v66);
+  v68 = 0;
+  v69 = ((unsigned int)~v67 >> 1) & 1;
+  if ( v114 == v126 && v66 == v65 && v122 && v69 )
+    v68 = 1;
+  if ( !v107 )
+    v68 = 1;
+  if ( v68 )
+  {
+    v70 = v123;
+    v71 = v116;
+    v72 = v117;
+    pParty->uFallSpeed = v121;
+    v73 = v123;
+    pParty->vPosition.x = v116;
+    pParty->vPosition.y = v117;
+    pParty->vPosition.z = v123;
+    pParty->field_6F0 = v113;
+    if ( v123 > 8160 )
+    {
+      v73 = 8160;
+      pParty->uFallStartY = 8160;
+      pParty->vPosition.z = 8160;
+    }
+    if ( !v103
+      || (EventProcessor(v103, 0, 1), pParty->vPosition.x == v71)
+      && pParty->vPosition.y == v72
+      && (v73 = pParty->vPosition.z, pParty->vPosition.z == v70) )
+    {
+      if ( v73 < v111 )
+      {
+        pParty->uFallSpeed = 0;
+        v73 = v105;
+        pParty->vPosition.z = v105;
+        if ( pParty->uFallStartY - v70 > 512 && !bFeatherFall && v70 <= v105 && !bUnderwater )
+        {
+          if ( pParty->uFlags & 0x100 )
+          {
+            BYTE1(pParty->uFlags) &= 0xFEu;
+          }
+          else
+          {
+            v74 = &pPlayers[1];
+            do
+            {
+              v110 = (*v74)->GetMaxHealth();
+              (*v74)->ReceiveDamage(
+                (signed int)((pParty->uFallStartY - v70) * (unsigned __int64)(signed __int64)((double)v110 * 0.1)) / 256,
+                4);
+              v75 = (*v74)->GetActualEndurance();
+              v110 = 20 - (*v74)->_48EA1B_get_static_effect(v75);
+              (*v74)->SetRecoveryTime(
+                (signed __int64)((double)v110 * flt_6BE3A4_debug_recmod1 * 2.133333333333333));
+              ++v74;
+            }
+            while ( (signed int)v74 <= (signed int)&pPlayers[4] );
+            v73 = pParty->vPosition.z;
+          }
+        }
+        pParty->uFallStartY = v70;
+      }
+      if ( v102 && v73 < v109 )
+      {
+        if ( (signed int)(pParty->uPartyHeight + v73) >= v109 )
+        {
+          pParty->vPosition.z = v109 - pParty->uPartyHeight - 1;
+          pParty->field_6F0 = v109 - pParty->uPartyHeight - 1;
+        }
+      }
+      LOWORD(pParty->uFlags) &= 0xFDFBu;
+    }
+    return;
+  }
+  v76 = pParty->bFlying;
+  if ( pParty->bFlying || v101 == 0 || bWaterWalk || !v127 )
+    v77 = 1;
+  else
+    v77 = v122 != 0;
+  v114 = 0;
+  if ( !pParty->bFlying && v101 != 0 && !bWaterWalk )
+  {
+    if ( v127 )
+    {
+      v78 = v69 != 0;
+      goto LABEL_306;
+    }
+    v114 = 1;
+  }
+  v78 = 1;
+LABEL_306:
+  if ( v77 )
+  {
+    pParty->vPosition.x = v116;
+    if ( !v78 )
+      goto LABEL_313;
+    goto LABEL_312;
+  }
+  if ( v78 )
+  {
+LABEL_312:
+    pParty->vPosition.y = v117;
+LABEL_313:
+    if ( bWaterWalk )
+    {
+      LOBYTE(pParty->uFlags) &= 0x7Fu;
+      v79 = 20 * pParty->pPartyBuffs[18].uOverlayID + 6180178;
+      *(short *)&stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[18].uOverlayID + 119] |= 1u;
+      if ( !v122 || !v69 )
+      {
+        if ( !v76 )
+        {
+          v80 = *(short *)v79;
+          LOBYTE(pParty->uFlags) |= 0x80u;
+          *(short *)v79 = v80 & 0xFFFE;
+        }
+      }
+    }
+    goto LABEL_318;
+  }
+  if ( bWalkSound && pParty->field_6F8 <= 0 )
+  {
+    pAudioPlayer->_4AA258(804);
+    pParty->field_6F8 = 64;
+  }
+LABEL_318:
+  v81 = v123;
+  v82 = v123;
+  pParty->vPosition.z = v123;
+  if ( v123 > 8160 )
+  {
+    v82 = 8160;
+    pParty->uFallStartY = 8160;
+    pParty->vPosition.z = 8160;
+  }
+  LOWORD(pParty->uFlags) &= 0xFDFBu;
+  pParty->uFallSpeed = v121;
+  pParty->field_6F0 = v113;
+  if ( v114 )
+  {
+    v83 = GetTerrainHeightsAroundParty2(pParty->vPosition.x, pParty->vPosition.y, &v110, 1);
+    v82 = pParty->vPosition.z;
+    if ( pParty->vPosition.z <= v83 )
+      pParty->uFlags |= 4u;
+  }
+  if ( !v103
+    || (EventProcessor(v103, 0, 1), pParty->vPosition.x == v116)
+    && pParty->vPosition.y == v117
+    && (v82 = pParty->vPosition.z, pParty->vPosition.z == v81) )
+  {
+    if ( v82 < v111 )
+    {
+      v82 = v105;
+      pParty->uFallSpeed = 0;
+      pParty->vPosition.z = v105;
+      if ( pParty->uFallStartY - v81 > 512 && !bFeatherFall && v81 <= v105 && !bUnderwater )
+      {
+        if ( pParty->uFlags & 0x100 )
+        {
+          BYTE1(pParty->uFlags) &= 0xFEu;
+        }
+        else
+        {
+          v84 = &pPlayers[1];
+          do
+          {
+            v110 = (*v84)->GetMaxHealth();
+            (*v84)->ReceiveDamage(
+              (signed int)((pParty->uFallStartY - v81) * (unsigned __int64)(signed __int64)((double)v110 * 0.1)) / 256,
+              4);
+            v85 = (*v84)->GetActualEndurance();
+            v110 = 20 - (*v84)->_48EA1B_get_static_effect(v85);
+            (*v84)->SetRecoveryTime((signed __int64)((double)v110 * flt_6BE3A4_debug_recmod1 * 2.133333333333333));
+            ++v84;
+          }
+          while ( (signed int)v84 <= (signed int)&pPlayers[4] );
+          v82 = pParty->vPosition.z;
+        }
+      }
+      pParty->uFallStartY = v81;
+    }
+    if ( v102 && v82 < v109 && (signed int)(pParty->uPartyHeight + v82) >= v109 )
+    {
+      pParty->vPosition.z = v82 + pParty->uPartyHeight - v109 + 1;
+      pParty->field_6F0 = v82 + pParty->uPartyHeight - v109 + 1;
+    }
+  }
+}
+
+
+
+
+
+//----- (0047531C) --------------------------------------------------------
+bool __fastcall sub_47531C(int a1, int *a2, int a3, int a4, int a5, int a6, int a7, int a8, BLVFace *a9, int a10)
+{
+  BLVFace *v10; // ebx@1
+  int v11; // ST1C_4@3
+  int v12; // edi@3
+  int v13; // esi@3
+  int v14; // edi@4
+  signed __int64 v15; // qtt@6
+  __int16 v16; // si@7
+  int *v18; // [sp+Ch] [bp-Ch]@1
+  int v19; // [sp+10h] [bp-8h]@1
+  int a7a; // [sp+30h] [bp+18h]@7
+  int a9b; // [sp+38h] [bp+20h]@3
+  int a9a; // [sp+38h] [bp+20h]@3
+  int a10b; // [sp+3Ch] [bp+24h]@3
+  signed int a10a; // [sp+3Ch] [bp+24h]@4
+  int a10c; // [sp+3Ch] [bp+24h]@5
+
+  v10 = a9;
+  v18 = a2;
+  v19 = a1;
+  if ( a10 && BYTE3(a9->uAttributes) & 0x20 )
+    return 0;
+  v11 = (unsigned __int64)(a6 * (signed __int64)a9->pFacePlane_old.vNormal.x) >> 16;
+  a10b = (unsigned __int64)(a7 * (signed __int64)a9->pFacePlane_old.vNormal.y) >> 16;
+  a9b = (unsigned __int64)(a8 * (signed __int64)a9->pFacePlane_old.vNormal.z) >> 16;
+  v12 = v11 + a9b + a10b;
+  a9a = v11 + a9b + a10b;
+  v13 = (a1 << 16)
+      - a3 * v10->pFacePlane_old.vNormal.x
+      - a4 * v10->pFacePlane_old.vNormal.y
+      - a5 * v10->pFacePlane_old.vNormal.z
+      - v10->pFacePlane_old.dist;
+  if ( abs((a1 << 16)
+         - a3 * v10->pFacePlane_old.vNormal.x
+         - a4 * v10->pFacePlane_old.vNormal.y
+         - a5 * v10->pFacePlane_old.vNormal.z - v10->pFacePlane_old.dist) >= a1 << 16 )
+  {
+    a10c = abs(v13) >> 14;
+    if ( a10c > abs(v12) )
+      return 0;
+    LODWORD(v15) = v13 << 16;
+    HIDWORD(v15) = v13 >> 16;
+    v14 = v19;
+    a10a = v15 / a9a;
+  }
+  else
+  {
+    a10a = 0;
+    v14 = abs(v13) >> 16;
+  }
+  v16 = a4 + ((unsigned int)((unsigned __int64)(a10a * (signed __int64)a7) >> 16) >> 16);
+  LOWORD(a7a) = (short)a3
+              + ((unsigned int)((unsigned __int64)(a10a * (signed __int64)a6) >> 16) >> 16)
+              - ((unsigned int)(v14 * v10->pFacePlane_old.vNormal.x) >> 16);
+  HIWORD(a7a) = v16 - ((unsigned int)(v14 * v10->pFacePlane_old.vNormal.y) >> 16);
+  if ( !sub_475665(
+          v10,
+          a7a,
+          (short)a5
+        + ((unsigned int)((unsigned __int64)(a10a * (signed __int64)a8) >> 16) >> 16)
+        - ((unsigned int)(v14 * v10->pFacePlane_old.vNormal.z) >> 16)) )
+    return 0;
+  *v18 = a10a >> 16;
+  if ( a10a >> 16 < 0 )
+    *v18 = 0;
+  return 1;
+}
+
+//----- (004754BF) --------------------------------------------------------
+bool __fastcall sub_4754BF(int a1, int *a2, int a3, int a4, int a5, int a6, int a7, int a8, BLVFace *a9, int a10, int a11)
+{
+  BLVFace *v11; // ebx@1
+  int v12; // ST1C_4@3
+  int v13; // edi@3
+  int v14; // esi@3
+  int v15; // edi@4
+  signed __int64 v16; // qtt@6
+  __int16 v17; // si@7
+  int *v19; // [sp+Ch] [bp-Ch]@1
+  int v20; // [sp+10h] [bp-8h]@1
+  int a7a; // [sp+30h] [bp+18h]@7
+  int a1b; // [sp+38h] [bp+20h]@3
+  int a1a; // [sp+38h] [bp+20h]@3
+  int a11b; // [sp+40h] [bp+28h]@3
+  signed int a11a; // [sp+40h] [bp+28h]@4
+  int a11c; // [sp+40h] [bp+28h]@5
+
+  v11 = a9;
+  v19 = a2;
+  v20 = a1;
+  if ( a11 && BYTE3(a9->uAttributes) & 0x20 )
+    return 0;
+  v12 = (unsigned __int64)(a6 * (signed __int64)a9->pFacePlane_old.vNormal.x) >> 16;
+  a11b = (unsigned __int64)(a7 * (signed __int64)a9->pFacePlane_old.vNormal.y) >> 16;
+  a1b = (unsigned __int64)(a8 * (signed __int64)a9->pFacePlane_old.vNormal.z) >> 16;
+  v13 = v12 + a1b + a11b;
+  a1a = v12 + a1b + a11b;
+  v14 = (a1 << 16)
+      - a3 * v11->pFacePlane_old.vNormal.x
+      - a4 * v11->pFacePlane_old.vNormal.y
+      - a5 * v11->pFacePlane_old.vNormal.z
+      - v11->pFacePlane_old.dist;
+  if ( abs((a1 << 16)
+         - a3 * v11->pFacePlane_old.vNormal.x
+         - a4 * v11->pFacePlane_old.vNormal.y
+         - a5 * v11->pFacePlane_old.vNormal.z - v11->pFacePlane_old.dist) >= a1 << 16 )
+  {
+    a11c = abs(v14) >> 14;
+    if ( a11c > abs(v13) )
+      return 0;
+    LODWORD(v16) = v14 << 16;
+    HIDWORD(v16) = v14 >> 16;
+    v15 = v20;
+    a11a = v16 / a1a;
+  }
+  else
+  {
+    a11a = 0;
+    v15 = abs(v14) >> 16;
+  }
+  v17 = a4 + ((unsigned int)((unsigned __int64)(a11a * (signed __int64)a7) >> 16) >> 16);
+  LOWORD(a7a) = (short)a3
+              + ((unsigned int)((unsigned __int64)(a11a * (signed __int64)a6) >> 16) >> 16)
+              - ((unsigned int)(v15 * v11->pFacePlane_old.vNormal.x) >> 16);
+  HIWORD(a7a) = v17 - ((unsigned int)(v15 * v11->pFacePlane_old.vNormal.y) >> 16);
+  if ( !sub_4759C9(
+          v11,
+          a10,
+          a7a,
+          (short)a5
+        + ((unsigned int)((unsigned __int64)(a11a * (signed __int64)a8) >> 16) >> 16)
+        - ((unsigned int)(v15 * v11->pFacePlane_old.vNormal.z) >> 16)) )
+    return 0;
+  *v19 = a11a >> 16;
+  if ( a11a >> 16 < 0 )
+    *v19 = 0;
+  return 1;
+}
+
+
+
+//----- (00475665) --------------------------------------------------------
+signed int __thiscall sub_475665(BLVFace *_this, int a2, __int16 a3)
+{
+  unsigned int v3; // eax@1
+  Vec3_short_ *v4; // edx@3
+  signed int v5; // eax@4
+  int v6; // esi@4
+  signed int v7; // eax@7
+  Vec3_short_ *v8; // edx@8
+  signed int v9; // eax@9
+  int v10; // esi@9
+  signed int v11; // eax@11
+  Vec3_short_ *v12; // edx@12
+  signed int v13; // eax@13
+  int v14; // esi@13
+  int v15; // esi@14
+  bool v16; // edi@14
+  int v17; // ecx@16
+  signed int v18; // edx@16
+  int v19; // eax@17
+  signed int v20; // ebx@18
+  int v21; // edi@20
+  signed int v22; // ST14_4@22
+  signed __int64 v23; // qtt@22
+  signed int result; // eax@25
+  int v25; // [sp+14h] [bp-10h]@14
+  int v26; // [sp+1Ch] [bp-8h]@2
+  signed int v27; // [sp+20h] [bp-4h]@2
+  signed int v28; // [sp+30h] [bp+Ch]@2
+  signed int v29; // [sp+30h] [bp+Ch]@7
+  signed int v30; // [sp+30h] [bp+Ch]@11
+  signed int v31; // [sp+30h] [bp+Ch]@14
+
+  v3 = _this->uAttributes;
+  if ( BYTE1(v3) & 1 )
+  {
+    v28 = 0;
+    v26 = (signed __int16)a2;
+    v27 = SHIWORD(a2);
+    if ( _this->uNumVertices )
+    {
+      v4 = pIndoor->pVertices;
+      do
+      {
+        v5 = v28;
+        v6 = 2 * v28;
+        word_720C10_intercepts_xs[2 * v28] = _this->pXInterceptDisplacements[v28] + v4[_this->pVertexIDs[v28]].x;
+        word_720B40_intercepts_zs[2 * v28] = _this->pYInterceptDisplacements[v5] + v4[_this->pVertexIDs[v5]].y;
+        word_720C10_intercepts_xs[2 * v28++ + 1] = _this->pXInterceptDisplacements[v5 + 1]
+                                                 + v4[_this->pVertexIDs[v5 + 1]].x;
+        word_720B40_intercepts_zs[v6 + 1] = _this->pYInterceptDisplacements[v5 + 1] + v4[_this->pVertexIDs[v5 + 1]].y;
+      }
+      while ( v28 < _this->uNumVertices );
+    }
+  }
+  else
+  {
+    if ( BYTE1(v3) & 2 )
+    {
+      v26 = (signed __int16)a2;
+      v7 = a3;
+      v29 = 0;
+      v27 = v7;
+      if ( _this->uNumVertices )
+      {
+        v8 = pIndoor->pVertices;
+        do
+        {
+          v9 = v29;
+          v10 = 2 * v29;
+          word_720C10_intercepts_xs[2 * v29] = _this->pXInterceptDisplacements[v29] + v8[_this->pVertexIDs[v29]].x;
+          word_720B40_intercepts_zs[2 * v29] = _this->pZInterceptDisplacements[v9] + v8[_this->pVertexIDs[v9]].z;
+          word_720C10_intercepts_xs[2 * v29++ + 1] = _this->pXInterceptDisplacements[v9 + 1] + v8[_this->pVertexIDs[v9 + 1]].x;
+          word_720B40_intercepts_zs[v10 + 1] = _this->pZInterceptDisplacements[v9 + 1] + v8[_this->pVertexIDs[v9 + 1]].z;
+        }
+        while ( v29 < _this->uNumVertices );
+      }
+    }
+    else
+    {
+      v26 = SHIWORD(a2);
+      v11 = a3;
+      v30 = 0;
+      v27 = v11;
+      if ( _this->uNumVertices )
+      {
+        v12 = pIndoor->pVertices;
+        do
+        {
+          v13 = v30;
+          v14 = 2 * v30;
+          word_720C10_intercepts_xs[2 * v30] = _this->pYInterceptDisplacements[v30] + v12[_this->pVertexIDs[v30]].y;
+          word_720B40_intercepts_zs[2 * v30] = _this->pZInterceptDisplacements[v13] + v12[_this->pVertexIDs[v13]].z;
+          word_720C10_intercepts_xs[2 * v30++ + 1] = _this->pYInterceptDisplacements[v13 + 1] + v12[_this->pVertexIDs[v13 + 1]].y;
+          word_720B40_intercepts_zs[v14 + 1] = _this->pZInterceptDisplacements[v13 + 1] + v12[_this->pVertexIDs[v13 + 1]].z;
+        }
+        while ( v30 < _this->uNumVertices );
+      }
+    }
+  }
+  v15 = 2 * _this->uNumVertices;
+  v31 = 0;
+  word_720C10_intercepts_xs[2 * _this->uNumVertices] = word_720C10_intercepts_xs[0];
+  word_720B40_intercepts_zs[v15] = word_720B40_intercepts_zs[0];
+  v25 = 0;
+  v16 = word_720B40_intercepts_zs[0] >= v27;
+  if ( v15 <= 0 )
+    goto LABEL_29;
+  do
+  {
+    if ( v31 >= 2 )
+      break;
+    v17 = v25;
+    v18 = word_720B40_intercepts_zs[v25 + 1];
+    if ( v16 ^ v18 >= v27 )
+    {
+      v19 = word_720C10_intercepts_xs[v17 + 1];
+      if ( v19 >= v26 )
+        v20 = 0;
+      else
+        v20 = 2;
+      v21 = v20 | word_720C10_intercepts_xs[v17] < v26;
+      if ( v21 != 3 )
+      {
+        if ( !v21
+          || (v22 = v19 - word_720C10_intercepts_xs[v17],
+              LODWORD(v23) = v22 << 16,
+              HIDWORD(v23) = v22 >> 16,
+              word_720C10_intercepts_xs[v17]
+            + ((signed int)(((unsigned __int64)(v23
+                                              / (v18 - word_720B40_intercepts_zs[v17])
+                                              * ((v27 - (signed int)word_720B40_intercepts_zs[v17]) << 16)) >> 16)
+                          + 32768) >> 16) >= v26) )
+          ++v31;
+      }
+    }
+    ++v25;
+    v16 = v18 >= v27;
+  }
+  while ( v25 < v15 );
+  result = 1;
+  if ( v31 != 1 )
+LABEL_29:
+    result = 0;
+  return result;
+}
+
+//----- (004759C9) --------------------------------------------------------
+bool __fastcall sub_4759C9(BLVFace *a1, int a2, int a3, __int16 a4)
+{
+  unsigned int v4; // eax@1
+  int v5; // edx@4
+  __int16 v6; // si@4
+  int v7; // edx@9
+  __int16 v8; // si@9
+  int v9; // edx@13
+  __int16 v10; // si@13
+  int v11; // esi@14
+  bool v12; // edi@14
+  int v13; // ecx@16
+  signed int v14; // edx@16
+  int v15; // eax@17
+  signed int v16; // ebx@18
+  int v17; // edi@20
+  signed int v18; // ST14_4@22
+  signed __int64 v19; // qtt@22
+  bool result; // eax@25
+  int v21; // [sp+14h] [bp-10h]@14
+  signed int v22; // [sp+18h] [bp-Ch]@1
+  int v23; // [sp+1Ch] [bp-8h]@2
+  signed int v24; // [sp+20h] [bp-4h]@2
+  Vec3_int_ **a4a; // [sp+30h] [bp+Ch]@3
+  Vec3_int_ **a4b; // [sp+30h] [bp+Ch]@8
+  Vec3_int_ **a4c; // [sp+30h] [bp+Ch]@12
+  signed int a4d; // [sp+30h] [bp+Ch]@14
+
+  v4 = a1->uAttributes;
+  v22 = 0;
+  if ( BYTE1(v4) & 1 )
+  {
+    v23 = (signed __int16)a3;
+    v24 = SHIWORD(a3);
+    if ( a1->uNumVertices )
+    {
+      a4a = &pOutdoor->pBModels[a2].pVertices.pVertices;
+      do
+      {
+        v5 = 2 * v22;
+        word_720A70_intercepts_xs_plus_xs[2 * v22] = a1->pXInterceptDisplacements[v22] + LOWORD((*a4a)[a1->pVertexIDs[v22]].x);
+        word_7209A0_intercepts_ys_plus_ys[2 * v22] = a1->pYInterceptDisplacements[v22] + LOWORD((*a4a)[a1->pVertexIDs[v22]].y);
+        word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = a1->pXInterceptDisplacements[v22 + 1] + LOWORD((*a4a)[a1->pVertexIDs[v22 + 1]].x);
+        word_7209A0_intercepts_ys_plus_ys[v5 + 1] = v6 = a1->pYInterceptDisplacements[v22 + 1] + LOWORD((*a4a)[a1->pVertexIDs[v22 + 1]].y);
+        ++v22;
+      }
+      while ( v22 < a1->uNumVertices );
+    }
+  }
+  else
+  {
+    if ( BYTE1(v4) & 2 )
+    {
+      v23 = (signed __int16)a3;
+      v24 = a4;
+      if ( a1->uNumVertices )
+      {
+        a4b = &pOutdoor->pBModels[a2].pVertices.pVertices;
+        do
+        {
+          v7 = 2 * v22;
+          word_720A70_intercepts_xs_plus_xs[2 * v22] = a1->pXInterceptDisplacements[v22] + LOWORD((*a4b)[a1->pVertexIDs[v22]].x);
+          word_7209A0_intercepts_ys_plus_ys[2 * v22] = a1->pZInterceptDisplacements[v22] + LOWORD((*a4b)[a1->pVertexIDs[v22]].z);
+          word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = a1->pXInterceptDisplacements[v22 + 1] + LOWORD((*a4b)[a1->pVertexIDs[v22 + 1]].x);
+          word_7209A0_intercepts_ys_plus_ys[v7 + 1] = v8 = a1->pZInterceptDisplacements[v22 + 1] + LOWORD((*a4b)[a1->pVertexIDs[v22 + 1]].z);
+          ++v22;
+        }
+        while ( v22 < a1->uNumVertices );
+      }
+    }
+    else
+    {
+      v23 = SHIWORD(a3);
+      v24 = a4;
+      if ( a1->uNumVertices )
+      {
+        a4c = &pOutdoor->pBModels[a2].pVertices.pVertices;
+        do
+        {
+          v9 = 2 * v22;
+          word_720A70_intercepts_xs_plus_xs[2 * v22] = a1->pYInterceptDisplacements[v22] + LOWORD((*a4c)[a1->pVertexIDs[v22]].y);
+          word_7209A0_intercepts_ys_plus_ys[2 * v22] = a1->pZInterceptDisplacements[v22] + LOWORD((*a4c)[a1->pVertexIDs[v22]].z);
+          word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = a1->pYInterceptDisplacements[v22 + 1] + LOWORD((*a4c)[a1->pVertexIDs[v22 + 1]].y);
+          word_7209A0_intercepts_ys_plus_ys[v9 + 1] = v10 = a1->pZInterceptDisplacements[v22 + 1] + LOWORD((*a4c)[a1->pVertexIDs[v22 + 1]].z);
+          ++v22;
+        }
+        while ( v22 < a1->uNumVertices );
+      }
+    }
+  }
+  v11 = 2 * a1->uNumVertices;
+  a4d = 0;
+  word_720A70_intercepts_xs_plus_xs[2 * a1->uNumVertices] = word_720A70_intercepts_xs_plus_xs[0];
+  word_7209A0_intercepts_ys_plus_ys[v11] = word_7209A0_intercepts_ys_plus_ys[0];
+  v21 = 0;
+  v12 = word_7209A0_intercepts_ys_plus_ys[0] >= v24;
+  if ( v11 <= 0 )
+    goto LABEL_29;
+  do
+  {
+    if ( a4d >= 2 )
+      break;
+    v13 = v21;
+    v14 = word_7209A0_intercepts_ys_plus_ys[v21 + 1];
+    if ( v12 ^ v14 >= v24 )
+    {
+      v15 = word_720A70_intercepts_xs_plus_xs[v13 + 1];
+      if ( v15 >= v23 )
+        v16 = 0;
+      else
+        v16 = 2;
+      v17 = v16 | word_720A70_intercepts_xs_plus_xs[v13] < v23;
+      if ( v17 != 3 )
+      {
+        if ( !v17
+          || (v18 = v15 - word_720A70_intercepts_xs_plus_xs[v13],
+              LODWORD(v19) = v18 << 16,
+              HIDWORD(v19) = v18 >> 16,
+              word_720A70_intercepts_xs_plus_xs[v13]
+            + ((signed int)(((unsigned __int64)(v19
+                                              / (v14 - word_7209A0_intercepts_ys_plus_ys[v13])
+                                              * ((v24 - (signed int)word_7209A0_intercepts_ys_plus_ys[v13]) << 16)) >> 16)
+                          + 32768) >> 16) >= v23) )
+          ++a4d;
+      }
+    }
+    ++v21;
+    v12 = v14 >= v24;
+  }
+  while ( v21 < v11 );
+  result = 1;
+  if ( a4d != 1 )
+LABEL_29:
+    result = 0;
+  return result;
+}
+
+//----- (00475D85) --------------------------------------------------------
+bool __fastcall sub_475D85(Vec3_int_ *a1, Vec3_int_ *a2, int *a3, BLVFace *a4)
+{
+  BLVFace *v4; // ebx@1
+  int v5; // ST24_4@2
+  int v6; // ST28_4@2
+  int v7; // edi@2
+  int v8; // eax@5
+  signed int v9; // esi@5
+  signed __int64 v10; // qtt@10
+  Vec3_int_ *v11; // esi@11
+  int v12; // ST14_4@11
+  Vec3_int_ *v14; // [sp+Ch] [bp-18h]@1
+  Vec3_int_ *v15; // [sp+14h] [bp-10h]@1
+  int v16; // [sp+18h] [bp-Ch]@2
+  int v17; // [sp+20h] [bp-4h]@10
+  int a4b; // [sp+30h] [bp+Ch]@2
+  int a4c; // [sp+30h] [bp+Ch]@9
+  signed int a4a; // [sp+30h] [bp+Ch]@10
+
+  v4 = a4;
+  v15 = a2;
+  v14 = a1;
+  if ( BYTE3(a4->uAttributes) & 0x20
+    || (v5 = (unsigned __int64)(a2->x * (signed __int64)a4->pFacePlane_old.vNormal.x) >> 16,
+        a4b = (unsigned __int64)(a2->y * (signed __int64)a4->pFacePlane_old.vNormal.y) >> 16,
+        v6 = (unsigned __int64)(a2->z * (signed __int64)v4->pFacePlane_old.vNormal.z) >> 16,
+        v7 = v5 + v6 + a4b,
+        (v16 = v5 + v6 + a4b) == 0)
+    || v7 > 0 && !(v4->uAttributes & 1) )
+    return 0;
+  v8 = v4->pFacePlane_old.vNormal.z * a1->z;
+  v9 = -(v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x);
+  if ( v7 <= 0 )
+  {
+    if ( v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x < 0 )
+      return 0;
+  }
+  else
+  {
+    if ( v9 < 0 )
+      return 0;
+  }
+  a4c = abs(-(v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x)) >> 14;
+  if ( a4c > abs(v7)
+    || (LODWORD(v10) = v9 << 16, HIDWORD(v10) = v9 >> 16, a4a = v10 / v16, v17 = v10 / v16, v17 > *a3 << 16)
+    || (v11 = v14,
+        LOWORD(v12) = LOWORD(v14->x)
+                    + (((unsigned int)((unsigned __int64)(v17 * (signed __int64)v15->x) >> 16) + 32768) >> 16),
+        HIWORD(v12) = LOWORD(v11->y)
+                    + (((unsigned int)((unsigned __int64)(v17 * (signed __int64)v15->y) >> 16) + 32768) >> 16),
+        !sub_475665(
+           v4,
+           v12,
+           LOWORD(v11->z) + (((unsigned int)((unsigned __int64)(v17 * (signed __int64)v15->z) >> 16) + 32768) >> 16))) )
+    return 0;
+  *a3 = a4a >> 16;
+  return 1;
+}
+
+//----- (00475F30) --------------------------------------------------------
+bool __fastcall sub_475F30(int *a1, BLVFace *a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9)
+{
+  BLVFace *v9; // ebx@1
+  int v10; // ST20_4@2
+  int v11; // ST28_4@2
+  int v12; // ST24_4@2
+  char v13; // zf@2
+  int v14; // edi@2
+  int v15; // eax@5
+  signed int v16; // esi@5
+  int v17; // ST20_4@9
+  signed __int64 v18; // qtt@10
+  int v19; // ST14_4@11
+  int *v21; // [sp+14h] [bp-10h]@1
+  int v22; // [sp+1Ch] [bp-8h]@2
+  int v23; // [sp+1Ch] [bp-8h]@10
+  signed int v24; // [sp+20h] [bp-4h]@10
+
+  v9 = a2;
+  v21 = a1;
+  if ( BYTE3(a2->uAttributes) & 0x20
+    || (v10 = (unsigned __int64)(a6 * (signed __int64)a2->pFacePlane_old.vNormal.x) >> 16,
+        v11 = (unsigned __int64)(a7 * (signed __int64)a2->pFacePlane_old.vNormal.y) >> 16,
+        v12 = (unsigned __int64)(a8 * (signed __int64)a2->pFacePlane_old.vNormal.z) >> 16,
+        v13 = v10 + v12 + v11 == 0,
+        v14 = v10 + v12 + v11,
+        v22 = v10 + v12 + v11,
+        v13)
+    || v14 > 0 && !(a2->uAttributes & 1) )
+    return 0;
+  v15 = a4 * a2->pFacePlane_old.vNormal.y;
+  v16 = -(a2->pFacePlane_old.dist + v15 + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z);
+  if ( v14 <= 0 )
+  {
+    if ( a2->pFacePlane_old.dist + v15 + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z < 0 )
+      return 0;
+  }
+  else
+  {
+    if ( v16 < 0 )
+      return 0;
+  }
+  v17 = abs(-(a2->pFacePlane_old.dist + v15 + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z)) >> 14;
+  if ( v17 > abs(v14)
+    || (LODWORD(v18) = v16 << 16, HIDWORD(v18) = v16 >> 16, v24 = v18 / v22, v23 = v18 / v22, v23 > *v21 << 16)
+    || (LOWORD(v19) = a3 + (((unsigned int)((unsigned __int64)(v23 * (signed __int64)a6) >> 16) + 32768) >> 16),
+        HIWORD(v19) = a4 + (((unsigned int)((unsigned __int64)(v23 * (signed __int64)a7) >> 16) + 32768) >> 16),
+        !sub_4759C9(
+           v9,
+           a9,
+           v19,
+           a5 + (((unsigned int)((unsigned __int64)(v23 * (signed __int64)a8) >> 16) + 32768) >> 16))) )
+    return 0;
+  *v21 = v24 >> 16;
+  return 1;
+}
+
+
+
+
+
+//----- (004760D5) --------------------------------------------------------
+PartyAction ActionQueue::Next()
+{
+  if (!uNumActions)
+    return PARTY_INVALID;
+
+  auto result = pActions[0];
+  for (unsigned int i = 0; i < uNumActions - 1; ++i)
+    pActions[i] = pActions[i + 1];
+  --uNumActions;
+
+  return result;
+}
+
+//----- (00476387) --------------------------------------------------------
+bool __cdecl sub_476387()
+{
+  return (pNPCStats->pNewNPCData[57].uFlags & 0x80) != 0;
+}
+
+//----- (00476395) --------------------------------------------------------
+//0x26 Wizard eye at skill level 2
+bool __thiscall CheckHiredNPCSpeciality(unsigned int uProfession)
+{
+  bool result; // eax@2
+  signed int v2; // esi@3
+  char *v3; // eax@4
+
+  if ( bNoNPCHiring == 1 )
+    return 0;
+  v2 = 0;
+  if ( (signed int)pNPCStats->uNumNewNPCs <= 0 )
+  {
+LABEL_8:
+    result = 0;
+    if ( pParty->pHirelings[0].uProfession != uProfession )
+    {
+      LOBYTE(result) = pParty->pHirelings[1].uProfession == uProfession;
+      return result;
+    }
+  }
+  else
+  {
+    v3 = (char *)&pNPCStats->pNewNPCData[0].uFlags;
+    while ( *((int *)v3 + 4) != uProfession || !(*v3 & 0x80) )
+    {
+      ++v2;
+      v3 += 76;
+      if ( v2 >= (signed int)pNPCStats->uNumNewNPCs )
+        goto LABEL_8;
+    }
+    result = 0;
+  }
+  ++result;
+  return result;
+}
+// 6BE3C5: using guessed type char bNoNPCHiring;
+
+//----- (004763E0) --------------------------------------------------------
+void __cdecl InitializeAwards()
+{
+  char *v0; // ebx@1
+  char *v1; // eax@4
+  char v2; // dl@5
+  char *v3; // ecx@5
+  int v4; // esi@9
+  signed int v5; // [sp+Ch] [bp-Ch]@4
+  char *v6; // [sp+10h] [bp-8h]@4
+  Award *v7; // [sp+14h] [bp-4h]@3
+
+  v0 = 0;
+  if ( pAwardsTXT_Raw )
+    pAllocator->FreeChunk(pAwardsTXT_Raw);
+  pAwardsTXT_Raw = 0;
+  pAwardsTXT_Raw = (char *)pEvents_LOD->LoadRaw("awards.txt", 0);
+  strtok(pAwardsTXT_Raw, "\r");
+  v7 = pAwards;
+  for (uint i = 0; i < 104; ++i)
+  {
+    v1 = strtok(v0, "\r") + 1;
+    v6 = v0;
+    v5 = (signed int)v0;
+    do
+    {
+      v2 = *v1;
+      v3 = 0;
+      if ( *v1 != 9 )
+      {
+        v0 = 0;
+        do
+        {
+          if ( !v2 )
+            break;
+          ++v3;
+          v2 = v1[(int)v3];
+        }
+        while ( v2 != 9 );
+      }
+      v4 = (int)&v1[(int)v3];
+      if ( v1[(int)v3] == (char)v0 )
+        v5 = 1;
+      *(char *)v4 = (char)v0;
+      if ( v3 == v0 )
+      {
+        v5 = 1;
+      }
+      else
+      {
+        if ( v6 == (char *)1 )
+        {
+          v7->pText = RemoveQuotes(v1);
+        }
+        else
+        {
+          if ( v6 == (char *)2 )
+            v7->uSort = atoi(v1);
+        }
+      }
+      ++v6;
+      v1 = (char *)(v4 + 1);
+    }
+    while ( (signed int)(v6 - 1) <= 2 && (char *)v5 == v0 );
+    ++v7;
+  }
+  //while ( (signed int)v7 < (signed int)&dword_7241C8 );
+}
+// 7241C8: using guessed type int dword_7241C8;
+
+//----- (004764C2) --------------------------------------------------------
+void __cdecl InitializeScrolls()
+{
+  char *v0; // ebx@1
+  char *v1; // eax@4
+  int v2; // edi@4
+  char v3; // dl@5
+  char *v4; // ecx@5
+  int v5; // esi@9
+  const char **v6; // [sp+10h] [bp-8h]@3
+  signed int v7; // [sp+14h] [bp-4h]@4
+
+  v0 = 0;
+  if ( pScrollsTXT_Raw )
+    pAllocator->FreeChunk(pScrollsTXT_Raw);
+  pScrollsTXT_Raw = 0;
+  pScrollsTXT_Raw = (char *)pEvents_LOD->LoadRaw("scroll.txt", 0);
+  strtok(pScrollsTXT_Raw, "\r");
+  v6 = pScrolls;
+  for (uint i = 0; i < 82; ++i)
+  {
+    v1 = strtok(v0, "\r") + 1;
+    v2 = 0;
+    v7 = (signed int)v0;
+    do
+    {
+      v3 = *v1;
+      v4 = 0;
+      if ( *v1 != 9 )
+      {
+        v0 = 0;
+        do
+        {
+          if ( !v3 )
+            break;
+          ++v4;
+          v3 = v1[(int)v4];
+        }
+        while ( v3 != 9 );
+      }
+      v5 = (int)&v1[(int)v4];
+      if ( v1[(int)v4] == (char)v0 )
+        v7 = 1;
+      *(char *)v5 = (char)v0;
+      if ( v4 == v0 )
+      {
+        v7 = 1;
+      }
+      else
+      {
+        if ( v2 == 1 )
+          *v6 = RemoveQuotes(v1);
+      }
+      ++v2;
+      v1 = (char *)(v5 + 1);
+    }
+    while ( v2 - 1 <= 1 && (char *)v7 == v0 );
+    ++v6;
+  }
+  //while ( (signed int)v6 < (signed int)dword_723E80_award_related );
+}
+
+
+//----- (00476590) --------------------------------------------------------
+void __cdecl InitializeMerchants()
+{
+  char *v0; // ebx@1
+  //char **v1; // edi@3
+  char *v2; // ecx@4
+  char v3; // dl@5
+  char *v4; // eax@5
+  int v5; // esi@9
+  signed int v6; // [sp+Ch] [bp-8h]@4
+  char *v7; // [sp+10h] [bp-4h]@4
+
+  v0 = 0;
+  if ( pMerchantsTXT_Raw )
+    pAllocator->FreeChunk(pMerchantsTXT_Raw);
+  pMerchantsTXT_Raw = 0;
+  pMerchantsTXT_Raw = (char *)pEvents_LOD->LoadRaw("merchant.txt", 0);
+  strtok(pMerchantsTXT_Raw, "\r");
+  //v1 = (char **)pMerchantsRepairPhrases;
+  for (uint i = 0; i < 7; ++i)
+  {
+    v7 = v0;
+    v6 = (signed int)v0;
+    v2 = strtok(v0, "\r") + 1;
+    do
+    {
+      v3 = *v2;
+      v4 = 0;
+      if ( *v2 != 9 )
+      {
+        v0 = 0;
+        do
+        {
+          if ( !v3 )
+            break;
+          ++v4;
+          v3 = v2[(int)v4];
+        }
+        while ( v3 != 9 );
+      }
+      v5 = (int)&v2[(int)v4];
+      if ( v2[(int)v4] == (char)v0 )
+        v6 = 1;
+      *(char *)v5 = (char)v0;
+      if ( v4 == v0 )
+      {
+        v6 = 1;
+      }
+      else
+      {
+        if ( v7 == (char *)1 )
+        {
+          pMerchantsBuyPhrases[i] = RemoveQuotes(v2);
+        }
+        else
+        {
+          if ( v7 == (char *)2 )
+          {
+            pMerchantsSellPhrases[i] = RemoveQuotes(v2);
+          }
+          else
+          {
+            if ( v7 == (char *)3 )
+            {
+              pMerchantsRepairPhrases[i] = RemoveQuotes(v2);
+            }
+            else
+            {
+              if ( v7 - 3 == (char *)1 )
+                pMerchantsIdentifyPhrases[i] = RemoveQuotes(v2);
+            }
+          }
+        }
+      }
+      ++v7;
+      v2 = (char *)(v5 + 1);
+    }
+    while ( (signed int)(v7 - 1) <= 4 && (char *)v6 == v0 );
+    //++v1;
+  }
+  //while ( (signed int)v1 < (signed int)pMerchantsIdentifyPhrases );
+}
+
+//----- (00476682) --------------------------------------------------------
+void __cdecl InitializeTransitions()
+{
+  char *v0; // ebx@1
+  char *v1; // eax@4
+  int v2; // edi@4
+  char v3; // dl@5
+  char *v4; // ecx@5
+  int v5; // esi@9
+  char **v6; // [sp+10h] [bp-8h]@3
+  signed int v7; // [sp+14h] [bp-4h]@4
+
+  v0 = 0;
+  if ( pTransitionsTXT_Raw )
+    pAllocator->FreeChunk(pTransitionsTXT_Raw);
+  pTransitionsTXT_Raw = 0;
+  pTransitionsTXT_Raw = (char *)pEvents_LOD->LoadRaw("trans.txt", 0);
+  strtok(pTransitionsTXT_Raw, "\r");
+  v6 = pTransitionStrings;
+  for (uint i = 0; i < 464; ++i)
+  {
+    v1 = strtok(v0, "\r") + 1;
+    v2 = 0;
+    v7 = (signed int)v0;
+    do
+    {
+      v3 = *v1;
+      v4 = 0;
+      if ( *v1 != 9 )
+      {
+        v0 = 0;
+        do
+        {
+          if ( !v3 )
+            break;
+          ++v4;
+          v3 = v1[(int)v4];
+        }
+        while ( v3 != 9 );
+      }
+      v5 = (int)&v1[(int)v4];
+      if ( v1[(int)v4] == (char)v0 )
+        v7 = 1;
+      *(char *)v5 = (char)v0;
+      if ( v4 == v0 )
+      {
+        v7 = 1;
+      }
+      else
+      {
+        if ( v2 == 1 )
+          *v6 = (char *)RemoveQuotes(v1);
+      }
+      ++v2;
+      v1 = (char *)(v5 + 1);
+    }
+    while ( v2 - 1 <= 1 && (char *)v7 == v0 );
+    ++v6;
+  }
+  //while ( (signed int)v6 < (signed int)"awards.txt" );
+}
+
+//----- (00476750) --------------------------------------------------------
+void __cdecl InitializeAutonotes()
+{
+  char *v0; // ebp@3
+  int v1; // ebx@4
+  char *v2; // esi@4
+  char v3; // cl@5
+  int v4; // eax@5
+  int v5; // edi@9
+  signed int v6; // [sp+0h] [bp-4h]@4
+
+  if ( pAutonoteTXT_Raw )
+    pAllocator->FreeChunk(pAutonoteTXT_Raw);
+  pAutonoteTXT_Raw = 0;
+  pAutonoteTXT_Raw = (char *)pEvents_LOD->LoadRaw("autonote.txt", 0);
+  strtok(pAutonoteTXT_Raw, "\r");
+  v0 = (char *)&stru_723720[0].eType;
+  for (uint i = 0; i < 195; ++i)
+  {
+    v1 = 0;
+    v2 = strtok(0, "\r") + 1;
+    v6 = 0;
+    do
+    {
+      v3 = *v2;
+      v4 = 0;
+      while ( v3 != 9 && v3 )
+      {
+        ++v4;
+        v3 = v2[v4];
+      }
+      v5 = (int)&v2[v4];
+      if ( !v2[v4] )
+        v6 = 1;
+      *(char *)v5 = 0;
+      if ( v4 )
+      {
+        if ( v1 == 1 )
+        {
+          *((int *)v0 - 1) = (int)RemoveQuotes(v2);
+        }
+        else
+        {
+          if ( v1 == 2 )
+          {
+            if ( _strcmpi(v2, "potion") )
+            {
+              if ( _strcmpi(v2, "stat") )
+              {
+                if ( _strcmpi(v2, "seer") )
+                {
+                  if ( _strcmpi(v2, "obelisk") )
+                    *(int *)v0 = 5 - (_strcmpi(v2, "teacher") != 0);
+                  else
+                    *(int *)v0 = 2;
+                }
+                else
+                {
+                  *(int *)v0 = 3;
+                }
+              }
+              else
+              {
+                *(int *)v0 = 1;
+              }
+            }
+            else
+            {
+              *(int *)v0 = 0;
+            }
+          }
+        }
+      }
+      else
+      {
+        v6 = 1;
+      }
+      ++v1;
+      v2 = (char *)(v5 + 1);
+    }
+    while ( v1 - 1 <= 2 && !v6 );
+    v0 += 8;
+  }
+  //while ( (signed int)v0 < (signed int)&pScrolls[1] );
+}
+
+
+//----- (004768A9) --------------------------------------------------------
+void __cdecl InitializeQuests()
+{
+  char *v0; // ebx@1
+  char *v1; // eax@4
+  int v2; // edi@4
+  char v3; // dl@5
+  char *v4; // ecx@5
+  int v5; // esi@9
+  //const char **v6; // [sp+10h] [bp-8h]@3
+  signed int v7; // [sp+14h] [bp-4h]@4
+
+  v0 = 0;
+  if ( pQuestsTXT_Raw )
+    pAllocator->FreeChunk(pQuestsTXT_Raw);
+  pQuestsTXT_Raw = 0;
+  pQuestsTXT_Raw = (char *)pEvents_LOD->LoadRaw("quests.txt", 0);
+  strtok(pQuestsTXT_Raw, "\r");
+
+  //v6 = pQuestTable;
+  for (uint i = 0; i < 512; ++i)
+  //do
+  {
+    v1 = strtok(v0, "\r") + 1;
+    v2 = 0;
+    v7 = (signed int)v0;
+    do
+    {
+      v3 = *v1;
+      v4 = 0;
+      if ( *v1 != '\t' )
+      {
+        v0 = 0;
+        do
+        {
+          if ( !v3 )
+            break;
+          ++v4;
+          v3 = v1[(int)v4];
+        }
+        while ( v3 != '\t' );
+      }
+      v5 = (int)&v1[(int)v4];
+      if ( v1[(int)v4] == (char)v0 )
+        v7 = 1;
+      *(char *)v5 = (char)v0;
+      if ( v4 == v0 )
+      {
+        v7 = 1;
+      }
+      else
+      {
+        if ( v2 == 1 )
+          pQuestTable[i] = RemoveQuotes(v1);
+      }
+      ++v2;
+      v1 = (char *)(v5 + 1);
+    }
+    while ( v2 - 1 <= 1 && (char *)v7 == v0 );
+    //++v6;
+  }
+  //while ( (signed int)v6 < (signed int)&unk_723714 );
+}
+
+
+
+//----- (00476977) --------------------------------------------------------
+void NPCStats::Initialize2()
+{
+  char *v4; // eax@4
+  char v5; // dl@5
+  char *v6; // ecx@5
+  int v7; // edi@9
+  char *v9; // eax@21
+  char v10; // dl@22
+  char *v11; // ecx@22
+  int v12; // edi@26
+  char *v14; // eax@39
+  char v15; // dl@40
+  int v16; // ecx@40
+  int v17; // edi@44
+  char v18; // zf@47
+  NPCStats_stru0 *v19; // eax@57
+  signed int v20; // edx@57
+  signed int v21; // ecx@58
+  char *v22; // [sp+10h] [bp-10h]@4
+  char *v23; // [sp+10h] [bp-10h]@21
+  char *v25; // [sp+14h] [bp-Ch]@4
+  char *v26; // [sp+14h] [bp-Ch]@21
+  signed int v27; // [sp+14h] [bp-Ch]@39
+  //signed int v28; // [sp+18h] [bp-8h]@3
+  //signed int v29; // [sp+18h] [bp-8h]@20
+  signed int v30; // [sp+18h] [bp-8h]@37
+  char *v31; // [sp+1Ch] [bp-4h]@37
+
+  //v1 = this;
+  //v2 = 0;
+  if (pNPCTextTXT_Raw)
+    pAllocator->FreeChunk(pNPCTextTXT_Raw);
+
+  //v3 = (char *)pEvents_LOD->LoadRaw("npctext.txt", 0);
+  pNPCTextTXT_Raw = (char *)pEvents_LOD->LoadRaw("npctext.txt", 0);
+  strtok(pNPCTextTXT_Raw, "\r");
+
+  for (uint i = 0; i < 789; ++i)
+  {
+    v4 = strtok(nullptr, "\r") + 1;
+    v22 = nullptr;
+    v25 = nullptr;
+    do
+    {
+      v5 = *v4;
+      v6 = 0;
+      if ( *v4 != 9 )
+      {
+        do
+        {
+          if ( !v5 )
+            break;
+          ++v6;
+          v5 = v4[(int)v6];
+        }
+        while ( v5 != 9 );
+        //v2 = 0;
+      }
+      v7 = (int)&v4[(int)v6];
+      if ( !v4[(int)v6] )
+        v25 = (char *)1;
+      *(char *)v7 = 0;
+      if ( v6 == nullptr )
+      {
+        v25 = (char *)1;
+      }
+      else
+      {
+        if ( v22 == (char *)1 )
+          pNPCTopics[i].pText = RemoveQuotes(v4);
+      }
+      ++v22;
+      v4 = (char *)(v7 + 1);
+    }
+    while ( (signed int)(v22 - 1) <= 1 && v25 == nullptr );
+  }
+
+  if (pNPCTopicTXT_Raw)
+    pAllocator->FreeChunk(pNPCTopicTXT_Raw);
+
+  //v8 = (char *)pEvents_LOD->LoadRaw("npctopic.txt", (int)v2);
+  pNPCTopicTXT_Raw = (char *)pEvents_LOD->LoadRaw("npctopic.txt", 0);
+  strtok(pNPCTopicTXT_Raw, "\r");
+
+  for (uint i = 0; i < 579; ++i)
+  {
+    v9 = strtok(nullptr, "\r") + 1;
+    v23 = nullptr;
+    v26 = nullptr;
+    do
+    {
+      v10 = *v9;
+      v11 = 0;
+      if ( *v9 != 9 )
+      {
+        do
+        {
+          if ( !v10 )
+            break;
+          ++v11;
+          v10 = v9[(int)v11];
+        }
+        while ( v10 != 9 );
+        //v2 = 0;
+      }
+      v12 = (int)&v9[(int)v11];
+      if ( !v9[(int)v11] )
+        v26 = (char *)1;
+      *(char *)v12 = 0;
+      if ( v11 == nullptr )
+      {
+        v26 = (char *)1;
+      }
+      else
+      {
+        if ( v23 == (char *)1 )
+          pNPCTopics[i].pTopic = RemoveQuotes(v9);
+      }
+      ++v23;
+      v9 = (char *)(v12 + 1);
+    }
+    while ( (signed int)(v23 - 1) <= 1 && v26 == nullptr );
+  }
+
+  if (pNPCDistTXT_Raw)
+    pAllocator->FreeChunk(pNPCDistTXT_Raw);
+
+  //v13 = (char *)pEvents_LOD->LoadRaw("npcdist.txt", (int)v2);
+  pNPCDistTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcdist.txt", 0);
+  strtok(pNPCDistTXT_Raw, "\r");
+  strtok(nullptr, "\r");
+  v30 = 1;
+  v31 = &array_16544[0].field_4[1];
+
+  char *v2 = 0;
+  while ( 2 )
+  {
+    v14 = strtok(nullptr, "\r") + 1;
+    v27 = 0;
+    char *v24 = nullptr;
+    do
+    {
+      v15 = *v14;
+      v16 = 0;
+      if ( *v14 != 9 )
+      {
+        do
+        {
+          if ( !v15 )
+            break;
+          ++v16;
+          v15 = v14[v16];
+        }
+        while ( v15 != 9 );
+        v2 = v24;
+      }
+      v17 = (int)&v14[v16];
+      if ( !v14[v16] )
+        v27 = 1;
+      *(char *)v17 = 0;
+      if ( !v16 )
+      {
+        v27 = 1;
+        goto LABEL_54;
+      }
+      v18 = v2 == 0;
+      if ( (signed int)v2 > 0 )
+      {
+        if ( (signed int)v2 < 77 )
+        {
+          array_16544[(int)v2].field_4[v30] = atoi(v14);
+          goto LABEL_54;
+        }
+        v18 = v2 == 0;
+      }
+      if ( v18 )
+        *v31 = 10;
+LABEL_54:
+      ++v2;
+      v14 = (char *)(v17 + 1);
+      v24 = v2;
+    }
+    while ( (signed int)(v2 - 1) <= 77 && !v27 );
+    ++v30;
+    ++v31;
+    if ( v30 < 59 )
+    {
+      v2 = 0;
+      continue;
+    }
+    break;
+  }
+  v19 = array_16544;
+  v20 = 77;
+  do
+  {
+    v19->field_0 = 0;
+    v21 = 1;
+    do
+      v19->field_0 += v19->field_4[v21++];
+    while ( v21 < 59 );
+    ++v19;
+    --v20;
+  }
+  while ( v20 );
+
+  if (pNPCDistTXT_Raw)
+  {
+    pAllocator->FreeChunk(pNPCDistTXT_Raw);
+    pNPCDistTXT_Raw = nullptr;
+  }
+}
+
+//----- (00476C60) --------------------------------------------------------
+void NPCStats::_476C60()
+{
+  for (uint i = 1; i < uNumNewNPCs; ++i)
+    pNewNPCData[i].pName = pNPCNames2[i - 1];
+
+  if (pParty->pHirelings[0].pName)
+    pParty->pHirelings[0].pName = pParty->pHireling1Name;
+  if (pParty->pHirelings[1].pName)
+    pParty->pHirelings[1].pName = pParty->pHireling2Name;
+}
+
+//----- (00476CB5) --------------------------------------------------------
+void NPCStats::Initialize1()
+{
+  NPCStats *pNPCStats; // esi@1
+  char *pRaw; // eax@1
+  char *pHouse; // edi@1
+  char *v4; // eax@2
+  char v5; // dl@3
+  int v6; // ecx@3
+  char *v7; // eax@11
+  char *v8; // eax@26
+  char *v9; // ecx@27
+  char v10; // dl@28
+  int v11; // eax@28
+  int v12; // edi@32
+  char *v13; // eax@42
+  char *v14; // eax@43
+  char v15; // dl@44
+  int v16; // ecx@44
+  int v17; // edi@48
+  char *v18; // eax@56
+  char *v19; // eax@57
+  char v20; // cl@58
+  int v21; // edi@58
+  int v22; // esi@62
+  int v23; // [sp+Ch] [bp-14h]@7
+  signed int v24; // [sp+10h] [bp-10h]@1
+  signed int v25; // [sp+10h] [bp-10h]@26
+  signed int v26; // [sp+10h] [bp-10h]@42
+  signed int v27; // [sp+10h] [bp-10h]@56
+  char *Str; // [sp+14h] [bp-Ch]@1
+  NPCGreeting *pGreetings; // [sp+14h] [bp-Ch]@26
+  unsigned __int16 *pGroups; // [sp+14h] [bp-Ch]@42
+  char **pCatchPhrase; // [sp+14h] [bp-Ch]@56
+  signed int v32; // [sp+18h] [bp-8h]@2
+  signed int v33; // [sp+18h] [bp-8h]@27
+  signed int v34; // [sp+18h] [bp-8h]@43
+  signed int v35; // [sp+18h] [bp-8h]@57
+  signed int v36; // [sp+1Ch] [bp-4h]@2
+  signed int v37; // [sp+1Ch] [bp-4h]@27
+  signed int v38; // [sp+1Ch] [bp-4h]@43
+  signed int v39; // [sp+1Ch] [bp-4h]@57
+
+  pNPCStats = this;
+  pRaw = (char *)pEvents_LOD->LoadRaw("npcdata.txt", 0);
+  pNPCStats->pNPCDataTXT_Raw = pRaw;
+  strtok(pRaw, "\r");
+  strtok(0, "\r");
+  pHouse = (char *)&pNPCStats->pNPCData[1].house;
+  Str = (char *)pNPCStats->pNPCNames2;
+  v24 = 500;
+  do
+  {
+    v32 = 0;
+    v4 = strtok(0, "\r") + 1;
+    v36 = -1;
+    do
+    {
+      v5 = *v4;
+      v6 = 0;
+      while ( v5 != 9 && v5 )
+      {
+        ++v6;
+        v5 = v4[v6];
+      }
+      v23 = (int)&v4[v6];
+      if ( !v4[v6] )
+        v32 = 1;
+      v4[v6] = 0;
+      if ( v6 )
+      {
+        switch ( v36 )
+        {
+          case 0:
+            v7 = RemoveQuotes(v4);
+            *((int *)pHouse - 5) = (int)v7;
+            *(int *)Str = (int)v7;
+            break;
+          case 1:
+            *((int *)pHouse - 4) = atoi(v4);
+            break;
+          case 5:
+            *(int *)pHouse = atoi(v4);
+            break;
+          case 6:
+            *((int *)pHouse + 1) = atoi(v4);
+            break;
+          case 7:
+            *((int *)pHouse + 2) = atoi(v4);
+            break;
+          case 8:
+            *((int *)pHouse + 3) = *v4 == 121;
+            break;
+          case 9:
+            *((int *)pHouse + 5) = atoi(v4);
+            break;
+          case 10:
+            *((int *)pHouse + 6) = atoi(v4);
+            break;
+          case 11:
+            *((int *)pHouse + 7) = atoi(v4);
+            break;
+          case 12:
+            *((int *)pHouse + 8) = atoi(v4);
+            break;
+          case 13:
+            *((int *)pHouse + 9) = atoi(v4);
+            break;
+          case 14:
+            *((int *)pHouse + 10) = atoi(v4);
+            break;
+          default:
+            break;
+        }
+      }
+      ++v36;
+      v4 = (char *)(v23 + 1);
+    }
+    while ( v36 + 1 <= 15 && !v32 );
+    Str += 4;
+    pHouse += 76;
+    --v24;
+  }
+  while ( v24 );
+  pNPCStats->uNumNewNPCs = 501;
+  v8 = (char *)pEvents_LOD->LoadRaw("npcgreet.txt", 0);
+  pNPCStats->pNPCGreetTXT_Raw = v8;
+  strtok(v8, "\r");
+  pGreetings = pNPCStats->pNPCGreetings;
+  v25 = 205;
+  do
+  {
+    v37 = 0;
+    v33 = 0;
+    v9 = strtok(0, "\r") + 1;
+    do
+    {
+      v10 = *v9;
+      v11 = 0;
+      while ( v10 != 9 && v10 )
+      {
+        ++v11;
+        v10 = v9[v11];
+      }
+      v12 = (int)&v9[v11];
+      if ( !v9[v11] )
+        v33 = 1;
+      *(char *)v12 = 0;
+      if ( v11 )
+      {
+        if ( v37 == 1 )
+        {
+          pGreetings->pGreeting1 = (char *)RemoveQuotes(v9);
+        }
+        else
+        {
+          if ( v37 == 2 )
+            pGreetings->pGreeting2 = (char *)RemoveQuotes(v9);
+        }
+      }
+      ++v37;
+      v9 = (char *)(v12 + 1);
+    }
+    while ( v37 <= 2 && !v33 );
+    ++pGreetings;
+    --v25;
+  }
+  while ( v25 );
+  v13 = (char *)pEvents_LOD->LoadRaw("npcgroup.txt", 0);
+  pNPCStats->pNCPGroupTXT_Raw = v13;
+  strtok(v13, "\r");
+  pGroups = pNPCStats->pGroups;
+  v26 = 51;
+  do
+  {
+    v14 = strtok(0, "\r") + 1;
+    v38 = 0;
+    v34 = 0;
+    do
+    {
+      v15 = *v14;
+      v16 = 0;
+      while ( v15 != 9 && v15 )
+      {
+        ++v16;
+        v15 = v14[v16];
+      }
+      v17 = (int)&v14[v16];
+      if ( !v14[v16] )
+        v34 = 1;
+      *(char *)v17 = 0;
+      if ( v16 && v38 == 1 )
+        *pGroups = atoi(v14);
+      ++v38;
+      v14 = (char *)(v17 + 1);
+    }
+    while ( v38 <= 1 && !v34 );
+    ++pGroups;
+    --v26;
+  }
+  while ( v26 );
+  v18 = (char *)pEvents_LOD->LoadRaw("npcnews.txt", 0);
+  pNPCStats->pNPCNewsTXT_Raw = v18;
+  strtok(v18, "\r");
+  pCatchPhrase = pNPCStats->pCatchPhrases;
+  v27 = 51;
+  do
+  {
+    v19 = strtok(0, "\r") + 1;
+    v39 = 0;
+    v35 = 0;
+    do
+    {
+      v20 = *v19;
+      v21 = 0;
+      while ( v20 != 9 && v20 )
+      {
+        ++v21;
+        v20 = v19[v21];
+      }
+      v22 = (int)&v19[v21];
+      if ( !v19[v21] )
+        v35 = 1;
+      *(char *)v22 = 0;
+      if ( v21 && v39 == 1 )
+        *pCatchPhrase = (char *)RemoveQuotes(v19);
+      ++v39;
+      v19 = (char *)(v22 + 1);
+    }
+    while ( v39 <= 1 && !v35 );
+    ++pCatchPhrase;
+    --v27;
+  }
+  while ( v27 );
+}
+
+//----- (0047702F) --------------------------------------------------------
+void NPCStats::Initialize()
+{
+  //NPCStats *v1; // edi@1
+  char *v2; // ebx@1
+  //char *v3; // eax@1
+  char *v4; // ebx@3
+  char v5; // al@4
+  int v6; // ecx@4
+  //char *v7; // eax@18
+  char *v8; // ebx@18
+  char *v9; // ecx@19
+  char v10; // dl@20
+  int v11; // eax@20
+  char v12; // zf@41
+  signed int v13; // [sp+Ch] [bp-14h]@18
+  int v14; // [sp+10h] [bp-10h]@4
+  int v15; // [sp+10h] [bp-10h]@24
+  char *v16; // [sp+14h] [bp-Ch]@1
+  signed int v17; // [sp+14h] [bp-Ch]@19
+  unsigned int v18; // [sp+18h] [bp-8h]@1
+  char *v19; // [sp+18h] [bp-8h]@18
+  signed int v20; // [sp+1Ch] [bp-4h]@3
+  signed int v21; // [sp+1Ch] [bp-4h]@19
+  //v1 = this;
+
+  Initialize1();
+  Initialize2();
+
+  InitializeQuests();
+  InitializeAutonotes();
+  InitializeAwards();
+  InitializeTransitions();
+  InitializeMerchants();
+  InitializeScrolls();
+  v2 = 0;
+  field_17FC0 = 0;
+  pNPCNamesTXT_Raw = 0;
+  //v3 = (char *)pEvents_LOD->LoadRaw("npcnames.txt", 0);
+  pNPCNamesTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcnames.txt", 0);
+  strtok(pNPCNamesTXT_Raw, "\r");
+  v18 = 0;
+  v16 = (char *)pNPCNames;
+  while ( 1 )
+  {
+    v4 = strtok(v2, "\r") + 1;
+    v20 = 0;
+    do
+    {
+      v5 = *v4;
+      v6 = 0;
+      v14 = 0;
+      if ( *v4 == 9 )
+        goto LABEL_45;
+      do
+      {
+        if ( !v5 )
+          break;
+        if ( v5 == 10 )
+          break;
+        ++v6;
+        v14 = v6;
+        v5 = v4[v6];
+      }
+      while ( v5 != 9 );
+      if ( v6 )
+      {
+        v4[v6] = 0;
+        if ( v20 )
+        {
+          if ( v20 == 1 )
+            *((int *)v16 + 1) = (int)RemoveQuotes(v4);
+        }
+        else
+        {
+          *(int *)v16 = (int)RemoveQuotes(v4);
+        }
+      }
+      else
+      {
+LABEL_45:
+        if ( v20 == 1 && !uNumNPCNames[1] )
+          uNumNPCNames[1] = v18;
+      }
+      ++v20;
+      v4 += v14 + 1;
+    }
+    while ( v20 <= 1 );
+    ++v18;
+    v16 += 8;
+    if ( (signed int)v18 >= 540 )
+      break;
+    v2 = 0;
+  }
+  pNPCProfTXT_Raw = 0;
+  uNumNPCNames[0] = v18;
+  //v7 = (char *)pEvents_LOD->LoadRaw("npcprof.txt", 0);
+  pNPCProfTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcprof.txt", 0);
+  strtok(pNPCProfTXT_Raw, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  strtok(0, "\r");
+  v8 = (char *)&pProfessions[0].pJoinText;
+  v19 = (char *)&pProfessions[0].pJoinText;
+  v13 = 58;
+  do
+  {
+    v21 = 0;
+    v9 = strtok(0, "\r") + 1;
+    v17 = 0;
+    do
+    {
+      v10 = *v9;
+      v11 = 0;
+      if ( *v9 != 9 )
+      {
+        do
+        {
+          if ( !v10 )
+            break;
+          ++v11;
+          v10 = v9[v11];
+        }
+        while ( v10 != 9 );
+        v8 = v19;
+      }
+      v15 = (int)&v9[v11];
+      if ( !v9[v11] )
+        v17 = 1;
+      *(char *)v15 = 0;
+      if ( v11 )
+      {
+        switch ( v21 )
+        {
+          case 2:
+            *((int *)v8 - 3) = atoi(v9);
+            break;
+          case 3:
+            *((int *)v8 - 1) = (int)RemoveQuotes(v9);
+            break;
+          case 4:
+            *((int *)v8 - 2) = (int)RemoveQuotes(v9);
+            break;
+          case 5:
+            *(int *)v8 = (int)RemoveQuotes(v9);
+            break;
+          case 6:
+            *((int *)v8 + 1) = (int)RemoveQuotes(v9);
+            break;
+        }
+      }
+      else
+      {
+        if ( !v21 )
+          v17 = 1;
+      }
+      ++v21;
+      v9 = (char *)(v15 + 1);
+    }
+    while ( v21 <= 6 && !v17 );
+    v8 += 20;
+    v12 = v13-- == 1;
+    v19 = v8;
+  }
+  while ( !v12 );
+  uNumNPCProfessions = 59;
+}
+
+//----- (00477266) --------------------------------------------------------
+void NPCStats::Release()
+{
+  NPCStats *v1; // esi@1
+  void *v2; // ST00_4@1
+  int v3; // ebx@1
+
+  v1 = this;
+  pAllocator->FreeChunk(this->pNPCTopicTXT_Raw);
+  v2 = v1->pNPCTextTXT_Raw;
+  v1->pNPCNewsTXT_Raw = 0;
+  pAllocator->FreeChunk(v2);
+  v1->pNPCNewsTXT_Raw = 0;
+  pAllocator->FreeChunk(0);
+  v1->pNPCNewsTXT_Raw = 0;
+  pAllocator->FreeChunk(v1->pNPCProfTXT_Raw);
+  v1->pNPCProfTXT_Raw = 0;
+  pAllocator->FreeChunk(v1->pNPCNamesTXT_Raw);
+  v1->pNPCNamesTXT_Raw = 0;
+  pAllocator->FreeChunk(v1->pNPCDataTXT_Raw);
+  v1->pNPCDataTXT_Raw = 0;
+  pAllocator->FreeChunk(v1->pNPCDistTXT_Raw);
+  v1->pNPCDistTXT_Raw = 0;
+  v3 = (int)&v1->pNPCGreetTXT_Raw;
+  pAllocator->FreeChunk(v1->pNPCGreetTXT_Raw);
+  v1 = (NPCStats *)((char *)v1 + 98296);
+  *(int *)v3 = 0;
+  pAllocator->FreeChunk(v1->pNPCData[0].pName);
+  v1->pNPCData[0].pName = 0;
+}
+
+//----- (0047730C) --------------------------------------------------------
+int __fastcall const_1(int a1, int)
+{
+  return 1;
+}
+// 47730C: using guessed type int __stdcall const_1(int);
+
+//----- (0047732C) --------------------------------------------------------
+bool NPCStats::InitializeAdditionalNPCs(NPCData *a2, int a3, int a4, int a5)
+{
+  //NPCStats *v5; // ebx@1
+  signed __int64 v6; // qax@1
+  int v7; // esi@1
+  int v8; // edx@1
+  NPCData *v9; // edi@1
+  int v10; // eax@1
+  //int v11; // eax@23
+  int v12; // ecx@23
+  int v13; // edx@28
+  int v14; // esi@37
+  int v15; // edx@37
+  int v16; // ecx@37
+  int v17; // eax@37
+  int v18; // edx@37
+  signed int result; // eax@39
+  int v20; // [sp+Ch] [bp-Ch]@1
+  signed int v21; // [sp+10h] [bp-8h]@1
+  signed int v22; // [sp+14h] [bp-4h]@1
+  int v23; // [sp+24h] [bp+Ch]@1
+
+
+  v23 = a3 - 1;
+  //v5 = this;
+  v6 = (signed __int64)((double)v23 * -0.33333334);
+  v7 = (unsigned __int8)byte_4E8394[-(_DWORD)v6 + 28];
+  v20 = (unsigned __int8)byte_4E8394[-(_DWORD)v6 + 116];
+  v8 = rand() % uNumNPCNames[v7];
+  v9 = a2;
+  a2->uSex = v7;
+  a2->pName = pNPCNames[v8][v7];
+  v10 = 0;
+  v22 = 0;
+  v21 = 0;
+
+  while ( 1 )
+  {
+    if ( v20 == v10 )
+    {
+      if ( v7 == v10 )
+      {
+        v23 = 2;
+        a2 = (NPCData *)100;
+      }
+      else
+      {
+        if ( v7 - v10 == 1 )
+        {
+          v23 = 201;
+          a2 = (NPCData *)250;
+        }
+      }
+    }
+    else
+    {
+      switch ( v20 - v10 )
+      {
+        case 1:
+          if ( v7 == v10 )
+          {
+            v23 = 400;
+            a2 = (NPCData *)430;
+          }
+          else
+          {
+            if ( v7 - v10 == 1 )
+            {
+              v23 = 460;
+              a2 = (NPCData *)490;
+            }
+          }
+          break;
+        case 2:
+          if ( v7 == v10 )
+          {
+            v23 = 500;
+            a2 = (NPCData *)520;
+          }
+          else
+          {
+            if ( v7 - v10 == 1 )
+            {
+              v23 = 530;
+              a2 = (NPCData *)550;
+            }
+          }
+          break;
+        case 3:
+          if ( v7 == v10 )
+          {
+            v23 = 300;
+            a2 = (NPCData *)330;
+          }
+          else
+          {
+            if ( v7 - v10 == 1 )
+            {
+              v23 = 360;
+              a2 = (NPCData *)387;
+            }
+          }
+          break;
+      }
+    }
+    v12 = v23 + rand() % ((int)a2 - v23 + 1);
+    if ( const_1(v12, v7) == 1 )
+      v21 = 1;
+    ++v22;
+    if ( v22 >= 4 )
+    {
+      v12 = v23;
+      v21 = 1;
+    }
+    if ( v21 )
+      break;
+    v10 = 0;
+  }
+
+  v9->uPortraitID = v12;
+  v9->uFlags = 0;
+  v9->fame = 0;
+  v13 = rand() % 100 + 1;
+
+  if ( v13 >= 60 )
+  {
+    if ( v13 >= 90 )
+    {
+      if ( v13 >= 95 )
+      {
+        if ( v13 >= 98 )
+          v9->rep = -600;
+        else
+          v9->rep = 400;
+      }
+      else
+      {
+        v9->rep = -300;
+      }
+    }
+    else
+    {
+      v9->rep = 200;
+    }
+  }
+  else
+  {
+    v9->rep = 0;
+  }
+
+  //v14 = (int)((char *)v5 + 64 * a5);
+  //v15 = rand() % *(_DWORD *)(v14 + 91460);
+  v15 = rand() % array_16544[a5].field_0;
+  v16 = 0;
+  v17 = 0;
+  v18 = v15 + 1;
+  
+  if ( v18 > 0 )
+  {
+    do
+      //v14 += *(char *)(v14 + v17++ + 0x16548);
+      v16 += array_16544[a5].field_4[v17++];
+    while ( v16 < v18 );
+  }
+  v9->uProfession = v17 - 1;
+  v9->house = a4;
+  v9->field_24 = 1;
+  v9->joins = 1;
+  return true;
+}
+// 47730C: using guessed type int __stdcall const_1(int);
+
+//----- (0047752B) --------------------------------------------------------
+int __cdecl GetPartyReputation()
+{
+  DDM_DLV_Header *v0; // ebx@1
+  signed int v1; // esi@3
+
+  v0 = &pOutdoor->ddm;
+  if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+    v0 = &pIndoor->dlv;
+  v1 = 0;
+  if ( CheckHiredNPCSpeciality(0x2Du) )
+    v1 = 5;
+  if ( CheckHiredNPCSpeciality(0x33u) )
+    v1 += 5;
+  if ( CheckHiredNPCSpeciality(0x30u) )
+    v1 += 5;
+  if ( CheckHiredNPCSpeciality(0x32u) )
+    v1 += 5;
+  if ( CheckHiredNPCSpeciality(0x34u) )
+    v1 += 5;
+  return v1 + v0->uReputation;
+}
+
+
+
+
+
+//----- (004775ED) --------------------------------------------------------
+int stru6_stru1_indoor_sw_billboard::_4775ED(float a2)
+{
+  char *v2; // edi@1
+  int v3; // eax@1
+  char *v4; // edx@2
+  char *v5; // esi@3
+  double v6; // st7@6
+  signed __int64 v7; // ST84_8@6
+  double v8; // ST0C_8@6
+  int v9; // esi@6
+  double v10; // ST44_8@6
+  int v11; // ecx@6
+  double v12; // ST34_8@6
+  int v13; // ecx@6
+  double v14; // ST14_8@6
+  double v15; // st7@8
+  unsigned int v16; // ecx@8
+  signed __int64 v17; // ST64_8@8
+  double v18; // ST24_8@8
+  int v19; // edi@8
+  double v20; // ST3C_8@8
+  int v21; // ecx@8
+  double v22; // ST2C_8@8
+  int v23; // ST9C_4@8
+  double v24; // ST1C_8@8
+  int *v25; // edi@8
+  int v26; // esi@8
+  int *v27; // edi@10
+  int v28; // esi@10
+  int result; // eax@12
+  __int64 v30; // [sp+A8h] [bp-30h]@8
+  float v31; // [sp+B0h] [bp-28h]@6
+  float v32; // [sp+B4h] [bp-24h]@6
+  int v33; // [sp+B8h] [bp-20h]@6
+  int v34; // [sp+BCh] [bp-1Ch]@2
+  stru6_stru1_indoor_sw_billboard *v35; // [sp+C0h] [bp-18h]@1
+  float v36; // [sp+C4h] [bp-14h]@6
+  int v37; // [sp+C8h] [bp-10h]@6
+  int v38; // [sp+CCh] [bp-Ch]@1
+  float v39; // [sp+D0h] [bp-8h]@6
+  int *v40; // [sp+D4h] [bp-4h]@2
+
+  v2 = (char *)&this->field_14[4 * this->field_10 + 20];
+  v38 = 0;
+  *(int *)v2 = this->field_14[20];
+  v2 += 4;
+  *(int *)v2 = this->field_14[21];
+  v2 += 4;
+  *(int *)v2 = this->field_14[22];
+  *((int *)v2 + 1) = this->field_14[23];
+  v3 = this->field_10;
+  v35 = this;
+  if ( v3 > 0 )
+  {
+    v40 = &this->field_14[40];
+    v4 = (char *)&this->field_14[23] + 3;
+    v34 = v3;
+    while ( 1 )
+    {
+      v5 = v4 - 15;
+      if ( *(float *)(v4 - 15) <= (double)a2 && *(float *)(v4 + 1) <= (double)a2 )
+        goto LABEL_11;
+      if ( *(float *)v5 <= (double)a2 )
+        break;
+      if ( *(float *)(v4 + 1) <= (double)a2 )
+      {
+        v15 = (a2 - *(float *)v5) / (*(float *)(v4 + 1) - *(float *)v5);
+        v16 = (unsigned __int8)*v4;
+        HIDWORD(v30) = LODWORD(a2);
+        v17 = (unsigned __int8)v4[16] - v16;
+        v36 = v15;
+        v31 = (*(float *)(v4 + 5) - *(float *)(v4 - 11)) * v15 + *(float *)(v4 - 11);
+        v32 = (*(float *)(v4 + 9) - *(float *)(v4 - 7)) * v15 + *(float *)(v4 - 7);
+        v39 = (double)v17 * v15;
+        v18 = v39 + 6.7553994e15;
+        v19 = (unsigned __int8)*v4;
+        v39 = (double)((unsigned __int8)v4[15] - (unsigned int)(unsigned __int8)*(v4 - 1)) * v36;
+        v20 = v39 + 6.7553994e15;
+        v21 = (unsigned __int8)*(v4 - 2);
+        v37 = LODWORD(v20) + (unsigned __int8)*(v4 - 1);
+        v39 = (double)((unsigned int)(unsigned __int8)v4[14] - v21) * v36;
+        v22 = v39 + 6.7553994e15;
+        v23 = LODWORD(v22) + (unsigned __int8)*(v4 - 2);
+        v39 = (double)((*(int *)(v4 + 13) & 0xFF) - (*(int *)(v4 - 3) & 0xFFu)) * v36;
+        v24 = v39 + 6.7553994e15;
+        v33 = (LODWORD(v24) + (*(int *)(v4 - 3) & 0xFF)) | ((v23 | ((v37 | ((LODWORD(v18) + v19) << 8)) << 8)) << 8);
+        v25 = v40;
+        *v40 = *(int *)v5;
+        v26 = (int)(v5 + 4);
+        ++v25;
+        *v25 = *(int *)v26;
+        v26 += 4;
+        ++v25;
+        ++v38;
+        v40 += 4;
+        *v25 = *(int *)v26;
+        v25[1] = *(int *)(v26 + 4);
+        goto LABEL_9;
+      }
+LABEL_10:
+      v27 = v40;
+      ++v38;
+      *v40 = *(int *)v5;
+      v28 = (int)(v5 + 4);
+      ++v27;
+      *v27 = *(int *)v28;
+      v28 += 4;
+      ++v27;
+      v40 += 4;
+      *v27 = *(int *)v28;
+      v27[1] = *(int *)(v28 + 4);
+LABEL_11:
+      v4 += 16;
+      --v34;
+      if ( !v34 )
+        goto LABEL_12;
+    }
+    v6 = (a2 - *(float *)v5) / (*(float *)(v4 + 1) - *(float *)v5);
+    v7 = (unsigned __int8)v4[16] - (unsigned int)(unsigned __int8)*v4;
+    v36 = v6;
+    v31 = (*(float *)(v4 + 5) - *(float *)(v4 - 11)) * v6 + *(float *)(v4 - 11);
+    v32 = (*(float *)(v4 + 9) - *(float *)(v4 - 7)) * v6 + *(float *)(v4 - 7);
+    *(float *)&v37 = (double)v7 * v6;
+    v8 = *(float *)&v37 + 6.7553994e15;
+    v9 = (unsigned __int8)*v4;
+    *(float *)&v37 = (double)((unsigned __int8)v4[15] - (unsigned int)(unsigned __int8)*(v4 - 1)) * v36;
+    v10 = *(float *)&v37 + 6.7553994e15;
+    v11 = (unsigned __int8)*(v4 - 2);
+    v37 = LODWORD(v10) + (unsigned __int8)*(v4 - 1);
+    v39 = (double)((unsigned int)(unsigned __int8)v4[14] - v11) * v36;
+    v12 = v39 + 6.7553994e15;
+    v13 = LODWORD(v12) + (unsigned __int8)*(v4 - 2);
+    v39 = (double)((*(int *)(v4 + 13) & 0xFF) - (*(int *)(v4 - 3) & 0xFFu)) * v36;
+    v14 = v39 + 6.7553994e15;
+    v33 = (LODWORD(v14) + (*(int *)(v4 - 3) & 0xFF)) | ((v13 | ((v37 | ((LODWORD(v8) + v9) << 8)) << 8)) << 8);
+LABEL_9:
+    //this = v35;
+    v5 = (char *)&v30 + 4;
+    goto LABEL_10;
+  }
+LABEL_12:
+  result = v38;
+  this->field_10 = v38;
+  return result;
+}
+
+//----- (00477927) --------------------------------------------------------
+int stru6_stru1_indoor_sw_billboard::_477927(float a2)
+{
+  char *v2; // edi@1
+  int v3; // eax@1
+  char *v4; // edx@2
+  char *v5; // esi@3
+  double v6; // st7@6
+  signed __int64 v7; // ST84_8@6
+  double v8; // ST0C_8@6
+  int v9; // esi@6
+  double v10; // ST44_8@6
+  int v11; // ecx@6
+  double v12; // ST34_8@6
+  int v13; // ecx@6
+  double v14; // ST14_8@6
+  double v15; // st7@8
+  unsigned int v16; // ecx@8
+  signed __int64 v17; // ST64_8@8
+  double v18; // ST24_8@8
+  int v19; // edi@8
+  double v20; // ST3C_8@8
+  int v21; // ecx@8
+  double v22; // ST2C_8@8
+  int v23; // ST9C_4@8
+  double v24; // ST1C_8@8
+  int *v25; // edi@8
+  int v26; // esi@8
+  int *v27; // edi@10
+  int v28; // esi@10
+  int result; // eax@12
+  __int64 v30; // [sp+A8h] [bp-30h]@8
+  float v31; // [sp+B0h] [bp-28h]@6
+  float v32; // [sp+B4h] [bp-24h]@6
+  int v33; // [sp+B8h] [bp-20h]@6
+  int v34; // [sp+BCh] [bp-1Ch]@2
+  stru6_stru1_indoor_sw_billboard *v35; // [sp+C0h] [bp-18h]@1
+  float v36; // [sp+C4h] [bp-14h]@6
+  int v37; // [sp+C8h] [bp-10h]@6
+  int v38; // [sp+CCh] [bp-Ch]@1
+  float v39; // [sp+D0h] [bp-8h]@6
+  int *v40; // [sp+D4h] [bp-4h]@2
+
+  v2 = (char *)&this->field_14[4 * this->field_10 + 20];
+  v38 = 0;
+  *(int *)v2 = this->field_14[20];
+  v2 += 4;
+  *(int *)v2 = this->field_14[21];
+  v2 += 4;
+  *(int *)v2 = this->field_14[22];
+  *((int *)v2 + 1) = this->field_14[23];
+  v3 = this->field_10;
+  v35 = this;
+  if ( v3 > 0 )
+  {
+    v40 = &this->field_14[40];
+    v4 = (char *)&this->field_14[23] + 3;
+    v34 = v3;
+    while ( 1 )
+    {
+      v5 = v4 - 15;
+      if ( *(float *)(v4 - 15) >= (double)a2 && *(float *)(v4 + 1) >= (double)a2 )
+        goto LABEL_11;
+      if ( *(float *)v5 >= (double)a2 )
+        break;
+      if ( *(float *)(v4 + 1) >= (double)a2 )
+      {
+        v15 = (a2 - *(float *)v5) / (*(float *)(v4 + 1) - *(float *)v5);
+        v16 = (unsigned __int8)*v4;
+        HIDWORD(v30) = LODWORD(a2);
+        v17 = (unsigned __int8)v4[16] - v16;
+        v36 = v15;
+        v31 = (*(float *)(v4 + 5) - *(float *)(v4 - 11)) * v15 + *(float *)(v4 - 11);
+        v32 = (*(float *)(v4 + 9) - *(float *)(v4 - 7)) * v15 + *(float *)(v4 - 7);
+        v39 = (double)v17 * v15;
+        v18 = v39 + 6.7553994e15;
+        v19 = (unsigned __int8)*v4;
+        v39 = (double)((unsigned __int8)v4[15] - (unsigned int)(unsigned __int8)*(v4 - 1)) * v36;
+        v20 = v39 + 6.7553994e15;
+        v21 = (unsigned __int8)*(v4 - 2);
+        v37 = LODWORD(v20) + (unsigned __int8)*(v4 - 1);
+        v39 = (double)((unsigned int)(unsigned __int8)v4[14] - v21) * v36;
+        v22 = v39 + 6.7553994e15;
+        v23 = LODWORD(v22) + (unsigned __int8)*(v4 - 2);
+        v39 = (double)((*(int *)(v4 + 13) & 0xFF) - (*(int *)(v4 - 3) & 0xFFu)) * v36;
+        v24 = v39 + 6.7553994e15;
+        v33 = (LODWORD(v24) + (*(int *)(v4 - 3) & 0xFF)) | ((v23 | ((v37 | ((LODWORD(v18) + v19) << 8)) << 8)) << 8);
+        v25 = v40;
+        *v40 = *(int *)v5;
+        v26 = (int)(v5 + 4);
+        ++v25;
+        *v25 = *(int *)v26;
+        v26 += 4;
+        ++v25;
+        ++v38;
+        v40 += 4;
+        *v25 = *(int *)v26;
+        v25[1] = *(int *)(v26 + 4);
+        goto LABEL_9;
+      }
+LABEL_10:
+      v27 = v40;
+      ++v38;
+      *v40 = *(int *)v5;
+      v28 = (int)(v5 + 4);
+      ++v27;
+      *v27 = *(int *)v28;
+      v28 += 4;
+      ++v27;
+      v40 += 4;
+      *v27 = *(int *)v28;
+      v27[1] = *(int *)(v28 + 4);
+LABEL_11:
+      v4 += 16;
+      --v34;
+      if ( !v34 )
+        goto LABEL_12;
+    }
+    v6 = (a2 - *(float *)v5) / (*(float *)(v4 + 1) - *(float *)v5);
+    v7 = (unsigned __int8)v4[16] - (unsigned int)(unsigned __int8)*v4;
+    v36 = v6;
+    v31 = (*(float *)(v4 + 5) - *(float *)(v4 - 11)) * v6 + *(float *)(v4 - 11);
+    v32 = (*(float *)(v4 + 9) - *(float *)(v4 - 7)) * v6 + *(float *)(v4 - 7);
+    *(float *)&v37 = (double)v7 * v6;
+    v8 = *(float *)&v37 + 6.7553994e15;
+    v9 = (unsigned __int8)*v4;
+    *(float *)&v37 = (double)((unsigned __int8)v4[15] - (unsigned int)(unsigned __int8)*(v4 - 1)) * v36;
+    v10 = *(float *)&v37 + 6.7553994e15;
+    v11 = (unsigned __int8)*(v4 - 2);
+    v37 = LODWORD(v10) + (unsigned __int8)*(v4 - 1);
+    v39 = (double)((unsigned int)(unsigned __int8)v4[14] - v11) * v36;
+    v12 = v39 + 6.7553994e15;
+    v13 = LODWORD(v12) + (unsigned __int8)*(v4 - 2);
+    v39 = (double)((*(int *)(v4 + 13) & 0xFF) - (*(int *)(v4 - 3) & 0xFFu)) * v36;
+    v14 = v39 + 6.7553994e15;
+    v33 = (LODWORD(v14) + (*(int *)(v4 - 3) & 0xFF)) | ((v13 | ((v37 | ((LODWORD(v8) + v9) << 8)) << 8)) << 8);
+LABEL_9:
+    //this = v35;
+    v5 = (char *)&v30 + 4;
+    goto LABEL_10;
+  }
+LABEL_12:
+  result = v38;
+  this->field_10 = v38;
+  return result;
+}
+
+//----- (00477C61) --------------------------------------------------------
+int stru6_stru1_indoor_sw_billboard::sub_477C61()
+{
+  stru6_stru1_indoor_sw_billboard *v1; // ebx@1
+  int v2; // ecx@2
+  int v3; // eax@3
+  double v4; // st7@4
+  double v5; // st7@5
+  double v6; // st6@5
+  double v7; // st5@6
+  float v8; // ST30_4@8
+  float v9; // ST24_4@8
+  double v10; // st7@8
+  double v11; // st6@8
+  double v12; // st5@8
+  float v13; // ST24_4@13
+  int v14; // esi@13
+  char *v15; // esi@15
+  signed int v16; // eax@16
+  __int16 v17; // fps@16
+  unsigned __int8 v18; // c2@16
+  unsigned __int8 v19; // c3@16
+  double v20; // st6@16
+  float v21; // ST18_4@17
+  float v22; // ST2C_4@17
+  float v23; // ST34_4@17
+  float v24; // ST24_4@17
+  double v25; // st7@17
+  double v26; // st6@17
+  float v27; // ST34_4@18
+  float v28; // ST30_4@18
+  int v29; // eax@19
+  signed int v31; // [sp+8h] [bp-28h]@15
+  float v32; // [sp+Ch] [bp-24h]@16
+  float v33; // [sp+14h] [bp-1Ch]@16
+  float v34; // [sp+18h] [bp-18h]@16
+  float v35; // [sp+1Ch] [bp-14h]@17
+  float v36; // [sp+20h] [bp-10h]@4
+  float v37; // [sp+24h] [bp-Ch]@4
+  float v38; // [sp+24h] [bp-Ch]@16
+  float v39; // [sp+28h] [bp-8h]@9
+  float v40; // [sp+28h] [bp-8h]@16
+  float v41; // [sp+2Ch] [bp-4h]@6
+  float v42; // [sp+2Ch] [bp-4h]@9
+
+  v1 = this;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    v2 = 0;
+    if ( v1->field_10 > 0 )
+    {
+      v3 = (int)&v1->field_14[1];
+      do
+      {
+        v4 = *(float *)(v3 - 4);
+        LODWORD(v37) = *(int *)v3;
+        LODWORD(v36) = *(int *)(v3 + 4);
+        if ( pBLVRenderParams->sPartyRotX )
+        {
+          v5 = v4 - (double)pBLVRenderParams->vPartyPos.x;
+          v6 = v37 - (double)pBLVRenderParams->vPartyPos.y;
+          if ( pRenderer->pRenderD3D )
+          {
+            v41 = pBLVRenderParams->fSineY * v6 + pBLVRenderParams->fCosineY * v5;
+            v7 = pBLVRenderParams->fSineY * v5 - pBLVRenderParams->fCosineY * v6;
+          }
+          else
+          {
+            v41 = pBLVRenderParams->fCosineY * v5 - pBLVRenderParams->fSineY * v6;
+            v7 = pBLVRenderParams->fSineY * v5 + pBLVRenderParams->fCosineY * v6;
+          }
+          v8 = v7;
+          v9 = v36 - (double)pBLVRenderParams->vPartyPos.z;
+          v10 = pBLVRenderParams->fCosineNegX * v41 - pBLVRenderParams->fSineNegX * v9;
+          v11 = v8;
+          v12 = pBLVRenderParams->fCosineNegX * v9 + pBLVRenderParams->fSineNegX * v41;
+        }
+        else
+        {
+          v42 = v4 - (double)pBLVRenderParams->vPartyPos.x;
+          v39 = v37 - (double)pBLVRenderParams->vPartyPos.y;
+          if ( pRenderer->pRenderD3D )
+          {
+            v10 = pBLVRenderParams->fSineY * v39 + pBLVRenderParams->fCosineY * v42;
+            v11 = pBLVRenderParams->fSineY * v42 - pBLVRenderParams->fCosineY * v39;
+          }
+          else
+          {
+            v10 = pBLVRenderParams->fCosineY * v42 - pBLVRenderParams->fSineY * v39;
+            v11 = pBLVRenderParams->fSineY * v42 + pBLVRenderParams->fCosineY * v39;
+          }
+          v12 = v36 - (double)pBLVRenderParams->vPartyPos.z;
+        }
+        v13 = v12;
+        ++v2;
+        *(int *)(v3 + 84) = LODWORD(v13);
+        v14 = *(int *)(v3 + 8);
+        *(float *)(v3 + 76) = v10;
+        *(int *)(v3 + 88) = v14;
+        *(float *)(v3 + 80) = v11;
+        v3 += 16;
+      }
+      while ( v2 < v1->field_10 );
+    }
+  }
+  else
+  {
+    v15 = (char *)&this->field_14[1];
+    v31 = 3;
+    do
+    {
+      v40 = (double)stru_5C6E00->SinCos(pIndoorCamera->sRotationX) * 0.0000152587890625;
+      v32 = (double)stru_5C6E00->SinCos(pIndoorCamera->sRotationX - stru_5C6E00->uIntegerHalfPi)
+          * 0.0000152587890625;
+      v34 = (double)stru_5C6E00->SinCos(pIndoorCamera->sRotationY) * 0.0000152587890625;
+      v16 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY - stru_5C6E00->uIntegerHalfPi);
+      LODWORD(v38) = *(int *)v15;
+      v33 = (double)v16 * 0.0000152587890625;
+      //UNDEF(v17);
+      v20 = *((float *)v15 - 1) - (double)pIndoorCamera->pos.x;
+      if ( v19 | v18 )
+      {
+        v27 = v20;
+        LODWORD(v35) = *((int *)v15 + 1);
+        v28 = v38 - (double)pIndoorCamera->pos.y;
+        v25 = v33 * v28 + v34 * v27;
+        v26 = v34 * v28 - v33 * v27;
+      }
+      else
+      {
+        v21 = v20;
+        v22 = v38 - (double)pIndoorCamera->pos.y;
+        v23 = v33 * v22 + v34 * v21;
+        v24 = *((float *)v15 + 1) - (double)pIndoorCamera->pos.z;
+        v25 = v32 * v24 + v40 * v23;
+        v26 = v34 * v22 - v33 * v21;
+        v35 = v40 * v24 - v32 * v23;
+      }
+      *((int *)v15 + 21) = LODWORD(v35);
+      v29 = *((int *)v15 + 2);
+      *((float *)v15 + 19) = v25;
+      *((int *)v15 + 22) = v29;
+      *((float *)v15 + 20) = v26;
+      v15 += 16;
+      --v31;
+    }
+    while ( v31 );
+  }
+  v1->field_10 = 3;
+  return 1;
+}
+
+//----- (00477F63) --------------------------------------------------------
+bool stru6_stru1_indoor_sw_billboard::sub_477F63()
+{
+  signed int v1; // ebx@1
+  stru6_stru1_indoor_sw_billboard *v2; // esi@1
+  double v3; // st7@2
+  int v4; // edx@4
+  char *v5; // ecx@5
+  int v6; // edi@5
+  float v7; // ST08_4@13
+  signed int v9; // [sp+Ch] [bp-8h]@1
+  float v10; // [sp+10h] [bp-4h]@2
+
+  auto a1 = this;
+
+  v1 = 0;
+  v2 = a1;
+  v9 = 0;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    v10 = 16192.0;
+    v3 = (double)pBLVRenderParams->field_40 * 0.000015258789;
+  }
+  else
+  {
+    v10 = (double)pOutdoorCamera->shading_dist_mist;
+    v3 = 8.0;
+  }
+  v4 = a1->field_10;
+  if ( v4 <= 0 )
+    goto LABEL_16;
+  v5 = (char *)&a1->field_14[20];
+  v6 = v4;
+  do
+  {
+    if ( v3 >= *(float *)v5 || *(float *)v5 >= (double)v10 )
+    {
+      if ( v3 < *(float *)v5 )
+        v9 = 1;
+      else
+        v1 = 1;
+    }
+    v5 += 16;
+    --v6;
+  }
+  while ( v6 );
+  if ( !v1 )
+  {
+    if ( v9 )
+    {
+      v2->_477927(v10);
+      return v2->field_10 != 0;
+    }
+LABEL_16:
+    memcpy(&v2->field_14[40], &v2->field_14[20], 16 * v4);
+    return v2->field_10 != 0;
+  }
+  v7 = v3;
+  _4775ED(v7);
+  return v2->field_10 != 0;
+}
+
+//----- (0047802A) --------------------------------------------------------
+int stru6_stru1_indoor_sw_billboard::sub_47802A()
+{
+  int v1; // edx@1
+  stru6_stru1_indoor_sw_billboard *v2; // edi@1
+  int v3; // ebx@2
+  char *v4; // esi@3
+  float v5; // eax@4
+  double v6; // st7@4
+  double v7; // ST30_8@5
+  double v8; // st6@6
+  double v9; // st5@6
+  char *v10; // ecx@15
+  float v11; // eax@16
+  double v12; // st7@16
+  double v13; // st6@16
+  double v14; // st5@16
+  signed int v16; // [sp+38h] [bp-Ch]@1
+  int a6; // [sp+3Ch] [bp-8h]@5
+  int a5; // [sp+40h] [bp-4h]@5
+
+  auto a1 = this;
+
+  v1 = 0;
+  v2 = a1;
+  v16 = 0;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    v3 = 0;
+    if ( a1->field_10 > 0 )
+    {
+      v4 = (char *)&a1->field_14[42];
+      do
+      {
+        LODWORD(v5) = *((int *)v4 - 2);
+        v6 = (double)pBLVRenderParams->field_40 * 0.000015258789 / *((float *)v4 - 2);
+        if ( pRenderer->pRenderD3D )
+        {
+          v7 = v5 + 6.7553994e15;
+          pGame->pIndoorCameraD3D->Project(
+            COERCE_UNSIGNED_INT64(v5 + 6.7553994e15),
+            COERCE_UNSIGNED_INT64(*((float *)v4 - 1) + 6.7553994e15),
+            COERCE_UNSIGNED_INT64(*(float *)v4 + 6.7553994e15),
+            &a5,
+            &a6);
+          *((float *)v4 + 18) = (double)a5;
+          *((float *)v4 + 19) = (double)a6;
+          *((float *)v4 + 20) = (double)SLODWORD(v7);
+        }
+        else
+        {
+          *((float *)v4 + 18) = (double)pBLVRenderParams->uViewportCenterX - v6 * *((float *)v4 - 1);
+          v8 = (double)pBLVRenderParams->uViewportCenterY;
+          v9 = v6 * *(float *)v4;
+          *((int *)v4 + 20) = LODWORD(v5);
+          *((float *)v4 + 19) = v8 - v9;
+        }
+        *((int *)v4 + 21) = *((int *)v4 + 1);
+        if ( (double)(signed int)pViewport->uViewportX <= *((float *)v4 + 18)
+          && (double)(signed int)pViewport->uViewportZ > *((float *)v4 + 18)
+          && (double)(signed int)pViewport->uViewportY <= *((float *)v4 + 19)
+          && (double)(signed int)pViewport->uViewportW > *((float *)v4 + 19) )
+          v16 = 1;
+        ++v3;
+        v4 += 16;
+      }
+      while ( v3 < v2->field_10 );
+    }
+  }
+  else
+  {
+    if ( a1->field_10 > 0 )
+    {
+      v10 = (char *)&a1->field_14[40];
+      do
+      {
+        LODWORD(v11) = *(int *)v10;
+        v12 = (double)pOutdoorCamera->int_fov_rad / *(float *)v10;
+        *((float *)v10 + 20) = (double)pViewport->uScreenCenterX - v12 * *((float *)v10 + 1);
+        v13 = (double)pViewport->uScreenCenterY;
+        v14 = v12 * *((float *)v10 + 2);
+        *((int *)v10 + 22) = LODWORD(v11);
+        *((int *)v10 + 23) = *((int *)v10 + 3);
+        *((float *)v10 + 21) = v13 - v14;
+        if ( (double)(signed int)pViewport->uViewportX <= *((float *)v10 + 20)
+          && (double)(signed int)pViewport->uViewportZ > *((float *)v10 + 20)
+          && (double)(signed int)pViewport->uViewportY <= *((float *)v10 + 21)
+          && (double)(signed int)pViewport->uViewportW > *((float *)v10 + 21) )
+          v16 = 1;
+        ++v1;
+        v10 += 16;
+      }
+      while ( v1 < v2->field_10 );
+    }
+  }
+  return v16;
+}
+
+
+
+//----- (004783FA) --------------------------------------------------------
+void __cdecl sub_4783FA_construct_global_73D150()
+{
+  char *v0; // eax@1
+  signed int v1; // ecx@1
+
+  v0 = (char *)&array_73D150[0].flt_2C;
+  v1 = 20;
+  do
+  {
+    *(float *)v0 = 0.0;
+    v0 += 48;
+    --v1;
+  }
+  while ( v1 );
+}
+
+
+
+//----- (0047840D) --------------------------------------------------------
+char Render::DrawBuildingsD3D()
+{
+  IndoorCameraD3D *v0; // eax@3
+  char result; // al@3
+  Vec3_int_ **v2; // ebx@4
+  Vec3_int_ *v3; // eax@6
+  ODMFace *pFace; // esi@6
+  int v5; // ecx@8
+  int v6; // eax@8
+  stru148 *v7; // ebx@8
+  LightmapBuilder *v8; // eax@8
+  int v9; // ecx@8
+  char v10; // zf@8
+  Texture *pFaceTexture; // eax@10
+  signed int v12; // ecx@10
+  unsigned int v13; // eax@14
+  unsigned int v14; // eax@18
+  unsigned int v15; // eax@22
+  unsigned int v16; // edi@22
+  int v17; // eax@24
+  int v18; // edi@34
+  char *v19; // eax@35
+  char *v20; // ecx@35
+  Vec3_int_ *v21; // edx@36
+  int v22; // edx@36
+  char *v23; // edi@37
+  int v24; // eax@50
+  int v25; // ecx@55
+  int v26; // eax@57
+  int v27; // eax@57
+  int v28; // eax@58
+  int v29; // edx@58
+  double v30; // st7@59
+  LightmapBuilder *v31; // edi@63
+  signed int v32; // eax@73
+  int v33; // eax@78
+  unsigned int v34; // eax@80
+  std::string v35; // [sp-18h] [bp-70h]@2
+  int v36; // [sp-14h] [bp-6Ch]@69
+  RenderVertexSoft *v37; // [sp-10h] [bp-68h]@69
+  int v38; // [sp-Ch] [bp-64h]@69
+  LightmapBuilder *v39; // [sp-8h] [bp-60h]@2
+  int v40; // [sp-4h] [bp-5Ch]@2
+  std::string *v41; // [sp+Ch] [bp-4Ch]@2
+  Vec3_int_ *v42; // [sp+10h] [bp-48h]@6
+  LightmapBuilder *pLightmapBuilder; // [sp+14h] [bp-44h]@8
+  float v44; // [sp+18h] [bp-40h]@10
+  float v45; // [sp+1Ch] [bp-3Ch]@10
+  ODMFace *v46; // [sp+20h] [bp-38h]@6
+  IndoorCameraD3D *v47; // [sp+24h] [bp-34h]@3
+  unsigned int v48; // [sp+28h] [bp-30h]@8
+  int v49; // [sp+2Ch] [bp-2Ch]@10
+  int v50; // [sp+30h] [bp-28h]@34
+  int v51; // [sp+34h] [bp-24h]@35
+  int v52; // [sp+38h] [bp-20h]@36
+  int v53; // [sp+3Ch] [bp-1Ch]@8
+  Vec3_int_ *v54; // [sp+40h] [bp-18h]@6
+  int a1; // [sp+44h] [bp-14h]@3
+  Vec3_int_ **v56; // [sp+48h] [bp-10h]@4
+  int uNumVertices; // [sp+4Ch] [bp-Ch]@34
+  int unused; // [sp+50h] [bp-8h]@3
+  int a3; // [sp+57h] [bp-1h]@2
+
+  if ( !pRenderer->pRenderD3D )
+  {
+          MessageBoxW(nullptr, L"D3D version of RenderBuildings called in software!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odbuild.cpp:73", 0);
+  }
+  unused = 0;
+  v0 = pGame->pIndoorCameraD3D;
+  a1 = 0;
+  v47 = v0;
+  result = LOBYTE(pOutdoor->pBModels);
+  v41 = (std::string *)pOutdoor->uNumBModels;
+  if ( (signed int)pOutdoor->uNumBModels > 0 )
+  {
+    v2 = (Vec3_int_ **)&pOutdoor->pBModels->uNumFaces;
+    v56 = (Vec3_int_ **)&pOutdoor->pBModels->uNumFaces;
+    while ( 1 )
+    {
+      if ( IsBModelVisible(a1, &unused) )
+      {
+        *(v2 - 3) = (Vec3_int_ *)((unsigned int)*(v2 - 3) | 1);
+        v3 = *v2;
+        pFace = (ODMFace *)v2[2];
+        v54 = 0;
+        v46 = pFace;
+        v42 = v3;
+        if ( (signed int)v3 > 0 )
+          break;
+      }
+LABEL_86:
+      ++a1;
+      v2 += 47;
+      result = a1;
+      v56 = v2;
+      if ( a1 >= (signed int)v41 )
+        return result;
+    }
+    while ( 1 )
+    {
+      if (pFace->Invisible())
+        goto LABEL_85;
+      v5 = (int)*(v2 - 1);
+      v6 = pFace->pVertexIDs[0];
+      v53 = 0;
+      v7 = &array_77EC08[pOutdoorCamera->numStru148s];
+      v8 = *(LightmapBuilder **)(v5 + 12 * v6 + 8);
+      *(int *)&v7->flags = 0;
+      pLightmapBuilder = v8;
+      v9 = pFace->uTextureID;
+      v10 = (BYTE1(pFace->uAttributes) & 0x40) == 0;
+      v48 = pFace->uTextureID;
+      if ( !v10 )
+      {
+        v48 = pTextureFrameTable->GetFrameTexture(v9, pEventTimer->uTotalGameTimeElapsed);
+        v9 = v48;
+      }
+      pFaceTexture = (Texture *)(v9 != -1 ? (int)&pBitmaps_LOD->pTextures[v9] : 0);
+      v7->pTexture = pFaceTexture;
+      v12 = (v9 != -1 ? pBitmaps_LOD->pTextures[v9].uTextureWidth : 24);
+      v49 = v12;
+      v49 = pFaceTexture->uTextureHeight;
+      v10 = (pFace->uAttributes & 0x10) == 0;
+      v45 = 1.0 / (double)v12;
+      v44 = 1.0 / (double)v49;
+      if ( !v10 )
+        *(int *)&v7->flags |= 2u;
+      if ( BYTE2(pFace->uAttributes) & 0x40 )
+        HIBYTE(v7->flags) |= 4u;
+      v13 = pFace->uAttributes;
+      if ( v13 & 4 )
+      {
+        HIBYTE(v7->flags) |= 4u;
+      }
+      else
+      {
+        if ( v13 & 0x20 )
+          HIBYTE(v7->flags) |= 8u;
+      }
+      v14 = pFace->uAttributes;
+      if ( BYTE1(v14) & 8 )
+      {
+        *(int *)&v7->flags |= 0x2000u;
+      }
+      else
+      {
+        if ( v14 & 0x40 )
+          HIBYTE(v7->flags) |= 0x10u;
+      }
+      v15 = GetTickCount();
+      v7->sTextureDeltaU = pFace->sTextureDeltaU;
+      v7->sTextureDeltaV = pFace->sTextureDeltaV;
+      v16 = v15 >> 4;
+      if ( pFace->pFacePlane.vNormal.z && (v40 = pFace->pFacePlane.vNormal.z, abs(v40) >= 59082) )
+      {
+        v17 = *(int *)&v7->flags;
+        if ( BYTE1(v17) & 4 )
+          goto LABEL_29;
+        if ( BYTE1(v17) & 8 )
+        {
+LABEL_26:
+          v7->sTextureDeltaV -= v16 & v7->pTexture->uHeightMinus1;
+          goto LABEL_30;
+        }
+      }
+      else
+      {
+        v17 = *(int *)&v7->flags;
+        if ( BYTE1(v17) & 4 )
+          goto LABEL_26;
+        if ( BYTE1(v17) & 8 )
+        {
+LABEL_29:
+          v7->sTextureDeltaV += v16 & v7->pTexture->uHeightMinus1;
+          goto LABEL_30;
+        }
+      }
+LABEL_30:
+      if ( BYTE1(v17) & 0x10 )
+      {
+        v7->sTextureDeltaU -= v16 & v7->pTexture->uWidthMinus1;
+      }
+      else
+      {
+        if ( BYTE1(v17) & 0x20 )
+          v7->sTextureDeltaU += v16 & v7->pTexture->uWidthMinus1;
+      }
+      v18 = pFace->uNumVertices;
+      v50 = 0;
+      v49 = 0;
+      uNumVertices = v18;
+      if ( v18 > 0 )
+      {
+        v19 = (char *)&array_73D150[0].vWorldPosition.z;
+        v20 = (char *)pFace->pTextureUIDs;
+        v51 = v18;
+        do
+        {
+          v21 = &(*(v56 - 1))[*((short *)v20 - 20)];
+          *((float *)v19 - 2) = (double)v21->x;
+          *((float *)v19 - 1) = (double)v21->y;
+          *(float *)v19 = (double)v21->z;
+          v19 += 48;
+          v52 = v7->sTextureDeltaU + *(short *)v20;
+          *((float *)v19 - 5) = (double)v52 * v45;
+          v22 = v7->sTextureDeltaV + *((short *)v20 + 20);
+          v20 += 2;
+          v10 = v51-- == 1;
+          v52 = v22;
+          *((float *)v19 - 4) = (double)v22 * v44;
+        }
+        while ( !v10 );
+        v23 = (char *)&array_73D150[0].vWorldViewPosition;
+        v51 = uNumVertices;
+        *(float *)&pLightmapBuilder = (double)(signed int)pLightmapBuilder;
+        do
+        {
+          if ( *(float *)&pLightmapBuilder == *((float *)v23 - 1) )
+            ++v53;
+          v47->ViewTransform((RenderVertexSoft *)(v23 - 12), 1u);
+          if ( *(float *)v23 < 8.0 || (double)pOutdoorCamera->shading_dist_mist < *(float *)v23 )
+          {
+            if ( *(float *)v23 >= 8.0 )
+              v49 = 1;
+            else
+              v50 = 1;
+          }
+          else
+          {
+            v47->Project((RenderVertexSoft *)(v23 - 12), 1u, 0);
+          }
+          v23 += 48;
+          --v51;
+        }
+        while ( v51 );
+        v18 = uNumVertices;
+      }
+      if ( v53 == v18 )
+        LOBYTE(v7->field_32) |= 1u;
+      v24 = pOutdoor->vSunlight.x;
+      v7->pODMFace = pFace;
+      v7->uNumVertices = v18;
+      v7->field_59 = 5;
+      pLightmapBuilder = (LightmapBuilder *)-v24;
+      v51 = pFace->pFacePlane.vNormal.x;
+      v51 = (unsigned __int64)(-v24 * (signed __int64)v51) >> 16;
+      v53 = pFace->pFacePlane.vNormal.y;
+      pLightmapBuilder = (LightmapBuilder *)-pOutdoor->vSunlight.y;
+      v53 = (unsigned __int64)(-pOutdoor->vSunlight.y * (signed __int64)v53) >> 16;
+      v52 = pFace->pFacePlane.vNormal.z;
+      v52 = (unsigned __int64)(-pOutdoor->vSunlight.z * (signed __int64)v52) >> 16;
+      pLightmapBuilder = (LightmapBuilder *)(v51 + v53 + v52);
+      v51 = 20 * (int)pLightmapBuilder;
+      result = 20 - (20 * (signed int)pLightmapBuilder >> 16);
+      v7->field_58 = result;
+      if ( result < 0 )
+        v7->field_58 = 0;
+      if ( v7->field_58 > 31 )
+        v7->field_58 = 31;
+      if ( pOutdoorCamera->numStru148s >= 1999 )
+        return result;
+      ++pOutdoorCamera->numStru148s;
+      ++pOutdoorCamera->field_44;
+      if ( ODMFace::IsBackfaceCulled(pFace, array_73D150, v7) )
+      {
+        LOBYTE(v25) = (char)v54;
+        v26 = a1;
+        pFace->bVisible = 1;
+        v7->uBModelFaceID = v25;
+        LOWORD(v25) = (unsigned __int8)v25;
+        v7->uBModelID = v26;
+        v27 = 8 * (v25 | (v26 << 6));
+        LOBYTE(v27) = v27 | 6;
+        v7->field_50 = v27;
+        if ( v18 > 0 )
+        {
+          v28 = 0;
+          v29 = v18;
+          do
+          {
+            v30 = 1.0 / (array_73D150[v28].vWorldViewPosition.x + 0.0000001);
+            memcpy(&array_50AC10[v28], &array_73D150[v28], sizeof(array_50AC10[v28]));
+            ++v28;
+            --v29;
+            array_50A2B0[v28 + 49].flt_20 = v30;
+          }
+          while ( v29 );
+          pFace = v46;
+        }
+
+        static stru154 static_RenderBuildingsD3D_stru_73C834;
+        /*static bool __init_flag = false;
+        if (!__init_flag)
+        {
+          __init_flag = true;
+
+          static_RenderBuildingsD3D_byte_73C84C_init_flag |= 1u;
+          stru154::stru154(&static_RenderBuildingsD3D_stru_73C834);
+          atexit(loc_4789D4);
+        }*/
+
+        v40 = (int)pFace;
+        pLightmapBuilder = pGame->pLightmapBuilder;
+        v31 = pLightmapBuilder;
+        pLightmapBuilder->ApplyLights_OutdoorFace(pFace);
+        pDecalBuilder->ApplyDecals_OutdoorFace(pFace);
+        v31->std__vector_000004_size = 0;
+        LOBYTE(v31) = 0;
+        if ( stru_F8AD28.uNumLightsApplied > 0 || pDecalBuilder->uNumDecals > 0 )
+        {
+          v31 = (LightmapBuilder *)(v50 ? 3 : v49 != 0 ? 5 : 0);
+          static_RenderBuildingsD3D_stru_73C834._49B04D(pFace, (BSPVertexBuffer *)v56 - 1);
+          if ( pDecalBuilder->uNumDecals > 0 )
+          {
+            v40 = -1;
+            v39 = v31;
+            v38 = 0;
+            v37 = array_50AC10;
+            v36 = uNumVertices;
+            pDecalBuilder->ApplyDecals(
+              31 - v7->field_58,
+              2,
+              &static_RenderBuildingsD3D_stru_73C834,
+              uNumVertices,
+              array_50AC10,
+              0,
+              (char)v31,
+              -1);
+          }
+        }
+        if ( stru_F8AD28.uNumLightsApplied > 0 )
+          pLightmapBuilder->ApplyLights(
+            &stru_F8AD28,
+            &static_RenderBuildingsD3D_stru_73C834,
+            uNumVertices,
+            array_50AC10,
+            0,
+            (char)v31);
+        if ( v50 )
+        {
+          v32 = sr_424CD7(uNumVertices);
+          goto LABEL_76;
+        }
+        if ( v49 )
+        {
+          v32 = sr_424EE0_MakeFanFromTriangle(uNumVertices);
+LABEL_76:
+          v7->uNumVertices = v32;
+          uNumVertices = v32;
+          OutdoorCamera::Project(v32);
+        }
+        if ( uNumVertices )
+        {
+          v33 = *(int *)&v7->flags;
+          if ( v33 & 2 )
+          {
+            if ( BYTE1(v33) & 0x3C )
+              v34 = pRenderer->pHDWaterBitmapIDs[0];
+            else
+              v34 = pRenderer->pHDWaterBitmapIDs[pRenderer->field_1036A8_bitmapid];
+            v40 = (int)pBitmaps_LOD->pHardwareTextures[v34];
+          }
+          else
+          {
+            v40 = (int)pBitmaps_LOD->pHardwareTextures[v48];
+          }
+          pRenderer->DrawPolygon(uNumVertices, v7, pFace, (IDirect3DTexture2 *)v40);
+        }
+        goto LABEL_85;
+      }
+      --pOutdoorCamera->numStru148s;
+      --pOutdoorCamera->field_44;
+LABEL_85:
+      v54 = (Vec3_int_ *)((char *)v54 + 1);
+      v2 = v56;
+      ++pFace;
+      v46 = pFace;
+      if ( (signed int)v54 >= (signed int)v42 )
+        goto LABEL_86;
+    }
+  }
+  return result;
+}
+// 73C84C: using guessed type char static_RenderBuildingsD3D_byte_73C84C_init_flag;
+
+//----- (004789DE) --------------------------------------------------------
+BSPModel *Render::DrawBuildingsSW()
+{
+  BSPModel *result; // eax@1
+  unsigned int *v1; // ebx@2
+  int v2; // eax@4
+  int v3; // edi@4
+  int v4; // ecx@6
+  int v5; // eax@6
+  int v6; // ecx@6
+  int v7; // ecx@6
+  double v8; // st7@7
+  char *v9; // ebx@7
+  int v10; // eax@9
+  double v11; // st7@9
+  stru148 *v12; // ebx@19
+  double v13; // st7@21
+  double v14; // ST4C_8@23
+  int v15; // eax@23
+  int v16; // eax@27
+  int v17; // ecx@29
+  unsigned __int8 v18; // sf@29
+  unsigned __int8 v19; // of@29
+  int v20; // ecx@30
+  int v21; // eax@31
+  int v22; // eax@31
+  int v23; // eax@35
+  int v24; // eax@39
+  Texture *v25; // eax@43
+  int v26; // esi@43
+  signed int v27; // ecx@43
+  double v28; // st6@43
+  double v29; // st5@43
+  int v30; // edx@44
+  int v31; // eax@44
+  double v32; // st4@45
+  int v33; // ecx@45
+  char v34; // zf@45
+  BSPVertexBuffer *v35; // eax@50
+  unsigned int v36; // eax@53
+  signed int v37; // esi@53
+  int v38; // eax@54
+  signed int v39; // edx@55
+  char *v40; // ecx@56
+  double v41; // ST1C_8@57
+  double v42; // ST24_8@57
+  signed int v43; // eax@60
+  signed int v44; // esi@60
+  int v45; // eax@61
+  signed int v46; // edx@62
+  char *v47; // ecx@63
+  double v48; // ST34_8@64
+  double v49; // ST44_8@64
+  int v50; // eax@66
+  signed int v51; // ecx@67
+  char *v52; // edx@68
+  double v53; // ST3C_8@69
+  double v54; // ST2C_8@69
+  float v55; // [sp+44h] [bp-7Ch]@50
+  float v56; // [sp+48h] [bp-78h]@50
+  float v57; // [sp+4Ch] [bp-74h]@50
+  float v58; // [sp+50h] [bp-70h]@64
+  int v59; // [sp+54h] [bp-6Ch]@64
+  int v60; // [sp+58h] [bp-68h]@69
+  float v61; // [sp+5Ch] [bp-64h]@64
+  float v62; // [sp+60h] [bp-60h]@69
+  float v63; // [sp+64h] [bp-5Ch]@57
+  float v64; // [sp+68h] [bp-58h]@57
+  int v65; // [sp+6Ch] [bp-54h]@64
+  int v66; // [sp+70h] [bp-50h]@1
+  int v67; // [sp+74h] [bp-4Ch]@6
+  int v68; // [sp+78h] [bp-48h]@4
+  int v69; // [sp+7Ch] [bp-44h]@57
+  int v70; // [sp+80h] [bp-40h]@69
+  int v71; // [sp+84h] [bp-3Ch]@23
+  float v72; // [sp+88h] [bp-38h]@69
+  int v73; // [sp+8Ch] [bp-34h]@57
+  int v74; // [sp+90h] [bp-30h]@6
+  int v75; // [sp+94h] [bp-2Ch]@6
+  int v76; // [sp+98h] [bp-28h]@4
+  int v77; // [sp+9Ch] [bp-24h]@6
+  unsigned int *v78; // [sp+A0h] [bp-20h]@2
+  int v79; // [sp+A4h] [bp-1Ch]@4
+  int a1; // [sp+A8h] [bp-18h]@1
+  int v81; // [sp+ACh] [bp-14h]@7
+  int v82; // [sp+B0h] [bp-10h]@6
+  int v83; // [sp+B4h] [bp-Ch]@6
+  signed int v84; // [sp+B8h] [bp-8h]@7
+  int a2; // [sp+BCh] [bp-4h]@1
+
+  a2 = 0;
+  a1 = 0;
+  result = pOutdoor->pBModels;
+  v66 = pOutdoor->uNumBModels;
+  if ( (signed int)pOutdoor->uNumBModels > 0 )
+  {
+    v1 = &pOutdoor->pBModels->uNumFaces;
+    v78 = &pOutdoor->pBModels->uNumFaces;
+    while ( 1 )
+    {
+      if ( IsBModelVisible(a1, &a2) )
+      {
+        *(v1 - 3) |= 1u;
+        v2 = *v1;
+        v3 = v1[2];
+        v79 = 0;
+        v76 = v3;
+        v68 = v2;
+        if ( v2 > 0 )
+          break;
+      }
+LABEL_73:
+      ++a1;
+      v1 += 47;
+      result = (BSPModel *)a1;
+      v78 = v1;
+      if ( a1 >= v66 )
+        return result;
+    }
+    while ( 1 )
+    {
+      if ( !(*(char *)(v3 + 29) & 0x20) )
+      {
+        v4 = 3 * *(short *)(v3 + 32);
+        v5 = (int)(v1 - 2);
+        v67 = (int)(v1 - 2);
+        v6 = *(int *)(*(v1 - 1) + 4 * v4 + 8) + 4;
+        v82 = 0;
+        v83 = v6;
+        v74 = 0;
+        v7 = *(char *)(v3 + 302);
+        v75 = 0;
+        v77 = v7;
+        if ( v7 > 0 )
+        {
+          v8 = (double)v83;
+          v9 = (char *)&array_73D150[0].vWorldViewPosition;
+          v81 = v3 + 32;
+          v83 = v7;
+          *(float *)&v84 = v8;
+          while ( 1 )
+          {
+            v10 = *(int *)(v5 + 4) + 12 * *(short *)v81;
+            *((float *)v9 - 3) = (double)*(signed int *)v10 + 4.0;
+            *((float *)v9 - 2) = (double)*(signed int *)(v10 + 4) + 4.0;
+            v11 = (double)*(signed int *)(v10 + 8) + 4.0;
+            *((float *)v9 - 1) = v11;
+            if ( *(float *)&v84 == v11 )
+              ++v82;
+            pGame->pIndoorCameraD3D->ViewTransform((RenderVertexSoft *)(v9 - 12), 1u);
+            if ( *(float *)v9 < 8.0 || (double)pOutdoorCamera->shading_dist_mist < *(float *)v9 )
+            {
+              if ( *(float *)v9 >= 8.0 )
+                v75 = 1;
+              else
+                v74 = 1;
+            }
+            else
+            {
+              pGame->pIndoorCameraD3D->Project((RenderVertexSoft *)(v9 - 12), 1u, 0);
+            }
+            v81 += 2;
+            v9 += 48;
+            --v83;
+            if ( !v83 )
+              break;
+            v5 = v67;
+          }
+          v7 = v77;
+        }
+        v12 = &array_77EC08[pOutdoorCamera->numStru148s];
+        *(int *)&v12->flags = 0;
+        if ( v82 == v7 )
+          *(int *)&v12->flags = 65536;
+        v12->pODMFace = (ODMFace *)v3;
+        v12->uNumVertices = v7;
+        v12->field_59 = 5;
+        v84 = *(int *)v3;
+        v83 = (unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.x) >> 16;
+        v82 = -pOutdoor->vSunlight.y;
+        v84 = *(int *)(v3 + 4);
+        v82 = (unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.y) >> 16;
+        v81 = -pOutdoor->vSunlight.z;
+        v84 = *(int *)(v3 + 8);
+        v81 = (unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.z) >> 16;
+        v84 = v83 + v82 + ((unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.z) >> 16);
+        v13 = (double)v84 * 0.000015258789;
+        if ( v13 < 0.0 )
+          v13 = 0.0;
+        *(float *)&v84 = v13 * 31.0;
+        v14 = *(float *)&v84 + 6.7553994e15;
+        v71 = LODWORD(v14);
+        v15 = (int)&v12->field_58;
+        v12->field_58 = 31 - LOBYTE(v14);
+        if ( (char)(31 - LOBYTE(v14)) < 0 )
+          *(char *)v15 = 0;
+        if ( *(char *)v15 > 31 )
+          *(char *)v15 = 31;
+        v16 = *(short *)(v3 + 272);
+        if ( *(char *)(v3 + 29) & 0x40 )
+          v16 = pTextureFrameTable->GetFrameTexture(v16, pEventTimer->uTotalGameTimeElapsed);
+        v17 = v16;
+        result = (BSPModel *)&pBitmaps_LOD->pTextures[v16];
+        v19 = __OFSUB__(pOutdoorCamera->numStru148s, 1999);
+        v18 = pOutdoorCamera->numStru148s - 1999 < 0;
+        v12->pTexture = (Texture *)(v17 != -1 ? (int)result : 0);
+        if ( !(v18 ^ v19) )
+          return result;
+        ++pOutdoorCamera->numStru148s;
+        ++pOutdoorCamera->field_44;
+        if ( !ODMFace::IsBackfaceCulled((ODMFace *)v3, array_73D150, v12) )
+        {
+LABEL_71:
+          --pOutdoorCamera->numStru148s;
+          --pOutdoorCamera->field_44;
+          goto LABEL_72;
+        }
+        LOBYTE(v20) = v79;
+        v21 = a1;
+        *(char *)(v3 + 305) = 1;
+        v12->uBModelFaceID = v20;
+        LOWORD(v20) = (unsigned __int8)v20;
+        v12->uBModelID = v21;
+        v22 = 8 * (v20 | (v21 << 6));
+        LOBYTE(v22) = v22 | 6;
+        v12->field_50 = v22;
+        if ( *(char *)(v3 + 28) & 0x10 )
+          *(int *)&v12->flags |= 2u;
+        if ( *(char *)(v3 + 30) & 0x40 )
+          HIBYTE(v12->flags) |= 4u;
+        v23 = *(int *)(v3 + 28);
+        if ( v23 & 4 )
+        {
+          HIBYTE(v12->flags) |= 4u;
+        }
+        else
+        {
+          if ( v23 & 0x20 )
+            HIBYTE(v12->flags) |= 8u;
+        }
+        v24 = *(int *)(v3 + 28);
+        if ( BYTE1(v24) & 8 )
+        {
+          HIBYTE(v12->flags) |= 0x20u;
+        }
+        else
+        {
+          if ( v24 & 0x40 )
+            HIBYTE(v12->flags) |= 0x10u;
+        }
+        v25 = v12->pTexture;
+        v26 = v77;
+        v27 = v25->uTextureWidth;
+        v84 = v25->uTextureHeight;
+        v28 = 1.0 / (double)v27;
+        v29 = 1.0 / (double)v84;
+        if ( v77 > 0 )
+        {
+          v30 = v3 + 112;
+          v31 = 0;
+          v83 = v77;
+          do
+          {
+            v32 = 1.0 / (*(float *)(v31 * 48 + 7590236) + 0.0000001);
+            memcpy(&array_50AC10[v31], &array_73D150[v31], sizeof(array_50AC10[v31]));
+            ++v31;
+            array_50A2B0[v31 + 49].flt_20 = v32;
+            v84 = v12->sTextureDeltaU + *(short *)(v30 - 40);
+            array_50A2B0[v31 + 49].u = (double)v84 * v28;
+            v33 = v12->sTextureDeltaV + *(short *)v30;
+            v30 += 2;
+            v34 = v83-- == 1;
+            v84 = v33;
+            array_50A2B0[v31 + 49].v = (double)v33 * v29;
+          }
+          while ( !v34 );
+          v3 = v76;
+          v26 = v77;
+        }
+        
+        static stru154 static_sub_004789DE_stru_73C818; // idb
+        /*static bool __init_flag = false;
+        if (!__init_flag)
+        {
+          __init_flag = true;
+
+          static_sub_004789DE_byte_73C830__init_flag |= 1u;
+          stru154::stru154(&static_sub_004789DE_stru_73C818);
+        }*/
+
+        pGame->pLightmapBuilder->ApplyLights_OutdoorFace((ODMFace *)v3);
+        if ( stru_F8AD28.uNumLightsApplied <= 0 )
+        {
+          v12->field_108 = 0;
+        }
+        else
+        {
+          v35 = (BSPVertexBuffer *)(v78 - 2);
+          v12->field_108 = 1;
+
+          static_sub_004789DE_stru_73C818._49B04D((ODMFace *)v3, v35);
+          v55 = static_sub_004789DE_stru_73C818.face_plane.vNormal.x;
+          v56 = static_sub_004789DE_stru_73C818.face_plane.vNormal.y;
+          v57 = static_sub_004789DE_stru_73C818.face_plane.vNormal.z;
+          pGame->pLightmapBuilder->_45CA88(&stru_F8AD28, array_50AC10, v26, (Vec3_float_ *)&v55);
+        }
+        if ( v74 )
+        {
+          v36 = sr_4250FE(v26);
+          v37 = v36;
+          if ( !v36 || (OutdoorCamera::Project(v36), v38 = sr_4254D2(v37), (v12->uNumVertices = v38) == 0) )
+            goto LABEL_71;
+          v12->_48276F_sr();
+          v39 = 0;
+          if ( (signed int)v12->uNumVertices > 0 )
+          {
+            v40 = (char *)&array_508690[0].vWorldViewProjY;
+            do
+            {
+              LODWORD(v64) = *((int *)v40 - 1);
+              v41 = v64 + 6.7553994e15;
+              v69 = LODWORD(v41);
+              dword_50B638[v39] = LODWORD(v41);
+              LODWORD(v63) = *(int *)v40;
+              v42 = v63 + 6.7553994e15;
+              v73 = LODWORD(v42);
+              v40 += 48;
+              dword_50B570[v39++] = LODWORD(v42);
+            }
+            while ( v39 < (signed int)v12->uNumVertices );
+          }
+        }
+        else
+        {
+          if ( v75 )
+          {
+            v43 = sr_4252E8(v26);
+            v44 = v43;
+            if ( !v43 || (OutdoorCamera::Project(v43), v45 = sr_4254D2(v44), (v12->uNumVertices = v45) == 0) )
+              goto LABEL_71;
+            v12->_48276F_sr();
+            v46 = 0;
+            if ( (signed int)v12->uNumVertices > 0 )
+            {
+              v47 = (char *)&array_508690[0].vWorldViewProjY;
+              do
+              {
+                LODWORD(v61) = *((int *)v47 - 1);
+                v48 = v61 + 6.7553994e15;
+                v65 = LODWORD(v48);
+                dword_50B638[v46] = LODWORD(v48);
+                LODWORD(v58) = *(int *)v47;
+                v49 = v58 + 6.7553994e15;
+                v59 = LODWORD(v49);
+                v47 += 48;
+                dword_50B570[v46++] = LODWORD(v49);
+              }
+              while ( v46 < (signed int)v12->uNumVertices );
+            }
+          }
+          else
+          {
+            v50 = sr_4254D2(v26);
+            v12->uNumVertices = v50;
+            if ( !v50 )
+              goto LABEL_71;
+            sr_sub_4829B9(
+              &array_73D150[*(char *)(v3 + 298)],
+              &array_73D150[*(char *)(v3 + 299)],
+              &array_73D150[*(char *)(v3 + 300)],
+              v12,
+              0);
+            v51 = 0;
+            if ( (signed int)v12->uNumVertices > 0 )
+            {
+              v52 = (char *)&array_508690[0].vWorldViewProjY;
+              do
+              {
+                LODWORD(v62) = *((int *)v52 - 1);
+                v53 = v62 + 6.7553994e15;
+                v60 = LODWORD(v53);
+                dword_50B638[v51] = LODWORD(v53);
+                LODWORD(v72) = *(int *)v52;
+                v54 = v72 + 6.7553994e15;
+                v70 = LODWORD(v54);
+                v52 += 48;
+                dword_50B570[v51++] = LODWORD(v54);
+              }
+              while ( v51 < (signed int)v12->uNumVertices );
+            }
+          }
+        }
+        sr_sub_486B4E_push_outdoor_edges(array_508690, dword_50B638, dword_50B570, v12);
+      }
+LABEL_72:
+      ++v79;
+      v1 = v78;
+      v3 += 308;
+      v76 = v3;
+      if ( v79 >= v68 )
+        goto LABEL_73;
+    }
+  }
+  return result;
+}
+// 50B570: using guessed type int dword_50B570[];
+// 50B638: using guessed type int dword_50B638[];
+// 73C830: using guessed type char static_sub_004789DE_byte_73C830__init_flag;
+
+//----- (00479089) --------------------------------------------------------
+bool __fastcall IsBModelVisible(unsigned int uModelID, int *unused)
+{
+  BSPModel *v2; // eax@1
+  int v3; // edi@1
+  int v4; // ebx@1
+  int v5; // ST28_4@1
+  int v6; // ecx@1
+  int v7; // ebx@3
+  int v8; // eax@3
+  int v9; // eax@3
+  int v10; // ebx@3
+  signed int v11; // esi@6
+  int v12; // esi@8
+  bool result; // eax@9
+  unsigned int v14; // [sp+Ch] [bp-20h]@1
+  int v15; // [sp+Ch] [bp-20h]@5
+  int *v16; // [sp+10h] [bp-1Ch]@1
+  int v17; // [sp+1Ch] [bp-10h]@1
+  int v18; // [sp+20h] [bp-Ch]@1
+  int v19; // [sp+20h] [bp-Ch]@3
+  int angle; // [sp+24h] [bp-8h]@1
+  int v21; // [sp+28h] [bp-4h]@1
+  int v22; // [sp+28h] [bp-4h]@3
+
+  v16 = unused;
+  angle = (signed int)(pOutdoorCamera->uCameraFovInDegrees << 11) / 360 >> 1;
+  v14 = uModelID;
+  v2 = &pOutdoor->pBModels[uModelID];
+  v3 = v2->vBoundingCenter.x - pIndoorCamera->pos.x;
+  v4 = v2->vBoundingCenter.y - pIndoorCamera->pos.y;
+  v5 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY);
+  v21 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY - stru_5C6E00->uIntegerHalfPi);
+  v18 = stru_5C6E00->SinCos(pIndoorCamera->sRotationX);
+  stru_5C6E00->SinCos(pIndoorCamera->sRotationX - stru_5C6E00->uIntegerHalfPi);
+  v6 = v5;
+  v17 = v3 * v5 + v4 * v21;
+  if ( pIndoorCamera->sRotationX )
+    v17 = (unsigned __int64)(v17 * (signed __int64)v18) >> 16;
+  v19 = v4 * v6 - v3 * v21;
+  v7 = abs(v4);
+  v8 = abs(v3);
+  v9 = sub_4621DA(v8, v7, 0);
+  v10 = v14 * 188;
+  v22 = v9;
+  *v16 = 0;
+  if ( v9 < pOutdoor->pBModels[v14].sBoundingRadius + 256 )
+    *v16 = 1;
+  v15 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+  if ( v19 >= 0 )
+    v11 = ((unsigned __int64)(v15 * (signed __int64)v17) >> 16)
+        - ((unsigned __int64)(stru_5C6E00->SinCos(angle) * (signed __int64)v19) >> 16);
+  else
+    v11 = ((unsigned __int64)(stru_5C6E00->SinCos(angle) * (signed __int64)v19) >> 16)
+        + ((unsigned __int64)(v15 * (signed __int64)v17) >> 16);
+  v12 = v11 >> 16;
+  if ( v22 <= pOutdoorCamera->shading_dist_mist + 2048 )
+  {
+    if ( abs(v12) > *(int *)((char *)&pOutdoor->pBModels->sBoundingRadius + v10) + 512 )
+    {
+      result = v12 < 0;
+      LOBYTE(result) = v12 >= 0;
+    }
+    else
+    {
+      result = 1;
+    }
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+
+
+
+//----- (00479295) --------------------------------------------------------
+int stru148::_479295()
+{
+  stru148 *v1; // edi@1
+  ODMFace *v2; // esi@1
+  int v3; // ecx@4
+  int v4; // eax@4
+  int v5; // edx@4
+  int v6; // ST14_4@5
+  int v7; // ST04_4@5
+  stru149 *v8; // ecx@5
+  Vec3_int_ thisa; // [sp+Ch] [bp-10h]@8
+  int v11; // [sp+18h] [bp-4h]@4
+
+  v1 = this;
+  v2 = this->pODMFace;
+  if ( !v2->pFacePlane.vNormal.z )
+  {
+    v3 = v2->pFacePlane.vNormal.x;
+    v4 = -v2->pFacePlane.vNormal.y;
+LABEL_9:
+    v5 = 0;
+    v11 = 65536;
+    goto LABEL_5;
+  }
+  if ( (v2->pFacePlane.vNormal.x || v2->pFacePlane.vNormal.y) && abs(v2->pFacePlane.vNormal.z) < 59082 )
+  {
+    thisa.x = -v2->pFacePlane.vNormal.y;
+    thisa.y = v2->pFacePlane.vNormal.x;
+    thisa.z = 0;
+    thisa.Normalize_float();
+    v4 = thisa.x;
+    v3 = thisa.y;
+    goto LABEL_9;
+  }
+  v3 = 0;
+  v4 = 65536;
+  v11 = 0;
+  v5 = -65536;
+LABEL_5:
+  v6 = v11;
+  v1->sTextureDeltaU = v2->sTextureDeltaU;
+  v7 = v3;
+  v8 = v1->ptr_38;
+  v1->sTextureDeltaV = v2->sTextureDeltaV;
+  v8->_48616B(v4, v7, 0, 0, v5, v6);
+  return 1;
+}
+
+//----- (00479332) --------------------------------------------------------
+int Render::OnOutdoorRedrawSW()
+{
+  signed int result; // eax@1
+  unsigned int v1; // edi@1
+  char *v2; // esi@2
+  char v3; // cl@3
+  double v4; // st7@4
+  float v5; // ST34_4@6
+  double v6; // ST24_8@6
+  int v7; // eax@6
+  unsigned int v8; // eax@11
+  signed int v9; // eax@13
+  Vec3_float_ *v10; // eax@14
+  double v11; // st7@17
+  float v12; // ST34_4@19
+  double v13; // ST1C_8@19
+  float v14; // [sp+4h] [bp-34h]@1
+  float v15; // [sp+8h] [bp-30h]@1
+  float v16; // [sp+Ch] [bp-2Ch]@1
+
+  v14 = (double)pOutdoor->vSunlight.x * 0.000015258789;
+  result = 0;
+  v1 = (unsigned int)&array_77EC08[pOutdoorCamera->numStru148s];
+  v15 = (double)pOutdoor->vSunlight.y * 0.000015258789;
+  v16 = (double)pOutdoor->vSunlight.z * 0.000015258789;
+  if ( v1 > (unsigned int)array_77EC08 )
+  {
+    v2 = (char *)&array_77EC08[0].pODMFace;
+    while ( 1 )
+    {
+      v3 = v2[5];
+      if ( v3 == 5 )
+        break;
+      if ( v3 == 1 )
+      {
+        v9 = pTerrainNormalIndices[((*((int *)v2 - 9) >> 15) & 1)
+                                 + 2 * ((unsigned __int8)v2[9] + ((unsigned __int8)v2[8] << 7))];
+        if ( v9 > (signed int)(uNumTerrainNormals - 1) )
+          v10 = 0;
+        else
+          v10 = &pTerrainNormals[v9];
+        if ( v10 )
+        {
+          v11 = -(v16 * v10->z + v15 * v10->y + v14 * v10->x);
+          if ( v11 < 0.0 )
+            v11 = 0.0;
+          v12 = v11 * 31.0;
+          v13 = v12 + 6.7553994e15;
+          v2[4] = 31 - LOBYTE(v13);
+        }
+        else
+        {
+          v2[4] = 0;
+        }
+        if ( v2[4] < 0 )
+          v2[4] = 0;
+        goto LABEL_23;
+      }
+LABEL_24:
+      v2 += 268;
+      if ( (unsigned int)(v2 - 84) >= v1 )
+        return result;
+    }
+    v4 = (double)(signed int)(((unsigned __int64)(**(int **)v2 * (signed __int64)-pOutdoor->vSunlight.x) >> 16)
+                            + ((unsigned __int64)(*(int *)(*(int *)v2 + 4) * (signed __int64)-pOutdoor->vSunlight.y) >> 16)
+                            + ((unsigned __int64)(*(int *)(*(int *)v2 + 8) * (signed __int64)-pOutdoor->vSunlight.z) >> 16))
+       * 0.000015258789;
+    if ( v4 < 0.0 )
+      v4 = 0.0;
+    v5 = v4 * 31.0;
+    v6 = v5 + 6.7553994e15;
+    v7 = (int)(v2 + 4);
+    v2[4] = 31 - LOBYTE(v6);
+    if ( (char)(31 - LOBYTE(v6)) < 0 )
+      *(char *)v7 = 0;
+    if ( *(char *)v7 > 31 )
+      *(char *)v7 = 31;
+    if ( *(char *)(*(int *)v2 + 29) & 0x40 )
+    {
+      v8 = pTextureFrameTable->GetFrameTexture(
+             *((short *)v2 - 4),
+             pEventTimer->uTotalGameTimeElapsed);
+      *((int *)v2 - 6) = v8 != -1 ? (int)&pBitmaps_LOD->pTextures[v8] : 0;
+    }
+LABEL_23:
+    result = 1;
+    goto LABEL_24;
+  }
+  return result;
+}
+
+//----- (00479543) --------------------------------------------------------
+void Render::DrawSkyD3D()
+{
+  int v0; // esi@2
+  int v1; // eax@2
+  double v2; // st7@2
+  double v3; // st6@2
+  double v4; // st5@2
+  double v5; // st4@2
+  double v6; // st7@2
+  char *v7; // esi@3
+  int v8; // eax@4
+  int v9; // eax@4
+  int v10; // ebx@4
+  signed __int64 v11; // qax@6
+  double v12; // st7@6
+  int v13; // edi@6
+  int v14; // ecx@6
+  int v15; // eax@8
+  int v16; // eax@12
+  signed __int64 v17; // qtt@13
+  signed int v18; // ecx@13
+  Texture *v19; // eax@15
+  double v20; // st6@15
+  double v21; // st7@15
+  double v22; // st6@15
+  unsigned __int8 v23; // sf@15
+  unsigned __int8 v24; // of@15
+  stru148 _this; // [sp+14h] [bp-150h]@1
+  double v26; // [sp+120h] [bp-44h]@4
+  float v27; // [sp+128h] [bp-3Ch]@4
+  float v28; // [sp+12Ch] [bp-38h]@2
+  int v29; // [sp+130h] [bp-34h]@4
+  int v30; // [sp+134h] [bp-30h]@1
+  int v31; // [sp+138h] [bp-2Ch]@2
+  int v32; // [sp+13Ch] [bp-28h]@6
+  int v33; // [sp+140h] [bp-24h]@2
+  float v34; // [sp+144h] [bp-20h]@1
+  int v35; // [sp+148h] [bp-1Ch]@4
+  double v36; // [sp+14Ch] [bp-18h]@2
+  int v37; // [sp+154h] [bp-10h]@8
+  int v38; // [sp+158h] [bp-Ch]@1
+  int v39; // [sp+15Ch] [bp-8h]@4
+  int v40; // [sp+160h] [bp-4h]@7
+
+  v30 = (signed __int64)((double)(pOutdoorCamera->int_fov_rad * pIndoorCamera->pos.z)
+                       / ((double)pOutdoorCamera->int_fov_rad + 8192.0)
+                       + (double)pViewport->uScreenCenterY);
+  v34 = cos((double)pIndoorCamera->sRotationX * 0.0030664064) * (double)pOutdoorCamera->shading_dist_mist;
+  v38 = (signed __int64)((double)pViewport->uScreenCenterY
+                       - (double)pOutdoorCamera->int_fov_rad
+                       / (v34 + 0.0000001)
+                       * (sin((double)pIndoorCamera->sRotationX * 0.0030664064)
+                        * (double)-pOutdoorCamera->shading_dist_mist
+                        - (double)pIndoorCamera->pos.z));
+  _this._48607B(&stru_8019C8);
+  _this.ptr_38->_48694B();
+  _this.uTileBitmapID = LOWORD(pOutdoor->uSky_TextureID);
+  _this.pTexture = (Texture *)(SLOWORD(pOutdoor->uSky_TextureID) != -1 ? (int)&pBitmaps_LOD->pTextures[SLOWORD(pOutdoor->uSky_TextureID)] : 0);
+  if ( _this.pTexture )
+  {
+    v0 = pIndoorCamera->sRotationX;
+    _this.field_58 = 0;
+    _this.uNumVertices = 4;
+    _this.v_18.x = -stru_5C6E00->SinCos(pIndoorCamera->sRotationX - stru_5C6E00->uIntegerHalfPi + 16);
+    _this.v_18.y = 0;
+    v1 = stru_5C6E00->SinCos(v0 + 16);
+    v2 = (double)(signed int)pViewport->uViewportX;
+    _this.v_18.z = -v1;
+    array_50AC10[0].vWorldViewProjX = v2;
+    v3 = (double)(signed int)pViewport->uViewportY;
+    array_50AC10[0].vWorldViewProjY = v3;
+    array_50AC10[1].vWorldViewProjX = v2;
+    v4 = (double)v38;
+    _this.sTextureDeltaU = 224 * pMiscTimer->uTotalGameTimeElapsed;
+    _this.sTextureDeltaV = 224 * pMiscTimer->uTotalGameTimeElapsed;
+    v28 = v4;
+    array_50AC10[1].vWorldViewProjY = v4;
+    v5 = (double)(signed int)pViewport->uViewportZ;
+    array_50AC10[2].vWorldViewProjX = v5;
+    v38 = pViewport->uViewportZ - pViewport->uViewportX;
+    _this.field_24 = 0x2000000u;
+    array_50AC10[2].vWorldViewProjY = v4;
+    array_50AC10[3].vWorldViewProjX = v5;
+    array_50AC10[3].vWorldViewProjY = v3;
+    v36 = (double)(pViewport->uViewportZ - pViewport->uViewportX) * 0.5;
+    v6 = tan(0.6457717418670654);
+    v31 = 0;
+    v33 = 65536 / (signed int)(signed __int64)(v36 / v6 + 0.5);
+    if ( (signed int)_this.uNumVertices <= 0 )
+      goto LABEL_16;
+    v7 = (char *)&array_50AC10[0].vWorldViewProjY;
+    while ( 1 )
+    {
+      LODWORD(v27) = *(int *)v7;
+      v26 = v27 + 6.7553994e15;
+      v29 = LODWORD(v26);
+      v38 = _this.ptr_38->field_14;
+      v39 = (unsigned __int64)(v38 * (signed __int64)(v33 * (v30 - LODWORD(v26)))) >> 16;
+      v8 = v39 + _this.ptr_38->field_C;
+      v39 = v33 * (v30 - LODWORD(v26));
+      v35 = v8;
+      v38 = _this.ptr_38->field_20;
+      v39 = (unsigned __int64)(v38 * (signed __int64)(v33 * (v30 - LODWORD(v26)))) >> 16;
+      HIDWORD(v36) = v39 + _this.ptr_38->field_18;
+      v38 = _this.v_18.z;
+      v9 = (unsigned __int64)(_this.v_18.z * (signed __int64)(v33 * (v30 - LODWORD(v26)))) >> 16;
+      v10 = _this.v_18.x + v9;
+      v39 = _this.v_18.x + v9;
+      if ( _this.v_18.x + v9 > 0 )
+      {
+        v10 = 0;
+        v39 = 0;
+      }
+      v11 = (signed __int64)*((float *)v7 - 1);
+      v38 = v10;
+      v12 = *(float *)v7 - 1.0;
+      v13 = v33 * (pViewport->uScreenCenterX - v11);
+      LODWORD(v34) = -_this.field_24;
+      v32 = (signed __int64)v12;
+      v14 = v33 * (v30 - v32);
+      while ( 1 )
+      {
+        v40 = v14;
+        if ( !v10 )
+          goto LABEL_12;
+        v37 = abs(SLODWORD(v34) >> 14);
+        v15 = abs(v10);
+        if ( v37 <= v15 || v32 <= (signed int)pViewport->uViewportY )
+        {
+          if ( v39 <= 0 )
+            break;
+        }
+        v14 = v40;
+LABEL_12:
+        v37 = _this.v_18.z;
+        v16 = (unsigned __int64)(_this.v_18.z * (signed __int64)v14) >> 16;
+        --v32;
+        v14 += v33;
+        v10 = _this.v_18.x + v16;
+        v39 = _this.v_18.x + v16;
+        v38 = _this.v_18.x + v16;
+      }
+      LODWORD(v17) = LODWORD(v34) << 16;
+      HIDWORD(v17) = SLODWORD(v34) >> 16;
+      v40 = v17 / v38;
+      v18 = v17 / v38;
+      if ( v18 < 0 )
+        v18 = pOutdoorCamera->shading_dist_mist;
+      v40 = v13;
+      v37 = _this.ptr_38->field_10;
+      v40 = v13;
+      v37 = v35 + ((unsigned __int64)(v37 * (signed __int64)v13) >> 16);
+      v35 = _this.ptr_38->field_1C;
+      HIDWORD(v36) += (unsigned __int64)(v35 * (signed __int64)v13) >> 16;
+      v35 = 224 * pMiscTimer->uTotalGameTimeElapsed
+          + ((signed int)((unsigned __int64)(v37 * (signed __int64)v18) >> 16) >> 3);
+      v40 = (unsigned __int64)(SHIDWORD(v36) * (signed __int64)v18) >> 16;
+      v19 = _this.pTexture;
+      HIDWORD(v36) = _this.pTexture->uTextureWidth;
+      v7 += 48;
+      v20 = (double)SHIDWORD(v36) * 65536.0;
+      HIDWORD(v36) = 224 * pMiscTimer->uTotalGameTimeElapsed + (v40 >> 3);
+      ++v31;
+      *((float *)v7 - 10) = (double)v35 / v20;
+      v21 = (double)SHIDWORD(v36);
+      HIDWORD(v36) = v19->uTextureHeight;
+      v22 = (double)SHIDWORD(v36);
+      HIDWORD(v36) = v18 >> 16;
+      v24 = _this.uNumVertices > v31;
+      v23 = ((v31 - _this.uNumVertices) & 0x80000000u) != 0;
+      *((float *)v7 - 9) = v21 / (v22 * 65536.0);
+      *((float *)v7 - 16) = (double)pOutdoorCamera->shading_dist_mist;
+      *((float *)v7 - 11) = 1.0 / (double)SHIDWORD(v36);
+      if ( !(v23 ^ v24) )
+      {
+LABEL_16:
+        pRenderer->DrawFan(
+          _this.uNumVertices,
+          &_this,
+          pBitmaps_LOD->pHardwareTextures[(signed __int16)_this.uTileBitmapID]);
+        array_50AC10[0].vWorldViewProjY = v28;
+        array_50AC10[1].vWorldViewProjY = array_50AC10[1].vWorldViewProjY + 30.0;
+        array_50AC10[2].vWorldViewProjY = array_50AC10[2].vWorldViewProjY + 30.0;
+        array_50AC10[3].vWorldViewProjY = v28;
+        pRenderer->DrawFan(
+          _this.uNumVertices,
+          &_this,
+          pBitmaps_LOD->pHardwareTextures[(signed __int16)_this.uTileBitmapID]);
+        return;
+      }
+    }
+  }
+}
+
+
+//----- (00479A53) --------------------------------------------------------
+void __fastcall _479A53_draw_some_blv_poly(unsigned int uNumVertices, unsigned int uFaceID)
+{
+  BLVFace *pFace; // esi@1
+  unsigned int v3; // edi@1
+  PolygonType v4; // al@1
+  double v5; // st7@3
+  signed __int64 v6; // qax@3
+  PolygonType v7; // cl@3
+  int v8; // esi@7
+  int v9; // eax@7
+  unsigned int v10; // eax@7
+  double v11; // st6@7
+  int v12; // edx@7
+  int v13; // eax@7
+  char *v14; // esi@8
+  void *v15; // ecx@9
+  int v16; // eax@9
+  int v17; // edi@9
+  double v18; // st7@9
+  signed int v19; // ebx@9
+  void *v20; // ecx@9
+  int v21; // ebx@11
+  int v22; // eax@14
+  signed __int64 v23; // qtt@16
+  double v24; // st7@16
+  unsigned __int8 v25; // sf@16
+  unsigned __int8 v26; // of@16
+  Render *v27; // ecx@17
+  double v28; // st7@20
+  char *v29; // ebx@20
+  char *v30; // edx@20
+  unsigned __int8 v31; // c0@21
+  unsigned __int8 v32; // c3@21
+  double v33; // st6@23
+  char *v34; // esi@30
+  const void *v35; // ecx@31
+  int v36; // eax@31
+  const void *v37; // edi@31
+  signed __int64 v38; // qax@31
+  int v39; // ecx@31
+  int v40; // ebx@33
+  int v41; // eax@36
+  signed __int64 v42; // qtt@39
+  int v43; // eax@39
+  char v44; // zf@39
+  double v45; // st7@39
+  double v46; // st7@39
+  unsigned int v47; // edx@40
+  double v48; // st7@41
+  RenderVertexSoft *v49; // ebx@41
+  void *v50; // edi@43
+  double v51; // st7@46
+  RenderVertexSoft *v52; // edx@46
+  void *v53; // edi@48
+  char *v54; // ebx@52
+  unsigned int v55; // eax@53
+  unsigned int v56; // eax@55
+  int v57; // ST10_4@55
+  Texture *v58; // eax@55
+  signed int v59; // [sp-4h] [bp-178h]@17
+  stru148 *v60; // [sp+0h] [bp-174h]@17
+  IDirect3DTexture2 *v61; // [sp+4h] [bp-170h]@17
+  stru148 v62; // [sp+14h] [bp-160h]@6
+  unsigned int v63; // [sp+120h] [bp-54h]@7
+  double v64; // [sp+124h] [bp-50h]@7
+  unsigned int v65; // [sp+128h] [bp-4Ch]@1
+  unsigned int v66; // [sp+12Ch] [bp-48h]@7
+  float v67; // [sp+130h] [bp-44h]@7
+  __int64 v68; // [sp+134h] [bp-40h]@3
+  __int64 v69; // [sp+13Ch] [bp-38h]@3
+  int v70; // [sp+144h] [bp-30h]@3
+  int X; // [sp+148h] [bp-2Ch]@9
+  int v72; // [sp+14Ch] [bp-28h]@7
+  float v73; // [sp+150h] [bp-24h]@16
+  unsigned int v74; // [sp+154h] [bp-20h]@3
+  RenderVertexSoft *v75; // [sp+158h] [bp-1Ch]@3
+  float v76; // [sp+15Ch] [bp-18h]@9
+  int v77; // [sp+160h] [bp-14h]@9
+  int v78; // [sp+164h] [bp-10h]@7
+  void *v79; // [sp+168h] [bp-Ch]@9
+  float v80; // [sp+16Ch] [bp-8h]@3
+  const void *v81; // [sp+170h] [bp-4h]@7
+
+  __debugbreak();
+
+  pFace = &pIndoor->pFaces[uFaceID];
+  v65 = uFaceID;
+  v3 = uNumVertices;
+  v4 = pFace->uPolygonType;
+  if ( v4 == POLYGON_InBetweenFloorAndWall || v4 == POLYGON_Floor )
+  {
+    if ( (signed int)uNumVertices > 0 )
+    {
+      v54 = (char *)&array_507D30[0].u;
+      LODWORD(v80) = uNumVertices;
+      do
+      {
+        v69 = (GetTickCount() >> 5) - pBLVRenderParams->vPartyPos.x;
+        *(float *)v54 = (double)v69 + *(float *)v54;
+        *(float *)v54 = *(float *)v54 * 0.25;
+        v55 = GetTickCount();
+        v54 += 48;
+        v44 = LODWORD(v80)-- == 1;
+        v68 = pBLVRenderParams->vPartyPos.y + (v55 >> 5);
+        *((float *)v54 - 11) = ((double)v68 + *((float *)v54 - 11)) * 0.25;
+      }
+      while ( !v44 );
+      uFaceID = v65;
+    }
+    v56 = 8 * uFaceID;
+    LOBYTE(v56) = 8 * uFaceID | 6;
+    v57 = v56;
+    v58 = pFace->GetTexture();
+    pRenderer->DrawIndoorPolygon(v3, pFace, pBitmaps_LOD->pHardwareTextures[pFace->uBitmapID], v58, v57, -1, 0);
+    return;
+  }
+  HIDWORD(v69) = pIndoorCamera->sRotationX;
+  HIDWORD(v68) = pIndoorCamera->pos.z;
+  *(float *)&v74 = (double)pBLVRenderParams->uViewportCenterY;
+  v70 = (signed __int64)((double)(pBLVRenderParams->field_40 * pBLVRenderParams->vPartyPos.z)
+                       / (((double)pBLVRenderParams->field_40 + 16192.0)
+                        * 65536.0)
+                       + *(float *)&v74);
+  v5 = (double)pIndoorCamera->sRotationX * 0.0030664064;
+  *(float *)&v75 = v5;
+  v80 = cos(v5) * 16192.0;
+  v6 = (signed __int64)(*(float *)&v74
+                      - (double)pBLVRenderParams->field_40
+                      / ((v80 + 0.0000001)
+                       * 65535.0)
+                      * (sin(*(float *)&v75) * -16192.0 - (double)SHIDWORD(v68)));
+  v7 = pFace->uPolygonType;
+  if ( v7 == 4 || v7 == 3 )
+    v70 = v6;
+  stru_8019C8._48653D(65536, 0, 0, 0, 65536, 0);
+  v62._48607B(&stru_8019C8);
+  v62.uTileBitmapID = pFace->uBitmapID;
+  v62.pTexture = (Texture *)((signed __int16)v62.uTileBitmapID != -1 ? (int)&pBitmaps_LOD->pTextures[(signed __int16)v62.uTileBitmapID] : 0);
+  if ( !v62.pTexture )
+    return;
+  v8 = pBLVRenderParams->sPartyRotX;
+  v62.field_58 = 0;
+  v62.uNumVertices = v3;
+  v9 = stru_5C6E00->SinCos(pBLVRenderParams->sPartyRotX - stru_5C6E00->uIntegerHalfPi + 16);
+  v62.v_18.y = 0;
+  v62.v_18.x = -v9;
+  v62.v_18.z = -stru_5C6E00->SinCos(v8 + 16);
+  v10 = pBLVRenderParams->uViewportZ - pBLVRenderParams->uViewportX;
+  memcpy(&array_507D30[v3], array_507D30, sizeof(array_507D30[v3]));
+  LODWORD(v80) = v10;
+  v62.field_24 = 33554432;
+  v64 = (double)(signed int)v10 * 0.5;
+  v72 = 65536 / (signed int)(signed __int64)(v64 / tan(0.6457717418670654) + 0.5);
+  LODWORD(v80) = v62.pTexture->uTextureWidth;
+  v11 = 1.0 / (double)SLODWORD(v80);
+  LODWORD(v80) = v62.pTexture->uTextureHeight;
+  v12 = v62.pTexture->uWidthMinus1;
+  v13 = v62.pTexture->uHeightMinus1;
+  v67 = v11;
+  v63 = 224 * pMiscTimer->uTotalGameTimeElapsed & v13;
+  v66 = 224 * pMiscTimer->uTotalGameTimeElapsed & v12;
+  v78 = 0;
+  v81 = 0;
+  *((float *)&v68 + 1) = 1.0 / (double)SLODWORD(v80);
+  if ( (signed int)v62.uNumVertices <= 0 )
+  {
+LABEL_17:
+    v61 = pBitmaps_LOD->pHardwareTextures[(signed __int16)v62.uTileBitmapID];
+    v27 = pRenderer;
+    v60 = &v62;
+    v59 = v62.uNumVertices;
+    goto LABEL_18;
+  }
+  v14 = (char *)&array_507D30[0].vWorldViewProjY;
+  while ( 2 )
+  {
+    v15 = (void *)(v72 * (v70 - (unsigned __int64)(signed __int64)*(float *)v14));
+    LODWORD(v80) = v62.ptr_38->field_14;
+    v77 = (unsigned __int64)(SLODWORD(v80) * (signed __int64)(signed int)v15) >> 16;
+    v16 = v77 + v62.ptr_38->field_C;
+    v77 = (int)v15;
+    v74 = v16;
+    LODWORD(v80) = v62.ptr_38->field_20;
+    v77 = (unsigned __int64)(SLODWORD(v80) * (signed __int64)(signed int)v15) >> 16;
+    v79 = v15;
+    v75 = (RenderVertexSoft *)(v77 + v62.ptr_38->field_18);
+    LODWORD(v80) = v62.v_18.z;
+    v79 = (void *)((unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v15) >> 16);
+    v17 = v72 * (pBLVRenderParams->uViewportCenterX - (unsigned __int64)(signed __int64)*((float *)v14 - 1));
+    v18 = *(float *)v14 - 1.0;
+    v19 = -v62.field_24;
+    v77 = -v62.field_24;
+    X = (int)((char *)v79 + v62.v_18.x);
+    LODWORD(v76) = (signed __int64)v18;
+    v20 = (void *)(v72 * (v70 - LODWORD(v76)));
+    while ( 1 )
+    {
+      v79 = v20;
+      if ( !X )
+        goto LABEL_14;
+      v21 = abs(v19 >> 14);
+      if ( v21 <= abs(X) )
+        break;
+      if ( SLODWORD(v76) <= (signed int)pViewport->uViewportY )
+        break;
+      v19 = v77;
+      v20 = v79;
+LABEL_14:
+      LODWORD(v80) = v62.v_18.z;
+      v79 = (void *)((unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v20) >> 16);
+      v22 = (unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v20) >> 16;
+      --LODWORD(v76);
+      v20 = (char *)v20 + v72;
+      X = v22 + v62.v_18.x;
+      v78 = 1;
+    }
+    if ( !v78 )
+    {
+      LODWORD(v23) = v77 << 16;
+      HIDWORD(v23) = v77 >> 16;
+      v79 = (void *)(v23 / X);
+      v77 = v17;
+      LODWORD(v80) = v62.ptr_38->field_10;
+      v77 = v17;
+      LODWORD(v76) = v74 + ((unsigned __int64)(SLODWORD(v80) * (signed __int64)v17) >> 16);
+      LODWORD(v80) = v62.ptr_38->field_1C;
+      v75 = (RenderVertexSoft *)((char *)v75 + ((unsigned __int64)(SLODWORD(v80) * (signed __int64)v17) >> 16));
+      v77 = (unsigned __int64)(SLODWORD(v76) * v23 / X) >> 16;
+      LODWORD(v73) = (unsigned __int64)((signed int)v75 * v23 / X) >> 16;
+      v14 += 48;
+      LODWORD(v80) = v66 + ((signed int)((unsigned __int64)(SLODWORD(v76) * v23 / X) >> 16) >> 4);
+      v81 = (char *)v81 + 1;
+      v24 = (double)SLODWORD(v80) * 0.000015259022;
+      LODWORD(v80) = v63 + ((signed int)((unsigned __int64)((signed int)v75 * v23 / X) >> 16) >> 4);
+      v26 = __OFSUB__((int)v81, v62.uNumVertices);
+      v25 = (signed int)((char *)v81 - v62.uNumVertices) < 0;
+      *((float *)v14 - 10) = v24 * v67;
+      *((float *)v14 - 9) = (double)SLODWORD(v80) * 0.000015259022 * *((float *)&v68 + 1);
+      *((float *)v14 - 11) = 65536.0 / (double)(signed int)v79;
+      if ( !(v25 ^ v26) )
+        goto LABEL_17;
+      continue;
+    }
+    break;
+  }
+  LODWORD(v73) = 0;
+  v80 = v76;
+  if ( (signed int)v62.uNumVertices > 0 )
+  {
+    v28 = (double)SLODWORD(v76);
+    LODWORD(v76) = (int)(char *)array_50AC10 + 28;
+    v29 = (char *)&array_50AC10[0].vWorldViewProjX;
+    v30 = (char *)&array_507D30[1].vWorldViewProjY;
+    v79 = array_50AC10;
+    v81 = array_507D30;
+    v78 = v62.uNumVertices;
+    do
+    {
+      v31 = v28 < *((float *)v30 - 12);
+      v32 = v28 == *((float *)v30 - 12);
+      ++LODWORD(v73);
+      memcpy(v79, v81, 0x30u);
+      v79 = (char *)v79 + 48;
+      LODWORD(v76) += 48;
+      v29 += 48;
+      if ( v31 | v32 || v28 >= *(float *)v30 )
+      {
+        if ( v28 >= *((float *)v30 - 12) || v28 <= *(float *)v30 )
+          goto LABEL_28;
+        v33 = (*((float *)v30 - 1) - *((float *)v30 - 13)) * v28 / (*(float *)v30 - *((float *)v30 - 12))
+            + *((float *)v30 - 1);
+      }
+      else
+      {
+        v33 = (*((float *)v30 - 13) - *((float *)v30 - 1)) * v28 / (*((float *)v30 - 12) - *(float *)v30)
+            + *((float *)v30 - 13);
+      }
+      *(float *)v29 = v33;
+      v79 = (char *)v79 + 48;
+      v29 += 48;
+      ++LODWORD(v73);
+      *(unsigned int *)LODWORD(v76) = v28;
+      LODWORD(v76) += 48;
+LABEL_28:
+      v81 = (char *)v81 + 48;
+      v30 += 48;
+      --v78;
+    }
+    while ( v78 );
+  }
+  if ( SLODWORD(v73) <= 0 )
+    goto LABEL_40;
+  v34 = (char *)&array_50AC10[0].vWorldViewProjY;
+  v65 = v77 >> 14;
+  HIDWORD(v69) = LODWORD(v73);
+  do
+  {
+    v35 = (const void *)(v72 * (v70 - (unsigned __int64)(signed __int64)*(float *)v34));
+    v78 = v62.ptr_38->field_14;
+    v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v35) >> 16);
+    v36 = (int)((char *)v81 + v62.ptr_38->field_C);
+    v81 = v35;
+    v74 = v36;
+    v78 = v62.ptr_38->field_20;
+    v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v35) >> 16);
+    v78 = (int)v35;
+    v75 = (RenderVertexSoft *)((char *)v81 + v62.ptr_38->field_18);
+    v81 = (const void *)v62.v_18.z;
+    v78 = (unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v35) >> 16;
+    v37 = (const void *)(v72
+                       * (pBLVRenderParams->uViewportCenterX - (unsigned __int64)(signed __int64)*((float *)v34 - 1)));
+    v38 = (signed __int64)(*(float *)v34 - 1.0);
+    v81 = 0;
+    LODWORD(v76) = v38;
+    v39 = v72 * (v70 - v38);
+    while ( 1 )
+    {
+      v78 = v39;
+      if ( !X )
+        goto LABEL_36;
+      v40 = abs(X);
+      if ( abs((signed __int64)v65) <= v40 )
+        break;
+      if ( SLODWORD(v76) <= (signed int)pViewport->uViewportY )
+        break;
+      v39 = v78;
+LABEL_36:
+      v78 = v62.v_18.z;
+      v41 = (unsigned __int64)(v62.v_18.z * (signed __int64)v39) >> 16;
+      --LODWORD(v76);
+      v39 += v72;
+      X = v41 + v62.v_18.x;
+      v81 = (const void *)1;
+    }
+    if ( v81 )
+    {
+      v79 = (void *)v62.v_18.z;
+      v78 = 2 * LODWORD(v76);
+      v81 = (const void *)((unsigned __int64)(v62.v_18.z
+                                            * (signed __int64)(signed int)(signed __int64)(((double)v70
+                                                                                          - ((double)(2 * LODWORD(v76))
+                                                                                           - *(float *)v34))
+                                                                                         * (double)v72)) >> 16);
+      X = (int)((char *)v81 + v62.v_18.x);
+    }
+    LODWORD(v42) = v77 << 16;
+    HIDWORD(v42) = v77 >> 16;
+    v79 = (void *)(v42 / X);
+    v81 = v37;
+    v78 = v62.ptr_38->field_10;
+    v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16);
+    v43 = v74 + ((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16);
+    v74 = (unsigned int)v37;
+    LODWORD(v76) = v43;
+    v78 = v62.ptr_38->field_1C;
+    v75 = (RenderVertexSoft *)((char *)v75 + ((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16));
+    v74 = (unsigned __int64)(v43 * v42 / X) >> 16;
+    v81 = (const void *)((unsigned __int64)((signed int)v75 * v42 / X) >> 16);
+    v34 += 48;
+    v78 = v66 + ((signed int)v74 >> 4);
+    v44 = HIDWORD(v69)-- == 1;
+    v45 = (double)v78 * 0.000015259022;
+    v78 = v63 + ((signed int)((unsigned __int64)((signed int)v75 * v42 / X) >> 16) >> 4);
+    *((float *)v34 - 10) = v45 * v67;
+    *((float *)v34 - 9) = (double)v78 * 0.000015259022 * *((float *)&v68 + 1);
+    v46 = (double)(signed int)v79;
+    *((float *)v34 - 16) = 0.000015258789 * v46;
+    *((float *)v34 - 11) = 65536.0 / v46;
+  }
+  while ( !v44 );
+LABEL_40:
+  v47 = 0;
+  if ( SLODWORD(v73) > 0 )
+  {
+    v48 = (double)SLODWORD(v80);
+    v75 = array_507D30;
+    v49 = array_50AC10;
+    HIDWORD(v69) = LODWORD(v73);
+    do
+    {
+      if ( v48 >= v49->vWorldViewProjY )
+      {
+        v50 = v75;
+        ++v47;
+        ++v75;
+        memcpy(v50, v49, 0x30u);
+      }
+      ++v49;
+      --HIDWORD(v69);
+    }
+    while ( HIDWORD(v69) );
+  }
+  v62.uNumVertices = v47;
+  pRenderer->_4A2ED5(v47, &v62, pBitmaps_LOD->pHardwareTextures[(signed __int16)v62.uTileBitmapID]);
+  *(float *)&v74 = 0.0;
+  if ( SLODWORD(v73) > 0 )
+  {
+    v51 = (double)SLODWORD(v80);
+    v75 = array_507D30;
+    v52 = array_50AC10;
+    v80 = v73;
+    do
+    {
+      if ( v51 <= v52->vWorldViewProjY )
+      {
+        v53 = v75;
+        ++v74;
+        ++v75;
+        memcpy(v53, v52, 0x30u);
+      }
+      ++v52;
+      --LODWORD(v80);
+    }
+    while ( v80 != 0.0 );
+  }
+  v62.uNumVertices = v74;
+  v61 = pBitmaps_LOD->pHardwareTextures[(signed __int16)v62.uTileBitmapID];
+  v60 = &v62;
+  v59 = v74;
+  v27 = pRenderer;
+LABEL_18:
+  v27->_4A2ED5(v59, v60, v61);
+}
+
+//----- (0047A384) --------------------------------------------------------
+void ODM_LoadAndInitialize(const char *pLevelFilename, OutdoorCamera *thisa)
+{
+  int v2; // ebx@3
+  unsigned int v3; // eax@3
+  MapInfo *v4; // edi@4
+  //int v5; // eax@8
+  //SpawnPointMM7 *v6; // edx@14
+  size_t v7; // eax@19
+  char *v8; // eax@19
+  char *v9; // eax@21
+  char Source[120]; // [sp+Ch] [bp-84h]@19
+  const char *pFilename; // [sp+84h] [bp-Ch]@1
+  //unsigned int v12; // [sp+88h] [bp-8h]@12
+  //int v13; // [sp+8Ch] [bp-4h]@11
+
+  pFilename = pLevelFilename;
+  thisa->AllocSoftwareDrawBuffers();
+  pOutdoorCamera->_485F64();
+  pWeather->bRenderSnow = 0;
+  pRenderer->ClearZBuffer(0, 479);
+  thisa = (OutdoorCamera *)1;
+  GetAlertStatus();
+  if ( qword_A750D8 )
+    qword_A750D8 = 0i64;
+  v2 = pMapStats->GetMapInfo(pCurrentMapName);
+  v3 = 0;
+  if ( v2 )
+  {
+    v4 = &pMapStats->pInfos[v2];
+    v3 = v4->uRespawnIntervalDays;
+  }
+  else
+  {
+    v4 = (MapInfo *)thisa;
+  }
+  day_attrib &= 0xFFFFFFFEu;
+  dword_6BE13C_uCurrentlyLoadedLocationID = v2;
+  pOutdoor->Initialize(
+    pFilename,
+    (unsigned int)(signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 0x3C / 0x3C / 0x18 + 1,
+    v3,
+    (int)&thisa);
+  if ( !(BYTE1(dword_6BE364_game_settings_1) & 0x20) )
+  {
+    InitializeActors();
+    InitializeLayingItems();
+  }
+  BYTE1(dword_6BE364_game_settings_1) &= 0xDFu;
+  //v5 = 0;
+  if ( !v2 )
+    thisa = 0;
+  if ( thisa == (OutdoorCamera *)1 )
+  {
+    //v13 = 0;
+    for (uint i = 0; i < pOutdoor->uNumSpawnPoints; ++i)
+    {
+      //v12 = 0;
+      //while ( 1 )
+      //{
+      auto spawn = pOutdoor->pSpawnPoints + i;
+        //v6 = &pOutdoor->pSpawnPoints[v12 / 0x18];
+      if (spawn->uKind == 3 )
+        SpawnEncounter(v4, spawn, 0, 0, 0);
+      else
+        v4->SpawnRandomTreasure(spawn);
+        //++v13;
+        //v12 += 24;
+        //if ( v13 >= (signed int)pOutdoor->uNumSpawnPoints )
+        //  break;
+        //v5 = 0;
+      //}
+    }
+    RespawnGlobalDecorations();
+  }
+  pOutdoor->PrepareDecorations();
+  pOutdoor->_47F223_LooksLikeGenerateMonsterLoot();
+  pOutdoor->InitalizeActors(v2);
+  pOutdoor->MessWithLUN();
+  v7 = strlen("levels\\");
+  strcpy(Source, &pFilename[v7]);
+  strcpy(pOutdoor->pLevelFilename, Source);
+  pWeather->Initialize();
+  pIndoorCamera->sRotationY = pParty->sRotationY;
+  pIndoorCamera->sRotationX = pParty->sRotationX;
+  pOutdoorCamera->RotationToInts();
+  pOutdoor->UpdateSunlightVectors();
+  pOutdoorCamera->int_fov_rad = (signed __int64)pIndoorCamera->flt_1C_fov;
+  pOutdoorCamera->int_fov_rad_inv = (signed __int64)pIndoorCamera->flt_20_inv_1C;
+  v8 = (char *)&array_77EC08[0].ptr_38;
+  do
+  {
+    *(int *)v8 = (int)&stru_8019C8;
+    v8 += 268;
+  }
+  while ( (signed int)v8 < (signed int)&unk_801A00 );
+  v9 = (char *)&array_77EC08[0].prolly_tail;
+  do
+  {
+    *((int *)v9 - 1) = 0;
+    *(int *)v9 = 0;
+    *((int *)v9 - 5) = 0;
+    v9 += 268;
+  }
+  while ( (signed int)v9 < (signed int)&unk_801A0C );
+  MM7Initialization();
+}
+
+
+
+//----- (0047A825) --------------------------------------------------------
+bool LevelDecoration::_47A825()
+{
+  bool v1; // ebx@1
+  LevelDecoration *v2; // edi@1
+
+  v1 = 0;
+  v2 = this;
+  if ( pParty->uCurrentHour >= 1 || (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 178) )
+  {
+    v1 = 0;
+  }
+  else
+  {
+    if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 164)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 165)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 166)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 167)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 168)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 169)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 170)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 171)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 172)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 173)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 174)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 175)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 176)
+      && (unsigned __int16)_449B57_test_bit(pParty->_award_bits, 177) )
+    {
+      v1 = 1;
+      LOBYTE(v2->field_2) &= 0xDFu;
+      return v1;
+    }
+  }
+  LOBYTE(v2->field_2) |= 0x20u;
+  return v1;
+}
+
+
+
+//----- (0047BC6F) --------------------------------------------------------
+unsigned __int16 *__fastcall GetBillboardPalette(RenderBillboard *a1, int a2, signed int a3, int a4)
+{
+  int v4; // ebx@1
+  int v6; // edx@4
+  int v7; // ecx@5
+  signed int v8; // eax@6
+  signed __int64 v9; // qtt@11
+  signed int v10; // eax@12
+  int v11; // esi@17
+  signed __int64 v12; // qtt@19
+  double v13; // ST10_8@19
+  int v14; // edi@25
+  signed int v15; // edx@26
+  signed __int64 v16; // qtt@29
+  signed int v17; // eax@30
+  int v18; // [sp+10h] [bp-8h]@1
+  float a3a; // [sp+20h] [bp+8h]@19
+
+  v4 = a2;
+  v18 = a2;
+  if ( pParty->field_1613C )
+    return PaletteManager::Get(a2);
+  if ( !pWeather->field_FA0 )
+  {
+    if ( day_attrib & 1 )
+    {
+      v14 = day_fogrange_1 << 16;
+      if ( a3 >= day_fogrange_1 << 16 )
+      {
+        if ( a3 <= day_fogrange_2 << 16 )
+        {
+          LODWORD(v16) = (a3 - v14) << 16;
+          HIDWORD(v16) = (a3 - v14) >> 16;
+          v15 = (unsigned __int64)(27 * v16 / ((day_fogrange_2 - day_fogrange_1) << 16)) >> 16;
+        }
+        else
+        {
+          v15 = 27;
+        }
+      }
+      else
+      {
+        v15 = 0;
+      }
+      v17 = _43F55F_get_billboard_light_level(a1, v15);
+      if ( v17 > 27 )
+        v17 = 27;
+      if ( !a3 )
+        v17 = 27;
+      v7 = v18;
+      v6 = v17;
+      return (unsigned __int16 *)PaletteManager::Get_Mist_or_Red_LUT(v7, v6, 1);
+    }
+    v11 = a4;
+    if ( a4 < 0 )
+      v11 = 0;
+    LODWORD(v12) = a3 << 16;
+    HIDWORD(v12) = a3 >> 16;
+    a3a = (double)(signed int)(((unsigned __int64)(11 * v12 / (pOutdoorCamera->shading_dist_shade << 16)) >> 16) + 20)
+        * pOutdoor->fFogDensity;
+    v13 = a3a + 6.7553994e15;
+    v10 = _43F55F_get_billboard_light_level(a1, LODWORD(v13) + v11);
+    if ( v10 > 27 )
+      v10 = 27;
+    if ( v10 < a4 )
+      v10 = a4;
+    if ( v10 > pOutdoor->field_CBC_terrain_triangles_shade_type )
+      v10 = pOutdoor->field_CBC_terrain_triangles_shade_type;
+    return PaletteManager::Get_Dark_or_Red_LUT(v4, v10, 1);
+  }
+  v6 = 0;
+  if ( pWeather->field_FA0 == 1 )
+  {
+    v8 = 67108864;
+    if ( (signed __int64)pParty->pPartyBuffs[16].uExpireTime > 0 )
+      v8 = pParty->pPartyBuffs[16].uPower << 26;
+    if ( a3 <= v8 )
+    {
+      if ( a3 > 0 )
+      {
+        LODWORD(v9) = a3 << 16;
+        HIDWORD(v9) = a3 >> 16;
+        v6 = (unsigned __int64)(27 * v9 / v8) >> 16;
+      }
+    }
+    else
+    {
+      v6 = 27;
+    }
+    v10 = _43F55F_get_billboard_light_level(a1, v6);
+    if ( v10 > 27 || !a3 )
+      v10 = 27;
+    return PaletteManager::Get_Dark_or_Red_LUT(v4, v10, 1);
+  }
+  v7 = 0;
+  return (unsigned __int16 *)PaletteManager::Get_Mist_or_Red_LUT(v7, v6, 1);
+}
+// 6BE030: using guessed type int day_attrib;
+// 6BE040: using guessed type int day_fogrange_1;
+// 6BE044: using guessed type int day_fogrange_2;
+
+
+
+
+
+
+
+
+//----- (0047BEB1) --------------------------------------------------------
+int __fastcall sr_sub_47BEB1(signed int a1, stru148 *a2, int terrain_gamma, int a4, int *a5, int *a6, int a7, int a8)
+{
+  stru148 *v8; // ebx@1
+  signed int v9; // edx@1
+  int v10; // eax@5
+  signed int v11; // eax@9
+  signed int v12; // eax@15
+  signed __int64 v13; // qtt@21
+  int *v14; // ecx@30
+  int *v15; // edi@30
+  int v16; // ebx@32
+  signed __int64 v17; // qtt@37
+  double v18; // ST10_8@37
+  double v19; // ST10_8@38
+  int v20; // edi@39
+  int result; // eax@46
+  int *v22; // eax@48
+  signed int v23; // edx@51
+  signed __int64 v24; // qtt@51
+  int v25; // ecx@51
+  signed int v26; // [sp+14h] [bp-4h]@1
+  float v27; // [sp+28h] [bp+10h]@37
+  float v28; // [sp+28h] [bp+10h]@38
+  int v29; // [sp+2Ch] [bp+14h]@37
+
+  v8 = a2;
+  v9 = a1;
+  v26 = a1;
+  if ( pParty->field_1613C )
+  {
+    *a5 = -1;
+    *a6 = -1;
+    *(char *)a7 = 1;
+LABEL_46:
+    result = a8;
+    *(char *)a8 = 0;
+    return result;
+  }
+  if ( a1 < 0 )
+  {
+    v26 = v8->field_34 << 16;
+    v9 = v8->field_34 << 16;
+  }
+  v10 = pWeather->field_FA0;
+  if ( bUnderwater == 1 )
+    v10 = 0;
+  if ( !v10 )
+  {
+    if ( !(day_attrib & 1) && !bUnderwater )
+    {
+      v14 = a5;
+      v15 = a6;
+      if ( !v9 )
+      {
+        *a5 = 31;
+        *a6 = -1;
+      }
+      v16 = v8->field_58 - terrain_gamma;
+      if ( v16 >= 0 )
+      {
+        if ( v16 > 27 )
+          v16 = 27;
+      }
+      else
+      {
+        v16 = 0;
+      }
+      *a6 = 27;
+      if ( a4 )
+      {
+        v28 = pOutdoor->fFogDensity * 27.0;
+        v19 = v28 + 6.7553994e15;
+        v29 = LODWORD(v19);
+      }
+      else
+      {
+        LODWORD(v17) = v9 << 16;
+        HIDWORD(v17) = v9 >> 16;
+        v27 = (double)(signed int)(((unsigned __int64)(v17 / (pOutdoorCamera->shading_dist_shade << 16) * (31 - *a6)) >> 16)
+                                 + *a6)
+            * pOutdoor->fFogDensity;
+        v18 = v27 + 6.7553994e15;
+        v29 = LODWORD(v18);
+      }
+      *v14 = v16 + v29;
+      v20 = *v15;
+      if ( v16 + v29 > v20 )
+        *v14 = v20;
+      if ( *v14 < v16 )
+        *v14 = v16;
+      if ( *v14 > pOutdoor->field_CBC_terrain_triangles_shade_type )
+        *v14 = pOutdoor->field_CBC_terrain_triangles_shade_type;
+      goto LABEL_45;
+    }
+    if ( v9 >= day_fogrange_1 << 16 )
+    {
+      if ( v9 <= day_fogrange_2 << 16 )
+      {
+        v23 = v9 - (day_fogrange_1 << 16);
+        LODWORD(v24) = v23 << 16;
+        HIDWORD(v24) = v23 >> 16;
+        v25 = (unsigned __int64)(27 * v24 / ((day_fogrange_2 - day_fogrange_1) << 16)) >> 16;
+        v22 = a5;
+        *a5 = v25;
+        if ( v25 > 27 )
+          goto LABEL_54;
+        v9 = v26;
+      }
+      else
+      {
+        v22 = a5;
+        *a5 = 27;
+      }
+    }
+    else
+    {
+      v22 = a5;
+      *a5 = 0;
+    }
+    if ( v9 )
+    {
+LABEL_55:
+      if ( a4 )
+        *v22 = 31;
+      *a6 = 31;
+      *(char *)a7 = 0;
+      goto LABEL_59;
+    }
+LABEL_54:
+    *v22 = 27;
+    goto LABEL_55;
+  }
+  if ( v10 == 1 )
+  {
+    v11 = 1;
+    if ( byte_4D864C && BYTE1(pGame->uFlags) & 0x10 )
+    {
+      v12 = 0;
+    }
+    else
+    {
+      if ( (signed __int64)pParty->pPartyBuffs[16].uExpireTime > 0 )
+      {
+        if ( (signed __int64)pParty->pPartyBuffs[16].uExpireTime <= 0 )
+          v11 = 0;
+        else
+          v11 = pParty->pPartyBuffs[16].uPower;
+      }
+      v12 = v11 << 26;
+    }
+    if ( a4 )
+      goto LABEL_24;
+    if ( v9 <= v12 )
+    {
+      if ( v9 > 0 )
+      {
+        LODWORD(v13) = v9 << 16;
+        HIDWORD(v13) = v9 >> 16;
+        v9 = v26;
+        *a5 = (unsigned __int64)(27 * v13 / v12) >> 16;
+      }
+      if ( *a5 > 27 )
+        goto LABEL_24;
+    }
+    else
+    {
+      *a5 = 27;
+    }
+    if ( v9 )
+    {
+LABEL_25:
+      if ( v8->field_32 & 4 )
+        *a5 = 27;
+      *a6 = 27;
+LABEL_45:
+      *(char *)a7 = 0;
+      goto LABEL_46;
+    }
+LABEL_24:
+    *a5 = 27;
+    goto LABEL_25;
+  }
+  *a5 = -1;
+  *a6 = -1;
+  *(char *)a7 = 1;
+LABEL_59:
+  result = a8;
+  *(char *)a8 = 1;
+  return result;
+}
+// 4D864C: using guessed type char byte_4D864C;
+// 6BE030: using guessed type int day_attrib;
+// 6BE040: using guessed type int day_fogrange_1;
+// 6BE044: using guessed type int day_fogrange_2;
+// 6BE3C4: using guessed type char bUnderwater;
+
+//----- (0047C178) --------------------------------------------------------
+void *__fastcall sr_sub_47C178(signed int a1, stru148 *a2, int terrain_gamma, int a4)
+{
+  stru148 *v4; // esi@1
+  void *result; // eax@2
+  int v6; // [sp+4h] [bp-8h]@3
+  int v7; // [sp+8h] [bp-4h]@3
+
+  v4 = a2;
+  if ( pParty->field_1613C )
+  {
+    result = PaletteManager::Get(a2->pTexture->palette_id2);
+  }
+  else
+  {
+    sr_sub_47BEB1(a1, a2, terrain_gamma, a4, &v6, &v7, (int)((char *)&terrain_gamma + 3), (int)((char *)&a4 + 3));
+    result = sr_sub_47C1CA(v4, SBYTE3(a4), v6, v7);
+  }
+  return result;
+}
+
+//----- (0047C1CA) --------------------------------------------------------
+void *__fastcall sr_sub_47C1CA(stru148 *a1, char a2, int a3, signed int a4)
+{
+  stru148 *v4; // esi@1
+  void *result; // eax@2
+  int v6; // edx@3
+  int v7; // ecx@8
+  int a3a; // [sp+4h] [bp-8h]@1
+  char v9; // [sp+8h] [bp-4h]@1
+
+  v9 = a2;
+  v4 = a1;
+  a3a = 1;
+  if ( pParty->field_1613C )
+  {
+    result = PaletteManager::Get(a1->pTexture->palette_id2);
+  }
+  else
+  {
+    v6 = pGame->_44EC23(a1, &a3a, a4);
+    if ( v6 == -1 )
+      v6 = a3;
+    if ( v9 == 1 )
+    {
+      if ( v6 != -1 || a4 != -1 )
+      {
+        v7 = v4->pTexture->palette_id2;
+      }
+      else
+      {
+        v6 = 0;
+        v7 = 0;
+      }
+      result = PaletteManager::Get_Mist_or_Red_LUT(v7, v6, a3a);
+    }
+    else
+    {
+      result = PaletteManager::Get_Dark_or_Red_LUT(v4->pTexture->palette_id2, v6, a3a);
+    }
+  }
+  return result;
+}
+
+//----- (0047C24C) --------------------------------------------------------
+unsigned __int16 *__fastcall sr_sub_47C24C_get_palette(BLVFace *a1, int a2, int a3, char a4)
+{
+  int v4; // esi@1
+  int v5; // eax@2
+  int a3a; // [sp+4h] [bp-4h]@1
+
+  v4 = a2;
+  a3a = 1;
+  if ( a4 )
+  {
+    v5 = pGame->_44ED0A(a1, &a3a, 31);
+    if ( v5 != -1 )
+      a3 = v5;
+  }
+  return PaletteManager::Get_Dark_or_Red_LUT(v4, a3, a3a);
+}
+
+//----- (0047C28C) --------------------------------------------------------
+char *__fastcall sr_sub_47C28C_get_palette(stru148 *a1, char a2, signed int a3, signed int a4)
+{
+  stru148 *v4; // esi@1
+  char *result; // eax@2
+  signed int v6; // eax@3
+  int v7; // ecx@8
+  int a2a; // [sp+4h] [bp-8h]@1
+  char v9; // [sp+8h] [bp-4h]@1
+
+  v9 = a2;
+  v4 = a1;
+  a2a = 1;
+  if ( pParty->field_1613C )
+  {
+    result = (char *)pPaletteManager->field_199600_palettes[a1->pTexture->palette_id2];
+  }
+  else
+  {
+    v6 = pGame->_44EC23(a1, &a2a, a4);
+    if ( v6 != -1 )
+      a3 = v6;
+    if ( v9 == 1 )
+    {
+      if ( a3 != -1 || a4 != -1 )
+        v7 = v4->pTexture->palette_id2;
+      else
+        v7 = 0;
+      result = (char *)PaletteManager::_47C30E_get_palette(v7, a2a);
+    }
+    else
+    {
+      result = (char *)PaletteManager::_47C33F_get_palette(v4->pTexture->palette_id2, a2a);
+    }
+  }
+  return result;
+}
+
+// 4D864C: using guessed type char byte_4D864C;
+
+
+//----- (0047C370) --------------------------------------------------------
+unsigned int __cdecl GetLevelFogColor()
+{
+  unsigned int result; // eax@2
+  signed __int64 v1; // qax@5
+  int v2; // eax@6
+
+  if ( bUnderwater )
+  {
+    result = 0xFF258F5Cu;
+  }
+  else
+  {
+    if ( day_attrib & 1 )
+    {
+      if ( pWeather->field_FA0 )
+      {
+        v2 = -(pWeather->field_FA0 != 1);
+        result = (v2 & 0xE0E0E1) - 0xE0E0E1;
+      }
+      else
+      {
+        v1 = (signed __int64)((1.0 - pOutdoor->fFogDensity) * 200.0 + pOutdoor->fFogDensity * 31.0);
+        result = v1 | (((unsigned int)v1 | (((unsigned int)v1 | 0xFFFFFF00) << 8)) << 8);
+      }
+    }
+    else
+    {
+      result = 0;
+    }
+  }
+  return result;
+}
+// 6BE030: using guessed type int day_attrib;
+// 6BE3C4: using guessed type char bUnderwater;
+
+//----- (0047C3D7) --------------------------------------------------------
+int __fastcall sub_47C3D7_get_fog_related_stuff(int a1, int a2, float a3)
+{
+  int v3; // ecx@1
+  double v5; // st7@10
+  signed int v6; // esi@10
+  signed int v7; // ecx@11
+  double v8; // st6@12
+  double v9; // st7@15
+  double v10; // st6@16
+  float v11; // ST14_4@17
+  double v12; // ST08_8@17
+
+  v3 = pWeather->field_FA0;
+  if ( bUnderwater == 1 )
+    v3 = 0;
+  if ( pParty->field_1613C || !(day_attrib & 1) && !bUnderwater )
+    return 0xFF000000u;
+  if ( v3 )
+  {
+    if ( v3 != 1 )
+      return 0;
+    v5 = (double)day_fogrange_1;
+    v6 = 216;
+    if ( a3 < v5 )
+      goto LABEL_11;
+    v8 = (double)day_fogrange_2;
+    if ( a3 > v8 )
+    {
+LABEL_13:
+      v7 = v6;
+      goto LABEL_19;
+    }
+    v7 = (signed __int64)((a3 - v5) / (v8 - v5) * 216.0);
+  }
+  else
+  {
+    v9 = (double)day_fogrange_1;
+    v6 = 216;
+    if ( a3 < v9 )
+    {
+LABEL_11:
+      v7 = 0;
+      goto LABEL_19;
+    }
+    v10 = (double)day_fogrange_2;
+    if ( a3 > v10 )
+      goto LABEL_13;
+    v11 = (a3 - v9) * 216.0 / (v10 - v9);
+    v12 = v11 + 6.7553994e15;
+    v7 = LODWORD(v12);
+  }
+  if ( v7 > v6 )
+  {
+LABEL_20:
+    v7 = v6;
+    goto LABEL_21;
+  }
+LABEL_19:
+  if ( a3 == 0.0 )
+    goto LABEL_20;
+LABEL_21:
+  if ( a2 )
+    v7 = 248;
+  return (-1 - v7) << 24;
+}
+// 6BE030: using guessed type int day_attrib;
+// 6BE040: using guessed type int day_fogrange_1;
+// 6BE044: using guessed type int day_fogrange_2;
+// 6BE3C4: using guessed type char bUnderwater;
+
+//----- (0047C4FC) --------------------------------------------------------
+signed int __fastcall GetActorTintColor(int a1, int a2, float a3, int a4, RenderBillboard *a5)
+{
+  int v5; // esi@1
+  signed int v6; // edx@1
+  signed int result; // eax@2
+  int v8; // eax@3
+  double v9; // st7@12
+  double v10; // ST0C_8@18
+  int v11; // ecx@28
+  signed int v12; // edi@28
+  double v13; // ST0C_8@33
+  double v14; // ST0C_8@34
+  double v15; // st7@44
+  double v16; // ST0C_8@44
+  double v17; // ST0C_8@44
+  int v18; // ST14_4@44
+  double v19; // ST0C_8@44
+  signed int v20; // [sp+10h] [bp-4h]@10
+  float a3a; // [sp+1Ch] [bp+8h]@33
+  float a3b; // [sp+1Ch] [bp+8h]@34
+  float a3c; // [sp+1Ch] [bp+8h]@44
+  float a3d; // [sp+1Ch] [bp+8h]@44
+  float a4b; // [sp+20h] [bp+Ch]@18
+  int a4a; // [sp+20h] [bp+Ch]@33
+  float a4c; // [sp+20h] [bp+Ch]@44
+  float a4d; // [sp+20h] [bp+Ch]@44
+  int a5a; // [sp+24h] [bp+10h]@44
+
+  v5 = a2;
+  v6 = 0;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+    return 8 * (31 - a1) | ((8 * (31 - a1) | ((31 - a1) << 11)) << 8);
+  v8 = pWeather->field_FA0;
+  if ( bUnderwater == 1 )
+    v8 = 0;
+  if ( pParty->field_1613C )
+    return 16711680;
+  if ( v8 )
+  {
+    if ( v8 != 1 )
+      return 0;
+    v20 = 1;
+    if ( (signed __int64)pParty->pPartyBuffs[16].uExpireTime > 0 )
+      v20 = pParty->pPartyBuffs[16].uPower;
+    v9 = (double)v20 * 1024.0;
+    if ( a4 )
+      goto LABEL_19;
+    if ( a3 <= v9 )
+    {
+      if ( a3 > 0.0 )
+      {
+        a4b = a3 * 216.0 / v9;
+        v10 = a4b + 6.7553994e15;
+        v6 = LODWORD(v10);
+        if ( SLODWORD(v10) > 216 )
+          goto LABEL_19;
+      }
+    }
+    else
+    {
+      v6 = 216;
+    }
+    if ( a3 != 0.0 )
+    {
+LABEL_20:
+      if ( a5 )
+        v6 = 8 * _43F55F_get_billboard_light_level(a5, v6 >> 3);
+      if ( v6 > 216 )
+        v6 = 216;
+      return (255 - v6) | ((255 - v6) << 16) | ((255 - v6) << 8);
+    }
+LABEL_19:
+    v6 = 216;
+    goto LABEL_20;
+  }
+  if ( a3 == 0.0 )
+  {
+    result = (signed int)0xF8F8F8;
+  }
+  else
+  {
+    v11 = 8 * (a1 - v5);
+    v12 = v11;
+    if ( v11 >= 0 )
+    {
+      if ( v11 > 216 )
+        v12 = 216;
+    }
+    else
+    {
+      v12 = 0;
+    }
+    if ( a4 )
+    {
+      a3b = pOutdoor->fFogDensity * 216.0;
+      v14 = a3b + 6.7553994e15;
+      a4a = LODWORD(v14);
+    }
+    else
+    {
+      a3a = (a3 / (double)pOutdoorCamera->shading_dist_shade * 32.0 + 216.0) * pOutdoor->fFogDensity;
+      v13 = a3a + 6.7553994e15;
+      a4a = LODWORD(v13);
+    }
+    v6 = a4a + v12;
+    if ( a5 )
+      v6 = 8 * _43F55F_get_billboard_light_level(a5, v6 >> 3);
+    if ( v6 > 216 )
+      v6 = 216;
+    if ( v6 < v12 )
+      v6 = v12;
+    if ( v6 > 8 * pOutdoor->field_CBC_terrain_triangles_shade_type )
+      v6 = 8 * pOutdoor->field_CBC_terrain_triangles_shade_type;
+    if ( !bUnderwater )
+      return (255 - v6) | ((255 - v6) << 16) | ((255 - v6) << 8);
+    v15 = (double)(255 - v6) * 0.0039215689;
+    a3c = v15;
+    a4c = v15 * 16.0;
+    v16 = a4c + 6.7553994e15;
+    a5a = LODWORD(v16);
+    a4d = a3c * 194.0;
+    v17 = a4d + 6.7553994e15;
+    v18 = LODWORD(v17);
+    a3d = a3c * 153.0;
+    v19 = a3d + 6.7553994e15;
+    result = LODWORD(v19) | ((v18 | (a5a << 8)) << 8);
+  }
+  return result;
+}
+// 6BE3C4: using guessed type char bUnderwater;
+
+
+
+
+//----- (0047F44B) --------------------------------------------------------
+int __stdcall WorldPosToGridCellX(signed int a1)
+{
+  return (a1 >> 9) + 64;
+}
+// 47F44B: using guessed type int __stdcall WorldPosToGridCellX(int);
+
+//----- (0047F458) --------------------------------------------------------
+int __stdcall WorldPosToGridCellZ(signed int a1)
+{
+  return 64 - (a1 >> 9);
+}
+
+//----- (0047F469) --------------------------------------------------------
+int __stdcall GridCellToWorldPosX(int a1)
+{
+  return (a1 - 64) << 9;
+}
+
+//----- (0047F476) --------------------------------------------------------
+int __stdcall GridCellToWorldPosZ(int a1)
+{
+  return (64 - a1) << 9;
+}
+
+//----- (0047F4D3) --------------------------------------------------------
+void __fastcall sub_47F4D3(int band1, int band2, int band3)
+{
+  int v3; // edi@1
+  //stru220 *v4; // esi@1
+  double v5; // ST2C_8@3
+  double v6; // st7@3
+  //double v7; // [sp+18h] [bp-28h]@3
+  //double v8; // [sp+20h] [bp-20h]@2
+  int v9; // [sp+34h] [bp-Ch]@1
+  int v10; // [sp+38h] [bp-8h]@1
+  //signed int band3a; // [sp+48h] [bp+8h]@2
+
+  v9 = band2 * 512;
+  pOutdoorCamera->outdoor_grid_band_3 = band3;
+  v10 = band1 * 512;
+  v3 = band3 * 512;
+  pOutdoorCamera->uPickDepth = band3 * 512;
+  //v4 = stru_76E5C8;                             // v4:  0 -> 65536
+  for (uint i = 0; i < 16384; ++i)
+  //do
+  {
+    auto v4 = stru_76E5C8 + i;
+    //band3a = 256;
+    //v8 = (double)(signed int)((char *)v4 + 256 - (int)stru_76E5C8);
+    for (uint j = 0; j < 128; ++j)                  // band3a: 0 -> 128
+    {
+      v5 = pow(j * 512 + 256, 2.0);
+      v6 = pow(i * 4 + 256, 2.0);
+      //*((float *)&v5 + 1) = sqrt(v6 + v5);
+      int v7 = floorf(sqrtf(v5 + v6) + 0.5f);//*((float *)&v5 + 1) + 6.7553994e15;
+      if (v7 >= v10)
+      {
+        if (v7 >= v9)
+          v4->field_0 = ((v7 >= v3) - 1) & 2;
+        else
+          v4->field_0 = 2;
+      }
+      else
+      {
+        v4->field_0 = 1;
+      }
+      //band3a += 512;
+      v4->distance = v7;
+      ++v4;
+    }
+    //while ( band3a < 65792 );
+  }
+  //while ( (signed int)v4 < (signed int)arary_77E5C8 );
+}
+
+
+
+
+//----- (004811A3) --------------------------------------------------------
+void stru148::_4811A3()
+{
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
+  pRenderer->DrawTerrainPolygon(uNumVertices, this,
+    pBitmaps_LOD->pHardwareTextures[pRenderer->pHDWaterBitmapIDs[pRenderer->field_1036A8_bitmapid]],
+    0, 0);
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1));
+  pRenderer->DrawTerrainPolygon(uNumVertices, this,
+    pBitmaps_LOD->pHardwareTextures[uTileBitmapID],
+    1, 1);
+}
+
+
+
+//----- (00481DB2) --------------------------------------------------------
+char __fastcall sr_sub_481DB2(RenderVertexSoft *a1, signed int a2, stru148 *a3)
+{
+  int v3; // eax@2
+  int v4; // esi@2
+  signed int v5; // esi@2
+  char *v6; // edi@3
+  double v7; // ST14_8@4
+  double v8; // ST0C_8@4
+  char result; // al@5
+
+  if ( a2 >= 3 )
+  {
+    v3 = a3->uTileBitmapID;
+    v4 = a3->uTileBitmapID;
+    a3->ptr_38 = &stru_8019C8;
+    a3->pTexture = (Texture *)(v4 != -1 ? (int)&pBitmaps_LOD->pTextures[v3] : 0);
+    v5 = 0;
+    if ( (signed int)a3->uNumVertices > 0 )
+    {
+      v6 = (char *)&array_508690[0].vWorldViewProjY;
+      do
+      {
+        v7 = *((float *)v6 - 1) + 6.7553994e15;
+        dword_50B638[v5] = LODWORD(v7);
+        v8 = *(float *)v6 + 6.7553994e15;
+        v6 += 48;
+        dword_50B570[v5++] = LODWORD(v8);
+      }
+      while ( v5 < (signed int)a3->uNumVertices );
+    }
+    result = sr_sub_486B4E_push_outdoor_edges(a1, dword_50B638, dword_50B570, a3);
+  }
+  return result;
+}
+// 50B570: using guessed type int dword_50B570[];
+// 50B638: using guessed type int dword_50B638[];
+
+
+
+//----- (00481E55) --------------------------------------------------------
+void OutdoorCamera::Project(unsigned int uNumVertices)
+{
+  double v1; // st7@2
+  double v2; // st6@2
+  double v3; // st5@2
+  int v4; // eax@2
+  unsigned int v5; // edx@2
+  double v6; // st4@3
+  double v7; // st3@3
+
+  if ( (signed int)uNumVertices > 0 )
+  {
+    v1 = (double)pOutdoorCamera->int_fov_rad;
+    v2 = (double)pViewport->uScreenCenterX;
+    v3 = (double)pViewport->uScreenCenterY;
+    v4 = 0;
+    v5 = uNumVertices;
+    do
+    {
+      v6 = v1 * array_507D30[v4].flt_20;
+      v7 = v6 * array_507D30[v4].vWorldViewPosition.y;
+      memcpy(&array_50AC10[v4], &array_507D30[v4], sizeof(array_50AC10[v4]));
+      array_50AC10[v4].vWorldViewProjX = v2 - v7;
+      array_50AC10[v4].vWorldViewProjY = v3 - v6 * array_507D30[v4].vWorldViewPosition.z;
+      ++v4;
+      --v5;
+    }
+    while ( v5 );
+  }
+}
+
+//----- (00481EB7) --------------------------------------------------------
+void __cdecl ResetStru148s()
+{
+  int v0; // ecx@1
+  char *v1; // eax@2
+
+  v0 = pOutdoorCamera->numStru148s;
+  if ( pOutdoorCamera->numStru148s > 0 )
+  {
+    v1 = (char *)&array_77EC08[0].prolly_tail;
+    do
+    {
+      *((int *)v1 - 1) = 0;
+      *(int *)v1 = 0;
+      *((int *)v1 - 5) = 0;
+      v1 += 268;
+      --v0;
+    }
+    while ( v0 );
+  }
+}
+
+//----- (00481ED9) --------------------------------------------------------
+void __cdecl sub_481ED9_MessWithOutdoorCamera()
+{
+  stru_8019C8._48616B(65536, 0, 0, 0, 65536, 0);
+  pOutdoorCamera->numStru148s = 0;
+  pOutdoorCamera->uNumEdges = 0;
+  pOutdoorCamera->uNumSpans = 0;
+  pOutdoorCamera->uNumSurfs = 0;
+  pOutdoorCamera->uNumBillboards = 0;
+  pOutdoorCamera->field_44 = 0;
+}
+
+//----- (00481EFA) --------------------------------------------------------
+bool __fastcall sub_481EFA(RenderVertexSoft *a1, RenderVertexSoft *a2, RenderVertexSoft *a3, RenderVertexSoft *a4, int a5)
+{
+  RenderVertexSoft *v5; // esi@1
+  RenderVertexSoft *v6; // edx@1
+  bool v7; // edi@2
+  bool v8; // ecx@5
+  bool v9; // esi@8
+  bool v10; // eax@11
+  double v11; // st7@14
+  signed int v12; // esi@15
+  signed int v13; // edx@18
+  signed int v14; // ecx@21
+  signed int v15; // eax@24
+  RenderVertexSoft *v17; // [sp+Ch] [bp-8h]@1
+
+  v5 = a2;
+  v6 = a1;
+  v17 = v5;
+  v7 = a1->vWorldViewPosition.x < 8.0;
+  v8 = v5->vWorldViewPosition.x < 8.0;
+  v9 = a3->vWorldViewPosition.x < 8.0;
+  v10 = a4->vWorldViewPosition.x < 8.0;
+  return !(v8 & v9 & v10 & v7)
+      && ((v11 = (double)pOutdoorCamera->shading_dist_mist, v11 > v6->vWorldViewPosition.x) ? (v12 = 0) : (v12 = 1),
+          v11 > v17->vWorldViewPosition.x ? (v13 = 0) : (v13 = 1),
+          v11 > a3->vWorldViewPosition.x ? (v14 = 0) : (v14 = 1),
+          v11 > a4->vWorldViewPosition.x ? (v15 = 0) : (v15 = 1),
+          !(v13 & v14 & v15 & v12));
+}
+
+//----- (00481FC9) --------------------------------------------------------
+int __fastcall sub_481FC9(RenderVertexSoft *_ECX, RenderVertexSoft *a2, RenderVertexSoft *a3, stru148 *a4)
+{
+  __debugbreak();
+  return 0;
+  /*signed int result; // eax@5
+  __int64 v11; // ST08_8@6
+  __int64 v12; // ST08_8@6
+  __int64 v13; // ST08_8@6
+  __int64 v14; // ST08_8@6
+
+  __asm { fld     dword ptr [ecx+8] }
+  _ESI = a2;
+  _EDX = a3;
+  __asm { fcomp   dword ptr [esi+8] }
+  _EDI = a4;
+  __asm { fnstsw  ax }
+  if ( !__SETP__(HIBYTE(_AX) & 0x44, 0) )
+  {
+    __asm
+    {
+      fld     dword ptr [esi+8]
+      fcomp   dword ptr [edx+8]
+      fnstsw  ax
+    }
+    if ( !__SETP__(HIBYTE(_AX) & 0x44, 0) )
+      *(int *)&a4->flags |= 0x10u;
+  }
+  __asm
+  {
+    fld     dword ptr [ecx+0Ch]
+    fsub    dword ptr [esi+0Ch]
+    fstp    [ebp+var_C]
+    fld     dword ptr [ecx+10h]
+    fsub    dword ptr [esi+10h]
+    fstp    [ebp+var_14]
+    fld     dword ptr [ecx+14h]
+    fsub    dword ptr [esi+14h]
+    fstp    [ebp+arg_0]
+    fld     dword ptr [edx+0Ch]
+    fsub    dword ptr [esi+0Ch]
+    fstp    [ebp+var_10]
+    fld     dword ptr [edx+10h]
+    fsub    dword ptr [esi+10h]
+    fstp    [ebp+var_8]
+    fld     dword ptr [edx+14h]
+    fsub    dword ptr [esi+14h]
+    fstp    [ebp+var_4]
+    fld     dword ptr [ecx]
+    fsub    dword ptr [esi]
+    fld     dword ptr [ecx+4]
+    fsub    dword ptr [esi+4]
+    fld     dword ptr [ecx+8]
+    fsub    dword ptr [esi+8]
+    fld     dword ptr [edx]
+    fsub    dword ptr [esi]
+    fld     dword ptr [edx+4]
+    fsub    dword ptr [esi+4]
+    fld     dword ptr [edx+8]
+    fsub    dword ptr [esi+8]
+    fstp    [ebp+arg_4]
+    fld     st
+    fmul    st, st(3)
+    fld     [ebp+arg_4]
+    fmul    st, st(5)
+    fsubp   st(1), st
+    fild    pIndoorCamera->pos.x
+    fsub    dword ptr [esi]
+    fmulp   st(1), st
+    fld     [ebp+arg_4]
+    fmul    st, st(6)
+    fld     st(3)
+    fmul    st, st(5)
+    fsubp   st(1), st
+    fild    pIndoorCamera->pos.y
+    fsub    dword ptr [esi+4]
+    fmulp   st(1), st
+    faddp   st(1), st
+    fld     st(2)
+    fmul    st, st(5)
+    fld     st(2)
+    fmul    st, st(7)
+    fsubp   st(1), st
+    fild    pIndoorCamera->pos.z
+    fsub    dword ptr [esi+8]
+    fmulp   st(1), st
+    faddp   st(1), st
+    fcomp   ds:flt_4D84E8
+    fstp    st
+    fstp    st
+    fstp    st
+    fnstsw  ax
+    fstp    st
+    fstp    st
+  }
+  if ( __SETP__(HIBYTE(_AX) & 0x41, 0) )
+  {
+    __asm
+    {
+      fld     [ebp+var_4]
+      fmul    [ebp+var_14]
+      fld     [ebp+var_8]
+      fmul    [ebp+arg_0]
+      fsubp   st(1), st
+      fstp    [ebp+arg_4]
+      fld     [ebp+arg_4]
+      fadd    ds:flt_4D87D0
+      fstp    [ebp+var_20]
+      fld     [ebp+var_10]
+      fmul    [ebp+arg_0]
+      fld     [ebp+var_4]
+      fmul    [ebp+var_C]
+    }
+    _EDI->v_18.x = v11;
+    __asm
+    {
+      fsubp   st(1), st
+      fstp    [ebp+arg_4]
+      fld     [ebp+arg_4]
+      fadd    ds:flt_4D87D0
+      fstp    [ebp+var_20]
+      fld     [ebp+var_8]
+      fmul    [ebp+var_C]
+      fld     [ebp+var_10]
+      fmul    [ebp+var_14]
+    }
+    _EDI->v_18.y = v12;
+    __asm
+    {
+      fsubp   st(1), st
+      fstp    [ebp+arg_4]
+      fld     [ebp+arg_4]
+      fadd    ds:flt_4D87D0
+      fstp    [ebp+var_20]
+    }
+    _EDI->v_18.z = v13;
+    stru148::_486089_normalize_v_18(_EDI);
+    __asm
+    {
+      fild    dword ptr [edi+18h]
+      fmul    dword ptr [esi+0Ch]
+      fchs
+      fild    dword ptr [edi+1Ch]
+      fmul    dword ptr [esi+10h]
+      fsubp   st(1), st
+      fild    dword ptr [edi+20h]
+      fmul    dword ptr [esi+14h]
+      fsubp   st(1), st
+      fstp    [ebp+arg_4]
+      fld     [ebp+arg_4]
+      fadd    ds:flt_4D87D0
+      fstp    [ebp+var_20]
+    }
+    _EDI->field_24 = v14;
+    result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;*/
+}
+
+
+
+//----- (004823F4) --------------------------------------------------------
+bool __fastcall GetTerrainHeightsAroundParty(int a1, int a2)
+{
+  unsigned int v2; // ebx@1
+  unsigned int v3; // edi@1
+  int v4; // eax@1
+  int v6; // esi@5
+  int v7; // ecx@6
+  int v8; // edx@6
+  int v9; // eax@6
+  int v10; // esi@10
+  int v11; // [sp+14h] [bp-8h]@1
+  int v12; // [sp+18h] [bp-4h]@1
+
+  v12 = a1;
+  v11 = a2;
+  v2 = WorldPosToGridCellX(a1);
+  v3 = WorldPosToGridCellZ(v11) - 1;
+  dword_76D568_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v2);
+  dword_76D56C_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v2 + 1);
+  dword_76D570_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v2 + 1);
+  dword_76D574_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v2);
+  dword_76D558_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v3);
+  dword_76D55C_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v3);
+  dword_76D560_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v3 + 1);
+  dword_76D564_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v3 + 1);
+  dword_76D548_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v2, v3);
+  dword_76D54C_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v2 + 1, v3);
+  dword_76D550_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v2 + 1, v3 + 1);
+  v4 = pOutdoor->DoGetHeightOnTerrain(v2, v3 + 1);
+  dword_76D554_terrain_cell_world_pos_around_party_y = v4;
+  if ( dword_76D548_terrain_cell_world_pos_around_party_y == dword_76D54C_terrain_cell_world_pos_around_party_y
+    && dword_76D54C_terrain_cell_world_pos_around_party_y == dword_76D550_terrain_cell_world_pos_around_party_y
+    && dword_76D550_terrain_cell_world_pos_around_party_y == v4 )
+    return 0;
+  v6 = abs(v12 - dword_76D568_terrain_cell_world_pos_around_party_x);
+  if ( abs(dword_76D558_terrain_cell_world_pos_around_party_z - v11) >= v6 )
+  {
+    v7 = dword_76D554_terrain_cell_world_pos_around_party_y;
+    v8 = dword_76D550_terrain_cell_world_pos_around_party_y;
+    v9 = dword_76D548_terrain_cell_world_pos_around_party_y;
+  }
+  else
+  {
+    v7 = dword_76D54C_terrain_cell_world_pos_around_party_y;
+    v8 = dword_76D548_terrain_cell_world_pos_around_party_y;
+    v9 = dword_76D550_terrain_cell_world_pos_around_party_y;
+  }
+  if ( v7 >= v8 )
+  {
+    v10 = v8;
+    if ( v8 < v9 )
+      goto LABEL_13;
+LABEL_12:
+    v10 = v9;
+    goto LABEL_13;
+  }
+  if ( v7 >= v9 )
+    goto LABEL_12;
+  v10 = v7;
+LABEL_13:
+  if ( v7 <= v8 )
+  {
+    if ( v8 > v9 )
+      v9 = v8;
+  }
+  else
+  {
+    if ( v7 > v9 )
+      v9 = v7;
+  }
+  return v9 - v10 > 512;
+}
+
+
+//----- (0048257A) --------------------------------------------------------
+int __fastcall GetTerrainHeightsAroundParty2(int a1, int a2, int *a3, int a4)
+{
+  unsigned int v4; // ebx@1
+  unsigned int v5; // edi@1
+  int result; // eax@9
+  int v7; // ebx@10
+  int v8; // ebx@11
+  int v9; // eax@11
+  int v10; // ecx@11
+  int v11; // [sp+Ch] [bp-Ch]@1
+  int v12; // [sp+10h] [bp-8h]@1
+  int v13; // [sp+10h] [bp-8h]@11
+  signed int v14; // [sp+14h] [bp-4h]@3
+  int v15; // [sp+24h] [bp+Ch]@11
+
+  v11 = a1;
+  v12 = a2;
+  v4 = WorldPosToGridCellX(a1);
+  v5 = WorldPosToGridCellZ(v12) - 1;
+  dword_76D538_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v4);
+  dword_76D53C_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v4 + 1);
+  dword_76D540_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v4 + 1);
+  dword_76D544_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v4);
+  dword_76D528_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v5);
+  dword_76D52C_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v5);
+  dword_76D530_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v5 + 1);
+  dword_76D534_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v5 + 1);
+  dword_76D518_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4, v5);
+  dword_76D51C_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4 + 1, v5);
+  dword_76D520_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4 + 1, v5 + 1);
+  dword_76D524_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4, v5 + 1);
+  *a3 = 0;
+  if ( pOutdoor->ActuallyGetSomeOtherTileInfo(v4, v5) & 2 )
+    *a3 = 1;
+  v14 = 0;
+  if ( !a4 && *a3 )
+    v14 = -60;
+  if ( dword_76D518_terrain_cell_world_pos_around_party_y != dword_76D51C_terrain_cell_world_pos_around_party_y
+    || dword_76D51C_terrain_cell_world_pos_around_party_y != dword_76D520_terrain_cell_world_pos_around_party_y
+    || dword_76D520_terrain_cell_world_pos_around_party_y != dword_76D524_terrain_cell_world_pos_around_party_y )
+  {
+    v7 = abs(v11 - dword_76D538_terrain_cell_world_pos_around_party_x);
+    if ( abs(dword_76D528_terrain_cell_world_pos_around_party_z - v12) >= v7 )
+    {
+      v8 = dword_76D524_terrain_cell_world_pos_around_party_y;
+      v9 = dword_76D520_terrain_cell_world_pos_around_party_y;
+      v10 = dword_76D518_terrain_cell_world_pos_around_party_y;
+      v15 = v11 - dword_76D544_terrain_cell_world_pos_around_party_x;
+      v13 = v12 - dword_76D534_terrain_cell_world_pos_around_party_z;
+    }
+    else
+    {
+      v8 = dword_76D51C_terrain_cell_world_pos_around_party_y;
+      v9 = dword_76D518_terrain_cell_world_pos_around_party_y;
+      v10 = dword_76D520_terrain_cell_world_pos_around_party_y;
+      v15 = dword_76D53C_terrain_cell_world_pos_around_party_x - v11;
+      v13 = dword_76D52C_terrain_cell_world_pos_around_party_z - v12;
+    }
+    result = v14
+           + v8
+           + ((unsigned __int64)(v13 * (signed __int64)((v10 - v8) << 7)) >> 16)
+           + ((unsigned __int64)(v15 * (signed __int64)((v9 - v8) << 7)) >> 16);
+  }
+  else
+  {
+    result = v14 + dword_76D518_terrain_cell_world_pos_around_party_y;
+  }
+  return result;
+}
+
+
+//----- (0048276F) --------------------------------------------------------
+void stru148::_48276F_sr()
+{
+  unsigned int v1; // ebx@1
+  float v2; // edx@2
+  double v3; // st7@2
+  char *v4; // ecx@3
+  float v5; // eax@5
+  float v6; // eax@7
+  float v7; // eax@9
+  float v8; // ecx@13
+  int i; // eax@16
+  int v10; // edx@20
+  RenderVertexSoft *v11; // ecx@22
+  RenderVertexSoft *v12; // edx@22
+  RenderVertexSoft *v13; // esi@22
+  int v14; // ebx@26
+  RenderVertexSoft *v15; // ebx@27
+  double v16; // st6@28
+  double v17; // st5@28
+  double v18; // st4@28
+  int v19; // [sp+4h] [bp-2Ch]@20
+  int v20; // [sp+8h] [bp-28h]@22
+  int v21; // [sp+Ch] [bp-24h]@22
+  stru148 *v22; // [sp+10h] [bp-20h]@1
+  float v23; // [sp+14h] [bp-1Ch]@11
+  float v24; // [sp+18h] [bp-18h]@7
+  float v25; // [sp+1Ch] [bp-14h]@5
+  float v26; // [sp+20h] [bp-10h]@2
+  float v27; // [sp+24h] [bp-Ch]@2
+  float v28; // [sp+28h] [bp-8h]@2
+  float v29; // [sp+2Ch] [bp-4h]@9
+
+  v1 = this->uNumVertices;
+  v22 = this;
+  if ( (signed int)v1 >= 3 )
+  {
+    LODWORD(v2) = 0;
+    v26 = 10000.0;
+    v28 = 10000.0;
+    v3 = -10000.0;
+    v27 = -10000.0;
+    if ( (signed int)v1 > 0 )
+    {
+      v4 = (char *)&array_508690[0].vWorldViewProjY;
+      do
+      {
+        if ( *((float *)v4 - 1) < (double)v26 )
+        {
+          LODWORD(v5) = *((int *)v4 - 1);
+          v25 = v2;
+          v26 = v5;
+        }
+        if ( *((float *)v4 - 1) > (double)v27 )
+        {
+          LODWORD(v6) = *((int *)v4 - 1);
+          v24 = v2;
+          v27 = v6;
+        }
+        if ( *(float *)v4 < (double)v28 )
+        {
+          LODWORD(v7) = *(int *)v4;
+          v29 = v2;
+          v28 = v7;
+        }
+        if ( v3 < *(float *)v4 )
+        {
+          v3 = *(float *)v4;
+          v23 = v2;
+        }
+        ++LODWORD(v2);
+        v4 += 48;
+      }
+      while ( SLODWORD(v2) < (signed int)v1 );
+    }
+    v8 = v29;
+    if ( LODWORD(v29) == LODWORD(v25) || LODWORD(v29) == LODWORD(v24) )
+      v8 = v23;
+    v29 = 0.0;
+    for ( i = 0; i < (signed int)v1; ++i )
+    {
+      if ( i == LODWORD(v25) || i == LODWORD(v24) || i == LODWORD(v8) )
+      {
+        v10 = LODWORD(v29)++;
+        *(&v19 + v10) = i;
+      }
+    }
+    v11 = &array_508690[v19];
+    v12 = &array_508690[v20];
+    v13 = &array_508690[v21];
+    if ( LODWORD(v29) != 3 )
+    {
+      v11 = array_508690;
+      v13 = (RenderVertexSoft *)((char *)array_508690 + 16 * (3 * v1 - 3));
+      v12 = &array_508690[1];
+      v28 = array_508690[1].vWorldPosition.x - array_508690[0].vWorldPosition.x;
+      v27 = array_508690[1].vWorldPosition.y - array_508690[0].vWorldPosition.y;
+      v29 = array_508690[1].vWorldPosition.z - array_508690[0].vWorldPosition.z;
+      v26 = v13->vWorldPosition.x - array_508690[0].vWorldPosition.x;
+      v25 = v13->vWorldPosition.y - array_508690[0].vWorldPosition.y;
+      v24 = v13->vWorldPosition.z - array_508690[0].vWorldPosition.z;
+      if ( v24 * v27 - v25 * v29 == 0.0 )
+      {
+        if ( v26 * v29 - v24 * v28 == 0.0 )
+        {
+          if ( v25 * v28 - v26 * v27 == 0.0 )
+          {
+            v14 = v1 - 2;
+            LODWORD(v26) = v14;
+            if ( v14 >= 2 )
+            {
+              v15 = &array_508690[v14];
+              do
+              {
+                v16 = v15->vWorldPosition.x - array_508690[0].vWorldPosition.x;
+                v17 = v15->vWorldPosition.y - array_508690[0].vWorldPosition.y;
+                v18 = v15->vWorldPosition.z - array_508690[0].vWorldPosition.z;
+                v13 = v15;
+                if ( v27 * v18 - v17 * v29 != 0.0 )
+                  break;
+                if ( v16 * v29 - v18 * v28 != 0.0 )
+                  break;
+                if ( v28 * v17 - v16 * v27 != 0.0 )
+                  break;
+                --LODWORD(v26);
+                --v15;
+              }
+              while ( SLODWORD(v26) >= 2 );
+            }
+          }
+        }
+      }
+    }
+    sr_sub_4829B9(v11, v12, v13, v22, 1);
+  }
+}
+
+//----- (004829B9) --------------------------------------------------------
+stru148 *__fastcall sr_sub_4829B9(RenderVertexSoft *a1, RenderVertexSoft *a2, RenderVertexSoft *a3, stru148 *a4, int a5)
+{
+  double v5; // st7@1
+  RenderVertexSoft *v6; // esi@1
+  double v7; // st6@1
+  stru148 *result; // eax@3
+  double v9; // st6@3
+  double v10; // st5@3
+  float v11; // ST0C_4@3
+  float v12; // ST04_4@3
+  double v13; // st4@3
+  float v14; // [sp+8h] [bp-Ch]@1
+  float v15; // [sp+10h] [bp-4h]@1
+  float v16; // [sp+1Ch] [bp+8h]@1
+  float v17; // [sp+1Ch] [bp+8h]@3
+
+  v5 = a2->vWorldViewProjX - a1->vWorldViewProjX;
+  v6 = a3;
+  v16 = a3->vWorldViewProjY - a1->vWorldViewProjY;
+  v15 = a2->vWorldViewProjY - a1->vWorldViewProjY;
+  v14 = v6->vWorldViewProjX - a1->vWorldViewProjX;
+  v7 = v16 * v5 - v14 * v15;
+  if ( v7 == 0.0 )
+    v7 = 0.0000001;
+  result = a4;
+  v9 = 1.0 / v7;
+  v10 = 1.0 / a1->vWorldViewPosition.x;
+  v11 = 1.0 / a2->vWorldViewPosition.x - v10;
+  v12 = 1.0 / v6->vWorldViewPosition.x - v10;
+  v13 = (v11 * v16 - v12 * v15) * v9;
+  v17 = (v11 * v14 - v12 * v5) * -v9;
+  a4->field_C = a1->vWorldViewProjX;
+  a4->field_10 = a1->vWorldViewProjY;
+  a4->field_0 = v10;
+  a4->field_8 = v17;
+  a4->field_4 = v13;
+  return result;
+}
+
+//----- (00482A90) --------------------------------------------------------
+signed int __cdecl const_1_0()
+{
+  return 1;
+}
+
+
+//----- (00482A94) --------------------------------------------------------
+int sr_sub_482A94(Span *_this)
+{
+  stru315 *v1; // ebp@0
+  Span *v2; // edi@1
+  stru148 *v3; // esi@1
+  int v4; // ecx@1
+  stru149 *v5; // eax@1
+  stru149 *v6; // eax@1
+  int v7; // edx@1
+  int v8; // eax@1
+  int v9; // ecx@1
+  int v10; // edx@1
+  int v11; // ebx@1
+  int v12; // eax@1
+  signed int v13; // ebx@1
+  int v14; // ebx@2
+  signed __int64 v15; // qtt@3
+  stru149 *v16; // eax@3
+  signed int v17; // ebx@3
+  Texture *v18; // eax@14
+  unsigned __int16 *v19; // eax@15
+  stru149 *v20; // eax@21
+  signed int v21; // eax@21
+  int v22; // eax@21
+  int v23; // ecx@21
+  Texture *v24; // edx@21
+  signed int v25; // eax@21
+  signed int v27; // [sp-4h] [bp-A4h]@8
+  int v28; // [sp+Ch] [bp-94h]@1
+  int v29; // [sp+10h] [bp-90h]@1
+  stru316 a2; // [sp+14h] [bp-8Ch]@21
+  stru315 a1; // [sp+3Ch] [bp-64h]@1
+  int v32; // [sp+80h] [bp-20h]@1
+  int v33; // [sp+84h] [bp-1Ch]@1
+  int v34; // [sp+88h] [bp-18h]@1
+  int v35; // [sp+8Ch] [bp-14h]@1
+  int v36; // [sp+90h] [bp-10h]@1
+  int v37; // [sp+94h] [bp-Ch]@1
+  int v38; // [sp+98h] [bp-8h]@1
+  int X; // [sp+9Ch] [bp-4h]@1
+
+  v2 = _this;
+  v3 = _this->pParent;
+  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
+  v5 = v3->ptr_38;
+  v38 = v4;
+  v37 = v5->field_14;
+  v38 = (unsigned __int64)(v37 * (signed __int64)v4) >> 16;
+  v6 = v3->ptr_38;
+  v7 = v38 + v6->field_C;
+  v37 = v6->field_20;
+  v33 = v7;
+  v8 = ((unsigned __int64)(v37 * (signed __int64)v4) >> 16) + v3->ptr_38->field_18;
+  v38 = v4;
+  v34 = v8;
+  v37 = v3->v_18.z;
+  v38 = (unsigned __int64)(v37 * (signed __int64)v4) >> 16;
+  v9 = v3->v_18.x;
+  v28 = v3->sTextureDeltaU << 16;
+  v35 = v3->sTextureDeltaV << 16;
+  v10 = v2->field_8;
+  v29 = pOutdoorCamera->camera_rotation_y_int_sine;
+  v32 = pOutdoorCamera->camera_rotation_y_int_cosine;
+  a1.field_28 = v2->field_C;
+  v11 = v3->field_24;
+  v37 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v10);
+  v12 = v3->v_18.y;
+  v13 = -v11;
+  v36 = v13;
+  X = ((unsigned __int64)(v37 * (signed __int64)v12) >> 16) + v38 + v9;
+  if ( !X || (v14 = abs(v13 >> 14), v14 > abs(X)) )
+    return 0;
+  LODWORD(v15) = v36 << 16;
+  HIDWORD(v15) = v36 >> 16;
+  v38 = v15 / X;
+  v16 = v3->ptr_38;
+  X = v37;
+  v36 = v16->field_10;
+  X = v37;
+  v36 = v33 + ((unsigned __int64)(v36 * (signed __int64)v37) >> 16);
+  v33 = v3->ptr_38->field_1C;
+  X = (unsigned __int64)(v33 * (signed __int64)v37) >> 16;
+  v34 += (unsigned __int64)(v33 * (signed __int64)v37) >> 16;
+  v17 = 2;
+  a1.pTextureLOD = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
+  if ( v38 >= mipmapping_building_mm1 << 16 )
+  {
+    if ( v38 >= mipmapping_building_mm2 << 16 )
+    {
+      if ( v38 >= mipmapping_building_mm3 << 16 )
+      {
+        if ( bUseLoResSprites )
+          goto LABEL_12;
+        v27 = 3;
+      }
+      else
+      {
+        v27 = 2;
+      }
+      v17 = v27;
+      goto LABEL_12;
+    }
+    v17 = 1;
+  }
+  else
+  {
+    v17 = 0;
+  }
+LABEL_12:
+  if ( v17 < (signed int)v3->ptr_48 )
+    v17 = (signed int)v3->ptr_48;
+  v18 = v3->pTexture;
+  if ( v17 )
+  {
+    if ( v17 == 1 )
+    {
+      v19 = (unsigned __int16 *)v18->pLevelOfDetail1;
+    }
+    else
+    {
+      if ( v17 == 2 )
+        v19 = (unsigned __int16 *)v18->pLevelOfDetail2;
+      else
+        v19 = (unsigned __int16 *)v18->pLevelOfDetail3;
+    }
+  }
+  else
+  {
+    v19 = (unsigned __int16 *)v18->pLevelOfDetail0;
+  }
+  a1.pTextureLOD = v19;
+  X = (unsigned __int64)(v36 * (signed __int64)v38) >> 16;
+  v20 = v3->ptr_38;
+  X = v38;
+  a1.field_30 = v28 + ((unsigned __int64)(v36 * (signed __int64)v38) >> 16) - v20->field_24;
+  X = (unsigned __int64)(v34 * (signed __int64)v38) >> 16;
+  v21 = X - v3->ptr_38->field_28 - v35;
+  a1.field_30 >>= v17 + bUseLoResSprites;
+  a1.field_2C = v21 >> (v17 + bUseLoResSprites);
+  v35 = pOutdoorCamera->int_fov_rad_inv;
+  v37 = (signed int)((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * (signed __int64)v38) >> 16) >> (v17 + bUseLoResSprites);
+  a1.field_4 = (unsigned __int64)(v37 * (signed __int64)v29) >> 16;
+  X = (unsigned __int64)(v37 * (signed __int64)v32) >> 16;
+  a1.field_0 = -(signed int)((unsigned __int64)(v37 * (signed __int64)v32) >> 16);
+  v22 = v2->field_A;
+  a1.pColorBuffer = &pRenderer->pTargetSurface[v2->field_8 + pRenderer->uTargetSurfacePitch * v2->field_A];
+  HIWORD(v23) = HIWORD(v38);
+  a1.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v2->field_8 + 640 * v22];
+  LOWORD(v23) = 0;
+  a1.field_24 = v23 | v3->field_50;
+  v24 = v3->pTexture;
+  v32 = (signed int)v24->uTextureWidth >> v17;
+  v25 = (signed int)v24->uTextureHeight >> v17;
+  a1.field_10 = v17 - v24->uWidthLn2 + 16;
+  a1.field_C = v32 - 1;
+  a1.field_8 = (v25 << 16) - 65536;
+  a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v2, v38, v3, pOutdoorCamera->building_gamme, 1u, 1);
+  if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+    sr_sub_485975(&a1, (stru315 *)&a2);
+  else
+    sr_sub_4D6FB0(v1);
+  return 1;
+}
+
+//----- (00482E07) --------------------------------------------------------
+signed int __fastcall sr_sub_482E07(Span *ecx0, unsigned __int16 *pRenderTarget)
+{
+  stru315 *v2; // ebp@0
+  stru148 *v3; // esi@1
+  int v4; // edi@1
+  int v5; // edi@1
+  stru149 *v6; // eax@1
+  stru149 *v7; // eax@1
+  int v8; // edx@1
+  int v9; // eax@1
+  int v10; // edi@1
+  int v11; // eax@1
+  unsigned __int64 v12; // qax@1
+  int v13; // eax@1
+  signed __int64 v14; // qtt@3
+  int v15; // ebx@4
+  signed __int64 v16; // qtt@5
+  int v17; // eax@5
+  unsigned __int16 *v18; // eax@7
+  Texture *v19; // eax@8
+  Texture *v20; // eax@10
+  Texture *v21; // eax@12
+  Texture *v22; // eax@14
+  int v23; // ecx@17
+  Texture *v24; // ebx@17
+  signed int v25; // edx@17
+  signed int v26; // eax@17
+  char v27; // bl@17
+  stru149 *v28; // eax@18
+  stru149 *v29; // eax@18
+  int v30; // eax@18
+  int v31; // eax@18
+  unsigned int v32; // edx@18
+  int v33; // edi@21
+  signed __int64 v34; // qtt@22
+  signed int v35; // ecx@22
+  int v36; // eax@24
+  stru149 *v37; // eax@24
+  int v38; // edi@24
+  int v39; // eax@24
+  int v40; // edi@35
+  signed __int64 v41; // qtt@36
+  int v42; // edx@36
+  stru149 *v43; // eax@36
+  int v44; // edi@36
+  int v45; // eax@36
+  Span *v46; // edi@44
+  stru149 *v47; // eax@44
+  stru149 *v48; // eax@44
+  int v49; // eax@44
+  int v50; // ecx@44
+  unsigned int v51; // edx@44
+  int v52; // edi@46
+  signed __int64 v53; // qtt@47
+  unsigned int v54; // ecx@47
+  int v55; // eax@49
+  stru149 *v56; // eax@49
+  int v57; // edi@49
+  int v58; // eax@49
+  int v59; // edi@60
+  signed __int64 v60; // qtt@61
+  int v61; // edx@61
+  stru149 *v62; // eax@61
+  int v63; // edi@61
+  int v64; // eax@61
+  int v66; // [sp+Ch] [bp-B8h]@1
+  int v67; // [sp+10h] [bp-B4h]@1
+  int v68; // [sp+14h] [bp-B0h]@1
+  int v69; // [sp+18h] [bp-ACh]@1
+  int v70; // [sp+1Ch] [bp-A8h]@5
+  int v71; // [sp+20h] [bp-A4h]@1
+  signed int v72; // [sp+24h] [bp-A0h]@1
+  stru316 a2; // [sp+28h] [bp-9Ch]@18
+  int v74; // [sp+50h] [bp-74h]@17
+  stru315 a1; // [sp+54h] [bp-70h]@5
+  Span *v76; // [sp+98h] [bp-2Ch]@1
+  unsigned __int16 *v77; // [sp+9Ch] [bp-28h]@1
+  int v78; // [sp+A0h] [bp-24h]@17
+  int v79; // [sp+A4h] [bp-20h]@3
+  int v80; // [sp+A8h] [bp-1Ch]@3
+  int v81; // [sp+ACh] [bp-18h]@1
+  int X; // [sp+B0h] [bp-14h]@2
+  int v83; // [sp+B4h] [bp-10h]@1
+  int v84; // [sp+B8h] [bp-Ch]@1
+  int v85; // [sp+BCh] [bp-8h]@1
+  int v86; // [sp+C0h] [bp-4h]@18
+
+  v85 = ecx0->field_C;
+  v3 = ecx0->pParent;
+  v4 = pViewport->uScreenCenterY - ecx0->field_A;
+  v77 = pRenderTarget;
+  v5 = pOutdoorCamera->int_fov_rad_inv * v4;
+  v6 = v3->ptr_38;
+  v76 = ecx0;
+  v81 = v5;
+  v83 = v6->field_14;
+  v81 = (unsigned __int64)(v83 * (signed __int64)v5) >> 16;
+  v7 = v3->ptr_38;
+  v8 = v81 + v7->field_C;
+  v83 = v7->field_20;
+  v67 = v8;
+  v9 = ((unsigned __int64)(v83 * (signed __int64)v5) >> 16) + v3->ptr_38->field_18;
+  v81 = v5;
+  v71 = v9;
+  v83 = v3->v_18.z;
+  v81 = (unsigned __int64)(v83 * (signed __int64)v5) >> 16;
+  v68 = v3->sTextureDeltaU << 16;
+  v69 = v3->sTextureDeltaV << 16;
+  v72 = -v3->field_24;
+  v10 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - ecx0->field_8);
+  v11 = v3->v_18.y;
+  v66 = v81 + v3->v_18.x;
+  v83 = v10;
+  v12 = v10 * (signed __int64)v11;
+  v81 = v12 >> 16;
+  v13 = v66 + (v12 >> 16);
+  v84 = v13;
+  if ( !v13
+    || (X = v72 >> 15, v83 = abs(v13), abs(v72 >> 15) >= v83)
+    || (LODWORD(v14) = v72 << 16,
+        HIDWORD(v14) = v72 >> 16,
+        v79 = v14 / v84,
+        v80 = v10 - v85 * pOutdoorCamera->int_fov_rad_inv,
+        v81 = (unsigned __int64)(v80 * (signed __int64)v3->v_18.y) >> 16,
+        (v84 = v66 + v81) == 0)
+    || (v15 = abs(v66 + v81), abs(X) >= v15) )
+    return 0;
+  LODWORD(v16) = v72 << 16;
+  HIDWORD(v16) = v72 >> 16;
+  v70 = v16 / v84;
+  v17 = v16 / v84;
+  a1.field_24 = v79;
+  if ( v79 >= v17 )
+    a1.field_24 = v17;
+  v18 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
+  a1.pTextureLOD = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
+  v84 = 2;
+  if ( a1.field_24 >= mipmapping_building_mm1 << 16 )
+  {
+    if ( a1.field_24 >= mipmapping_building_mm2 << 16 )
+    {
+      if ( a1.field_24 >= mipmapping_building_mm3 << 16 )
+      {
+        if ( bUseLoResSprites )
+          goto LABEL_16;
+        v22 = v3->pTexture;
+        v84 = 3;
+        v18 = (unsigned __int16 *)v22->pLevelOfDetail3;
+      }
+      else
+      {
+        v21 = v3->pTexture;
+        v84 = 2;
+        v18 = (unsigned __int16 *)v21->pLevelOfDetail2;
+      }
+    }
+    else
+    {
+      v20 = v3->pTexture;
+      v84 = 1;
+      v18 = (unsigned __int16 *)v20->pLevelOfDetail1;
+    }
+  }
+  else
+  {
+    v19 = v3->pTexture;
+    v84 = 0;
+    v18 = (unsigned __int16 *)v19->pLevelOfDetail0;
+  }
+  a1.pTextureLOD = v18;
+LABEL_16:
+  if ( v18 )
+  {
+    v23 = v3->field_5A;
+    v83 = v3->field_52;
+    v24 = v3->pTexture;
+    v74 = v23;
+    v78 = v85 >> v23;
+    v25 = v24->uTextureWidth;
+    v81 = v85 - (v85 >> v23 << v23);
+    v26 = (signed int)v24->uTextureHeight >> v84;
+    a1.field_10 = v84 - v24->uWidthLn2 + 16;
+    v27 = v84 + bUseLoResSprites;
+    a1.field_8 = (v26 << 16) - 65536;
+    a1.field_C = (v25 >> v84) - 1;
+    if ( v79 >= v70 )
+    {
+      v46 = v76;
+      a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v76, v70, v3, pOutdoorCamera->building_gamme, 0, 1);
+      v47 = v3->ptr_38;
+      v79 = v80;
+      v86 = v47->field_10;
+      v79 = v80;
+      v84 = v67 + ((unsigned __int64)(v86 * (signed __int64)v80) >> 16);
+      v86 = v3->ptr_38->field_1C;
+      v86 = v71 + ((unsigned __int64)(v86 * (signed __int64)v80) >> 16);
+      v79 = (unsigned __int64)(v84 * (signed __int64)v70) >> 16;
+      v48 = v3->ptr_38;
+      v79 = v70;
+      a1.field_30 = v68 + ((unsigned __int64)(v84 * (signed __int64)v70) >> 16) - v48->field_24;
+      v79 = (unsigned __int64)(v86 * (signed __int64)v70) >> 16;
+      v49 = ((unsigned __int64)(v86 * (signed __int64)v70) >> 16) - v3->ptr_38->field_28;
+      a1.field_30 >>= v27;
+      a1.field_2C = (v69 + v49) >> v27;
+      a1.field_14 = dword_80AA20 >> v27;
+      a1.field_18 = dword_80AA1C >> v27;
+      a1.field_1C = dword_80AA18 >> v27;
+      v50 = v46->field_8;
+      a1.field_20 = dword_80AA14 >> v27;
+      v51 = v50 + pRenderer->uTargetSurfacePitch * v46->field_A;
+      a1.pDepthBuffer = (unsigned int *)(&pRenderer->pActiveZBuffer[640 * v46->field_A - 1] + v85 + v50);
+      a1.pColorBuffer = &v77[v85 - 1] + v51;
+      v80 += pOutdoorCamera->int_fov_rad_inv << v74;
+      if ( v78 > 0 )
+      {
+        do
+        {
+          v77 = (unsigned __int16 *)v3->v_18.y;
+          v86 = (unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16;
+          v84 = v66 + ((unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16);
+          if ( v66 + (unsigned int)((unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16)
+            && (v52 = abs((signed __int64)v66 + ((__int64)((signed int)v77 * (signed __int64)v80) >> 16)), abs((signed __int64)X) < v52) )
+          {
+            LODWORD(v53) = v72 << 16;
+            HIDWORD(v53) = v72 >> 16;
+            v86 = v53 / v84;
+            v54 = v53 / v84;
+            v84 = v53 / v84;
+          }
+          else
+          {
+            v84 = 0x40000000u;
+            v54 = 0x40000000u;
+          }
+          HIWORD(v55) = HIWORD(v54);
+          LOWORD(v55) = 0;
+          a1.field_24 = v3->field_50 | v55;
+          v77 = (unsigned __int16 *)v3->ptr_38->field_10;
+          v77 = (unsigned __int16 *)(v67 + ((unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16));
+          v86 = (unsigned __int64)((signed int)v77 * (signed __int64)(signed int)v54) >> 16;
+          v56 = v3->ptr_38;
+          v57 = ((unsigned __int64)((signed int)v77 * (signed __int64)(signed int)v54) >> 16) - v56->field_24;
+          v77 = (unsigned __int16 *)v56->field_1C;
+          v77 = (unsigned __int16 *)(v71 + ((unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16));
+          v86 = (unsigned __int64)((signed int)v77 * (signed __int64)(signed int)v54) >> 16;
+          v58 = (((v69 + v86 - v3->ptr_38->field_28) >> v27) - a1.field_2C) >> v74;
+          a1.field_4 = (((v68 + v57) >> v27) - a1.field_30) >> v74;
+          a1.field_0 = v58;
+          a1.field_28 = v83;
+          if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+          {
+            if ( v3->pODMFace->uPolygonType == 1 )
+              sr_sub_485BAE(&a1, &a2);
+            else
+              sr_sub_485AFF(&a1, &a2);
+          }
+          else
+          {
+            if ( v3->pODMFace->uPolygonType == 1 )
+              sr_sub_4D71F8(&a1);
+            else
+              sr_sub_4D714C(&a1);
+          }
+          a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(
+                                                      &a2,
+                                                      v76,
+                                                      v84,
+                                                      v3,
+                                                      pOutdoorCamera->building_gamme,
+                                                      0,
+                                                      0);
+          v80 += pOutdoorCamera->int_fov_rad_inv << v74;
+          --v78;
+        }
+        while ( v78 );
+      }
+      if ( !v81 )
+        return 1;
+      v83 = v3->v_18.y;
+      v86 = (unsigned __int64)(v83 * (signed __int64)v80) >> 16;
+      v84 = v66 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
+      if ( v66 + (unsigned int)((unsigned __int64)(v83 * (signed __int64)v80) >> 16) )
+      {
+        v59 = abs((signed __int64)v66 + ((__int64)(v83 * (signed __int64)v80) >> 16));
+        if ( abs(X) < v59 )
+        {
+          LODWORD(v60) = v72 << 16;
+          HIDWORD(v60) = v72 >> 16;
+          v86 = v60 / v84;
+          HIWORD(v61) = (unsigned int)(v60 / v84) >> 16;
+          LOWORD(v61) = 0;
+          a1.field_24 = v61 | v3->field_50;
+          v83 = v3->ptr_38->field_10;
+          v83 = v67 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
+          v86 = (unsigned __int64)(v83 * v60 / v84) >> 16;
+          v62 = v3->ptr_38;
+          v63 = ((unsigned __int64)(v83 * v60 / v84) >> 16) - v62->field_24;
+          v83 = v62->field_1C;
+          v83 = v71 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
+          v86 = (unsigned __int64)(v83 * v60 / v84) >> 16;
+          v64 = (((signed int)(v69 + ((unsigned __int64)(v83 * v60 / v84) >> 16) - v3->ptr_38->field_28) >> v27)
+               - a1.field_2C) >> v74;
+          a1.field_4 = (((v68 + v63) >> v27) - a1.field_30) >> v74;
+          a1.field_0 = v64;
+          a1.field_28 = v81;
+          if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+          {
+            if ( v3->pODMFace->uPolygonType == 1 )
+              sr_sub_485BAE(&a1, &a2);
+            else
+              sr_sub_485AFF(&a1, &a2);
+          }
+          else
+          {
+            if ( v3->pODMFace->uPolygonType == 1 )
+              sr_sub_4D71F8(&a1);
+            else
+              sr_sub_4D714C(&a1);
+          }
+          return 1;
+        }
+      }
+    }
+    else
+    {
+      a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v76, v79, v3, pOutdoorCamera->building_gamme, 1u, 1);
+      v28 = v3->ptr_38;
+      v85 = v10;
+      v86 = v28->field_10;
+      v85 = v10;
+      v84 = v67 + ((unsigned __int64)(v86 * (signed __int64)v10) >> 16);
+      v86 = v3->ptr_38->field_1C;
+      v86 = v71 + ((unsigned __int64)(v86 * (signed __int64)v10) >> 16);
+      v85 = (unsigned __int64)(v84 * (signed __int64)v79) >> 16;
+      v29 = v3->ptr_38;
+      v85 = v79;
+      a1.field_30 = v68 + ((unsigned __int64)(v84 * (signed __int64)v79) >> 16) - v29->field_24;
+      v85 = (unsigned __int64)(v86 * (signed __int64)v79) >> 16;
+      v30 = ((unsigned __int64)(v86 * (signed __int64)v79) >> 16) - v3->ptr_38->field_28;
+      a1.field_30 >>= v27;
+      a1.field_2C = (v69 + v30) >> v27;
+      a1.field_14 = dword_80AA20 >> v27;
+      a1.field_18 = dword_80AA1C >> v27;
+      a1.field_1C = dword_80AA18 >> v27;
+      a1.field_20 = dword_80AA14 >> v27;
+      v31 = v76->field_A;
+      v32 = pRenderer->uTargetSurfacePitch * v76->field_A;
+      v86 = v76->field_8;
+      a1.pColorBuffer = &v77[v86 + v32];
+      a1.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v86 + 640 * v31];
+      v80 = v10 - (pOutdoorCamera->int_fov_rad_inv << v74);
+      if ( v78 > 0 )
+      {
+        v86 = v78;
+        do
+        {
+          v78 = v3->v_18.y;
+          v85 = (unsigned __int64)(v78 * (signed __int64)v80) >> 16;
+          v84 = v66 + ((unsigned __int64)(v78 * (signed __int64)v80) >> 16);
+          if ( v66 + (unsigned int)((unsigned __int64)(v78 * (signed __int64)v80) >> 16)
+            && (v33 = abs((signed __int64)v66 + ((__int64)(v78 * (signed __int64)v80) >> 16)), abs((signed __int64)X) < v33) )
+          {
+            LODWORD(v34) = v72 << 16;
+            HIDWORD(v34) = v72 >> 16;
+            v85 = v34 / v84;
+            v35 = v34 / v84;
+            v84 = v34 / v84;
+          }
+          else
+          {
+            v84 = 1073741824;
+            v35 = 1073741824;
+          }
+          HIWORD(v36) = HIWORD(v35);
+          LOWORD(v36) = 0;
+          a1.field_24 = v3->field_50 | v36;
+          v78 = v3->ptr_38->field_10;
+          v78 = v67 + ((unsigned __int64)(v78 * (signed __int64)v80) >> 16);
+          v85 = (unsigned __int64)(v78 * (signed __int64)v35) >> 16;
+          v37 = v3->ptr_38;
+          v38 = ((unsigned __int64)(v78 * (signed __int64)v35) >> 16) - v37->field_24;
+          v78 = v37->field_1C;
+          v78 = v71 + ((unsigned __int64)(v78 * (signed __int64)v80) >> 16);
+          v85 = (unsigned __int64)(v78 * (signed __int64)v35) >> 16;
+          v39 = (((v69 + v85 - v3->ptr_38->field_28) >> v27) - a1.field_2C) >> v74;
+          a1.field_4 = (((v68 + v38) >> v27) - a1.field_30) >> v74;
+          a1.field_0 = v39;
+          a1.field_28 = v83;
+          if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+          {
+            if ( v3->pODMFace->uPolygonType == 1 )
+              sr_sub_485A24(&a1, (stru315 *)&a2);
+            else
+              sr_sub_485975(&a1, (stru315 *)&a2);
+          }
+          else
+          {
+            if ( v3->pODMFace->uPolygonType == 1 )
+              sr_sub_4D705A(v2);
+            else
+              sr_sub_4D6FB0(v2);
+          }
+          a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(
+                                                      &a2,
+                                                      v76,
+                                                      v84,
+                                                      v3,
+                                                      pOutdoorCamera->building_gamme,
+                                                      1u,
+                                                      0);
+          v80 -= pOutdoorCamera->int_fov_rad_inv << v74;
+          --v86;
+        }
+        while ( v86 );
+      }
+      if ( !v81 )
+        return 1;
+      v83 = v3->v_18.y;
+      v76 = (Span *)((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
+      v84 = v66 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
+      if ( v66 + (unsigned int)((unsigned __int64)(v83 * (signed __int64)v80) >> 16) )
+      {
+        v40 = abs((signed __int64)v66 + ((__int64)(v83 * (signed __int64)v80) >> 16));
+        if ( abs(X) < v40 )
+        {
+          LODWORD(v41) = v72 << 16;
+          HIDWORD(v41) = v72 >> 16;
+          X = v41 / v84;
+          HIWORD(v42) = (unsigned int)(v41 / v84) >> 16;
+          LOWORD(v42) = 0;
+          a1.field_24 = v42 | v3->field_50;
+          v83 = v3->ptr_38->field_10;
+          v83 = v67 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
+          X = (unsigned __int64)(v83 * v41 / v84) >> 16;
+          v43 = v3->ptr_38;
+          v44 = ((unsigned __int64)(v83 * v41 / v84) >> 16) - v43->field_24;
+          v83 = v43->field_1C;
+          v83 = v71 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
+          X = (unsigned __int64)(v83 * v41 / v84) >> 16;
+          v45 = (((signed int)(v69 + ((unsigned __int64)(v83 * v41 / v84) >> 16) - v3->ptr_38->field_28) >> v27)
+               - a1.field_2C) >> v74;
+          a1.field_4 = (((v68 + v44) >> v27) - a1.field_30) >> v74;
+          a1.field_0 = v45;
+          a1.field_28 = v81;
+          if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+          {
+            if ( v3->pODMFace->uPolygonType == 1 )
+              sr_sub_485A24(&a1, (stru315 *)&a2);
+            else
+              sr_sub_485975(&a1, (stru315 *)&a2);
+          }
+          else
+          {
+            if ( v3->pODMFace->uPolygonType == 1 )
+              sr_sub_4D705A(v2);
+            else
+              sr_sub_4D6FB0(v2);
+          }
+          return 1;
+        }
+      }
+    }
+  }
+  return 0;
+}
+// 4D864C: using guessed type char byte_4D864C;
+// 6BE0E4: using guessed type int mipmapping_building_mm1;
+// 6BE0E8: using guessed type int mipmapping_building_mm2;
+// 6BE0EC: using guessed type int mipmapping_building_mm3;
+// 80AA14: using guessed type int dword_80AA14;
+// 80AA18: using guessed type int dword_80AA18;
+// 80AA1C: using guessed type int dword_80AA1C;
+// 80AA20: using guessed type int dword_80AA20;
+
+//----- (004839BD) --------------------------------------------------------
+signed int __fastcall sr_sub_4839BD(Span *ecx0, unsigned __int16 *pTargetSurface)
+{
+  stru315 *v2; // ebp@0
+  int v3; // eax@1
+  int v4; // edi@1
+  stru148 *v5; // esi@1
+  unsigned int v6; // ebx@1
+  int v7; // ecx@1
+  int v8; // ebx@1
+  int v9; // ecx@1
+  int v10; // eax@1
+  stru149 *v11; // eax@1
+  int v12; // edx@1
+  int v13; // eax@1
+  int v14; // edi@1
+  int v15; // ecx@1
+  int v16; // eax@1
+  signed int v17; // edi@1
+  int v18; // edi@2
+  signed __int64 v19; // qtt@3
+  int v20; // edi@3
+  unsigned __int16 *v21; // eax@3
+  Texture *v22; // eax@4
+  Texture *v23; // eax@6
+  Texture *v24; // eax@8
+  Texture *v25; // eax@10
+  stru149 *v26; // eax@13
+  int v27; // edi@13
+  signed int v28; // edx@13
+  Texture *v29; // ebx@13
+  int v30; // edi@13
+  signed int v31; // edx@13
+  signed int v32; // eax@13
+  signed int v33; // eax@13
+  int v34; // ebx@13
+  int v35; // eax@15
+  int v36; // ebx@15
+  int v37; // eax@16
+  signed __int64 v38; // qtt@17
+  int v39; // ecx@17
+  int v40; // eax@19
+  stru149 *v41; // eax@21
+  int v42; // ebx@21
+  int v43; // ebx@21
+  int v44; // eax@21
+  char v45; // zf@25
+  int v46; // eax@28
+  int v47; // eax@28
+  int v48; // ebx@28
+  int v49; // eax@29
+  signed __int64 v50; // qtt@30
+  int v51; // ecx@30
+  int v52; // eax@30
+  int v53; // edx@31
+  stru149 *v54; // eax@33
+  int v55; // ebx@33
+  signed int v56; // ebx@33
+  int v57; // eax@33
+  unsigned __int64 v58; // qax@33
+  int v60; // [sp+Ch] [bp-BCh]@1
+  Span *v61; // [sp+10h] [bp-B8h]@1
+  int v62; // [sp+14h] [bp-B4h]@2
+  int v63; // [sp+18h] [bp-B0h]@1
+  stru315 a1; // [sp+1Ch] [bp-ACh]@1
+  stru316 a2; // [sp+60h] [bp-68h]@13
+  int v66; // [sp+88h] [bp-40h]@13
+  int v67; // [sp+8Ch] [bp-3Ch]@1
+  int v68; // [sp+90h] [bp-38h]@13
+  int v69; // [sp+94h] [bp-34h]@3
+  int v70; // [sp+98h] [bp-30h]@1
+  int v71; // [sp+9Ch] [bp-2Ch]@1
+  int v72; // [sp+A0h] [bp-28h]@1
+  int v73; // [sp+A4h] [bp-24h]@13
+  int v74; // [sp+A8h] [bp-20h]@1
+  int v75; // [sp+ACh] [bp-1Ch]@3
+  int v76; // [sp+B0h] [bp-18h]@1
+  int v77; // [sp+B4h] [bp-14h]@1
+  int X; // [sp+B8h] [bp-10h]@1
+  int v79; // [sp+BCh] [bp-Ch]@21
+  int v80; // [sp+C0h] [bp-8h]@13
+  unsigned int v81; // [sp+C4h] [bp-4h]@1
+
+  v3 = ecx0->field_A;
+  v4 = ecx0->field_8;
+  v5 = ecx0->pParent;
+  v6 = v4 + pRenderer->uTargetSurfacePitch * ecx0->field_A;
+  v61 = ecx0;
+  v7 = ecx0->field_C;
+  a1.pColorBuffer = &pTargetSurface[v6];
+  v74 = v7;
+  a1.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v4 + 640 * v3];
+  v8 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v4);
+  v9 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v3);
+  v10 = v5->ptr_38->field_14;
+  v76 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v4);
+  v72 = v10;
+  v81 = (unsigned __int64)(v10 * (signed __int64)v9) >> 16;
+  v11 = v5->ptr_38;
+  v12 = v81 + v11->field_C;
+  v72 = v11->field_20;
+  v67 = v12;
+  v13 = ((unsigned __int64)(v72 * (signed __int64)v9) >> 16) + v5->ptr_38->field_18;
+  v81 = v9;
+  v70 = v13;
+  v72 = v5->v_18.z;
+  v81 = (unsigned __int64)(v72 * (signed __int64)v9) >> 16;
+  v14 = v5->field_24;
+  v15 = v81 + v5->v_18.x;
+  v71 = v5->sTextureDeltaU << 16;
+  v63 = v5->sTextureDeltaV << 16;
+  v16 = v5->v_18.y;
+  v17 = -v14;
+  v60 = v15;
+  v77 = v17;
+  v81 = (unsigned __int64)(v76 * (signed __int64)v16) >> 16;
+  X = v81 + v15;
+  if ( !(v81 + v15) || (v62 = v17 >> 14, v18 = abs(v17 >> 14), v18 > abs(X)) )
+    return 0;
+  LODWORD(v19) = v77 << 16;
+  HIDWORD(v19) = v77 >> 16;
+  v69 = v19 / X;
+  v20 = v19 / X;
+  v21 = (unsigned __int16 *)v5->pTexture->pLevelOfDetail2;
+  a1.pTextureLOD = (unsigned __int16 *)v5->pTexture->pLevelOfDetail2;
+  v75 = 2;
+  if ( v20 >= mipmapping_building_mm1 << 16 )
+  {
+    if ( v20 >= mipmapping_building_mm2 << 16 )
+    {
+      if ( v20 >= mipmapping_building_mm3 << 16 )
+      {
+        if ( bUseLoResSprites )
+          goto LABEL_12;
+        v25 = v5->pTexture;
+        v75 = 3;
+        v21 = (unsigned __int16 *)v25->pLevelOfDetail3;
+      }
+      else
+      {
+        v24 = v5->pTexture;
+        v75 = 2;
+        v21 = (unsigned __int16 *)v24->pLevelOfDetail2;
+      }
+    }
+    else
+    {
+      v23 = v5->pTexture;
+      v75 = 1;
+      v21 = (unsigned __int16 *)v23->pLevelOfDetail1;
+    }
+  }
+  else
+  {
+    v22 = v5->pTexture;
+    v75 = 0;
+    v21 = (unsigned __int16 *)v22->pLevelOfDetail0;
+  }
+  a1.pTextureLOD = v21;
+LABEL_12:
+  if ( v21 )
+  {
+    a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v61, v20, v5, pOutdoorCamera->building_gamme, 1u, 1);
+    a1.field_28 = 16;
+    v66 = v74 >> 4;
+    v81 = v8;
+    v26 = v5->ptr_38;
+    v72 = v74 - 16 * (v74 >> 4);
+    v76 = v26->field_10;
+    v81 = v8;
+    v74 = v67 + ((unsigned __int64)(v76 * (signed __int64)v8) >> 16);
+    v76 = v5->ptr_38->field_1C;
+    v76 = v70 + ((unsigned __int64)(v76 * (signed __int64)v8) >> 16);
+    v81 = (unsigned __int64)(v74 * (signed __int64)v20) >> 16;
+    v27 = ((unsigned __int64)(v74 * (signed __int64)v20) >> 16) - v5->ptr_38->field_24;
+    v81 = (unsigned __int64)(v76 * (signed __int64)v69) >> 16;
+    v28 = v63 + ((unsigned __int64)(v76 * (signed __int64)v69) >> 16) - v5->ptr_38->field_28;
+    v76 = v75 + bUseLoResSprites;
+    v73 = v8 - 16 * pOutdoorCamera->int_fov_rad_inv;
+    v29 = v5->pTexture;
+    v30 = (v71 + v27) >> v76;
+    v31 = v28 >> v76;
+    v32 = (signed int)v29->uTextureWidth >> v75;
+    v74 = (signed __int16)v75;
+    v68 = v31;
+    v80 = v32;
+    v33 = (signed int)v29->uTextureHeight >> v75;
+    v34 = v75 - v29->uWidthLn2;
+    a1.field_8 = (v33 << 16) - 65536;
+    v81 = 2 * pMiscTimer->uTotalGameTimeElapsed;
+    a1.field_10 = v34 + 16;
+    a1.field_C = v80 - 1;
+    if ( v66 > 0 )
+    {
+      v74 = v66;
+      v66 = 12 - v75;
+      do
+      {
+        v80 = v5->v_18.y;
+        v35 = (unsigned __int64)(v80 * (signed __int64)v73) >> 16;
+        v36 = v35 + v60;
+        X = v35 + v60;
+        if ( v35 + v60 && (v80 = abs(v62), v37 = abs(v36), v80 <= v37) )
+        {
+          LODWORD(v38) = v77 << 16;
+          HIDWORD(v38) = v77 >> 16;
+          v80 = v38 / X;
+          v39 = v38 / X;
+          X = v38 / X;
+        }
+        else
+        {
+          X = 0x40000000u;
+          v39 = 0x40000000u;
+        }
+        HIWORD(v40) = HIWORD(v39);
+        if ( v39 <= v69 )
+          HIWORD(v40) = HIWORD(v69);
+        LOWORD(v40) = 0;
+        a1.field_24 = v5->field_50 | v40;
+        v79 = v5->ptr_38->field_10;
+        v79 = v67 + ((unsigned __int64)(v79 * (signed __int64)v73) >> 16);
+        v80 = (unsigned __int64)(v79 * (signed __int64)v39) >> 16;
+        v41 = v5->ptr_38;
+        v42 = ((unsigned __int64)(v79 * (signed __int64)v39) >> 16) - v41->field_24;
+        v79 = v41->field_1C;
+        v79 = v70 + ((unsigned __int64)(v79 * (signed __int64)v73) >> 16);
+        v80 = (unsigned __int64)(v79 * (signed __int64)v39) >> 16;
+        v43 = (v71 + v42) >> v76;
+        v79 = (signed int)(v63 + ((unsigned __int64)(v79 * (signed __int64)v39) >> 16) - v5->ptr_38->field_28) >> v76;
+        a1.field_4 = (v43 - v30) >> 4;
+        a1.field_0 = (v79 - v68) >> 4;
+        a1.field_30 = v30 + 4 * stru_5C6E00->SinCos(v81 + (v68 >> v66));
+        v44 = stru_5C6E00->SinCos(v81 + (v30 >> v66) - stru_5C6E00->uIntegerHalfPi);
+        a1.field_2C = v68 + 4 * v44;
+        if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+          sr_sub_485975(&a1, (stru315 *)&a2);
+        else
+          sr_sub_4D6FB0(v2);
+        a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v61, X, v5, pOutdoorCamera->building_gamme, 1u, 0);
+        v73 -= 16 * pOutdoorCamera->int_fov_rad_inv;
+        v45 = v74-- == 1;
+        a1.field_28 = 16;
+        v30 = v43;
+        v68 = v79;
+      }
+      while ( !v45 );
+      v31 = v79;
+    }
+    if ( !v72 )
+      return 1;
+    v66 = 12 - v75;
+    a1.field_30 = v30 + 4 * stru_5C6E00->SinCos(v81 + (v31 >> (12 - v75)));
+    v46 = stru_5C6E00->SinCos(v81 + (v30 >> v66) - stru_5C6E00->uIntegerHalfPi);
+    a1.field_2C = v68 + 4 * v46;
+    v79 = v5->v_18.y;
+    v80 = (unsigned __int64)(v79 * (signed __int64)v73) >> 16;
+    v47 = (unsigned __int64)(v79 * (signed __int64)v73) >> 16;
+    v48 = v47 + v60;
+    X = v47 + v60;
+    if ( v47 + v60 )
+    {
+      v79 = abs(v62);
+      v49 = abs(v48);
+      if ( v79 <= v49 )
+      {
+        LODWORD(v50) = v77 << 16;
+        HIDWORD(v50) = v77 >> 16;
+        v77 = v50 / X;
+        v51 = v50 / X;
+        HIWORD(v52) = HIWORD(v69);
+        if ( v51 <= v69 )
+        {
+          LOWORD(v52) = 0;
+          a1.field_24 = v52 | v5->field_50;
+        }
+        else
+        {
+          HIWORD(v53) = HIWORD(v51);
+          LOWORD(v53) = 0;
+          a1.field_24 = v53 | v5->field_50;
+        }
+        v79 = v5->ptr_38->field_10;
+        v77 = (unsigned __int64)(v79 * (signed __int64)v73) >> 16;
+        v79 = v67 + ((unsigned __int64)(v79 * (signed __int64)v73) >> 16);
+        v67 = (unsigned __int64)(v79 * (signed __int64)v51) >> 16;
+        v54 = v5->ptr_38;
+        v55 = v67 - v54->field_24;
+        v79 = v54->field_1C;
+        v56 = v71 + v55;
+        v71 = (unsigned __int64)(v79 * (signed __int64)v73) >> 16;
+        v57 = v70 + ((unsigned __int64)(v79 * (signed __int64)v73) >> 16);
+        v79 = v57;
+        v58 = v57 * (signed __int64)v51;
+        v70 = v58 >> 16;
+        LODWORD(v58) = (signed int)(v63 + (v58 >> 16) - v5->ptr_38->field_28) >> v76;
+        a1.field_4 = ((v56 >> v76) - v30) >> 4;
+        a1.field_0 = ((signed int)v58 - v68) >> 4;
+        a1.field_28 = v72;
+        if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+          sr_sub_485975(&a1, (stru315 *)&a2);
+        else
+          sr_sub_4D6FB0(v2);
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+// 4D864C: using guessed type char byte_4D864C;
+// 6BE0E4: using guessed type int mipmapping_building_mm1;
+// 6BE0E8: using guessed type int mipmapping_building_mm2;
+// 6BE0EC: using guessed type int mipmapping_building_mm3;
+
+
+
+//----- (0048408A) --------------------------------------------------------
+signed int sr_sub_48408A_prolly_odm_water_no_waves(Span *_this)
+{
+  stru315 *v1; // ebp@0
+  Span *v2; // edi@1
+  stru148 *v3; // esi@1
+  int v4; // ecx@1
+  stru149 *v5; // eax@1
+  stru149 *v6; // eax@1
+  int v7; // edx@1
+  int v8; // eax@1
+  int v9; // ebx@1
+  int v10; // eax@1
+  int v11; // ecx@1
+  int v12; // eax@1
+  int v13; // ecx@1
+  int v14; // eax@1
+  signed int v15; // ecx@1
+  int v16; // ebx@1
+  signed __int64 v17; // qtt@3
+  stru149 *v18; // eax@3
+  int v19; // ebx@3
+  Texture *v20; // eax@4
+  unsigned __int16 *v21; // eax@4
+  Texture *v22; // eax@6
+  Texture *v23; // ecx@8
+  Texture *v24; // eax@10
+  stru149 *v25; // eax@12
+  signed int v26; // eax@12
+  int v27; // ecx@12
+  int v28; // eax@14
+  int v29; // edx@14
+  int v30; // ecx@14
+  Texture *v31; // esi@14
+  int v32; // edx@14
+  int v33; // eax@14
+  int v35; // [sp+Ch] [bp-8Ch]@1
+  int v36; // [sp+10h] [bp-88h]@1
+  stru316 a2; // [sp+14h] [bp-84h]@14
+  stru315 a1; // [sp+3Ch] [bp-5Ch]@1
+  int v39; // [sp+80h] [bp-18h]@1
+  int v40; // [sp+84h] [bp-14h]@1
+  int v41; // [sp+88h] [bp-10h]@1
+  int v42; // [sp+8Ch] [bp-Ch]@1
+  int v43; // [sp+90h] [bp-8h]@2
+  int v44; // [sp+94h] [bp-4h]@1
+
+  v2 = _this;
+  v3 = _this->pParent;
+  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
+  v5 = v3->ptr_38;
+  v44 = v4;
+  v42 = v5->field_14;
+  v44 = (unsigned __int64)(v42 * (signed __int64)v4) >> 16;
+  v6 = v3->ptr_38;
+  v7 = v44 + v6->field_C;
+  v42 = v6->field_20;
+  v39 = v7;
+  v8 = ((unsigned __int64)(v42 * (signed __int64)v4) >> 16) + v3->ptr_38->field_18;
+  v44 = v4;
+  v41 = v8;
+  v42 = v3->v_18.z;
+  v44 = (unsigned __int64)(v42 * (signed __int64)v4) >> 16;
+  v9 = v44 + v3->v_18.x;
+  v35 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY - stru_5C6E00->uIntegerHalfPi);
+  v10 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY);
+  v11 = v2->field_8;
+  v36 = v10;
+  a1.field_28 = v2->field_C;
+  v12 = pViewport->uScreenCenterX - v11;
+  v13 = v3->field_24;
+  v42 = pOutdoorCamera->int_fov_rad_inv * v12;
+  v14 = v3->v_18.y;
+  v15 = -v13;
+  v40 = v15;
+  v16 = ((unsigned __int64)(v42 * (signed __int64)v14) >> 16) + v9;
+  v44 = v16;
+  if ( !v16 || (v43 = abs(v15 >> 14), v43 > abs(v16)) )
+    return 0;
+  LODWORD(v17) = v40 << 16;
+  HIDWORD(v17) = v40 >> 16;
+  v43 = v17 / v44;
+  v18 = v3->ptr_38;
+  v44 = v42;
+  v40 = v18->field_10;
+  v44 = v42;
+  v40 = v39 + ((unsigned __int64)(v40 * (signed __int64)v42) >> 16);
+  v39 = v3->ptr_38->field_1C;
+  v44 = (unsigned __int64)(v39 * (signed __int64)v42) >> 16;
+  v19 = v43;
+  v41 += (unsigned __int64)(v39 * (signed __int64)v42) >> 16;
+  a1.pTextureLOD = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
+  v44 = 2;
+  if ( v43 < mipmapping_terrain_mm1 << 16 )
+  {
+    v20 = v3->pTexture;
+    v44 = 0;
+    v21 = (unsigned __int16 *)v20->pLevelOfDetail0;
+LABEL_11:
+    a1.pTextureLOD = v21;
+    goto LABEL_12;
+  }
+  if ( v43 < mipmapping_terrain_mm2 << 16 )
+  {
+    v22 = v3->pTexture;
+    v44 = 1;
+    v21 = (unsigned __int16 *)v22->pLevelOfDetail1;
+    goto LABEL_11;
+  }
+  if ( v43 >= mipmapping_terrain_mm3 << 16 )
+  {
+    if ( !bUseLoResSprites )
+    {
+      v24 = v3->pTexture;
+      v44 = 3;
+      v21 = (unsigned __int16 *)v24->pLevelOfDetail3;
+      goto LABEL_11;
+    }
+  }
+  else
+  {
+    v23 = v3->pTexture;
+    v44 = 2;
+    a1.pTextureLOD = (unsigned __int16 *)v23->pLevelOfDetail2;
+  }
+LABEL_12:
+  v43 = (unsigned __int64)(v40 * (signed __int64)v43) >> 16;
+  v25 = v3->ptr_38;
+  v43 = v19;
+  a1.field_30 = ((unsigned __int64)(v40 * (signed __int64)v19) >> 16) - v25->field_24;
+  v43 = (unsigned __int64)(v41 * (signed __int64)v19) >> 16;
+  v26 = ((unsigned __int64)(v41 * (signed __int64)v19) >> 16) - v3->ptr_38->field_28;
+  v27 = bUseLoResSprites + v44 + 2;
+  a1.field_30 >>= v27;
+  v41 = bUseLoResSprites + v44 + 2;
+  a1.field_2C = v26 >> v27;
+  if ( byte_80AA10 )
+  {
+    a1.field_14 = dword_80AA20 >> v27;
+    a1.field_18 = dword_80AA1C >> v27;
+    a1.field_1C = dword_80AA18 >> v27;
+    a1.field_20 = dword_80AA14 >> v27;
+  }
+  v41 = pOutdoorCamera->int_fov_rad_inv;
+  v42 = (signed int)((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * (signed __int64)v19) >> 16) >> v27;
+  a1.field_4 = (unsigned __int64)(v42 * (signed __int64)v35) >> 16;
+  v43 = (unsigned __int64)(v42 * (signed __int64)v36) >> 16;
+  a1.field_0 = (unsigned __int64)(v42 * (signed __int64)v36) >> 16;
+  a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v2, v19, v3, pOutdoorCamera->terrain_gamma, 1u, 1);
+  LOWORD(v19) = 0;
+  v28 = v2->field_A;
+  v29 = v2->field_A;
+  a1.field_24 = v19;
+  v30 = v2->field_8;
+  a1.pColorBuffer = &pRenderer->pTargetSurface[v30 + pRenderer->uTargetSurfacePitch * v29];
+  a1.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v30 + 640 * v28];
+  v31 = v3->pTexture;
+  v32 = ((signed int)v31->uTextureWidth >> v44) - 1;
+  v33 = ((signed int)v31->uTextureHeight >> v44 << 16) - 65536;
+  a1.field_10 = v44 - v31->uWidthLn2 + 16;
+  a1.field_C = v32;
+  a1.field_8 = v33;
+  if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+  {
+    if ( byte_80AA10 )
+      sr_sub_485A24(&a1, (stru315 *)&a2);
+    else
+      sr_sub_485975(&a1, (stru315 *)&a2);
+  }
+  else
+  {
+    if ( byte_80AA10 )
+      sr_sub_4D705A(v1);
+    else
+      sr_sub_4D6FB0(v1);
+  }
+  return 1;
+}
+
+
+
+//----- (00484442) --------------------------------------------------------
+signed int sr_sub_484442(Span *_this)
+{
+  int v1; // ebp@0
+  Span *v2; // edi@1
+  stru148 *v3; // esi@1
+  int v4; // ecx@1
+  stru149 *v5; // eax@1
+  stru149 *v6; // eax@1
+  int v7; // edx@1
+  int v8; // eax@1
+  int v9; // ebx@1
+  int v10; // eax@1
+  int v11; // ecx@1
+  int v12; // eax@1
+  int v13; // ecx@1
+  signed int v14; // ecx@1
+  int v15; // ebx@1
+  signed __int64 v16; // qtt@3
+  int v17; // ecx@3
+  int v18; // ebx@3
+  int v19; // eax@3
+  signed int v20; // ebx@3
+  unsigned __int16 *v21; // eax@4
+  stru149 *v22; // eax@12
+  signed int v23; // eax@12
+  int v24; // ecx@12
+  int v25; // ecx@14
+  unsigned int *v26; // eax@14
+  Texture *v27; // esi@14
+  signed int v28; // edi@14
+  signed int v29; // eax@14
+  signed int v31; // [sp+Ch] [bp-90h]@1
+  int v32; // [sp+10h] [bp-8Ch]@1
+  int v33; // [sp+14h] [bp-88h]@1
+  stru316 v34; // [sp+18h] [bp-84h]@14
+  stru315 v35; // [sp+40h] [bp-5Ch]@1
+  int v36; // [sp+84h] [bp-18h]@1
+  int v37; // [sp+88h] [bp-14h]@1
+  int v38; // [sp+8Ch] [bp-10h]@1
+  int v39; // [sp+90h] [bp-Ch]@1
+  int v40; // [sp+94h] [bp-8h]@1
+  int v41; // [sp+98h] [bp-4h]@1
+
+  v2 = _this;
+  v3 = _this->pParent;
+  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
+  v5 = v3->ptr_38;
+  v40 = v4;
+  v39 = v5->field_14;
+  v40 = (unsigned __int64)(v39 * (signed __int64)v4) >> 16;
+  v6 = v3->ptr_38;
+  v7 = v40 + v6->field_C;
+  v39 = v6->field_20;
+  v36 = v7;
+  v8 = ((unsigned __int64)(v39 * (signed __int64)v4) >> 16) + v3->ptr_38->field_18;
+  v40 = v4;
+  v38 = v8;
+  v39 = v3->v_18.z;
+  v40 = (unsigned __int64)(v39 * (signed __int64)v4) >> 16;
+  v9 = v40 + v3->v_18.x;
+  v32 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY - stru_5C6E00->uIntegerHalfPi);
+  v10 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY);
+  v11 = v2->field_8;
+  v33 = v10;
+  v35.field_28 = v2->field_C;
+  v12 = pViewport->uScreenCenterX - v11;
+  v13 = v3->field_24;
+  v41 = pOutdoorCamera->int_fov_rad_inv * v12;
+  v14 = -v13;
+  v31 = v14;
+  v15 = ((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * v12 * (signed __int64)v3->v_18.y) >> 16) + v9;
+  v37 = v15;
+  if ( !v15 || (v39 = abs(v14 >> 14), v39 > abs(v15)) )
+    return 0;
+  LODWORD(v16) = v31 << 16;
+  HIDWORD(v16) = v31 >> 16;
+  v40 = v16 / v37;
+  v17 = v16 / v37;
+  v18 = v41;
+  HIWORD(v19) = (unsigned int)(v16 / v37) >> 16;
+  LOWORD(v19) = 0;
+  v35.field_24 = v19;
+  v37 = v36 + ((unsigned __int64)(v3->ptr_38->field_10 * (signed __int64)v41) >> 16);
+  v36 = v3->ptr_38->field_1C;
+  v41 = (unsigned __int64)(v36 * (signed __int64)v41) >> 16;
+  v38 += (unsigned __int64)(v36 * (signed __int64)v18) >> 16;
+  v20 = 2;
+  v35.pTextureLOD = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
+  if ( v17 < mipmapping_terrain_mm1 << 16 )
+  {
+    v20 = 0;
+    v21 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail0;
+LABEL_11:
+    v35.pTextureLOD = v21;
+    goto LABEL_12;
+  }
+  if ( v17 < mipmapping_terrain_mm2 << 16 )
+  {
+    v20 = 1;
+    v21 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail1;
+    goto LABEL_11;
+  }
+  if ( v17 < mipmapping_terrain_mm3 << 16 )
+  {
+    v21 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
+    goto LABEL_11;
+  }
+  if ( !bUseLoResSprites )
+  {
+    v20 = 3;
+    v21 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail3;
+    goto LABEL_11;
+  }
+LABEL_12:
+  v41 = (unsigned __int64)(v37 * (signed __int64)v17) >> 16;
+  v22 = v3->ptr_38;
+  v41 = v17;
+  v35.field_30 = ((unsigned __int64)(v37 * (signed __int64)v17) >> 16) - v22->field_24;
+  v23 = ((unsigned __int64)(v38 * (signed __int64)v17) >> 16) - v3->ptr_38->field_28;
+  v24 = bUseLoResSprites + v20 + 2;
+  v35.field_30 >>= v24;
+  v38 = bUseLoResSprites + v20 + 2;
+  v35.field_2C = v23 >> v24;
+  if ( byte_80AA10 )
+  {
+    v35.field_14 = dword_80AA20 >> v24;
+    v35.field_18 = dword_80AA1C >> v24;
+    v35.field_1C = dword_80AA18 >> v24;
+    v35.field_20 = dword_80AA14 >> v24;
+  }
+  v38 = pOutdoorCamera->int_fov_rad_inv;
+  v39 = (signed int)((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * (signed __int64)v40) >> 16) >> v24;
+  v35.field_4 = (unsigned __int64)(v39 * (signed __int64)v32) >> 16;
+  v41 = (unsigned __int64)(v39 * (signed __int64)v33) >> 16;
+  v35.field_0 = (unsigned __int64)(v39 * (signed __int64)v33) >> 16;
+  v35.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&v34, v2, v40, v3, pOutdoorCamera->terrain_gamma, 1u, 1);
+  v25 = v2->field_8;
+  v26 = (unsigned int *)&pRenderer->pActiveZBuffer[v25 + 640 * v2->field_A];
+  v35.pColorBuffer = &pRenderer->pTargetSurface[v25 + pRenderer->uTargetSurfacePitch * v2->field_A];
+  v35.pDepthBuffer = v26;
+  v27 = v3->pTexture;
+  v28 = (signed int)v27->uTextureWidth >> v20;
+  v29 = (signed int)v27->uTextureHeight >> v20;
+  v35.field_10 = v20 - v27->uWidthLn2 + 16;
+  v35.field_C = v28 - 1;
+  v35.field_8 = (v29 << 16) - 65536;
+  if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+  {
+    if ( byte_80AA10 )
+      sr_sub_485D3E(&v35, &v34);
+    else
+      sr_sub_485C89(&v35, &v34);
+  }
+  else
+  {
+    if ( byte_80AA10 )
+      sr_sub_4D72EC(v1);
+    else
+      sr_sub_4D73DF(v1);
+  }
+  return 1;
+}
+
+
+//----- (004847EB) --------------------------------------------------------
+int sr_sub_4847EB(Span *_this)
+{
+  stru315 *v1; // ebp@0
+  int v2; // ebx@1
+  int v3; // edx@1
+  stru148 *v4; // esi@1
+  int v5; // eax@1
+  signed int v6; // eax@3
+  int v7; // edi@3
+  stru149 *v8; // eax@3
+  stru149 *v9; // eax@3
+  int v10; // edx@3
+  int v11; // eax@3
+  signed int v12; // ebx@3
+  int v13; // ebx@4
+  signed __int64 v14; // qtt@5
+  int v15; // eax@5
+  signed int v16; // ebx@5
+  unsigned __int16 *v17; // ecx@6
+  stru149 *v18; // eax@14
+  stru149 *v19; // eax@14
+  signed int v20; // eax@14
+  int v21; // ecx@14
+  Texture *v22; // edx@16
+  signed int v23; // eax@16
+  int v24; // ebx@16
+  int v25; // edi@17
+  int v26; // ebx@17
+  int v27; // eax@17
+  int v28; // edi@17
+  int v29; // eax@18
+  signed __int64 v30; // qtt@19
+  int v31; // ecx@19
+  int v32; // eax@19
+  stru149 *v33; // eax@21
+  signed int v34; // edi@21
+  int v35; // ebx@21
+  signed int v36; // edi@21
+  signed __int64 v37; // qtt@21
+  signed int v38; // ebx@21
+  int v39; // ebx@29
+  int v40; // eax@32
+  unsigned __int64 v41; // qax@32
+  int v42; // edi@32
+  int v43; // eax@33
+  signed __int64 v44; // qtt@34
+  int v45; // ecx@34
+  int v46; // eax@34
+  stru149 *v47; // eax@36
+  signed int v48; // edi@36
+  int v49; // eax@36
+  int v50; // eax@47
+  unsigned __int64 v51; // qax@47
+  int v52; // edi@47
+  int v53; // eax@48
+  signed __int64 v54; // qtt@49
+  int v55; // ecx@49
+  int v56; // eax@49
+  stru149 *v57; // eax@51
+  signed int v58; // edi@51
+  int v59; // eax@51
+  Span *v61; // [sp+Ch] [bp-B0h]@1
+  int v62; // [sp+10h] [bp-ACh]@3
+  int v63; // [sp+14h] [bp-A8h]@3
+  int v64; // [sp+18h] [bp-A4h]@3
+  int v65; // [sp+1Ch] [bp-A0h]@3
+  signed int v66; // [sp+20h] [bp-9Ch]@3
+  signed int v67; // [sp+24h] [bp-98h]@3
+  int v68; // [sp+28h] [bp-94h]@1
+  char v69; // [sp+2Ch] [bp-90h]@1
+  stru315 sr; // [sp+30h] [bp-8Ch]@1
+  stru316 sr2; // [sp+74h] [bp-48h]@14
+  int v72; // [sp+9Ch] [bp-20h]@5
+  int v73; // [sp+A0h] [bp-1Ch]@1
+  int v74; // [sp+A4h] [bp-18h]@3
+  int v75; // [sp+A8h] [bp-14h]@21
+  int v76; // [sp+ACh] [bp-10h]@1
+  int v77; // [sp+B0h] [bp-Ch]@14
+  int v78; // [sp+B4h] [bp-8h]@3
+  int v79; // [sp+B8h] [bp-4h]@3
+
+  v2 = _this->field_A;
+  v3 = _this->field_8;
+  v4 = _this->pParent;
+  v73 = 0;
+  v61 = _this;
+  sr.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v3 + 640 * v2];
+  v76 = v3;
+  v5 = _this->field_C;
+  sr.pColorBuffer = &pRenderer->pTargetSurface[v3 + pRenderer->uTargetSurfacePitch * v2];
+  v68 = texmapping_terrain_subdivsize;
+  v69 = texmapping_terrain_subdivpow2;
+  if ( v5 >= texmapping_terrain_subdivsize )
+    v73 = texmapping_terrain_subdivsize - (v3 & (texmapping_terrain_subdivsize - 1));
+  v6 = v5 - v73;
+  v67 = v6 >> texmapping_terrain_subdivpow2;
+  v62 = v6 - (v6 >> texmapping_terrain_subdivpow2 << texmapping_terrain_subdivpow2);
+  v7 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v76);
+  v8 = v4->ptr_38;
+  v79 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v76);
+  v78 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2);
+  v76 = v8->field_14;
+  v78 = (unsigned __int64)(v76 * (signed __int64)(pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2))) >> 16;
+  v9 = v4->ptr_38;
+  v10 = v78 + v9->field_C;
+  v76 = v9->field_20;
+  v65 = v10;
+  v11 = ((unsigned __int64)(v76 * (signed __int64)(pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2))) >> 16)
+      + v4->ptr_38->field_18;
+  v78 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2);
+  v64 = v11;
+  v76 = v4->v_18.z;
+  v78 = (unsigned __int64)(v76 * (signed __int64)(pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2))) >> 16;
+  v12 = -v4->field_24;
+  v63 = v78 + v4->v_18.x;
+  v66 = -v4->field_24;
+  v78 = (unsigned __int64)(v79 * (signed __int64)v4->v_18.y) >> 16;
+  v74 = v78 + v63;
+  if ( !(v78 + v63) || (v76 = v12 >> 14, v13 = abs(v12 >> 14), v13 > abs(v74)) )
+    return 0;
+  LODWORD(v14) = v66 << 16;
+  HIDWORD(v14) = v66 >> 16;
+  v72 = v14 / v74;
+  sr.pTextureLOD = (unsigned __int16 *)v4->pTexture->pLevelOfDetail2;
+  v15 = v14 / v74;
+  v16 = 2;
+  if ( v15 >= mipmapping_terrain_mm1 << 16 )
+  {
+    if ( v15 >= mipmapping_terrain_mm2 << 16 )
+    {
+      if ( v15 >= mipmapping_terrain_mm3 << 16 )
+      {
+        if ( bUseLoResSprites )
+          goto LABEL_14;
+        v16 = 3;
+        v17 = (unsigned __int16 *)v4->pTexture->pLevelOfDetail3;
+      }
+      else
+      {
+        v17 = (unsigned __int16 *)v4->pTexture->pLevelOfDetail2;
+      }
+    }
+    else
+    {
+      v16 = 1;
+      v17 = (unsigned __int16 *)v4->pTexture->pLevelOfDetail1;
+    }
+  }
+  else
+  {
+    v16 = 0;
+    v17 = (unsigned __int16 *)v4->pTexture->pLevelOfDetail0;
+  }
+  sr.pTextureLOD = v17;
+LABEL_14:
+  sr.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&sr2, v61, v15, v4, pOutdoorCamera->terrain_gamma, 1u, 1);
+  v18 = v4->ptr_38;
+  v78 = v7;
+  v79 = v18->field_10;
+  v78 = v7;
+  v77 = v65 + ((unsigned __int64)(v79 * (signed __int64)v7) >> 16);
+  v79 = v4->ptr_38->field_1C;
+  v79 = v64 + ((unsigned __int64)(v79 * (signed __int64)v7) >> 16);
+  v78 = (unsigned __int64)(v77 * (signed __int64)v72) >> 16;
+  v19 = v4->ptr_38;
+  v78 = v72;
+  sr.field_30 = ((unsigned __int64)(v77 * (signed __int64)v72) >> 16) - v19->field_24;
+  v78 = (unsigned __int64)(v79 * (signed __int64)v72) >> 16;
+  v20 = ((unsigned __int64)(v79 * (signed __int64)v72) >> 16) - v4->ptr_38->field_28;
+  v21 = bUseLoResSprites + v16 + 2;
+  sr.field_30 >>= v21;
+  v78 = bUseLoResSprites + v16 + 2;
+  sr.field_2C = v20 >> v21;
+  if ( byte_80AA10 )
+  {
+    sr.field_14 = dword_80AA20 >> v21;
+    sr.field_18 = dword_80AA1C >> v21;
+    sr.field_1C = dword_80AA18 >> v21;
+    sr.field_20 = dword_80AA14 >> v21;
+  }
+  v22 = v4->pTexture;
+  v79 = (signed int)v22->uTextureWidth >> v16;
+  v23 = (signed int)v22->uTextureHeight >> v16;
+  v24 = v16 - v22->uWidthLn2 + 16;
+  sr.field_8 = (v23 << 16) - 65536;
+  sr.field_10 = v24;
+  sr.field_C = v79 - 1;
+  if ( v73 )
+  {
+    v25 = v7 - v73 * pOutdoorCamera->int_fov_rad_inv;
+    v26 = v25;
+    v77 = v4->v_18.y;
+    v79 = v25;
+    v27 = (unsigned __int64)(v77 * (signed __int64)v25) >> 16;
+    v28 = v27 + v63;
+    v74 = v27 + v63;
+    if ( !(v27 + v63) || (v77 = abs(v76), v29 = abs(v28), v77 > v29) )
+      return 0;
+    LODWORD(v30) = v66 << 16;
+    HIDWORD(v30) = v66 >> 16;
+    v77 = v30 / v74;
+    v31 = v30 / v74;
+    HIWORD(v32) = HIWORD(v72);
+    if ( v72 <= v31 )
+      HIWORD(v32) = HIWORD(v31);
+    LOWORD(v32) = 0;
+    v77 = v26;
+    sr.field_24 = v32;
+    v74 = v4->ptr_38->field_10;
+    v74 = v65 + ((unsigned __int64)(v74 * (signed __int64)v26) >> 16);
+    v77 = (unsigned __int64)(v74 * (signed __int64)v31) >> 16;
+    v33 = v4->ptr_38;
+    v77 = v26;
+    v34 = ((unsigned __int64)(v74 * (signed __int64)v31) >> 16) - v33->field_24;
+    v74 = v33->field_1C;
+    v74 = v64 + ((unsigned __int64)(v74 * (signed __int64)v26) >> 16);
+    v77 = (unsigned __int64)(v74 * (signed __int64)v31) >> 16;
+    v35 = (v77 - v4->ptr_38->field_28) >> v78;
+    v74 = v73 << 16;
+    v36 = (v34 >> v78) - sr.field_30;
+    LODWORD(v37) = v36 << 16;
+    HIDWORD(v37) = v36 >> 16;
+    v38 = v35 - sr.field_2C;
+    sr.field_4 = v37 / (v73 << 16);
+    v75 = v73 << 16;
+    LODWORD(v37) = v38 << 16;
+    HIDWORD(v37) = v38 >> 16;
+    v77 = v37 / (v73 << 16);
+    sr.field_0 = v37 / (v73 << 16);
+    sr.field_28 = v73;
+    if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+    {
+      if ( byte_80AA10 )
+        sr_sub_485A24(&sr, (stru315 *)&sr2);
+      else
+        sr_sub_485975(&sr, (stru315 *)&sr2);
+    }
+    else
+    {
+      if ( byte_80AA10 )
+        sr_sub_4D705A(v1);
+      else
+        sr_sub_4D6FB0(v1);
+    }
+    v39 = v79 - (pOutdoorCamera->int_fov_rad_inv << v69);
+  }
+  else
+  {
+    v79 = v7 - (pOutdoorCamera->int_fov_rad_inv << v69);
+    v39 = v7 - (pOutdoorCamera->int_fov_rad_inv << v69);
+  }
+  sr.field_28 = v68;
+  while ( v67 > 0 )
+  {
+    v40 = v4->v_18.y;
+    --v67;
+    v75 = v40;
+    v41 = v40 * (signed __int64)v39;
+    v79 = v41 >> 16;
+    LODWORD(v41) = v41 >> 16;
+    v42 = v41 + v63;
+    v74 = v41 + v63;
+    if ( !((int)v41 + v63) || (v75 = abs(v76), v43 = abs(v42), v75 > v43) )
+      return 0;
+    LODWORD(v44) = v66 << 16;
+    HIDWORD(v44) = v66 >> 16;
+    v73 = v44 / v74;
+    v45 = v44 / v74;
+    HIWORD(v46) = HIWORD(v72);
+    if ( v72 <= v45 )
+      HIWORD(v46) = HIWORD(v45);
+    LOWORD(v46) = 0;
+    v79 = v39;
+    sr.field_24 = v46;
+    v75 = v4->ptr_38->field_10;
+    v75 = v65 + ((unsigned __int64)(v75 * (signed __int64)v39) >> 16);
+    v79 = (unsigned __int64)(v75 * (signed __int64)v45) >> 16;
+    v47 = v4->ptr_38;
+    v79 = v39;
+    v48 = ((unsigned __int64)(v75 * (signed __int64)v45) >> 16) - v47->field_24;
+    v75 = v47->field_1C;
+    v75 = v64 + ((unsigned __int64)(v75 * (signed __int64)v39) >> 16);
+    v79 = (unsigned __int64)(v75 * (signed __int64)v45) >> 16;
+    v49 = (((v79 - v4->ptr_38->field_28) >> v78) - sr.field_2C) >> v69;
+    sr.field_4 = ((v48 >> v78) - sr.field_30) >> v69;
+    sr.field_0 = v49;
+    if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+    {
+      if ( byte_80AA10 )
+        sr_sub_485A24(&sr, (stru315 *)&sr2);
+      else
+        sr_sub_485975(&sr, (stru315 *)&sr2);
+    }
+    else
+    {
+      if ( byte_80AA10 )
+        sr_sub_4D705A(v1);
+      else
+        sr_sub_4D6FB0(v1);
+    }
+    sr.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&sr2, v61, v73, v4, pOutdoorCamera->terrain_gamma, 1u, 0);
+    sr.field_28 = v68;
+    v39 -= pOutdoorCamera->int_fov_rad_inv << v69;
+  }
+  if ( !v62 )
+    return 1;
+  v50 = v4->v_18.y;
+  v75 = v50;
+  v51 = v50 * (signed __int64)v39;
+  v79 = v51 >> 16;
+  LODWORD(v51) = v51 >> 16;
+  v52 = v51 + v63;
+  v74 = v51 + v63;
+  if ( (int)v51 + v63 )
+  {
+    v75 = abs(v76);
+    v53 = abs(v52);
+    if ( v75 <= v53 )
+    {
+      LODWORD(v54) = v66 << 16;
+      HIDWORD(v54) = v66 >> 16;
+      v76 = v54 / v74;
+      v55 = v54 / v74;
+      HIWORD(v56) = HIWORD(v72);
+      if ( v72 <= v55 )
+        HIWORD(v56) = HIWORD(v55);
+      LOWORD(v56) = 0;
+      v76 = v39;
+      sr.field_24 = v56;
+      v75 = v4->ptr_38->field_10;
+      v75 = v65 + ((unsigned __int64)(v75 * (signed __int64)v39) >> 16);
+      v76 = (unsigned __int64)(v75 * (signed __int64)v55) >> 16;
+      v57 = v4->ptr_38;
+      v76 = v39;
+      v58 = ((unsigned __int64)(v75 * (signed __int64)v55) >> 16) - v57->field_24;
+      v75 = v57->field_1C;
+      v75 = v64 + ((unsigned __int64)(v75 * (signed __int64)v39) >> 16);
+      v76 = (unsigned __int64)(v75 * (signed __int64)v55) >> 16;
+      v59 = (((v76 - v4->ptr_38->field_28) >> v78) - sr.field_2C) >> v69;
+      sr.field_4 = ((v58 >> v78) - sr.field_30) >> v69;
+      sr.field_0 = v59;
+      sr.field_28 = v62;
+      if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+      {
+        if ( byte_80AA10 )
+          sr_sub_485A24(&sr, (stru315 *)&sr2);
+        else
+          sr_sub_485975(&sr, (stru315 *)&sr2);
+      }
+      else
+      {
+        if ( byte_80AA10 )
+          sr_sub_4D705A(v1);
+        else
+          sr_sub_4D6FB0(v1);
+      }
+      return 1;
+    }
+  }
+  return 0;
+}
+// 4D864C: using guessed type char byte_4D864C;
+// 6BE050: using guessed type int texmapping_terrain_subdivsize;
+// 6BE054: using guessed type int texmapping_terrain_subdivpow2;
+// 6BE0F0: using guessed type int mipmapping_terrain_mm1;
+// 6BE0F4: using guessed type int mipmapping_terrain_mm2;
+// 6BE0F8: using guessed type int mipmapping_terrain_mm3;
+// 80AA10: using guessed type char byte_80AA10;
+// 80AA14: using guessed type int dword_80AA14;
+// 80AA18: using guessed type int dword_80AA18;
+// 80AA1C: using guessed type int dword_80AA1C;
+// 80AA20: using guessed type int dword_80AA20;
+
+
+
+//----- (00485407) --------------------------------------------------------
+signed int __fastcall sr_sub_485407_prolly_odm_water_wavy(Span *a1)
+{
+  stru315 *v1; // ebp@0
+  int v2; // eax@1
+  int v3; // edx@1
+  unsigned int v4; // edi@1
+  stru148 *v5; // esi@1
+  int v6; // ecx@1
+  int v7; // ebx@1
+  int v8; // ecx@1
+  stru149 *v9; // eax@1
+  stru149 *v10; // eax@1
+  int v11; // edx@1
+  int v12; // eax@1
+  int v13; // eax@1
+  int v14; // ecx@1
+  signed int v15; // edi@1
+  int v16; // edi@2
+  signed __int64 v17; // qtt@3
+  int v18; // edi@3
+  int v19; // eax@3
+  unsigned __int8 *pLOD; // eax@3
+  Texture *v21; // eax@4
+  Texture *v22; // eax@6
+  Texture *v23; // eax@8
+  Texture *v24; // eax@10
+  stru149 *v25; // eax@13
+  stru149 *v26; // eax@13
+  signed int v27; // ebx@13
+  stru149 *v28; // eax@13
+  Texture *v29; // esi@13
+  signed int v30; // ebx@13
+  signed int v31; // edi@13
+  signed int v32; // edx@13
+  signed int v33; // eax@13
+  int v34; // esi@13
+  int v35; // eax@13
+  unsigned __int64 v36; // qax@13
+  int v37; // eax@13
+  unsigned __int64 v38; // qax@13
+  char v39; // cl@14
+  stru316 a2; // [sp+Ch] [bp-90h]@13
+  stru315 a1a; // [sp+34h] [bp-68h]@1
+  Span *v43; // [sp+78h] [bp-24h]@1
+  int v44; // [sp+7Ch] [bp-20h]@1
+  int v45; // [sp+80h] [bp-1Ch]@1
+  int v46; // [sp+84h] [bp-18h]@1
+  Span *v47; // [sp+88h] [bp-14h]@1
+  int v48; // [sp+8Ch] [bp-10h]@1
+  int v49; // [sp+90h] [bp-Ch]@3
+  int i; // [sp+94h] [bp-8h]@3
+  int X; // [sp+98h] [bp-4h]@1
+
+  v2 = a1->field_A;
+  v3 = a1->field_8;
+  v4 = v3 + pRenderer->uTargetSurfacePitch * a1->field_A;
+  v5 = a1->pParent;
+  v43 = a1;
+  v6 = a1->field_C;
+  a1a.pColorBuffer = &pRenderer->pTargetSurface[v4];
+  v46 = v6;
+  v7 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v3);
+  v8 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2);
+  a1a.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v3 + 640 * v2];
+  v9 = v5->ptr_38;
+  v47 = (Span *)v7;
+  X = v8;
+  v48 = v9->field_14;
+  X = (unsigned __int64)(v48 * (signed __int64)v8) >> 16;
+  v10 = v5->ptr_38;
+  v11 = X + v10->field_C;
+  v48 = v10->field_20;
+  v44 = v11;
+  v12 = ((unsigned __int64)(v48 * (signed __int64)v8) >> 16) + v5->ptr_38->field_18;
+  X = v8;
+  v45 = v12;
+  v48 = v5->v_18.z;
+  X = (unsigned __int64)(v48 * (signed __int64)v8) >> 16;
+  v13 = v5->v_18.y;
+  v14 = X + v5->v_18.x;
+  v15 = -v5->field_24;
+  v48 = -v5->field_24;
+  X = ((unsigned __int64)(v7 * (signed __int64)v13) >> 16) + v14;
+  if ( !X || (v16 = abs(v15 >> 14), v16 > abs(X)) )
+    return 0;
+  LODWORD(v17) = v48 << 16;
+  HIDWORD(v17) = v48 >> 16;
+  i = v17 / X;
+  v18 = v17 / X;
+  HIWORD(v19) = (unsigned int)(v17 / X) >> 16;
+  LOWORD(v19) = 0;
+  a1a.field_24 = v19;
+  pLOD = v5->pTexture->pLevelOfDetail2;
+  a1a.pTextureLOD = (unsigned __int16 *)v5->pTexture->pLevelOfDetail2;
+  v49 = 2;
+  if ( v18 >= mipmapping_terrain_mm1 << 16 )
+  {
+    if ( v18 >= mipmapping_terrain_mm2 << 16 )
+    {
+      if ( v18 >= mipmapping_terrain_mm3 << 16 )
+      {
+        if ( bUseLoResSprites )
+          goto LABEL_12;
+        v24 = v5->pTexture;
+        v49 = 3;
+        pLOD = v24->pLevelOfDetail3;
+      }
+      else
+      {
+        v23 = v5->pTexture;
+        v49 = 2;
+        pLOD = v23->pLevelOfDetail2;
+      }
+    }
+    else
+    {
+      v22 = v5->pTexture;
+      v49 = 1;
+      pLOD = v22->pLevelOfDetail1;
+    }
+  }
+  else
+  {
+    v21 = v5->pTexture;
+    v49 = 0;
+    pLOD = v21->pLevelOfDetail0;
+  }
+  a1a.pTextureLOD = (unsigned __int16 *)pLOD;
+LABEL_12:
+  if ( !pLOD )
+    return 0;
+  a1a.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v43, v18, v5, pOutdoorCamera->terrain_gamma, 1u, 1);
+  a1a.field_28 = 16;
+  v43 = (Span *)(v46 >> 4);
+  X = v7;
+  v25 = v5->ptr_38;
+  v48 = v46 - 16 * (v46 >> 4);
+  v46 = v25->field_10;
+  X = v7;
+  v46 = v44 + ((unsigned __int64)(v46 * (signed __int64)v7) >> 16);
+  v44 = v5->ptr_38->field_1C;
+  v45 += (unsigned __int64)(v44 * (signed __int64)v7) >> 16;
+  X = (unsigned __int64)(v46 * (signed __int64)v18) >> 16;
+  v26 = v5->ptr_38;
+  X = v18;
+  v27 = ((unsigned __int64)(v46 * (signed __int64)v18) >> 16) - v26->field_24;
+  X = (unsigned __int64)(v45 * (signed __int64)v18) >> 16;
+  v28 = v5->ptr_38;
+  v29 = v5->pTexture;
+  v44 = bUseLoResSprites + v49 + 2;
+  v30 = v27 >> v44;
+  v31 = (signed int)(((unsigned __int64)(v45 * (signed __int64)v18) >> 16) - v28->field_28) >> v44;
+  v32 = (signed int)v29->uTextureWidth >> v49;
+  v33 = (signed int)v29->uTextureHeight >> v49;
+  v34 = v49 - v29->uWidthLn2;
+  a1a.field_8 = (v33 << 16) - 65536;
+  X = 2 * pMiscTimer->uTotalGameTimeElapsed;
+  v45 = pOutdoorCamera->int_fov_rad_inv;
+  a1a.field_10 = v34 + 16;
+  a1a.field_C = v32 - 1;
+  i = (unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * (signed __int64)i) >> 16;
+  v47 = (Span *)(i >> v44);
+  v35 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY - stru_5C6E00->uIntegerHalfPi);
+  v36 = (signed int)v47 * (signed __int64)v35;
+  i = v36 >> 16;
+  a1a.field_4 = v36 >> 16;
+  v37 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY);
+  v38 = (signed int)v47 * (signed __int64)v37;
+  i = v38 >> 16;
+  a1a.field_0 = v38 >> 16;
+  if ( (signed int)v43 > 0 )
+  {
+    v47 = v43;
+    v39 = 12 - v49;
+    for ( i = 12 - v49; ; v39 = i )
+    {
+      a1a.field_30 = v30 + 4 * stru_5C6E00->SinCos(X + (v31 >> v39));
+      a1a.field_2C = v31 + 4 * stru_5C6E00->SinCos(X + (v30 >> i) - stru_5C6E00->uIntegerHalfPi);
+      if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+        sr_sub_485975(&a1a, (stru315 *)&a2);
+      else
+        sr_sub_4D6FB0(v1);
+      a1a.field_28 = 16;
+      v30 += 16 * a1a.field_4;
+      v31 += 16 * a1a.field_0;
+      v47 = (Span *)((char *)v47 - 1);
+      if ( !v47 )
+        break;
+    }
+  }
+  if ( v48 )
+  {
+    i = 12 - v49;
+    a1a.field_30 = v30 + 4 * stru_5C6E00->SinCos(X + (v31 >> (12 - v49)));
+    a1a.field_2C = v31 + 4 * stru_5C6E00->SinCos(X + (v30 >> i) - stru_5C6E00->uIntegerHalfPi);
+    a1a.field_28 = v48;
+    if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
+      sr_sub_485975(&a1a, (stru315 *)&a2);
+    else
+      sr_sub_4D6FB0(v1);
+  }
+  return 1;
+}
+
+
+//----- (0048585C) --------------------------------------------------------
+signed int __fastcall sr_sub_48585C_mb_DrawSpan(Span *a1, unsigned __int16 *pRenderTarget, int a4)
+{
+  Span *v3; // esi@1
+  stru148 *v4; // edi@1
+  int v5; // ebx@2
+  signed __int64 v6; // qtt@3
+  int v7; // ebx@3
+  signed int v8; // ecx@3
+  void *v9; // eax@5
+  int v10; // ecx@5
+  unsigned __int16 *pPixels; // [sp+Ch] [bp-14h]@1
+  signed int v13; // [sp+10h] [bp-10h]@1
+  int X; // [sp+18h] [bp-8h]@1
+
+  v3 = a1;
+  pPixels = pRenderTarget;
+  v4 = a1->pParent;
+  v13 = -v4->field_24;
+  X = ((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv
+                        * (pViewport->uScreenCenterX - (signed int)a1->field_8)
+                        * (signed __int64)v4->v_18.y) >> 16)
+    + ((unsigned __int64)(v4->v_18.z
+                        * (signed __int64)(pOutdoorCamera->int_fov_rad_inv
+                                         * (pViewport->uScreenCenterY - (signed int)a1->field_A))) >> 16)
+    + v4->v_18.x;
+  if ( X && (v5 = abs(-v4->field_24 >> 14), v5 <= abs(X)) )
+  {
+    LODWORD(v6) = v13 << 16;
+    HIDWORD(v6) = v13 >> 16;
+    v7 = v6 / X;
+    v8 = v6 / X;
+  }
+  else
+  {
+    v7 = pOutdoorCamera->shading_dist_mist << 16;
+    v8 = pOutdoorCamera->shading_dist_mist << 16;
+  }
+  v9 = sr_sub_47C178(v8, v4, pOutdoorCamera->terrain_gamma, a4);
+  fill_pixels_fast(*((short *)v9 + v4->pTexture->uDecompressedSize), pPixels, v3->field_C);
+  HIWORD(v10) = HIWORD(v7);
+  LOWORD(v10) = 0;
+  j_memset32(v10, &pRenderer->pActiveZBuffer[v3->field_8 + 640 * v3->field_A], v3->field_C);
+  return 1;
+}
+
+//----- (00485975) --------------------------------------------------------
+stru315 *__fastcall sr_sub_485975(stru315 *a1, stru315 *a2)
+{
+  stru315 *result; // eax@1
+  int i; // ecx@1
+  int v4; // esi@2
+  int v5; // esi@2
+  int v6; // ecx@2
+  int v7; // esi@3
+  int v8; // edi@3
+  int v9; // ebx@3
+  int v10; // ecx@8
+  unsigned __int16 *v11; // esi@10
+  unsigned int *v12; // ecx@12
+  int v13; // esi@12
+  int v14; // [sp+0h] [bp-4h]@2
+
+  result = a1;
+  for ( i = a1->field_28; i; i = result->field_28 )
+  {
+    v4 = result->field_8 & result->field_2C;
+    result->field_28 = i - 1;
+    v5 = (result->field_C & HIWORD(result->field_30)) + (v4 >> result->field_10);
+    v6 = *((char *)result->pTextureLOD + v5);
+    v14 = *((char *)result->pTextureLOD + v5);
+    if ( a2->field_20 )
+    {
+      v7 = HIWORD(a2->field_10);
+      v8 = a2->field_C;
+      v9 = v7;
+      if ( v7 >= v8 )
+        v9 = a2->field_C;
+      if ( a2->field_8 - v9 <= 0 )
+      {
+        v10 = 0;
+      }
+      else
+      {
+        if ( v7 >= v8 )
+          v7 = a2->field_C;
+        v10 = a2->field_8 - v7;
+      }
+      v11 = (unsigned __int16 *)a2->field_24;
+      v6 = v14 + (v10 << 8);
+    }
+    else
+    {
+      v11 = result->field_34_palette;
+    }
+    *result->pColorBuffer = v11[v6];
+    v12 = result->pDepthBuffer;
+    v13 = result->field_24;
+    ++result->pColorBuffer;
+    *v12 = v13;
+    ++result->pDepthBuffer;
+    a2->field_10 += a2->field_18;
+    result->field_30 += result->field_4;
+    result->field_2C += result->field_0;
+  }
+  --result->field_28;
+  return result;
+}
+
+//----- (00485A24) --------------------------------------------------------
+stru315 *__fastcall sr_sub_485A24(stru315 *a1, stru315 *a2)
+{
+  stru315 *result; // eax@1
+  int i; // ecx@1
+  int v4; // ecx@2
+  int v5; // ecx@4
+  int v6; // ecx@6
+  int v7; // ecx@8
+  int v8; // esi@10
+  int v9; // ecx@10
+  int v10; // esi@11
+  int v11; // edi@11
+  int v12; // ebx@11
+  int v13; // ecx@16
+  unsigned __int16 *v14; // esi@18
+  unsigned int *v15; // ecx@20
+  int v16; // esi@20
+  int v17; // [sp+0h] [bp-4h]@10
+
+  result = a1;
+  for ( i = a1->field_28; i; i = result->field_28 )
+  {
+    result->field_28 = i - 1;
+    v4 = result->field_18;
+    if ( result->field_30 > v4 )
+      result->field_30 = v4;
+    v5 = result->field_20;
+    if ( result->field_2C > v5 )
+      result->field_2C = v5;
+    v6 = result->field_14;
+    if ( result->field_30 < v6 )
+      result->field_30 = v6;
+    v7 = result->field_1C;
+    if ( result->field_2C < v7 )
+      result->field_2C = v7;
+    v8 = (result->field_C & HIWORD(result->field_30)) + ((result->field_2C & result->field_8) >> result->field_10);
+    v9 = *((char *)result->pTextureLOD + v8);
+    v17 = *((char *)result->pTextureLOD + v8);
+    if ( a2->field_20 )
+    {
+      v10 = HIWORD(a2->field_10);
+      v11 = a2->field_C;
+      v12 = v10;
+      if ( v10 >= v11 )
+        v12 = a2->field_C;
+      if ( a2->field_8 - v12 <= 0 )
+      {
+        v13 = 0;
+      }
+      else
+      {
+        if ( v10 >= v11 )
+          v10 = a2->field_C;
+        v13 = a2->field_8 - v10;
+      }
+      v14 = (unsigned __int16 *)a2->field_24;
+      v9 = v17 + (v13 << 8);
+    }
+    else
+    {
+      v14 = result->field_34_palette;
+    }
+    *result->pColorBuffer = v14[v9];
+    v15 = result->pDepthBuffer;
+    v16 = result->field_24;
+    ++result->pColorBuffer;
+    *v15 = v16;
+    ++result->pDepthBuffer;
+    a2->field_10 += a2->field_18;
+    result->field_30 += result->field_4;
+    result->field_2C += result->field_0;
+  }
+  --result->field_28;
+  return result;
+}
+
+//----- (00485AFF) --------------------------------------------------------
+stru315 *__fastcall sr_sub_485AFF(stru315 *a1, stru316 *a2)
+{
+  stru315 *result; // eax@1
+  int i; // ecx@1
+  int v4; // esi@2
+  int v5; // esi@2
+  int v6; // ecx@2
+  int v7; // esi@3
+  int v8; // edi@3
+  int v9; // ebx@3
+  int v10; // ecx@8
+  unsigned __int16 *v11; // esi@10
+  unsigned int *v12; // ecx@12
+  int v13; // esi@12
+  int v14; // [sp+0h] [bp-4h]@2
+
+  result = a1;
+  for ( i = a1->field_28; i; i = result->field_28 )
+  {
+    v4 = result->field_8 & result->field_2C;
+    result->field_28 = i - 1;
+    v5 = (result->field_C & HIWORD(result->field_30)) + (v4 >> result->field_10);
+    v6 = *((char *)result->pTextureLOD + v5);
+    v14 = *((char *)result->pTextureLOD + v5);
+    if ( a2->field_20 )
+    {
+      v7 = HIWORD(a2->field_14);
+      v8 = a2->field_C;
+      v9 = v7;
+      if ( v7 >= v8 )
+        v9 = a2->field_C;
+      if ( a2->field_8 - v9 <= 0 )
+      {
+        v10 = 0;
+      }
+      else
+      {
+        if ( v7 >= v8 )
+          v7 = a2->field_C;
+        v10 = a2->field_8 - v7;
+      }
+      v11 = a2->field_24_palette;
+      v6 = v14 + (v10 << 8);
+    }
+    else
+    {
+      v11 = result->field_34_palette;
+    }
+    *result->pColorBuffer = v11[v6];
+    v12 = result->pDepthBuffer;
+    v13 = result->field_24;
+    --result->pColorBuffer;
+    *v12 = v13;
+    --result->pDepthBuffer;
+    a2->field_14 -= a2->field_18;
+    result->field_30 += result->field_4;
+    result->field_2C += result->field_0;
+  }
+  --result->field_28;
+  return result;
+}
+
+//----- (00485BAE) --------------------------------------------------------
+stru315 *__fastcall sr_sub_485BAE(stru315 *a1, stru316 *a2)
+{
+  stru315 *result; // eax@1
+  int i; // ecx@1
+  int v4; // ecx@2
+  int v5; // ecx@4
+  int v6; // ecx@6
+  int v7; // ecx@8
+  int v8; // esi@10
+  int v9; // ecx@10
+  int v10; // esi@11
+  int v11; // edi@11
+  int v12; // ebx@11
+  int v13; // ecx@16
+  unsigned __int16 *v14; // esi@18
+  unsigned int *v15; // ecx@20
+  int v16; // esi@20
+  int v17; // [sp+0h] [bp-4h]@10
+
+  result = a1;
+  for ( i = a1->field_28; i; i = result->field_28 )
+  {
+    result->field_28 = i - 1;
+    v4 = result->field_18;
+    if ( result->field_30 > v4 )
+      result->field_30 = v4;
+    v5 = result->field_20;
+    if ( result->field_2C > v5 )
+      result->field_2C = v5;
+    v6 = result->field_14;
+    if ( result->field_30 < v6 )
+      result->field_30 = v6;
+    v7 = result->field_1C;
+    if ( result->field_2C < v7 )
+      result->field_2C = v7;
+    v8 = (result->field_C & HIWORD(result->field_30)) + ((result->field_2C & result->field_8) >> result->field_10);
+    v9 = *((char *)result->pTextureLOD + v8);
+    v17 = *((char *)result->pTextureLOD + v8);
+    if ( a2->field_20 )
+    {
+      v10 = HIWORD(a2->field_14);
+      v11 = a2->field_C;
+      v12 = v10;
+      if ( v10 >= v11 )
+        v12 = a2->field_C;
+      if ( a2->field_8 - v12 <= 0 )
+      {
+        v13 = 0;
+      }
+      else
+      {
+        if ( v10 >= v11 )
+          v10 = a2->field_C;
+        v13 = a2->field_8 - v10;
+      }
+      v14 = a2->field_24_palette;
+      v9 = v17 + (v13 << 8);
+    }
+    else
+    {
+      v14 = result->field_34_palette;
+    }
+    *result->pColorBuffer = v14[v9];
+    v15 = result->pDepthBuffer;
+    v16 = result->field_24;
+    --result->pColorBuffer;
+    *v15 = v16;
+    --result->pDepthBuffer;
+    a2->field_14 -= a2->field_18;
+    result->field_30 += result->field_4;
+    result->field_2C += result->field_0;
+  }
+  --result->field_28;
+  return result;
+}
+
+//----- (00485C89) --------------------------------------------------------
+stru315 *__fastcall sr_sub_485C89(stru315 *a1, stru316 *a2)
+{
+  stru315 *result; // eax@1
+  int i; // ecx@1
+  int v4; // esi@2
+  int v5; // esi@2
+  int v6; // ecx@2
+  int v7; // esi@4
+  int v8; // edi@4
+  int v9; // ecx@9
+  unsigned __int16 *v10; // esi@11
+  unsigned int *v11; // ecx@14
+  int v12; // esi@14
+  int v13; // [sp+0h] [bp-4h]@2
+
+  result = a1;
+  for ( i = a1->field_28; i; i = result->field_28 )
+  {
+    v4 = result->field_8 & result->field_2C;
+    result->field_28 = i - 1;
+    v5 = (result->field_C & HIWORD(result->field_30)) + (v4 >> result->field_10);
+    v6 = *((char *)result->pTextureLOD + v5);
+    v13 = *((char *)result->pTextureLOD + v5);
+    if ( *((char *)result->pTextureLOD + v5) )
+    {
+      if ( a2->field_20 )
+      {
+        v7 = HIWORD(a2->field_10);
+        v8 = v7;
+        if ( v7 >= a2->field_C )
+          v8 = a2->field_C;
+        if ( a2->field_8 - v8 <= 0 )
+        {
+          v9 = 0;
+        }
+        else
+        {
+          if ( v7 >= a2->field_C )
+            v7 = a2->field_C;
+          v9 = a2->field_8 - v7;
+        }
+        v10 = a2->field_24_palette;
+        v6 = v13 + (v9 << 8);
+      }
+      else
+      {
+        v10 = result->field_34_palette;
+      }
+      *result->pColorBuffer = v10[v6];
+    }
+    v11 = result->pDepthBuffer;
+    v12 = result->field_24;
+    ++result->pColorBuffer;
+    *v11 = v12;
+    ++result->pDepthBuffer;
+    a2->field_10 += a2->field_18;
+    result->field_30 += result->field_4;
+    result->field_2C += result->field_0;
+  }
+  --result->field_28;
+  return result;
+}
+
+//----- (00485D3E) --------------------------------------------------------
+stru315 *__fastcall sr_sub_485D3E(stru315 *a1, stru316 *a2)
+{
+  stru315 *result; // eax@1
+  int i; // ecx@1
+  int v4; // ecx@2
+  int v5; // ecx@4
+  int v6; // ecx@6
+  int v7; // ecx@8
+  int v8; // esi@10
+  int v9; // ecx@10
+  int v10; // esi@12
+  int v11; // edi@12
+  int v12; // ecx@17
+  unsigned __int16 *v13; // esi@19
+  unsigned int *v14; // ecx@22
+  int v15; // esi@22
+  int v16; // [sp+0h] [bp-4h]@10
+
+  result = a1;
+  for ( i = a1->field_28; i; i = result->field_28 )
+  {
+    result->field_28 = i - 1;
+    v4 = result->field_18;
+    if ( result->field_30 > v4 )
+      result->field_30 = v4;
+    v5 = result->field_20;
+    if ( result->field_2C > v5 )
+      result->field_2C = v5;
+    v6 = result->field_14;
+    if ( result->field_30 < v6 )
+      result->field_30 = v6;
+    v7 = result->field_1C;
+    if ( result->field_2C < v7 )
+      result->field_2C = v7;
+    v8 = (result->field_C & HIWORD(result->field_30)) + ((result->field_2C & result->field_8) >> result->field_10);
+    v9 = *((char *)result->pTextureLOD + v8);
+    v16 = *((char *)result->pTextureLOD + v8);
+    if ( *((char *)result->pTextureLOD + v8) )
+    {
+      if ( a2->field_20 )
+      {
+        v10 = HIWORD(a2->field_10);
+        v11 = v10;
+        if ( v10 >= a2->field_C )
+          v11 = a2->field_C;
+        if ( a2->field_8 - v11 <= 0 )
+        {
+          v12 = 0;
+        }
+        else
+        {
+          if ( v10 >= a2->field_C )
+            v10 = a2->field_C;
+          v12 = a2->field_8 - v10;
+        }
+        v13 = a2->field_24_palette;
+        v9 = v16 + (v12 << 8);
+      }
+      else
+      {
+        v13 = result->field_34_palette;
+      }
+      *result->pColorBuffer = v13[v9];
+    }
+    v14 = result->pDepthBuffer;
+    v15 = result->field_24;
+    ++result->pColorBuffer;
+    *v14 = v15;
+    ++result->pDepthBuffer;
+    a2->field_10 += a2->field_18;
+    result->field_30 += result->field_4;
+    result->field_2C += result->field_0;
+  }
+  --result->field_28;
+  return result;
+}
+
+//----- (00485E1F) --------------------------------------------------------
+void *__fastcall sr_sub_485E1F(stru316 *a1, Span *a2, int a3, stru148 *a4, int a5, unsigned __int8 a6, char a7)
+{
+  stru316 *v7; // esi@1
+  signed int *v8; // edi@1
+  signed int *v9; // ebx@1
+  char v10; // zf@1
+  int v11; // eax@1
+  Span *v12; // ecx@3
+  double v13; // ST24_8@3
+  double v14; // ST24_8@3
+  int v15; // eax@3
+  signed int v16; // ST14_4@4
+  char v17; // dl@4
+  signed int v18; // ST10_4@4
+  void *v19; // eax@4
+  signed int v20; // ST14_4@5
+  char v21; // dl@5
+  int v22; // ST10_4@5
+  signed int v23; // ST14_4@6
+  char v24; // dl@6
+  Span *v26; // [sp+10h] [bp-8h]@1
+  char v27; // [sp+16h] [bp-2h]@1
+  char v28; // [sp+17h] [bp-1h]@1
+  float v29; // [sp+30h] [bp+18h]@3
+  float v30; // [sp+30h] [bp+18h]@3
+
+  v7 = a1;
+  v26 = a2;
+  v8 = &a1->field_C;
+  v9 = &a1->field_8;
+  v10 = a1->field_0 == 0;
+  v27 = a1->field_4 != 0;
+  v28 = !v10;
+  sr_sub_47BEB1(a3, a4, a5, 0, &a1->field_8, &a1->field_C, (int)&v27, (int)&v28);
+  v7->field_24_palette = (unsigned __int16 *)sr_sub_47C28C_get_palette(a4, v28, *v9, *v8);
+  v11 = a4->field_108;
+  v7->field_20 = v11;
+  if ( v11 )
+  {
+    if ( a7 )
+    {
+      v12 = v26;
+      v29 = v26->field_10 * 31.0;
+      v13 = v29 + 6.7553994e15;
+      v7->field_10 = LODWORD(v13) << 16;
+      v30 = v12->field_14 * 31.0;
+      v14 = v30 + 6.7553994e15;
+      v15 = v7->field_10;
+      v7->field_14 = LODWORD(v14) << 16;
+      v7->field_18 = -((v15 - (LODWORD(v14) << 16)) / v12->field_C);
+    }
+    v16 = *v8;
+    v17 = v28;
+    v18 = *v9;
+    v7->field_1C = a6;
+    v19 = sr_sub_47C28C_get_palette(a4, v17, v18, v16);
+  }
+  else
+  {
+    v20 = *v8;
+    v21 = v28;
+    v7->field_10 = 0;
+    v7->field_14 = 0;
+    v22 = *v9;
+    v7->field_18 = 0;
+    v7->field_1C = 0;
+    v19 = sr_sub_47C1CA(a4, v21, v22, v20);
+  }
+  v23 = *v8;
+  v24 = v28;
+  v7->field_24_palette = (unsigned __int16 *)v19;
+  return sr_sub_47C1CA(a4, v24, *v9, v23);
+}
+
+//----- (00485F53) --------------------------------------------------------
+void __thiscall sub_485F53(Vec2_int_ *v)
+{
+  ++v->y;
+  if ( v->y > 1000 )
+    v->y = 0;
+}
+
+
+
+//----- (00485F64) --------------------------------------------------------
+void OutdoorCamera::_485F64()
+{
+  int v1; // eax@1
+  int v2; // eax@2
+  signed __int64 v3; // qtt@4
+  int v4; // eax@4
+
+  this->uCameraFovInDegrees = 75;
+  v1 = stru_5C6E00->uPiMask & 0xD5;
+  if ( v1 >= (signed int)stru_5C6E00->uIntegerHalfPi )
+    v2 = -stru_5C6E00->pTanTable[stru_5C6E00->uIntegerPi - v1];
+  else
+    v2 = stru_5C6E00->pTanTable[v1];
+  LODWORD(v3) = (viewparams->uSomeZ - viewparams->uSomeX) << 31;
+  HIDWORD(v3) = (viewparams->uSomeZ - viewparams->uSomeX) << 15 >> 16;
+  v4 = (signed int)(v3 / v2) >> 16;
+  this->int_fov_rad = v4;
+  this->field_4C = 360000;
+  this->int_fov_rad_inv = 65536 / v4;
+  this->field_50 = 115;
+  unnamed_6BE060[1] = 1;
+  RotationToInts();
+}
+
+//----- (0048600E) --------------------------------------------------------
+void OutdoorCamera::RotationToInts()
+{
+  camera_rotation_y_int_sine   = stru_5C6E00->SinCos(pIndoorCamera->sRotationY - stru_5C6E00->uIntegerHalfPi);
+  camera_rotation_y_int_cosine = stru_5C6E00->SinCos(pIndoorCamera->sRotationY);
+  camera_rotation_x_int_sine   = stru_5C6E00->SinCos(pIndoorCamera->sRotationX - stru_5C6E00->uIntegerHalfPi);
+  camera_rotation_x_int_cosine = stru_5C6E00->SinCos(pIndoorCamera->sRotationX);
+}
+
+
+//----- (0048607B) --------------------------------------------------------
+void stru148::_48607B(stru149 *a2)
+{
+  this->pTexture = 0;
+  this->ptr_38 = a2;
+}
+
+//----- (00486089) --------------------------------------------------------
+void stru148::_486089_normalize_v_18()
+{
+  stru148 *v1; // esi@1
+  double v2; // st7@1
+  double v3; // st6@1
+  float v4; // ST18_4@2
+  double v5; // st5@1
+  float v6; // ST14_4@2
+  double v7; // st7@1
+  float v8; // ST24_4@2
+  float v9; // ST20_4@2
+  double v10; // ST0C_8@2
+  float v11; // ST18_4@2
+  double v12; // ST0C_8@2
+  float v13; // ST14_4@2
+  double v14; // ST0C_8@2
+  float v15; // [sp+20h] [bp-8h]@1
+
+  v1 = this;
+  v2 = (double)this->v_18.x;
+  v15 = v2;
+  v3 = (double)this->v_18.y;
+  v5 = (double)this->v_18.z;
+  v7 = sqrt(v5 * v5 + v3 * v3 + v2 * v2);
+  if ( v7 == 0.0 )
+  {
+    v1->v_18.x = 0;
+    v1->v_18.y = 0;
+    v1->v_18.z = 65536;
+  }
+  else
+  {
+    v8 = 1.0 / v7;
+    v9 = v8 * v15 * 65536.0;
+    v10 = v9 + 6.7553994e15;
+    v1->v_18.x = LODWORD(v10);
+    v4 = v3;
+    v11 = v8 * v4 * 65536.0;
+    v12 = v11 + 6.7553994e15;
+    v1->v_18.y = LODWORD(v12);
+    v6 = v5;
+    v13 = v8 * v6 * 65536.0;
+    v14 = v13 + 6.7553994e15;
+    v1->v_18.z = LODWORD(v14);
+  }
+}
+
+//----- (0048616B) --------------------------------------------------------
+int stru149::_48616B(int a2, int a3, int a4, int a5, int a6, int a7)
+{
+  int v7; // ebx@1
+  int v8; // esi@1
+  int v9; // edi@1
+  int v10; // eax@1
+  int v11; // edx@1
+  int v12; // esi@2
+  int v13; // eax@2
+  int v14; // ST10_4@3
+  int v15; // esi@3
+  int v16; // eax@5
+  int v17; // ST0C_4@6
+  int v18; // eax@8
+  int v19; // ST0C_4@9
+  int v20; // eax@10
+  int v21; // edx@10
+  int v22; // eax@10
+  int result; // eax@10
+  int v24; // [sp+14h] [bp-14h]@1
+  int v25; // [sp+18h] [bp-10h]@1
+  int v26; // [sp+1Ch] [bp-Ch]@1
+  int v27; // [sp+24h] [bp-4h]@1
+  int v28; // [sp+30h] [bp+8h]@10
+  int v29; // [sp+3Ch] [bp+14h]@10
+
+  v25 = pOutdoorCamera->camera_rotation_x_int_cosine;
+  v7 = pOutdoorCamera->camera_rotation_y_int_sine;
+  v27 = pOutdoorCamera->camera_rotation_x_int_sine;
+  v8 = -pIndoorCamera->pos.y;
+  v9 = pOutdoorCamera->camera_rotation_y_int_cosine;
+  v26 = -pIndoorCamera->pos.z;
+  v24 = -pIndoorCamera->pos.x;
+  v10 = pOutdoorCamera->camera_rotation_y_int_cosine * -pIndoorCamera->pos.x;
+  v11 = v10 + pOutdoorCamera->camera_rotation_y_int_sine * -pIndoorCamera->pos.y;
+  if ( pIndoorCamera->sRotationX )
+  {
+    v14 = v10 + pOutdoorCamera->camera_rotation_y_int_sine * -pIndoorCamera->pos.y;
+    v15 = pOutdoorCamera->camera_rotation_y_int_cosine * v8 - pOutdoorCamera->camera_rotation_y_int_sine * v24;
+    this->field_0 = ((unsigned __int64)(v11 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16)
+                  + ((unsigned __int64)(-65536
+                                      * pIndoorCamera->pos.z
+                                      * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
+    this->field_4 = v15;
+    v12 = v25;
+    v13 = ((unsigned __int64)((v26 << 16) * (signed __int64)v25) >> 16)
+        - ((unsigned __int64)(v14 * (signed __int64)v27) >> 16);
+  }
+  else
+  {
+    this->field_4 = pOutdoorCamera->camera_rotation_y_int_cosine * v8 - pOutdoorCamera->camera_rotation_y_int_sine * v24;
+    v12 = v25;
+    this->field_0 = v11;
+    v13 = v26 << 16;
+  }
+  this->field_8 = v13;
+  if ( pIndoorCamera->sRotationX )
+  {
+    v17 = ((unsigned __int64)(a2 * (signed __int64)v9) >> 16) + ((unsigned __int64)(a3 * (signed __int64)v7) >> 16);
+    this->field_C = ((unsigned __int64)(v17 * (signed __int64)v12) >> 16)
+                  + ((unsigned __int64)(a4 * (signed __int64)v27) >> 16);
+    this->field_10 = ((unsigned __int64)(a3 * (signed __int64)v9) >> 16)
+                   - ((unsigned __int64)(a2 * (signed __int64)v7) >> 16);
+    v16 = ((unsigned __int64)(a4 * (signed __int64)v12) >> 16) - ((unsigned __int64)(v17 * (signed __int64)v27) >> 16);
+  }
+  else
+  {
+    this->field_C = ((unsigned __int64)(a2 * (signed __int64)v9) >> 16)
+                  + ((unsigned __int64)(a3 * (signed __int64)v7) >> 16);
+    this->field_10 = ((unsigned __int64)(a3 * (signed __int64)v9) >> 16)
+                   - ((unsigned __int64)(a2 * (signed __int64)v7) >> 16);
+    v16 = a4;
+  }
+  this->field_14 = v16;
+  if ( pIndoorCamera->sRotationX )
+  {
+    v19 = ((unsigned __int64)(a5 * (signed __int64)v9) >> 16) + ((unsigned __int64)(a6 * (signed __int64)v7) >> 16);
+    this->field_18 = ((unsigned __int64)(v19 * (signed __int64)v12) >> 16)
+                   + ((unsigned __int64)(a7 * (signed __int64)v27) >> 16);
+    this->field_1C = ((unsigned __int64)(a6 * (signed __int64)v9) >> 16)
+                   - ((unsigned __int64)(a5 * (signed __int64)v7) >> 16);
+    v18 = ((unsigned __int64)(a7 * (signed __int64)v12) >> 16) - ((unsigned __int64)(v19 * (signed __int64)v27) >> 16);
+  }
+  else
+  {
+    this->field_18 = ((unsigned __int64)(a5 * (signed __int64)v9) >> 16)
+                   + ((unsigned __int64)(a6 * (signed __int64)v7) >> 16);
+    this->field_1C = ((unsigned __int64)(a6 * (signed __int64)v9) >> 16)
+                   - ((unsigned __int64)(a5 * (signed __int64)v7) >> 16);
+    v18 = a7;
+  }
+  this->field_18 = -this->field_18;
+  this->field_1C = -this->field_1C;
+  this->field_20 = v18;
+  v20 = this->field_C;
+  this->field_20 = -this->field_20;
+  v21 = ((unsigned __int64)(v20 * (signed __int64)this->field_0) >> 16)
+      + ((unsigned __int64)(this->field_10 * (signed __int64)this->field_4) >> 16)
+      + ((unsigned __int64)(this->field_14 * (signed __int64)this->field_8) >> 16);
+  v28 = this->field_18;
+  v22 = this->field_0;
+  this->field_24 = v21;
+  v29 = (unsigned __int64)(v28 * (signed __int64)v22) >> 16;
+  result = (unsigned __int64)(this->field_1C * (signed __int64)this->field_4) >> 16;
+  this->field_28 = v29 + result + ((unsigned __int64)(this->field_20 * (signed __int64)this->field_8) >> 16);
+  return result;
+}
+
+//----- (0048653D) --------------------------------------------------------
+int stru149::_48653D(int a2, int a3, int a4, int a5, int a6, int a7)
+{
+  stru149 *v7; // esi@1
+  int v8; // edi@1
+  int v9; // eax@1
+  int v10; // edx@1
+  int v11; // ecx@1
+  int v12; // eax@1
+  int v13; // ebx@2
+  int v14; // ecx@2
+  int v15; // eax@2
+  int v16; // ST14_4@3
+  int v17; // ST10_4@3
+  int v18; // eax@5
+  int v19; // ST10_4@6
+  int v20; // eax@8
+  int v21; // ST10_4@9
+  int v22; // eax@10
+  int v23; // ecx@10
+  int v24; // eax@10
+  int result; // eax@10
+  int v26; // [sp+14h] [bp-14h]@1
+  int v27; // [sp+18h] [bp-10h]@1
+  int v28; // [sp+1Ch] [bp-Ch]@1
+  int v29; // [sp+24h] [bp-4h]@1
+  int v30; // [sp+30h] [bp+8h]@10
+  int v31; // [sp+3Ch] [bp+14h]@10
+
+  v7 = this;
+  v8 = stru_5C6E00->SinCos(pBLVRenderParams->sPartyRotY);
+  v29 = stru_5C6E00->SinCos(pBLVRenderParams->sPartyRotY - stru_5C6E00->uIntegerHalfPi);
+  v28 = stru_5C6E00->SinCos(pBLVRenderParams->sPartyRotX);
+  v9 = stru_5C6E00->SinCos(pBLVRenderParams->sPartyRotX - stru_5C6E00->uIntegerHalfPi);
+  v11 = -pBLVRenderParams->vPartyPos.y;
+  v26 = -pBLVRenderParams->vPartyPos.x;
+  v27 = v9;
+  v12 = -pBLVRenderParams->vPartyPos.z;
+  if ( pBLVRenderParams->sPartyRotX )
+  {
+    v16 = v8 * -pBLVRenderParams->vPartyPos.x + v29 * -pBLVRenderParams->vPartyPos.y;
+    v13 = v28;
+    v17 = -65536 * pBLVRenderParams->vPartyPos.z;
+    v7->field_0 = ((unsigned __int64)(v16 * (signed __int64)v28) >> 16)
+                + ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)v27) >> 16);
+    v7->field_4 = v8 * v11 - v29 * v26;
+    v14 = v27;
+    v15 = ((unsigned __int64)(v17 * (signed __int64)v28) >> 16) - ((unsigned __int64)(v16 * (signed __int64)v27) >> 16);
+  }
+  else
+  {
+    v7->field_0 = v10 + v29 * -pBLVRenderParams->vPartyPos.y;
+    v13 = v28;
+    v7->field_4 = v8 * v11 - v29 * v26;
+    v14 = v27;
+    v15 = v12 << 16;
+  }
+  v7->field_8 = v15;
+  if ( pBLVRenderParams->sPartyRotX )
+  {
+    v19 = ((unsigned __int64)(a2 * (signed __int64)v8) >> 16) + ((unsigned __int64)(a3 * (signed __int64)v29) >> 16);
+    v7->field_C = ((unsigned __int64)(v19 * (signed __int64)v13) >> 16)
+                + ((unsigned __int64)(a4 * (signed __int64)v14) >> 16);
+    v7->field_10 = ((unsigned __int64)(a3 * (signed __int64)v8) >> 16)
+                 - ((unsigned __int64)(a2 * (signed __int64)v29) >> 16);
+    v18 = ((unsigned __int64)(a4 * (signed __int64)v13) >> 16) - ((unsigned __int64)(v19 * (signed __int64)v14) >> 16);
+  }
+  else
+  {
+    v7->field_C = ((unsigned __int64)(a2 * (signed __int64)v8) >> 16)
+                + ((unsigned __int64)(a3 * (signed __int64)v29) >> 16);
+    v7->field_10 = ((unsigned __int64)(a3 * (signed __int64)v8) >> 16)
+                 - ((unsigned __int64)(a2 * (signed __int64)v29) >> 16);
+    v18 = a4;
+  }
+  v7->field_14 = v18;
+  if ( pBLVRenderParams->sPartyRotX )
+  {
+    v21 = ((unsigned __int64)(a5 * (signed __int64)v8) >> 16) + ((unsigned __int64)(a6 * (signed __int64)v29) >> 16);
+    v7->field_18 = ((unsigned __int64)(v21 * (signed __int64)v13) >> 16)
+                 + ((unsigned __int64)(a7 * (signed __int64)v14) >> 16);
+    v7->field_1C = ((unsigned __int64)(a6 * (signed __int64)v8) >> 16)
+                 - ((unsigned __int64)(a5 * (signed __int64)v29) >> 16);
+    v20 = ((unsigned __int64)(a7 * (signed __int64)v13) >> 16) - ((unsigned __int64)(v21 * (signed __int64)v14) >> 16);
+  }
+  else
+  {
+    v7->field_18 = ((unsigned __int64)(a5 * (signed __int64)v8) >> 16)
+                 + ((unsigned __int64)(a6 * (signed __int64)v29) >> 16);
+    v7->field_1C = ((unsigned __int64)(a6 * (signed __int64)v8) >> 16)
+                 - ((unsigned __int64)(a5 * (signed __int64)v29) >> 16);
+    v20 = a7;
+  }
+  v7->field_18 = -v7->field_18;
+  v7->field_1C = -v7->field_1C;
+  v7->field_20 = v20;
+  v22 = v7->field_C;
+  v7->field_20 = -v7->field_20;
+  v23 = ((unsigned __int64)(v22 * (signed __int64)v7->field_0) >> 16)
+      + ((unsigned __int64)(v7->field_10 * (signed __int64)v7->field_4) >> 16)
+      + ((unsigned __int64)(v7->field_14 * (signed __int64)v7->field_8) >> 16);
+  v30 = v7->field_18;
+  v24 = v7->field_0;
+  v7->field_24 = v23;
+  v31 = (unsigned __int64)(v30 * (signed __int64)v24) >> 16;
+  result = (unsigned __int64)(v7->field_1C * (signed __int64)v7->field_4) >> 16;
+  v7->field_28 = v31 + result + ((unsigned __int64)(v7->field_20 * (signed __int64)v7->field_8) >> 16);
+  return result;
+}
+
+//----- (0048694B) --------------------------------------------------------
+int stru149::_48694B()
+{
+  int v1; // eax@1
+  int v2; // ST04_4@1
+  int v3; // ST00_4@1
+  int v4; // eax@1
+  int v5; // ST0C_4@1
+  int result; // eax@1
+
+  v1 = this->field_C;
+  this->field_18 = -this->field_18;
+  this->field_1C = -this->field_1C;
+  this->field_20 = -this->field_20;
+  v2 = (unsigned __int64)(v1 * (signed __int64)this->field_0) >> 16;
+  v3 = this->field_18;
+  v4 = this->field_0;
+  this->field_24 = v2
+                 + ((unsigned __int64)(this->field_10 * (signed __int64)this->field_4) >> 16)
+                 + ((unsigned __int64)(this->field_14 * (signed __int64)this->field_8) >> 16);
+  v5 = (unsigned __int64)(v3 * (signed __int64)v4) >> 16;
+  result = (unsigned __int64)(this->field_1C * (signed __int64)this->field_4) >> 16;
+  this->field_28 = v5 + result + ((unsigned __int64)(this->field_20 * (signed __int64)this->field_8) >> 16);
+  return result;
+}
+
+
+//----- (00486A28) --------------------------------------------------------
+void OutdoorCamera::AllocSoftwareDrawBuffers()
+{
+  if ( !this || !pSpans )
+  {
+    ReleaseSoftwareDrawBuffers();
+    pSpans = (Span *)pAllocator->AllocNamedChunk(pSpans, 0x493E0u, "SPANS");
+    pEdges = (Edge *)pAllocator->AllocNamedChunk(pEdges, 0x4C2C0u, "EDGES");
+    pSurfs = (Surf *)pAllocator->AllocNamedChunk(pSurfs, 0x11940u, "SURFS");
+    pNewEdges = (Edge *)pAllocator->AllocNamedChunk(pNewEdges, 0x6180u, "NEWEDGES");
+    memset(pSpans, 0, 0x493E0u);
+    memset(pEdges, 0, 0x4C2C0u);
+    memset(pSurfs, 0, 0x11940u);
+    memset(pNewEdges, 0, 0x6180u);
+  }
+}
+
+//----- (00486AFC) --------------------------------------------------------
+void OutdoorCamera::ReleaseSoftwareDrawBuffers()
+{
+  pAllocator->FreeChunk(pSpans);
+  pAllocator->FreeChunk(pEdges);
+  pAllocator->FreeChunk(pSurfs);
+  pAllocator->FreeChunk(pNewEdges);
+  pSpans = 0;
+  pEdges = 0;
+  pSurfs = 0;
+  pNewEdges = 0;
+}
+
+//----- (00486B4E) --------------------------------------------------------
+char __fastcall sr_sub_486B4E_push_outdoor_edges(RenderVertexSoft *a1, int *a2, int *a3, stru148 *a4)
+{
+  stru148 *v4; // esi@1
+  RenderVertexSoft *v5; // edi@1
+  char v6; // zf@1
+  unsigned int v7; // eax@3
+  int v8; // ebx@3
+  int *v9; // ecx@7
+  int v10; // ebx@8
+  int v11; // eax@10
+  double v12; // st7@14
+  int *v13; // edx@14
+  double v14; // st6@14
+  double v15; // st7@16
+  int v16; // edi@16
+  double v17; // st7@16
+  double v18; // st7@16
+  int v19; // edi@18
+  double v20; // st7@18
+  double v21; // st7@18
+  Edge *i; // edx@20
+  double v23; // st7@28
+  Edge *v24; // eax@28
+  std::string v26; // [sp-18h] [bp-98h]@2
+  const char *v27; // [sp-8h] [bp-88h]@2
+  int v28; // [sp-4h] [bp-84h]@2
+  double v29; // [sp+Ch] [bp-74h]@28
+  double v30; // [sp+14h] [bp-6Ch]@28
+  double v31; // [sp+1Ch] [bp-64h]@20
+  double v32; // [sp+24h] [bp-5Ch]@16
+  double v33; // [sp+2Ch] [bp-54h]@14
+  unsigned int v34; // [sp+34h] [bp-4Ch]@2
+  unsigned __int64 v35; // [sp+38h] [bp-48h]@28
+  int v36; // [sp+40h] [bp-40h]@28
+  int v37; // [sp+44h] [bp-3Ch]@20
+  float v38; // [sp+48h] [bp-38h]@18
+  int v39; // [sp+4Ch] [bp-34h]@16
+  int v40; // [sp+50h] [bp-30h]@14
+  int v41; // [sp+54h] [bp-2Ch]@3
+  RenderVertexSoft *v42; // [sp+58h] [bp-28h]@1
+  int v43; // [sp+5Ch] [bp-24h]@14
+  int v44; // [sp+60h] [bp-20h]@6
+  int v45; // [sp+64h] [bp-1Ch]@6
+  unsigned int v46; // [sp+68h] [bp-18h]@7
+  int *v47; // [sp+6Ch] [bp-14h]@1
+  int v48; // [sp+70h] [bp-10h]@7
+  float *v49; // [sp+74h] [bp-Ch]@7
+  float v50; // [sp+78h] [bp-8h]@10
+  float v51; // [sp+7Ch] [bp-4h]@14
+
+  v4 = a4;
+  v5 = a1;
+  v47 = a2;
+  v6 = (HIBYTE(a4->flags) & 0x40) == 0;
+  v42 = a1;
+  if ( !v6 )
+  {
+          MessageBoxW(nullptr, L"The Texture Frame Table is not a supported feature.", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odspan.cpp:162", 0);
+  }
+  LOBYTE(v7) = v4->field_108;
+  v8 = v4->uNumVertices;
+  v4->field_108 = 0;
+  BYTE3(a4) = v7;
+  v41 = v8;
+  if ( v8 > 0 )
+  {
+    if ( (signed int)pOutdoorCamera->uNumSurfs < 1999 )
+    {
+      v7 = pOutdoorCamera->uNumEdges;
+      if ( (signed int)pOutdoorCamera->uNumEdges < 5979 )
+      {
+        v4->uEdgeList1Size = 0;
+        v4->uEdgeList2Size = 0;
+        v45 = -1;
+        v34 = v7;
+        v28 = v8;
+        v27 = (const char *)v5;
+        v44 = 10000;
+        pGame->pLightmapBuilder->_45CB89(v5, v8);
+        if ( v8 > 0 )
+        {
+          v9 = a3;
+          v48 = 1;
+          v49 = &v5->flt_2C;
+          v46 = (char *)v47 - (char *)a3;
+          do
+          {
+            v10 = v48;
+            ++pOutdoorCamera->uNumEdges;
+            if ( v48 >= v41 )
+              v10 = 0;
+            v11 = *v9;
+            LODWORD(v50) = *v9;
+            if ( SLODWORD(v50) > v45 )
+              v45 = v11;
+            if ( v11 < v44 )
+              v44 = v11;
+            v12 = (double)SLODWORD(v50);
+            v13 = &a3[v10];
+            v51 = v12;
+            v14 = (double)*v13;
+            v50 = v14;
+            *(float *)&v40 = v14 - v12;
+            v33 = *(float *)&v40 + 6.7553994e15;
+            v43 = LODWORD(v33);
+            if ( LODWORD(v33) )
+            {
+              if ( SLODWORD(v33) >= 0 )
+              {
+                v19 = (int)((char *)v9 + v46);
+                ptr_80C978_Edges->field_8 = 1;
+                LODWORD(v38) = (int)&v47[v10];
+                v40 = *(unsigned int *)LODWORD(v38) - *(int *)v19;
+                v6 = BYTE3(a4) == 0;
+                v20 = (double)v40;
+                v40 = *v13 - *v9;
+                v21 = v20 / (double)v40;
+                ptr_80C978_Edges->field_4 = v21;
+                ptr_80C978_Edges->field_0 = (v51 - (double)*v9) * v21 + (double)*(signed int *)v19;
+                if ( !v6 )
+                {
+                  ptr_80C978_Edges->field_1C = *v49;
+                  ptr_80C978_Edges->field_20 = v42[v10].flt_2C;
+                  ptr_80C978_Edges->field_24 = (double)*(signed int *)v19;
+                  ptr_80C978_Edges->field_28 = (double)(signed int)*(unsigned int *)LODWORD(v38);
+                  ptr_80C978_Edges->field_2C = (double)*v9;
+                  ptr_80C978_Edges->field_30 = (double)*v13;
+                  v4->pEdgeList1[v4->uEdgeList1Size++] = ptr_80C978_Edges;
+                }
+              }
+              else
+              {
+                v32 = v51 + 6.7553994e15;
+                v39 = LODWORD(v32);
+                v51 = v50;
+                v15 = (double)SLODWORD(v32);
+                ptr_80C978_Edges->field_8 = 0;
+                v16 = (int)&v47[v10];
+                v50 = v15;
+                v40 = *(int *)((char *)v9 + v46) - *(int *)v16;
+                v6 = BYTE3(a4) == 0;
+                v17 = (double)v40;
+                v40 = *v9 - *v13;
+                v18 = v17 / (double)v40;
+                ptr_80C978_Edges->field_4 = v18;
+                ptr_80C978_Edges->field_0 = (v51 - (double)*v13) * v18 + (double)*(signed int *)v16;
+                if ( !v6 )
+                {
+                  ptr_80C978_Edges->field_1C = v42[v10].flt_2C;
+                  ptr_80C978_Edges->field_20 = *v49;
+                  ptr_80C978_Edges->field_24 = (double)*(signed int *)v16;
+                  ptr_80C978_Edges->field_28 = (double)*(int *)((char *)v9 + v46);
+                  ptr_80C978_Edges->field_2C = (double)*v13;
+                  ptr_80C978_Edges->field_30 = (double)*v9;
+                  v4->pEdgeList2[v4->uEdgeList2Size++] = ptr_80C978_Edges;
+                }
+              }
+              v31 = v51 + 6.7553994e15;
+              v37 = LODWORD(v31);
+              for ( i = &pNewEdges[LODWORD(v31)]; i->pNext->field_0 < (double)ptr_80C978_Edges->field_0; i = i->pNext )
+                ;
+              if ( i->field_0 != ptr_80C978_Edges->field_0 || i->field_8 || ptr_80C978_Edges->field_8 != 1 )
+              {
+                ptr_80C978_Edges->pNext = i->pNext;
+                i->pNext = ptr_80C978_Edges;
+              }
+              else
+              {
+                ptr_80C978_Edges->pNext = i;
+                i->pPrev->pNext = ptr_80C978_Edges;
+              }
+              v23 = v50 - 1.0;
+              *(float *)&v40 = v23;
+              v38 = v23;
+              v30 = v38 + 6.7553994e15;
+              v36 = LODWORD(v30);
+              ptr_80C978_Edges->ptr_18 = ptr_80CA10[LODWORD(v30)];
+              v29 = *(float *)&v40 + 6.7553994e15;
+              v35 = __PAIR__(v40, LODWORD(v29));
+              v24 = ptr_80C978_Edges;
+              ptr_80CA10[LODWORD(v29)] = ptr_80C978_Edges;
+              v24->pSurf = ptr_80C97C_Surfs;
+              if ( ptr_80C978_Edges < &pEdges[5999] )
+                ++ptr_80C978_Edges;
+            }
+            ++v48;
+            v49 += 12;
+            ++v9;
+          }
+          while ( v48 - 1 < v41 );
+        }
+        LOBYTE(v7) = v34;
+        if ( pOutdoorCamera->uNumEdges != v34 )
+        {
+          v4->ptr_48 = 0;
+          ptr_80C97C_Surfs->field_22 = 0;
+          ptr_80C97C_Surfs->pParent = v4;
+          ptr_80C97C_Surfs->field_4 = v4->field_4;
+          ptr_80C97C_Surfs->field_8 = v4->field_8;
+          ptr_80C97C_Surfs->field_0 = v4->field_0;
+          ptr_80C97C_Surfs->field_C = v4->field_C;
+          ptr_80C97C_Surfs->field_10 = v4->field_10;
+          LOBYTE(v7) = (char)pSurfs + 28;
+          if ( ptr_80C97C_Surfs < &pSurfs[1999] )
+          {
+            ++ptr_80C97C_Surfs;
+            ++pOutdoorCamera->uNumSurfs;
+          }
+          if ( BYTE3(a4) )
+            v4->field_108 = 1;
+        }
+      }
+    }
+  }
+  return v7;
+}
+
+
+
+//----- (0043F953) --------------------------------------------------------
+void PrepareBspRenderList_BLV()
+{
+  pBspRenderer->uNumFaceIDs = 0;
+
+  if (pBLVRenderParams->uPartySectorID)
+  {
+    pBspRenderer->field_FA8[0].uSectorID = pBLVRenderParams->uPartySectorID;
+    pBspRenderer->field_FA8[0].uViewportW = pBLVRenderParams->uViewportW;
+    pBspRenderer->field_FA8[0].uViewportZ = pBLVRenderParams->uViewportZ;
+    pBspRenderer->field_FA8[0].uViewportY = pBLVRenderParams->uViewportY;
+    pBspRenderer->field_FA8[0].uViewportX = pBLVRenderParams->uViewportX;
+    pBspRenderer->field_FA8[0].field_C._43F9E1(
+      pBLVRenderParams->uViewportX,
+      pBLVRenderParams->uViewportY,
+      pBLVRenderParams->uViewportZ,
+      pBLVRenderParams->uViewportW);
+    pBspRenderer->field_FA8[0].uFaceID = -1;
+    pBspRenderer->field_FA8[0].std__vector_0007A8 = -1;
+    pBspRenderer->std__vector_000FA8 = 1;
+    sub_440639(0);
+  }
+
+  pBspRenderer->MakeVisibleSectorList();
+}
+
+//----- (0043F9E1) --------------------------------------------------------
+void BspRenderer_stru2::_43F9E1(__int16 x, int y, __int16 z, int w)
+{
+  _viewport_space_y = y;
+  _viewport_space_w = w;
+
+  for (uint i = 0; i < 480; ++i)
+  {
+    if ( i < y || i > w )
+    {
+      array_3D8[i] = -1;
+      array_18[i] = 640;
+    }
+    else
+    {
+      array_18[i] = x;
+      array_3D8[i] = z;
+    } 
+  }
+}
+
+//----- (0043FA33) --------------------------------------------------------
+void __fastcall PrepareDecorationsRenderList_BLV(unsigned int uDecorationID, unsigned int uSectorID)
+{
+  LevelDecoration *v2; // esi@1
+  DecorationDesc *v3; // ebx@2
+  __int16 v4; // ax@2
+  double v5; // st7@3
+  int v6; // eax@5
+  int v7; // edx@5
+  unsigned int v8; // edi@5
+  int v9; // edi@5
+  int v10; // eax@7
+  SpriteFrame *v11; // eax@7
+  SpriteFrame *v12; // esi@7
+  int v13; // eax@7
+  int v14; // ebx@16
+  RenderBillboard *v15; // ecx@17
+  char v16; // zf@18
+  IndoorCameraD3D **v17; // eax@19
+  double v18; // st7@19
+  float v19; // eax@19
+  signed __int64 v20; // qtt@19
+  signed __int64 v21; // qtt@20
+  int v22; // edx@21
+  int v23; // eax@21
+  Particle_ local_0; // [sp+Ch] [bp-A0h]@3
+  double v25; // [sp+74h] [bp-38h]@19
+  unsigned int v26; // [sp+7Ch] [bp-30h]@1
+  int a2; // [sp+80h] [bp-2Ch]@5
+  int a3; // [sp+84h] [bp-28h]@5
+  int a1; // [sp+88h] [bp-24h]@5
+  int v30; // [sp+8Ch] [bp-20h]@7
+  float v31; // [sp+90h] [bp-1Ch]@1
+  int a5; // [sp+94h] [bp-18h]@17
+  int z; // [sp+98h] [bp-14h]@15
+  int a6; // [sp+9Ch] [bp-10h]@17
+  int y; // [sp+A0h] [bp-Ch]@15
+  int x; // [sp+A4h] [bp-8h]@15
+  int v37; // [sp+A8h] [bp-4h]@5
+
+  v26 = uDecorationID;
+  LODWORD(v31) = uSectorID;
+  v2 = &pLevelDecorations[uDecorationID];
+  if ( !(v2->field_2 & 0x20) )
+  {
+    v3 = &pDecorationList->pDecorations[v2->uDecorationDescID];
+    v4 = v3->uFlags;
+    if ( (char)v4 >= 0 )
+    {
+      if ( !(v4 & DECORATION_DONT_DRAW) )
+      {
+        v6 = v2->vPosition.x;
+        v7 = v2->vPosition.z;
+        a2 = v2->vPosition.y;
+        a1 = v6;
+        a3 = v7;
+        v8 = v2->field_10_y_rot
+           + ((signed int)stru_5C6E00->uIntegerPi >> 3)
+           - stru_5C6E00->Atan2(v6 - pBLVRenderParams->vPartyPos.x, a2 - pBLVRenderParams->vPartyPos.y);
+        v37 = pBLVRenderParams->field_0_timer_;
+        v9 = ((signed int)(stru_5C6E00->uIntegerPi + v8) >> 8) & 7;
+        if ( pParty->bTurnBasedModeOn == 1 )
+          v37 = pMiscTimer->uTotalGameTimeElapsed;
+        v10 = abs(v2->vPosition.x + v2->vPosition.y);
+        v11 = pSpriteFrameTable->GetFrame(v3->uSpriteID, v37 + v10);
+        v30 = 0;
+        v12 = v11;
+        v13 = v11->uFlags;
+        if ( v13 & 2 )
+          v30 = 2;
+        if ( v13 & 0x40000 )
+          v30 |= 0x40u;
+        if ( v13 & 0x20000 )
+          LOBYTE(v30) = v30 | 0x80;
+        if ( (256 << v9) & v13 )
+          v30 |= 4u;
+        if ( pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(a1, a2, a3, &x, &y, &z, 1) )
+        {
+          v14 = abs(x);
+          if ( v14 >= abs(y) )
+          {
+            pGame->pIndoorCameraD3D->Project(x, y, z, &a5, &a6);
+            v15 = &pBillboardRenderList[uNumBillboardsToDraw];
+            if ( (signed int)uNumBillboardsToDraw < 500 )
+            {
+              ++uNumBillboardsToDraw;
+              ++uNumDecorationsDrawnThisFrame;
+              v16 = pRenderer->pRenderD3D == 0;
+              v15->uHwSpriteID = v12->pHwSpriteIDs[v9];
+              v15->uPalette = v12->uPaletteIndex;
+              v15->uIndoorSectorID = LOWORD(v31);
+              if ( v16 )
+              {
+                LODWORD(v21) = pBLVRenderParams->field_40 << 16;
+                HIDWORD(v21) = pBLVRenderParams->field_40 >> 16;
+                v37 = v21 / x;
+                LODWORD(v31) = v12->scale;
+                v37 = v21 / x;
+                v15->field_0 = (unsigned __int64)(SLODWORD(v31) * v21 / x) >> 16;
+                v37 = (unsigned __int64)(v12->scale * (signed __int64)v37) >> 16;
+              }
+              else
+              {
+                v17 = &pGame->pIndoorCameraD3D;
+                v15->fov_x = pGame->pIndoorCameraD3D->fov_x;
+                v18 = (*v17)->fov_y;
+                v19 = v15->fov_x;
+                v15->fov_y = v18;
+                v31 = v19;
+                v25 = v19 + 6.7553994e15;
+                LODWORD(v20) = 0;
+                HIDWORD(v20) = SLOWORD(v25);
+                v37 = v20 / x;
+                LODWORD(v31) = v12->scale;
+                v37 = (unsigned __int64)(SLODWORD(v31) * v20 / x) >> 16;
+                v15->field_0 = (unsigned __int64)(SLODWORD(v31) * v20 / x) >> 16;
+                v31 = v15->fov_y;
+                v25 = v31 + 6.7553994e15;
+                LODWORD(v20) = 0;
+                HIDWORD(v20) = SLOWORD(v25);
+                v37 = v20 / x;
+                v37 = (unsigned __int64)(v12->scale * v20 / x) >> 16;
+              }
+              HIWORD(v22) = HIWORD(x);
+              v15->field_4 = v37;
+              v15->field_1E = v30;
+              v15->some_x = a1;
+              v15->some_y = a2;
+              v15->some_z = a3;
+              v15->uScreenSpaceX = a5;
+              v15->uScreenSpaceY = a6;
+              v23 = 8 * v26;
+              LOBYTE(v23) = 8 * v26 | 5;
+              LOWORD(v22) = 0;
+              v15->uTintColor = 0;
+              v15->sZValue = v22 + v23;
+              v15->pSpriteFrame = v12;
+            }
+          }
+        }
+      }
+    }
+    else
+    {
+      memset(&local_0, 0, 0x68u);               // fire,  like at the Pit's tavern
+      v5 = (double)v2->vPosition.x;
+      local_0.bFree = 1036;
+      local_0.uDiffuse = 0xFF3C1Eu;
+      local_0.x = v5;
+      local_0.y = (double)v2->vPosition.y;
+      local_0.z = (double)v2->vPosition.z;
+      local_0.flt_10 = 0.0;
+      local_0.flt_14 = 0.0;
+      local_0.flt_18 = 0.0;
+      local_0.flt_28 = 1.0;
+      local_0.timeToLive = (rand() & 0x80) + 128;
+      local_0.uTextureID = pBitmaps_LOD->LoadTexture("effpar01");
+      pGame->pParticleEngine->AddParticle(&local_0);
+    }
+  }
+}
+
+
+//----- (0044028F) --------------------------------------------------------
+void PrepareItemsRenderList_BLV()
+{
+  ObjectDesc *v1; // ebx@4
+  __int16 v2; // ax@5
+  RenderBillboard *v3; // esi@12
+  SpriteFrame *v4; // eax@12
+  SpriteFrame *v5; // ebx@12
+  unsigned int v6; // eax@12
+  int v7; // ecx@12
+  int v8; // edx@12
+  int v9; // ecx@12
+  unsigned __int16 v10; // ax@12
+  int *v11; // eax@20
+  char v12; // zf@26
+  int v18; // ST5C_4@27
+  signed __int64 v19; // qtt@28
+  int v20; // ST5C_4@28
+  int v21; // edx@29
+  __int16 v22; // ax@29
+  int v23; // eax@29
+  SpriteFrame *v24; // [sp+1Ch] [bp-40h]@12
+  __int16 a5; // [sp+28h] [bp-34h]@12
+  int a6; // [sp+2Ch] [bp-30h]@12
+  int a2; // [sp+30h] [bp-2Ch]@12
+  int a1; // [sp+34h] [bp-28h]@12
+  int v30; // [sp+38h] [bp-24h]@12
+  int v31; // [sp+38h] [bp-24h]@27
+  int a3; // [sp+40h] [bp-1Ch]@12
+  signed __int16 v34; // [sp+44h] [bp-18h]@14
+  int v35; // [sp+48h] [bp-14h]@25
+  int v36; // [sp+4Ch] [bp-10h]@25
+  signed int z; // [sp+50h] [bp-Ch]@24
+  signed int y; // [sp+54h] [bp-8h]@24
+  signed int x; // [sp+58h] [bp-4h]@24
+
+  for (uint i = 0; i < uNumLayingItems; ++i)
+  {
+    auto p = pLayingItems + i;
+    if (p->uObjectDescID)
+    {
+      v1 = &pObjectList->pObjects[p->uObjectDescID];
+        if ( !(v1->uFlags & 1) )
+         {
+          if ( ((v2 = p->uItemType, v2 < 1000) || v2 >= 10000)
+            && (v2 < 500 || v2 >= 600)
+            && (v2 < 811 || v2 >= 815)
+            || pGame->pStru6Instance->_4A81CA(p))
+          {
+            a5 = p->uSectorID;
+            a1 = p->vPosition.x;
+            a2 = p->vPosition.y;
+            a3 = p->vPosition.z;
+            v3 = &pBillboardRenderList[uNumBillboardsToDraw];
+            v4 = pSpriteFrameTable->GetFrame(v1->uSpriteID, p->uSpriteFrameID);
+            v5 = v4;
+            v24 = v4;
+            v30 = v4->uFlags;
+            a6 = v4->uGlowRadius * p->field_22;
+            v6 = stru_5C6E00->Atan2(
+                   p->vPosition.x - pBLVRenderParams->vPartyPos.x,
+                   p->vPosition.y - pBLVRenderParams->vPartyPos.y);
+            LOWORD(v7) = p->uFacing;
+            v8 = v30;
+            v9 = ((signed int)(stru_5C6E00->uIntegerPi + ((signed int)stru_5C6E00->uIntegerPi >> 3) + v7 - v6) >> 8) & 7;
+            v10 = v5->pHwSpriteIDs[v9];
+            v3->uHwSpriteID = v10;
+            if ( v30 & 0x20 )
+            {
+              v8 = v30;
+              a3 -= (signed int)((unsigned __int64)(v5->scale
+                                                  * (signed __int64)pSprites_LOD->pSpriteHeaders[(signed __int16)v10].uHeight) >> 16) >> 1;
+            }
+            v34 = 0;
+            if ( v8 & 2 )
+              v34 = 2;
+            if ( v8 & 0x40000 )
+              v34 |= 0x40u;
+            if ( v8 & 0x20000 )
+              LOBYTE(v34) = v34 | 0x80;
+            v11 = (int *)(256 << v9);
+            if ( (256 << v9) & v8 )
+              v34 |= 4u;
+            if ( a6 )
+            {
+              LOBYTE(v11) = byte_4E94D3;
+              pMobileLightsStack->AddLight(
+                a1,
+                a2,
+                a3,
+                a5,
+                a6,
+                v1->uParticleTrailColorR,
+                v1->uParticleTrailColorG,
+                v1->uParticleTrailColorB,
+                byte_4E94D3);
+            }
+            if ( pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(
+                   a1,
+                   a2,
+                   a3,
+                   &x,
+                   &y,
+                   &z,
+                   1) )
+            {
+              pGame->pIndoorCameraD3D->Project(x, y, z, &v36, &v35);
+              if ( (signed int)uNumBillboardsToDraw >= 500 )
+                return;
+              ++uNumBillboardsToDraw;
+              ++uNumSpritesDrawnThisFrame;
+              p->uAttributes |= 1u;
+              v12 = pRenderer->pRenderD3D == 0;
+              v3->uPalette = v24->uPaletteIndex;
+              v3->uIndoorSectorID = a5;
+              if ( v12 )
+              {
+                LODWORD(v19) = pBLVRenderParams->field_40 << 16;
+                HIDWORD(v19) = pBLVRenderParams->field_40 >> 16;
+                v20 = v19 / x;
+                v3->field_0 = (unsigned __int64)(v24->scale * v19 / x) >> 16;
+                v31 = (unsigned __int64)(v24->scale * (signed __int64)v20) >> 16;
+              }
+              else
+              {
+                v3->fov_x = pGame->pIndoorCameraD3D->fov_x;
+                v3->fov_y = pGame->pIndoorCameraD3D->fov_y;
+                v18 = (int)floorf(v3->fov_x + 0.5f) / x;
+                v3->field_0 = (unsigned __int64)(v24->scale * (__int64)v18) >> 16;
+                v31 = (unsigned __int64)(v24->scale * (__int64)v18) >> 16;
+              }
+              HIWORD(v21) = HIWORD(x);
+              v3->field_4 = v31;
+              v3->field_1E = v34;
+              v3->some_x = a1;
+              v3->some_y = a2;
+              v3->some_z = a3;
+              v3->uScreenSpaceX = v36;
+              v22 = v35;
+              v3->uTintColor = 0;
+              v3->uScreenSpaceY = v22;
+              LOWORD(v21) = 0;
+              v23 = 8 * i;
+              LOBYTE(v23) = 8 * i | 2;
+              v3->pSpriteFrame = v24;
+              v12 = (p->uAttributes & 0x20) == 0;
+              v3->sZValue = v21 + v23;
+              if ( !v12 )
+              {
+                if ( !pRenderer->pRenderD3D )
+                  v3->sZValue = 0;
+              }
+            }
+          }
+        }
+      }
+  }
+}
+
+
+
+//----- (00440639) --------------------------------------------------------
+void __fastcall sub_440639(int a1)
+{
+  int v1; // ebx@1
+  signed int v2; // edi@1
+  BLVSector *v3; // esi@1
+
+  v1 = a1;
+  v2 = 0;
+  v3 = &pIndoor->pSectors[pBspRenderer->field_FA8[a1].uSectorID];
+  if ( pRenderer->pRenderD3D )
+  {
+    if ( v3->uNumNonBSPFaces > 0 )
+    {
+      do
+      {
+        Log::Warning(L"Non-BSP face: %X", v3->pFaceIDs[v2]);
+        pBspRenderer->PrepareFaceRenderList_d3d(v1, v3->pFaceIDs[v2++]);
+      }
+      while ( v2 < v3->uNumNonBSPFaces );
+    }
+  }
+  else
+  {
+    if ( v3->uNumNonBSPFaces > 0 )
+    {
+      do
+        pBspRenderer->PrepareFaceRenderList_sw(v1, v3->pFaceIDs[v2++]);
+      while ( v2 < v3->uNumNonBSPFaces );
+    }
+  }
+  if ( v3->field_0 & 0x10 )
+    sub_4406BC(v1, v3->uFirstBSPNode);
+}
+
+//----- (004406BC) --------------------------------------------------------
+void __fastcall sub_4406BC(int a1, unsigned int uFirstNode)
+{
+  BLVSector *v2; // esi@2
+  BSPNode *v3; // edi@2
+  BLVFace *v4; // eax@2
+  int v5; // ecx@2
+  __int16 v6; // ax@6
+  int v7; // ebp@10
+  int v8; // ebx@10
+  __int16 v9; // di@18
+  int v10; // [sp+10h] [bp-Ch]@1
+  bool v11; // [sp+14h] [bp-8h]@5
+  BspRenderer_stru0 *v12; // [sp+18h] [bp-4h]@1
+
+  Log::Warning(L"sub_4406BC(%u, %u)", a1, uFirstNode);
+
+  v10 = a1;
+  v12 = &pBspRenderer->field_FA8[a1];
+  while ( 1 )
+  {
+    v2 = &pIndoor->pSectors[v12->uSectorID];
+    v3 = &pIndoor->pNodes[uFirstNode];
+    v4 = &pIndoor->pFaces[v2->pFaceIDs[v3->uCoplanarOffset]];
+    v5 = v4->pFacePlane_old.dist
+       + pBLVRenderParams->vPartyPos.x * v4->pFacePlane_old.vNormal.x
+       + pBLVRenderParams->vPartyPos.y * v4->pFacePlane_old.vNormal.y
+       + pBLVRenderParams->vPartyPos.z * v4->pFacePlane_old.vNormal.z;
+    if ( v4->uAttributes & 1 && v4->uSectorID != v12->uSectorID )
+      v5 = -v5;
+    v11 = v5 > 0;
+    if ( v5 <= 0 )
+      v6 = v3->uFront;
+    else
+      v6 = v3->uBack;
+    if ( v6 != -1 )
+      sub_4406BC(v10, v6);
+    v7 = v3->uCoplanarOffset;
+    v8 = v7 + v3->uCoplanarSize;
+
+    Log::Warning(L"Node %u: %X to %X (%hX)", uFirstNode, v7, v8, v2->pFaceIDs[v7]);
+    
+    if ( pRenderer->pRenderD3D )
+    {
+      while ( v7 < v8 )
+        pBspRenderer->PrepareFaceRenderList_d3d(v10, v2->pFaceIDs[v7++]);
+    }
+    else
+    {
+      while ( v7 < v8 )
+        pBspRenderer->PrepareFaceRenderList_sw(v10, v2->pFaceIDs[v7++]);
+    }
+    v9 = v11 ? v3->uFront : v3->uBack;
+    if ( v9 == -1 )
+      break;
+    uFirstNode = v9;
+  }
+}
+
+//----- (00440DF5) --------------------------------------------------------
+int stru167_wrap::Push(__int16 a2, __int16 a3, __int16 a4, int a5, __int16 bgr)
+{
+  int result; // eax@1
+
+  pElements[uNumElements].field_6_rnd_value = a2;
+  pElements[uNumElements].field_8_rnd_value = a3;
+  pElements[uNumElements].field_A_rnd_value = a4;
+  pElements[uNumElements].field_C_time_left = rand() % 64 + 256;
+  pElements[uNumElements].field_E_time_to_live = pElements[uNumElements].field_C_time_left;
+  result = 3 * uNumElements;
+  pElements[uNumElements++].bgr16 = bgr;
+  if (uNumElements >= 100 )
+    uNumElements = 0;
+   return result;
+}
+
+//----- (00440E91) --------------------------------------------------------
+void stru167_wrap::_440E91(__int16 x, int y, int z, int a5, __int16 bgr)
+{
+  stru167_wrap *v6; // edi@1
+  int i; // esi@1
+  int v8; // ST08_4@2
+  int v9; // ST04_4@2
+  int v10; // eax@2
+
+  v6 = this;
+  for ( i = 0; i < rand() % 6 + 5; ++i )
+  {
+    v8 = z + rand() % 33;
+    v9 = rand() % 33 + y - 16;
+    v10 = rand();
+    Push(v10 % 33 + x - 16, v9, v8, a5, bgr);
+  }
+}
+
+//----- (00440F07) --------------------------------------------------------
+void stru167_wrap::_440F07()
+{
+  for (uint i = 0; i < 100; ++i)
+  {
+    if (pElements[i].field_C_time_left > 0)
+    {
+      pElements[i].field_A_rnd_value += rand() % 5 + 4;
+      pElements[i].field_6_rnd_value += rand() % 5 - 2;
+      pElements[i].field_8_rnd_value += rand() % 5 - 2;
+      pElements[i].field_C_time_left -= (short)pEventTimer->uTimeElapsed;
+    }
+  }
+}
+
+//----- (0044100D) --------------------------------------------------------
+bool __cdecl sub_44100D()
+{
+  return pCurrentScreen == 4
+      || pCurrentScreen == 7
+      || pCurrentScreen > 12
+      && (pCurrentScreen <= 14
+       || pCurrentScreen > 16
+       && (pCurrentScreen <= 18
+        || pCurrentScreen == 23));
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (00441498) --------------------------------------------------------
+void __cdecl GameUI_DrawTorchlightAndWizardEye()
+{
+  unsigned int v0; // eax@15
+  IconFrame *v1; // eax@15
+  unsigned int v2; // eax@19
+  IconFrame *v3; // eax@19
+
+  if ( !pCurrentScreen
+    || pCurrentScreen == 1
+    || pCurrentScreen == 2
+    || pCurrentScreen == 5
+    || pCurrentScreen == 8
+    || pCurrentScreen == 10
+    || pCurrentScreen == 11
+    || pCurrentScreen == 12
+    || pCurrentScreen == 15
+    || pCurrentScreen == 3
+    || pCurrentScreen == 19 )
+  {
+    if ( SHIDWORD(pParty->pPartyBuffs[16].uExpireTime) >= 0
+      && (SHIDWORD(pParty->pPartyBuffs[16].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[16].uExpireTime)) )
+    {
+      v0 = pEventTimer->Time();
+      v1 = pIconsFrameTable->GetFrame((signed __int16)pUIAnum_Torchlight->uIconID, v0);
+      pRenderer->DrawTextureTransparent(
+        pUIAnum_Torchlight->x,
+        pUIAnum_Torchlight->y,
+        &pIcons_LOD->pTextures[v1->uTextureID]);
+    }
+    if ( SHIDWORD(pParty->pPartyBuffs[19].uExpireTime) >= 0
+      && (SHIDWORD(pParty->pPartyBuffs[19].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[19].uExpireTime)) )
+    {
+      v2 = pEventTimer->Time();
+      v3 = pIconsFrameTable->GetFrame((signed __int16)pUIAnim_WizardEye->uIconID, v2);
+      pRenderer->DrawTextureTransparent(
+        pUIAnim_WizardEye->x,
+        pUIAnim_WizardEye->y,
+        &pIcons_LOD->pTextures[v3->uTextureID]);
+    }
+  }
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (0044158F) --------------------------------------------------------
+void __cdecl GameUI_DrawCharacterSelectionFrame()
+{
+  if ( uActiveCharacter )
+    pRenderer->DrawTextureTransparent(
+      pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[uActiveCharacter - 1] - 9,
+      0x17Cu,
+      &pIcons_LOD->pTextures[dword_50C98C]);
+}
+
+
+//----- (004415C5) --------------------------------------------------------
+void __cdecl Load_isn_spells_21_27()
+{
+  signed int v0; // esi@1
+  char pContainer[120]; // [sp+8h] [bp-20h]@2
+
+  v0 = 0;
+  do
+  {
+    sprintf(pContainer, "isn-%02d", v0 + 1);
+    pTextureIDs_isns[v0++] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+  }
+  while ( v0 < 14 );
+  uIconIdx_Spell21 = pIconsFrameTable->FindIcon("spell21");
+  uIconIdx_Spell27 = pIconsFrameTable->FindIcon("spell27");
+}
+
+//----- (0044162D) --------------------------------------------------------
+void __cdecl GameUI_DrawPartySpells()
+{
+  unsigned int v0; // ebp@1
+  signed int v1; // edi@1
+  int v2; // eax@2
+  int v3; // ecx@5
+  __int16 *v4; // ebx@25
+  Player *v5; // edi@26
+  unsigned int v6; // [sp-4h] [bp-1Ch]@11
+  Texture *v7; // [sp-4h] [bp-1Ch]@12
+  unsigned int v8; // [sp-4h] [bp-1Ch]@20
+  Texture *v9; // [sp-4h] [bp-1Ch]@21
+  Player **v10; // [sp+10h] [bp-8h]@25
+
+  v0 = (signed __int64)((double)GetTickCount() * 0.050000001);
+  v1 = 0;
+  do
+  {
+    v2 = (unsigned __int8)byte_4E5DD8[v1];
+    if ( SHIDWORD(pParty->pPartyBuffs[v2].uExpireTime) >= 0
+      && (SHIDWORD(pParty->pPartyBuffs[v2].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[v2].uExpireTime) > 0) )
+    {
+      v3 = pTextureIDs_isns[v1];
+      pRenderer->_4A65CC(
+        pPartySpellbuffsUI_XYs[v1][0],
+        pPartySpellbuffsUI_XYs[v1][1],
+        (Texture *)(v3 != -1 ? &pIcons_LOD->pTextures[v3] : 0),
+        (Texture *)(v3 != -1 ? &pIcons_LOD->pTextures[v3] : 0),
+        v0 + 20 * pPartySpellbuffsUI_smthns[v1],
+        0,
+        63);
+    }
+    ++v1;
+  }
+  while ( v1 < 14 );
+  if ( !pCurrentScreen
+    || pCurrentScreen == 4 )
+  {
+    if ( (signed __int64)pParty->pPartyBuffs[7].uExpireTime > 0 )
+    {
+      if ( pParty->bFlying )
+        v6 = v0;
+      else
+        v6 = 0;
+      v7 = &pIcons_LOD->pTextures[pIconsFrameTable->GetFrame(uIconIdx_Spell21, v6)->uTextureID];
+      if ( pRenderer->pRenderD3D )
+        pRenderer->DrawTextureIndexed(8u, 8u, v7);
+      else
+        pRenderer->DrawTextureTransparent(8u, 8u, v7);
+    }
+    if ( SHIDWORD(pParty->pPartyBuffs[18].uExpireTime) >= 0
+      && (SHIDWORD(pParty->pPartyBuffs[18].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[18].uExpireTime)) )
+    {
+      if ( pParty->uFlags & 0x80 )
+        v8 = v0;
+      else
+        v8 = 0;
+      v9 = &pIcons_LOD->pTextures[pIconsFrameTable->GetFrame(uIconIdx_Spell27, v8)->uTextureID];
+      if ( pRenderer->pRenderD3D )
+        pRenderer->DrawTextureIndexed(396u, 8u, v9);
+      else
+        pRenderer->DrawTextureTransparent(396u, 8u, v9);
+    }
+  }
+
+  uint _it = 0;
+  v10 = &pPlayers[1];
+  v4 = pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing;
+  do
+  {
+    v5 = *v10;
+    if ( (signed __int64)(*v10)->pPlayerBuffs[6].uExpireTime > 0 )
+      pRenderer->DrawTextureIndexed(
+        *v4 + 72,
+        0x1ABu,
+        (Texture *)(dword_507964 != -1 ? &pIcons_LOD->pTextures[dword_507964] : 0));
+    if ( (signed __int64)v5->pPlayerBuffs[1].uExpireTime > 0 )
+      pRenderer->DrawTextureIndexed(
+        *v4 + 72,
+        0x189u,
+        (Texture *)(dword_50796C != -1 ? &pIcons_LOD->pTextures[dword_50796C] : 0));
+    if ( (signed __int64)v5->pPlayerBuffs[11].uExpireTime > 0 )
+      pRenderer->DrawTextureIndexed(
+        *v4 + 72,
+        0x19Au,
+        (Texture *)(dword_507968 != -1 ? &pIcons_LOD->pTextures[dword_507968] : 0));
+    if ( (signed __int64)v5->pPlayerBuffs[10].uExpireTime > 0 )
+      pRenderer->DrawTextureIndexed(
+        *v4 + 72,
+        0x1BCu,
+        (Texture *)(dword_507960 != -1 ? &pIcons_LOD->pTextures[dword_507960] : 0));
+    ++v10;
+    ++v4;
+  }
+  //while ( (signed int)v4 < (signed int)pBaseHealthByClass );
+  while (++_it != 4);
+}
+
+
+//----- (00441A4E) --------------------------------------------------------
+__int16 __fastcall sub_441A4E(int a1)
+{
+  __int16 result; // ax@1
+  int v2; // ebx@1
+  char *v3; // esi@1
+  int v4; // edi@4
+  int v5; // ecx@4
+  SpriteFrame *v6; // eax@6
+  SpriteFrame *v7; // edi@6
+  int v8; // eax@6
+  unsigned __int16 v9; // ax@6
+  RenderBillboardTransform_local0 v10; // [sp+Ch] [bp-5Ch]@1
+  int v11; // [sp+5Ch] [bp-Ch]@6
+  int v12; // [sp+60h] [bp-8h]@1
+  int v13; // [sp+64h] [bp-4h]@6
+
+  v10.uParentBillboardID = -1;
+  v10.pTarget = pRenderer->pTargetSurface;
+  v10.pTargetZ = pRenderer->pActiveZBuffer;
+  v10.uTargetPitch = pRenderer->field_10;
+  result = 0;
+  v2 = a1;
+  v10.uViewportX = 0;
+  v10.uViewportY = 0;
+  v10.uViewportZ = 639;
+  v10.uViewportW = 479;
+  v12 = 0;
+  v3 = (char *)&pOtherOverlayList->pOverlays[0].field_C;
+  do
+  {
+    if ( *((short *)v3 - 3) > 0 )
+    {
+      result = *((short *)v3 - 6);
+      if ( result >= 300 )
+      {
+        v4 = result;
+        v5 = result == v2 + 320 | result == v2 + 330 | result == v2 + 340 | result == v2 + 350;
+        result = v2 + 310;
+        if ( v4 == v2 + 310 | v5 )
+        {
+          if ( !*(short *)v3 )
+          {
+            v6 = pSpriteFrameTable->GetFrame(
+                   pOverlayList->pOverlays[*((short *)v3 - 5)].uSpriteFramesetID,
+                   *((short *)v3 - 4));
+            v7 = v6;
+            v11 = *((int *)v3 + 1);
+            v13 = v6->scale;
+            v13 = (unsigned __int64)(v11 * (signed __int64)v13) >> 16;
+            v10.uScreenSpaceX = *((short *)v3 - 2);
+            v10.uScreenSpaceY = *((short *)v3 - 1);
+            v10.field_10 = v13;
+            v10.field_14 = v13;
+            v10.pPalette = PaletteManager::Get_Dark_or_Red_LUT(v6->uPaletteIndex, 0, 1);
+            v8 = *((short *)v3 - 5);
+            v10.sZValue = 0;
+            v10.uFlags = 0;
+            v9 = pOverlayList->pOverlays[v8].uOverlayType;
+            if ( !v9 || v9 == 2 )
+              v10.uScreenSpaceY += pSprites_LOD->pSpriteHeaders[v7->pHwSpriteIDs[0]].uHeight >> 1;
+            result = pSprites_LOD->pSpriteHeaders[v7->pHwSpriteIDs[0]]._4AD2D1(&v10, 0);
+            ++v12;
+            if ( v12 == 5 )
+              break;
+          }
+        }
+      }
+    }
+    v3 += 20;
+  }
+  while ( (signed int)v3 < (signed int)&pOverlayList->pOverlays );
+  return result;
+}
+
+
+
+//----- (00441D38) --------------------------------------------------------
+void GameUI_DrawMinimap(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW, unsigned int uZoom, unsigned int flags)
+{
+  int uHeight; // ebx@6
+  //unsigned int v9; // edx@9
+  //unsigned int v10; // ebx@10
+  __int16 v11; // cx@11
+  //BLVFace *v12; // ecx@17
+  //unsigned int v13; // ecx@21
+  unsigned int v14; // ebx@23
+  int v15; // eax@23
+  //unsigned int *v16; // ecx@28
+  __int16 v17; // di@30
+  double v18; // st7@30
+  float v19; // ST38_4@30
+  double v20; // st7@30
+  double v21; // st6@30
+  double v22; // st5@33
+  unsigned __int16 *v26; // edx@37
+  signed int v27; // eax@37
+  unsigned __int16 *v28; // ecx@37
+  signed int v29; // edi@40
+  int v30; // eax@42
+  unsigned __int16 *v31; // ebx@43
+  signed int v32; // edi@46
+  signed int v33; // ebx@50
+  unsigned int v34; // eax@50
+  signed int v35; // ecx@50
+  unsigned __int16 v36; // di@66
+  int v37; // edi@72
+  int v38; // ebx@72
+  __int16 v39; // ax@87
+  int v40; // edi@91
+  int v41; // ebx@91
+  unsigned int v42; // eax@101
+  unsigned int v43; // ebx@101
+  unsigned int v44; // ST30_4@101
+  char *v45; // ebx@106
+  int v46; // edi@108
+  int v47; // eax@108
+  unsigned int v48; // ebx@114
+  unsigned int v49; // ST64_4@114
+  double v50; // ST20_8@117
+  unsigned int v51; // [sp-10h] [bp-64h]@79
+  unsigned int v52; // [sp-10h] [bp-64h]@100
+  unsigned int v53; // [sp-Ch] [bp-60h]@79
+  unsigned int v54; // [sp-Ch] [bp-60h]@100
+  unsigned int v55; // [sp-8h] [bp-5Ch]@77
+  unsigned int v56; // [sp-8h] [bp-5Ch]@100
+  signed int v57; // [sp-4h] [bp-58h]@54
+  unsigned __int16 v58; // [sp-4h] [bp-58h]@77
+  unsigned __int16 v59; // [sp-4h] [bp-58h]@100
+  unsigned __int16 v60; // [sp+10h] [bp-44h]@66
+  unsigned int v61; // [sp+10h] [bp-44h]@85
+  unsigned __int16 *v62; // [sp+14h] [bp-40h]@30
+  unsigned int v63; // [sp+14h] [bp-40h]@85
+  int v64; // [sp+18h] [bp-3Ch]@39
+  unsigned int v65; // [sp+18h] [bp-3Ch]@85
+  unsigned int lPitch; // [sp+20h] [bp-34h]@1
+  unsigned int lPitcha; // [sp+20h] [bp-34h]@23
+  char *lPitchb; // [sp+20h] [bp-34h]@106
+  unsigned int v69; // [sp+24h] [bp-30h]@23
+  signed int v70; // [sp+24h] [bp-30h]@37
+  unsigned __int16 uBlue; // [sp+28h] [bp-2Ch]@1
+  signed int uBluea; // [sp+28h] [bp-2Ch]@37
+  int v73; // [sp+2Ch] [bp-28h]@30
+  unsigned __int8 *v74; // [sp+30h] [bp-24h]@30
+  int v76; // [sp+34h] [bp-20h]@91
+  int v77; // [sp+34h] [bp-20h]@108
+  signed int v78; // [sp+38h] [bp-1Ch]@37
+  int v79; // [sp+38h] [bp-1Ch]@72
+  signed int a2b; // [sp+40h] [bp-14h]@41
+  char *a2c; // [sp+40h] [bp-14h]@68
+  int a3a; // [sp+44h] [bp-10h]@40
+  signed int uCenterY; // [sp+48h] [bp-Ch]@1
+  signed int uCenterX; // [sp+4Ch] [bp-8h]@1
+  //signed int uZb; // [sp+5Ch] [bp+8h]@27
+  signed int uWidth; // [sp+5Ch] [bp+8h]@30
+  signed int uZd; // [sp+5Ch] [bp+8h]@45
+  signed int uZe; // [sp+5Ch] [bp+8h]@67
+  signed int uZf; // [sp+5Ch] [bp+8h]@85
+  signed int uZg; // [sp+5Ch] [bp+8h]@105
+  unsigned int uWa; // [sp+60h] [bp+Ch]@23
+  float uWb; // [sp+60h] [bp+Ch]@30
+  unsigned __int16 *uWc; // [sp+60h] [bp+Ch]@37
+  unsigned int uWd; // [sp+60h] [bp+Ch]@95
+  float uZooma; // [sp+64h] [bp+10h]@117
+  signed int flagsa; // [sp+68h] [bp+14h]@42
+  unsigned int flagsb; // [sp+68h] [bp+14h]@66
+  char *flagsc; // [sp+68h] [bp+14h]@86
+  unsigned int flagsd; // [sp+68h] [bp+14h]@105
+
+  //a3 = uY;
+  //a2 = uX;
+  uCenterX = (uX + uZ) / 2;
+  uCenterY = (uY + uW) / 2;
+  lPitch = pRenderer->uTargetSurfacePitch;
+  GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0, 0);
+  uBlue = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0, 0xFFu);
+  auto bWizardEyeActive = pParty->WizardEyeActive();
+  auto uWizardEyeSkillLevel = pParty->WizardEyeSkillLevel();
+  if (CheckHiredNPCSpeciality(0x26u))
+  {
+    bWizardEyeActive = true;
+    uWizardEyeSkillLevel = 2;
+  }
+  pRenderer->Clip_v2(uX, uY, uZ - 1, uW - 1);
+  uHeight = uW - uY;
+  uWidth = uZ - uX;
+
+  if ( uCurrentlyLoadedLevelType != LEVEL_Indoor)
+  {
+    v17 = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uWidthLn2;
+    v74 = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].pLevelOfDetail0;
+    v62 = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].pPalette16;
+    v73 = (1 << (v17 + 16)) / (signed int)uZoom;
+    v18 = (double)(1 << (16 - v17));
+    v19 = v18;
+    v20 = (double)(pParty->vPosition.x + 32768) / v18;
+    v21 = (double)(32768 - pParty->vPosition.y) / v19;
+    uWb = v21;
+    if ( uZoom == 512 )
+    {
+      v20 = v20 - (double)(uWidth / 2);
+      v22 = (double)(uHeight / 2);
+    }
+    else
+    {
+      if ( uZoom == 1024 )
+      {
+        v20 = v20 - (double)(uWidth / 4);
+        v22 = (double)(uHeight / 4);
+      }
+      else
+      {
+        if ( uZoom != 2048 )
+          goto LABEL_37;
+        v20 = v20 - (double)(uWidth / 8);
+        v22 = (double)(uHeight / 8);
+      }
+    }
+    uWb = v21 - v22;
+LABEL_37:
+    //v23 = v20 * 65536.0;
+    //v24 = v23 + 6.7553994e15;
+    v70 = floorf(v20 * 65536.0 + 0.5f);//LODWORD(v24);
+    //uWe = uWb * 65536.0;
+    //v25 = uWe + 6.7553994e15;
+    v78 = v70;
+    uBluea = floorf(uWb * 65536.0 + 0.5f);//LODWORD(v25);
+    v26 = (unsigned __int16 *)_56EFD8_minimap;
+    v27 = uBluea >> 16;
+    uWc = (unsigned __int16 *)_56EFD8_minimap;
+    v28 = &pRenderer->pTargetSurface[uX + uY * lPitch];
+    if ( flags )
+    {
+      if ( v74 )
+      {
+        v64 = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uTextureWidth;
+        if ( uHeight > 0 )
+        {
+          a3a = uHeight;
+          v29 = v70 >> 16;
+          do
+          {
+            a2b = 0;
+            if ( uWidth > 0 )
+            {
+              v30 = (int)&v74[v27 * v64];
+              flagsa = uWidth;
+              a2b = uWidth;
+              do
+              {
+                v31 = uWc;
+                ++uWc;
+                *v31 = v62[*(char *)(v30 + v29)];
+                v78 += v73;
+                v29 = v78 >> 16;
+                --flagsa;
+              }
+              while ( flagsa );
+            }
+            v78 = v70;
+            v29 = v70 >> 16;
+            v28 += 137 - a2b;
+            uBluea += v73;
+            v27 = uBluea >> 16;
+            --a3a;
+          }
+          while ( a3a );
+        }
+      }
+    }
+    uZd = 117;
+    do
+    {
+      v32 = 137;
+      do
+      {
+        *v28 = *v26;
+        ++v28;
+        ++v26;
+        --v32;
+      }
+      while ( v32 );
+      v28 += lPitch - 137;
+      --uZd;
+    }
+    while ( uZd );
+    uNumBlueFacesInBLVMinimap = 0;
+  }
+  else
+  {
+    pRenderer->FillRectFast(uX, uY, uZ - uX, uHeight, 0xF);
+    uNumBlueFacesInBLVMinimap = 0;
+
+    for (uint i = 0; i < pIndoor->pMapOutlines->uNumOutlines; ++i)
+    {
+      auto pOutline = &pIndoor->pMapOutlines->pOutlines[i];
+
+      auto pFace1 = pIndoor->pFaces + pOutline->uFace1ID;
+      auto pFace2 = pIndoor->pFaces + pOutline->uFace2ID;
+      //v9 = pIndoor->pFaces[pMapVertex->uFace1ID].uAttributes;
+        //v10 = pIndoor->pFaces[pMapVertex->uFace2ID].uAttributes;
+      if (pFace1->Visible() && pFace2->Visible())
+      {
+        v11 = pOutline->uFlags;
+        if ( v11 & 1 )
+          goto LABEL_15;
+        if (pFace1->uAttributes & 0x80 || pFace2->uAttributes & 0x80u != 0 )
+          goto LABEL_ABC;
+
+      }
+      continue;
+
+LABEL_ABC:
+    pOutline->uFlags = v11 | 1;
+    pIndoor->_visible_outlines[i >> 3] |= 1 << (7 - i % 8);
+
+LABEL_15:
+    //v12 = &pIndoor->pFaces[pOutline->uFace1ID];
+    if (bWizardEyeActive && uWizardEyeSkillLevel >= 3 &&
+        (pFace1->uAttributes & 0x2000000 || pFace2->uAttributes & 0x2000000) &&
+        (pIndoor->pFaceExtras[pFace1->uFaceExtraID].uEventID || pIndoor->pFaceExtras[pFace2->uFaceExtraID].uEventID))
+    {
+      if (uNumBlueFacesInBLVMinimap < 49)
+        pBlueFacesInBLVMinimapIDs[uNumBlueFacesInBLVMinimap++] = i;
+    }
+    else
+    {
+      auto _a = (uZoom * (signed __int64)pIndoor->pVertices[pOutline->uVertex1ID].x);
+      auto _b = ((unsigned int)((unsigned __int64)_a >> 16) << 16);
+      auto _c = ((signed int)(_b - uZoom * pParty->vPosition.x) >> 16);
+      v69 =     uCenterX + _c;
+      v69 =     uCenterX + ((signed int)(((unsigned int)((unsigned __int64)(uZoom * (signed __int64)pIndoor->pVertices[pOutline->uVertex1ID].x) >> 16) << 16) - uZoom * pParty->vPosition.x) >> 16);
+      lPitcha = uCenterY - ((signed int)(((unsigned int)((unsigned __int64)(uZoom * (signed __int64)pIndoor->pVertices[pOutline->uVertex1ID].y) >> 16) << 16) - uZoom * pParty->vPosition.y) >> 16);
+      uWa =     uCenterX + ((signed int)(((unsigned int)((unsigned __int64)(uZoom * (signed __int64)pIndoor->pVertices[pOutline->uVertex2ID].x) >> 16) << 16) - uZoom * pParty->vPosition.x) >> 16);
+      v14 =     uCenterY - ((signed int)(((unsigned int)((unsigned __int64)(uZoom * (signed __int64)pIndoor->pVertices[pOutline->uVertex2ID].y) >> 16) << 16) - uZoom * pParty->vPosition.y) >> 16);
+      v15 = abs(pOutline->sZ - pParty->vPosition.z) / 8;
+      if ( v15 > 100 )
+        v15 = 100;
+      pRenderer->Line2D(v69, lPitcha, uWa, v14, viewparams->pPalette[-v15 + 200]);
+    }
+  }
+
+
+  for (uint i = 0; i < uNumBlueFacesInBLVMinimap; ++i)
+  {
+    //v16 = (uint *)&pIndoor->pMapOutlines->pOutlines[pBlueFacesInBLVMinimapIDs[uZb]];
+    auto pOutline = &pIndoor->pMapOutlines->pOutlines[pBlueFacesInBLVMinimapIDs[i]];
+    pRenderer->Line2D(
+      uCenterX
+    + ((signed int)(((unsigned int)((unsigned __int64)((signed int)uZoom
+                                                     * (signed __int64)pIndoor->pVertices[pOutline->uVertex1ID].x) >> 16) << 16)
+                  - uZoom * pParty->vPosition.x) >> 16),
+      uCenterY
+    - ((signed int)(((unsigned int)((unsigned __int64)((signed int)uZoom
+                                                     * (signed __int64)pIndoor->pVertices[pOutline->uVertex1ID].y) >> 16) << 16)
+                  - uZoom * pParty->vPosition.y) >> 16),
+      uCenterX
+    + ((signed int)(((unsigned int)((unsigned __int64)((signed int)uZoom
+                                                     * (signed __int64)pIndoor->pVertices[pOutline->uVertex2ID].x) >> 16) << 16)
+                  - uZoom * pParty->vPosition.x) >> 16),
+      uCenterY
+    - ((signed int)(((unsigned int)((unsigned __int64)((signed int)uZoom
+                                                     * (signed __int64)pIndoor->pVertices[pOutline->uVertex2ID].y) >> 16) << 16)
+                  - uZoom * pParty->vPosition.y) >> 16),
+      uBlue);
+  }
+  }
+
+
+//_draw_party_arrow:
+  v33 = 0;
+  v34 = pParty->sRotationY & stru_5C6E00->uDoublePiMask;
+  v35 = 0;
+  if ( (signed int)(pParty->sRotationY & stru_5C6E00->uDoublePiMask) < 128 )
+    goto LABEL_66;
+  if ( (signed int)v34 <= 384 )
+  {
+    v35 = 1;
+    goto LABEL_66;
+  }
+  if ( (signed int)v34 >= 640 )
+  {
+    if ( (signed int)v34 > 896 )
+    {
+      if ( (signed int)v34 >= 1152 )
+      {
+        if ( (signed int)v34 > 1408 )
+        {
+          if ( (signed int)v34 >= 1664 )
+          {
+            if ( (signed int)v34 > 1920 )
+              goto LABEL_66;
+            v57 = 7;
+          }
+          else
+          {
+            v57 = 6;
+          }
+        }
+        else
+        {
+          v57 = 5;
+        }
+      }
+      else
+      {
+        v57 = 4;
+      }
+    }
+    else
+    {
+      v57 = 3;
+    }
+  }
+  else
+  {
+    v57 = 2;
+  }
+  v35 = v57;
+LABEL_66:
+  pRenderer->DrawTextureTransparent(
+    uCenterX - 3,
+    uCenterY - 3,
+    (Texture *)(pTextureIDs_pMapDirs[v35] != -1 ? (int)&pIcons_LOD->pTextures[pTextureIDs_pMapDirs[v35]] : 0));
+  v36 = 255;
+  flagsb = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0, 0xFFu);
+  v60 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0, 0);
+  if ( bWizardEyeActive )
+  {
+    uZe = 0;
+    //for (uint i = 0; i < uNumLayingItems; ++i)
+    if (uNumLayingItems > 0)
+    {
+      a2c = (char *)&pLayingItems[0].uObjectDescID;
+      while ( 1 )
+      {
+        if ( !*((short *)a2c - 1)
+          || !*(short *)a2c
+          || uWizardEyeSkillLevel == 1
+          || (v37 = ((unsigned __int64)((*(int *)(a2c + 2) - pParty->vPosition.x) * (signed __int64)(signed int)uZoom) >> 16)
+                  + uCenterX,
+              v79 = (unsigned __int64)((*(int *)(a2c + 6) - pParty->vPosition.y) * (signed __int64)(signed int)uZoom) >> 16,
+              v38 = uCenterY - v79,
+              v37 < pRenderer->field_1C_clipx)
+          || v37 > pRenderer->field_24_clipz
+          || v38 < pRenderer->field_20_clipy
+          || v38 > pRenderer->field_28_clipw )
+          goto LABEL_83;
+        if ( pObjectList->pObjects[*(short *)a2c].uFlags & 0x10 )
+          break;
+        if ( (signed int)uZoom > 512 )
+        {
+          pRenderer->Line2D(v37 - 1, v38 - 1, v37 - 1, v38 + 1, flagsb);
+          pRenderer->Line2D(v37, v38 - 2, v37, v38 + 1, flagsb);
+          pRenderer->Line2D(v37 + 1, v38 - 1, v37 + 1, v38 + 1, flagsb);
+          pRenderer->Line2D(v37 - 2, v38, v37 - 2, v38 + 1, flagsb);
+          v37 += 2;
+          v58 = flagsb;
+          v55 = v38 + 1;
+          goto LABEL_81;
+        }
+        pRenderer->Line2D(v37 - 1, v38 - 1, v37 - 1, uCenterY - v79, flagsb);
+        v58 = flagsb;
+        v55 = uCenterY - v79;
+        v53 = v37;
+        v51 = v38 - 1;
+LABEL_82:
+        pRenderer->Line2D(v37, v51, v53, v55, v58);
+LABEL_83:
+        ++uZe;
+        a2c += 112;
+        if ( uZe >= (signed int)uNumLayingItems )
+        {
+          v36 = 255;
+          v33 = 0;
+          goto LABEL_85;
+        }
+      }
+      v58 = v60;
+      v55 = uCenterY - v79;
+LABEL_81:
+      v53 = v37;
+      v51 = uCenterY - v79;
+      goto LABEL_82;
+    }
+LABEL_85:
+    v63 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v36, 0, v33);
+    v61 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, v36, v33);
+    v65 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v36, v36, v33);
+    uZf = v33;
+    if ( (signed int)uNumActors > v33 )
+    {
+      flagsc = (char *)&pActors[0].uAIState;
+      do
+      {
+        v39 = *(short *)flagsc;
+        if ( *(short *)flagsc != 11 && v39 != 19 && (v39 == 5 || *(flagsc - 139) & 0x80) )
+        {
+          v40 = ((unsigned __int64)(((signed int)*((short *)flagsc - 17) - pParty->vPosition.x)
+                                  * (signed __int64)(signed int)uZoom) >> 16)
+              + uCenterX;
+          v76 = (unsigned __int64)(((signed int)*((short *)flagsc - 16) - pParty->vPosition.y)
+                                 * (signed __int64)(signed int)uZoom) >> 16;
+          v41 = uCenterY - v76;
+          if ( v40 >= pRenderer->field_1C_clipx )
+          {
+            if ( v40 <= pRenderer->field_24_clipz && v41 >= pRenderer->field_20_clipy && v41 <= pRenderer->field_28_clipw )
+            {
+              uWd = v61;
+              if ( *(flagsc - 137) & 1 )
+                uWd = v63;
+              if ( *(short *)flagsc == 5 )
+                uWd = v65;
+              if ( (signed int)uZoom > 1024 )
+              {
+                pRenderer->Line2D(v40 - 1, v41 - 2, v40 - 1, v41 + 2, uWd);
+                pRenderer->Line2D(v40, v41 - 2, v40, v41 + 2, uWd);
+                pRenderer->Line2D(v40 + 1, v41 - 2, v40 + 1, v41 + 2, uWd);
+                v42 = v41 + 1;
+                v43 = v41 - 1;
+                v44 = v42;
+                pRenderer->Line2D(v40 - 2, v43, v40 - 2, v42, uWd);
+                v40 += 2;
+                v59 = uWd;
+                v56 = v44;
+                v54 = v40;
+                v52 = v43;
+              }
+              else
+              {
+                pRenderer->Line2D(v40 - 1, v41 - 1, v40 - 1, uCenterY - v76, uWd);
+                v59 = uWd;
+                v56 = uCenterY - v76;
+                v54 = v40;
+                v52 = v41 - 1;
+              }
+              pRenderer->Line2D(v40, v52, v54, v56, v59);
+            }
+          }
+        }
+        ++uZf;
+        flagsc += 836;
+      }
+      while ( uZf < (signed int)uNumActors );
+      v36 = 255;
+      v33 = 0;
+    }
+  }
+  flagsd = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v36, v36, v36);
+  uZg = v33;
+  if ( (signed int)uNumLevelDecorations > v33 )
+  {
+    v45 = (char *)&pLevelDecorations[0].vPosition;
+    lPitchb = (char *)&pLevelDecorations[0].vPosition;
+    do
+    {
+      if ( *(v45 - 2) & 8 )
+      {
+        v46 = ((unsigned __int64)((*(int *)v45 - pParty->vPosition.x) * (signed __int64)(signed int)uZoom) >> 16)
+            + uCenterX;
+        v77 = (unsigned __int64)((*((int *)v45 + 1) - pParty->vPosition.y) * (signed __int64)(signed int)uZoom) >> 16;
+        v47 = uCenterY - v77;
+        if ( v46 >= pRenderer->field_1C_clipx )
+        {
+          if ( v46 <= pRenderer->field_24_clipz && v47 >= pRenderer->field_20_clipy && v47 <= pRenderer->field_28_clipw )
+          {
+            if ( (signed int)uZoom > 512 )
+            {
+              v48 = v47 + 1;
+              v49 = v47 - 1;
+              pRenderer->Line2D(v46 - 1, v47 - 1, v46 - 1, v47 + 1, flagsd);
+              pRenderer->Line2D(v46, v49, v46, v48, flagsd);
+              pRenderer->Line2D(v46 + 1, v49, v46 + 1, v48, flagsd);
+              v45 = lPitchb;
+            }
+            else
+            {
+              pRenderer->Line2D(v46, uCenterY - v77, v46, uCenterY - v77, flagsd);
+            }
+          }
+        }
+      }
+      ++uZg;
+      v45 += 32;
+      lPitchb = v45;
+    }
+    while ( uZg < (signed int)uNumLevelDecorations );
+    v33 = 0;
+  }
+  pRenderer->DrawTextureTransparent(
+    0x1D4u,
+    v33,
+    (Texture *)(dword_5079D8 != -1 ? &pIcons_LOD->pTextures[dword_5079D8] : 0));
+  uZooma = (double)pParty->sRotationY * 0.1171875;
+  v50 = uZooma + 6.7553994e15;
+  pRenderer->Clip(0x21Du, v33, 0x237u, 0x1E0u);
+  pRenderer->DrawTextureIndexed(
+    LODWORD(v50) + 285,
+    0x88u,
+    (Texture *)(dword_5079B4 != -1 ? &pIcons_LOD->pTextures[dword_5079B4] : 0));
+  pRenderer->ResetClip();
+}
+
+
+//----- (00442955) --------------------------------------------------------
+int __fastcall DrawSpellbook_Map_sub(unsigned int x, unsigned int y, unsigned int a4, int a5, int _48074)
+{
+  int v5; // ebx@1
+  int v6; // edi@1
+  unsigned int *v7; // eax@8
+  unsigned __int8 v8; // zf@8
+  unsigned __int8 v9; // sf@8
+  int v10; // esi@10
+  unsigned int v11; // edx@11
+  __int16 v12; // cx@12
+  signed int v13; // eax@15
+  int v14; // eax@16
+  Vec3_short_ *v15; // ecx@16
+  int v16; // edx@16
+  int v17; // ecx@16
+  Vec3_short_ *v18; // eax@16
+  int v19; // ecx@16
+  int v20; // eax@16
+  signed int v21; // esi@18
+  int v22; // ecx@21
+  int v23; // ecx@21
+  Vec3_short_ *v24; // edx@21
+  Vec3_short_ *v25; // eax@21
+  int v26; // ecx@21
+  unsigned __int16 *v27; // edi@21
+  int v28; // edx@21
+  int v29; // eax@21
+  double v30; // st7@23
+  signed __int64 v31; // qax@23
+  char *v32; // edx@23
+  int v33; // esi@23
+  signed int v34; // eax@23
+  signed int v35; // ecx@23
+  int v36; // esi@27
+  int v37; // ecx@27
+  int v38; // edx@31
+  unsigned int v39; // eax@33
+  const void *v40; // esi@33
+  unsigned __int16 *v41; // edi@33
+  unsigned __int8 v42; // cf@33
+  unsigned int v43; // ecx@33
+  int v44; // edi@33
+  int v45; // esi@33
+  int v46; // ecx@33
+  signed int v47; // esi@38
+  signed int v48; // ecx@38
+  int v49; // eax@38
+  signed int v50; // edx@55
+  unsigned int v51; // ecx@55
+  int result; // eax@72
+  int v53; // eax@75
+  int v54; // esi@75
+  int v55; // eax@75
+  __int16 v56; // si@85
+  double v57; // st7@85
+  int v58; // ebx@85
+  signed __int64 v59; // qax@85
+  signed int v60; // edi@85
+  signed __int64 v61; // qax@85
+  signed int v62; // ebx@85
+  signed int v63; // esi@85
+  int v64; // eax@87
+  unsigned int v65; // ebx@95
+  char *v66; // edx@95
+  unsigned __int16 *v67; // esi@96
+  int v68; // edi@98
+  unsigned __int16 v69; // cx@99
+  unsigned int v70; // [sp-10h] [bp-48074h]@80
+  unsigned int v71; // [sp-Ch] [bp-48070h]@80
+  unsigned int v72; // [sp-8h] [bp-4806Ch]@80
+  signed int v73; // [sp-4h] [bp-48068h]@59
+  unsigned __int16 v74; // [sp-4h] [bp-48068h]@79
+  char v75; // [sp+Ch] [bp-48058h]@23
+  int v76; // [sp+4800Ch] [bp-58h]@23
+  unsigned __int16 *v77; // [sp+48010h] [bp-54h]@27
+  unsigned __int16 *v78; // [sp+48014h] [bp-50h]@23
+  unsigned int v79; // [sp+48018h] [bp-4Ch]@1
+  unsigned int y_; // [sp+4801Ch] [bp-48h]@1
+  int v81; // [sp+48020h] [bp-44h]@23
+  unsigned int x_; // [sp+48024h] [bp-40h]@1
+  unsigned int teal; // [sp+48028h] [bp-3Ch]@8
+  int v84; // [sp+4802Ch] [bp-38h]@1
+  int v85; // [sp+48030h] [bp-34h]@1
+  int v86; // [sp+48034h] [bp-30h]@1
+  int v87; // [sp+48038h] [bp-2Ch]@16
+  unsigned int v88; // [sp+4803Ch] [bp-28h]@16
+  int black; // [sp+48040h] [bp-24h]@8
+  int v90; // [sp+48044h] [bp-20h]@1
+  unsigned int i; // [sp+48048h] [bp-1Ch]@9
+  unsigned int v92; // [sp+4804Ch] [bp-18h]@16
+  unsigned __int16 *v93; // [sp+48050h] [bp-14h]@16
+  unsigned int v94; // [sp+48054h] [bp-10h]@8
+  unsigned int v95; // [sp+48058h] [bp-Ch]@16
+  int v96; // [sp+4805Ch] [bp-8h]@10
+  const void *v97; // [sp+48060h] [bp-4h]@16
+  char *a4a; // [sp+4806Ch] [bp+8h]@85
+  int a5a; // [sp+48070h] [bp+Ch]@86
+
+  x_ = x;
+  y_ = y;
+  v85 = (signed int)(x + a4) >> 1;
+  v90 = (signed int)(y + a5) >> 1;
+  v79 = pRenderer->uTargetSurfacePitch;
+  pRenderer->Clip_v2(x, y, a4, a5);
+  v5 = viewparams->field_2C;
+  v6 = viewparams->sPartyPosX;
+  v86 = viewparams->sPartyPosX;
+  v84 = viewparams->sPartyPosZ;
+  if ( viewparams->field_2C != 384 )
+  {
+    if ( viewparams->field_2C == 768 )
+    {
+      if ( uCurrentlyLoadedLevelType != LEVEL_Indoor)
+        goto LABEL_23;
+      v5 = 680;
+    }
+    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+      goto LABEL_8;
+LABEL_23:
+    v94 = a4 - x_ + 1;
+    v92 = a5 - y_ + 1;
+    v93 = &pRenderer->pTargetSurface[x_ + y_ * v79];
+    v95 = (unsigned int)pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].pLevelOfDetail0;
+    v78 = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].pPalette16;
+    v87 = (1 << (pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uWidthLn2 + 16)) / v5;
+    v30 = (double)(1 << (16 - pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uWidthLn2));
+    black = 22528 / (v5 / 384);
+    teal = (unsigned int)(signed __int64)((double)(v6 - 22528 / (v5 / 384) + 32768) / v30) << 16;
+    v97 = (const void *)((unsigned int)(signed __int64)((double)(v6 - 22528 / (v5 / 384) + 32768) / v30) << 16);
+    v96 = 32768 - black - v84;
+    v31 = (signed __int64)((double)v96 / v30);
+    v32 = &v75;
+    v33 = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uTextureWidth;
+    v34 = (int)v31 << 16;
+    v81 = (signed __int16)(signed __int64)((double)(v6 - 22528 / (v5 / 384) + 32768) / v30);
+    black = (signed __int16)(signed __int64)((double)(v6 - 22528 / (v5 / 384) + 32768) / v30);
+    v76 = v33;
+    v35 = v34 >> 16;
+    if ( v95 && (signed int)v92 > 0 )
+    {
+      v96 = v92;
+      do
+      {
+        v88 = 0;
+        if ( (signed int)v94 > 0 )
+        {
+          v36 = v95 + v35 * v76;
+          i = v94;
+          v88 = v94;
+          v37 = black;
+          v77 = (unsigned __int16 *)v36;
+          do
+          {
+            *(short *)v32 = v78[*((char *)v77 + v37)];
+            v32 += 2;
+            v97 = (char *)v97 + v87;
+            v37 = (signed int)v97 >> 16;
+            --i;
+          }
+          while ( i );
+        }
+        v34 += v87;
+        v97 = (const void *)teal;
+        black = v81;
+        v32 += 2 * (v94 - v88);
+        v35 = v34 >> 16;
+        --v96;
+      }
+      while ( v96 );
+    }
+    v97 = &v75;
+    if ( (signed int)v92 > 0 )
+    {
+      v96 = v92;
+      v38 = 2 * (v79 - v94);
+      do
+      {
+        if ( (signed int)v94 > 0 )
+        {
+          v39 = v94;
+          v40 = v97;
+          v41 = v93;
+          v42 = v94 & 1;
+          v43 = v94 >> 1;
+          memcpy(v93, v97, 4 * (v94 >> 1));
+          v45 = (int)((char *)v40 + 4 * v43);
+          v44 = (int)&v41[2 * v43];
+          v46 = v42;
+          v39 *= 2;
+          v93 = (unsigned __int16 *)((char *)v93 + v39);
+          v97 = (char *)v97 + v39;
+          while ( v46 )
+          {
+            *(short *)v44 = *(short *)v45;
+            v45 += 2;
+            v44 += 2;
+            --v46;
+          }
+          v6 = v86;
+        }
+        v93 = (unsigned __int16 *)((char *)v93 + v38);
+        --v96;
+      }
+      while ( v96 );
+    }
+    goto LABEL_38;
+  }
+  v6 = viewparams->field_38;
+  v86 = viewparams->field_38;
+  v84 = viewparams->field_3A;
+  if ( uCurrentlyLoadedLevelType != LEVEL_Indoor)
+    goto LABEL_23;
+  v5 = viewparams->field_2C - 34;
+LABEL_8:
+  black = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0, 0);
+  teal = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0xFFu);
+  v7 = (uint *)pIndoor->pMapOutlines;
+  uNumBlueFacesInBLVMinimap = 0;
+  v8 = pIndoor->pMapOutlines->uNumOutlines == 0;
+  v9 = (pIndoor->pMapOutlines->uNumOutlines & 0x80000000u) != 0;
+  v94 = 0;
+  if ( !(v9 | v8) )
+  {
+    i = 0;
+    do
+    {
+      v10 = (int)((char *)v7 + i + 4);
+      v96 = pIndoor->pFaces[*(short *)((char *)v7 + i + 8)].uAttributes;
+      if ( BYTE1(v96) & 0x20 || (v11 = pIndoor->pFaces[*(short *)((char *)v7 + i + 10)].uAttributes, BYTE1(v11) & 0x20) )
+        goto LABEL_17;
+      v12 = *(short *)((char *)v7 + i + 14);
+      if ( !(v12 & 1) )
+      {
+        if ( !(v96 & 0x80) && (v11 & 0x80u) == 0 )
+          goto LABEL_17;
+        v96 = (signed int)v94 >> 3;
+        v13 = v94;
+        *(short *)(v10 + 10) = v12 | 1;
+        pIndoor->_visible_outlines[v96] |= 1 << (7 - v13 % 8);
+      }
+      v14 = *(short *)v10;
+      v88 = v5;
+      v15 = &pIndoor->pVertices[v14];
+      v16 = v15->x;
+      v17 = v15->y - v84;
+      v93 = (unsigned __int16 *)(v16 - v6);
+      v92 = v17;
+      v18 = &pIndoor->pVertices[*(short *)(v10 + 2)];
+      v19 = v18->x;
+      v20 = v18->y - v84;
+      v95 = v19 - v6;
+      v97 = (const void *)v20;
+      v88 = (unsigned __int64)((v16 - v6) * (signed __int64)v5) >> 16;
+      v87 = (unsigned __int64)((signed int)v92 * (signed __int64)v5) >> 16;
+      v93 = (unsigned __int16 *)((unsigned __int64)((v19 - v6) * (signed __int64)v5) >> 16);
+      v92 = (unsigned __int64)(v20 * (signed __int64)v5) >> 16;
+      pRenderer->Line2D(
+        v85 + v88,
+        v90 - v87,
+        v85 + ((unsigned __int64)((v19 - v6) * (signed __int64)v5) >> 16),
+        v90 - v92,
+        black);
+      v7 = (uint *)pIndoor->pMapOutlines;
+LABEL_17:
+      ++v94;
+      i += 12;
+    }
+    while ( (signed int)v94 < (signed int)*v7 );
+  }
+  v21 = 0;
+  if ( (signed int)uNumBlueFacesInBLVMinimap > 0 )
+  {
+    while ( 1 )
+    {
+      v22 = pBlueFacesInBLVMinimapIDs[v21];
+      v87 = v5;
+      v23 = (int)&v7[3 * v22 + 1];
+      v24 = &pIndoor->pVertices[*(short *)v23];
+      v25 = &pIndoor->pVertices[*(short *)(v23 + 2)];
+      v26 = v25->x;
+      v27 = (unsigned __int16 *)(v24->x - v86);
+      v28 = v24->y - v84;
+      v29 = v25->y - v84;
+      v93 = v27;
+      v92 = v28;
+      v97 = (const void *)v29;
+      v87 = (unsigned __int64)((signed int)v27 * (signed __int64)v5) >> 16;
+      v88 = (unsigned __int64)(v28 * (signed __int64)v5) >> 16;
+      i = (unsigned __int64)((v26 - v86) * (signed __int64)v5) >> 16;
+      v95 = (unsigned __int64)(v29 * (signed __int64)v5) >> 16;
+      pRenderer->Line2D(
+        v85 + ((unsigned __int64)((signed int)v27 * (signed __int64)v5) >> 16),
+        v90 - v88,
+        v85 + ((unsigned __int64)((v26 - v86) * (signed __int64)v5) >> 16),
+        v90 - v95,
+        teal);
+      ++v21;
+      if ( v21 >= (signed int)uNumBlueFacesInBLVMinimap )
+        break;
+      v7 = (uint *)pIndoor->pMapOutlines;
+    }
+    v6 = v86;
+  }
+LABEL_38:
+  v47 = ((unsigned __int64)((pParty->vPosition.x - v6) * (signed __int64)v5) >> 16) + v85 - 3;
+  v81 = pParty->vPosition.y - v84;
+  v97 = (const void *)((unsigned __int64)((pParty->vPosition.y - v84) * (signed __int64)v5) >> 16);
+  v48 = 1;
+  v49 = v90 - (int)v97 - 3;
+  if ( v47 >= (signed int)x_ )
+  {
+    if ( v47 > (signed int)a4 )
+    {
+      if ( (signed int)(((unsigned __int64)((pParty->vPosition.x - v6) * (signed __int64)v5) >> 16) + v85 - 6) > (signed int)a4 )
+        v48 = 0;
+      v47 = a4;
+    }
+  }
+  else
+  {
+    if ( (signed int)(((unsigned __int64)((pParty->vPosition.x - v6) * (signed __int64)v5) >> 16) + v85) < (signed int)x_ )
+      v48 = 0;
+    v47 = x_;
+  }
+  if ( v49 >= (signed int)y_ )
+  {
+    if ( v49 > a5 )
+    {
+      if ( v90 - (signed int)v97 - 6 > a5 )
+        v48 = 0;
+      v49 = a5;
+    }
+  }
+  else
+  {
+    if ( v90 - (signed int)v97 < (signed int)y_ )
+      v48 = 0;
+    v49 = y_;
+  }
+  if ( v48 == 1 )
+  {
+    v50 = 0;
+    v51 = pParty->sRotationY & stru_5C6E00->uDoublePiMask;
+    if ( (signed int)(pParty->sRotationY & stru_5C6E00->uDoublePiMask) >= 128 )
+    {
+      if ( (signed int)v51 > 384 )
+      {
+        if ( (signed int)v51 >= 640 )
+        {
+          if ( (signed int)v51 > 896 )
+          {
+            if ( (signed int)v51 >= 1152 )
+            {
+              if ( (signed int)v51 > 1408 )
+              {
+                if ( (signed int)v51 >= 1664 )
+                {
+                  if ( (signed int)v51 > 1920 )
+                    goto LABEL_71;
+                  v73 = 7;
+                }
+                else
+                {
+                  v73 = 6;
+                }
+              }
+              else
+              {
+                v73 = 5;
+              }
+            }
+            else
+            {
+              v73 = 4;
+            }
+          }
+          else
+          {
+            v73 = 3;
+          }
+        }
+        else
+        {
+          v73 = 2;
+        }
+        v50 = v73;
+        goto LABEL_71;
+      }
+      v50 = 1;
+    }
+LABEL_71:
+    pRenderer->_4A6776(
+      v47,
+      v49,
+      (Texture *)(pTextureIDs_pMapDirs[v50] != -1 ? (int)&pIcons_LOD->pTextures[pTextureIDs_pMapDirs[v50]] : 0));
+  }
+  result = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v95 = 0;
+  v86 = result;
+  if ( (signed int)uNumLevelDecorations > 0 )
+  {
+    v94 = (unsigned int)&pLevelDecorations[0].vPosition;
+    do
+    {
+      if ( *(char *)(v94 - 2) & 8 )
+      {
+        v53 = *(int *)(v94 + 4) - v84;
+        v93 = (unsigned __int16 *)(*(int *)v94 - v6);
+        v92 = v53;
+        v54 = ((unsigned __int64)((signed int)v93 * (signed __int64)v5) >> 16) + v85;
+        v97 = (const void *)((unsigned __int64)(v53 * (signed __int64)v5) >> 16);
+        v55 = v90 - (int)v97;
+        if ( v54 >= pRenderer->field_1C_clipx )
+        {
+          if ( v54 <= pRenderer->field_24_clipz && v55 >= pRenderer->field_20_clipy && v55 <= pRenderer->field_28_clipw )
+          {
+            v74 = v86;
+            if ( v5 > 512 )
+            {
+              v96 = v55 + 1;
+              black = v55 - 1;
+              pRenderer->Line2D(v54 - 1, v55 - 1, v54 - 1, v55 + 1, v86);
+              pRenderer->Line2D(v54, black, v54, v96, v86);
+              ++v54;
+              v74 = v86;
+              v72 = v96;
+              v71 = v54;
+              v70 = black;
+            }
+            else
+            {
+              v72 = v90 - (int)v97;
+              v71 = ((unsigned __int64)((signed int)v93 * (signed __int64)v5) >> 16) + v85;
+              v70 = v90 - (int)v97;
+            }
+            pRenderer->Line2D(v54, v70, v71, v72, v74);
+          }
+        }
+      }
+      ++v95;
+      result = v95;
+      v94 += 32;
+    }
+    while ( (signed int)v95 < (signed int)uNumLevelDecorations );
+  }
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+  {
+    v90 = a4 - x_ + 1;
+    v95 = a5 - y_ + 1;
+    v77 = &pRenderer->pTargetSurface[x_ + y_ * v79];
+    v56 = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uWidthLn2;
+    black = (1 << (v56 + 16)) / v5;
+    v57 = (double)(1 << (16 - v56));
+    v58 = 22528 / (v5 / 384);
+    v59 = (signed __int64)((double)(v6 - v58 + 32768) / v57);
+    v60 = (int)v59 << 16;
+    v97 = (const void *)((int)v59 << 16);
+    v61 = (signed __int64)((double)(32768 - v58 - v84) / v57);
+    v78 = (unsigned __int16 *)(v60 >> 16);
+    v62 = (int)v61 << 16;
+    teal = v60 >> 16;
+    v63 = (signed __int16)v61;
+    a4a = &v75;
+    result = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xCu, 0xCu, 0xCu);
+    v85 = 0;
+    for ( i = result; v85 < (signed int)v95; result = v85 )
+    {
+      a5a = 0;
+      if ( v90 > 0 )
+      {
+        v96 = (v63 - 80) / 4;
+        v64 = teal;
+        do
+        {
+          v81 = (v64 - 80) / 4;
+          if ( !pOutdoor->_47F04C(v81, v96) )
+          {
+            if ( pOutdoor->_47F097(v81, v96) )
+            {
+              if ( !((a5a + v85) % 2) )
+                *(short *)a4a = i;
+            }
+            else
+            {
+              *(short *)a4a = 0;
+            }
+          }
+          a4a += 2;
+          v97 = (char *)v97 + black;
+          v64 = (signed int)v97 >> 16;
+          ++a5a;
+        }
+        while ( a5a < v90 );
+      }
+      v62 += black;
+      v97 = (const void *)v60;
+      a4a += 2 * (v90 - a5a);
+      v63 = v62 >> 16;
+      ++v85;
+      teal = (unsigned int)v78;
+    }
+    v65 = v95;
+    v66 = &v75;
+    if ( (signed int)v95 > 0 )
+    {
+      v67 = v77;
+      result = 2 * (v79 - v90);
+      do
+      {
+        if ( v90 > 0 )
+        {
+          v68 = v90;
+          do
+          {
+            v69 = *(short *)v66;
+            if ( !*(short *)v66 || v69 == (short)i )
+              *v67 = v69;
+            v66 += 2;
+            ++v67;
+            --v68;
+          }
+          while ( v68 );
+        }
+        v67 = (unsigned __int16 *)((char *)v67 + result);
+        --v65;
+      }
+      while ( v65 );
+    }
+  }
+  return result;
+}
+
+//----- (00443219) --------------------------------------------------------
+int ViewingParams::_443219()
+{
+  this->sPartyPosZ += 512;
+  return _4432E7();
+}
+
+//----- (00443225) --------------------------------------------------------
+int ViewingParams::_443225()
+{
+  this->sPartyPosX -= 512;
+  return _4432E7();
+}
+
+//----- (00443231) --------------------------------------------------------
+int ViewingParams::_443231()
+{
+  this->sPartyPosZ -= 512;
+  return _4432E7();
+}
+
+//----- (0044323D) --------------------------------------------------------
+int ViewingParams::_44323D()
+{
+  this->sPartyPosX += 512;
+  return _4432E7();
+}
+
+//----- (00443249) --------------------------------------------------------
+int ViewingParams::_443249()
+{
+  int v1; // edx@1
+
+  v1 = (unsigned __int64)((signed __int64)this->field_2C << 15) >> 16;
+  this->field_2C = v1;
+  if ( v1 < 384 )
+    this->field_2C = 384;
+  this->sPartyPosX = pParty->vPosition.x;
+  this->sPartyPosZ = pParty->vPosition.y;
+  return _4432E7();
+}
+
+//----- (00443291) --------------------------------------------------------
+int ViewingParams::_443291()
+{
+  int v1; // edx@1
+  int v2; // eax@1
+
+  v1 = 2 * this->field_2C;
+  v2 = 1536;
+  this->field_2C = v1;
+  if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+    v2 = 3072;
+  if ( v1 > v2 )
+    this->field_2C = v2;
+  this->sPartyPosX = pParty->vPosition.x;
+  this->sPartyPosZ = pParty->vPosition.y;
+  return _4432E7();
+}
+
+//----- (004432E7) --------------------------------------------------------
+int ViewingParams::_4432E7()
+{
+  ViewingParams *v1; // esi@1
+  int v2; // ebx@1
+  signed int v3; // edx@1
+  int v4; // ecx@1
+  int v5; // edi@3
+  int v6; // eax@3
+  int v7; // eax@5
+  int result; // eax@7
+
+  v1 = this;
+  v2 = this->field_3A;
+  v3 = 88 >> this->field_2C / 384;
+  v4 = (44 - v3) << 9;
+  if ( v1->sPartyPosZ > v2 + v4 )
+    v1->sPartyPosZ = v2 + v4;
+  v5 = v1->field_38;
+  v6 = (v3 - 44) << 9;
+  if ( v1->sPartyPosX < v5 + v6 )
+    v1->sPartyPosX = v5 + v6;
+  v7 = v2 + v6;
+  if ( v1->sPartyPosZ < v7 )
+    v1->sPartyPosZ = v7;
+  result = v5 + v4;
+  if ( v1->sPartyPosX > v5 + v4 )
+    v1->sPartyPosX = result;
+  return result;
+}
+
+//----- (00443343) --------------------------------------------------------
+unsigned int ViewingParams::_443343()
+{
+  signed int v1; // esi@1
+  unsigned __int16 *v2; // edi@1
+  unsigned int result; // eax@2
+
+  v1 = 0;
+  v2 = this->pPalette;
+  do
+  {
+    result = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v1, v1, v1);
+    *v2 = result;
+    ++v1;
+    ++v2;
+  }
+  while ( v1 < 256 );
+  return result;
+}
+
+//----- (00443365) --------------------------------------------------------
+int ViewingParams::_443365()
+{
+  ViewingParams *v1; // esi@1
+  __int16 *v2; // edi@3
+  Vec3_short_ *v3; // eax@4
+  unsigned int v4; // edx@4
+  signed int v5; // eax@8
+  Vec3_short_ *v6; // eax@12
+  signed int v7; // edi@12
+  signed int v8; // eax@16
+  char v9; // zf@20
+  int result; // eax@21
+  unsigned int v11; // [sp+4h] [bp-1Ch]@3
+  unsigned int *v12; // [sp+8h] [bp-18h]@3
+  unsigned int v13; // [sp+Ch] [bp-14h]@8
+  unsigned int v14; // [sp+10h] [bp-10h]@2
+  unsigned int v15; // [sp+14h] [bp-Ch]@2
+  unsigned int v16; // [sp+18h] [bp-8h]@2
+  unsigned int v17; // [sp+1Ch] [bp-4h]@2
+
+  v1 = this;
+  _443343();
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    v16 = 0x40000000u;
+    v14 = 0x40000000u;
+    v17 = 0xC0000000u;
+    v15 = 0xC0000000u;
+    if ( (signed int)pIndoor->pMapOutlines->uNumOutlines > 0 )
+    {
+      v2 = (__int16 *)(pIndoor->pMapOutlines->pOutlines);
+      v11 = pIndoor->pMapOutlines->uNumOutlines;
+      v12 = (uint *)pIndoor->pMapOutlines->pOutlines;
+      do
+      {
+        v3 = &pIndoor->pVertices[*v2];
+        v4 = v3->x;
+        if ( (signed int)v4 < (signed int)v16 )
+          v16 = v3->x;
+        if ( (signed int)v4 > (signed int)v17 )
+          v17 = v3->x;
+        v5 = v3->y;
+        v13 = v5;
+        if ( v5 < (signed int)v14 )
+          v14 = v4;
+        if ( v5 > (signed int)v15 )
+          v15 = v4;
+        v6 = &pIndoor->pVertices[v2[1]];
+        v7 = v6->x;
+        if ( v7 < (signed int)v16 )
+          v16 = v4;
+        if ( v7 > (signed int)v17 )
+          v17 = v4;
+        v8 = v6->y;
+        if ( v8 < (signed int)v14 )
+          v14 = v13;
+        if ( v8 > (signed int)v15 )
+          v15 = v13;
+        v2 = (__int16 *)(v12 + 3);
+        v9 = v11-- == 1;
+        v12 += 3;
+      }
+      while ( !v9 );
+    }
+    v1->uMinimapZoom = 1024;
+    v1->field_38 = (signed int)(v16 + v17) / 2;
+    v1->field_28 = 10;
+    result = (signed int)(v14 + v15) / 2;
+    v1->field_3A = result;
+  }
+  else
+  {
+    v1->field_38 = 0;
+    v1->field_3A = 0;
+    v1->uMinimapZoom = dword_576E2C;
+    result = dword_576E28;
+    v1->field_28 = dword_576E28;
+  }
+  v1->field_2C = 384;
+  return result;
+}
+
+
+//----- (00443801) --------------------------------------------------------
+int __cdecl Initialize2DA()
+{
+  const char *v0; // esi@3
+  _2devent *v1; // edi@3
+  char *v2; // esi@5
+  int v3; // edx@5
+  char v4; // cl@6
+  int v5; // eax@6
+  int v6; // ebx@10
+  int v7; // eax@60
+  int result; // eax@78
+  signed int v9; // [sp+10h] [bp-8h]@5
+  signed int v10; // [sp+14h] [bp-4h]@5
+
+  int it = 0;
+
+  if ( p2DEventsTXT_Raw )
+    pAllocator->FreeChunk(p2DEventsTXT_Raw);
+  p2DEventsTXT_Raw = 0;
+  v0 = "\r";
+  p2DEventsTXT_Raw = (char *)pEvents_LOD->LoadRaw("2dEvents.txt", 0);
+  strtok(p2DEventsTXT_Raw, "\r");
+  strtok(0, "\r");
+  v1 = p2DEvents;
+  while ( 1 )
+  {
+    v2 = strtok(0, v0) + 1;
+    v10 = 0;
+    v3 = -2;
+    v9 = -2;
+    do
+    {
+      v4 = *v2;
+      v5 = 0;
+      while ( v4 != 9 && v4 )
+      {
+        ++v5;
+        v4 = v2[v5];
+      }
+      v6 = (int)&v2[v5];
+      if ( !v2[v5] )
+        v10 = 1;
+      *(char *)v6 = 0;
+      if ( v5 )
+      {
+        switch ( v3 )
+        {
+          case 0:
+            if ( _strnicmp(v2, "wea", 3u) )
+            {
+              if ( _strnicmp(v2, "arm", 3u) )
+              {
+                if ( _strnicmp(v2, "mag", 3u) )
+                {
+                  if ( _strnicmp(v2, "alc", 3u) )
+                  {
+                    if ( _strnicmp(v2, "sta", 3u) )
+                    {
+                      if ( _strnicmp(v2, "boa", 3u) )
+                      {
+                        if ( _strnicmp(v2, "tem", 3u) )
+                        {
+                          if ( _strnicmp(v2, "tra", 3u) )
+                          {
+                            if ( _strnicmp(v2, "tow", 3u) )
+                            {
+                              if ( _strnicmp(v2, "tav", 3u) )
+                              {
+                                if ( _strnicmp(v2, "ban", 3u) )
+                                {
+                                  if ( _strnicmp(v2, "fir", 3u) )
+                                  {
+                                    if ( _strnicmp(v2, "air", 3u) )
+                                    {
+                                      if ( _strnicmp(v2, "wat", 3u) )
+                                      {
+                                        if ( _strnicmp(v2, "ear", 3u) )
+                                        {
+                                          if ( _strnicmp(v2, "spi", 3u) )
+                                          {
+                                            if ( _strnicmp(v2, "min", 3u) )
+                                            {
+                                              if ( _strnicmp(v2, "bod", 3u) )
+                                              {
+                                                if ( _strnicmp(v2, "lig", 3u) )
+                                                {
+                                                  if ( _strnicmp(v2, "dar", 3u) )
+                                                  {
+                                                    if ( _strnicmp(v2, "ele", 3u) )
+                                                    {
+                                                      if ( _strnicmp(v2, "sel", 3u) )
+                                                      {
+                                                        if ( _strnicmp(v2, "mir", 3u) )
+                                                        {
+                                                          v7 = -(_strnicmp(v2, "mer", 3u) != 0);
+                                                          LOBYTE(v7) = v7 & 0xEE;
+                                                          v1->uType = v7 + 18;
+                                                        }
+                                                        else
+                                                        {
+                                                          v1->uType = 16;
+                                                        }
+                                                      }
+                                                      else
+                                                      {
+                                                        v1->uType = 15;
+                                                      }
+                                                    }
+                                                    else
+                                                    {
+                                                      v1->uType = 14;
+                                                    }
+                                                  }
+                                                  else
+                                                  {
+                                                    v1->uType = 13;
+                                                  }
+                                                }
+                                                else
+                                                {
+                                                  v1->uType = 12;
+                                                }
+                                              }
+                                              else
+                                              {
+                                                v1->uType = 11;
+                                              }
+                                            }
+                                            else
+                                            {
+                                              v1->uType = 10;
+                                            }
+                                          }
+                                          else
+                                          {
+                                            v1->uType = 9;
+                                          }
+                                        }
+                                        else
+                                        {
+                                          v1->uType = 8;
+                                        }
+                                      }
+                                      else
+                                      {
+                                        v1->uType = 7;
+                                      }
+                                    }
+                                    else
+                                    {
+                                      v1->uType = 6;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    v1->uType = 5;
+                                  }
+                                }
+                                else
+                                {
+                                  v1->uType = 22;
+                                }
+                              }
+                              else
+                              {
+                                v1->uType = 21;
+                              }
+                            }
+                            else
+                            {
+                              v1->uType = 17;
+                            }
+                          }
+                          else
+                          {
+                            v1->uType = 30;
+                          }
+                        }
+                        else
+                        {
+                          v1->uType = 23;
+                        }
+                      }
+                      else
+                      {
+                        v1->uType = 28;
+                      }
+                    }
+                    else
+                    {
+                      v1->uType = 27;
+                    }
+                  }
+                  else
+                  {
+                    v1->uType = 4;
+                  }
+                }
+                else
+                {
+                  v1->uType = 3;
+                }
+              }
+              else
+              {
+                v1->uType = 2;
+              }
+            }
+            else
+            {
+              v1->uType = 1;
+            }
+            break;
+          case 2:
+            v1->uAnimationID = atoi(v2);
+            break;
+          case 3:
+            v1->pName = (char *)RemoveQuotes(v2);
+            break;
+          case 4:
+            v1->pProprieterName = RemoveQuotes(v2);
+            break;
+          case 5:
+            v1->pProprieterTitle = RemoveQuotes(v2);
+            break;
+          case 6:
+            v1->field_14 = atoi(v2);
+            break;
+          case 7:
+            v1->_state = atoi(v2);
+            break;
+          case 8:
+            v1->_rep = atoi(v2);
+            break;
+          case 9:
+            v1->_per = atoi(v2);
+            break;
+          case 10:
+            v1->fPriceMultiplier = atof(v2);
+            break;
+          case 11:
+            v1->flt_24 = atof(v2);
+            break;
+          case 13:
+            v1->field_1C = atoi(v2);
+            break;
+          case 16:
+            v1->uOpenTime = atoi(v2);
+            break;
+          case 17:
+            v1->uCloseTime = atoi(v2);
+            break;
+          case 18:
+            v1->uExitPicID = atoi(v2);
+            break;
+          case 19:
+            v1->uExitMapID = atoi(v2);
+            break;
+          case 20:
+            v1->_quest_related = atoi(v2);
+            break;
+          case 21:
+            v1->pEnterText = RemoveQuotes(v2);
+            break;
+          default:
+            break;
+        }
+      }
+      v2 = (char *)(v6 + 1);
+      v3 = v9 + 1;
+      v9 = v3;
+      result = v3 + 1;
+    }
+    while ( v3 + 1 <= 23 && !v10 );
+    ++v1;
+    //if ( (signed int)v1 >= (signed int)&unk_597F10 )
+    if (++it >= 525)
+      return result;
+    v0 = "\r";
+  }
+}
+
+//----- (00443CE1) --------------------------------------------------------
+unsigned int __fastcall LoadEventsToBuffer(const char *pContainerName, char *a2, unsigned int uBufferSize)
+{
+  const char *v3; // edi@1
+  FILE *v4; // eax@1
+  unsigned int v5; // esi@3
+  char Args; // [sp+8h] [bp-B4h]@6
+  //Texture DstBuf; // [sp+6Ch] [bp-50h]@1
+  void *Dst; // [sp+B4h] [bp-8h]@1
+  void *ptr; // [sp+B8h] [bp-4h]@1
+
+  v3 = pContainerName;
+  Dst = a2;
+  ptr = pEvents_LOD->LoadRaw(pContainerName, 0);
+  
+  Texture DstBuf; // [sp+6Ch] [bp-50h]@1
+  //Texture::Texture(&DstBuf);
+
+  v4 = pEvents_LOD->FindContainer(v3, 0);
+  if ( !v4 )
+    Abortf("Unable to load %s", v3);
+  fread(&DstBuf, 1u, 0x30u, v4);
+  v5 = DstBuf.uDecompressedSize;
+  if ( !DstBuf.uDecompressedSize )
+    v5 = DstBuf.uTextureSize;
+  memset(&DstBuf, 0, 0x48u);
+  if ( (signed int)v5 >= (signed int)uBufferSize )
+  {
+    sprintf(&Args, "File %s Size %lu - Buffer size %lu", v3, v5, uBufferSize);
+    Abortf(&Args);
+  }
+  memcpy(Dst, ptr, v5);
+  pAllocator->FreeChunk(ptr);
+  return v5;
+}
+
+//----- (00443DA1) --------------------------------------------------------
+void __cdecl Initialize_GlobalEVT()
+{
+  signed int v0; // esi@1
+  unsigned int v1; // ecx@2
+  char *v2; // eax@2
+
+  v0 = 0;
+  uGlobalEVT_Size = LoadEventsToBuffer("global.evt", pGlobalEVT, 0xB400u);
+  if ( uGlobalEVT_Size )
+  {
+    uGlobalEVT_NumEvents = 0;
+    memset(pGlobalEVT_Events, 128, 0xCE40u);
+    v1 = uGlobalEVT_NumEvents;
+    v2 = (char *)&pGlobalEVT_Events[uGlobalEVT_NumEvents].field_4;
+    do
+    {
+      ++v1;
+      *((int *)v2 - 1) = (unsigned __int8)pGlobalEVT[v0 + 1] + ((unsigned __int8)pGlobalEVT[v0 + 2] << 8);
+      *(int *)v2 = (unsigned __int8)pGlobalEVT[v0 + 3];
+      *((int *)v2 + 1) = v0;
+      v2 += 12;
+      v0 += (unsigned __int8)pGlobalEVT[v0] + 1;
+    }
+    while ( v0 < (signed int)uGlobalEVT_Size );
+    uGlobalEVT_NumEvents = v1;
+  }
+}
+
+//----- (00443E31) --------------------------------------------------------
+void __cdecl LoadLevel_InitializeLevelStr()
+{
+  signed __int16 v0; // si@1
+  //unsigned int v1; // ecx@1
+  signed int v2; // edi@1
+  int v3; // edx@1
+  //int v4; // eax@2
+  int v5; // ebx@4
+  int v6; // ebx@11
+  int v7; // eax@12
+  unsigned int *v8; // edi@13
+  char Args[100]; // [sp+Ch] [bp-68h]@9
+  int v10; // [sp+70h] [bp-4h]@1
+
+  if (sizeof(pLevelStrOffsets) != 0x7D0)
+    Log::Warning(L"pLevelStrOffsets: deserialization warning");
+  memset(pLevelStrOffsets, 0, 0x7D0u);
+  
+  v0 = 0;
+  //v1 = uLevelStrFileSize;
+  v2 = 1;
+  v3 = 0;
+  v10 = 0;
+    //v4 = 0;
+  for (uint i = 0; i < uLevelStrFileSize; ++i)
+  {
+      if ( !pLevelStr[i] )
+      {
+        v5 = (signed __int16)v2++;
+        pLevelStrOffsets[v5] = i + 1;
+        if ( (signed __int16)(i - (short)v10) > v0 )
+          v0 = i - v10;
+        v10 = i;
+      }
+  }
+
+  uLevelStrNumStrings = (signed __int16)v2 - 1;
+  if ( v0 > 800 )
+  {
+    sprintf(Args, "MAX_EVENT_TEXT_LENGTH needs to be increased to %lu", v0 + 1);
+    Abortf(Args);
+  }
+  v6 = 0;
+  if ( (signed __int16)v2 - 1 > 0 )
+  {
+    v7 = 0;
+    do
+    {
+      v8 = &pLevelStrOffsets[v7];
+      if ( RemoveQuotes(&pLevelStr[*v8]) != &pLevelStr[*v8] )
+        ++*v8;
+      ++v6;
+      v7 = (signed __int16)v6;
+    }
+    while ( (signed __int16)v6 < (signed int)uLevelStrNumStrings );
+  }
+}
+
+//----- (00443EF8) --------------------------------------------------------
+void __cdecl LoadLevel_InitializeLevelEvt()
+{
+  if (!uLevelEVT_Size)
+    return;
+
+  memset(array_5B5928, 0, 0xC80u);
+  memset(pLevelEVT_Events, 128, 0xCE40u);
+
+  uLevelEVT_NumEvents = 0;
+  dword_5B65C8 = 0;
+
+  for (uint i = 0, j = 0; j < uLevelEVT_Size; ++i)
+  {
+    pLevelEVT_Events[i].uEventID = pLevelEVT[j + 1] + ((unsigned short)pLevelEVT[j + 2] << 8);
+    pLevelEVT_Events[i].field_4 = pLevelEVT[j + 3];
+    pLevelEVT_Events[i].uEventOffsetInEVT = j;
+    j += pLevelEVT[j] + 1;
+
+    uLevelEVT_NumEvents++;
+  }
+}
+
+//----- (00443F95) --------------------------------------------------------
+void __cdecl OnMapLeave()
+{
+  signed int v0; // edi@1
+  char *v1; // esi@2
+  int v2; // ecx@4
+
+  v0 = 0;
+  if ( (signed int)uLevelEVT_NumEvents > 0 )
+  {
+    v1 = (char *)&pLevelEVT_Events[0].field_4;
+    do
+    {
+      if ( pLevelEVT[*((short *)v1 + 2) + 4] == 53 )
+      {
+        v2 = *((int *)v1 - 1);
+        dword_597F18 = *(int *)v1;
+        EventProcessor(v2, 0, 1);
+        dword_597F18 = 0;
+      }
+      ++v0;
+      v1 += 12;
+    }
+    while ( v0 < (signed int)uLevelEVT_NumEvents );
+  }
+}
+
+
+//----- (00443FDC) --------------------------------------------------------
+void OnMapLoad()
+{
+  stru176 *v3; // esi@7
+  __int16 v4; // cx@9
+  __int16 v5; // di@9
+  int v6; // eax@9
+  signed __int64 v8; // qax@26
+  unsigned int v9; // ecx@26
+  signed __int64 v10; // qax@26
+  signed __int64 v11; // qax@26
+  int v12; // ST50_4@26
+  signed __int64 v13; // qax@26
+  signed __int64 v14; // qax@26
+  int v15; // ST58_4@26
+  signed __int64 v16; // qax@26
+  int v17; // ebx@26
+  unsigned __int64 v18; // [sp+Ch] [bp-44h]@12
+  signed __int64 v19; // [sp+14h] [bp-3Ch]@26
+  unsigned __int64 v20; // [sp+1Ch] [bp-34h]@7
+  int v22; // [sp+2Ch] [bp-24h]@26
+  int v24; // [sp+34h] [bp-1Ch]@26
+  int v25; // [sp+38h] [bp-18h]@26
+  int v26; // [sp+3Ch] [bp-14h]@15
+  int v27; // [sp+3Ch] [bp-14h]@26
+  int v28; // [sp+40h] [bp-10h]@26
+  __int16 v29; // [sp+46h] [bp-Ah]@9
+  __int16 v30; // [sp+48h] [bp-8h]@9
+  __int16 v31; // [sp+4Ah] [bp-6h]@9
+  __int16 v32; // [sp+4Ch] [bp-4h]@9
+  __int16 v33; // [sp+4Eh] [bp-2h]@9
+
+  for (uint i = 0; i < uLevelEVT_NumEvents; ++i)
+  {
+    auto pEvent = pLevelEVT_Events + i;
+
+    auto _evt = (_evt_raw *)(pLevelEVT + pEvent->uEventOffsetInEVT);
+
+    if (_evt->v4 == 3)
+    {
+      pSoundList->LoadSound(
+          _evt->v5 +
+          ((_evt->v6 + ((_evt->v7 + ((unsigned int)_evt->v8 << 8)) << 8)) << 8),
+          0);
+    }
+    else if (_evt->v4 == 37)
+    {
+      dword_597F18 = pEvent->field_4;
+      EventProcessor(pEvent->uEventID, 0, 0);
+      dword_597F18 = 0;
+    }
+    else if (_evt->v4 == 31 || _evt->v4 == 38)
+    {
+      v3 = &array_5B5928[dword_5B65C8];
+      v20 = pOutdoor->uLastVisitDay;
+      if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+        v20 = pIndoor->stru1.uLastVisitDay;
+
+      v4 = _evt->v4;
+      v3->field_1C = v4;
+      v3->field_8 = pEvent->uEventID;
+      v3->field_A = pEvent->field_4;
+      v33 = _evt->v6;
+      v3->field_12 = v33;
+      v32 = _evt->v7;
+      v3->field_14 = v32;
+      v31 = _evt->v8;
+      v3->field_16 = v31;
+      v5 = _evt->v5;
+      v30 = _evt->v9;
+      v3->field_18 = v30;
+      v29 = _evt->v10;
+      v3->field_1A = v29;
+
+      v6 = ((unsigned short)_evt->v12 << 8) + _evt->v11;
+      v3->field_10 = v5;
+      v3->field_C = v6;
+      v3->field_E = v6;
+      if ( v4 == 38 && !(short)v6 )
+      {
+        if ( v20 )
+          v18 = pParty->uTimePlayed - v20;
+        else
+          v18 = 0i64;
+        v26 = (signed int)(signed __int64)((double)(signed __int64)v18 * 0.234375) / 60 / 60 / 24;
+
+        if ( v26 / 7 / 4 / 12 )
+        {
+          if ( v5 )
+          {
+            v3->field_4 = 0;
+            ++dword_5B65C8;
+            v3->field_0 = 0;
+            continue;
+          }
+        }
+        if (v26 / 7 / 4 != 0 && v33 != 0 ||
+            v26 / 7 != 0 && v32 != 0 ||
+            v26 != 0 || !v20)
+        {
+          v3->field_4 = 0;
+          ++dword_5B65C8;
+          v3->field_0 = 0;
+          continue;
+        }
+      }
+
+      v8 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375);
+      v9 = v8;
+      v10 = (signed int)v8 / 60;
+      v22 = v10 % 60;
+      v11 = (signed int)(v10 / 60);
+      v12 = v11 % 24;
+      v13 = (signed int)(v11 / 24);
+      v27 = v13 % 7;
+      v14 = (signed int)(v13 / 7);
+      v15 = v14 % 4;
+      v16 = (signed int)(v14 / 4);
+      v24 = v16 / 12;
+
+      auto _1 = (unsigned __int64)((double)pParty->uTimePlayed * 0.234375) >> 32;
+      auto _2 = ((__int64)v9 << 32) | _1;
+
+      v19 = _2 % 60;
+      //v19 = (signed __int64)__PAIR__((unsigned __int64)(signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) >> 32,
+      //                        v9)
+      //    % 60;
+
+      v17 = v12;
+      v25 = v15;
+      v28 = v16 % 12;
+      if ( v5 )
+      {
+        ++v24;
+      }
+      else
+      {
+        if ( v33 )
+        {
+          ++v28;
+        }
+        else
+        {
+          if ( v32 )
+          {
+            ++v25;
+          }
+          else
+          {
+            ++v27;
+            v22 = v30;
+            v17 = v31;
+            v19 = v29;
+          }
+        }
+      }
+      auto v0 = (signed __int64)((double)((v19
+                                + 0x3C * v22
+                                + 0xE10 * v17
+                                + 0x93A80 * v25
+                                + 0x15180 * v27
+                                + 0x24EA00 * (v28 + 12i64 * v24)) << 7)
+                      * 0.033333335);
+      v3->field_4 = HIDWORD(v0);
+
+      ++dword_5B65C8;
+      v3->field_0 = v0;
+    }
+  }
+}
+
+//----- (00444360) --------------------------------------------------------
+void __thiscall Level_LoadEvtAndStr(const char *pLevelName)
+{
+  char pContainerName[120]; // [sp+8h] [bp-98h]@1
+
+  sprintf(pContainerName, "%s.evt", pLevelName);
+  uLevelEVT_Size = LoadEventsToBuffer(pContainerName, pLevelEVT, 0x2400u);
+
+  sprintf(pContainerName, "%s.str", pLevelName);
+  uLevelStrFileSize = LoadEventsToBuffer(pContainerName, pLevelStr, 0x2400u);
+  if (uLevelStrFileSize)
+    LoadLevel_InitializeLevelStr();
+}
+
+//----- (004443D5) --------------------------------------------------------
+char *__cdecl _4443D5_GetMinimapRightClickText()
+{
+  int v0; // ST20_4@1
+  unsigned int v1; // esi@1
+  signed int v2; // ebx@1
+  double v3; // st7@1
+  int v4; // esi@3
+  int v5; // edi@4
+  int v6; // eax@4
+  int v7; // eax@4
+  BSPModel *v8; // ecx@4
+  unsigned __int8 v9; // zf@5
+  char v10; // sf@5
+  unsigned __int8 v11; // of@5
+  ODMFace *v12; // eax@6
+  __int16 v13; // cx@6
+  const char *v14; // eax@8
+  const char *v15; // edi@8
+  char *result; // eax@12
+  unsigned int v17; // eax@14
+  unsigned int v18; // [sp+Ch] [bp-20h]@1
+  int v19; // [sp+10h] [bp-1Ch]@1
+  int v20; // [sp+14h] [bp-18h]@1
+  char *v21; // [sp+18h] [bp-14h]@1
+  unsigned int pY; // [sp+1Ch] [bp-10h]@1
+  int v23; // [sp+20h] [bp-Ch]@1
+  int v24; // [sp+24h] [bp-8h]@1
+  int pX; // [sp+28h] [bp-4h]@1
+
+  v24 = pParty->vPosition.x;
+  v0 = pParty->vPosition.y;
+  v1 = pOutdoor->uNumBModels;
+  *(float *)&v23 = (double)(signed int)viewparams->uMinimapZoom * 0.000015258789;
+  v2 = 0;
+  v18 = pOutdoor->uNumBModels;
+  v21 = 0;
+  pMouse->GetClickPos((unsigned int *)&pX, &pY);
+  v3 = 1.0 / *(float *)&v23;
+  v23 = pX - 557;
+  v19 = (signed __int64)((double)(pX - 557) * v3 + (double)v24);
+  v20 = (signed __int64)((double)v0 - (double)(signed int)(pY - 74) * v3);
+  if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor || (*(float *)&v23 = 0.0, (signed int)v1 <= 0) )
+  {
+LABEL_14:
+    v17 = pMapStats->GetMapInfo(pCurrentMapName);
+    if ( v17 == v2 )
+      result = "No Maze Info for this maze on file!";
+    else
+      result = pMapStats->pInfos[v17].pName;
+  }
+  else
+  {
+    v4 = 0;
+    while ( 1 )
+    {
+      pX = pOutdoor->pBModels[v4].vBoundingCenter.x - v19;
+      pY = pOutdoor->pBModels[v4].vBoundingCenter.y - v20;
+      v5 = abs((signed)pY);
+      v6 = abs((signed)pX);
+      v7 = sub_4621DA(v6, v5, v2);
+      v8 = pOutdoor->pBModels;
+      if ( v7 < 2 * pOutdoor->pBModels[v4].sBoundingRadius )
+      {
+        v11 = __OFSUB__(pOutdoor->pBModels[v4].uNumFaces, v2);
+        v9 = pOutdoor->pBModels[v4].uNumFaces == v2;
+        v10 = ((pOutdoor->pBModels[v4].uNumFaces - v2) & 0x80000000u) != 0;
+        v24 = v2;
+        if ( !((unsigned __int8)(v10 ^ v11) | v9) )
+        {
+          do
+          {
+            v12 = &v8[v4].pFaces[v2 / 0x134u];
+            v13 = v12->sCogTriggeredID;
+            if ( v13 )
+            {
+              if ( !(BYTE2(v12->uAttributes) & 0x10) )
+              {
+                v14 = _444732_GetEventHintString(v13);
+                v15 = v14;
+                if ( v14 )
+                {
+                  if ( _strcmpi(v14, "") )
+                    v21 = (char *)v15;
+                }
+              }
+            }
+            ++v24;
+            v8 = pOutdoor->pBModels;
+            v2 += 308;
+          }
+          while ( v24 < (signed int)pOutdoor->pBModels[v4].uNumFaces );
+        }
+        result = v21;
+        v2 = 0;
+        if ( v21 )
+          break;
+      }
+      ++v23;
+      ++v4;
+      if ( v23 >= (signed int)v18 )
+        goto LABEL_14;
+    }
+  }
+  return result;
+}
+
+//----- (00444564) --------------------------------------------------------
+const char *__cdecl sub_444564()
+{
+  double v0; // st7@3
+  int v1; // ebx@3
+  int v2; // edi@3
+  int v3; // eax@3
+  int v4; // esi@5
+  int v5; // edi@6
+  int v6; // eax@6
+  int v7; // eax@6
+  BSPModel *v8; // ecx@6
+  unsigned __int8 v9; // zf@7
+  unsigned __int8 v10; // sf@7
+  ODMFace *v11; // eax@9
+  __int16 v12; // cx@9
+  const char *v13; // eax@11
+  const char *v14; // edi@11
+  const char *result; // eax@15
+  unsigned int v16; // [sp+0h] [bp-20h]@3
+  const char *v17; // [sp+4h] [bp-1Ch]@3
+  unsigned int pY; // [sp+8h] [bp-18h]@3
+  float v19; // [sp+Ch] [bp-14h]@1
+  int v20; // [sp+10h] [bp-10h]@1
+  int v21; // [sp+14h] [bp-Ch]@1
+  unsigned int v22; // [sp+18h] [bp-8h]@8
+  int pX; // [sp+1Ch] [bp-4h]@3
+
+  v20 = viewparams->sPartyPosX;
+  v21 = viewparams->sPartyPosZ;
+  v19 = (double)viewparams->field_2C * 0.000015258789;
+  if ( viewparams->field_2C == 384 )
+  {
+    v20 = viewparams->field_38;
+    v21 = viewparams->field_3A;
+  }
+  v17 = 0;
+  v16 = pOutdoor->uNumBModels;
+  pMouse->GetClickPos((unsigned int *)&pX, &pY);
+  v0 = 1.0 / v19;
+  v1 = (signed __int64)((double)(pX - 229) * v0 + (double)v20);
+  LODWORD(v19) = (signed __int64)((double)v21 - (double)(signed int)(pY - 181) * v0);
+  v2 = abs(v1 + 22528) / 512;
+  v3 = abs((signed)LODWORD(v19) - 22528);
+  if ( pOutdoor->_47F04C(v2, v3 / 512)
+    && uCurrentlyLoadedLevelType == LEVEL_Outdoor
+    && (v4 = 0, v20 = 0, (signed int)v16 > 0) )
+  {
+    while ( 1 )
+    {
+      pX = *(int *)((char *)&pOutdoor->pBModels->vBoundingCenter.x + v4) - v1;
+      pY = *(int *)((char *)&pOutdoor->pBModels->vBoundingCenter.y + v4) - LODWORD(v19);
+      v5 = abs((signed)pY);
+      v6 = abs((signed)pX);
+      v7 = sub_4621DA(v6, v5, 0);
+      v8 = pOutdoor->pBModels;
+      if ( v7 < *(int *)((char *)&pOutdoor->pBModels->sBoundingRadius + v4) )
+      {
+        v9 = *(unsigned int *)((char *)&pOutdoor->pBModels->uNumFaces + v4) == 0;
+        v10 = *(signed int *)((char *)&pOutdoor->pBModels->uNumFaces + v4) < 0;
+        v21 = 0;
+        if ( !(v10 | v9) )
+        {
+          v22 = 0;
+          do
+          {
+            v11 = &(*(ODMFace **)((char *)&v8->pFaces + v4))[v22 / 0x134];
+            v12 = v11->sCogTriggeredID;
+            if ( v12 )
+            {
+              if ( !(BYTE2(v11->uAttributes) & 0x10) )
+              {
+                v13 = _444732_GetEventHintString(v12);
+                v14 = v13;
+                if ( v13 )
+                {
+                  if ( _strcmpi(v13, "") )
+                    v17 = v14;
+                }
+              }
+            }
+            ++v21;
+            v8 = pOutdoor->pBModels;
+            v22 += 308;
+          }
+          while ( v21 < *(signed int *)((char *)&pOutdoor->pBModels->uNumFaces + v4) );
+        }
+        result = v17;
+        if ( v17 )
+          break;
+      }
+      ++v20;
+      v4 += 188;
+      if ( v20 >= (signed int)v16 )
+        goto LABEL_17;
+    }
+  }
+  else
+  {
+LABEL_17:
+    result = 0;
+  }
+  return result;
+}
+
+
+
+
+//----- (00444A51) --------------------------------------------------------
+char *__cdecl TransitionUI_Draw()
+{
+  MapInfo *v0; // esi@5
+  char *v1; // eax@6
+  char *result; // eax@12
+  std::string v3; // [sp-18h] [bp-84h]@11
+  unsigned int v4; // [sp-10h] [bp-7Ch]@12
+  int v5; // [sp-Ch] [bp-78h]@12
+  const char *v6; // [sp-8h] [bp-74h]@11
+  signed int v7; // [sp-4h] [bp-70h]@11
+  GUIWindow v8; // [sp+Ch] [bp-60h]@1
+  unsigned int v9; // [sp+60h] [bp-Ch]@1
+  unsigned int v10; // [sp+64h] [bp-8h]@1
+  int a3; // [sp+6Bh] [bp-1h]@11
+
+  memcpy(&v8, pPrimaryWindow, sizeof(v8));
+  v10 = pMapStats->GetMapInfo(pCurrentMapName);
+  v9 = IndoorLocation::GetLocationIndex(dword_591164_teleport_map_name);
+  pRenderer->DrawTextureIndexed(0x1DDu, 0, pTexture_Dialogue_Background);
+  pRenderer->DrawTextureIndexed(
+    _4E5E50_transui_x - 4,
+    _4E5EE0_transui_y - 4,
+    (Texture *)(uTextureID_50795C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50795C] : 0));
+  pRenderer->DrawTextureIndexed(_4E5E50_transui_x, _4E5EE0_transui_y, pTexture_outside);
+  uTextureID_507B04 = uTextureID_right_panel;
+  pRenderer->DrawTextureTransparent(
+    0x1D4u,
+    0,
+    (Texture *)(uTextureID_right_panel != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_right_panel] : 0));
+  pRenderer->DrawTextureIndexed(
+    0x22Cu,
+    0x1C3u,
+    (Texture *)(uTextureID_x_x_u != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_x_u] : 0));
+  pRenderer->DrawTextureIndexed(
+    0x1DCu,
+    0x1C3u,
+    (Texture *)(uTextureID_x_ok_u != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_ok_u] : 0));
+  if ( (pVideoPlayer->AnyMovieLoaded() || v9) && *dword_591164_teleport_map_name != 48 )
+    v10 = pMapStats->GetMapInfo(dword_591164_teleport_map_name);
+  v0 = &pMapStats->pInfos[v10];
+  v8.uFrameX = 493;
+  v8.uFrameWidth = 126;
+  v8.uFrameZ = 366;
+  v8.DrawTitleText(pFontCreate, 0, 5u, 0, v0->pName, 3u);
+  v8.uFrameX = 483;
+  v8.uFrameWidth = 148;
+  v8.uFrameZ = 334;
+  if ( uCurrentHouse_Animation )
+  {
+    v1 = (&off_4EB080)[4 * uCurrentHouse_Animation];
+  }
+  else
+  {
+    if ( v10 )
+    {
+      sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[409], v0->pName);// "Do you wish to leave %s?"
+      v1 = pTmpBuf;
+      goto LABEL_12;
+    }
+    v1 = "";
+  }
+  if ( !v1 )
+  {
+    MessageBoxW(nullptr, L"No transition text found!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Events.cpp:1410", 0);
+    v1 = "";
+  }
+LABEL_12:
+  v7 = 3;
+  v6 = v1;
+  v5 = 0;
+  v4 = (212 - pFontCreate->CalcTextHeight(v1, &v8, 0, 0)) / 2 + 101;
+  result = v8.DrawTitleText(pFontCreate, 0, v4, v5, v6, v7);
+  dword_5B5924 = 1;
+  return result;
+}
+
+
+//----- (00444C8F) --------------------------------------------------------
+GUIWindow *__cdecl UI_CreateTravelDialogue()
+{
+  signed int v0; // eax@1
+  unsigned int v1; // eax@6
+  GUIWindow *result; // eax@9
+  const char *v3; // [sp-4h] [bp-2Ch]@2
+  char pContainer[32]; // [sp+0h] [bp-28h]@1
+
+  pEventTimer->Pause();
+  v0 = const_2();
+  sprintf(pContainer, "evt%02d", v0);
+  if ( pParty->uAlignment )
+  {
+    if ( pParty->uAlignment != 2 )
+      goto LABEL_6;
+    v3 = "-c";
+  }
+  else
+  {
+    v3 = "-b";
+  }
+  strcat(pContainer, v3);
+LABEL_6:
+  pTexture_Dialogue_Background = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE)];
+  pTexture_outside = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("outside", TEXTURE_16BIT_PALETTE)];
+  v1 = pMapStats->GetMapInfo(pCurrentMapName);
+  if ( v1 )
+    sprintf(byte_591098, pGlobalTXT_LocalizationStrings[410], pMapStats->pInfos[v1].pName);// "Leave %s"
+  else
+    strcpy(byte_591098, pGlobalTXT_LocalizationStrings[79]);// "Exit"
+  result = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)17, 0, (int)byte_591098);
+  pDialogueWindow = result;
+  return result;
+}
+
+//----- (00444D80) --------------------------------------------------------
+signed int __cdecl GetTravelTime()
+{
+  signed int v0; // esi@1
+
+  v0 = uDefaultTravelTime_ByFoot;
+  if ( CheckHiredNPCSpeciality(5u) )
+    --v0;
+  if ( CheckHiredNPCSpeciality(6u) )
+    v0 -= 2;
+  if ( CheckHiredNPCSpeciality(7u) )
+    v0 -= 3;
+  if ( CheckHiredNPCSpeciality(0x2Cu) )
+    --v0;
+  if ( v0 < 1 )
+    v0 = 1;
+  return v0;
+}
+// 6BD07C: using guessed type int uDefaultTravelTime_ByFoot;
+
+//----- (00444DCA) --------------------------------------------------------
+void __cdecl TravelUI_Draw()
+{
+  unsigned int v0; // edi@1
+  MapInfo *v1; // edi@2
+  char *v2; // ST14_4@2
+  signed int v3; // eax@2
+  int v4; // eax@5
+  const char *v5; // [sp-Ch] [bp-90h]@3
+  signed int v6; // [sp-8h] [bp-8Ch]@3
+  GUIWindow v7; // [sp+Ch] [bp-78h]@1
+  char pDestinationMapName[32]; // [sp+60h] [bp-24h]@1
+  unsigned int v9; // [sp+80h] [bp-4h]@1
+
+  memcpy(&v7, pPrimaryWindow, sizeof(v7));
+  v9 = pMapStats->GetMapInfo(pCurrentMapName);
+  pOutdoor->GetTravelDestination(pParty->vPosition.x, pParty->vPosition.y, pDestinationMapName, 20);
+  v0 = pMapStats->GetMapInfo(pDestinationMapName);
+  pRenderer->DrawTextureIndexed(0x1DDu, 0, pTexture_Dialogue_Background);
+  pRenderer->DrawTextureTransparent(0x1D4u, 0,
+    (Texture *)(uTextureID_507B04 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507B04] : 0));
+  pRenderer->DrawTextureIndexed(_4E5E50_transui_x, _4E5EE0_transui_y, pTexture_outside);
+  pRenderer->DrawTextureIndexed(0x22Cu, 0x1C3u,
+    (Texture *)(uTextureID_x_x_u != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_x_u] : 0));
+  pRenderer->DrawTextureIndexed(0x1DCu, 0x1C3u,
+    (Texture *)(uTextureID_x_ok_u != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_x_ok_u] : 0));
+  if ( v0 )
+  {
+    v1 = &pMapStats->pInfos[v0];
+    v7.uFrameX = 493;
+    v7.uFrameWidth = 126;
+    v2 = v1->pName;
+    v7.uFrameZ = 366;
+    v7.DrawTitleText(pFontCreate, 0, 4u, 0, v2, 3u);
+    v7.uFrameX = 483;
+    v7.uFrameWidth = 148;
+    v7.uFrameZ = 334;
+    v3 = GetTravelTime();
+    if ( v3 == 1 )
+    {
+      v6 = 1;
+      v5 = pGlobalTXT_LocalizationStrings[663]; // "It will take %d day to cross to %s."
+    }
+    else
+    {
+      v6 = v3;
+      v5 = pGlobalTXT_LocalizationStrings[128]; // "It will take %d days to travel to %s."
+    }
+    sprintf(pTmpBuf, v5, v6, v1->pName);
+    strcat(pTmpBuf, "\n \n");
+    sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[126], pMapStats->pInfos[v9].pName);
+    strcat(pTmpBuf, pTmpBuf2);
+    v4 = pFontCreate->CalcTextHeight(pTmpBuf, &v7, 0, 0);
+    v7.DrawTitleText(pFontCreate, 0, (212 - v4) / 2 + 101, 0, pTmpBuf, 3u);
+    dword_5B5924 = 1;
+  }
+}
+
+
+//----- (00444FBE) --------------------------------------------------------
+void __cdecl DrawBranchlessDialogueUI()
+{
+  GUIFont *v0; // esi@1
+  int v1; // esi@4
+  char *v2; // eax@6
+  int v3; // edi@12
+  char Str[200]; // [sp+Ch] [bp-120h]@12
+  GUIWindow v5; // [sp+D4h] [bp-58h]@4
+  GUIFont *pFont; // [sp+128h] [bp-4h]@1
+
+  v0 = pFontArrus;
+  pFont = pFontArrus;
+  if ( ptr_F8B1E8 && !byte_5B0938[0] )
+    strcpy(byte_5B0938, ptr_F8B1E8);
+  v5.uFrameWidth = 460;
+  v5.uFrameZ = 452;
+  v1 = pFontArrus->CalcTextHeight(byte_5B0938, &v5, 12, 0) + 7;
+  if ( 352 - v1 < 8 )
+  {
+    pFont = pFontCreate;
+    v1 = pFontCreate->CalcTextHeight(byte_5B0938, &v5, 12, 0) + 7;
+  }
+  pRenderer->_4A6A68(
+    8u,
+    352 - v1,
+    (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
+    (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v1);
+  pRenderer->DrawTextureIndexed(8u, 347 - v1, pTexture_591428);
+  v2 = FitTextInAWindow(byte_5B0938, pFont, &v5, 0xCu, 0);
+  pGUIWindow2->DrawText(pFont, 12, 354 - v1, 0, v2, 0, 0, 0);
+  pRenderer->DrawTextureRGB(0, 0x160u, pTexture_StatusBar);
+  if ( pGUIWindow2->field_40 != 1 )
+  {
+    if ( pGUIWindow2->field_40 == 2 )
+    {
+      pGUIWindow2->field_40 = 0;
+      strcpy(GameUI_StatusBar_TimedString, (const char *)pKeyActionMap->pPressedKeysBuffer);
+LABEL_16:
+      sub_4452BB();
+      return;
+    }
+    if ( pGUIWindow2->field_40 != 3 )
+      return;
+    pGUIWindow2->field_40 = 0;
+LABEL_15:
+    memset(GameUI_StatusBar_TimedString, 0, 0xC8u);
+    goto LABEL_16;
+  }
+  if ( pGUIWindow2->ptr_1C == (void *)26 )
+  {
+    sprintf(Str, "%s %s", GameUI_StatusBar_TimedString, pKeyActionMap->pPressedKeysBuffer);
+    v3 = pFontLucida->GetLineWidth(Str);
+    pGUIWindow2->DrawText(pFontLucida, 13, 357, 0, Str, 0, 0, 0);
+    pGUIWindow2->DrawFlashingInputCursor(v3 + 13, 357, pFontLucida);
+    return;
+  }
+  if ( pKeyActionMap->pPressedKeysBuffer[0] )
+  {
+    pKeyActionMap->_459ED1(0);
+    goto LABEL_15;
+  }
+}
+
+//----- (004451A8) --------------------------------------------------------
+void __fastcall sub_4451A8_press_any_key(int a1, int a2, int a4)
+{
+  int v3; // esi@1
+  int v4; // edi@1
+
+  v3 = a2;
+  v4 = a1;
+  if ( !pGUIWindow2 )
+  {
+    if ( pParty->uFlags & 2 )
+      pGame->Draw();
+    if ( !dword_597F18 )
+      pAudioPlayer->StopChannels(-1, -1);
+    pMiscTimer->Pause();
+    pEventTimer->Pause();
+    dword_5C3418 = v4;
+    dword_5C341C = v3;
+    _591094_decoration = _5C3420_pDecoration;
+    pGUIWindow2 = GUIWindow::Create(0, 0, 640u, 480u, (enum WindowType)19, a4, 0);
+    pGUIWindow2->CreateButton(61u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+    pGUIWindow2->CreateButton(177u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+    pGUIWindow2->CreateButton(292u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+    pGUIWindow2->CreateButton(407u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+  }
+}
+
+//----- (004452BB) --------------------------------------------------------
+void __cdecl sub_4452BB()
+{
+  pGUIWindow2->Release();
+  pGUIWindow2 = 0;
+  _5C3420_pDecoration = _591094_decoration;
+  dword_597F18 = dword_5C341C;
+  EventProcessor(dword_5C3418, 0, 1);
+  dword_597F18 = 0;
+  _5C3420_pDecoration = 0;
+  pEventTimer->Resume();
+}
+
+
+//----- (00445308) --------------------------------------------------------
+const char *__fastcall sub_445308(int a1)
+{
+  if ( a1 == 10
+    || a1 == 11
+    || a1 == 12
+    || a1 == 33
+    || a1 == 34
+    || a1 == 39
+    || a1 == 40
+    || a1 == 41
+    || a1 == 42
+    || a1 == 43
+    || a1 == 52 )
+    return (const char *)*(&pNPCStats->field_13A60 + 5 * a1);
+  else
+    return pNPCTopics[407].pTopic;
+}
+
+
+//----- (00445350) --------------------------------------------------------
+void __cdecl DrawDialogueUI()
+{
+  NPCData *v0; // ebx@2
+  int v1; // eax@2
+  unsigned __int16 v2; // di@2
+  unsigned int v3; // eax@2
+  char *v4; // esi@3
+  int v5; // eax@11
+  char *v6; // ecx@13
+  char *v7; // eax@16
+  unsigned int v8; // edi@19
+  char *v9; // ecx@27
+  char *v10; // eax@29
+  int v11; // eax@30
+  int v12; // esi@39
+  char *v13; // eax@41
+  GUIButton *v14; // eax@43
+  GUIButton *v15; // edi@43
+  signed int v16; // eax@44
+  int v17; // eax@46
+  int v18; // eax@47
+  int v19; // eax@48
+  int v20; // eax@49
+  int v21; // eax@50
+  int v22; // eax@51
+  unsigned int v23; // eax@53
+  const char *v24; // eax@59
+  int v25; // eax@65
+  int v26; // eax@66
+  int v27; // eax@67
+  int v28; // eax@68
+  int v29; // eax@69
+  unsigned __int16 v30; // cx@83
+  int v31; // ecx@86
+  int v32; // ebx@93
+  unsigned int v33; // eax@93
+  GUIWindow *v34; // ecx@93
+  int v35; // esi@93
+  int i; // eax@93
+  GUIButton *v37; // eax@94
+  int v38; // eax@95
+  signed int v39; // esi@99
+  signed int v40; // eax@102
+  unsigned int v41; // ebx@102
+  int v42; // edi@102
+  GUIButton *v43; // esi@103
+  int v44; // eax@104
+  unsigned int v45; // ecx@104
+  unsigned __int16 *v46; // edx@104
+  unsigned __int16 v47; // ax@104
+  char pFont; // [sp+4h] [bp-110h]@39
+  int v49; // [sp+Ch] [bp-108h]@39
+  int v50; // [sp+14h] [bp-100h]@39
+  GUIWindow v51; // [sp+58h] [bp-BCh]@2
+  GUIWindow v52; // [sp+ACh] [bp-68h]@42
+  char *Str; // [sp+100h] [bp-14h]@104
+  __int16 v54[2]; // [sp+104h] [bp-10h]@2
+  unsigned __int16 *v55; // [sp+108h] [bp-Ch]@82
+  GUIFont *pOutString; // [sp+10Ch] [bp-8h]@39
+  char *pInString; // [sp+110h] [bp-4h]@32
+
+  if ( !pDialogueWindow )
+    return;
+  memcpy(&v51, pDialogueWindow, sizeof(v51));
+  v0 = GetNPCData(uDialogue_SpeakingActorNPC_ID);
+  v1 = sub_445C8B(uDialogue_SpeakingActorNPC_ID);
+  v51.uFrameWidth -= 10;
+  v51.uFrameZ -= 10;
+  *(int *)v54 = v1;
+  GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  v2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0x15u, 0x99u, 0xE9u);
+  pRenderer->DrawTextureIndexed(0x1DDu, 0, pTexture_Dialogue_Background);
+  pRenderer->DrawTextureTransparent(
+    0x1D4u,
+    0,
+    (Texture *)(uTextureID_507B04 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507B04] : 0));
+  pRenderer->DrawTextureIndexed(
+    _4E5E50_transui_x - 4,
+    _4E5EE0_transui_y - 4,
+    (Texture *)(uTextureID_50795C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50795C] : 0));
+  pRenderer->DrawTextureIndexed(_4E5E50_transui_x, _4E5EE0_transui_y, pDialogueNPCPortraits[0]);
+  v3 = v0->uProfession;
+  if ( v3 )
+  {
+    v4 = pTmpBuf;
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[429], v0->pName, aNPCProfessionNames[v3]);
+  }
+  else
+  {
+    strcpy(pTmpBuf, v0->pName);
+    v4 = pTmpBuf;
+  }
+  v51.DrawTitleText(pFontArrus, 0x1E3u, 0x70u, v2, v4, 3u);
+  pParty->GetPartyFame();
+  if ( (signed int)uDialogueType > 89 )
+  {
+    if ( uDialogueType == 90 )
+    {
+      v7 = pGlobalTXT_LocalizationStrings[577]; // "Get back in there you wimps:"
+      goto LABEL_37;
+    }
+    if ( uDialogueType == 91 )
+    {
+      sprintf(v4, pGlobalTXT_LocalizationStrings[576], dword_F8B1B4);// "Congratulations on your win: here's your stuff: %u gold."
+      pInString = v4;
+      v8 = 0;
+      goto LABEL_39;
+    }
+    if ( uDialogueType == 92 )
+    {
+      v7 = pGlobalTXT_LocalizationStrings[582]; // "You already won this trip to the Arena:"
+      goto LABEL_37;
+    }
+  }
+  else
+  {
+    if ( uDialogueType == 89 )
+    {
+      v7 = pGlobalTXT_LocalizationStrings[574]; // "Welcome to the Arena of Life and Death.  Remember, you are only allowed one arena combat per visit.  To fight an arena battle, select the option that best describes your abilities and return to me- if you survive:"
+      goto LABEL_37;
+    }
+    if ( uDialogueType == 13 )
+    {
+      v5 = 5 * v0->uProfession;
+      goto LABEL_18;
+    }
+    if ( (signed int)uDialogueType > 18 )
+    {
+      if ( (signed int)uDialogueType > 24 )
+      {
+        if ( uDialogueType == 77 )
+        {
+          v5 = 5 * v0->uProfession;
+          if ( byte_F8B1EC )
+          {
+            v6 = (char *)*(&pNPCStats->field_13A5C + 5 * v0->uProfession);
+            goto LABEL_19;
+          }
+          if ( v0->uFlags & 0x80 )
+          {
+            v6 = (char *)*(&pNPCStats->field_13A68 + 5 * v0->uProfession);
+LABEL_19:
+            v8 = 0;
+            v7 = sub_495461(v6, uActiveCharacter - 1, 0, 0, 0, 0);
+LABEL_38:
+            pInString = v7;
+            goto LABEL_39;
+          }
+LABEL_18:
+          v6 = (char *)*(&pNPCStats->field_13A64 + v5);
+          goto LABEL_19;
+        }
+        goto LABEL_24;
+      }
+      if ( byte_5B0938[0] )
+        goto LABEL_24;
+      v7 = (char *)ptr_F8B1E8;
+LABEL_37:
+      v8 = 0;
+      goto LABEL_38;
+    }
+  }
+LABEL_24:
+  if ( *(int *)v54 == 1 )
+  {
+    v11 = v0->greet;
+    v8 = 0;
+    if ( v11 )
+    {
+      v10 = (char *)*(&pNPCStats->field_17884 + ((v0->uFlags & 3) == 2) + 2 * v11);
+      goto LABEL_32;
+    }
+  }
+  else
+  {
+    if ( *(int *)v54 == 2 )
+    {
+      v8 = 0;
+      if ( v0->uFlags & 0x80 )
+        v9 = (char *)*(&pNPCStats->field_13A68 + 5 * v0->uProfession);
+      else
+        v9 = (char *)*(&pNPCStats->field_13A64 + 5 * v0->uProfession);
+      v10 = sub_495461(v9, uActiveCharacter - 1, 0, 0, 0, 0);
+LABEL_32:
+      pInString = v10;
+      if ( v10 == (char *)v8 )
+        goto LABEL_42;
+LABEL_39:
+      v49 = 460;
+      v50 = 452;
+      pOutString = pFontArrus;
+      v12 = pFontArrus->CalcTextHeight(pInString, (GUIWindow *)&pFont, 13, v8) + 7;
+      if ( 352 - v12 < 8 )
+      {
+        pOutString = pFontCreate;
+        v12 = pFontCreate->CalcTextHeight(pInString, (GUIWindow *)&pFont, 13, v8) + 7;
+      }
+      pRenderer->_4A6A68(
+        8u,
+        352 - v12,
+        (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
+        (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v12);
+      pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
+      v13 = FitTextInAWindow(pInString, pOutString, (GUIWindow *)&pFont, 0xDu, v8);
+      pDialogueWindow->DrawText(pOutString, 13, 354 - v12, v8, v13, v8, v8, v8);
+      goto LABEL_42;
+    }
+  }
+LABEL_42:
+  memcpy(&v52, pDialogueWindow, sizeof(v52));
+  v52.uFrameX = 483;
+  v52.uFrameWidth = 148;
+  v52.uFrameZ = 334;
+  for ( pOutString = (GUIFont *)v52.pStartingPosActiveItem;
+        (signed int)pOutString < v52.pStartingPosActiveItem + v52.pNumPresenceButton;
+        pOutString = (GUIFont *)((char *)pOutString + 1) )
+  {
+    v14 = v52.GetControl((unsigned int)pOutString);
+    v15 = v14;
+    if ( !v14 )
+      break;
+    v16 = v14->uControlParam;
+    if ( v16 > 24 )
+    {
+      v25 = v16 - 76;
+      if ( v25 )
+      {
+        v26 = v25 - 1;
+        if ( v26 )
+        {
+          v27 = v26 - 8;
+          if ( v27 )
+          {
+            v28 = v27 - 1;
+            if ( v28 )
+            {
+              v29 = v28 - 1;
+              if ( v29 )
+              {
+                if ( v29 != 1 )
+                  goto LABEL_71;
+                v24 = pGlobalTXT_LocalizationStrings[581];
+              }
+              else
+              {
+                v24 = pGlobalTXT_LocalizationStrings[580];
+              }
+            }
+            else
+            {
+              v24 = pGlobalTXT_LocalizationStrings[579];
+            }
+          }
+          else
+          {
+            v24 = pGlobalTXT_LocalizationStrings[578];
+          }
+        }
+        else
+        {
+          v24 = pGlobalTXT_LocalizationStrings[407];
+        }
+      }
+      else
+      {
+        if ( v0->uFlags & 0x80 )
+        {
+LABEL_59:
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[408], v0->pName);
+          v24 = pTmpBuf;
+          goto LABEL_79;
+        }
+        v24 = pGlobalTXT_LocalizationStrings[406];
+      }
+    }
+    else
+    {
+      if ( v16 == 24 )
+      {
+        v23 = v0->evtf;
+LABEL_63:
+        v24 = (&dword_721660)[8 * v23];
+        if ( !v24 )
+        {
+          v24 = "";
+          v15->uControlParam = 0;
+        }
+        goto LABEL_79;
+      }
+      v17 = v16 - 9;
+      if ( !v17 )
+      {
+        v24 = (const char *)sub_445308(v0->uProfession);
+        goto LABEL_79;
+      }
+      v18 = v17 - 4;
+      if ( v18 )
+      {
+        v19 = v18 - 6;
+        if ( !v19 )
+        {
+          v23 = v0->bDrawSomeAnim;
+          goto LABEL_63;
+        }
+        v20 = v19 - 1;
+        if ( !v20 )
+        {
+          v23 = v0->evtb;
+          goto LABEL_63;
+        }
+        v21 = v20 - 1;
+        if ( !v21 )
+        {
+          v23 = v0->evtc;
+          goto LABEL_63;
+        }
+        v22 = v21 - 1;
+        if ( !v22 )
+        {
+          v23 = v0->evtd;
+          goto LABEL_63;
+        }
+        if ( v22 == 1 )
+        {
+          v23 = v0->evte;
+          goto LABEL_63;
+        }
+LABEL_71:
+        v24 = "";
+        goto LABEL_79;
+      }
+      if ( v0->uFlags & 0x80 )
+        goto LABEL_59;
+      v24 = pGlobalTXT_LocalizationStrings[122];
+    }
+LABEL_79:
+    if ( pParty->field_7B5_in_arena_quest && pParty->field_7B5_in_arena_quest != -1 )
+    {
+      pInString = 0;
+      if ( (signed int)uNumActors > 0 )
+      {
+        v55 = (unsigned short *)&pActors[0].uAIState;
+        *(int *)v54 = uNumActors;
+        do
+        {
+          v30 = *v55;
+          if ( *v55 == 5 || v30 == 11 || v30 == 19 || (v31 = *((int *)v55 + 159)) != 0 && (v31 & 7) == 4 )
+            ++pInString;
+          v55 += 418;
+          --*(int *)v54;
+        }
+        while ( *(int *)v54 );
+      }
+      if ( pInString == (char *)uNumActors )
+        v24 = pGlobalTXT_LocalizationStrings[658];
+    }
+    strcpy(v15->pButtonName, v24);
+  }
+  v32 = 0;
+  pInString = (char *)GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v33 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  v34 = pDialogueWindow;
+  *(int *)v54 = v33;
+  v35 = pDialogueWindow->pStartingPosActiveItem;
+  for ( i = v35 + pDialogueWindow->pNumPresenceButton; v35 < i; i = pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem )
+  {
+    v37 = v34->GetControl(v35);
+    if ( !v37 )
+    {
+      v34 = pDialogueWindow;
+      break;
+    }
+    v38 = pFontArrus->CalcTextHeight(v37->pButtonName, &v52, 0, 0);
+    v34 = pDialogueWindow;
+    v32 += v38;
+    ++v35;
+  }
+  v39 = v34->pNumPresenceButton;
+  if ( v39 )
+  {
+    pOutString = (GUIFont *)((174 - v32) / v39);
+    if ( (174 - v32) / v39 > 32 )
+      pOutString = (GUIFont *)32;
+    v55 = (unsigned __int16 *)1;
+    v40 = 174 - (int)pOutString * v39 - v32;
+    v41 = v34->pStartingPosActiveItem;
+    v42 = v40 / 2 - (signed int)pOutString / 2 + 138;
+    if ( (signed int)v41 < (signed int)(v41 + v39) )
+    {
+      do
+      {
+        v43 = v34->GetControl(v41);
+        if ( !v43 )
+          break;
+        v43->uY = (unsigned int)((char *)pOutString + v42);
+        Str = v43->pButtonName;
+        v44 = pFontArrus->CalcTextHeight(v43->pButtonName, &v52, 0, 0);
+        v45 = v43->uY;
+        v46 = v55;
+        v43->uHeight = v44;
+        v42 = v45 + v44 - 1;
+        v43->uW = v42;
+        v47 = v54[0];
+        if ( (unsigned __int16 *)pDialogueWindow->pCurrentPosActiveItem != v46 )
+          v47 = (unsigned __int16)pInString;
+        v52.DrawTitleText(pFontArrus, 0, v45, v47, Str, 3u);
+        v34 = pDialogueWindow;
+        v55 = (unsigned __int16 *)((char *)v55 + 1);
+        ++v41;
+      }
+      while ( (signed int)v41 < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem );
+    }
+  }
+  pRenderer->DrawTextureIndexed(
+    0x1D7u,
+    0x1BDu,
+    (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0));
+}
+
+//----- (004459F9) --------------------------------------------------------
+NPCData *__fastcall GetNPCData(unsigned int npcid)
+{
+  unsigned int v1; // esi@1
+  NPCData *result; // eax@5
+  int v3; // esi@9
+  int v4; // ecx@9
+  int v5; // edx@9
+  NPCData *v6; // eax@9
+  char *v7; // ebx@14
+  NPCData *v8; // edi@14
+  char v9; // al@22
+  std::string v10; // [sp-18h] [bp-2Ch]@4
+  const char *v11; // [sp-8h] [bp-1Ch]@4
+  int v12; // [sp-4h] [bp-18h]@4
+  std::string *v13; // [sp+Ch] [bp-8h]@4
+  int a3; // [sp+13h] [bp-1h]@4
+
+  v1 = npcid;
+  if ( (npcid & 0x80000000u) == 0 )
+  {
+    if ( (signed int)npcid < 5000 )
+    {
+      if ( (signed int)npcid >= 501 )
+      {
+    MessageBoxW(nullptr, L"NPC id exceeds MAX_DATA!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Events.cpp:1984", 0);
+      }
+      return &pNPCStats->pNewNPCData[v1];
+    }
+    return &pNPCStats->array_13EF4[npcid - 5000];
+  }
+  if ( (signed int)npcid >= 5000 )
+    return &pNPCStats->array_13EF4[npcid - 5000];
+  if ( (uDialogue_SpeakingActorNPC_ID & 0x80000000u) == 0 )
+  {
+    result = 0;
+  }
+  else
+  {
+    v3 = abs((int)uDialogue_SpeakingActorNPC_ID) - 1;
+    v4 = 0;
+    v5 = 0;
+    v6 = pParty->pHirelings;
+    do
+    {
+      if ( v6->pName )
+        pTmpBuf[v4++] = v5;
+      ++v6;
+      ++v5;
+    }
+    while ( (signed int)v6 < (signed int)&pParty->pPickedItem );
+    v13 = 0;
+    if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+    {
+      v7 = &pTmpBuf[v4];
+      v8 = pNPCStats->pNewNPCData;
+      do
+      {
+        if ( v8->uFlags & 0x80
+          && (!pParty->pHirelings[0].pName || strcmp(v8->pName, pParty->pHirelings[0].pName))
+          && (!pParty->pHirelings[1].pName || strcmp(v8->pName, pParty->pHirelings[1].pName)) )
+          *v7++ = (char)v13 + 2;
+        v13 = (std::string *)((char *)v13 + 1);
+        ++v8;
+      }
+      while ( (signed int)v13 < (signed int)pNPCStats->uNumNewNPCs );
+    }
+    v9 = pTmpBuf[v3];
+    if ( (unsigned __int8)v9 >= 2u )
+      result = &pNPCStats->pNPCData[(unsigned __int8)v9 + 499];
+    else
+      result = &pParty->pHirelings[(unsigned __int8)v9];
+  }
+  return result;
+}
+
+//----- (00445B2C) --------------------------------------------------------
+NPCData *__fastcall GetNewNPCData(signed int npcid, int a2)
+{
+  signed int v2; // esi@1
+  int v3; // edi@1
+  NPCData *result; // eax@5
+  int v5; // esi@9
+  int v6; // ecx@9
+  int v7; // edx@9
+  NPCData *v8; // eax@9
+  NPCData *v9; // edi@14
+  int v10; // ecx@20
+  char v11; // al@23
+  std::string v12; // [sp-18h] [bp-34h]@4
+  const char *v13; // [sp-8h] [bp-24h]@4
+  int v14; // [sp-4h] [bp-20h]@4
+  std::string *v15; // [sp+Ch] [bp-10h]@1
+  char *v16; // [sp+10h] [bp-Ch]@14
+  int v17; // [sp+14h] [bp-8h]@13
+  int a3; // [sp+1Bh] [bp-1h]@4
+
+  v2 = npcid;
+  v3 = a2;
+  v15 = (std::string *)a2;
+  if ( npcid >= 0 )
+  {
+    if ( npcid < 5000 )
+    {
+      if ( npcid >= 501 )
+      {
+    MessageBoxW(nullptr, L"NPC id exceeds MAX_DATA!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Events.cpp:2040", 0);
+      }
+      *(int *)v3 = v2;
+      return &pNPCStats->pNewNPCData[v2];
+    }
+LABEL_7:
+    *(int *)a2 = npcid - 5000;
+    return &pNPCStats->array_13EF4[npcid - 5000];
+  }
+  if ( npcid >= 5000 )
+    goto LABEL_7;
+  if ( (uDialogue_SpeakingActorNPC_ID & 0x80000000u) == 0 )
+  {
+    *(int *)a2 = 0;
+    result = 0;
+  }
+  else
+  {
+    v5 = abs((int)uDialogue_SpeakingActorNPC_ID) - 1;
+    v6 = 0;
+    v7 = 0;
+    v8 = pParty->pHirelings;
+    do
+    {
+      if ( v8->pName )
+        pTmpBuf[v6++] = v7;
+      ++v8;
+      ++v7;
+    }
+    while ( (signed int)v8 < (signed int)&pParty->pPickedItem );
+    v17 = 0;
+    if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+    {
+      v9 = pNPCStats->pNewNPCData;
+      v16 = &pTmpBuf[v6];
+      do
+      {
+        if ( v9->uFlags & 0x80
+          && (!pParty->pHirelings[0].pName || strcmp(v9->pName, pParty->pHirelings[0].pName))
+          && (!pParty->pHirelings[1].pName || strcmp(v9->pName, pParty->pHirelings[1].pName)) )
+        {
+          v10 = (int)v16++;
+          *(char *)v10 = v17 + 2;
+        }
+        ++v17;
+        ++v9;
+      }
+      while ( v17 < (signed int)pNPCStats->uNumNewNPCs );
+      v3 = (int)v15;
+    }
+    v11 = pTmpBuf[v5];
+    if ( (unsigned __int8)v11 >= 2u )
+    {
+      *(int *)v3 = (unsigned __int8)v11 - 2;
+      result = &pNPCStats->pNPCData[(unsigned __int8)pTmpBuf[v5] + 499];
+    }
+    else
+    {
+      *(int *)v3 = (unsigned __int8)v11;
+      result = &pParty->pHirelings[(unsigned __int8)pTmpBuf[v5]];
+    }
+  }
+  return result;
+}
+
+//----- (00445C8B) --------------------------------------------------------
+int __fastcall sub_445C8B(signed int a1)
+{
+  signed int v1; // ebx@1
+  int v3; // edi@6
+  int v4; // ecx@6
+  int v5; // edx@6
+  NPCData *v6; // eax@6
+  char *v7; // ebp@11
+  NPCData *v8; // esi@11
+
+  v1 = 0;
+  if ( a1 >= 0 )
+  {
+    if ( a1 < 5000 )
+      return 1;
+    return 2;
+  }
+  if ( a1 >= 5000 )
+    return 2;
+  v3 = abs((int)uDialogue_SpeakingActorNPC_ID) - 1;
+  v4 = 0;
+  v5 = 0;
+  v6 = pParty->pHirelings;
+  do
+  {
+    if ( v6->pName )
+      pTmpBuf[v4++] = v5;
+    ++v6;
+    ++v5;
+  }
+  while ( (signed int)v6 < (signed int)&pParty->pPickedItem );
+  if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+  {
+    v7 = &pTmpBuf[v4];
+    v8 = pNPCStats->pNewNPCData;
+    do
+    {
+      if ( v8->uFlags & 0x80 && (!pParty->pHirelings[0].pName || strcmp(v8->pName, pParty->pHirelings[0].pName)) )
+      {
+        if ( !pParty->pHirelings[1].pName || strcmp(v8->pName, pParty->pHirelings[1].pName) )
+          *v7++ = v1 + 2;
+      }
+      ++v1;
+      ++v8;
+    }
+    while ( v1 < (signed int)pNPCStats->uNumNewNPCs );
+  }
+  return ((unsigned __int8)pTmpBuf[v3] < 2u) + 1;
+}
+
+
+//----- (0044603D) --------------------------------------------------------
+void __cdecl sub_44603D()
+{
+  uDialogue_SpeakingActorNPC_ID = 0;
+  pDialogueWindow->Release();
+  pDialogueWindow = 0;
+  pMiscTimer->Resume();
+  pEventTimer->Resume();
+}
+
+
+//----- (004465DF) --------------------------------------------------------
+int sub_4465DF_check_season(int a1)
+{
+  unsigned int v1; // eax@1
+  unsigned int v2; // edx@1
+  int v3; // ecx@2
+  int v4; // ecx@3
+  char v6; // zf@9
+
+  v1 = pParty->uCurrentMonth + 1;
+  v2 = pParty->uDaysPlayed + 1;
+  if ( a1 )
+  {
+    v3 = a1 - 1;
+    if ( v3 )
+    {
+      v4 = v3 - 1;
+      if ( v4 )
+      {
+        if ( v4 != 1 )
+          return 0;
+        if ( v1 != 12 )
+        {
+          if ( (signed int)v1 >= 1 && (signed int)v1 <= 2 )
+            return 1;
+          v6 = v1 == 3;
+LABEL_24:
+          if ( !v6 || (signed int)v2 >= 21 )
+            return 0;
+          return 1;
+        }
+      }
+      else
+      {
+        if ( v1 != 9 )
+        {
+          if ( (signed int)v1 >= 10 && (signed int)v1 <= 11 )
+            return 1;
+          v6 = v1 == 12;
+          goto LABEL_24;
+        }
+      }
+    }
+    else
+    {
+      if ( v1 != 6 )
+      {
+        if ( (signed int)v1 >= 7 && (signed int)v1 <= 8 )
+          return 1;
+        v6 = v1 == 9;
+        goto LABEL_24;
+      }
+    }
+  }
+  else
+  {
+    if ( v1 != 3 )
+    {
+      if ( (signed int)v1 >= 4 && (signed int)v1 <= 5 )
+        return 1;
+      v6 = v1 == 6;
+      goto LABEL_24;
+    }
+  }
+  if ( (signed int)v2 >= 21 )
+    return 1;
+  return 0;
+}
+
+//----- (0044665D) --------------------------------------------------------
+// uType:     0 -> any monster
+//            1 -> uParam is GroupID
+//            2 -> uParam is MonsterID
+//            3 -> uParam is ActorID
+// uNumAlive: 0 -> all must be alive
+int __fastcall IsActorAlive(unsigned int uType, unsigned int uParam, unsigned int uNumAlive)
+{
+  unsigned int uAliveActors; // eax@6
+  int v5; // ecx@10
+  unsigned int uTotalActors; // [sp+0h] [bp-4h]@1
+
+  uTotalActors = 0;
+  if ( uType )
+  {
+    if ( uType == 1 )
+    {
+      uAliveActors = SearchActorByGroup(&uTotalActors, uParam);
+    }
+    else
+    {
+      if ( uType == 2 )
+      {
+        uAliveActors = SearchActorByMonsterID(&uTotalActors, uParam);
+      }
+      else
+      {
+        if ( uType != 3 )
+          return 0;
+        uAliveActors = SearchActorByID(&uTotalActors, uParam);
+      }
+    }
+  }
+  else
+  {
+    uAliveActors = SearchAliveActors(&uTotalActors);
+  }
+  v5 = 0;
+  if ( uNumAlive )
+    LOBYTE(v5) = (signed int)uAliveActors >= (signed int)uNumAlive;
+  else
+    LOBYTE(v5) = uTotalActors == uAliveActors;
+  return v5;
+}
+
+//----- (004466C4) --------------------------------------------------------
+bool __thiscall sub_4466C4(void *_this)
+{
+  signed int v1; // ebp@1
+  bool result; // eax@2
+  int v3; // esi@3
+  signed int v4; // edx@3
+  signed int v5; // eax@4
+  unsigned int v6; // ebx@6
+  char *v7; // eax@6
+  signed int v8; // edi@18
+  int v9; // eax@19
+  Player *v10; // [sp+8h] [bp-10h]@18
+  signed int v11; // [sp+Ch] [bp-Ch]@3
+  signed int v12; // [sp+10h] [bp-8h]@3
+  void *v13; // [sp+14h] [bp-4h]@1
+
+  v1 = 0;
+  v13 = _this;
+  if ( !_this )
+    return 0;
+  v3 = dword_597F18;
+  pSomeOtherEVT = pGlobalEVT;
+  uSomeOtherEVT_NumEvents = uGlobalEVT_NumEvents;
+  memcpy(pSomeOtherEVT_Events, pGlobalEVT_Events, 0xCE40u);
+  v4 = 1;
+  v12 = 1;
+  v11 = 0;
+  if ( (signed int)uSomeOtherEVT_NumEvents <= 0 )
+    goto LABEL_16;
+  do
+  {
+    v5 = v1;
+    if ( (void *)pSomeOtherEVT_Events[v1].uEventID == v13 && pSomeOtherEVT_Events[v5].field_4 == v3 )
+    {
+      v6 = pSomeOtherEVT_Events[v5].uEventOffsetInEVT;
+      v7 = &pSomeOtherEVT[v6];
+      if ( (unsigned __int8)pSomeOtherEVT[v6 + 4] == 1 )
+        break;
+      if ( (unsigned __int8)pSomeOtherEVT[v6 + 4] == 44 )
+      {
+        v11 = v4;
+        v10 = pParty->pPlayers;
+        v8 = (unsigned __int8)v7[7]
+           + (((unsigned __int8)v7[8] + (((unsigned __int8)v7[9] + ((unsigned __int8)v7[10] << 8)) << 8)) << 8);
+        while ( 1 )
+        {
+          LOBYTE(v9) = v10->CompareVariable(
+                         (enum VariableType)((unsigned __int8)pSomeOtherEVT[v6 + 5]
+                                           + ((unsigned __int8)pSomeOtherEVT[v6 + 6] << 8)),
+                         v8);
+          if ( v9 )
+            break;
+          ++v10;
+          if ( (signed int)v10 >= (signed int)pParty->pHirelings )
+            goto LABEL_13;
+        }
+      }
+      else
+      {
+        if ( (unsigned __int8)pSomeOtherEVT[v6 + 4] == 45 )
+          break;
+        if ( (unsigned __int8)pSomeOtherEVT[v6 + 4] == 46 )
+        {
+          v11 = v4;
+          v12 = (unsigned __int8)v7[5];
+          goto LABEL_13;
+        }
+        if ( (unsigned __int8)pSomeOtherEVT[v6 + 4] != 52
+          || !IsActorAlive(
+                (unsigned __int8)v7[5],
+                (unsigned __int8)v7[6]
+              + (((unsigned __int8)v7[7] + (((unsigned __int8)v7[8] + ((unsigned __int8)v7[9] << 8)) << 8)) << 8),
+                (unsigned __int8)v7[10]) )
+          goto LABEL_13;
+      }
+      v1 = -1;
+      v3 = (unsigned __int8)pSomeOtherEVT[v6 + 11] - 1;
+LABEL_13:
+      ++v3;
+      v4 = 1;
+    }
+    ++v1;
+  }
+  while ( v1 < (signed int)uSomeOtherEVT_NumEvents );
+  if ( v11 )
+    result = v12 != 0;
+  else
+LABEL_16:
+    result = 2;
+  return result;
+}
+
+
+//----- (0044684A) --------------------------------------------------------
+void __fastcall EventProcessor(int uEventID, int a2, int a3)
+{
+  unsigned int v3; // eax@5
+  //signed int v4; // esi@7
+  //char *v5; // eax@8
+  Player *v6; // ecx@8
+  //char *v7; // ebp@8
+  //signed int v8; // edx@10
+  //int v9; // edi@12
+  //ByteArray *v10; // esi@12
+  int v11; // eax@14
+  char *v12; // eax@15
+  //char *v13; // edi@21
+  int v14; // ebp@21
+  int v15; // edi@21
+  const char *v16; // esi@21
+  bool v17; // edx@21
+  int v18; // ecx@22
+  int v19; // ebp@36
+  signed int v20; // ecx@40
+  int v21; // eax@40
+  int v22; // edx@40
+  int v23; // eax@40
+  unsigned __int16 v24; // ax@45
+  int v25; // eax@54
+  LevelDecoration *v26; // eax@55
+  int v27; // eax@57
+  int v28; // ecx@57
+  int v29; // edx@58
+  int v30; // eax@58
+  int v31; // ecx@58
+  int v32; // esi@58
+  NPCData *v33; // ecx@58
+  int v34; // esi@59
+  int v35; // esi@60
+  int v36; // esi@61
+  int v37; // esi@62
+  int v38; // eax@78
+  int v39; // ecx@78
+  size_t v40; // edx@78
+  char *v41; // esi@79
+  int v42; // eax@84
+  int v43; // ecx@84
+  size_t v44; // edx@84
+  char *v45; // esi@85
+  void *v46; // eax@91
+  GUIWindow *v47; // eax@93
+  GUIButton *v48; // ecx@93
+  GUIButton *v49; // esi@94
+  char v50; // al@100
+  Player *v51; // esi@103
+  Player *v52; // ecx@106
+  int v53; // ecx@107
+  char v54; // al@111
+  Player *v55; // esi@114
+  Player *v56; // ecx@117
+  int v57; // ecx@118
+  signed int v58; // ebp@124
+  Player *v59; // esi@125
+  int v60; // eax@126
+  int v61; // edx@133
+  int v62; // eax@139
+  void *v63; // ebp@145
+  signed int v64; // edi@146
+  unsigned int v65; // edx@148
+  Player *v66; // ecx@148
+  int v67; // esi@148
+  signed int v68; // eax@151
+  int v69; // esi@151
+  Player *v70; // ecx@158
+  unsigned int v71; // eax@159
+  int v72; // esi@159
+  signed int v73; // eax@162
+  int v74; // esi@162
+  int v75; // edx@172
+  Player *v76; // esi@173
+  signed int v77; // ebp@186
+  int v78; // edx@186
+  Player *v79; // esi@187
+  signed int v80; // ebp@200
+  int v81; // edx@200
+  Player *v82; // esi@201
+  int v83; // eax@212
+  int v84; // ebp@220
+  signed int v85; // ebp@224
+  char v86; // al@224
+  Player *v87; // esi@227
+  Player *v88; // ecx@231
+  int v89; // ecx@232
+  int v90; // eax@243
+  const char *v91; // ecx@247
+  int v92; // eax@251
+  char *v93; // eax@252
+  int v94; // ecx@262
+  int v95; // ebp@262
+  int v96; // edx@262
+  int v97; // eax@262
+  unsigned int v98; // edx@265
+  const char *v99; // esi@267
+  int v100; // edx@267
+  //char *v101; // edi@281
+  unsigned int v102; // esi@281
+  int v103; // edi@284
+  int v104; // eax@288
+  int v105; // edx@294
+  int v106; // [sp-20h] [bp-4C8h]@278
+  signed int v107; // [sp-1Ch] [bp-4C4h]@278
+  unsigned int v108; // [sp-18h] [bp-4C0h]@278
+  signed int v109; // [sp-14h] [bp-4BCh]@278
+  signed int v110; // [sp-10h] [bp-4B8h]@278
+  int v111; // [sp-Ch] [bp-4B4h]@278
+  Event *v112; // [sp-8h] [bp-4B0h]@5
+  int v113; // [sp-8h] [bp-4B0h]@106
+  int v114; // [sp-8h] [bp-4B0h]@117
+  signed int v115; // [sp-8h] [bp-4B0h]@231
+  unsigned int v116; // [sp-8h] [bp-4B0h]@278
+  int v117; // [sp-4h] [bp-4ACh]@106
+  int v118; // [sp-4h] [bp-4ACh]@117
+  int v119; // [sp-4h] [bp-4ACh]@231
+  int v120; // [sp-4h] [bp-4ACh]@278
+  int v121; // [sp-4h] [bp-4ACh]@294
+  int v122; // [sp+10h] [bp-498h]@4
+  //char *v123; // [sp+14h] [bp-494h]@0
+  //signed int v124; // [sp+18h] [bp-490h]@7
+  signed int v125; // [sp+1Ch] [bp-48Ch]@155
+  int v126; // [sp+1Ch] [bp-48Ch]@262
+  int v127; // [sp+20h] [bp-488h]@4
+  int v128; // [sp+24h] [bp-484h]@21
+  int v129; // [sp+24h] [bp-484h]@262
+  signed int v130; // [sp+28h] [bp-480h]@0
+  //int v131; // [sp+2Ch] [bp-47Ch]@1
+  int v132; // [sp+30h] [bp-478h]@262
+  signed int v133; // [sp+34h] [bp-474h]@1
+  int v134; // [sp+38h] [bp-470h]@262
+  int v135; // [sp+3Ch] [bp-46Ch]@262
+  int v136; // [sp+40h] [bp-468h]@40
+  int v137; // [sp+44h] [bp-464h]@40
+  int v138; // [sp+48h] [bp-460h]@40
+  int v139; // [sp+4Ch] [bp-45Ch]@40
+  ItemGen item; // [sp+50h] [bp-458h]@15
+  char Source[120]; // [sp+74h] [bp-434h]@15
+  char Str[120]; // [sp+ECh] [bp-3BCh]@21
+  Actor Dst; // [sp+164h] [bp-344h]@53
+
+  //v131 = uEventID;
+  v133 = 0;
+  dword_5B5920 = a2;
+  dword_5B65C4 = 0;
+  if ( !a1 )
+  {
+    if ( !GameUI_StatusBar_TimedStringTimeLeft )
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[521], 2u);// Nothing here
+    return;
+  }
+  v127 = 2 * (uActiveCharacter == 0) + 4;
+  v122 = dword_597F18;
+  if ( _5C3420_pDecoration )
+  {
+    v3 = uGlobalEVT_NumEvents;
+    pSomeEVT = pGlobalEVT;
+    v112 = pGlobalEVT_Events;
+  }
+  else
+  {
+    v3 = uLevelEVT_NumEvents;
+    pSomeEVT = pLevelEVT;
+    v112 = pLevelEVT_Events;
+  }
+  uSomeEVT_NumEvents = v3;
+  memcpy(pSomeEVT_Events, v112, 0xCE40u);
+  //v4 = 0;
+  //v124 = 0;
+  for (uint i = 0; i < uSomeEVT_NumEvents; ++i)
+  {
+    //v5 = pSomeEVT;
+    //v6 = v123;
+    //v7 = "";
+    //while ( 1 )
+    //{
+      if ( dword_5B65C4 )
+        goto LABEL_301;
+      //v8 = v4;
+      if ( pSomeEVT_Events[i/*v4*/].uEventID == uEventID && pSomeEVT_Events[i/*v4*/].field_4 == v122 )
+      {
+        //v9 = pSomeEVT_Events[v8].uEventOffsetInEVT;
+        //v10 = (ByteArray *)&v5[v9];
+        auto _evt = (_evt_raw *)(pSomeEVT + pSomeEVT_Events[i/*v4*/].uEventOffsetInEVT);
+
+        switch (_evt->v4)
+        {
+          case EVENT_CheckSeason:
+            if ( !sub_4465DF_check_season(_evt->v5) )
+              goto LABEL_291;
+            v11 = _evt->v6;
+            goto LABEL_130;
+          case EVENT_ShowMovie:
+            strcpy(Source, (char *)&_evt->v7);
+            v12 = (char *)&item.uExpireTime + strlen(Source) + 7;
+            if ( *v12 == 32 )
+              *v12 = 0;
+            if ( pVideoPlayer->field_54 )
+              pVideoPlayer->Unload();
+            pVideoPlayer->bStopBeforeSchedule = 0;
+            pVideoPlayer->field_40 = 0;
+            if (pAsyncMouse)
+              pAsyncMouse->Suspend();
+            v128 = pCurrentScreen;
+            //v13 = &pSomeEVT[v9];
+            //v14 = (unsigned __int8)v13[5];
+            //v15 = (unsigned __int8)v13[6];
+            v14 = _evt->v5;
+            v15 = _evt->v6;
+            strcpy(Str, Source);
+            v16 = RemoveQuotes(Str);
+            VideoPlayer::MovieLoop(v16, 0, v14, 1);
+            if ( !_strcmpi(v16, "arbiter good") )
+            {
+              pParty->uAlignment = 0;
+              v18 = 0;
+LABEL_23:
+              LOBYTE(v17) = 1;
+              SetUserInterface(v18, v17);
+              goto LABEL_28;
+            }
+            if ( !_strcmpi(v16, "arbiter evil") )
+            {
+              v18 = 2;
+              pParty->uAlignment = 2;
+              goto LABEL_23;
+            }
+            if ( !_strcmpi(v16, "pcout01") )    // moving to harmondale from emerald isle
+            {
+              Rest(0x2760u);
+              pParty->RestAndHeal();
+              pParty->field_764 = 0;
+            }
+LABEL_28:
+            if ( !v15 || v128 == 3 )
+            {
+              pCurrentScreen = v128;
+              if ( v128 == 3 )
+                pGameLoadingUI_ProgressBar->uType = GUIProgressBar::TYPE_Fullscreen;
+              if ( v128 == 13 )
+                pVideoPlayer->_4BF28F(pAnimatedRooms[uCurrentHouse_Animation].field_0, 1u);
+            }
+            if (pAsyncMouse)
+              pAsyncMouse->Resume();
+            goto LABEL_291;
+          case EVENT_CheckSkill:
+            v19 = _evt->v7 + ((_evt->v8 + ((_evt->v9 + ((unsigned int)_evt->v10 << 8)) << 8)) << 8);
+            if ( v127 < 0 )
+              goto LABEL_47;
+            if ( v127 <= 3 )
+            {
+              v24 = pParty->pPlayers[0].pActiveSkills[3486 * v127 + _evt->v5];
+            }
+            else
+            {
+              if ( v127 == 4 )
+              {
+                v24 = pPlayers[uActiveCharacter]->pActiveSkills[_evt->v5];
+              }
+              else
+              {
+                if ( v127 == 5 )
+                {
+                  v20 = 0;
+                  v21 = 3486 * v130 + _evt->v5;
+                  v136 = 1;
+                  LOWORD(v21) = pParty->pPlayers[0].pActiveSkills[v21];
+                  v137 = v21 & 0x40;
+                  v138 = v21 & 0x80;
+                  v22 = v21 & 0x100;
+                  v23 = v21 & 0x3F;
+                  v139 = v22;
+                  while ( v23 < v19 || !*(&v136 + _evt->v6) )
+                  {
+                    ++v20;
+                    if ( v20 >= 4 )
+                      goto LABEL_291;
+                  }
+LABEL_50:
+                  v11 = _evt->v11;
+                  goto LABEL_130;
+                }
+LABEL_47:
+                //v10 = (ByteArray *)&v5[v9];
+                v24 = pParty->pPlayers[0].pActiveSkills[_evt->v5 + 3486 * rand() % 4];
+              }
+            }
+            v136 = 1;
+            v137 = v24 & 0x40;
+            v138 = v24 & 0x80;
+            v139 = v24 & 0x100;
+            if ( (v24 & 0x3F) >= v19 && *(&v136 + _evt->v6) )
+              goto LABEL_50;
+            goto LABEL_291;
+          case EVENT_SpeakNPC:
+            if ( a3 )
+            {
+              //Actor::Actor(&Dst);
+              memset(&Dst, 0, 0x344u);
+              dword_5B65D0_dialogue_actor_npc_id = _evt->v5
+                                                 + ((_evt->v6
+                                                   + ((_evt->v7
+                                                     + ((unsigned int)_evt->v8 << 8)) << 8)) << 8);
+              Dst.uNPC_ID = dword_5B65D0_dialogue_actor_npc_id;
+              Dst.InitializeDialogue(0);
+            }
+            else
+            {
+              bDialogueUI_InitializeActor_NPC_ID = _evt->v5
+                                                 + ((_evt->v6 + ((_evt->v7 + ((unsigned int)_evt->v8 << 8)) << 8)) << 8);
+            }
+            goto LABEL_291;
+          case EVENT_ChangeEvent:
+            v25 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((unsigned int)_evt->v8 << 8)) << 8)) << 8);
+            if ( v25 )
+            {
+              stru_5E4C90._decor_events[_5C3420_pDecoration->_idx_in_stru123 - 75] = _evt->v5 - 124;
+            }
+            else
+            {
+              v26 = _5C3420_pDecoration;
+              stru_5E4C90._decor_events[_5C3420_pDecoration->_idx_in_stru123 - 75] = 0;
+              LOBYTE(v26->field_2) |= 0x20u;
+            }
+            goto LABEL_291;
+          case EVENT_SetNPCGreeting:
+            v27 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            v28 = _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8);
+            pNPCStats->pNewNPCData[v27].uFlags &= 0xFFFFFFFCu;
+            pNPCStats->pNewNPCData[v27].greet = v28;
+            goto LABEL_291;
+          case EVENT_SetNPCTopic:
+            v29 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            v30 = _evt->v10 + ((_evt->v11 + ((_evt->v12 + ((uint)_evt->v13 << 8)) << 8)) << 8);
+            v31 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            v32 = _evt->v9;
+            v33 = &pNPCStats->pNewNPCData[v31];
+            if ( v32 )
+            {
+              v34 = v32 - 1;
+              if ( v34 )
+              {
+                v35 = v34 - 1;
+                if ( v35 )
+                {
+                  v36 = v35 - 1;
+                  if ( v36 )
+                  {
+                    v37 = v36 - 1;
+                    if ( v37 )
+                    {
+                      if ( v37 == 1 )
+                        v33->evtf = v30;
+                    }
+                    else
+                    {
+                      v33->evte = v30;
+                    }
+                  }
+                  else
+                  {
+                    v33->evtd = v30;
+                  }
+                }
+                else
+                {
+                  v33->evtc = v30;
+                }
+              }
+              else
+              {
+                v33->evtb = v30;
+              }
+            }
+            else
+            {
+              v33->bDrawSomeAnim = v30;
+            }
+            if ( v29 == 8 )
+            {
+              if ( v30 == 78 )
+              {
+                sub_4BD8B5();
+                ptr_507BC0->Release();
+                pParty->uFlags &= 0xFFFFFFFDu;
+                if ( EnterHouse((enum HOUSE_TYPE)170) )
+                {
+                  pAudioPlayer->StopChannels(-1, -1);
+                  ptr_507BC0 = GUIWindow::Create(0, 0, 640, 480, WINDOW_HouseInterior, 170, 0);
+                  ptr_507BC0->CreateButton(0x3Du, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+                  ptr_507BC0->CreateButton(0xB1u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+                  ptr_507BC0->CreateButton(0x124u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+                  ptr_507BC0->CreateButton(0x197u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+                  ptr_507BC0->CreateButton(0, 0, 0, 0, 1, 0, 0xB0u, 0, 9u, "", 0);
+                  ptr_F8B1E8 = pNPCTopics[90].pText;
+                }
+              }
+            }
+            goto LABEL_291;
+          case EVENT_NPCSetItem:
+            sub_448518_npc_set_item(
+              _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8),
+              _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8),
+              _evt->v13);
+            goto LABEL_291;
+          case EVENT_SetActorItem:
+            Actor::GiveItem(
+              _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8),
+              _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8),
+              _evt->v13);
+            goto LABEL_291;
+          case EVENT_SetNPCGroupNews:
+            pNPCStats->pGroups_copy[_evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8)] = _evt->v9 + ((uint)_evt->v10 << 8);
+            goto LABEL_291;
+          case EVENT_SetActorGroup:
+            __debugbreak();
+            *(&pActors[0].uGroup + 0x11000000 * _evt->v8 + 209 * (_evt->v5 + ((_evt->v6 + ((uint)_evt->v7 << 8)) << 8))) = _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8);
+            goto LABEL_291;
+          case EVENT_ChangeGroup:
+            v38 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            v39 = _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8);
+            v40 = uNumActors;
+            __debugbreak();
+            if ( (signed int)uNumActors > 0 )
+            {
+              v41 = (char *)&pActors[0].uGroup;
+              do
+              {
+                if ( *(int *)v41 == v38 )
+                  *(int *)v41 = v39;
+                v41 += 836;
+                --v40;
+              }
+              while ( v40 );
+            }
+            goto LABEL_291;
+          case EVENT_ChangeGroupAlly:
+            v42 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            v43 = _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8);
+            v44 = uNumActors;
+            __debugbreak();
+            if ( (signed int)uNumActors > 0 )
+            {
+              v45 = (char *)&pActors[0].uAlly;
+              do
+              {
+                if ( *((int *)v45 - 1) == v42 )
+                  *(int *)v45 = v43;
+                v45 += 836;
+                --v44;
+              }
+              while ( v44 );
+            }
+            goto LABEL_291;
+          case EVENT_MoveNPC:
+            pNPCStats->pNewNPCData[_evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8)].house = _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8);
+            if ( ptr_507BC0 )
+            {
+              v46 = ptr_507BC0->ptr_1C;
+              if ( v46 == (void *)165 )
+              {
+                sub_4BD8B5();
+                pVideoPlayer->Unload();
+                ptr_507BC0->Release();
+                pParty->uFlags &= 0xFFFFFFFDu;
+                _5C3420_pDecoration = (LevelDecoration *)1;
+                if ( EnterHouse((enum HOUSE_TYPE)165) )
+                {
+                  pAudioPlayer->PlaySound((SoundID)0, 0, 0, -1, 0, 0, 0, 0);
+                  v47 = GUIWindow::Create(0, 0, 640, 480, WINDOW_HouseInterior, 165, 0);
+                  ptr_507BC0 = v47;
+                  v48 = v47->pControlsHead;
+                  if ( v48 )
+                  {
+                    do
+                    {
+                      v49 = v48->pNext;
+                      pAllocator->FreeChunk(v48);
+                      v48 = v49;
+                    }
+                    while ( v49 );
+                    v47 = ptr_507BC0;
+                  }
+                  v47->pControlsHead = 0;
+                  ptr_507BC0->pControlsTail = 0;
+                  ptr_507BC0->uNumControls = 0;
+                }
+              }
+              else
+              {
+                if ( v46 == (void *)553 )
+                  pVideoPlayer->bLoopPlaying = 0;
+              }
+            }
+            goto LABEL_291;
+          case EVENT_Jmp:
+            //v124 = -1;
+            v122 = _evt->v5 - 1;
+            goto LABEL_291;
+          case EVENT_ShowFace:
+            v50 = _evt->v5;
+            if ( (unsigned __int8)v50 <= 3u )
+            {
+              v117 = 0;
+              v113 = _evt->v6;
+              v53 = (unsigned __int8)v50;
+              goto LABEL_108;
+            }
+            if ( v50 == 4 )
+            {
+              v117 = 0;
+              v113 = _evt->v6;
+              v52 = pPlayers[uActiveCharacter];
+              goto LABEL_109;
+            }
+            if ( v50 != 5 )
+            {
+              v117 = 0;
+              v113 = _evt->v6;
+              v53 = rand() % 4;
+LABEL_108:
+              v52 = &pParty->pPlayers[v53];
+LABEL_109:
+              v52->PlayEmotion(v113, v117);
+              goto LABEL_291;
+            }
+            v51 = pParty->pPlayers;
+            do
+            {
+              v51->PlayEmotion(_evt->v6, 0);
+              ++v51;
+            }
+            while ( (signed int)v51 < (signed int)pParty->pHirelings );
+LABEL_291:
+            ++v122;
+            //v4 = v124;
+            //v5 = pSomeEVT;
+            //v6 = v123;
+            //v7 = "";
+            break;
+          case EVENT_CharacterAnimation:
+            v54 = _evt->v5;
+            if ( (unsigned __int8)v54 <= 3u )
+            {
+              v118 = 0;
+              v114 = _evt->v6;
+              v57 = (unsigned __int8)v54;
+              goto LABEL_119;
+            }
+            if ( v54 == 4 )
+            {
+              v118 = 0;
+              v114 = _evt->v6;
+              v56 = pPlayers[uActiveCharacter];
+              goto LABEL_120;
+            }
+            if ( v54 != 5 )
+            {
+              v118 = 0;
+              v114 = _evt->v6;
+              v57 = rand() % 4;
+LABEL_119:
+              v56 = &pParty->pPlayers[v57];
+LABEL_120:
+              v56->PlaySound(v114, v118);
+              goto LABEL_291;
+            }
+            v55 = pParty->pPlayers;
+            do
+            {
+              v55->PlaySound(_evt->v6, 0);
+              ++v55;
+            }
+            while ( (signed int)v55 < (signed int)pParty->pHirelings );
+            goto LABEL_291;
+          case EVENT_ForPartyMember:
+            v127 = _evt->v5;
+            goto LABEL_291;
+          case EVENT_SummonItem:
+            sub_42F7EB_DropItemAt(
+              _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8),
+              _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8),
+              _evt->v13 + ((_evt->v14 + ((_evt->v15 + ((uint)_evt->v16 << 8)) << 8)) << 8),
+              _evt->v17 + ((_evt->v18 + ((_evt->v19 + ((uint)_evt->v20 << 8)) << 8)) << 8),
+              _evt->v21 + ((_evt->v22 + ((_evt->v23 + ((uint)_evt->v24 << 8)) << 8)) << 8),
+              _evt->v25,
+              _evt->v26,
+              0,
+              0);
+            goto LABEL_291;
+          case EVENT_Compare:
+            v58 = _evt->v7 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v10 << 8)) << 8)) << 8);
+            if ( v127 == 5 )
+            {
+              v130 = 0;
+              v59 = pParty->pPlayers;
+              while ( 1 )
+              {
+                LOBYTE(v60) = v59->CompareVariable(
+                                (enum VariableType)(_evt->v5
+                                                  + ((uint)_evt->v6 << 8)),
+                                v58);
+                if ( v60 )
+                  break;
+                ++v130;
+                ++v59;
+                if ( (signed int)v59 >= (signed int)pParty->pHirelings )
+                  goto LABEL_291;
+              }
+LABEL_129:
+              v11 = _evt->v11;
+              goto LABEL_130;
+            }
+            if ( v127 < 0 )
+              goto LABEL_139;
+            v61 = v127;
+            if ( v127 <= 3 )
+              goto LABEL_137;
+            if ( v127 == 4 )
+            {
+              if ( uActiveCharacter )
+              {
+                v6 = pPlayers[uActiveCharacter];
+                goto LABEL_138;
+              }
+            }
+            else
+            {
+              if ( v127 != 6 )
+                goto LABEL_139;
+            }
+            v61 = rand() % 4;
+            //v5 = pSomeEVT;
+LABEL_137:
+            v6 = &pParty->pPlayers[v61];
+LABEL_138:
+            //v123 = v6;
+LABEL_139:
+            LOBYTE(v62) = ((Player *)v6)->CompareVariable(
+                            (enum VariableType)(_evt->v5 + ((uint)_evt->v6 << 8)),
+                            v58);
+LABEL_140:
+            if ( v62 )
+              goto LABEL_129;
+            goto LABEL_291;
+          case EVENT_IsActorAlive:
+            v62 = IsActorAlive(
+                    _evt->v5,
+                    _evt->v6 + ((_evt->v7 + ((_evt->v8 + ((uint)_evt->v9 << 8)) << 8)) << 8),
+                    _evt->v10);
+            goto LABEL_140;
+          case EVENT_Substract:
+            v63 = (void *)(_evt->v7 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v10 << 8)) << 8)) << 8));
+            if ( _evt->v5 + ((uint)_evt->v6 << 8) == VAR_PlayerItemInHands )
+            {
+              v64 = 0;
+              if ( (void *)pParty->pPickedItem.uItemID == v63 )
+              {
+                pMouse->RemoveHoldingItem();
+                goto LABEL_291;
+              }
+              v65 = 0;
+              v66 = pPlayers[uActiveCharacter];
+              v67 = (int)v66->pInventoryIndices;
+              do
+              {
+                if ( *(void **)&v66->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v67 + 5] == v63 )
+                {
+                  v66->RemoveItemAtInventoryIndex(v65);
+                  goto LABEL_291;
+                }
+                ++v65;
+                v67 += 4;
+              }
+              while ( (signed int)v65 < 126 );
+              v68 = 0;
+              v69 = (int)&v66->pEquipment;
+              do
+              {
+                if ( *(int *)v69 && *(void **)&v66->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v69 + 5] == v63 )
+                {
+                  *(&v66->pEquipment.uOffHand + v68) = 0;
+                  goto LABEL_291;
+                }
+                ++v68;
+                v69 += 4;
+              }
+              while ( v68 < 16 );
+              v125 = (signed int)&pPlayers[1];
+              while ( 1 )
+              {
+                v70 = *(Player **)v125;
+                if ( !v64 )
+                {
+                  v71 = 0;
+                  v72 = (int)v70->pInventoryIndices;
+                  do
+                  {
+                    if ( *(void **)&v70->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v72 + 5] == v63 )
+                    {
+                      v70->RemoveItemAtInventoryIndex(v71);
+                      goto LABEL_169;
+                    }
+                    ++v71;
+                    v72 += 4;
+                  }
+                  while ( (signed int)v71 < 126 );
+                  v73 = 0;
+                  v74 = (int)&v70->pEquipment;
+                  while ( !*(int *)v74
+                       || *(void **)&v70->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v74 + 5] != v63 )
+                  {
+                    ++v73;
+                    v74 += 4;
+                    if ( v73 >= 16 )
+                      goto LABEL_170;
+                  }
+                  *(&v70->pEquipment.uOffHand + v73) = 0;
+LABEL_169:
+                  v64 = 1;
+                }
+LABEL_170:
+                v125 += 4;
+                if ( v125 > (signed int)&pPlayers[4] )
+                  goto LABEL_291;
+              }
+            }
+            v75 = v127;
+            if ( v127 != 5 )
+            {
+              if ( v127 < 0 )
+                goto LABEL_183;
+              if ( v127 > 3 )
+              {
+                if ( v127 != 4 )
+                {
+                  if ( v127 == 6 )
+                    goto LABEL_180;
+LABEL_183:
+                  ((Player *)v6)->SubtractVariable(
+                    (enum VariableType)(_evt->v5 + ((uint)_evt->v6 << 8)),
+                    v63);
+                  goto LABEL_291;
+                }
+                if ( uActiveCharacter )
+                {
+                  v6 = pPlayers[uActiveCharacter];
+                  goto LABEL_182;
+                }
+LABEL_180:
+                v75 = rand() % 4;
+                //v5 = pSomeEVT;
+              }
+              v6 = &pParty->pPlayers[v75];
+LABEL_182:
+              //v123 = v6;
+              goto LABEL_183;
+            }
+            v76 = pParty->pPlayers;
+            v130 = 4;
+            do
+            {
+              v76->SubtractVariable(
+                (enum VariableType)(_evt->v5 + ((uint)_evt->v6 << 8)),
+                v63);
+              ++v76;
+            }
+            while ( (signed int)v76 < (signed int)pParty->pHirelings );
+            goto LABEL_291;
+          case EVENT_Set:
+            v77 = _evt->v7 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v10 << 8)) << 8)) << 8);
+            v78 = v127;
+            if ( v127 != 5 )
+            {
+              if ( v127 < 0 )
+                goto LABEL_197;
+              if ( v127 > 3 )
+              {
+                if ( v127 != 4 )
+                {
+                  if ( v127 == 6 )
+                    goto LABEL_194;
+LABEL_197:
+                  ((Player *)v6)->SetVariable(
+                    (enum VariableType)(_evt->v5 + ((uint)_evt->v6 << 8)),
+                    v77);
+                  goto LABEL_291;
+                }
+                if ( uActiveCharacter )
+                {
+                  v6 = pPlayers[uActiveCharacter];
+                  goto LABEL_196;
+                }
+LABEL_194:
+                v78 = rand() % 4;
+                //v5 = pSomeEVT;
+              }
+              v6 = &pParty->pPlayers[v78];
+LABEL_196:
+              //v123 = v6;
+              goto LABEL_197;
+            }
+            v79 = pParty->pPlayers;
+            v130 = 4;
+            do
+            {
+              v79->SetVariable(
+                (enum VariableType)(_evt->v5 + ((uint)_evt->v6 << 8)),
+                v77);
+              ++v79;
+            }
+            while ( (signed int)v79 < (signed int)pParty->pHirelings );
+            goto LABEL_291;
+          case EVENT_Add:
+            v80 = _evt->v7 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v10 << 8)) << 8)) << 8);
+            v81 = v127;
+            if ( v127 != 5 )
+            {
+              if ( v127 < 0 )
+                goto LABEL_211;
+              if ( v127 > 3 )
+              {
+                if ( v127 != 4 )
+                {
+                  if ( v127 == 6 )
+                    goto LABEL_208;
+LABEL_211:
+                  ((Player *)v6)->AddVariable(
+                    (enum VariableType)(_evt->v5 + ((uint)_evt->v6 << 8)),
+                    v80);
+                  goto LABEL_212;
+                }
+                if ( uActiveCharacter )
+                {
+                  v6 = pPlayers[uActiveCharacter];
+                  goto LABEL_210;
+                }
+LABEL_208:
+                v81 = rand() % 4;
+                //v5 = pSomeEVT;
+              }
+              v6 = &pParty->pPlayers[v81];
+LABEL_210:
+              //v123 = v6;
+              goto LABEL_211;
+            }
+            v82 = pParty->pPlayers;
+            v130 = 4;
+            do
+            {
+              v82->AddVariable(
+                (enum VariableType)(_evt->v5 + ((uint)_evt->v6 << 8)),
+                v80);
+              ++v82;
+            }
+            while ( (signed int)v82 < (signed int)pParty->pHirelings );
+LABEL_212:
+            v83 = _evt->v5 + ((uint)_evt->v6 << 8);
+            if ( v83 == 21 || v83 == 22 || v83 == 23 || v83 == 24 )
+              viewparams->bRedrawGameUI = 1;
+            goto LABEL_291;
+          case EVENT_InputString:
+            if ( !dword_597F18 )
+            {
+              strcpy(
+                GameUI_StatusBar_TimedString,
+                &pLevelStr[pLevelStrOffsets[_evt->v5
+                                          + ((_evt->v6
+                                            + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8)]]);
+              v105 = v122;
+              v121 = 26;
+LABEL_295:
+              sub_4451A8_press_any_key(uEventID, v105, v121);
+LABEL_301:
+              if ( v133 == 1 )
+LABEL_302:
+                OnMapLeave();
+              return;
+            }
+            v84 = _evt->v13 + ((_evt->v14 + ((_evt->v15 + ((uint)_evt->v16 << 8)) << 8)) << 8);
+            if ( !_strcmpi(
+                    GameUI_StatusBar_TimedString,
+                    &pLevelStr[pLevelStrOffsets[_evt->v9
+                                              + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8)]])
+              || !_strcmpi(GameUI_StatusBar_TimedString, &pLevelStr[pLevelStrOffsets[v84]]) )
+            {
+              v11 = _evt->v17;
+LABEL_130:
+              //v124 = -1;
+LABEL_131:
+              v122 = v11 - 1;
+            }
+            goto LABEL_291;
+          case EVENT_RandomGoTo:
+            //v124 = -1;
+            v11 = (unsigned __int8)*(&_evt->v5
+                                   + rand()
+                                   % ((_evt->v5 != 0)
+                                    + (_evt->v6 != 0)
+                                    + (_evt->v7 != 0)
+                                    + (_evt->v8 != 0)
+                                    + (_evt->v9 != 0)
+                                    + (_evt->v10 != 0)));
+            goto LABEL_131;
+          case EVENT_ReceiveDamage:
+            v85 = _evt->v7 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v10 << 8)) << 8)) << 8);
+            v86 = _evt->v5;
+            if ( (unsigned __int8)v86 <= 3u )
+            {
+              v119 = _evt->v6;
+              v115 = _evt->v7 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v10 << 8)) << 8)) << 8);
+              v89 = (unsigned __int8)v86;
+              goto LABEL_233;
+            }
+            if ( v86 == 4 )
+            {
+              if ( !uActiveCharacter )
+                goto LABEL_291;
+              v119 = _evt->v6;
+              v88 = pPlayers[uActiveCharacter];
+              v115 = _evt->v7 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v10 << 8)) << 8)) << 8);
+              goto LABEL_234;
+            }
+            if ( v86 != 5 )
+            {
+              v119 = _evt->v6;
+              v115 = _evt->v7 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v1 << 8)) << 8)) << 8);
+              v89 = rand() % 4;
+LABEL_233:
+              v88 = &pParty->pPlayers[v89];
+LABEL_234:
+              v88->ReceiveDamage(v115, v119);
+              goto LABEL_291;
+            }
+            v87 = pParty->pPlayers;
+            do
+            {
+              v87->ReceiveDamage(v85, _evt->v6);
+              ++v87;
+            }
+            while ( (signed int)v87 < (signed int)pParty->pHirelings );
+            goto LABEL_291;
+          case EVENT_ToggleIndoorLight:
+            pIndoor->ToggleLight(_evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8), _evt->v9);
+            goto LABEL_291;
+          case EVENT_SetFacesBit:
+            sub_44892E_set_faces_bit(
+              _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8),
+              _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8),
+              _evt->v13);
+            goto LABEL_291;
+          case EVENT_ToggleChestFlag:
+            Chest::ToggleFlag(
+              _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8),
+              _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8),
+              _evt->v13);
+            goto LABEL_291;
+          case EVENT_ToggleActorFlag:
+            Actor::ToggleFlag(
+              _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8),
+              _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8),
+              _evt->v13);
+            goto LABEL_291;
+          case EVENT_ToggleActorGroupFlag:
+            ToggleActorGroupFlag(
+              _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8),
+              _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8),
+              _evt->v13);
+            goto LABEL_291;
+          case EVENT_SetSnow:
+            if ( !_evt->v5 )
+              pWeather->bRenderSnow = _evt->v6 != 0;
+            goto LABEL_291;
+          case EVENT_StatusText:
+            v90 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            if ( _5C3420_pDecoration )
+            {
+              if ( _5C3420_pDecoration == (LevelDecoration *)1 )
+              {
+                ptr_F8B1E8 = (&dword_721664)[8 * v90];
+                goto LABEL_291;
+              }
+              if ( a3 == 1 )
+              {
+                v91 = (&dword_721664)[8 * v90];
+LABEL_248:
+                ShowStatusBarString(v91, 2u);
+                goto LABEL_291;
+              }
+            }
+            else
+            {
+              if ( a3 == 1 )
+              {
+                v91 = &pLevelStr[pLevelStrOffsets[v90]];
+                goto LABEL_248;
+              }
+            }
+            goto LABEL_291;
+          case EVENT_ShowMessage:
+            v92 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            if ( _5C3420_pDecoration )
+            {
+              v93 = (&dword_721664)[8 * v92];
+              byte_5B0938[0] = 0;
+              ptr_F8B1E8 = v93;
+            }
+            else
+            {
+              strcpy(byte_5B0938, &pLevelStr[pLevelStrOffsets[v92]]);
+            }
+            goto LABEL_291;
+          case EVENT_CastSpell:
+            sub_448DF8_cast_spell(
+              _evt->v5,
+              _evt->v6,
+              _evt->v7,
+              _evt->v8 + ((_evt->v9 + ((_evt->v10 + ((uint)_evt->v11 << 8)) << 8)) << 8),
+              _evt->v12 + ((_evt->v13 + ((_evt->v14 + ((uint)_evt->v15 << 8)) << 8)) << 8),
+              _evt->v16 + ((_evt->v17 + ((_evt->v18 + ((uint)_evt->v19 << 8)) << 8)) << 8),
+              _evt->v20 + ((_evt->v21 + ((_evt->v22 + ((uint)_evt->v23 << 8)) << 8)) << 8),
+              _evt->v24 + ((_evt->v25 + ((_evt->v26 + ((uint)_evt->v27 << 8)) << 8)) << 8),
+              _evt->v28 + ((_evt->v29 + ((_evt->v30 + ((uint)_evt->v31 << 8)) << 8)) << 8));
+            goto LABEL_291;
+          case EVENT_SetTexture:
+            sub_44861E_set_texture(_evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8), (char *)&_evt->v9);
+            goto LABEL_291;
+          case EVENT_SetSprite:
+            SetDecorationSprite(
+              _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8),
+              _evt->v9,
+              (char *)&_evt->v10);
+            goto LABEL_291;
+          case EVENT_SummonMonsters:
+            sub_448CF4_spawn_monsters(
+              _evt->v5,
+              _evt->v6,
+              _evt->v7,
+              _evt->v8 + ((_evt->v9 + ((_evt->v10 + ((uint)_evt->v11 << 8)) << 8)) << 8),
+              _evt->v12 + ((_evt->v13 + ((_evt->v14 + ((uint)_evt->v15 << 8)) << 8)) << 8),
+              _evt->v16 + ((_evt->v17 + ((_evt->v18 + ((uint)_evt->v19 << 8)) << 8)) << 8),
+              _evt->v20 + ((_evt->v21 + ((_evt->v22 + ((uint)_evt->v23 << 8)) << 8)) << 8),
+              _evt->v24 + ((_evt->v25 + ((_evt->v26 + ((uint)_evt->v27 << 8)) << 8)) << 8));
+            goto LABEL_291;
+          case EVENT_MouseOver:
+          case EVENT_LocationName:
+            --v122;
+            goto LABEL_291;
+          case EVENT_ChangeDoorState:
+            sub_449A49_door_switch_animation(_evt->v5, _evt->v6);
+            goto LABEL_291;
+          case EVENT_OpenChest:
+            if ( !Chest::Open(_evt->v5) )
+              goto LABEL_301;
+            goto LABEL_291;
+          case EVENT_MoveToMap:
+            v94 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            v135 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            v132 = _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8);
+            v126 = _evt->v13 + ((_evt->v14 + ((_evt->v15 + ((uint)_evt->v16 << 8)) << 8)) << 8);
+            v129 = _evt->v17 + ((_evt->v18 + ((_evt->v19 + ((uint)_evt->v20 << 8)) << 8)) << 8);
+            v95 = _evt->v21 + ((_evt->v22 + ((_evt->v23 + ((uint)_evt->v24 << 8)) << 8)) << 8);
+            v96 = _evt->v25;
+            v97 = v96 + ((_evt->v26 + ((_evt->v27 + ((uint)_evt->v28 << 8)) << 8)) << 8);
+            v134 = v96 + ((_evt->v26 + ((_evt->v27 + ((uint)_evt->v28 << 8)) << 8)) << 8);
+            if ( _evt->v29 || _evt->v30 )
+            {
+              if ( pRenderer->pRenderD3D && !pRenderer->bWindowMode )
+                pRenderer->_49FD3A();
+              sub_444839_move_map(
+                _evt->v29,
+                _evt->v30,
+                v135,
+                v132,
+                v126,
+                v129,
+                v95,
+                v134,
+                (char *)&_evt->v31);
+              dword_5C3418 = uEventID;
+              dword_5C341C = v122 + 1;
+              goto LABEL_301;
+            }
+            _5B65AC_npcdata_fame_or_other = _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8);
+            _5B65A8_npcdata_uflags_or_other = v94;
+            _5B65B0_npcdata_rep_or_other = v126;
+            if ( v129 == -1 )
+            {
+              v98 = _5B65B4_npcdata_loword_house_or_other;
+            }
+            else
+            {
+              v98 = v129 & stru_5C6E00->uDoublePiMask;
+              _5B65B4_npcdata_loword_house_or_other = v129 & stru_5C6E00->uDoublePiMask;
+            }
+            v99 = (char *)&_evt->v31;
+            _5B65B8_npcdata_hiword_house_or_other = v95;
+            dword_5B65BC = v97;
+            v100 = v94 | v132 | v126 | v95 | v97 | v98;
+            dword_5B65C0 = v100;
+            if ( *v99 == 48 )
+            {
+              if ( v100 )
+              {
+                pParty->vPosition.x = v135;
+                pParty->vPosition.y = v132;
+                pParty->vPosition.z = v126;
+                pParty->uFallStartY = v126;
+                if ( _5B65B4_npcdata_loword_house_or_other != -1 )
+                  pParty->sRotationY = _5B65B4_npcdata_loword_house_or_other;
+                _5B65B4_npcdata_loword_house_or_other = -1;
+                v120 = 0;
+                v116 = 0;
+                v111 = 0;
+                v110 = 0;
+                v109 = -1;
+                v108 = 0;
+                v107 = 0;
+                pParty->sRotationX = v95;
+                pParty->uFallSpeed = v134;
+                dword_5B65C0 = 0;
+                dword_5B65BC = 0;
+                _5B65B8_npcdata_hiword_house_or_other = 0;
+                _5B65B0_npcdata_rep_or_other = 0;
+                _5B65AC_npcdata_fame_or_other = 0;
+                _5B65A8_npcdata_uflags_or_other = 0;
+                v106 = 232;
+LABEL_280:
+                pAudioPlayer->PlaySound((SoundID)v106, v107, v108, v109, v110, v111, v116, v120);
+              }
+            }
+            else
+            {
+              pGameLoadingUI_ProgressBar->uType = (GUIProgressBar::Type)((_5C3420_pDecoration == 0) + 1);
+              sub_44987B(v99, 0);
+              v133 = 1;
+              if ( pCurrentScreen == 13 )
+              {
+                if ( uGameState == 2 )
+                {
+                  pAudioPlayer->StopChannels(-1, -1);
+                  dword_F8B19C = 0;
+                  while ( sub_4BD8B5() )
+                    ;
+                  pVideoPlayer->Unload();
+                  ptr_507BC0->Release();
+                  ptr_507BC0 = 0;
+                  if ( pMessageQueue_50CBD0->uNumMessages )
+                    pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+                  pCurrentScreen = 0;
+                  viewparams->bRedrawGameUI = 1;
+                  array_5913D8[6] = 0;
+                  pDialogueWindow->Release();
+                  dword_F8B19C = 0;
+                  pDialogueWindow = 0;
+                  pIcons_LOD->_40F9C5();
+                }
+                goto LABEL_302;
+              }
+            }
+            goto LABEL_291;
+          case EVENT_PlaySound:
+            v120 = 0;
+            v116 = 0;
+            v111 = 0;
+            v110 = _evt->v13 + ((_evt->v14 + ((_evt->v15 + ((uint)_evt->v16 << 8)) << 8)) << 8);
+            v109 = _evt->v9 + ((_evt->v10 + ((_evt->v11 + ((uint)_evt->v12 << 8)) << 8)) << 8);
+            v108 = 0;
+            v107 = 0;
+            v106 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            goto LABEL_280;
+          case EVENT_GiveItem:
+            item.Reset();
+            //v101 = &pSomeEVT[v9];
+            v102 = _evt->v7
+                 + ((_evt->v8 + ((_evt->v9 + ((uint)_evt->v10 << 8)) << 8)) << 8);
+            pItemsTable->GenerateItem(_evt->v5, _evt->v6, &item);
+            if ( v102 )
+              item.uItemID = v102;
+            pParty->SetHoldingItem(&item);
+            goto LABEL_291;
+          case EVENT_SpeakInHouse:
+            v103 = _evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8);
+            if ( EnterHouse((enum HOUSE_TYPE)(_evt->v5 + ((_evt->v6 + ((_evt->v7 + ((uint)_evt->v8 << 8)) << 8)) << 8))) )
+            {
+              if ( pRenderer->pRenderD3D && !pRenderer->bWindowMode )
+                pRenderer->_49FD3A();
+              pAudioPlayer->PlaySound((SoundID)0, 0, 0, -1, 0, 0, 0, 0);
+              pAudioPlayer->PlaySound(SOUND_EnteringAHouse, 814, 0, -1, 0, 0, 0, 0);
+              v104 = 187;
+              if ( uCurrentHouse_Animation != 167 )
+                v104 = v103;
+              ptr_507BC0 = GUIWindow::Create(0, 0, 640, 480, WINDOW_HouseInterior, v104, 0);
+              ptr_507BC0->CreateButton(0x3Du, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 1u, 0x31u, "", 0);
+              ptr_507BC0->CreateButton(0xB1u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
+              ptr_507BC0->CreateButton(0x124u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
+              ptr_507BC0->CreateButton(0x197u, 0x1A8u, 0x1Fu, 0, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
+              ptr_507BC0->CreateButton(0, 0, 0, 0, 1, 0, 0xB0u, 0, 9u, "", 0);
+            }
+            goto LABEL_291;
+          default:
+            goto LABEL_291;
+          case EVENT_PressAnyKey:
+            v121 = 33;
+            v105 = v122 + 1;
+            goto LABEL_295;
+          case EVENT_Exit:
+            goto LABEL_301;
+        }
+      }
+      //++v4;
+      //v124 = v4;
+      //if ( v4 >= (signed int)uSomeEVT_NumEvents )
+        //goto LABEL_301;
+    //}
+  }
+}
+
+
+
+//----- (0044861E) --------------------------------------------------------
+void __fastcall sub_44861E_set_texture(unsigned int uFaceCog, const char *pFilename)
+{
+  unsigned int v2; // eax@2
+  unsigned __int16 v3; // di@2
+  signed int v4; // esi@5
+  BLVFace *v5; // eax@7
+  unsigned int *v6; // eax@8
+  char *v7; // eax@9
+  int v8; // edi@16
+  char *v9; // esi@16
+  ODMFace *v10; // eax@17
+  unsigned int *v11; // eax@19
+  unsigned __int16 v12; // [sp+Ch] [bp-18h]@2
+  const char *Str2; // [sp+10h] [bp-14h]@1
+  unsigned int v14; // [sp+14h] [bp-10h]@1
+  signed int v15; // [sp+18h] [bp-Ch]@14
+  int v16; // [sp+1Ch] [bp-8h]@15
+  signed int v17; // [sp+20h] [bp-4h]@4
+  signed int v18; // [sp+20h] [bp-4h]@16
+
+  Str2 = pFilename;
+  v14 = uFaceCog;
+  if ( uFaceCog )
+  {
+    v2 = pBitmaps_LOD->LoadTexture(pFilename);
+    v3 = v2;
+    v12 = v2;
+    if ( v2 != -1 ? (int)&pBitmaps_LOD->pTextures[v2] : 0 )
+    {
+      pBitmaps_LOD->pTextures[v2].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[v2].palette_id1);
+
+      if ( uCurrentlyLoadedLevelType == 1 )
+      {
+        v17 = 1;
+        if ( (signed int)pIndoor->uNumFaceExtras > 1 )
+        {
+          v4 = 1;
+          do
+          {
+            if ( pIndoor->pFaceExtras[v4].sCogNumber == v14 )
+            {
+              v5 = &pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C];
+              if ( BYTE1(v5->uAttributes) & 0x40 )
+              {
+                pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C].uBitmapID = pTextureFrameTable->FindTextureByName(
+                                                                              Str2);
+                v6 = (unsigned int *)&pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C].uBitmapID;
+                if ( *(_WORD *)v6 )
+                {
+                  pTextureFrameTable->LoadAnimationSequenceAndPalettes(*(_WORD *)v6);
+                }
+                else
+                {
+                  *(_WORD *)v6 = v3;
+                  v7 = (char *)&pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C].uAttributes;
+                  v7[1] &= 0xBFu;
+                }
+              }
+              else
+              {
+                v5->uBitmapID = v3;
+              }
+            }
+            ++v17;
+            ++v4;
+          }
+          while ( v17 < (signed int)pIndoor->uNumFaceExtras );
+        }
+        pParty->uFlags |= 2u;
+      }
+      else
+      {
+        v15 = 0;
+        if ( (signed int)pOutdoor->uNumBModels > 0 )
+        {
+          v16 = 0;
+          do
+          {
+            v8 = 0;
+            v9 = (char *)&pOutdoor->pBModels[v16].pVertices;
+            v18 = 0;
+            if ( (signed int)pOutdoor->pBModels[v16].uNumFaces > 0 )
+            {
+              do
+              {
+                v10 = (ODMFace *)(v8 + *((_DWORD *)v9 + 4));
+                if ( v10->sCogNumber == v14 )
+                {
+                  if ( BYTE1(v10->uAttributes) & 0x40 )
+                  {
+                    *(_WORD *)(*((_DWORD *)v9 + 4) + v8 + 272) = pTextureFrameTable->FindTextureByName(
+                                                                   Str2);
+                    v11 = (unsigned int *)(*((_DWORD *)v9 + 4) + v8 + 272);
+                    if ( *(_WORD *)v11 )
+                    {
+                      pTextureFrameTable->LoadAnimationSequenceAndPalettes(*(_WORD *)v11);
+                    }
+                    else
+                    {
+                      *(_WORD *)v11 = v12;
+                      *(_BYTE *)(*((_DWORD *)v9 + 4) + v8 + 29) &= 0xBFu;
+                    }
+                  }
+                  else
+                  {
+                    v10->uTextureID = v12;
+                  }
+                }
+                ++v18;
+                v8 += 308;
+              }
+              while ( v18 < *((_DWORD *)v9 + 2) );
+            }
+            ++v15;
+            ++v16;
+          }
+          while ( v15 < (signed int)pOutdoor->uNumBModels );
+        }
+      }
+      pParty->uFlags |= 2u;
+    }
+  }
+}
+
+
+
+
+//----- (0044882F) --------------------------------------------------------
+void __fastcall SetDecorationSprite(unsigned int uCog, int a2, const char *pFileName)
+{
+  signed int v3; // ebp@1
+  char *v4; // esi@2
+  unsigned __int16 v5; // ax@6
+  unsigned int v6; // [sp+4h] [bp-8h]@1
+  int v7; // [sp+8h] [bp-4h]@1
+
+  v3 = 0;
+  v7 = a2;
+  v6 = uCog;
+  if ( (signed int)uNumLevelDecorations > 0 )
+  {
+    v4 = (char *)&pLevelDecorations[0].field_2;
+    do
+    {
+      if ( *((_WORD *)v4 + 9) == v6 )
+      {
+        if ( pFileName && _strcmpi(pFileName, "0") )
+        {
+          v5 = pDecorationList->GetDecorIdByName(pFileName);
+          *((_WORD *)v4 - 1) = v5;
+          pDecorationList->InitializeDecorationSprite((signed __int16)v5);
+        }
+        if ( v7 )
+          *v4 &= 0xDFu;
+        else
+          *v4 |= 0x20u;
+        pParty->uFlags |= 2u;
+      }
+      ++v3;
+      v4 += 32;
+    }
+    while ( v3 < (signed int)uNumLevelDecorations );
+  }
+}
+
+
+//----- (004488B6) --------------------------------------------------------
+unsigned __int16 DecorationList::GetDecorIdByName(const char *pName)
+{
+  DecorationList *v2; // esi@1
+  signed int uID; // edi@2
+  signed int v4; // ebx@3
+  unsigned __int16 result; // ax@6
+
+  v2 = this;
+  if ( pName && (uID = 1, (signed int)this->uNumDecorations > 1) )
+  {
+    v4 = 1;
+    while ( _strcmpi(pName, v2->pDecorations[v4].pName) )
+    {
+      ++uID;
+      ++v4;
+      if ( uID >= (signed int)v2->uNumDecorations )
+        goto LABEL_6;
+    }
+    result = uID;
+  }
+  else
+  {
+LABEL_6:
+    result = 0;
+  }
+  return result;
+}
+
+
+//----- (0044892E) --------------------------------------------------------
+void __fastcall sub_44892E_set_faces_bit(int sCogNumber, int bit, int on)
+{
+  signed int v3; // esi@2
+  signed int v4; // ecx@4
+  char *v5; // eax@6
+  int v6; // edi@13
+  char *v7; // esi@13
+  signed int v8; // ecx@13
+  ODMFace *v9; // eax@14
+  int v10; // [sp+0h] [bp-Ch]@1
+  signed int v11; // [sp+4h] [bp-8h]@11
+  int v12; // [sp+8h] [bp-4h]@12
+
+  v10 = sCogNumber;
+  if ( sCogNumber )
+  {
+    v3 = 1;
+    if ( uCurrentlyLoadedLevelType == 1 )
+    {
+      if ( (signed int)pIndoor->uNumFaceExtras > 1 )
+      {
+        v4 = 1;
+        do
+        {
+          if ( pIndoor->pFaceExtras[v4].sCogNumber == v10 )
+          {
+            v5 = (char *)&pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C].uAttributes;
+            if ( on )
+              *(_DWORD *)v5 |= bit;
+            else
+              *(_DWORD *)v5 &= ~bit;
+          }
+          ++v3;
+          ++v4;
+        }
+        while ( v3 < (signed int)pIndoor->uNumFaceExtras );
+      }
+      pParty->uFlags |= 2u;
+    }
+    else
+    {
+      v11 = 0;
+      if ( (signed int)pOutdoor->uNumBModels > 0 )
+      {
+        v12 = 0;
+        do
+        {
+          v6 = 0;
+          v7 = (char *)&pOutdoor->pBModels[v12].pVertices;
+          v8 = 0;
+          if ( (signed int)pOutdoor->pBModels[v12].uNumFaces > 0 )
+          {
+            do
+            {
+              v9 = (ODMFace *)(v6 + *((_DWORD *)v7 + 4));
+              if ( v9->sCogNumber == v10 )
+              {
+                if ( on )
+                  v9->uAttributes |= bit;
+                else
+                  v9->uAttributes &= ~bit;
+              }
+              ++v8;
+              v6 += 308;
+            }
+            while ( v8 < *((_DWORD *)v7 + 2) );
+          }
+          ++v11;
+          ++v12;
+        }
+        while ( v11 < (signed int)pOutdoor->uNumBModels );
+      }
+    }
+    pParty->uFlags |= 2u;
+  }
+}
+
+
+//----- (00448A17) --------------------------------------------------------
+void Chest::ToggleFlag(unsigned int uChestID, unsigned __int16 uFlag, unsigned int bToggle)
+{
+  unsigned __int16 *pFlags; // eax@3
+
+  if ( (uChestID & 0x80000000u) == 0 && (signed int)uChestID <= 19 )
+  {
+    pFlags = &pChests[uChestID].uFlags;
+    if ( bToggle )
+      *pFlags |= uFlag;
+    else
+      *pFlags &= ~uFlag;
+  }
+}
+
+//----- (00448A40) --------------------------------------------------------
+void Actor::ToggleFlag(signed int uActorID, unsigned int uFlag, int bToggle)
+{
+  if ( uActorID >= 0 && uActorID <= (signed int)(uNumActors - 1) )
+  {
+    if ( bToggle )
+    {
+      pActors[uActorID].uAttributes |= uFlag;
+    }
+    else
+    {
+      if ( uFlag == 0x10000 )
+      {
+        if (pActors[uActorID].uAIState == Disabled )
+          pActors[uActorID].uAIState = Standing;
+      }
+      pActors[uActorID].uAttributes &= ~uFlag;
+    }
+  }
+}
+
+//----- (00448A98) --------------------------------------------------------
+void __fastcall ToggleActorGroupFlag(unsigned int uGroupID, unsigned int uFlag, unsigned int bToggle)
+{
+  unsigned int v3; // ebx@1
+  unsigned int v4; // ebp@1
+  signed int v5; // edi@1
+  char *v6; // esi@4
+  size_t v7; // ecx@10
+  char *v8; // eax@11
+  unsigned __int16 v9; // dx@14
+
+  v4 = uGroupID;
+  v5 = Standing;
+  v3 = uFlag;
+  if ( uGroupID )
+  {
+    if ( bToggle )
+    {
+      if ( (signed int)uNumActors > Standing )
+      {
+        v6 = (char *)&pActors[0].uAttributes;
+        do
+        {
+          if ( *((_DWORD *)v6 + 168) == v4 )
+          {
+            *(_DWORD *)v6 |= v3;
+            if ( v3 == 0x10000 )
+            {
+              *((_WORD *)v6 + 70) = Disabled;
+              ((Actor *)(v6 - 36))->UpdateAnimation();
+            }
+          }
+          ++v5;
+          v6 += 836;
+        }
+        while ( v5 < (signed int)uNumActors );
+      }
+    }
+    else
+    {
+      v7 = uNumActors;
+      if ( (signed int)uNumActors > Standing )
+      {
+        v8 = (char *)&pActors[0].uAIState;
+        do
+        {
+          if ( *((_DWORD *)v8 + 133) == v4 )
+          {
+            if ( v3 == 0x10000 )
+            {
+              v9 = *(_WORD *)v8;
+              if ( *(_WORD *)v8 != Dead )
+              {
+                if ( v9 != 4 && v9 != 11 )
+                  *(_WORD *)v8 = Standing;
+              }
+            }
+            *((_DWORD *)v8 - 35) &= ~v3;
+          }
+          v8 += 836;
+          --v7;
+        }
+        while ( v7 );
+      }
+    }
+  }
+}
+
+
+//----- (00448B45) --------------------------------------------------------
+void __thiscall GameUI_StatusBar_UpdateTimedString(unsigned int bForceHide)
+{
+  if ( bForceHide || GameUI_StatusBar_TimedStringTimeLeft && GetTickCount() >= GameUI_StatusBar_TimedStringTimeLeft )
+    GameUI_StatusBar_TimedStringTimeLeft = 0;
+}
+
+//----- (00448B67) --------------------------------------------------------
+void __thiscall OnTimer(int a1)
+{
+  int v1; // ebp@1
+  unsigned int v2; // ebx@4
+  unsigned int v3; // edi@4
+  char *v4; // esi@6
+  __int16 v5; // ax@8
+  int v6; // ecx@10
+  unsigned int v7; // ebp@12
+  int v8; // eax@16
+  int v9; // eax@19
+  unsigned __int64 v10; // qax@20
+  int v11; // ecx@24
+  int v12; // [sp+Ch] [bp-10h]@5
+  unsigned int v13; // [sp+10h] [bp-Ch]@4
+
+  v1 = 0;
+  if ( !pEventTimer->bPaused )
+  {
+    if ( a1 )
+      dword_5773C0 = 0;
+    v3 = HIDWORD(pParty->uTimePlayed);
+    v2 = LODWORD(pParty->uTimePlayed);
+    v13 = (signed __int64)(pParty->uTimePlayed - _5773B8_event_timer) / 128;
+    if ( v13 )
+    {
+      _5773B8_event_timer = pParty->uTimePlayed;
+      v12 = 0;
+      if ( dword_5B65C8 > 0 )
+      {
+        v4 = (char *)&array_5B5928[0].field_C;
+        while ( 1 )
+        {
+          v5 = *(short *)v4;
+          if ( *(short *)v4 != (short)v1 )
+            break;
+          v7 = *((int *)v4 - 2);
+          if ( v7 <= v3 && (v7 < v3 || *((int *)v4 - 3) <= v2) )
+          {
+            if ( *((short *)v4 + 2) )
+            {
+              v8 = 29030400;
+            }
+            else
+            {
+              if ( *((short *)v4 + 3) )
+              {
+                v8 = 2419200;
+              }
+              else
+              {
+                v9 = -(*((short *)v4 + 4) != 0);
+                v8 = (v9 & 0x7E900) + 86400;
+              }
+            }
+            v10 = __PAIR__(v7, *((int *)v4 - 3)) + (signed __int64)((double)((signed __int64)v8 << 7) * 0.033333335);
+            *((int *)v4 - 3) = v10;
+            *((int *)v4 - 2) = HIDWORD(v10);
+            if ( HIDWORD(v10) <= v3 && (HIDWORD(v10) < v3 || *((int *)v4 - 3) < v2) )
+            {
+              *((int *)v4 - 3) = v2;
+              *((int *)v4 - 2) = v3;
+            }
+            v11 = *((short *)v4 - 2);
+            dword_597F18 = *((short *)v4 - 1);
+            EventProcessor(v11, 0, 1);
+            dword_597F18 = 0;
+LABEL_25:
+            v3 = HIDWORD(pParty->uTimePlayed);
+            v2 = LODWORD(pParty->uTimePlayed);
+          }
+LABEL_26:
+          ++v12;
+          v4 += 32;
+          if ( v12 >= dword_5B65C8 )
+            return;
+          v1 = 0;
+        }
+        if ( v13 < v5 )
+        {
+          *(short *)v4 = v5 - v13;
+          goto LABEL_26;
+        }
+        v6 = *((short *)v4 - 2);
+        *(short *)v4 = *((short *)v4 + 1);
+        dword_597F18 = *((short *)v4 - 1);
+        EventProcessor(v6, 0, 1);
+        dword_597F18 = v1;
+        goto LABEL_25;
+      }
+    }
+  }
+}
+
+//----- (00481D77) --------------------------------------------------------
+void _outdoor_project(RenderVertexSoft *v)
+{
+  double v1; // st7@1
+  double v2; // st7@1
+
+  v1 = 1.0 / (v->vWorldViewPosition.x + 0.0000001);
+  v->flt_20 = v1;
+  v2 = v1 * (double)pOutdoorCamera->int_fov_rad;
+  v->vWorldViewProjX = (double)pViewport->uScreenCenterX - v2 * v->vWorldViewPosition.y;
+  v->vWorldViewProjY = (double)pViewport->uScreenCenterY - v2 * v->vWorldViewPosition.z;
+}
+
+
+//----- (00448CF4) --------------------------------------------------------
+void __fastcall sub_448CF4_spawn_monsters(__int16 typeindex, __int16 level, int count, int x, int y, int z, int group, unsigned int uUniqueName)
+{
+  __int16 v8; // di@1
+  __int16 v9; // si@1
+  unsigned int v10; // eax@1
+  size_t v11; // ebx@2
+  signed int v12; // esi@2
+  char *v13;//Actor_uYawAngle_cr *v13; // ebx@3
+  AIDirection a3; // [sp+Ch] [bp-50h]@2
+  AIDirection v15; // [sp+28h] [bp-34h]@2
+  //SpawnPointMM7 v16; // [sp+44h] [bp-18h]@1
+
+  v8 = typeindex;
+  v9 = level;
+
+  SpawnPointMM7 v16; // [sp+44h] [bp-18h]@1
+  //SpawnPointMM7::SpawnPointMM7(&v16);
+
+  v16.vPosition.x = x;
+  v16.vPosition.y = y;
+  v16.vPosition.z = z;
+  v16.uGroup = group;
+  v16.uRadius = 32;
+  v16.uKind = 3;
+  v16.uIndex = v8 + 2 * v9 + v9;
+  v10 = pMapStats->GetMapInfo(pCurrentMapName);
+  if ( v10 )
+  {
+    v11 = uNumActors;
+    SpawnEncounter((MapInfo *)&pMapStats->pInfos[v10], &v16, 0, count, 0);
+    memcpy(&v15, Actor::GetDirectionInfo(8 * v11 | AI_OBJECT_ACTOR, 4u, &a3, 1), sizeof(v15));
+    v12 = v11;
+    if ( (signed int)v11 < (signed int)uNumActors )
+    {
+      v13 = (char *)&pActors[v11].uYawAngle;
+      do
+      {
+        ((Actor *)((char *)v13 - 154))->PrepareSprites(0);
+        ++v12;
+        *(short *)v13/*->uYawAngle*/ = LOWORD(v15.uYawAngle);
+        *(int *)(v13+666)/*->dword_000334_unique_name*/ = uUniqueName;
+        ++v13;
+      }
+      while ( v12 < (signed int)uNumActors );
+    }
+  }
+}
+
+
+//----- (00448DF8) --------------------------------------------------------
+void __fastcall sub_448DF8_cast_spell(int spellnum, int rank, int level, int fromx, int fromy, int fromz, int tox, int toy, int toz)
+{
+  int v9; // esi@1
+  double v10; // st7@4
+  double v11; // st6@4
+  double v12; // st5@4
+  double v13; // st7@6
+  int v14; // ST44_4@7
+  signed int v15; // ebx@9
+  signed int v16; // edx@15
+  char *v17; // ecx@16
+  unsigned __int16 v18; // ax@20
+  char *v19; // ecx@31
+  int v20; // edx@35
+  signed int v21; // edx@37
+  char *v22; // ecx@38
+  unsigned __int16 v23; // ax@41
+  int i; // esi@42
+  signed int v25; // edx@55
+  char *v26; // ecx@56
+  unsigned __int16 v27; // ax@59
+  int j; // esi@60
+  signed int v29; // edx@66
+  char *v30; // ecx@67
+  unsigned __int16 v31; // ax@70
+  char *v32; // eax@80
+  unsigned __int16 v33; // si@85
+  int v34; // eax@96
+  int v35; // eax@97
+  unsigned __int64 v36; // qax@99
+  SpellBuff *v37; // ecx@99
+  int v38; // esi@103
+  signed __int64 v39; // qax@105
+  int v40; // ebx@108
+  int v41; // ebx@109
+  int v42; // esi@111
+  int v43; // ebx@111
+  int v44; // eax@117
+  unsigned __int16 v45; // si@137
+  unsigned __int16 v46; // [sp-8h] [bp-BCh]@99
+  int v47; // [sp-4h] [bp-B8h]@35
+  unsigned __int16 v48; // [sp-4h] [bp-B8h]@99
+  int v49; // [sp+0h] [bp-B4h]@35
+  int v50; // [sp+0h] [bp-B4h]@99
+  int v51; // [sp+4h] [bp-B0h]@35
+  unsigned __int8 v52; // [sp+4h] [bp-B0h]@99
+  float v53; // [sp+14h] [bp-A0h]@4
+  float v54; // [sp+18h] [bp-9Ch]@4
+  int v55; // [sp+28h] [bp-8Ch]@7
+  unsigned int yaw; // [sp+30h] [bp-84h]@7
+  int pitch; // [sp+34h] [bp-80h]@7
+  //LayingItem a1; // [sp+38h] [bp-7Ch]@12
+  int v59; // [sp+A8h] [bp-Ch]@1
+  int v60; // [sp+ACh] [bp-8h]@1
+  int spellnum_; // [sp+B0h] [bp-4h]@1
+  signed int levela; // [sp+BCh] [bp+8h]@80
+  int a6_4; // [sp+C8h] [bp+14h]@117
+  float a7a; // [sp+CCh] [bp+18h]@6
+  signed int a7b; // [sp+CCh] [bp+18h]@12
+  int a7c; // [sp+CCh] [bp+18h]@29
+  int a7d; // [sp+CCh] [bp+18h]@55
+  float a8a; // [sp+D0h] [bp+1Ch]@6
+  int a8b; // [sp+D0h] [bp+1Ch]@37
+  int a8c; // [sp+D0h] [bp+1Ch]@55
+  float toza; // [sp+D4h] [bp+20h]@6
+
+  v9 = 0;
+  v59 = rank + 1;
+  spellnum_ = spellnum;
+  v60 = 0;
+  if ( tox || toy || toz )
+  {
+    v10 = (double)tox - (double)fromx;
+    v53 = v10;
+    v11 = (double)toy - (double)fromy;
+    v54 = v11;
+    v12 = (double)toz;
+  }
+  else
+  {
+    v10 = (double)pParty->vPosition.x - (double)fromx;
+    v53 = v10;
+    v11 = (double)pParty->vPosition.y - (double)fromy;
+    v54 = v11;
+    v12 = (double)(pParty->vPosition.z + pParty->sEyelevel);
+  }
+  a7a = v12 - (double)fromz;
+  toza = v11 * v11;
+  a8a = v10 * v10;
+  v13 = sqrt(a7a * a7a + a8a + toza);
+  if ( v13 <= 1.0 )
+  {
+    LOBYTE(v55) = 1;
+    yaw = 0;
+    pitch = 0;
+  }
+  else
+  {
+    v55 = (signed __int64)v13;
+    v14 = (signed __int64)sqrt(a8a + toza);
+    yaw = stru_5C6E00->Atan2((signed __int64)v53, (signed __int64)v54);
+    pitch = stru_5C6E00->Atan2(v14, (signed __int64)a7a);
+  }
+  v15 = v59;
+  if ( v59 <= 0 || v59 > 4 )
+    v15 = 1;
+  a7b = v15;
+
+  LayingItem a1; // [sp+38h] [bp-7Ch]@12
+  //LayingItem::LayingItem(&a1);
+
+  a1.uItemType = stru_4E3ACC[spellnum_].uItemType;
+  if ( spellnum_ > 58 )
+  {
+    if ( spellnum_ == 69 )
+      goto LABEL_117;
+    if ( spellnum_ != 83 )
+      return;
+    v40 = v15 - 2;
+    if ( v40 )
+    {
+      v41 = v40 - 1;
+      if ( !v41 )
+      {
+        v42 = 14400 * level;
+        v43 = 4 * level + 10;
+        goto LABEL_114;
+      }
+      if ( v41 == 1 )
+      {
+        v42 = 18000 * level;
+        v43 = 5 * level + 10;
+        goto LABEL_114;
+      }
+    }
+    v42 = 10800 * level;
+    v43 = 3 * level + 10;
+LABEL_114:
+    pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 0);
+    pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 1u);
+    pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 2u);
+    pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 3u);
+    v52 = 0;
+    v50 = 0;
+    v48 = v43;
+    v46 = a7b;
+    v39 = (signed __int64)((double)(v42 << 7) * 0.033333335);
+    v37 = &pParty->pPartyBuffs[2];
+LABEL_115:
+    v36 = pParty->uTimePlayed + v39;
+LABEL_116:
+    v37->Apply(v36, v46, v48, v50, v52);
+    goto LABEL_139;
+  }
+  if ( spellnum_ != 58 )
+  {
+    switch ( spellnum_ )
+    {
+      case 2:
+      case 6:
+      case 18:
+      case 26:
+      case 29:
+      case 32:
+      case 39:
+      case 41:
+        a1.stru_24.Reset();
+        v16 = 0;
+        a1.field_48 = spellnum_;
+        a1.field_4C = level;
+        a1.field_50 = v15;
+        if ( (signed int)pObjectList->uNumObjects <= 0 )
+          goto LABEL_34;
+        v17 = (char *)&pObjectList->pObjects->uObjectID;
+        while ( (short)a1.uItemType != *(short *)v17 )
+        {
+          ++v16;
+          v17 += 56;
+          if ( v16 >= (signed int)pObjectList->uNumObjects )
+            goto LABEL_34;
+        }
+LABEL_20:
+        v18 = v16;
+        goto LABEL_35;
+      case 24:
+        switch ( v15 )
+        {
+          case 1:
+            v60 = 1;
+            break;
+          case 2:
+            v60 = 3;
+            break;
+          case 3:
+            v60 = 5;
+            break;
+          case 4:
+            v60 = 7;
+            break;
+        }
+        a7c = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
+        if ( v60 != 1 )
+        {
+          a8b = a7c / (v60 - 1);
+          a1.stru_24.Reset();
+          v21 = 0;
+          a1.field_48 = spellnum_;
+          a1.field_4C = level;
+          a1.field_50 = v15;
+          if ( (signed int)pObjectList->uNumObjects <= 0 )
+          {
+LABEL_41:
+            v23 = 0;
+          }
+          else
+          {
+            v22 = (char *)&pObjectList->pObjects->uObjectID;
+            while ( (short)a1.uItemType != *(short *)v22 )
+            {
+              ++v21;
+              v22 += 56;
+              if ( v21 >= (signed int)pObjectList->uNumObjects )
+                goto LABEL_41;
+            }
+            v23 = v21;
+          }
+          a1.uObjectDescID = v23;
+          *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
+          a1.vPosition.x = fromx;
+          a1.uAttributes = 16;
+          a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
+          a1.field_60_distance_related_prolly_lod = v55;
+          a1.uSpriteFrameID = 0;
+          a1.field_58 = 8002;
+          a1.field_5C = 4;
+          a1.uSoundID = 0;
+          for ( i = a7c / -2; i <= a7c / 2; i += a8b )
+          {
+            a1.uFacing = i + yaw;
+            a1.Create(
+              (signed __int16)(i + (short)yaw),
+              pitch,
+              pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+              0);
+          }
+          goto LABEL_139;
+        }
+        a1.stru_24.Reset();
+        v16 = 0;
+        a1.field_48 = spellnum_;
+        a1.field_4C = level;
+        a1.field_50 = v15;
+        if ( (signed int)pObjectList->uNumObjects <= 0 )
+          goto LABEL_34;
+        v19 = (char *)&pObjectList->pObjects->uObjectID;
+        do
+        {
+          if ( (short)a1.uItemType == *(short *)v19 )
+            goto LABEL_20;
+          ++v16;
+          v19 += 56;
+        }
+        while ( v16 < (signed int)pObjectList->uNumObjects );
+LABEL_34:
+        v18 = 0;
+LABEL_35:
+        a1.uObjectDescID = v18;
+        *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
+        a1.vPosition.x = fromx;
+        a1.uAttributes = 16;
+        a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
+        a1.field_60_distance_related_prolly_lod = v55;
+        v20 = yaw;
+        a1.uSpriteFrameID = 0;
+        a1.field_58 = 8002;
+        a1.field_5C = 0;
+        a1.uFacing = yaw;
+        a1.uSoundID = 0;
+        v51 = 0;
+        v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
+        v47 = pitch;
+        goto LABEL_36;
+      case 15:
+        switch ( v15 )
+        {
+          case 1:
+            v60 = 3;
+            break;
+          case 2:
+            v60 = 5;
+            break;
+          case 3:
+            v60 = 7;
+            break;
+          case 4:
+            v60 = 9;
+            break;
+        }
+        a7d = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
+        a8c = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360 / (v60 - 1);
+        a1.stru_24.Reset();
+        v25 = 0;
+        a1.field_48 = spellnum_;
+        a1.field_4C = level;
+        a1.field_50 = v15;
+        if ( (signed int)pObjectList->uNumObjects <= 0 )
+          goto LABEL_59;
+        v26 = (char *)&pObjectList->pObjects->uObjectID;
+        while ( (short)a1.uItemType != *(short *)v26 )
+        {
+          ++v25;
+          v26 += 56;
+          if ( v25 >= (signed int)pObjectList->uNumObjects )
+          {
+LABEL_59:
+            v27 = 0;
+            goto LABEL_60;
+          }
+        }
+        v27 = v25;
+LABEL_60:
+        a1.uObjectDescID = v27;
+        *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
+        a1.vPosition.x = fromx;
+        a1.uAttributes = 16;
+        a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
+        a1.field_60_distance_related_prolly_lod = v55;
+        a1.uSpriteFrameID = 0;
+        a1.field_58 = 8002;
+        a1.field_5C = 4;
+        a1.uSoundID = 0;
+        for ( j = a7d / -2; j <= a7d / 2; j += a8c )
+        {
+          a1.uFacing = j + yaw;
+          a1.Create(
+            (signed __int16)(j + (short)yaw),
+            pitch,
+            pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+            0);
+        }
+        goto LABEL_139;
+      case 43:
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+          return;
+        a1.stru_24.Reset();
+        v29 = 0;
+        a1.field_48 = spellnum_;
+        a1.field_4C = level;
+        a1.field_50 = v15;
+        if ( (signed int)pObjectList->uNumObjects <= 0 )
+          goto LABEL_70;
+        v30 = (char *)&pObjectList->pObjects->uObjectID;
+        break;
+      case 5:
+        if ( v15 > 0 )
+        {
+          if ( v15 <= 2 )
+          {
+            v9 = 60 * (level + 60);
+          }
+          else
+          {
+            if ( v15 == 3 )
+            {
+              v9 = 180 * (level + 20);
+            }
+            else
+            {
+              if ( v15 == 4 )
+                v9 = 240 * (level + 15);
+            }
+          }
+        }
+        levela = 1;
+        v32 = (char *)&pParty->pPlayers[0].pConditions[1];
+        do
+        {
+          if ( *(_QWORD *)v32 )
+            levela = 0;
+          v32 += 6972;
+        }
+        while ( (signed int)v32 < (signed int)&pParty->pHirelings[0].uFlags );
+        if ( !levela )
+          return;
+        pParty->pPartyBuffs[8].Apply(
+          pParty->uTimePlayed + (signed int)(signed __int64)((double)(v9 << 7) * 0.033333335),
+          v15,
+          0,
+          0,
+          0);
+        v33 = spellnum_;
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 0);
+        pGame->pStru6Instance->SetPlayerBuffAnim(v33, 1u);
+        pGame->pStru6Instance->SetPlayerBuffAnim(v33, 2u);
+        pGame->pStru6Instance->SetPlayerBuffAnim(v33, 3u);
+        goto LABEL_138;
+      case 17:
+      case 38:
+      case 51:
+        switch ( v15 )
+        {
+          case 1:
+          case 2:
+            v9 = 300 * (level + 12);
+            break;
+          case 3:
+            v9 = 900 * (level + 4);
+            break;
+          case 4:
+            v9 = 3600 * (level + 1);
+            break;
+        }
+        switch ( spellnum_ )
+        {
+          case 17:
+            v60 = 0;
+            level = 14;
+            break;
+          case 38:
+            v35 = level + 5;
+            level = 15;
+            v60 = v35;
+            break;
+          case 51:
+            v34 = level + 5;
+            level = 9;
+            v60 = v34;
+            break;
+        }
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 0);
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 1u);
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 2u);
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 3u);
+        v52 = 0;
+        v50 = 0;
+        v48 = v60;
+        v46 = v15;
+        v36 = pParty->uTimePlayed + (signed int)(signed __int64)((double)(v9 << 7) * 0.033333335);
+        v37 = &pParty->pPartyBuffs[level];
+        goto LABEL_116;
+      case 8:
+        if ( v15 == 2 || v15 == 3 || v15 != 4 )
+          v38 = 60 * level;
+        else
+          v38 = 600 * level;
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 0);
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 1u);
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 2u);
+        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 3u);
+        v52 = 0;
+        v50 = 0;
+        v48 = level;
+        v46 = v15;
+        v39 = (signed __int64)((double)(v38 << 7) * 0.033333335);
+        v37 = &pParty->pPartyBuffs[10];
+        goto LABEL_115;
+      case 3:
+      case 14:
+      case 25:
+      case 36:
+        goto LABEL_117;
+      default:
+        return;
+    }
+    while ( (short)a1.uItemType != *(short *)v30 )
+    {
+      ++v29;
+      v30 += 56;
+      if ( v29 >= (signed int)pObjectList->uNumObjects )
+      {
+LABEL_70:
+        v31 = 0;
+        goto LABEL_71;
+      }
+    }
+    v31 = v29;
+LABEL_71:
+    a1.uObjectDescID = v31;
+    *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
+    a1.vPosition.x = fromx;
+    a1.uAttributes = 16;
+    a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
+    a1.field_60_distance_related_prolly_lod = v55;
+    a1.uSpriteFrameID = 0;
+    a1.field_58 = 8002;
+    a1.field_5C = 4;
+    a1.uSoundID = 0;
+    v51 = 0;
+    v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
+    v20 = yaw;
+    v47 = (signed int)stru_5C6E00->uIntegerHalfPi / 2;
+LABEL_36:
+    a1.Create(v20, v47, v49, v51);
+    goto LABEL_139;
+  }
+LABEL_117:
+  v44 = level;
+  a6_4 = 3600 * level;
+  if ( v15 == 1 )
+  {
+LABEL_124:
+    v60 = v44;
+    goto LABEL_125;
+  }
+  if ( v15 == 2 )
+  {
+    v44 = 2 * level;
+    goto LABEL_124;
+  }
+  if ( v15 == 3 )
+  {
+    v44 = 3 * level;
+    goto LABEL_124;
+  }
+  if ( v15 == 4 )
+  {
+    v44 = 4 * level;
+    goto LABEL_124;
+  }
+LABEL_125:
+  switch ( spellnum_ )
+  {
+    case 3:
+      level = 6;
+      break;
+    case 14:
+      level = 0;
+      break;
+    case 25:
+      level = 17;
+      break;
+    case 36:
+      level = 4;
+      break;
+    case 58:
+      level = 12;
+      break;
+    case 69:
+      level = 1;
+      break;
+  }
+  v45 = spellnum_;
+  pGame->pStru6Instance->SetPlayerBuffAnim(spellnum_, 0);
+  pGame->pStru6Instance->SetPlayerBuffAnim(v45, 1u);
+  pGame->pStru6Instance->SetPlayerBuffAnim(v45, 2u);
+  pGame->pStru6Instance->SetPlayerBuffAnim(v45, 3u);
+  pParty->pPartyBuffs[level].Apply(
+    pParty->uTimePlayed + (signed int)(signed __int64)((double)a6_4 * 4.2666669),
+    v15,
+    v60,
+    0,
+    0);
+  levela = 1;
+LABEL_138:
+  if ( levela )
+LABEL_139:
+    pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[spellnum_], 0, 0, fromx, fromy, 0, 0, 0);
+}
+// 4EE088: using guessed type __int16 word_4EE088_sound_ids[];
+
+//----- (0044987B) --------------------------------------------------------
+char *__fastcall sub_44987B(const char *pMapName, unsigned int uStartingPointType)
+{
+  const char *v2; // edi@1
+  unsigned int v3; // ebx@1
+  char *result; // eax@3
+
+  v2 = pMapName;
+  v3 = uStartingPointType;
+  pAudioPlayer->StopChannels(-1, -1);
+  pGameLoadingUI_ProgressBar->_443484((GUIProgressBar::Type)0);
+  if ( _strcmpi(pCurrentMapName, v2) )
+    SaveGame(1, 0);
+  uGameState = 2;
+  result = strcpy(pCurrentMapName, v2);
+  uLevel_StartingPointType = v3;
+  return result;
+}
+// 6BE35C: using guessed type int uLevel_StartingPointType;
+
+//----- (004498D5) --------------------------------------------------------
+void __thiscall TeleportToStartingPoint(unsigned int uPointType)
+{
+  unsigned int v1; // ecx@2
+  int v2; // ecx@3
+  int v3; // ecx@4
+  unsigned __int16 v4; // ax@11
+  signed int v5; // ecx@12
+  LevelDecoration *v6; // edx@13
+  signed int v7; // ecx@17
+  int v8; // eax@17
+  int v9; // ecx@17
+  const char *v10; // [sp-4h] [bp-84h]@6
+  char pName[128]; // [sp+8h] [bp-78h]@11
+
+  if ( uPointType )
+  {
+    v1 = uPointType - 1;
+    if ( v1 )
+    {
+      v2 = v1 - 1;
+      if ( v2 )
+      {
+        v3 = v2 - 1;
+        if ( v3 )
+        {
+          if ( v3 != 1 )
+            return;
+          v10 = "West Start";
+        }
+        else
+        {
+          v10 = "East Start";
+        }
+      }
+      else
+      {
+        v10 = "South Start";
+      }
+    }
+    else
+    {
+      v10 = "North Start";
+    }
+  }
+  else
+  {
+    v10 = "Party Start";
+  }
+  strcpy(pName, v10);
+  v4 = pDecorationList->GetDecorIdByName(pName);
+  if ( v4 )
+  {
+    v5 = 0;
+    if ( (signed int)uNumLevelDecorations > 0 )
+    {
+      v6 = pLevelDecorations;
+      while ( v6->uDecorationDescID != (signed __int16)v4 )
+      {
+        ++v5;
+        ++v6;
+        if ( v5 >= (signed int)uNumLevelDecorations )
+          goto LABEL_20;
+      }
+      v7 = v5;
+      pParty->vPosition.x = pLevelDecorations[v7].vPosition.x;
+      pParty->vPosition.y = pLevelDecorations[v7].vPosition.y;
+      pParty->vPosition.z = pLevelDecorations[v7].vPosition.z;
+      pParty->uFallStartY = pParty->vPosition.z;
+      v8 = (signed int)(stru_5C6E00->uIntegerHalfPi * pLevelDecorations[v7].field_1A) / 90;
+      v9 = pLevelDecorations[v7].field_10_y_rot;
+      pParty->sRotationY = v8;
+      if ( v9 )
+        pParty->sRotationY = v9;
+      pParty->sRotationX = 0;
+      pParty->uFallSpeed = 0;
+    }
+LABEL_20:
+    if ( dword_5B65C0 )
+    {
+      if ( _5B65A8_npcdata_uflags_or_other )
+        pParty->vPosition.x = _5B65A8_npcdata_uflags_or_other;
+      if ( _5B65AC_npcdata_fame_or_other )
+        pParty->vPosition.y = _5B65AC_npcdata_fame_or_other;
+      if ( _5B65B0_npcdata_rep_or_other )
+      {
+        pParty->vPosition.z = _5B65B0_npcdata_rep_or_other;
+        pParty->uFallStartY = _5B65B0_npcdata_rep_or_other;
+      }
+      if ( _5B65B4_npcdata_loword_house_or_other )
+        pParty->sRotationY = _5B65B4_npcdata_loword_house_or_other;
+      if ( _5B65B8_npcdata_hiword_house_or_other )
+        pParty->sRotationX = _5B65B8_npcdata_hiword_house_or_other;
+      if ( dword_5B65BC )
+        pParty->uFallSpeed = dword_5B65BC;
+    }
+    _5B65B4_npcdata_loword_house_or_other = -1;
+    dword_5B65C0 = 0;
+    dword_5B65BC = 0;
+    _5B65B8_npcdata_hiword_house_or_other = 0;
+    _5B65B0_npcdata_rep_or_other = 0;
+    _5B65AC_npcdata_fame_or_other = 0;
+    _5B65A8_npcdata_uflags_or_other = 0;
+  }
+}
+// 5B65A8: using guessed type int _5B65A8_npcdata_uflags_or_other;
+// 5B65AC: using guessed type int _5B65AC_npcdata_fame_or_other;
+// 5B65B0: using guessed type int _5B65B0_npcdata_rep_or_other;
+// 5B65B4: using guessed type int _5B65B4_npcdata_loword_house_or_other;
+// 5B65B8: using guessed type int _5B65B8_npcdata_hiword_house_or_other;
+// 5B65BC: using guessed type int dword_5B65BC;
+// 5B65C0: using guessed type int dword_5B65C0;
+
+//----- (00449A49) --------------------------------------------------------
+__int16 __fastcall sub_449A49_door_switch_animation(unsigned int uDoorID, int a2)
+{
+  int v2; // eax@1
+  int v3; // ebx@1
+  signed int v4; // esi@2
+  int v5; // edx@2
+  BLVDoor *v6; // ecx@8
+  unsigned int v7; // edx@18
+  signed int v8; // esi@19
+  int v9; // eax@19
+  char Args; // [sp+Ch] [bp-78h]@6
+
+  LOWORD(v2) = LOWORD(pIndoor->pDoors);
+  v3 = a2;
+  if ( !pIndoor->pDoors )
+    return v2;
+  v4 = 0;
+  v5 = (int)&pIndoor->pDoors->uDoorID;
+  do
+  {
+    if ( *(int *)v5 == uDoorID )
+      break;
+    ++v4;
+    v5 += 80;
+  }
+  while ( v4 < 200 );
+  if ( v4 >= 200 )
+  {
+    sprintf(&Args, "Unable to find Door ID: %i!", uDoorID);
+    Abortf(&Args);
+  }
+  v6 = &pIndoor->pDoors[v4];
+  if ( v3 == 2 )
+  {
+    LOWORD(v2) = v6->uState;
+    if ( (short)v2 == 3 || (short)v2 == 1 )
+      return v2;
+    if ( (short)v2 )
+      goto LABEL_14;
+  }
+  else
+  {
+    if ( !v3 )
+    {
+LABEL_14:
+      LOWORD(v2) = v6->uState;
+      if ( (short)v2 && (short)v2 != 3 )
+      {
+        v6->uState = BLVDoor::Closing;
+        if ( (short)v2 == 2 )
+        {
+LABEL_17:
+          v6->uTimeSinceTriggered = 0;
+          return v2;
+        }
+        v7 = v6->uTimeSinceTriggered;
+        v2 = 15360;
+        if ( v7 != 15360 )
+        {
+          v8 = v6->uOpenSpeed;
+          v9 = v6->uCloseSpeed;
+LABEL_26:
+          v2 = (v6->uMoveLength << 7) / v8 - ((signed int)(v7 * v9) / 128 << 7) / v8;
+          goto LABEL_27;
+        }
+        goto LABEL_27;
+      }
+      return v2;
+    }
+    if ( v3 != 1 )
+      return v2;
+  }
+  LOWORD(v2) = v6->uState;
+  if ( (short)v2 != 2 && (short)v2 != 1 )
+  {
+    v6->uState = BLVDoor::Opening;
+    if ( !(short)v2 )
+      goto LABEL_17;
+    v7 = v6->uTimeSinceTriggered;
+    v2 = 15360;
+    if ( v7 != 15360 )
+    {
+      v8 = v6->uCloseSpeed;
+      v9 = v6->uOpenSpeed;
+      goto LABEL_26;
+    }
+LABEL_27:
+    v6->uTimeSinceTriggered = v2;
+  }
+  return v2;
+}
+
+//----- (00449B57) --------------------------------------------------------
+unsigned int __fastcall _449B57_test_bit(unsigned __int8 *a1, __int16 a2)
+{
+  return a1[(a2 - 1) >> 3] & (0x80u >> (a2 - 1) % 8);
+}
+
+//----- (00449B7E) --------------------------------------------------------
+unsigned char *_449B7E_toggle_bit(unsigned char *pArray, __int16 a2, unsigned __int16 bToggle)
+{
+  signed int v3; // esi@1
+  unsigned char *result; // eax@1
+  unsigned int v5; // edx@1
+
+  v3 = a2 - 1;
+  result = &pArray[v3 / 8];
+  v5 = 0x80 >> v3 % 8;
+  if ( bToggle )
+    *result |= v5;
+  else
+    *result &= ~(unsigned char)v5;
+  return result;
+}
+
+
+//----- (0044A56A) --------------------------------------------------------
+void __cdecl sub_44A56A()
+{
+  signed int v0; // edi@1
+  NPCData *v1; // esi@2
+
+  pParty->field_70A = 0;
+  v0 = 0;
+  if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+  {
+    v1 = pNPCStats->pNewNPCData;
+    do
+    {
+      if ( v1->uFlags & 0x80 && (!pParty->pHirelings[0].pName || strcmp(v1->pName, pParty->pHirelings[0].pName)) )
+      {
+        if ( !pParty->pHirelings[1].pName || strcmp(v1->pName, pParty->pHirelings[1].pName) )
+          ++pParty->field_70A;
+      }
+      ++v0;
+      ++v1;
+    }
+    while ( v0 < (signed int)pNPCStats->uNumNewNPCs );
+  }
+}
+
+
+//----- (0044C175) --------------------------------------------------------
+void __fastcall ShowStatusBarString(const char *pString, unsigned int uNumSeconds)
+{
+  unsigned int v2; // esi@1
+  int i; // eax@1
+
+  v2 = uNumSeconds;
+  strcpy(GameUI_StatusBar_TimedString, pString);
+  GameUI_StatusBar_TimedStringTimeLeft = 1000 * v2 + GetTickCount();
+  for ( i = pFontLucida->GetLineWidth(GameUI_StatusBar_TimedString);
+        i > 450;
+        i = pFontLucida->GetLineWidth(GameUI_StatusBar_TimedString) )
+    byte_5C3427[strlen(GameUI_StatusBar_TimedString)] = 0;
+}
+
+//----- (0044C1D0) --------------------------------------------------------
+void __cdecl ShowNothingHereStatus()
+{
+  if ( !GameUI_StatusBar_TimedStringTimeLeft )
+    ShowStatusBarString(pGlobalTXT_LocalizationStrings[521], 2u);// Nothing here
+}
+
+
+//----- (0044C28B) --------------------------------------------------------
+signed int __cdecl const_2()
+{
+  return 2;
+}
+
+//----- (0044C28F) --------------------------------------------------------
+bool __cdecl sub_44C28F_open_nwc_dungeon()
+{
+  bool result; // eax@1
+
+  result = _strcmpi("nwc.blv", pCurrentMapName);
+  if ( result )
+  {
+    _5B65A8_npcdata_uflags_or_other = 0;
+    _5B65AC_npcdata_fame_or_other = 0;
+    _5B65B0_npcdata_rep_or_other = 0;
+    _5B65B4_npcdata_loword_house_or_other = 0;
+    _5B65B8_npcdata_hiword_house_or_other = 0;
+    dword_5B65BC = 0;
+    dword_5B65C0 = 0;
+    pGameLoadingUI_ProgressBar->uType = GUIProgressBar::TYPE_Fullscreen;
+    sub_44987B("nwc.blv", 0);
+    pCurrentScreen = 0;
+    result = 1;
+  }
+  return result;
+}
+
+
+//----- (0044C2F4) --------------------------------------------------------
+int LevelDecoration::IsInteractive()
+{
+  signed int v1; // eax@1
+
+  v1 = this->uDecorationDescID;
+  if ( v1 > 34 )
+  {
+    if ( v1 == 184 || v1 == 187 || v1 == 190 || v1 > 205 && v1 <= 221 )
+      return 1;
+  }
+  else
+  {
+    if ( v1 == 34 || v1 >= 4 && (v1 <= 6 || v1 == 11 || v1 > 12 && (v1 <= 14 || v1 == 24)) )
+      return 1;
+  }
+  return 0;
+}
+
+//----- (0044C362) --------------------------------------------------------
+void Vec3_int_::Normalize_float()
+{
+  Vec3_int_ *v1; // esi@1
+  double v2; // st6@1
+  float v3; // ST20_4@1
+  double v4; // st5@1
+  float v5; // ST18_4@1
+  double v6; // st4@1
+  float v7; // ST14_4@1
+  float v8; // ST24_4@1
+  float v9; // ST20_4@1
+  double v10; // ST0C_8@1
+  float v11; // ST18_4@1
+  double v12; // ST0C_8@1
+  float v13; // ST14_4@1
+  double v14; // ST0C_8@1
+
+  v1 = this;
+  v2 = (double)this->x * 0.000015258789;
+  v3 = v2;
+  v4 = (double)this->y * 0.000015258789;
+  v5 = v4;
+  v6 = (double)this->z * 0.000015258789;
+  v7 = v6;
+  v8 = 1.0 / sqrt(v6 * v6 + v4 * v4 + v2 * v2);
+  v9 = v8 * v3 * 65536.0;
+  v10 = v9 + 6.7553994e15;
+  v1->x = LODWORD(v10);
+  v11 = v8 * v5 * 65536.0;
+  v12 = v11 + 6.7553994e15;
+  v1->y = LODWORD(v12);
+  v13 = v8 * v7 * 65536.0;
+  v14 = v13 + 6.7553994e15;
+  v1->z = LODWORD(v14);
+}
+
+//----- (0044C448) --------------------------------------------------------
+GUIFont *LoadFont(const char *pFontFile, const char *pFontPalette, ...)
+{
+  GUIFont *result; // eax@1
+  const char *v3; // edi@1
+  const char **v4; // ebx@2
+  unsigned int v5; // eax@3
+  unsigned __int16 **v6; // ecx@6
+  GUIFont *v7; // [sp+4h] [bp-Ch]@1
+  int v8; // [sp+8h] [bp-8h]@1
+  unsigned __int16 **v9; // [sp+Ch] [bp-4h]@2
+
+  result = (GUIFont *)pIcons_LOD->LoadRaw(pFontFile, 0);
+  v3 = pFontPalette;
+  v8 = 0;
+  v7 = result;
+  if ( pFontPalette )
+  {
+    v4 = &pFontPalette;
+    v9 = result->pFontPalettes;
+    do
+    {
+      v5 = pIcons_LOD->LoadTexture(v3, TEXTURE_16BIT_PALETTE);
+      if ( v5 == -1 )
+      {
+        sprintf(pTmpBuf, "Unable to open %s", v3);
+        Abortf(pTmpBuf);
+      }
+      ++v4;
+      v6 = v9;
+      v3 = *v4;
+      ++v8;
+      ++v9;
+      *v6 = (v5 != -1 ? pIcons_LOD->pTextures[v5].pPalette16 : 0);
+    }
+    while ( v3 );
+    result = v7;
+  }
+  result->field_8 = v8;
+  return result;
+}
+
+
+
+
+//----- (0044C768) --------------------------------------------------------
+char *__fastcall FitTextInAWindow(const char *pInString, GUIFont *pFont, GUIWindow *pWindow, unsigned int uX, int a5)
+{
+  const char *v5; // edi@1
+  GUIFont *v6; // esi@1
+  unsigned int v8; // eax@3
+  int v9; // edi@3
+  unsigned __int8 v10; // cl@4
+  int v11; // edx@10
+  GUICharMetric *v12; // ecx@10
+  int v13; // edx@11
+  int v14; // edx@12
+  int v15; // edx@13
+  unsigned int v16; // esi@15
+  unsigned int v17; // edx@15
+  unsigned int v18; // ecx@15
+  int v19; // ebx@16
+  unsigned __int8 v20; // zf@16
+  char v21; // sf@16
+  unsigned __int8 v22; // of@16
+  int v23; // edi@16
+  unsigned __int8 v24; // dl@17
+  int v25; // edi@39
+  int v26; // eax@42
+  std::string v27; // [sp-18h] [bp-40h]@2
+  const char *v28; // [sp-8h] [bp-30h]@2
+  int v29; // [sp-4h] [bp-2Ch]@2
+  const char *v30; // [sp+Ch] [bp-1Ch]@1
+  char Str[3]; // [sp+10h] [bp-18h]@42
+  char v32; // [sp+13h] [bp-15h]@42
+  size_t v33; // [sp+14h] [bp-14h]@3
+  unsigned int v34; // [sp+18h] [bp-10h]@3
+  GUIFont *v35; // [sp+1Ch] [bp-Ch]@1
+  int v36; // [sp+20h] [bp-8h]@3
+  int v37; // [sp+24h] [bp-4h]@3
+
+  v5 = pInString;
+  v6 = pFont;
+  v30 = pInString;
+  v35 = pFont;
+  if ( !pInString )
+  {
+    MessageBoxW(nullptr, L"Invalid string passed !", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Font.cpp:445", 0);
+    return 0;
+  }
+  v33 = strlen(pInString);
+  strcpy(pTmpBuf3, v5);
+  v8 = uX;
+  v9 = 0;
+  v36 = 0;
+  v34 = uX;
+  v37 = 0;
+  if ( (signed int)v33 > 0 )
+  {
+    while ( 1 )
+    {
+      v10 = pTmpBuf3[v9];
+      if ((v10 < v6->cFirstChar || v10 > v6->cLastChar)
+          && v10 != '\f' && v10 != '\r' && v10 != '\t' && v10 != '\n' )
+        goto LABEL_34;
+      v11 = v10 - 9;
+      v12 = &v6->pMetrics[v10];
+      if ( !v11 )
+      {
+        strncpy(Str, &pTmpBuf3[v9 + 1], 3u);
+        v32 = 0;
+        v26 = atoi(Str);
+        v8 = uX + v26;
+        v25 = v9 + 3;
+        v34 = v8;
+        goto LABEL_43;
+      }
+      v13 = v11 - 1;
+      if ( !v13 )
+        break;
+      v14 = v13 - 2;
+      if ( !v14 )
+      {
+        v25 = v9 + 5;
+LABEL_43:
+        v37 = v25;
+        goto LABEL_34;
+      }
+      v15 = v14 - 1;
+      if ( v15 )
+      {
+        if ( v15 != 19 )
+        {
+          v16 = v12->uRightSpacing;
+          v17 = v12->uWidth;
+          v18 = v12->uLeftSpacing;
+          if ( v8 + v16 + v18 + v17 < pWindow->uFrameWidth )
+          {
+            if ( v37 > v36 )
+              v8 += v18;
+            v8 += v17;
+            if ( v37 < (signed int)v33 )
+              v8 += v16;
+            v6 = v35;
+          }
+          else
+          {
+            v19 = v36;
+            v8 = v34;
+            v22 = v36 > v37;
+            v20 = v36 == v37;
+            v21 = v36 - v37 < 0;
+            v6 = v35;
+            pTmpBuf3[v36] = 10;
+            v23 = v19;
+            if ( (unsigned __int8)(v21 ^ v22) | v20 )
+            {
+              do
+              {
+                v24 = pTmpBuf3[v23];
+                if ( v24 >= v6->cFirstChar && v24 <= v6->cLastChar || v24 == 12 || v24 == 13 || v24 == 9 || v24 == 10 )
+                {
+                  if ( v23 > v19 )
+                    v8 += v6->pMetrics[v24].uLeftSpacing;
+                  v8 += *((int *)&v6->cFirstChar + 3 * v24 + 9);
+                  if ( v23 < v37 )
+                    v8 += v6->pMetrics[v24].uRightSpacing;
+                }
+                ++v23;
+              }
+              while ( v23 <= v37 );
+            }
+          }
+          goto LABEL_34;
+        }
+        v8 += v12->uWidth;
+        goto LABEL_41;
+      }
+      if ( !a5 )
+        return (char *)v30;
+LABEL_34:
+      v9 = v37++ + 1;
+      if ( v37 >= (signed int)v33 )
+        return pTmpBuf3;
+    }
+    v8 = v34;
+LABEL_41:
+    v36 = v9;
+    goto LABEL_34;
+  }
+  return pTmpBuf3;
+}
+//----- (00401000) --------------------------------------------------------
+void __stdcall mm7__vector_constructor(void *a1, int objSize, int numObjs, int (__thiscall *constructor)(int))
+{
+  void *v4; // esi@2
+  int v5; // edi@2
+
+  if ( numObjs - 1 >= 0 )
+  {
+    v4 = a1;
+    v5 = numObjs;
+    do
+    {
+      constructor((int)v4);
+      v4 = (char *)v4 + objSize;
+      --v5;
+    }
+    while ( v5 );
+  }
+}
+
+
+//----- (004014E6) --------------------------------------------------------
+int __cdecl ODM_4014E6_AI()
+{
+  int v0; // esi@2
+  int v1; // eax@4
+  int v2; // ebx@4
+  unsigned int v3; // ecx@4
+  int v4; // edx@5
+  int v5; // edx@7
+  unsigned int v6; // edx@9
+  unsigned int v7; // ST20_4@10
+  int v8; // eax@10
+  int v9; // edi@10
+  int v10; // ebx@14
+  char v11; // zf@16
+  int v12; // eax@22
+  int result; // eax@24
+  int v14; // edx@25
+  int v15; // ecx@25
+  int v16; // ebx@26
+  unsigned int *v17; // ecx@27
+  unsigned int v18; // esi@27
+  int i; // edx@33
+  char *v20; // ecx@34
+  int v21; // [sp+Ch] [bp-14h]@4
+  int v22; // [sp+10h] [bp-10h]@4
+  int v23; // [sp+14h] [bp-Ch]@10
+  int v24; // [sp+14h] [bp-Ch]@29
+  signed int v25; // [sp+18h] [bp-8h]@1
+  signed int v26; // [sp+18h] [bp-8h]@25
+  int v27; // [sp+1Ch] [bp-4h]@1
+
+  pParty->uFlags &= 0xFFFFFFCFu;
+  v27 = 0;
+  v25 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v0 = (int)&pActors[0].uAttributes;
+    do
+    {
+      *(char *)(v0 + 1) &= 0xFBu;
+      if ( ! ((Actor *)(v0 - offsetof(Actor, uAttributes)))->CanAct() )
+        goto LABEL_37;
+      v22 = abs(pParty->vPosition.z - *(short *)(v0 + 110));
+      v21 = abs(pParty->vPosition.y - *(short *)(v0 + 108));
+      v1 = abs(pParty->vPosition.x - *(short *)(v0 + 106));
+      v2 = v21;
+      v3 = v22;
+      if ( v1 < v21 )
+      {
+        v4 = v1;
+        v1 = v21;
+        v2 = v4;
+      }
+      if ( v1 < v22 )
+      {
+        v5 = v1;
+        v1 = v22;
+        v3 = v5;
+      }
+      if ( v2 < (signed int)v3 )
+      {
+        v6 = v3;
+        v3 = v2;
+        v2 = v6;
+      }
+      v7 = ((unsigned int)(11 * v2) >> 5) + (v3 >> 2) + v1;
+      v8 = *(short *)(v0 + 100);
+      v9 = v7 - v8;
+      v23 = v7 - v8;
+      if ( v23 < 0 )
+      {
+        v9 = 0;
+        v23 = 0;
+      }
+      if ( v9 < 5632 )
+      {
+        v10 = *(int *)v0 & 0xFEFFFFFF;
+        *(int *)v0 = v10;
+        if ( v10 & 0x80000 || ((Actor *)(v0 - offsetof(Actor, uAttributes)))->GetActorsRelation(0) )
+        {
+          v11 = (pParty->uFlags & 0x10) == 0;
+          *(int *)v0 = v10 | 0x1000000;
+          if ( v11 && (double)v23 < 307.2 )
+            pParty->uFlags |= 0x10u;
+          if ( !(pParty->uFlags & 0x20) && v9 < 5120 )
+            pParty->uFlags |= 0x20u;
+        }
+        *(char *)(v0 + 1) |= 0x40u;
+        v12 = v27++;
+        ai_array_4F75E0[v12] = v9;
+        ai_array_4F7DB0_actor_ids[v12] = v25;
+      }
+      else
+      {
+LABEL_37:
+        *(char *)(v0 + 1) &= 0xBFu;
+      }
+      ++v25;
+      v0 += 836;
+    }
+    while ( v25 < (signed int)uNumActors );
+  }
+  result = v27;
+  if ( v27 > 0 )
+  {
+    v14 = 0;
+    v15 = 1;
+    v26 = 1;
+    do
+    {
+      while ( 1 )
+      {
+        v24 = v15;
+        if ( v15 >= result )
+          break;
+        v16 = ai_array_4F75E0[v14];
+        if ( v16 > ai_array_4F75E0[v15] )
+        {
+          v17 = &ai_array_4F7DB0_actor_ids[v15];
+          v18 = ai_array_4F7DB0_actor_ids[v14];
+          ai_array_4F7DB0_actor_ids[v14] = *v17;
+          *v17 = v18;
+          v15 = v24;
+          ai_array_4F75E0[v14] = ai_array_4F75E0[v24];
+          ai_array_4F75E0[v24] = v16;
+        }
+        result = v27;
+        ++v15;
+      }
+      ++v14;
+      v15 = v26 + 1;
+      v26 = v15;
+    }
+    while ( v15 - 1 < result );
+  }
+  ai_arrays_size = result;
+  if ( result > 30 )
+  {
+    result = 30;
+    ai_arrays_size = 30;
+  }
+  for ( i = 0; i < result; ++i )
+  {
+    v20 = (char *)&pActors[ai_array_4F7DB0_actor_ids[i]].uAttributes;
+    v20[1] |= 4u;
+  }
+  return result;
+}
+// 4F75D8: using guessed type int ai_arrays_size;
+
+//----- (004016FA) --------------------------------------------------------
+int __cdecl BLV_4016FA_AI()
+{
+  char *v0; // esi@2
+  int v1; // eax@4
+  int v2; // ebx@4
+  unsigned int v3; // ecx@4
+  int v4; // edx@5
+  int v5; // edx@7
+  unsigned int v6; // edx@9
+  unsigned int v7; // ST24_4@10
+  int v8; // eax@10
+  int v9; // edi@10
+  int v10; // ebx@14
+  char v11; // zf@16
+  int v12; // eax@22
+  int v13; // edx@24
+  int v14; // ecx@25
+  int v15; // ebx@26
+  unsigned int *v16; // ecx@27
+  unsigned int v17; // esi@27
+  int v18; // ecx@31
+  signed int v19; // edi@31
+  Actor *v20; // esi@32
+  bool v21; // eax@33
+  int v22; // eax@34
+  signed int v23; // ebx@36
+  char *v24; // esi@37
+  signed int v25; // eax@40
+  int v26; // eax@43
+  int v27; // ebx@45
+  int j; // edi@45
+  unsigned int v29; // eax@46
+  int v30; // eax@48
+  int v31; // ecx@51
+  int v32; // eax@51
+  signed int v33; // eax@53
+  __int64 v34; // qax@55
+  char *v35; // ecx@56
+  int v37; // [sp+Ch] [bp-18h]@1
+  int v38; // [sp+10h] [bp-14h]@4
+  int v39; // [sp+14h] [bp-10h]@4
+  int v40; // [sp+18h] [bp-Ch]@10
+  int v41; // [sp+18h] [bp-Ch]@29
+  int i; // [sp+18h] [bp-Ch]@31
+  signed int v43; // [sp+1Ch] [bp-8h]@1
+  signed int v44; // [sp+1Ch] [bp-8h]@25
+  int v45; // [sp+20h] [bp-4h]@1
+
+  pParty->uFlags &= 0xFFFFFFCFu;
+  v37 = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
+  v45 = 0;
+  v43 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v0 = (char *)&pActors[0].uAttributes;
+    do
+    {
+      v0[1] &= 0xFBu;
+      if ( ! ((Actor *)(v0 - 36))->CanAct() )
+        goto LABEL_60;
+      v39 = abs(pParty->vPosition.z - *((short *)v0 + 55));
+      v38 = abs(pParty->vPosition.y - *((short *)v0 + 54));
+      v1 = abs(pParty->vPosition.x - *((short *)v0 + 53));
+      v2 = v38;
+      v3 = v39;
+      if ( v1 < v38 )
+      {
+        v4 = v1;
+        v1 = v38;
+        v2 = v4;
+      }
+      if ( v1 < v39 )
+      {
+        v5 = v1;
+        v1 = v39;
+        v3 = v5;
+      }
+      if ( v2 < (signed int)v3 )
+      {
+        v6 = v3;
+        v3 = v2;
+        v2 = v6;
+      }
+      v7 = ((unsigned int)(11 * v2) >> 5) + (v3 >> 2) + v1;
+      v8 = *((short *)v0 + 50);
+      v9 = v7 - v8;
+      v40 = v7 - v8;
+      if ( v40 < 0 )
+      {
+        v9 = 0;
+        v40 = 0;
+      }
+      if ( v9 < 10240 )
+      {
+        v10 = *(int *)v0 & 0xFEFFFFFF;
+        *(int *)v0 = v10;
+        if ( v10 & 0x80000 || ((Actor *)(v0 - 36))->GetActorsRelation(0) )
+        {
+          v11 = (pParty->uFlags & 0x10) == 0;
+          *(int *)v0 = v10 | 0x1000000;
+          if ( v11 && (double)v40 < 307.2 )
+            pParty->uFlags |= 0x10u;
+          if ( !(pParty->uFlags & 0x20) && v9 < 5120 )
+            pParty->uFlags |= 0x20u;
+        }
+        v12 = v45++;
+        ai_array_4F75E0[v12] = v9;
+        ai_array_4F7DB0_actor_ids[v12] = v43;
+      }
+      else
+      {
+LABEL_60:
+        v0[1] &= 0xBFu;
+      }
+      ++v43;
+      v0 += 836;
+    }
+    while ( v43 < (signed int)uNumActors );
+  }
+  v13 = 0;
+  if ( v45 > 0 )
+  {
+    v14 = 1;
+    v44 = 1;
+    do
+    {
+      while ( 1 )
+      {
+        v41 = v14;
+        if ( v14 >= v45 )
+          break;
+        v15 = ai_array_4F75E0[v13];
+        if ( v15 > ai_array_4F75E0[v14] )
+        {
+          v16 = &ai_array_4F7DB0_actor_ids[v14];
+          v17 = ai_array_4F7DB0_actor_ids[v13];
+          ai_array_4F7DB0_actor_ids[v13] = *v16;
+          *v16 = v17;
+          v14 = v41;
+          ai_array_4F75E0[v13] = ai_array_4F75E0[v41];
+          ai_array_4F75E0[v41] = v15;
+        }
+        ++v14;
+      }
+      ++v13;
+      v14 = v44 + 1;
+      v44 = v14;
+    }
+    while ( v14 - 1 < v45 );
+  }
+  v18 = 0;
+  v19 = 0;
+  for ( i = 0; v18 < v45; i = v18 )
+  {
+    v20 = &pActors[ai_array_4F7DB0_actor_ids[v18]];
+    if ( v20->uAttributes & 0x8000
+      || (v21 = sub_4070EF_prolly_collide_objects(8 * ai_array_4F7DB0_actor_ids[v18] | 3, 4u), v18 = i, v21) )
+    {
+      v22 = ai_array_4F7DB0_actor_ids[v18];
+      v20->uAttributes |= 0x8000u;
+      ai_array_4F6638_actor_ids[v19] = v22;
+      ai_array_4F5E68[v19++] = ai_array_4F75E0[v18];
+      if ( v19 >= 30 )
+        break;
+    }
+    ++v18;
+  }
+  v23 = 0;
+  ai_arrays_size = v19;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v24 = (char *)&pActors[0].uAttributes;
+    do
+    {
+      if ( ((Actor *)(v24 - 36))->CanAct() && *((short *)v24 + 61) == v37 )
+      {
+        v25 = 0;
+        if ( v19 <= 0 )
+        {
+LABEL_43:
+          v26 = ai_arrays_size;
+          v24[1] |= 0x40u;
+          ++ai_arrays_size;
+          ai_array_4F6638_actor_ids[v26] = v23;
+        }
+        else
+        {
+          while ( ai_array_4F6638_actor_ids[v25] != v23 )
+          {
+            ++v25;
+            if ( v25 >= v19 )
+              goto LABEL_43;
+          }
+        }
+      }
+      ++v23;
+      v24 += 836;
+    }
+    while ( v23 < (signed int)uNumActors );
+  }
+  v27 = ai_arrays_size;
+  for ( j = 0; j < v45; ++j )
+  {
+    v29 = ai_array_4F7DB0_actor_ids[j];
+    if ( pActors[v29].uAttributes & 0xC000 && pActors[v29].CanAct() )
+    {
+      v30 = 0;
+      if ( v27 <= 0 )
+      {
+LABEL_51:
+        v31 = ai_arrays_size;
+        v32 = ai_array_4F7DB0_actor_ids[j];
+        ++ai_arrays_size;
+        ai_array_4F6638_actor_ids[v31] = v32;
+      }
+      else
+      {
+        while ( ai_array_4F6638_actor_ids[v30] != ai_array_4F7DB0_actor_ids[j] )
+        {
+          ++v30;
+          if ( v30 >= v27 )
+            goto LABEL_51;
+        }
+      }
+    }
+  }
+  v33 = ai_arrays_size;
+  if ( ai_arrays_size > 30 )
+  {
+    v33 = 30;
+    ai_arrays_size = 30;
+  }
+  memcpy(ai_array_4F7DB0_actor_ids, ai_array_4F6638_actor_ids, 4 * v33);
+  memcpy(ai_array_4F75E0, ai_array_4F5E68, 4 * ai_arrays_size);
+  v34 = (unsigned int)ai_arrays_size;
+  if ( ai_arrays_size > 0 )
+  {
+    do
+    {
+      v35 = (char *)&pActors[ai_array_4F7DB0_actor_ids[HIDWORD(v34)]].uAttributes;
+      v35[1] |= 4u;
+      ++HIDWORD(v34);
+    }
+    while ( SHIDWORD(v34) < (signed int)v34 );
+  }
+  return v34;
+}
+// 4F75D8: using guessed type int ai_arrays_size;
+
+//----- (00401A91) --------------------------------------------------------
+void __cdecl sub_401A91_AI()
+{
+  unsigned int v0; // esi@4
+  int v1; // eax@7
+  int v2; // ecx@7
+  int v3; // eax@7
+  signed int v4; // edi@10
+  char *v5; // esi@12
+  signed int v6; // eax@14
+  __int16 v7; // cx@14
+  Player **v8; // esi@20
+  Player *pPlayer; // ecx@21
+  Actor *pActor; // esi@34
+  __int16 v11; // ax@34
+  unsigned int v12; // eax@47
+  signed int v13; // edi@47
+  SpellBuff *v14; // ebx@47
+  unsigned int v15; // edi@67
+  char *v16; // eax@67
+  unsigned int v17; // edx@67
+  unsigned int v18; // ecx@67
+  unsigned __int16 v19; // ax@72
+  int *v20; // esi@80
+  Actor *v21; // ebx@80
+  unsigned __int16 v22; // ax@86
+  signed int v23; // eax@94
+  unsigned int v24; // eax@102
+  signed int v25; // edi@102
+  SpellBuff *v26; // esi@102
+  unsigned int v27; // ecx@123
+  unsigned int v28; // eax@123
+  unsigned int v29; // eax@127
+  AIDirection *v30; // eax@129
+  unsigned __int16 v31; // ax@132
+  unsigned int v32; // esi@142
+  int v33; // eax@144
+  int v34; // eax@147
+  char v35; // al@150
+  unsigned int v36; // edi@152
+  signed int v37; // eax@154
+  unsigned __int8 v38; // sf@158
+  unsigned __int8 v39; // of@158
+  signed int v40; // edx@166
+  unsigned int v41; // ecx@166
+  double v42; // st7@176
+  double v43; // st6@176
+  bool v44; // eax@189
+  bool v45; // eax@192
+  unsigned __int8 v46; // cl@197
+  double v47; // st7@206
+  double v48; // st7@207
+  char v49; // zf@208
+  char v50; // zf@214
+  signed int v51; // edx@219
+  unsigned int v52; // ecx@219
+  __int16 v53; // fps@224
+  unsigned __int8 v54; // c0@224
+  unsigned __int8 v55; // c3@224
+  double v56; // st7@226
+  AIDirection *v57; // eax@246
+  double v58; // st7@246
+  signed int v59; // [sp-18h] [bp-C8h]@213
+  int v60; // [sp-14h] [bp-C4h]@144
+  int v61; // [sp-14h] [bp-C4h]@168
+  AIDirection *v62; // [sp-14h] [bp-C4h]@213
+  signed int v63; // [sp-14h] [bp-C4h]@216
+  unsigned int v64; // [sp-14h] [bp-C4h]@219
+  unsigned int v65; // [sp-10h] [bp-C0h]@144
+  char v66; // [sp-10h] [bp-C0h]@147
+  AIDirection *v67; // [sp-10h] [bp-C0h]@167
+  int v68; // [sp-10h] [bp-C0h]@168
+  AIDirection *v69; // [sp-10h] [bp-C0h]@206
+  int v70; // [sp-10h] [bp-C0h]@213
+  AIDirection *v71; // [sp-10h] [bp-C0h]@216
+  AIDirection v72; // [sp+0h] [bp-B0h]@246
+  AIDirection a3; // [sp+1Ch] [bp-94h]@129
+  AIDirection v74; // [sp+38h] [bp-78h]@246
+  AIDirection v75; // [sp+54h] [bp-5Ch]@129
+  int v76; // [sp+70h] [bp-40h]@83
+  signed int a1; // [sp+74h] [bp-3Ch]@129
+  int v78; // [sp+78h] [bp-38h]@79
+  AIDirection pDir; // [sp+7Ch] [bp-34h]@129
+  float v80; // [sp+98h] [bp-18h]@33
+  int v81; // [sp+9Ch] [bp-14h]@100
+  int v82; // [sp+A0h] [bp-10h]@45
+  unsigned int uActorID; // [sp+A4h] [bp-Ch]@32
+  unsigned int v84; // [sp+A8h] [bp-8h]@11
+  signed int a2; // [sp+ACh] [bp-4h]@83
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    ODM_4014E6_AI();
+  else
+    BLV_4016FA_AI();
+  v0 = 0;
+  if ( uCurrentlyLoadedLevelType != LEVEL_Indoor && pParty->field_1613C > 0 )
+  {
+    if ( pParty->field_1613C > 417 )
+    {
+      pParty->field_1613C = 0;
+    }
+    else
+    {
+      pParty->sRotationY = (stru_5C6E00->uIntegerDoublePi - 1) & (pParty->sRotationY + rand() % 16 - 8);
+      v1 = rand();
+      v2 = 128;
+      v3 = pParty->sRotationX + v1 % 16 - 8;
+      pParty->sRotationX = v3;
+      if ( v3 > 128 || (v2 = -128, v3 < -128) )
+        pParty->sRotationX = v2;
+      pParty->uFlags |= 2u;
+      pParty->field_1613C -= pMiscTimer->uTimeElapsed;
+      v4 = pParty->field_16140 + 50;
+      if ( pParty->field_1613C <= 0 )
+      {
+        pParty->field_1613C = 0;
+        v84 = 0;
+        if ( (signed int)uNumActors > 0 )
+        {
+          v5 = (char *)&pActors[0].sCurrentHP;
+          do
+          {
+            if ( ((Actor *)(v5 - 40))->CanAct() )
+            {
+              v6 = stru_50C198.CalcMagicalDamageToActor((Actor *)(v5 - 40), 5, v4);
+              v7 = *(short *)v5 - v6;
+              *(short *)v5 = v7;
+              if ( v6 )
+              {
+                if ( v7 >= 0 )
+                {
+                  Actor::_4030AD(v84, 4, 0);
+                }
+                else
+                {
+                  Actor::Die(v84);
+                  if ( *((int *)v5 + 19) )
+                    sub_4269A2_GivePartyExp(pMonsterStats->pInfos[*((short *)v5 + 28)].uExp);
+                }
+              }
+            }
+            ++v84;
+            v5 += 836;
+          }
+          while ( (signed int)v84 < (signed int)uNumActors );
+        }
+        v8 = &pPlayers[1];
+        do
+        {
+          pPlayer = *v8;
+          if ( !(*v8)->pConditions[14] && !pPlayer->pConditions[15] && !pPlayer->pConditions[16] )
+            pPlayer->ReceiveDamage(v4, 5);
+          ++v8;
+        }
+        while ( (signed int)v8 <= (signed int)&pPlayers[4] );
+        v0 = 0;
+      }
+      if ( pTurnEngine->field_1C != v0 )
+        --pTurnEngine->field_1C;
+    }
+  }
+  if ( pParty->bTurnBasedModeOn == 1 )
+  {
+    pTurnEngine->_405E14();
+    return;
+  }
+  uActorID = v0;
+  if ( (signed int)uNumActors > (signed int)v0 )
+  {
+    LODWORD(v80) = (int)(char *)pActors + 176;
+    do
+    {
+      pActor = (Actor *)(LODWORD(v80) - 176);
+      v11 = *(unsigned int *)LODWORD(v80);
+      v49 = *(unsigned int *)LODWORD(v80) == 5;
+      dword_4F6E08[uActorID] = 4;
+      if ( v49 || v11 == 11 || v11 == 19 || *(char *)(LODWORD(v80) - 139) & 4 )
+        goto LABEL_78;
+      if ( !*(short *)(LODWORD(v80) - 136) && v11 != 4 )
+        Actor::Die(uActorID);
+      v84 = *(_QWORD *)(LODWORD(v80) + 84) <= 0i64 ? 0 : 1;
+      v82 = *(_QWORD *)(LODWORD(v80) + 52) <= 0i64 ? 0 : 1;
+      v12 = 0;
+      v13 = 0;
+      v14 = (SpellBuff *)(LODWORD(v80) + 36);
+      do
+      {
+        if ( v13 != 10 )
+        {
+          v14->_4585CA(pParty->uTimePlayed);
+          v12 = 0;
+        }
+        ++v13;
+        ++v14;
+      }
+      while ( v13 < 22 );
+      if ( v84 != v12
+        && SHIDWORD(pActor->pActorBuffs[3].uExpireTime) <= (signed int)v12
+        && (SHIDWORD(pActor->pActorBuffs[3].uExpireTime) < (signed int)v12
+         || LODWORD(pActor->pActorBuffs[3].uExpireTime) <= v12) )
+        pActor->uActorHeight = pMonsterList->pMonsters[pActor->pMonsterInfo.uID - 1].uMonsterHeight;
+      if ( v82 != v12 )
+      {
+        pActor->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+        if ( SHIDWORD(pActor->pActorBuffs[1].uExpireTime) <= (signed int)v12 )
+        {
+          if ( SHIDWORD(pActor->pActorBuffs[1].uExpireTime) < (signed int)v12
+            || LODWORD(pActor->pActorBuffs[1].uExpireTime) <= v12 )
+            pActor->pMonsterInfo.uHostilityType = pMonsterStats->pInfos[pActor->pMonsterInfo.uID].uHostilityType;
+        }
+      }
+      if ( SHIDWORD(pActor->pActorBuffs[5].uExpireTime) > (signed int)v12
+        || SHIDWORD(pActor->pActorBuffs[5].uExpireTime) >= (signed int)v12
+        && LODWORD(pActor->pActorBuffs[5].uExpireTime)
+        || SHIDWORD(pActor->pActorBuffs[6].uExpireTime) > 0
+        || SHIDWORD(pActor->pActorBuffs[6].uExpireTime) >= 0 && LODWORD(pActor->pActorBuffs[6].uExpireTime) )
+        goto LABEL_78;
+      v15 = pMiscTimer->uTimeElapsed;
+      v16 = (char *)&pActor->pMonsterInfo.uRecoveryTime;
+      pActor->uCurrentActionTime += pMiscTimer->uTimeElapsed;
+      v17 = pActor->uCurrentActionTime;
+      v18 = pActor->pMonsterInfo.uRecoveryTime;
+      if ( (signed int)v18 > 0 )
+        *(int *)v16 = v18 - v15;
+      if ( *(int *)v16 < 0 )
+        *(int *)v16 = 0;
+      if ( (signed int)v17 < pActor->uCurrentActionLength )
+        goto LABEL_78;
+      v19 = pActor->uAIState;
+      if ( v19 == Dying )
+      {
+        pActor->uAIState = Dead;
+      }
+      else
+      {
+        if ( v19 != 17 )
+        {
+          Actor::_403F58(uActorID, Dying, 256, 0);
+          goto LABEL_78;
+        }
+        pActor->uAIState = Standing;
+      }
+      pActor->uCurrentActionTime = 0;
+      pActor->uCurrentActionLength = 0;
+      pActor->UpdateAnimation();
+LABEL_78:
+      ++uActorID;
+      LODWORD(v80) += 836;
+    }
+    while ( (signed int)uActorID < (signed int)uNumActors );
+  }
+  v78 = 0;
+  if ( ai_arrays_size > 0 )
+  {
+    while ( 1 )
+    {
+      uActorID = ai_array_4F7DB0_actor_ids[v78];
+      v20 = &dword_4F6E08[uActorID];
+      v21 = &pActors[uActorID];
+      Actor::_401221(uActorID, &dword_4F6E08[uActorID], 1u);
+      if ( v21->pMonsterInfo.uHostilityType && !*v20 )
+        v21->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+      a2 = *v20;
+      v76 = a2 & 7;
+      if ( (a2 & 7) == 3 )
+        v80 = 0.5;
+      else
+        v80 = 1.0;
+      v22 = v21->uAIState;
+      if ( v22 == 4 || v22 == 5 || v22 == 11 || v22 == 19 || v22 == 17 )
+        goto LABEL_254;
+      if ( !v21->sCurrentHP )
+        Actor::Die(uActorID);
+      if ( (signed __int64)v21->pActorBuffs[3].uExpireTime <= 0 )
+      {
+        v84 = 0;
+        v23 = 1;
+      }
+      else
+      {
+        v23 = 1;
+        v84 = 1;
+      }
+      if ( (signed __int64)v21->pActorBuffs[1].uExpireTime <= 0 )
+        v82 = 0;
+      else
+        v82 = v23;
+      if ( (signed __int64)v21->pActorBuffs[2].uExpireTime <= 0 )
+        v81 = 0;
+      else
+        v81 = v23;
+      v24 = 0;
+      v25 = 0;
+      v26 = v21->pActorBuffs;
+      do
+      {
+        if ( v25 != 10 )
+        {
+          v26->_4585CA(pParty->uTimePlayed);
+          v24 = 0;
+        }
+        ++v25;
+        ++v26;
+      }
+      while ( v25 < 22 );
+      if ( v84 != v24
+        && SHIDWORD(v21->pActorBuffs[3].uExpireTime) <= (signed int)v24
+        && (SHIDWORD(v21->pActorBuffs[3].uExpireTime) < (signed int)v24
+         || LODWORD(v21->pActorBuffs[3].uExpireTime) <= v24) )
+        v21->uActorHeight = pMonsterList->pMonsters[v21->pMonsterInfo.uID - 1].uMonsterHeight;
+      if ( v82 != v24 )
+      {
+        v21->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+        if ( SHIDWORD(v21->pActorBuffs[1].uExpireTime) <= (signed int)v24 )
+        {
+          if ( SHIDWORD(v21->pActorBuffs[1].uExpireTime) < (signed int)v24
+            || LODWORD(v21->pActorBuffs[1].uExpireTime) <= v24 )
+            v21->pMonsterInfo.uHostilityType = pMonsterStats->pInfos[v21->pMonsterInfo.uID].uHostilityType;
+        }
+      }
+      if ( v81 != v24
+        && SHIDWORD(v21->pActorBuffs[2].uExpireTime) <= (signed int)v24
+        && (SHIDWORD(v21->pActorBuffs[2].uExpireTime) < (signed int)v24
+         || LODWORD(v21->pActorBuffs[2].uExpireTime) <= v24) )
+      {
+        v21->uAIState = Removed;
+        goto LABEL_254;
+      }
+      if ( v21->pActorBuffs[5].uExpireTime || v21->pActorBuffs[6].uExpireTime )
+        goto LABEL_254;
+      v27 = pMiscTimer->uTimeElapsed;
+      v28 = v21->pMonsterInfo.uRecoveryTime;
+      v21->uCurrentActionTime += pMiscTimer->uTimeElapsed;
+      if ( (signed int)v28 > 0 )
+        v21->pMonsterInfo.uRecoveryTime = v28 - v27;
+      if ( (v21->pMonsterInfo.uRecoveryTime & 0x80000000u) != 0 )
+        v21->pMonsterInfo.uRecoveryTime = 0;
+      v29 = v21->uAttributes;
+      if ( !(v29 & 0x8000) )
+        v21->uAttributes = v29 | 0x8000;
+      a1 = 8 * uActorID | 3;
+      v30 = Actor::GetDirectionInfo(8 * uActorID | 3, a2, &a3, 0);
+      v49 = v21->pMonsterInfo.uHostilityType == 0;
+      memcpy(&v75, v30, sizeof(v75));
+      memcpy(&pDir, &v75, sizeof(pDir));
+      if ( !v49 && (signed int)v21->pMonsterInfo.uRecoveryTime <= 0 )
+      {
+        if ( v80 * 307.2 >= (double)(signed int)v75.uDistance
+          && ((v31 = v21->uAIState, v31 == 6) || !v31 || v31 == 1 || v31 == 9)
+          || v21->pMonsterInfo.uMissleAttack1Type && v21->uAIState == 8 )
+        {
+          v32 = uActorID;
+          goto LABEL_152;
+        }
+      }
+      if ( (signed int)v21->uCurrentActionTime < v21->uCurrentActionLength )
+        goto LABEL_254;
+      if ( v21->uAIState == 2 )
+      {
+        v32 = uActorID;
+        v35 = stru_50C198.special_ability_use_check(v21, uActorID);
+        stru_50FE08.Add(
+          a1,
+          5120,
+          v21->vPosition.x,
+          v21->vPosition.y,
+          v21->vPosition.z + ((signed int)v21->uActorHeight >> 1),
+          v35,
+          1);
+        goto LABEL_152;
+      }
+      if ( v21->uAIState == 3 )
+      {
+        v34 = v21->pMonsterInfo.uMissleAttack1Type;
+        v66 = 0;
+        goto LABEL_149;
+      }
+      if ( v21->uAIState == 12 )
+      {
+        v34 = v21->pMonsterInfo.uMissleAttack2Type;
+        v66 = 1;
+LABEL_149:
+        v32 = uActorID;
+        Actor::_404874(uActorID, &pDir, v34, v66);
+        goto LABEL_152;
+      }
+      v32 = uActorID;
+      if ( v21->uAIState == 13 )
+        break;
+      if ( v21->uAIState == 18 )
+      {
+        v65 = v21->pMonsterInfo.uSpellSkillAndMastery2;
+        v60 = 3;
+        v33 = v21->pMonsterInfo.uSpell2ID;
+LABEL_146:
+        Actor::_404AC7(uActorID, &pDir, v33, v60, v65);
+      }
+LABEL_152:
+      v36 = v75.uDistance;
+      if ( v21->pMonsterInfo.uHostilityType )
+        goto LABEL_165;
+      if ( v76 == 3 )
+      {
+        v36 = v75.uDistance;
+        v37 = (unsigned __int8)*(&byte_5C8D1A[89 * (v21->pMonsterInfo.uID - 1) / 3]
+                               + (pActors[a2 >> 3].pMonsterInfo.uID - 1) / 3);
+      }
+      else
+      {
+        v37 = 4;
+      }
+      if ( v37 == 1 )
+        goto LABEL_257;
+      if ( v37 == 2 )
+      {
+        v39 = __OFSUB__(v36, 1024);
+        v38 = ((v36 - 1024) & 0x80000000u) != 0;
+      }
+      else
+      {
+        if ( v37 == 3 )
+        {
+          v39 = __OFSUB__(v36, 2560);
+          v38 = ((v36 - 2560) & 0x80000000u) != 0;
+        }
+        else
+        {
+          if ( v37 != 4 )
+            goto LABEL_165;
+          v39 = __OFSUB__(v36, 5120);
+          v38 = ((v36 - 5120) & 0x80000000u) != 0;
+        }
+      }
+      if ( v38 ^ v39 )
+LABEL_257:
+      v21->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Long;
+LABEL_165:
+      if ( (signed __int64)v21->pActorBuffs[4].uExpireTime > 0 )
+      {
+        v40 = a2;
+        v41 = v32;
+        if ( (signed int)v36 >= 10240 )
+        {
+          v68 = 0;
+          v61 = 1024;
+          goto LABEL_253;
+        }
+        v67 = &pDir;
+        goto LABEL_182;
+      }
+      if ( v21->pMonsterInfo.uHostilityType != 4 || !a2 )
+        goto LABEL_241;
+      if ( !(v21->uAttributes & 0x020000) || v21->pMonsterInfo.uAIType == 1 )
+      {
+        if ( v21->pMonsterInfo.uAIType == 1 )
+        {
+          v67 = &pDir;
+          if ( v21->pMonsterInfo.uMovementType != 5 )
+            goto LABEL_181;
+          Actor::_403EB6(
+            v32,
+            a2,
+            (signed __int64)((double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333),
+            &pDir);
+        }
+        else
+        {
+          if ( v21->pMonsterInfo.uAIType == 2 )
+          {
+            v84 = v21->sCurrentHP;
+            v42 = (double)(signed int)v84;
+            v43 = (double)(signed int)v21->pMonsterInfo.uHP * 0.2;
+          }
+          else
+          {
+            if ( v21->pMonsterInfo.uAIType != 3 )
+              goto LABEL_185;
+            v84 = v21->sCurrentHP;
+            v42 = (double)(signed int)v84;
+            v43 = (double)(signed int)v21->pMonsterInfo.uHP * 0.1;
+          }
+          if ( v43 > v42 && (signed int)v36 < 10240 )
+          {
+            v67 = &pDir;
+LABEL_181:
+            v40 = a2;
+            v41 = v32;
+LABEL_182:
+            Actor::_402968(v41, v40, 0, v67);
+            goto LABEL_254;
+          }
+        }
+      }
+LABEL_185:
+      v81 = v36 - v21->uActorRadius;
+      if ( v76 == 3 )
+        v81 -= pActors[a2 >> 3].uActorRadius;
+      if ( v81 < 0 )
+        v81 = 0;
+      rand();
+      v44 = (signed int)v21->pMonsterInfo.uRecoveryTime <= 0;
+      v21->uAttributes &= 0xFBFFFF;
+      v82 = 0;
+      v49 = v21->pMonsterInfo.uMovementType == 5;
+      v84 = v44;
+      if ( v49 )
+        v82 = 1;
+      if ( v81 >= 5120 )
+        goto LABEL_241;
+      v45 = stru_50C198.special_ability_use_check(v21, v32);
+      if ( !v45 )
+      {
+        if ( v21->pMonsterInfo.uMissleAttack1Type )
+        {
+          if ( v84 )
+          {
+            Actor::_403476(v32, a2, &pDir);
+            goto LABEL_254;
+          }
+LABEL_223:
+          if ( v82 )
+            goto LABEL_217;
+          v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
+          //UNDEF(v53);
+          v69 = &pDir;
+          if ( !(v54 | v55) )
+            goto LABEL_219;
+LABEL_225:
+          Actor::_402AD7(v32, a2, v32, (signed __int64)v47, v69);
+          goto LABEL_254;
+        }
+        v56 = v80 * 307.2;
+        if ( (double)v81 >= v56 )
+        {
+          if ( v81 >= 1024 )
+          {
+            if ( v82 )
+              goto LABEL_217;
+            v71 = &pDir;
+            v63 = 0;
+            goto LABEL_240;
+          }
+          goto LABEL_235;
+        }
+        goto LABEL_227;
+      }
+      if ( v45 != 1 )
+      {
+        if ( v45 > 1 && v45 <= 3 )
+        {
+          if ( v45 == 2 )
+            v46 = v21->pMonsterInfo.uSpell1ID;
+          else
+            v46 = v21->pMonsterInfo.uSpell2ID;
+          if ( v46 )
+          {
+            if ( v84 )
+            {
+              if ( v45 == 2 )
+                Actor::_403854(v32, a2, &pDir);
+              else
+                Actor::_403A60(v32, a2, &pDir);
+              goto LABEL_254;
+            }
+            if ( v80 * 307.2 > (double)v81 || v82 )
+            {
+LABEL_217:
+              v69 = &pDir;
+LABEL_218:
+              v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
+LABEL_219:
+              v51 = a2;
+              v64 = (signed __int64)v47;
+              v52 = v32;
+LABEL_247:
+              Actor::_403EB6(v52, v51, v64, v69);
+              goto LABEL_254;
+            }
+            v69 = &pDir;
+            v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
+            goto LABEL_225;
+          }
+          v48 = v80 * 307.2;
+          if ( (double)v81 >= v48 )
+          {
+            if ( v81 >= 1024 )
+            {
+              v50 = v82 == 0;
+LABEL_215:
+              if ( !v50 )
+                goto LABEL_217;
+              v71 = &pDir;
+              v63 = 256;
+LABEL_240:
+              Actor::_402686(v32, a2, v63, v71);
+              goto LABEL_254;
+            }
+            if ( v82 )
+              goto LABEL_217;
+            v70 = (signed __int64)v48;
+            v62 = &pDir;
+            v59 = 0;
+            goto LABEL_237;
+          }
+          v49 = v84 == 0;
+          goto LABEL_209;
+        }
+LABEL_241:
+        if ( !v21->pMonsterInfo.uMovementType )
+        {
+          v68 = 0;
+          v61 = 1024;
+LABEL_252:
+          v41 = v32;
+          v40 = 4;
+LABEL_253:
+          Actor::_4032B2(v41, v40, v61, v68);
+          goto LABEL_254;
+        }
+        if ( v21->pMonsterInfo.uMovementType == 1 )
+        {
+          v68 = 0;
+          v61 = 2560;
+          goto LABEL_252;
+        }
+        if ( v21->pMonsterInfo.uMovementType == 2 )
+        {
+          v68 = 0;
+          v61 = 5120;
+          goto LABEL_252;
+        }
+        if ( v21->pMonsterInfo.uMovementType == 4 )
+        {
+          v68 = 0;
+          v61 = 10240;
+          goto LABEL_252;
+        }
+        if ( v21->pMonsterInfo.uMovementType == 5 )
+        {
+          v57 = Actor::GetDirectionInfo(a1, 4u, &v72, 0);
+          v58 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
+          memcpy(&v74, v57, sizeof(v74));
+          memcpy(&pDir, &v74, sizeof(pDir));
+          v69 = &pDir;
+          v52 = uActorID;
+          v64 = (signed __int64)v58;
+          v51 = 4;
+          goto LABEL_247;
+        }
+        goto LABEL_254;
+      }
+      if ( !v21->pMonsterInfo.uMissleAttack2Type )
+      {
+        v56 = v80 * 307.2;
+        if ( (double)v81 >= v56 )
+        {
+          if ( v81 >= 1024 )
+          {
+            v50 = v82 == 0;
+            goto LABEL_215;
+          }
+LABEL_235:
+          if ( v82 )
+            goto LABEL_217;
+          v70 = (signed __int64)v56;
+          v62 = &pDir;
+          v59 = 0;
+LABEL_237:
+          Actor::_40281C(v32, a2, v59, v62, v70);
+          goto LABEL_254;
+        }
+LABEL_227:
+        v49 = v84 == 0;
+LABEL_209:
+        v69 = &pDir;
+        if ( v49 )
+          goto LABEL_218;
+        Actor::_403C6C(v32, a2, &pDir);
+        goto LABEL_254;
+      }
+      if ( !v84 )
+        goto LABEL_223;
+      Actor::_40368B(v32, a2, &pDir);
+LABEL_254:
+      ++v78;
+      if ( v78 >= ai_arrays_size )
+        return;
+    }
+    v65 = v21->pMonsterInfo.uSpellSkillAndMastery1;
+    v60 = 2;
+    v33 = v21->pMonsterInfo.uSpell1ID;
+    goto LABEL_146;
+  }
+}
+
+
+
+
+//----- (0040261D) --------------------------------------------------------
+int stru298::Add(__int16 uID, __int16 a3, __int16 x, __int16 y, __int16 z, char a7, char a8)
+{
+  int result; // eax@1
+
+  result = this->count;
+  if ( this->count < 100 )
+  {
+    this->pIDs[result] = uID;
+    this->pXs[this->count] = x;
+    this->pYs[this->count] = y;
+    this->pZs[this->count] = z;
+    this->field_324[this->count] = a3;
+    this->field_3EC[this->count] = a8;
+    result = this->count;
+    this->field_450[this->count++] = a7;
+  }
+  return result;
+}
+
+
+
+
+
+//----- (00402CAE) --------------------------------------------------------
+int stru193_math::SinCos(int angle)
+{
+  int v2; // eax@1
+
+  //a2: (angle - uIntegerHalfPi)    for  sin(angle)
+  //    (angle)                     for  cos(angle)
+
+  v2 = uDoublePiMask & angle;
+  
+  if ( v2 > uIntegerPi )
+    v2 = uIntegerDoublePi - v2;
+  if ( v2 >= uIntegerHalfPi )
+    return -pCosTable[uIntegerPi - v2];
+  else
+    return pCosTable[v2];
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//----- (00404544) --------------------------------------------------------
+signed int stru262_TurnBased::_404544()
+{
+  stru262_TurnBased *v1; // ebx@1
+  TurnBased_QueueElem *v2; // esi@2
+  Actor *v3; // edi@4
+  Actor *v4; // ecx@4
+  Player *v5; // eax@7
+  int v6; // ecx@15
+  TurnBased_QueueElem *v7; // eax@16
+  TurnBased_QueueElem *v8; // ecx@18
+  int v9; // edx@19
+  int v10; // esi@19
+  int v11; // esi@21
+  int v12; // ST0C_4@25
+  int v13; // ST10_4@25
+  int v14; // ST14_4@25
+  int v15; // ST18_4@25
+  signed int result; // eax@28
+  TurnBased_QueueElem *v17; // edi@32
+  int v18; // [sp+20h] [bp-Ch]@17
+  int v19; // [sp+24h] [bp-8h]@1
+  int v20; // [sp+28h] [bp-4h]@1
+  signed int v21; // [sp+28h] [bp-4h]@16
+  int v22; // [sp+28h] [bp-4h]@31
+
+  v20 = 0;
+  v1 = this;
+  v19 = this->uActorQueueSize;
+  if ( this->uActorQueueSize > 0 )
+  {
+    v2 = this->pQueue;
+    do
+    {
+      if ( (v2->uPackedID & 7) == 3 )
+      {
+        v3 = &pActors[v2->uPackedID >> 3];
+        v4 = &pActors[v2->uPackedID >> 3];
+        LOBYTE(v4->uAttributes) |= 0x80u;
+        if ( !v4->CanAct() )
+        {
+          --v19;
+          v2->field_4 = 1001;
+          LOBYTE(v3->uAttributes) &= 0x7Fu;
+        }
+      }
+      if ( (v2->uPackedID & 7) == 4 )
+      {
+        v5 = &pParty->pPlayers[v2->uPackedID >> 3];
+        if ( v5->pConditions[14]
+          || v5->pConditions[16]
+          || v5->pConditions[15]
+          || v5->pConditions[13]
+          || v5->pConditions[12]
+          || v5->pConditions[2] )
+        {
+          --v19;
+          v2->field_4 = 1001;
+        }
+      }
+      ++v20;
+      ++v2;
+    }
+    while ( v20 < v1->uActorQueueSize );
+  }
+  v6 = v1->uActorQueueSize;
+  if ( v6 > 0 )
+  {
+    v21 = 1;
+    v7 = v1->pQueue;
+    do
+    {
+      v18 = v21;
+      if ( v21 < v6 )
+      {
+        v8 = v7 + 1;
+        do
+        {
+          v9 = v8->field_4;
+          v10 = v7->field_4;
+          if ( v9 < v10
+            || v9 == v10
+            && ((v11 = v8->uPackedID & 7, v11 == 4) && (v7->uPackedID & 7) == 3
+             || v11 == (v7->uPackedID & 7) && (v8->uPackedID & 0xFFFFFFF8) < (v7->uPackedID & 0xFFFFFFF8)) )
+          {
+            v12 = v7->uPackedID;
+            v13 = v7->field_4;
+            v14 = v7->uActionLength;
+            v15 = v7->field_C;
+            v7->uPackedID = v8->uPackedID;
+            v7->field_4 = v8->field_4;
+            v7->uActionLength = v8->uActionLength;
+            v7->field_C = v8->field_C;
+            v8->uPackedID = v12;
+            v8->field_4 = v13;
+            v8->uActionLength = v14;
+            v8->field_C = v15;
+          }
+          ++v18;
+          ++v8;
+        }
+        while ( v18 < v1->uActorQueueSize );
+      }
+      ++v21;
+      v6 = v1->uActorQueueSize;
+      ++v7;
+    }
+    while ( v21 - 1 < v6 );
+  }
+  v1->uActorQueueSize = v19;
+  result = v1->pQueue[0].uPackedID;
+  if ( (v1->pQueue[0].uPackedID & 7) == 4 )
+  {
+    result = (result >> 3) + 1;
+    uActiveCharacter = result;
+    v1->field_18 |= 4u;
+  }
+  else
+  {
+    uActiveCharacter = 0;
+    v1->field_18 &= 0xFFFFFFFBu;
+  }
+  v22 = 0;
+  if ( v1->uActorQueueSize > 0 )
+  {
+    v17 = v1->pQueue;
+    do
+    {
+      if ( (v17->uPackedID & 7) == 4 )
+        pParty->pPlayers[v17->uPackedID >> 3].uTimeToRecovery = (signed __int64)((double)v17->field_4 * 0.46875);
+      ++v22;
+      ++v17;
+      result = v22;
+    }
+    while ( v22 < v1->uActorQueueSize );
+  }
+  return result;
+}
+
+//----- (0040471C) --------------------------------------------------------
+void stru262_TurnBased::_40471C()
+{
+  if ( pParty->bTurnBasedModeOn == 1 )
+  {
+    if ( pTurnEngine->field_4 == 2 )
+      _406457(0);
+  }
+}
+
+
+//----- (00404828) --------------------------------------------------------
+LayingItem::LayingItem()
+{
+  LayingItem *v1; // esi@1
+
+  v1 = this;
+  v1->field_22 = 1;
+  v1->uSoundID = 0;
+  v1->uFacing = 0;
+  v1->vVelocity.z = 0;
+  v1->vVelocity.y = 0;
+  v1->vVelocity.x = 0;
+  v1->uItemType = 0;
+  v1->uObjectDescID = 0;
+  v1->field_61 = 0;
+  v1->field_60_distance_related_prolly_lod = 0;
+  v1->field_20 = 0;
+  v1->uSpriteFrameID = 0;
+  v1->field_50 = 0;
+  v1->field_4C = 0;
+  v1->field_48 = 0;
+  v1->field_54 = 0;
+}
+
+
+
+//----- (004059DB) --------------------------------------------------------
+signed int stru262_TurnBased::Start()
+{
+  stru262_TurnBased *v1; // ebx@1
+  unsigned int v2; // edi@1
+  int v3; // esi@1
+  int v4; // eax@5
+  unsigned int v5; // esi@7
+  Actor *v6; // edi@7
+  unsigned int v7; // eax@9
+  unsigned int v8; // edx@10
+  unsigned __int8 v9; // zf@14
+  unsigned __int8 v10; // sf@14
+  unsigned __int8 v11; // of@14
+  char *v12; // esi@15
+  int v13; // ecx@16
+  unsigned __int16 v14; // ax@17
+  int v15; // ecx@18
+  signed __int64 v16; // qax@19
+  int v17; // edx@22
+  unsigned int v18; // esi@27
+  char *v19; // esi@32
+  int v20; // edx@33
+  char *v21; // eax@33
+  int v22; // ecx@33
+  int v23; // eax@34
+  char *v24; // eax@34
+  char *v25; // ecx@34
+  int v26; // edx@34
+  int v27; // eax@38
+  int v28; // ecx@38
+  AIDirection v30; // [sp+Ch] [bp-68h]@10
+  AIDirection v31; // [sp+28h] [bp-4Ch]@10
+  AIDirection a3; // [sp+44h] [bp-30h]@10
+  int v33; // [sp+60h] [bp-14h]@10
+  int *v34; // [sp+64h] [bp-10h]@6
+  int v35; // [sp+68h] [bp-Ch]@5
+  int v40; // [sp+6Ch] [bp-8h]@1
+  unsigned int v37; // [sp+70h] [bp-4h]@7
+
+  pTurnEngine->field_18 &= 0xFFFFFFFDu;
+  v1 = this;
+  pEventTimer->TrackGameTime();
+  pAudioPlayer->StopChannels(-1, -1);
+  v2 = 0;
+  pAudioPlayer->PlaySound((SoundID)(SOUND_GoldReceived|SOUND_EnteringAHouse|0x1), 0, 0, -1, 0, 0, 0, 0);
+  v40 = (int)pParty->pPlayers;
+  dword_50C998_turnbased_icon_1A = 8 * pIconsFrameTable->pIcons[uIconID_TurnStart].uAnimLength;
+  dword_50C994 = 0;
+  v1->field_10 = 100;
+  v1->field_0 = 0;
+  v1->field_8 = 64;
+  v1->field_4 = 1;
+  v1->uActorQueueSize = 0;
+  v3 = 0;
+  do
+  {
+    if ( ((Player *)v40)->CanAct() )
+    {
+      *(&v1->field_0 + 4 * (v1->uActorQueueSize + 2)) = 8 * v3 | OBJECT_Player;
+      v1->pQueue[v1->uActorQueueSize].field_C = 2;
+      v1->pQueue[v1->uActorQueueSize].uActionLength = 0;
+      pParty->pTurnBasedPlayerRecoveryTimes[v1->uActorQueueSize++] = 0;
+    }
+    v40 += 6972;
+    ++v3;
+  }
+  while ( v40 < (signed int)pParty->pHirelings );
+  v35 = v1->uActorQueueSize;
+  v4 = v35;
+  v40 = v35;
+  if ( v40 < v40 + ai_arrays_size )
+  {
+    v34 = (int *)ai_array_4F7DB0_actor_ids;
+    do
+    {
+      v37 = *v34;
+      v5 = v37;
+      v6 = &pActors[v37];
+      if ( v37 != 10 )
+      {
+        if ( pActors[v37].CanAct() )
+        {
+          v7 = v6->uAttributes;
+          if ( v7 & 0x8000 < 0 )
+          {
+            v8 = dword_4F6E08[v5];
+            LOBYTE(v7) = v7 | 0x80;
+            v6->uAttributes = v7;
+            v33 = 8 * v5 | OBJECT_Actor;
+            memcpy(&v31, Actor::GetDirectionInfo(8 * v5 | OBJECT_Actor, v8, &a3, 0), sizeof(v31));
+            memcpy(&v30, &v31, sizeof(v30));
+            Actor::_403F58(v37, 4, 32, &v30);
+            *(&v1->field_0 + 4 * (v1->uActorQueueSize + 2)) = v33;
+            v1->pQueue[v1->uActorQueueSize].field_C = 2;
+            v1->pQueue[v1->uActorQueueSize++].uActionLength = 0;
+          }
+        }
+        v4 = v35;
+      }
+      ++v40;
+      ++v34;
+    }
+    while ( v40 < v4 + ai_arrays_size );
+    v2 = 0;
+  }
+  v11 = __OFSUB__(v1->uActorQueueSize, v2);
+  v9 = v1->uActorQueueSize == v2;
+  v10 = ((v1->uActorQueueSize - v2) & 0x80000000u) != 0;
+  v37 = v2;
+  v40 = v2;
+  if ( !((unsigned __int8)(v10 ^ v11) | v9) )
+  {
+    v12 = (char *)&v1->pQueue[0].field_4;
+    while ( 1 )
+    {
+      v13 = *((int *)v12 - 1) & 7;
+      if ( v13 != OBJECT_Player )
+        break;
+      v14 = pPlayers[(*((int *)v12 - 1) >> 3) + 1]->uTimeToRecovery;
+      if ( v14 != (short)v2 )
+      {
+        v33 = v14;
+        v16 = (signed __int64)((double)v14 * 0.46875);
+LABEL_20:
+        *(int *)v12 = v16;
+        goto LABEL_26;
+      }
+      v15 = v37++;
+      *(&a3.uDistance + v15) = v40;
+LABEL_26:
+      ++v40;
+      v12 += 16;
+      if ( v40 >= v1->uActorQueueSize )
+        goto LABEL_27;
+    }
+    if ( v13 != 3 )
+    {
+      *(int *)v12 = 666;
+      goto LABEL_26;
+    }
+    v17 = rand() % 99;
+    if ( v17 < 33 )
+    {
+      *(int *)v12 = 1;
+      goto LABEL_26;
+    }
+    LODWORD(v16) = SHIDWORD(v16) < 66;
+    LOBYTE(v16) = SHIDWORD(v16) >= 66;
+    LODWORD(v16) = 2 * v16 + 3;
+    goto LABEL_20;
+  }
+LABEL_27:
+  v18 = 0;
+  if ( (signed int)v37 > (signed int)v2 )
+  {
+    do
+    {
+      *(&v31.uDistance + v18) = pParty->pPlayers[*(&v1->field_0 + 4 * (*(&a3.uDistance + v18) + 2)) >> 3].GetAttackRecoveryTime(
+                                  v2);
+      ++v18;
+    }
+    while ( (signed int)v18 < (signed int)v37 );
+    if ( (signed int)v37 > (signed int)v2 )
+    {
+      v35 = v2;
+      v34 = (int *)1;
+      do
+      {
+        v40 = (int)v34;
+        if ( (signed int)v34 < (signed int)v37 )
+        {
+          v19 = (char *)&v31.uDistance + v35;
+          do
+          {
+            v20 = *(int *)v19;
+            v33 = 4 * v40;
+            v21 = (char *)(&v31.uDistance + v40);
+            v22 = *(int *)v21;
+            if ( *(int *)v21 < v20 )
+            {
+              *(int *)v21 = v20;
+              v23 = v33;
+              *(int *)v19 = v22;
+              v24 = (char *)&a3.uDistance + v23;
+              v25 = (char *)&a3.uDistance + v35;
+              v26 = *(int *)v24;
+              *(int *)v24 = *(unsigned int *)((char *)&a3.uDistance + v35);
+              *(int *)v25 = v26;
+              v2 = 0;
+            }
+            ++v40;
+          }
+          while ( v40 < (signed int)v37 );
+        }
+        v34 = (int *)((char *)v34 + 1);
+        v35 += 4;
+      }
+      while ( (signed int)((char *)v34 - 1) < (signed int)v37 );
+      if ( (signed int)v37 > (signed int)v2 )
+      {
+        do
+        {
+          v27 = v2 + 2;
+          v28 = *(&a3.uDistance + v2++);
+          v11 = __OFSUB__(v2, v37);
+          v10 = ((v2 - v37) & 0x80000000u) != 0;
+          v1->pQueue[v28].field_4 = v27;
+        }
+        while ( v10 ^ v11 );
+      }
+    }
+  }
+  return v1->_404544();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mm7_4.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,15227 @@
+#include <io.h>
+#include <direct.h>
+
+#include "MapInfo.h"
+#include "Game.h"
+#include "GUIWindow.h"
+#include "GUIButton.h"
+#include "GUIFont.h"
+#include "Party.h"
+#include "AudioPlayer.h"
+#include "Outdoor.h"
+#include "IndoorCamera.h"
+#include "Overlays.h"
+#include "Monsters.h"
+#include "Arcomage.h"
+#include "LOD.h"
+#include "Actor.h"
+#include "Allocator.h"
+#include "Events.h"
+#include "Viewport.h"
+#include "FrameTableInc.h"
+#include "Math.h"
+#include "LayingItem.h"
+#include "ObjectList.h"
+#include "Chest.h"
+#include "PaletteManager.h"
+#include "DecorationList.h"
+#include "SaveLoad.h"
+#include "stru123.h"
+#include "stru287.h"
+#include "Time.h"
+#include "IconFrameTable.h"
+#include "GUIProgressBar.h"
+#include "stru157.h"
+#include "Bink_Smacker.h"
+#include "TileFrameTable.h"
+#include "PlayerFrameTable.h"
+#include "Awards.h"
+#include "Autonotes.h"
+#include "stru160.h"
+#include "stru279.h"
+#include "TurnEngine.h"
+#include "FactionTable.h"
+#include "StorylineTextTable.h"
+#include "Random.h"
+#include "stru277.h"
+#include "stru298.h"
+#include "stru12.h"
+#include "stru351.h"
+#include "Events2D.h"
+#include "stru159.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//----- (0046CC4B) --------------------------------------------------------
+void __cdecl _46CC4B_check_event_triggers()
+{
+  int v0; // eax@1
+  LevelDecoration *v1; // esi@2
+  signed int v2; // edi@2
+  int v3; // ebx@2
+  int v4; // eax@3
+  int v5; // ebx@3
+  unsigned int v6; // ecx@3
+  unsigned int v7; // edx@6
+  unsigned int v8; // edx@8
+  char *v9; // edi@13
+  int v10; // ebx@14
+  int v11; // eax@14
+  int v12; // ebx@14
+  unsigned int v13; // ecx@14
+  int v14; // edx@15
+  unsigned int v15; // edx@17
+  unsigned int v16; // edx@19
+  char *v17; // edi@25
+  int v18; // ebx@26
+  int v19; // eax@26
+  int v20; // ebx@26
+  unsigned int v21; // ecx@26
+  int v22; // edx@27
+  unsigned int v23; // edx@29
+  unsigned int v24; // edx@31
+  int v25; // [sp+0h] [bp-24h]@3
+  int v26; // [sp+0h] [bp-24h]@14
+  int v27; // [sp+0h] [bp-24h]@26
+  int v28; // [sp+4h] [bp-20h]@3
+  int v29; // [sp+4h] [bp-20h]@14
+  int v30; // [sp+4h] [bp-20h]@26
+  signed int v31; // [sp+8h] [bp-1Ch]@2
+  int v32; // [sp+Ch] [bp-18h]@2
+  int v33; // [sp+10h] [bp-14h]@2
+  int i; // [sp+14h] [bp-10h]@1
+  int v35; // [sp+18h] [bp-Ch]@2
+  int v36; // [sp+1Ch] [bp-8h]@3
+  signed int v37; // [sp+1Ch] [bp-8h]@12
+  signed int v38; // [sp+20h] [bp-4h]@24
+
+  v0 = 0;
+  for ( i = 0; i < _6836C8_num_decorations_6807E8; ++i )
+  {
+    v1 = &pLevelDecorations[_6807E8_level_decorations_ids[v0]];
+    v2 = v1->field_18;
+    v3 = v1->vPosition.y;
+    v33 = v1->vPosition.x;
+    v32 = v1->vPosition.y;
+    v35 = v1->vPosition.z;
+    v31 = v1->field_18;
+    if ( v1->field_2 & 1 )
+    {
+      v36 = abs(v1->vPosition.x - pParty->vPosition.x);
+      v25 = abs(v3 - pParty->vPosition.y);
+      v28 = abs(v35 - pParty->vPosition.z);
+      v4 = v36;
+      v5 = v25;
+      v6 = v28;
+      if ( v36 < v25 )
+      {
+        v4 = v25;
+        v5 = v36;
+      }
+      if ( v4 < v28 )
+      {
+        v7 = v4;
+        v4 = v28;
+        v6 = v7;
+      }
+      if ( v5 < (signed int)v6 )
+      {
+        v8 = v6;
+        v6 = v5;
+        v5 = v8;
+      }
+      if ( (signed int)(((unsigned int)(11 * v5) >> 5) + (v6 >> 2) + v4) < v2 )
+        EventProcessor(v1->field_16_event_id, 8 * i | 5, 1);
+    }
+    if ( v1->field_2 & 2 )
+    {
+      v37 = 0;
+      if ( (signed int)uNumActors > 0 )
+      {
+        v9 = (char *)&pActors[0].vPosition.y;
+        do
+        {
+          v10 = abs(v33 - *((short *)v9 - 1));
+          v29 = abs(v32 - *(short *)v9);
+          v26 = abs(v35 - *((short *)v9 + 1));
+          v11 = v10;
+          v12 = v29;
+          v13 = v26;
+          if ( v11 < v29 )
+          {
+            v14 = v11;
+            v11 = v29;
+            v12 = v14;
+          }
+          if ( v11 < v26 )
+          {
+            v15 = v11;
+            v11 = v26;
+            v13 = v15;
+          }
+          if ( v12 < (signed int)v13 )
+          {
+            v16 = v13;
+            v13 = v12;
+            v12 = v16;
+          }
+          if ( (signed int)(((unsigned int)(11 * v12) >> 5) + (v13 >> 2) + v11) < v31 )
+            EventProcessor(v1->field_16_event_id, 0, 1);
+          ++v37;
+          v9 += 836;
+        }
+        while ( v37 < (signed int)uNumActors );
+      }
+    }
+    if ( v1->field_2 & 4 )
+    {
+      v38 = 0;
+      if ( (signed int)uNumLayingItems > 0 )
+      {
+        v17 = (char *)&pLayingItems[0].vPosition.y;
+        do
+        {
+          v18 = abs(v33 - *((int *)v17 - 1));
+          v30 = abs(v32 - *(int *)v17);
+          v27 = abs(v35 - *((int *)v17 + 1));
+          v19 = v18;
+          v20 = v30;
+          v21 = v27;
+          if ( v19 < v30 )
+          {
+            v22 = v19;
+            v19 = v30;
+            v20 = v22;
+          }
+          if ( v19 < v27 )
+          {
+            v23 = v19;
+            v19 = v27;
+            v21 = v23;
+          }
+          if ( v20 < (signed int)v21 )
+          {
+            v24 = v21;
+            v21 = v20;
+            v20 = v24;
+          }
+          if ( (signed int)(((unsigned int)(11 * v20) >> 5) + (v21 >> 2) + v19) < v31 )
+            EventProcessor(v1->field_16_event_id, 0, 1);
+          ++v38;
+          v17 += 112;
+        }
+        while ( v38 < (signed int)uNumLayingItems );
+      }
+    }
+    v0 = i + 1;
+  }
+}
+// 6836C8: using guessed type int 6836C8_num_decorations_6807E8;
+
+//----- (0046CEC3) --------------------------------------------------------
+int _46CEC3_get_floor_level(int x, int y, int z, unsigned int uSectorID, unsigned int *pFaceID)
+{
+  //BLVSector *v5; // edi@1
+  //int v6; // ecx@1
+  //Vec3_short_ *v7; // edx@1
+  //BLVFace *v8; // esi@2
+  //int v9; // eax@8
+  //int v10; // edi@8
+  //int v11; // eax@10
+  int v12; // ecx@10
+  int v13; // ecx@13
+  signed int v14; // ebx@14
+  int v15; // eax@16
+  int v16; // edx@19
+  int v17; // ST18_4@19
+  signed int v18; // edx@19
+  signed __int64 v19; // qtt@19
+  PolygonType v20; // al@25
+  int v21; // eax@27
+  int v22; // ecx@29
+  //BLVFace *v23; // eax@33
+  //int v24; // esi@39
+  //int v25; // edi@39
+  int v26; // esi@41
+  int v27; // ecx@43
+  signed int v28; // eax@45
+  int v29; // ebx@47
+  int v30; // edx@49
+  int v31; // ST10_4@49
+  signed int v32; // edx@49
+  signed __int64 v33; // qtt@49
+  signed int v34; // eax@54
+  signed int v35; // esi@56
+  int result; // eax@57
+  int v37; // edi@61
+  int v38; // edx@62
+  //int v39; // [sp+Ch] [bp-34h]@1
+  //int v40; // [sp+10h] [bp-30h]@2
+  int v41; // [sp+14h] [bp-2Ch]@12
+  //unsigned __int16 *v42; // [sp+18h] [bp-28h]@1
+  //BLVSector *v43; // [sp+1Ch] [bp-24h]@1
+  int v44; // [sp+20h] [bp-20h]@10
+  int v45; // [sp+24h] [bp-1Ch]@10
+  //signed int v46; // [sp+24h] [bp-1Ch]@38
+  bool v47; // [sp+24h] [bp-1Ch]@43
+  bool v48; // [sp+28h] [bp-18h]@10
+  bool v49; // [sp+28h] [bp-18h]@41
+  bool v50; // [sp+2Ch] [bp-14h]@12
+  int v51; // [sp+2Ch] [bp-14h]@41
+  //signed int v52; // [sp+30h] [bp-10h]@7
+  signed int v53; // [sp+30h] [bp-10h]@10
+  signed int v54; // [sp+30h] [bp-10h]@41
+  signed int v55; // [sp+34h] [bp-Ch]@1
+  //signed int v56; // [sp+38h] [bp-8h]@1
+  //signed int v57; // [sp+3Ch] [bp-4h]@1
+  //int uSectorIDa; // [sp+4Ch] [bp+Ch]@1
+  //signed int uSectorIDb; // [sp+4Ch] [bp+Ch]@32
+
+  LOG_DECOMPILATION_WARNING();
+
+  //auto a1 = x;
+  //auto a2 = y;
+  //auto a3 = z;
+
+  //v5 = &pIndoor->pSectors[uSectorID];
+  auto pSector = &pIndoor->pSectors[uSectorID];
+  //v57 = y;
+  //v56 = x;
+  //v6 = 0;
+  v55 = 0;
+  //v43 = v5;
+  //v42 = v5->pFloors;
+  //v7 = pIndoor->pVertices;
+  //v39 = v5->uNumFloors;
+  //for ( uSectorIDa = 0; uSectorIDa < v39; ++uSectorIDa )
+  for (uint i = 0; i < pSector->uNumFloors; ++i)
+  {
+    //v40 = (int)&v42[v6];
+    //v8 = &pIndoor->pFaces[pSector->pFloors[i]];
+    auto pFloor = &pIndoor->pFaces[pSector->pFloors[i]];
+    if (pFloor->Clickable())
+      continue;
+
+    if (x <= pFloor->pBounding.x2 && x >= pFloor->pBounding.x1 &&
+        y <= pFloor->pBounding.y2 && y >= pFloor->pBounding.y1)
+    {
+      //v52 = 0;
+      for (uint j = 0; j < pFloor->uNumVertices; ++j)
+      {
+          //v9 = v52;
+          //v10 = 2 * v52;
+        word_721460[2 * j] =     pFloor->pXInterceptDisplacements[j] + pIndoor->pVertices[pFloor->pVertexIDs[j]].x;
+        word_721460[2 * j + 1] = pFloor->pXInterceptDisplacements[j] + pIndoor->pVertices[pFloor->pVertexIDs[j + 1]].x;
+        word_721390[2 * j] =     pFloor->pYInterceptDisplacements[j] + pIndoor->pVertices[pFloor->pVertexIDs[j]].y;
+        word_721390[2 * j + 1] = pFloor->pYInterceptDisplacements[j] + pIndoor->pVertices[pFloor->pVertexIDs[j + 1]].y;
+        //}
+        //while ( v52 < v8->uNumVertices );
+        //v5 = v43;
+      }
+      v44 = 2 * pFloor->uNumVertices;
+      //v11 = 2 * pFloor->uNumVertices;
+      word_721460[2 * pFloor->uNumVertices] = word_721460[0];
+      word_721390[2 * pFloor->uNumVertices] = word_721390[0];
+
+      v48 = word_721390[0] >= y;
+      v12 = 0;
+      v53 = 0;
+      v45 = 0;
+      if ( pFloor->uNumVertices > 0 )
+      {
+        do
+        {
+          if ( v53 >= 2 )
+            break;
+          v41 = word_721390[v12 + 1];
+          v50 = word_721390[v12 + 1] >= y;
+          if ( v48 == v50 )
+          {
+            v13 = v45;
+          }
+          else
+          {
+            v13 = v45;
+            if ( word_721460[v45 + 1] >= x )
+              v14 = 0;
+            else
+              v14 = 2;
+            v15 = v14 | word_721460[v45] < x;
+            if ( v15 != 3 )
+            {
+              if ( !v15
+                || (v16 = word_721390[v45],
+                    v17 = v41 - v16,
+                    v18 = y - v16,
+                    LODWORD(v19) = v18 << 16,
+                    HIDWORD(v19) = v18 >> 16,
+                    //v7 = pIndoor->pVertices,
+                    (signed int)(((unsigned __int64)(((signed int)word_721460[v45 + 1] - (signed int)word_721460[v45])
+                                                   * v19
+                                                   / v17) >> 16)
+                               + word_721460[v45]) >= x) )
+                ++v53;
+            }
+          }
+          v12 = v13 + 1;
+          v48 = v50;
+          v45 = v12;
+        }
+        while ( v12 < v44 );
+
+        if ( v53 == 1 )
+        {
+          if ( v55 >= 50 )
+            break;
+          v20 = pFloor->uPolygonType;
+          if ( v20 == 3 || v20 == 5 )
+          {
+            v21 = pIndoor->pVertices[*pFloor->pVertexIDs].z;
+          }
+          else
+          {
+            //v7 = pIndoor->pVertices;
+            v21 = ((unsigned __int64)(pFloor->zCalc1 * (signed __int64)x) >> 16)
+                + ((unsigned __int64)(pFloor->zCalc2 * (signed __int64)y) >> 16)
+                + HIWORD(pFloor->zCalc3);
+          }
+          v22 = v55++;
+          dword_7212C8[v22] = v21;
+          dword_721200[v22] = pSector->pFloors[i];
+        }
+      }
+    }
+    //v6 = uSectorIDa + 1;
+  }
+
+  if ( pSector->field_0 & 8 )
+  {
+    for (uint i = 0; i < pSector->uNumPortals; ++i)
+    {
+      //v23 = &pIndoor->pFaces[v5->pPortals[uSectorIDb]];
+      auto portal = &pIndoor->pFaces[pSector->pPortals[i]];
+      if (portal->uPolygonType != POLYGON_Floor)
+        continue;
+
+      if (x <= portal->pBounding.x2 &&
+          x >= portal->pBounding.x1 &&
+          y <= portal->pBounding.y2 &&
+          y >= portal->pBounding.y1 )
+      {
+        //v46 = 0;
+        for (uint j = 0; j < portal->uNumVertices; ++j)
+        {
+            //v24 = v46;
+            //v25 = 2 * v46;
+          word_721460[2 * j] =     portal->pXInterceptDisplacements[j] + pIndoor->pVertices[portal->pVertexIDs[j]].x;
+          word_721460[2 * j + 1] = portal->pXInterceptDisplacements[j + 1] + pIndoor->pVertices[portal->pVertexIDs[j + 1]].x;
+          word_721390[2 * j] =     portal->pYInterceptDisplacements[j] + pIndoor->pVertices[portal->pVertexIDs[j]].y;
+          word_721390[2 * j + 1] = portal->pYInterceptDisplacements[j + 1] + pIndoor->pVertices[portal->pVertexIDs[j + 1]].y;
+          //}
+          //while ( v46 < v23->uNumVertices );
+          //v5 = v43;
+        }
+
+        //v26 = 2 * v23->uNumVertices;
+        word_721460[2 * portal->uNumVertices] = word_721460[0];
+        word_721390[2 * portal->uNumVertices] = word_721390[0];
+        v54 = 0;
+        v51 = 0;
+        v49 = word_721390[0] >= y;
+        if ( v26 > 0 )
+        {
+          do
+          {
+            if ( v54 >= 2 )
+              break;
+            v27 = v51;
+            v47 = word_721390[v51 + 1] >= y;
+            if ( v49 != v47 )
+            {
+              if ( word_721460[v27 + 1] >= x )
+                v28 = 0;
+              else
+                v28 = 2;
+              v29 = v28 | word_721460[v27] < x;
+              if ( v29 != 3 )
+              {
+                if ( !v29
+                  || (v30 = word_721390[v27],
+                      v31 = word_721390[v51 + 1] - v30,
+                      v32 = y - v30,
+                      LODWORD(v33) = v32 << 16,
+                      HIDWORD(v33) = v32 >> 16,
+                      //v7 = pIndoor->pVertices,
+                      (signed int)(((unsigned __int64)(((signed int)word_721460[v27 + 1] - (signed int)word_721460[v27])
+                                                     * v33
+                                                     / v31) >> 16)
+                                 + word_721460[v27]) >= x) )
+                  ++v54;
+              }
+            }
+            ++v51;
+            v49 = v47;
+          }
+          while ( v51 < v26 );
+          if ( v54 == 1 )
+          {
+            if ( v55 >= 50 )
+              break;
+            v34 = v55++;
+            dword_7212C8[v34] = -29000;
+            dword_721200[v34] = pSector->pPortals[i];
+          }
+        }
+      }
+    }
+  }
+
+  v35 = 1;
+  if ( v55 == 1 )
+  {
+    *pFaceID = dword_721200[0];
+    return dword_7212C8[0];
+  }
+  if ( !v55 )
+    return -30000;
+  *pFaceID = dword_721200[0];
+  result = dword_7212C8[0];
+  if ( v55 > 1 )
+  {
+    v37 = z + 5;
+    while ( 1 )
+    {
+      v38 = dword_7212C8[v35];
+      if ( result <= v37 )
+        break;
+      if ( v38 < result )
+        goto LABEL_67;
+LABEL_68:
+      ++v35;
+      if ( v35 >= v55 )
+        return result;
+    }
+    if ( v38 <= result || v38 > v37 )
+      goto LABEL_68;
+LABEL_67:
+    result = dword_7212C8[v35];
+    *pFaceID = dword_721200[v35];
+    goto LABEL_68;
+  }
+  return result;
+}
+
+//----- (0046D49E) --------------------------------------------------------
+int __fastcall sub_46D49E_prolly_get_world_y_under_party(int a1, signed int a2, int a3, int a4, int *a5, int *a6, int a7)
+{
+  signed int v7; // edi@1
+  int v8; // ebx@1
+  int v9; // eax@1
+  BSPModel *v10; // esi@4
+  ODMFace *v11; // ecx@11
+  unsigned __int8 v12; // al@11
+  char *v13; // eax@19
+  int v14; // edx@20
+  int v15; // eax@22
+  int v16; // edx@22
+  int v17; // edi@24
+  signed int v18; // edx@26
+  int v19; // eax@28
+  int v20; // edx@30
+  int v21; // ST1C_4@30
+  signed int v22; // edx@30
+  signed __int64 v23; // qtt@30
+  int v24; // eax@36
+  signed int v25; // ecx@38
+  int result; // eax@42
+  signed int v27; // ecx@43
+  int v28; // edi@44
+  signed int v29; // edx@44
+  int v30; // esi@45
+  int v31; // eax@45
+  ODMFace *v32; // eax@57
+  int v33; // ecx@59
+  int v34; // [sp+Ch] [bp-34h]@8
+  int v35; // [sp+10h] [bp-30h]@22
+  int v36; // [sp+14h] [bp-2Ch]@24
+  int v37; // [sp+18h] [bp-28h]@22
+  int v38; // [sp+1Ch] [bp-24h]@2
+  int v39; // [sp+20h] [bp-20h]@9
+  int v40; // [sp+24h] [bp-1Ch]@1
+  signed int v41; // [sp+28h] [bp-18h]@1
+  int v42; // [sp+2Ch] [bp-14h]@8
+  bool v43; // [sp+30h] [bp-10h]@22
+  bool v44; // [sp+34h] [bp-Ch]@24
+  signed int v45; // [sp+38h] [bp-8h]@1
+  signed int v46; // [sp+3Ch] [bp-4h]@1
+  signed int v47; // [sp+58h] [bp+18h]@18
+  signed int v48; // [sp+58h] [bp+18h]@22
+  signed int v49; // [sp+58h] [bp+18h]@43
+
+  v7 = a2;
+  v8 = a1;
+  v45 = a2;
+  v40 = a1;
+  v46 = 1;
+  v9 = GetTerrainHeightsAroundParty2(a1, a2, a5, a7);
+  dword_721160[0] = -1;
+  dword_721110[0] = -1;
+  dword_7211B0[0] = v9;
+  v41 = 0;
+  if ( (signed int)pOutdoor->uNumBModels <= 0 )
+    goto LABEL_63;
+  v38 = 0;
+  while ( 1 )
+  {
+    v10 = &pOutdoor->pBModels[v38];
+    if ( v8 <= pOutdoor->pBModels[v38].sMaxX )
+    {
+      if ( v8 >= v10->sMinX )
+      {
+        if ( v7 <= v10->sMaxY )
+        {
+          if ( v7 >= v10->sMinY )
+          {
+            v42 = 0;
+            v34 = v10->uNumFaces;
+            if ( (signed int)v10->uNumFaces > 0 )
+            {
+              v39 = 0;
+              while ( 1 )
+              {
+                v11 = &v10->pFaces[v39];
+                v12 = v11->uPolygonType;
+                if ( (v12 == 3 || v12 == 4)
+                  && !(v11->uAttributes & 0x20000000)
+                  && v8 <= v11->pBoundingBox.x2
+                  && v8 >= v11->pBoundingBox.x1
+                  && v7 <= v11->pBoundingBox.y2
+                  && v7 >= v11->pBoundingBox.y1 )
+                {
+                  v47 = 0;
+                  if ( v11->uNumVertices )
+                  {
+                    v13 = (char *)v11->pXInterceptDisplacements;
+                    do
+                    {
+                      v14 = 2 * v47;
+                      word_721040[2 * v47] = *(short *)v13 + LOWORD(v10->pVertices.pVertices[*((short *)v13 - 60)].x);
+                      word_720F70[2 * v47] = *((short *)v13 + 20)
+                                           + LOWORD(v10->pVertices.pVertices[*((short *)v13 - 60)].y);
+                      word_721040[2 * v47++ + 1] = *(short *)v13
+                                                 + LOWORD(v10->pVertices.pVertices[*((short *)v13 - 59)].x);
+                      word_720F70[v14 + 1] = *((short *)v13 + 20)
+                                           + LOWORD(v10->pVertices.pVertices[*((short *)v13 - 59)].y);
+                      v13 += 2;
+                    }
+                    while ( v47 < v11->uNumVertices );
+                    v8 = v40;
+                  }
+                  v15 = 2 * v11->uNumVertices;
+                  word_721040[2 * v11->uNumVertices] = word_721040[0];
+                  word_720F70[v15] = word_720F70[0];
+                  v35 = v15;
+                  v16 = 0;
+                  v43 = word_720F70[0] >= v45;
+                  v48 = 0;
+                  v37 = 0;
+                  if ( v15 > 0 )
+                  {
+                    do
+                    {
+                      if ( v48 >= 2 )
+                        break;
+                      v17 = v16;
+                      v8 = v40;
+                      v36 = word_720F70[v16 + 1];
+                      v44 = word_720F70[v16 + 1] >= v45;
+                      if ( v43 != v44 )
+                      {
+                        v18 = word_721040[v17 + 1] >= v40 ? 0 : 2;
+                        v19 = v18 | word_721040[v17] < v40;
+                        if ( v19 != 3 )
+                        {
+                          if ( !v19
+                            || (v20 = word_720F70[v17],
+                                v21 = v36 - v20,
+                                v22 = v45 - v20,
+                                LODWORD(v23) = v22 << 16,
+                                HIDWORD(v23) = v22 >> 16,
+                                (signed int)(((unsigned __int64)(((signed int)word_721040[v17 + 1]
+                                                                - (signed int)word_721040[v17])
+                                                               * v23
+                                                               / v21) >> 16)
+                                           + word_721040[v17]) >= v40) )
+                            ++v48;
+                        }
+                      }
+                      v16 = v37 + 1;
+                      v43 = v44;
+                      ++v37;
+                    }
+                    while ( v37 < v35 );
+                    if ( v48 == 1 )
+                    {
+                      if ( v46 >= 20 )
+                        break;
+                      if ( v11->uPolygonType == 3 )
+                        v24 = v10->pVertices.pVertices[v11->pVertexIDs[0]].z;
+                      else
+                        v24 = ((unsigned __int64)(v11->zCalc1 * (signed __int64)v8) >> 16)
+                            + ((unsigned __int64)(v11->zCalc2 * (signed __int64)v45) >> 16)
+                            + HIWORD(v11->zCalc3);
+                      v25 = v46++;
+                      dword_7211B0[v25] = v24;
+                      dword_721160[v25] = v41;
+                      dword_721110[v25] = v42;
+                    }
+                  }
+                }
+                ++v42;
+                ++v39;
+                if ( v42 >= v34 )
+                  break;
+                v7 = v45;
+              }
+            }
+          }
+        }
+      }
+    }
+    ++v41;
+    ++v38;
+    if ( v41 >= (signed int)pOutdoor->uNumBModels )
+      break;
+    v7 = v45;
+  }
+  if ( v46 == 1 )
+  {
+LABEL_63:
+    *a6 = 0;
+    return dword_7211B0[0];
+  }
+  v27 = 0;
+  v49 = 1;
+  if ( v46 <= 1 )
+  {
+LABEL_55:
+    *a6 = 0;
+    goto LABEL_56;
+  }
+  v28 = 0;
+  v29 = 1;
+  do
+  {
+    v30 = dword_7211B0[v29];
+    v31 = *(int *)((char *)dword_7211B0 + v28);
+    if ( v30 == v31 )
+      goto LABEL_51;
+    if ( v31 > a3 + 5 )
+    {
+      if ( v30 >= v31 )
+        goto LABEL_52;
+LABEL_51:
+      v27 = v49;
+      v28 = v29 * 4;
+      goto LABEL_52;
+    }
+    if ( v30 > v31 && v30 <= a3 + 5 )
+      goto LABEL_51;
+LABEL_52:
+    ++v49;
+    ++v29;
+  }
+  while ( v49 < v46 );
+  if ( !v27 )
+    goto LABEL_55;
+  *a6 = dword_721110[v27] | (dword_721160[v27] << 6);
+LABEL_56:
+  if ( v27 )
+  {
+    v32 = &pOutdoor->pBModels[dword_721160[v27]].pFaces[dword_721110[v27]];
+    *a5 = 0;
+    if ( v32->uAttributes & 0x10 )
+      *a5 = 1;
+  }
+  v33 = dword_7211B0[v27];
+  result = dword_7211B0[0];
+  if ( v33 >= dword_7211B0[0] )
+    result = v33;
+  return result;
+}
+
+//----- (0046D8E3) --------------------------------------------------------
+int __fastcall sub_46D8E3(int a1, signed int a2, int a3, int a4)
+{
+  int v4; // ebx@1
+  unsigned int v5; // ecx@1
+  BSPModel *v6; // edi@3
+  ODMFace *v7; // esi@10
+  unsigned __int8 v8; // al@10
+  unsigned __int16 *v9; // eax@18
+  int v10; // edx@19
+  int v11; // ecx@21
+  int v12; // ecx@23
+  signed int v13; // eax@25
+  int v14; // edx@27
+  int v15; // edx@29
+  int v16; // ST18_4@29
+  signed int v17; // edx@29
+  signed __int64 v18; // qtt@29
+  int v19; // eax@35
+  signed int v20; // ecx@37
+  signed int v22; // ebx@42
+  unsigned int v23; // esi@43
+  int v24; // edx@44
+  int v25; // eax@44
+  int v26; // [sp+Ch] [bp-38h]@7
+  int v27; // [sp+10h] [bp-34h]@21
+  int v28; // [sp+18h] [bp-2Ch]@21
+  int v29; // [sp+1Ch] [bp-28h]@2
+  unsigned int v30; // [sp+20h] [bp-24h]@8
+  signed int v31; // [sp+24h] [bp-20h]@1
+  signed int v32; // [sp+28h] [bp-1Ch]@1
+  int v33; // [sp+2Ch] [bp-18h]@7
+  bool v34; // [sp+30h] [bp-14h]@21
+  bool v35; // [sp+34h] [bp-10h]@23
+  signed int v36; // [sp+38h] [bp-Ch]@17
+  signed int v37; // [sp+38h] [bp-Ch]@21
+  signed int v38; // [sp+38h] [bp-Ch]@42
+  signed int v39; // [sp+3Ch] [bp-8h]@1
+  signed int v40; // [sp+40h] [bp-4h]@1
+
+  dword_720ED0[0] = -1;
+  dword_720E80[0] = -1;
+  v4 = a1;
+  v5 = 0;
+  v40 = a2;
+  v31 = v4;
+  v39 = 1;
+  dword_720F20[0] = 10000;
+  v32 = 0;
+  if ( (signed int)pOutdoor->uNumBModels > 0 )
+  {
+    v29 = 0;
+    do
+    {
+      v6 = &pOutdoor->pBModels[v29];
+      if ( v4 <= pOutdoor->pBModels[v29].sMaxX )
+      {
+        if ( v4 >= v6->sMinX )
+        {
+          if ( v40 <= v6->sMaxY )
+          {
+            if ( v40 >= v6->sMinY )
+            {
+              v33 = v5;
+              v26 = v6->uNumFaces;
+              if ( (signed int)v6->uNumFaces > (signed int)v5 )
+              {
+                v30 = v5;
+                while ( 1 )
+                {
+                  v7 = (ODMFace *)((char *)v6->pFaces + v30);
+                  v8 = v7->uPolygonType;
+                  if ( (v8 == 5 || v8 == 6)
+                    && !(BYTE3(v7->uAttributes) & 0x20)
+                    && v4 <= v7->pBoundingBox.x2
+                    && v4 >= v7->pBoundingBox.x1
+                    && v40 <= v7->pBoundingBox.y2
+                    && v40 >= v7->pBoundingBox.y1 )
+                  {
+                    v36 = v5;
+                    if ( v7->uNumVertices )
+                    {
+                      v9 = v7->pXInterceptDisplacements;
+                      do
+                      {
+                        v10 = 2 * v36;
+                        word_720DB0_xs[2 * v36] = *v9 + LOWORD(v6->pVertices.pVertices[*(v9 - 60)].x);
+                        word_720CE0_ys[2 * v36] = v9[20] + LOWORD(v6->pVertices.pVertices[*(v9 - 60)].y);
+                        word_720DB0_xs[2 * v36++ + 1] = *v9 + LOWORD(v6->pVertices.pVertices[*(v9 - 59)].x);
+                        word_720CE0_ys[v10 + 1] = v9[20] + LOWORD(v6->pVertices.pVertices[*(v9 - 59)].y);
+                        ++v9;
+                      }
+                      while ( v36 < v7->uNumVertices );
+                      v4 = v31;
+                    }
+                    v27 = 2 * v7->uNumVertices;
+                    word_720DB0_xs[2 * v7->uNumVertices] = word_720DB0_xs[0];
+                    word_720CE0_ys[v27] = word_720CE0_ys[0];
+                    v11 = 0;
+                    v34 = word_720CE0_ys[0] >= v40;
+                    v37 = 0;
+                    v28 = 0;
+                    if ( v27 > 0 )
+                    {
+                      do
+                      {
+                        if ( v37 >= 2 )
+                          break;
+                        v12 = v11;
+                        v4 = v31;
+                        v35 = word_720CE0_ys[v12 + 1] >= v40;
+                        if ( v34 != v35 )
+                        {
+                          v13 = word_720DB0_xs[v12 + 1] >= v31 ? 0 : 2;
+                          v14 = v13 | word_720DB0_xs[v12] < v31;
+                          if ( v14 != 3 )
+                          {
+                            if ( !v14
+                              || (v15 = word_720CE0_ys[v12],
+                                  v16 = word_720CE0_ys[v12 + 1] - v15,
+                                  v17 = v40 - v15,
+                                  LODWORD(v18) = v17 << 16,
+                                  HIDWORD(v18) = v17 >> 16,
+                                  (signed int)(((unsigned __int64)(((signed int)word_720DB0_xs[v12 + 1]
+                                                                  - (signed int)word_720DB0_xs[v12])
+                                                                 * v18
+                                                                 / v16) >> 16)
+                                             + word_720DB0_xs[v12]) >= v31) )
+                              ++v37;
+                          }
+                        }
+                        v11 = v28 + 1;
+                        v34 = v35;
+                        ++v28;
+                      }
+                      while ( v28 < v27 );
+                      if ( v37 == 1 )
+                      {
+                        if ( v39 >= 20 )
+                          break;
+                        if ( v7->uPolygonType == 5 )
+                          v19 = v6->pVertices.pVertices[v7->pVertexIDs[0]].z;
+                        else
+                          v19 = ((unsigned __int64)(v7->zCalc1 * (signed __int64)v4) >> 16)
+                              + ((unsigned __int64)(v7->zCalc2 * (signed __int64)v40) >> 16)
+                              + HIWORD(v7->zCalc3);
+                        v20 = v39++;
+                        dword_720F20[v20] = v19;
+                        dword_720ED0[v20] = v32;
+                        dword_720E80[v20] = v33;
+                      }
+                    }
+                  }
+                  ++v33;
+                  v30 += 308;
+                  if ( v33 >= v26 )
+                    break;
+                  v5 = 0;
+                }
+              }
+            }
+          }
+        }
+      }
+      ++v32;
+      ++v29;
+      v5 = 0;
+    }
+    while ( v32 < (signed int)pOutdoor->uNumBModels );
+    if ( !v39 )
+    {
+      *(int *)a4 = 0;
+      return dword_720F20[0];
+    }
+  }
+  v22 = 0;
+  v38 = v5;
+  if ( v39 <= (signed int)v5 )
+    goto LABEL_54;
+  v23 = 0;
+  do
+  {
+    v24 = dword_720F20[v5 / 4];
+    v25 = *(int *)((char *)dword_720F20 + v23);
+    if ( v24 == v25 )
+      goto LABEL_50;
+    if ( v25 > a3 + 15 )
+    {
+      if ( v24 >= v25 )
+        goto LABEL_51;
+LABEL_50:
+      v22 = v38;
+      v23 = v5;
+      goto LABEL_51;
+    }
+    if ( v24 > v25 && v24 <= a3 + 15 )
+      goto LABEL_50;
+LABEL_51:
+    ++v38;
+    v5 += 4;
+  }
+  while ( v38 < v39 );
+  if ( v22 )
+  {
+    *(int *)a4 = dword_720E80[v22] | (dword_720ED0[v22] << 6);
+    return dword_720F20[v22];
+  }
+LABEL_54:
+  *(int *)a4 = 0;
+  return dword_720F20[v22];
+}
+
+//----- (0046DCC8) --------------------------------------------------------
+signed __int64 __fastcall _46DCC8_get_gravity_direction_outdoor(int a1, int a2, Vec3_int_ *a3)
+{
+  int v3; // ebx@1
+  int v4; // ST4C_4@1
+  unsigned int v5; // ST54_4@1
+  unsigned int v6; // edi@1
+  unsigned int v7; // ST50_4@1
+  int v8; // edi@1
+  int v9; // esi@1
+  int v10; // ebx@1
+  int v11; // ecx@2
+  int v12; // eax@2
+  int v13; // edx@2
+  int v14; // ebx@2
+  double v15; // st7@4
+  double v16; // st6@4
+  double v17; // st5@4
+  float v18; // ST44_4@4
+  float v19; // ST54_4@4
+  double v20; // st4@4
+  double v21; // st5@4
+  float v22; // ST44_4@6
+  double v23; // st7@4
+  double v24; // st7@6
+  signed __int64 result; // qax@6
+  int v26; // [sp+14h] [bp-44h]@1
+  int v27; // [sp+18h] [bp-40h]@1
+  int v28; // [sp+20h] [bp-38h]@1
+  int v29; // [sp+24h] [bp-34h]@1
+  int v30; // [sp+28h] [bp-30h]@1
+  int v31; // [sp+2Ch] [bp-2Ch]@1
+  int v32; // [sp+30h] [bp-28h]@1
+  int v33; // [sp+34h] [bp-24h]@1
+  int v34; // [sp+38h] [bp-20h]@1
+  int v35; // [sp+3Ch] [bp-1Ch]@1
+  int v36; // [sp+40h] [bp-18h]@1
+  int v37; // [sp+4Ch] [bp-Ch]@2
+  float v38; // [sp+4Ch] [bp-Ch]@4
+  int v39; // [sp+50h] [bp-8h]@2
+  float v40; // [sp+50h] [bp-8h]@4
+  int v41; // [sp+54h] [bp-4h]@2
+
+  v3 = a1;
+  v4 = a2;
+  v5 = WorldPosToGridCellX(a1);
+  v6 = WorldPosToGridCellZ(v4) - 1;
+  v33 = GridCellToWorldPosX(v5);
+  v34 = GridCellToWorldPosX(v5 + 1);
+  v35 = GridCellToWorldPosX(v5 + 1);
+  v36 = GridCellToWorldPosX(v5);
+  v29 = GridCellToWorldPosZ(v6);
+  v30 = GridCellToWorldPosZ(v6);
+  v7 = v6 + 1;
+  v31 = GridCellToWorldPosZ(v6 + 1);
+  v32 = GridCellToWorldPosZ(v6 + 1);
+  v26 = pOutdoor->DoGetHeightOnTerrain(v5, v6);
+  v27 = pOutdoor->DoGetHeightOnTerrain(v5 + 1, v6);
+  v8 = pOutdoor->DoGetHeightOnTerrain(v5 + 1, v6 + 1);
+  v28 = pOutdoor->DoGetHeightOnTerrain(v5, v7);
+  v9 = v29;
+  v10 = abs(v3 - v33);
+  if ( abs(v29 - v4) >= v10 )
+  {
+    v11 = v33;
+    v37 = v28;
+    v39 = v36;
+    v12 = v35;
+    v41 = v32;
+    v13 = v31;
+    v14 = v8;
+    v8 = v26;
+  }
+  else
+  {
+    v11 = v35;
+    v41 = v30;
+    v39 = v34;
+    v12 = v33;
+    v13 = v29;
+    v9 = v31;
+    v37 = v27;
+    v14 = v26;
+  }
+  v15 = (double)(v12 - v39);
+  v16 = (double)(v13 - v41);
+  v17 = (double)(v14 - v37);
+  v18 = (double)(v11 - v39);
+  v19 = (double)(v9 - v41);
+  v20 = (double)(v8 - v37);
+  v38 = v20 * v16 - v19 * v17;
+  v40 = v18 * v17 - v20 * v15;
+  v21 = v19 * v15 - v18 * v16;
+  v23 = sqrt(v21 * v21 + v40 * v40 + v38 * v38);
+  if ( v23 == 0.0 )
+  {
+    a3->y = 0;
+    a3->x = 0;
+    a3->z = 65536;
+  }
+  v24 = 1.0 / v23;
+  a3->x = (signed __int64)(v24 * v38 * 65536.0);
+  a3->y = (signed __int64)(v24 * v40 * 65536.0);
+  v22 = v21;
+  result = (signed __int64)(v24 * v22 * 65536.0);
+  a3->z = result;
+  return result;
+}
+// 47F44B: using guessed type int __stdcall WorldPosToGridCellX(int);
+// 47F458: using guessed type int __stdcall WorldPosToGridCellZ(int);
+// 47F469: using guessed type int __stdcall GridCellToWorldPosX(int);
+// 47F476: using guessed type int __stdcall GridCellToWorldPosZ(int);
+
+//----- (0046DEF2) --------------------------------------------------------
+unsigned int __fastcall sub_46DEF2(signed int a2, unsigned int uLayingItemID)
+{
+  unsigned int result; // eax@1
+
+  result = uLayingItemID;
+  if ( pObjectList->pObjects[pLayingItems[uLayingItemID].uObjectDescID].uFlags & 0x10 )
+    result = _46BFFA_check_object_intercept(uLayingItemID, a2);
+  return result;
+}
+
+//----- (0046DF1A) --------------------------------------------------------
+signed int __fastcall _46DF1A_collide_against_actor(int a1, int a2)
+{
+  Actor *v2; // edi@1
+  unsigned __int16 v3; // ax@1
+  int v4; // esi@6
+  int v5; // ecx@8
+  int v6; // eax@10
+  int v7; // edx@12
+  int v8; // ecx@14
+  int v9; // eax@14
+  int v10; // ebx@14
+  int v11; // esi@14
+  int v12; // ebx@15
+  int v13; // ebx@17
+  unsigned int v14; // eax@20
+  signed int result; // eax@21
+  int v16; // [sp+Ch] [bp-10h]@1
+  int v17; // [sp+10h] [bp-Ch]@14
+  int v18; // [sp+14h] [bp-8h]@14
+  int v19; // [sp+18h] [bp-4h]@14
+
+  v16 = a1;
+  v2 = &pActors[a1];
+  v3 = v2->uAIState;
+  if ( v3 == 11 || v3 == 4 || v3 == 19 || v3 == 5 || v3 == 17 )
+    goto LABEL_25;
+  v4 = v2->uActorRadius;
+  if ( a2 )
+    v4 = a2;
+  v5 = v2->vPosition.x;
+  if ( stru_721530.sMaxX > v5 + v4
+    || stru_721530.sMinX < v5 - v4
+    || (v6 = v2->vPosition.y, stru_721530.sMaxY > v6 + v4)
+    || stru_721530.sMinY < v6 - v4
+    || (v7 = v2->vPosition.z, stru_721530.sMaxZ > v7 + v2->uActorHeight)
+    || stru_721530.sMinZ < v7
+    || (v8 = v5 - stru_721530.normal.x,
+        v9 = v6 - stru_721530.normal.y,
+        v10 = stru_721530.prolly_normal_d + v4,
+        v17 = stru_721530.prolly_normal_d + v4,
+        v11 = (v8 * stru_721530.field_58.y - v9 * stru_721530.field_58.x) >> 16,
+        v18 = v8,
+        v19 = v9,
+        abs((v8 * stru_721530.field_58.y - v9 * stru_721530.field_58.x) >> 16) > v10)
+    || (v12 = (v18 * stru_721530.field_58.x + v19 * stru_721530.field_58.y) >> 16, v12 <= 0)
+    || (signed int)(((unsigned __int64)(stru_721530.field_58.z * (signed __int64)v12) >> 16) + stru_721530.normal.z) < v2->vPosition.z )
+  {
+LABEL_25:
+    result = 0;
+  }
+  else
+  {
+    v13 = v12 - sub_452A9E(v17 * v17 - v11 * v11);
+    if ( v13 < 0 )
+      v13 = 0;
+    if ( v13 < stru_721530.field_7C )
+    {
+      stru_721530.field_7C = v13;
+      v14 = 8 * v16;
+      LOBYTE(v14) = 8 * v16 | 3;
+      stru_721530.uFaceID = v14;
+    }
+    result = 1;
+  }
+  return result;
+}
+// 46DF1A: using guessed type int __fastcall 46DF1A_collide_against_actor(int, int);
+
+//----- (0046E0B2) --------------------------------------------------------
+void __cdecl _46E0B2_collide_against_decorations()
+{
+  BLVSector *v0; // ebp@1
+  LevelDecoration *v1; // edi@2
+  DecorationDesc *v2; // esi@3
+  int v3; // edx@4
+  int v4; // eax@4
+  int v5; // ecx@6
+  int v6; // ebx@8
+  int v7; // esi@8
+  int v8; // ebx@10
+  int v9; // esi@11
+  int v10; // edi@12
+  int v11; // eax@12
+  int v12; // esi@14
+  unsigned int v13; // eax@17
+  signed int i; // [sp+4h] [bp-14h]@1
+  int v15; // [sp+8h] [bp-10h]@10
+  int v16; // [sp+Ch] [bp-Ch]@10
+  int v17; // [sp+10h] [bp-8h]@10
+  int v18; // [sp+14h] [bp-4h]@8
+
+  v0 = &pIndoor->pSectors[stru_721530.uSectorID];
+  for ( i = 0; i < v0->uNumDecorations; ++i )
+  {
+    v1 = &pLevelDecorations[v0->pDecorationIDs[i]];
+    if ( !(v1->field_2 & 0x20) )
+    {
+      v2 = &pDecorationList->pDecorations[v1->uDecorationDescID];
+      if ( !(v2->uFlags & 1) )
+      {
+        v3 = v2->uRadius;
+        v4 = v1->vPosition.x;
+        if ( stru_721530.sMaxX <= v4 + v3 )
+        {
+          if ( stru_721530.sMinX >= v4 - v3 )
+          {
+            v5 = v1->vPosition.y;
+            if ( stru_721530.sMaxY <= v5 + v3 )
+            {
+              if ( stru_721530.sMinY >= v5 - v3 )
+              {
+                v6 = v2->uDecorationHeight;
+                v7 = v1->vPosition.z;
+                v18 = v6;
+                if ( stru_721530.sMaxZ <= v7 + v6 )
+                {
+                  if ( stru_721530.sMinZ >= v7 )
+                  {
+                    v16 = v4 - stru_721530.normal.x;
+                    v15 = v5 - stru_721530.normal.y;
+                    v8 = stru_721530.prolly_normal_d + v3;
+                    v17 = ((v4 - stru_721530.normal.x) * stru_721530.field_58.y
+                         - (v5 - stru_721530.normal.y) * stru_721530.field_58.x) >> 16;
+                    if ( abs(v17) <= stru_721530.prolly_normal_d + v3 )
+                    {
+                      v9 = (v16 * stru_721530.field_58.x + v15 * stru_721530.field_58.y) >> 16;
+                      if ( v9 > 0 )
+                      {
+                        v10 = v1->vPosition.z;
+                        v11 = stru_721530.normal.z
+                            + ((unsigned __int64)(stru_721530.field_58.z * (signed __int64)v9) >> 16);
+                        if ( v11 >= v10 )
+                        {
+                          if ( v11 <= v18 + v10 )
+                          {
+                            v12 = v9 - sub_452A9E(v8 * v8 - v17 * v17);
+                            if ( v12 < 0 )
+                              v12 = 0;
+                            if ( v12 < stru_721530.field_7C )
+                            {
+                              stru_721530.field_7C = v12;
+                              v13 = 8 * v0->pDecorationIDs[i];
+                              LOBYTE(v13) = v13 | 5;
+                              stru_721530.uFaceID = v13;
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+//----- (0046E26D) --------------------------------------------------------
+void __fastcall _46E26D_collide_against_sprites(signed int a1, signed int a2)
+{
+  int v2; // edx@5
+  unsigned __int16 *v3; // eax@5
+  unsigned __int16 v4; // ax@6
+  LevelDecoration *v5; // edi@7
+  DecorationDesc *v6; // esi@8
+  int v7; // edx@9
+  int v8; // eax@9
+  int v9; // ecx@11
+  int v10; // ebx@13
+  int v11; // esi@13
+  int v12; // ebp@15
+  int v13; // ebx@15
+  int v14; // esi@16
+  int v15; // edi@17
+  int v16; // eax@17
+  int v17; // esi@19
+  char v18; // zf@23
+  int v19; // [sp+0h] [bp-10h]@15
+  unsigned __int16 *v20; // [sp+4h] [bp-Ch]@5
+  int v21; // [sp+8h] [bp-8h]@15
+  int v22; // [sp+Ch] [bp-4h]@13
+
+  if ( a1 >= 0 )
+  {
+    if ( a1 <= 127 )
+    {
+      if ( a2 >= 0 )
+      {
+        if ( a2 <= 127 )
+        {
+          v2 = a1 + (a2 << 7);
+          v3 = &pOutdoor->pFaceIDLIST[pOutdoor->pOMAP[v2]];
+          v20 = &pOutdoor->pFaceIDLIST[pOutdoor->pOMAP[v2]];
+          if ( v3 )
+          {
+            do
+            {
+              v4 = *v3;
+              if ( (v4 & 7) == 5 )
+              {
+                v5 = &pLevelDecorations[(signed __int16)v4 >> 3];
+                if ( !(v5->field_2 & 0x20) )
+                {
+                  v6 = &pDecorationList->pDecorations[v5->uDecorationDescID];
+                  if ( !(v6->uFlags & 1) )
+                  {
+                    v7 = v6->uRadius;
+                    v8 = v5->vPosition.x;
+                    if ( stru_721530.sMaxX <= v8 + v7 )
+                    {
+                      if ( stru_721530.sMinX >= v8 - v7 )
+                      {
+                        v9 = v5->vPosition.y;
+                        if ( stru_721530.sMaxY <= v9 + v7 )
+                        {
+                          if ( stru_721530.sMinY >= v9 - v7 )
+                          {
+                            v10 = v6->uDecorationHeight;
+                            v11 = v5->vPosition.z;
+                            v22 = v10;
+                            if ( stru_721530.sMaxZ <= v11 + v10 )
+                            {
+                              if ( stru_721530.sMinZ >= v11 )
+                              {
+                                v12 = v8 - stru_721530.normal.x;
+                                v19 = v9 - stru_721530.normal.y;
+                                v13 = stru_721530.prolly_normal_d + v7;
+                                v21 = ((v8 - stru_721530.normal.x) * stru_721530.field_58.y
+                                     - (v9 - stru_721530.normal.y) * stru_721530.field_58.x) >> 16;
+                                if ( abs(v21) <= stru_721530.prolly_normal_d + v7 )
+                                {
+                                  v14 = (v12 * stru_721530.field_58.x + v19 * stru_721530.field_58.y) >> 16;
+                                  if ( v14 > 0 )
+                                  {
+                                    v15 = v5->vPosition.z;
+                                    v16 = stru_721530.normal.z
+                                        + ((unsigned __int64)(stru_721530.field_58.z * (signed __int64)v14) >> 16);
+                                    if ( v16 >= v15 )
+                                    {
+                                      if ( v16 <= v22 + v15 )
+                                      {
+                                        v17 = v14 - sub_452A9E(v13 * v13 - v21 * v21);
+                                        if ( v17 < 0 )
+                                          v17 = 0;
+                                        if ( v17 < stru_721530.field_7C )
+                                        {
+                                          stru_721530.field_7C = v17;
+                                          stru_721530.uFaceID = (signed __int16)*v20;
+                                        }
+                                      }
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+              v3 = v20 + 1;
+              v18 = *v20 == 0;
+              ++v20;
+            }
+            while ( !v18 );
+          }
+        }
+      }
+    }
+  }
+}
+
+//----- (00486F92) --------------------------------------------------------
+void __cdecl sr_sub_486F92_MessWithEdgesAndSpans()
+{
+  Span *v0; // ebx@1
+  int v1; // eax@2
+  Edge *v2; // ecx@3
+  Edge *v3; // edx@3
+  Edge *v4; // esi@6
+  Edge *v5; // eax@7
+  Edge *v6; // ecx@8
+  Surf *v7; // esi@11
+  double v8; // st7@13
+  Surf *v9; // edi@13
+  double v10; // st6@13
+  double v11; // st7@14
+  signed __int64 v12; // qax@14
+  stru148 *v13; // eax@15
+  Span *v14; // ecx@17
+  double v15; // st7@28
+  signed __int64 v16; // qax@28
+  stru148 *v17; // eax@29
+  Span *v18; // ecx@31
+  Edge *i; // eax@40
+  Edge *v20; // ecx@43
+  Edge *v21; // esi@44
+  double v22; // st7@45
+  Edge *v23; // edx@48
+  unsigned int v24; // [sp+10h] [bp-10h]@2
+  float v25; // [sp+14h] [bp-Ch]@3
+  Edge *v26; // [sp+18h] [bp-8h]@8
+  unsigned int v27; // [sp+1Ch] [bp-4h]@1
+
+  v0 = pSpans;
+  stru_80C9D8.pSurf = &stru_80C980;
+  stru_80C9D8.field_0 = (double)(signed int)pViewport->uViewportX;
+  stru_80C9A4.pSurf = &stru_80C980;
+  stru_80C980.pPrev = &stru_80C980;
+  stru_80C980.pNext = &stru_80C980;
+  stru_80C9A4.field_0 = (double)(signed int)pViewport->uViewportZ;
+  stru_80C980.field_8 = 0.0;
+  stru_80C980.field_4 = 0.0;
+  stru_80C9D8.pNext = &stru_80C9A4;
+  stru_80C9D8.pPrev = 0;
+  stru_80C9D8.field_8 = 1;
+  stru_80C9A4.pNext = 0;
+  stru_80C9A4.pPrev = &stru_80C9D8;
+  stru_80C9A4.field_8 = 0;
+  LODWORD(stru_80C980.field_0) = 0xC97423F0u;
+  v27 = pViewport->uViewportY;
+  if ( (signed int)pViewport->uViewportY > (signed int)pViewport->uViewportW )
+  {
+LABEL_51:
+    v0->field_8 = -1;
+  }
+  else
+  {
+    v1 = 52 * pViewport->uViewportY;
+    v24 = 52 * pViewport->uViewportY;
+    while ( 1 )
+    {
+      v2 = *(Edge **)((char *)&pNewEdges->pNext + v1);
+      v3 = &stru_80C9D8;
+      v25 = (double)(signed int)v27;
+      if ( v2 != &defaultEdge )
+      {
+        do
+        {
+          while ( 1 )
+          {
+            v4 = v3->pNext;
+            if ( v2->field_0 <= (double)v4->field_0 )
+              break;
+            v3 = v3->pNext;
+          }
+          v5 = v2->pNext;
+          v2->pNext = v4;
+          v2->pPrev = v3;
+          v3->pNext->pPrev = v2;
+          v3->pNext = v2;
+          v3 = v2;
+          v2 = v5;
+        }
+        while ( v5 != &defaultEdge );
+      }
+      v6 = stru_80C9D8.pNext;
+      stru_80C980.field_20 = 0;
+      stru_80C980.field_22 = 1;
+      v26 = stru_80C9D8.pNext;
+      if ( stru_80C9D8.pNext )
+      {
+        while ( 1 )
+        {
+          v7 = v6->pSurf;
+          if ( v6->field_8 )
+          {
+            ++v7->field_22;
+            if ( v7->field_22 == 1 )
+            {
+              v8 = v6->field_0 + 2.0;
+              v9 = stru_80C980.pNext;
+              v10 = (v8 - v7->field_C) * v7->field_4 + (v25 - v7->field_10) * v7->field_8 + v7->field_0;
+              if ( v10 <= (v8 - stru_80C980.pNext->field_C) * stru_80C980.pNext->field_4
+                        + (v25 - stru_80C980.pNext->field_10) * stru_80C980.pNext->field_8
+                        + stru_80C980.pNext->field_0 )
+              {
+                do
+                  v9 = v9->pNext;
+                while ( v10 <= (v8 - v9->field_C) * v9->field_4 + (v25 - v9->field_10) * v9->field_8 + v9->field_0 );
+                v7->pNext = v9;
+                v7->pPrev = v9->pPrev;
+                v9->pPrev->pNext = v7;
+                v9->pPrev = v7;
+              }
+              else
+              {
+                v11 = v6->field_0 + 0.5;
+                v12 = (signed __int64)(v11 - (double)stru_80C980.pNext->field_20);
+                v0->field_C = v12;
+                if ( (signed __int16)v12 > 0 )
+                {
+                  v0->field_A = v27;
+                  v0->field_8 = v9->field_20;
+                  v13 = v9->pParent;
+                  v0->pParent = v13;
+                  if ( v13 )
+                  {
+                    if ( v13->prolly_head )
+                    {
+                      v14 = v13->prolly_tail;
+                      if ( !v14 )
+                        return;
+                      v14->pNext = v0;
+                    }
+                    else
+                    {
+                      v13->prolly_head = v0;
+                    }
+                    v13->prolly_tail = v0;
+                  }
+                  if ( (signed int)pOutdoorCamera->uNumSpans >= 12499 )
+                    return;
+                  ++v0;
+                  ++pOutdoorCamera->uNumSpans;
+                }
+                v6 = v26;
+                v7->field_20 = (signed __int64)v11;
+                v7->pNext = v9;
+                v9->pPrev = v7;
+                stru_80C980.pNext = v7;
+                v7->pPrev = &stru_80C980;
+              }
+            }
+          }
+          else
+          {
+            --v7->field_22;
+            if ( !v7->field_22 )
+            {
+              if ( stru_80C980.pNext == v7 )
+              {
+                v15 = v6->field_0 + 0.5;
+                v16 = (signed __int64)(v15 - (double)v7->field_20);
+                v0->field_C = v16;
+                if ( (signed __int16)v16 > 0 )
+                {
+                  v0->field_A = v27;
+                  v0->field_8 = v7->field_20;
+                  v17 = v7->pParent;
+                  v0->pParent = v17;
+                  if ( v17 )
+                  {
+                    if ( v17->prolly_head )
+                    {
+                      v18 = v17->prolly_tail;
+                      if ( !v18 )
+                        return;
+                      v18->pNext = v0;
+                    }
+                    else
+                    {
+                      v17->prolly_head = v0;
+                    }
+                    v17->prolly_tail = v0;
+                  }
+                  if ( (signed int)pOutdoorCamera->uNumSpans >= 12499 )
+                    return;
+                  ++v0;
+                  ++pOutdoorCamera->uNumSpans;
+                }
+                v7->pNext->field_20 = (signed __int64)v15;
+                v6 = v26;
+              }
+              v7->pNext->pPrev = v7->pPrev;
+              v7->pPrev->pNext = v7->pNext;
+            }
+          }
+          v26 = v6->pNext;
+          if ( !v26 )
+            break;
+          v6 = v6->pNext;
+        }
+      }
+      for ( i = ptr_80CA10[v27]; i; i = i->ptr_18 )
+      {
+        i->pPrev->pNext = i->pNext;
+        i->pNext->pPrev = i->pPrev;
+      }
+      v20 = stru_80C9D8.pNext;
+      if ( stru_80C9D8.pNext != &stru_80C9A4 )
+        break;
+LABEL_50:
+      ++v27;
+      v1 = v24 + 52;
+      v24 += 52;
+      if ( (signed int)v27 > (signed int)pViewport->uViewportW )
+        goto LABEL_51;
+    }
+    while ( 1 )
+    {
+      v21 = v20->pNext;
+      if ( !v21 )
+        break;
+      v22 = v20->field_4 + v20->field_0;
+      v20->field_0 = v22;
+      if ( v22 < stru_80C9D8.field_0 )
+        v20->field_0 = stru_80C9D8.field_0 + 0.0000001;
+      while ( 1 )
+      {
+        v23 = v20->pPrev;
+        if ( v20->field_0 >= (double)v23->field_0 )
+          break;
+        v23->pNext = v20->pNext;
+        v20->pNext->pPrev = v23;
+        v23->pPrev->pNext = v20;
+        v20->pPrev = v23->pPrev;
+        v20->pNext = v23;
+        v23->pPrev = v20;
+      }
+      v20 = v21;
+      if ( v21 == &stru_80C9A4 )
+        goto LABEL_50;
+    }
+  }
+}
+// 4EC3EC: using guessed type Edge defaultEdge;
+
+
+
+//----- (00487355) --------------------------------------------------------
+bool OutdoorCamera::_487355()
+{
+  int v0; // esi@1
+  stru148 *v1; // edi@2
+  bool result; // eax@3
+
+  v0 = 0;
+  if ( pOutdoorCamera->numStru148s > 0 )
+  {
+    v1 = array_77EC08;
+    do
+    {
+      result = pGame->pLightmapBuilder->_45D3C7(v1);
+      ++v0;
+      ++v1;
+    }
+    while ( v0 < pOutdoorCamera->numStru148s );
+  }
+  return result;
+}
+
+
+
+//----- (00487DA9) --------------------------------------------------------
+void __cdecl sub_487DA9()
+{
+  char *v0; // eax@1
+
+  v0 = &array_77EC08[0].field_108;
+  do
+  {
+    *v0 = 0;
+    v0 += 268;
+  }
+  while ( (signed int)v0 < (signed int)&pVerticesSR_801A10[4] );
+}
+
+//----- (00487DBE) --------------------------------------------------------
+void Software_ResetNewEdges()
+{
+  int v0; // ecx@1
+  Edge **v1; // eax@1
+  signed int v2; // eax@3
+
+  v0 = 0;
+  v1 = ptr_80CA10;
+  do
+  {
+    ++v0;
+    *((int *)&pNewEdges[v0] - 9) = (int)&defaultEdge;
+    *v1 = 0;
+    ++v1;
+  }
+  while ( (signed int)v1 < (signed int)&unk_80D190 );
+  v2 = 2000;
+  do
+  {
+    pSurfs->field_22 = 0;
+    --v2;
+  }
+  while ( v2 );
+}
+// 4EC3EC: using guessed type Edge defaultEdge;
+
+
+
+
+//----- (00487E1D) --------------------------------------------------------
+TileTable::~TileTable()
+{
+  if ( this->pTiles )
+  {
+    pAllocator->FreeChunk(this->pTiles);
+    pTiles = nullptr;
+  }
+  uNumTiles = 0;
+}
+
+//----- (00487E3B) --------------------------------------------------------
+TileDesc *TileTable::GetTileById(unsigned int uTileID)
+{
+  TileDesc *result; // eax@3
+
+  if ( (uTileID & 0x80000000u) != 0 || (signed int)uTileID > (signed int)(this->uNumTiles - 1) )
+    result = this->pTiles;
+  else
+    result = &this->pTiles[uTileID];
+  return result;
+}
+
+//----- (00487E58) --------------------------------------------------------
+void TileTable::InitializeTileset(int uTerrainType)
+{
+  TileTable *v2; // edi@1
+  int v3; // ebx@1
+  TileDesc *v4; // eax@2
+  signed int i; // [sp+8h] [bp-4h]@1
+
+  v2 = this;
+  v3 = 0;
+  for ( i = 0; i < (signed int)v2->uNumTiles; ++v3 )
+  {
+    v4 = &v2->pTiles[v3];
+    if ( uTerrainType == v4->uTerrainType && v4->pTileName[0] )
+    {
+      v2->pTiles[v3].uBitmapID = pBitmaps_LOD->LoadTexture(v4->pTileName);
+      if ( v2->pTiles[v3].uBitmapID != -1 )
+        pBitmaps_LOD->pTextures[v2->pTiles[v3].uBitmapID].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[v2->pTiles[v3].uBitmapID].palette_id1);
+    }
+    ++i;
+  }
+}
+
+//----- (00487ED6) --------------------------------------------------------
+int TileTable::method_487ED6(signed int a1, int a2)
+{
+  int v3; // esi@1
+  TileTable *v4; // edi@1
+  int v5; // edx@3
+  int v6; // edx@11
+  unsigned int v8; // [sp-4h] [bp-10h]@4
+
+  v3 = 0;
+  v4 = this;
+  if ( a1 > 8 )
+  {
+    v8 = 0;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( a2 || (v5 = rand() % 50, v5 < 20) )
+  {
+    v8 = 0;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v5 < 30 )
+  {
+    v8 = 1;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v5 < 40 )
+  {
+    v8 = 2;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v5 < 48 )
+  {
+    v8 = 3;
+    return v4->GetTileId(a1, v8);
+  }
+  v6 = rand() % 8;
+  if ( !v6 )
+  {
+    v8 = 4;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v6 == 1 )
+  {
+    v8 = 5;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v6 == 2 )
+  {
+    v8 = 6;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v6 == 3 )
+  {
+    v8 = 7;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v6 == 4 )
+  {
+    v8 = 8;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v6 == 5 )
+  {
+    v8 = 9;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v6 == 6 )
+  {
+    v8 = 10;
+    return v4->GetTileId(a1, v8);
+  }
+  if ( v6 == 7 )
+  {
+    v8 = 11;
+    return v4->GetTileId(a1, v8);
+  }
+  return v3;
+}
+
+//----- (00487F84) --------------------------------------------------------
+unsigned int TileTable::GetTileId(unsigned int uTerrainType, unsigned int uSection)
+{
+  unsigned int v3; // edx@1
+  unsigned int result; // eax@1
+  unsigned __int16 *v5; // ecx@2
+
+  v3 = this->uNumTiles;
+  result = 0;
+  if ( (signed int)this->uNumTiles <= 0 )
+  {
+LABEL_6:
+    result = 0;
+  }
+  else
+  {
+    v5 = &this->pTiles->uSection;
+    while ( (signed __int16)*(v5 - 1) != uTerrainType || (signed __int16)*v5 != uSection )
+    {
+      ++result;
+      v5 += 13;
+      if ( (signed int)result >= (signed int)v3 )
+        goto LABEL_6;
+    }
+  }
+  return result;
+}
+
+//----- (00487FB4) --------------------------------------------------------
+void TileTable::ToFile()
+{
+  TileTable *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  auto Str = this;
+
+  v1 = Str;
+  v2 = fopen("data\\dtile.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dtile.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pTiles, 0x1Au, v1->uNumTiles, v3);
+  fclose(v3);
+}
+
+//----- (00488000) --------------------------------------------------------
+void TileTable::FromFile(void *pSerialized)
+{
+  uNumTiles = *(int *)pSerialized;
+  pTiles = (TileDesc *)pAllocator->AllocNamedChunk(pTiles, 26 * uNumTiles, "Tile Descrip");
+  memcpy(pTiles, (char *)pSerialized + 4, 26 * uNumTiles);
+}
+
+//----- (00488047) --------------------------------------------------------
+int TileTable::FromFileTxt(const char *pFilename)
+{
+  TileTable *v2; // ebp@1
+  FILE *v3; // eax@1
+  unsigned int v4; // ebx@3
+  void *v5; // eax@9
+  unsigned __int16 v6; // ax@14
+  const char *v7; // ST14_4@14
+  unsigned __int16 v8; // ax@14
+  const char *v9; // esi@14
+  int v10; // eax@17
+  int v11; // eax@20
+  int v12; // eax@22
+  int v13; // eax@24
+  int v14; // eax@26
+  int v15; // eax@28
+  int v16; // eax@30
+  int v17; // eax@32
+  int v18; // eax@34
+  int v19; // eax@36
+  int v20; // eax@38
+  int v21; // eax@40
+  int v22; // eax@42
+  int v23; // eax@44
+  int v24; // eax@46
+  int v25; // eax@48
+  int v26; // eax@50
+  int v27; // eax@52
+  int v28; // eax@54
+  int v29; // eax@56
+  int v30; // eax@58
+  int v31; // eax@60
+  int v32; // eax@62
+  int v33; // eax@64
+  int v34; // eax@66
+  const char *v35; // esi@67
+  int v36; // eax@70
+  int v37; // eax@73
+  int v38; // eax@75
+  int v39; // eax@77
+  int v40; // eax@79
+  int v41; // eax@81
+  int v42; // eax@83
+  int v43; // eax@85
+  int v44; // eax@87
+  int v45; // eax@89
+  int v46; // eax@91
+  int v47; // eax@93
+  int v48; // eax@108
+  int v49; // eax@110
+  int v50; // eax@112
+  int v51; // eax@114
+  int v52; // eax@116
+  int v53; // eax@118
+  int v54; // eax@120
+  int v55; // eax@122
+  int v56; // eax@124
+  int v57; // eax@126
+  int v58; // eax@128
+  int v59; // eax@130
+  int v60; // eax@132
+  int v61; // eax@134
+  int v62; // eax@136
+  int v63; // eax@138
+  int v64; // eax@140
+  int v65; // eax@142
+  int v66; // eax@144
+  int v67; // eax@146
+  int v68; // eax@148
+  int v69; // eax@150
+  int v70; // eax@151
+  int j; // edi@152
+  const char *v72; // esi@153
+  int v73; // eax@154
+  int v74; // eax@156
+  int v75; // eax@160
+  int v76; // eax@162
+  int v77; // eax@164
+  int v78; // eax@166
+  int v79; // eax@168
+  int v80; // eax@170
+  FILE *i; // [sp-10h] [bp-304h]@3
+  FILE *File; // [sp+4h] [bp-2F0h]@1
+  FrameTableTxtLine v84; // [sp+8h] [bp-2ECh]@4
+  FrameTableTxtLine v85; // [sp+84h] [bp-270h]@4
+  char Buf; // [sp+100h] [bp-1F4h]@4
+
+  v2 = this;
+  v3 = fopen(pFilename, "r");
+  File = v3;
+  if ( !v3 )
+    Abortf("TileTable::load - Unable to open file: %s.");
+  v4 = 0;
+  for ( i = v3; fgets(&Buf, 490, i); i = File )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v84, texture_frame_table_txt_parser(&Buf, &v85), sizeof(v84));
+    if ( v84.field_0 && *v84.pProperties[0] != 47 )
+      ++v4;
+  }
+  v2->uNumTiles = v4;
+  v5 = pAllocator->AllocNamedChunk(v2->pTiles, 26 * v4, "Tile Descrip");
+  v2->pTiles = (TileDesc *)v5;
+  if ( !v5 )
+    Abortf("TileTable::Load - Out of Memory!");
+  memset(v5, 0, 26 * v2->uNumTiles);
+  v2->uNumTiles = 0;
+  fseek(File, 0, 0);
+  if ( fgets(&Buf, 490, File) )
+  {
+    while ( 1 )
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v84, texture_frame_table_txt_parser(&Buf, &v85), sizeof(v84));
+      if ( v84.field_0 )
+      {
+        if ( *v84.pProperties[0] != 47 )
+          break;
+      }
+LABEL_173:
+      if ( !fgets(&Buf, 490, File) )
+        goto LABEL_174;
+    }
+    strcpy(v2->pTiles[v2->uNumTiles].pTileName, v84.pProperties[0]);
+    v6 = atoi(v84.pProperties[1]);
+    v7 = v84.pProperties[2];
+    v2->pTiles[v2->uNumTiles].uTileID = v6;
+    v8 = atoi(v7);
+    v9 = v84.pProperties[3];
+    v2->pTiles[v2->uNumTiles].uBitmapID = v8;
+    v2->pTiles[v2->uNumTiles].uTerrainType = 0;
+    if ( _strcmpi(v9, "TTtype_NULL") )
+    {
+      if ( _strcmpi(v9, "TTtype_Start") )
+      {
+        if ( _strcmpi(v9, "TTtype_Grass") )
+        {
+          if ( _strcmpi(v9, "TTtype_Cracked") )
+          {
+            if ( _strcmpi(v9, "TTtype_Snow") )
+            {
+              if ( _strcmpi(v9, "TTtype_Sand") )
+              {
+                if ( _strcmpi(v9, "TTtype_Volcano") )
+                {
+                  if ( _strcmpi(v9, "TTtype_Dirt") )
+                  {
+                    if ( _strcmpi(v9, "TTtype_Water") )
+                    {
+                      if ( _strcmpi(v9, "TTtype_Tropical") )
+                      {
+                        if ( _strcmpi(v9, "TTtype_Swamp") )
+                        {
+                          if ( _strcmpi(v9, "TTtype_City") )
+                          {
+                            if ( _strcmpi(v9, "TTtype_RoadGrassCobble") )
+                            {
+                              if ( _strcmpi(v9, "TTtype_RoadGrassDirt") )
+                              {
+                                if ( _strcmpi(v9, "TTtype_RoadCrackedCobble") )
+                                {
+                                  if ( _strcmpi(v9, "TTtype_RoadCrackedDirt") )
+                                  {
+                                    if ( _strcmpi(v9, "TTtype_RoadSandCobble") )
+                                    {
+                                      if ( _strcmpi(v9, "TTtype_RoadSandDirt") )
+                                      {
+                                        if ( _strcmpi(v9, "TTtype_RoadVolcanoCobble") )
+                                        {
+                                          if ( _strcmpi(v9, "TTtype_RoadVolcanoDirt") )
+                                          {
+                                            if ( _strcmpi(v9, "TTtype_RoadSwampCobble") )
+                                            {
+                                              if ( _strcmpi(v9, "TTtype_RoadSwampDirt") )
+                                              {
+                                                if ( _strcmpi(v9, "TTtype_RoadTropicalCobble") )
+                                                {
+                                                  if ( _strcmpi(v9, "TTtype_RoadTropicalDirt") )
+                                                  {
+                                                    if ( _strcmpi(v9, "TTtype_RoadSnowCobble") )
+                                                    {
+                                                      if ( _strcmpi(v9, "TTtype_RoadSnowDirt") )
+                                                      {
+                                                        if ( !_strcmpi(v9, "TTtype_RoadCityStone") )
+                                                        {
+                                                          v34 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                                          *(char *)v34 |= 0x1Cu;
+                                                        }
+                                                      }
+                                                      else
+                                                      {
+                                                        v33 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                                        *(char *)v33 |= 0xDu;
+                                                      }
+                                                    }
+                                                    else
+                                                    {
+                                                      v32 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                                      *(char *)v32 |= 0xCu;
+                                                    }
+                                                  }
+                                                  else
+                                                  {
+                                                    v31 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                                    *(char *)v31 |= 0x1Bu;
+                                                  }
+                                                }
+                                                else
+                                                {
+                                                  v30 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                                  *(char *)v30 |= 0x1Au;
+                                                }
+                                              }
+                                              else
+                                              {
+                                                v29 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                                *(char *)v29 |= 0x19u;
+                                              }
+                                            }
+                                            else
+                                            {
+                                              v28 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                              *(char *)v28 |= 0x18u;
+                                            }
+                                          }
+                                          else
+                                          {
+                                            v27 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                            *(char *)v27 |= 0x11u;
+                                          }
+                                        }
+                                        else
+                                        {
+                                          v26 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                          *(char *)v26 |= 0x10u;
+                                        }
+                                      }
+                                      else
+                                      {
+                                        v25 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                        *(char *)v25 |= 0xFu;
+                                      }
+                                    }
+                                    else
+                                    {
+                                      v24 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                      *(char *)v24 |= 0xEu;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    v23 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                    *(char *)v23 |= 0x17u;
+                                  }
+                                }
+                                else
+                                {
+                                  v22 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                  *(char *)v22 |= 0x16u;
+                                }
+                              }
+                              else
+                              {
+                                v21 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                                *(char *)v21 |= 0xBu;
+                              }
+                            }
+                            else
+                            {
+                              v20 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                              *(char *)v20 |= 0xAu;
+                            }
+                          }
+                          else
+                          {
+                            v19 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                            *(char *)v19 |= 9u;
+                          }
+                        }
+                        else
+                        {
+                          v18 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                          *(char *)v18 |= 7u;
+                        }
+                      }
+                      else
+                      {
+                        v17 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                        *(char *)v17 |= 8u;
+                      }
+                    }
+                    else
+                    {
+                      v16 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                      *(char *)v16 |= 5u;
+                    }
+                  }
+                  else
+                  {
+                    v15 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                    *(char *)v15 |= 4u;
+                  }
+                }
+                else
+                {
+                  v14 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                  *(char *)v14 |= 3u;
+                }
+              }
+              else
+              {
+                v13 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+                *(char *)v13 |= 2u;
+              }
+            }
+            else
+            {
+              v12 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+              *(char *)v12 |= 1u;
+            }
+          }
+          else
+          {
+            v11 = (int)&v2->pTiles[v2->uNumTiles].uTerrainType;
+            *(char *)v11 |= 6u;
+          }
+        }
+      }
+      else
+      {
+        v10 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+        *(char *)v10 |= 0xFEu;
+      }
+    }
+    else
+    {
+      LOBYTE(v2->pTiles[v2->uNumTiles].uTerrainType) = -1;
+    }
+    v35 = v84.pProperties[4];
+    v2->pTiles[v2->uNumTiles].uSection = 0;
+    v2->pTiles[v2->uNumTiles].uAttributes = 0;
+    if ( !_strcmpi(v35, "TTsect_NULL") )
+    {
+      LOBYTE(v2->pTiles[v2->uNumTiles].uSection) = -1;
+LABEL_152:
+      for ( j = 5; j < v84.field_0; ++j )
+      {
+        v72 = v84.pProperties[j];
+        if ( _strcmpi(v84.pProperties[j], "TTattr_Burn") )
+        {
+          if ( _strcmpi(v72, "TTattr_Water") )
+          {
+            if ( _strcmpi(v72, "TTattr_Water2") )
+            {
+              if ( _strcmpi(v72, "TTattr_Block") )
+              {
+                if ( _strcmpi(v72, "TTattr_Repulse") )
+                {
+                  if ( _strcmpi(v72, "TTattr_Flat") )
+                  {
+                    if ( _strcmpi(v72, "TTattr_Wave") )
+                    {
+                      if ( _strcmpi(v72, "TTattr_NoDraw") )
+                      {
+                        if ( !_strcmpi(v72, "TTattr_Transition") )
+                        {
+                          v80 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+                          *(short *)v80 |= 0x200u;
+                        }
+                      }
+                      else
+                      {
+                        v79 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+                        *(char *)v79 |= 0x40u;
+                      }
+                    }
+                    else
+                    {
+                      v78 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+                      *(char *)v78 |= 0x20u;
+                    }
+                  }
+                  else
+                  {
+                    v77 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+                    *(char *)v77 |= 0x10u;
+                  }
+                }
+                else
+                {
+                  v76 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+                  *(char *)v76 |= 8u;
+                }
+              }
+              else
+              {
+                v75 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+                *(char *)v75 |= 4u;
+              }
+            }
+            else
+            {
+              HIBYTE(v2->pTiles[v2->uNumTiles].uAttributes) |= 1u;
+            }
+          }
+          else
+          {
+            v74 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+            *(char *)v74 |= 2u;
+          }
+        }
+        else
+        {
+          v73 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+          *(char *)v73 |= 1u;
+        }
+      }
+      ++v2->uNumTiles;
+      goto LABEL_173;
+    }
+    if ( !_strcmpi(v35, "TTsect_Start") )
+    {
+      v36 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v36 |= 0xFEu;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Base1") )
+      goto LABEL_152;
+    if ( !_strcmpi(v35, "TTsect_Base2") )
+    {
+      v37 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v37 |= 1u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Base3") )
+    {
+      v38 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v38 |= 2u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Base4") )
+    {
+      v39 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v39 |= 3u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Special1") )
+    {
+      v40 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v40 |= 4u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Special2") )
+    {
+      v41 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v41 |= 5u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Special3") )
+    {
+      v42 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v42 |= 6u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Special4") )
+    {
+      v43 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v43 |= 7u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Special5") )
+    {
+      v44 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v44 |= 8u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Special6") )
+    {
+      v45 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v45 |= 9u;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Special7") )
+    {
+      v46 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v46 |= 0xAu;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_Special8") )
+    {
+      v47 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+      *(char *)v47 |= 0xBu;
+      goto LABEL_152;
+    }
+    if ( !_strcmpi(v35, "TTsect_NE1") )
+      goto LABEL_130;
+    if ( !_strcmpi(v35, "TTsect_NW1") )
+      goto LABEL_134;
+    if ( !_strcmpi(v35, "TTsect_SE1") )
+      goto LABEL_130;
+    if ( !_strcmpi(v35, "TTsect_SW1") )
+      goto LABEL_134;
+    if ( !_strcmpi(v35, "TTsect_E1") )
+      goto LABEL_138;
+    if ( !_strcmpi(v35, "TTsect_W1") )
+      goto LABEL_140;
+    if ( !_strcmpi(v35, "TTsect_N1") )
+      goto LABEL_142;
+    if ( !_strcmpi(v35, "TTsect_S1") )
+      goto LABEL_144;
+    if ( !_strcmpi(v35, "TTsect_XNE1") )
+      goto LABEL_146;
+    if ( _strcmpi(v35, "TTsect_XNW1") )
+    {
+      if ( !_strcmpi(v35, "TTsect_XSE1") )
+        goto LABEL_146;
+      if ( _strcmpi(v35, "TTsect_XSW1") )
+      {
+        if ( !_strcmpi(v35, "TTsect_CROS") )
+        {
+LABEL_151:
+          v70 = (int)&v2->pTiles[v2->uNumTiles].uAttributes;
+          *(short *)v70 |= 0x200u;
+          goto LABEL_152;
+        }
+        if ( !_strcmpi(v35, "TTsect_NS") )
+        {
+          v48 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v48 |= 1u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_EW") )
+        {
+          v49 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v49 |= 2u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_N_E") )
+        {
+          v50 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v50 |= 3u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_N_W") )
+        {
+          v51 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v51 |= 4u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_S_E") )
+        {
+          v52 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v52 |= 5u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_S_W") )
+        {
+          v53 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v53 |= 6u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_NS_E") )
+        {
+          v54 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v54 |= 7u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_NS_W") )
+        {
+          v55 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v55 |= 8u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_EW_N") )
+        {
+          v56 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v56 |= 9u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_EW_S") )
+        {
+          v57 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v57 |= 0xAu;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_NCAP") )
+        {
+          v58 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v58 |= 0xBu;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_ECAP") )
+        {
+LABEL_130:
+          v59 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v59 |= 0xCu;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_SCAP") )
+        {
+          v60 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v60 |= 0xDu;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_WCAP") )
+        {
+LABEL_134:
+          v61 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v61 |= 0xEu;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_DN") )
+        {
+          v62 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v62 |= 0xFu;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_DS") )
+        {
+LABEL_138:
+          v63 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v63 |= 0x10u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_DW") )
+        {
+LABEL_140:
+          v64 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v64 |= 0x11u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_DE") )
+        {
+LABEL_142:
+          v65 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v65 |= 0x12u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_DSW") )
+        {
+LABEL_144:
+          v66 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v66 |= 0x13u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_DNE") )
+        {
+LABEL_146:
+          v67 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v67 |= 0x14u;
+          goto LABEL_151;
+        }
+        if ( !_strcmpi(v35, "TTsect_DSE") )
+        {
+          v68 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+          *(char *)v68 |= 0x15u;
+          goto LABEL_151;
+        }
+        if ( _strcmpi(v35, "TTsect_DNW") )
+          goto LABEL_152;
+      }
+    }
+    v69 = (int)&v2->pTiles[v2->uNumTiles].uSection;
+    *(char *)v69 |= 0x16u;
+    goto LABEL_151;
+  }
+LABEL_174:
+  fclose(File);
+  return 1;
+}
+
+
+
+//----- (0048958E) --------------------------------------------------------
+stru12_MemoryBlock::stru12_MemoryBlock(int a2)
+{
+  stru12_MemoryBlock *v2; // esi@1
+  void *v3; // eax@1
+  void *v4; // ecx@1
+  stru12_MemoryBlock *result; // eax@1
+
+  v2 = this;
+  v3 = operator new(8 * a2 + 16);
+  v2->pBlockBase = v3;
+  v4 = (char *)v3 + (-(signed int)v3 & 7);
+  result = v2;
+  v2->pAlignedBlock = v4;
+}
+
+//----- (004895B7) --------------------------------------------------------
+stru12::stru12(stru11 *pStru11)
+{
+  stru12 *v2; // esi@1
+
+  v2 = this;
+  this->field_44 = 0x41000000u;
+  this->field_4C = 0x46000000u;
+  //this->vdestructor_ptr = stru12::_4898E6;
+  this->field_48 = 0;
+  this->field_50 = 0;
+  this->field_54 = 0x33D6BF95u;
+  this->field_58 = 0;
+  
+  for (int i = 0; i < 12; ++i)
+    v2->pMemBlocks[i] = new stru12_MemoryBlock(640);
+  /*
+  v3 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v3 )
+    v4 = AllocAlignedMem(v3, 640);
+  else
+    v4 = 0;
+  v2->pMemBlocks[0] = v4;
+  /*v5 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v5 )
+    v6 = AllocAlignedMem(v5, 640);
+  else
+    v6 = 0;
+  v2->pMemBlocks[1] = v6;
+  v7 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v7 )
+    v8 = AllocAlignedMem(v7, 640);
+  else
+    v8 = 0;
+  v2->pMemBlocks[2] = v8;
+  v9 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v9 )
+    v10 = AllocAlignedMem(v9, 640);
+  else
+    v10 = 0;
+  v2->pMemBlocks[3] = v10;
+  v11 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v11 )
+    v12 = AllocAlignedMem(v11, 640);
+  else
+    v12 = 0;
+  v2->pMemBlocks[4] = v12;
+  v13 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v13 )
+    v14 = AllocAlignedMem(v13, 640);
+  else
+    v14 = 0;
+  v2->pMemBlocks[5] = v14;
+  v15 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v15 )
+    v16 = AllocAlignedMem(v15, 640);
+  else
+    v16 = 0;
+  v2->pMemBlocks[6] = v16;
+  v17 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v17 )
+    v18 = AllocAlignedMem(v17, 640);
+  else
+    v18 = 0;
+  v2->pMemBlocks[7] = v18;
+  v19 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v19 )
+    v20 = AllocAlignedMem(v19, 640);
+  else
+    v20 = 0;
+  v2->pMemBlocks[8] = v20;
+  v21 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v21 )
+    v22 = AllocAlignedMem(v21, 640);
+  else
+    v22 = 0;
+  v2->pMemBlocks[9] = v22;
+  v23 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v23 )
+    v24 = AllocAlignedMem(v23, 640);
+  else
+    v24 = 0;
+  v2->pMemBlocks[10] = v24;
+  v25 = (stru12_MemoryBlock *)operator new(8u);
+  if ( v25 )
+    v26 = AllocAlignedMem(v25, 640);
+  else
+    v26 = 0;
+  v2->field_8C = 0;
+  v2->pMemBlocks[11] = v26;*/
+}
+
+//----- (00489810) --------------------------------------------------------
+stru12::~stru12()
+{
+  for (int i = 0; i < 12; ++i)
+    delete pMemBlocks[i];
+  /*if ( v2 )
+    stru12_MemoryBlock::dtor(v2, 1);
+  v3 = v1->pMemBlocks[1];
+  if ( v3 )
+    stru12_MemoryBlock::dtor(v3, 1);
+  v4 = v1->pMemBlocks[2];
+  if ( v4 )
+    stru12_MemoryBlock::dtor(v4, 1);
+  v5 = v1->pMemBlocks[3];
+  if ( v5 )
+    stru12_MemoryBlock::dtor(v5, 1);
+  v6 = v1->pMemBlocks[4];
+  if ( v6 )
+    stru12_MemoryBlock::dtor(v6, 1);
+  v7 = v1->pMemBlocks[5];
+  if ( v7 )
+    stru12_MemoryBlock::dtor(v7, 1);
+  v8 = v1->pMemBlocks[6];
+  if ( v8 )
+    stru12_MemoryBlock::dtor(v8, 1);
+  v9 = v1->pMemBlocks[7];
+  if ( v9 )
+    stru12_MemoryBlock::dtor(v9, 1);
+  v10 = v1->pMemBlocks[8];
+  if ( v10 )
+    stru12_MemoryBlock::dtor(v10, 1);
+  v11 = v1->pMemBlocks[9];
+  if ( v11 )
+    stru12_MemoryBlock::dtor(v11, 1);
+  v12 = v1->pMemBlocks[10];
+  if ( v12 )
+    stru12_MemoryBlock::dtor(v12, 1);
+  v13 = v1->pMemBlocks[11];
+  if ( v13 )
+    stru12_MemoryBlock::dtor(v13, 1);*/
+}
+
+//----- (004898BF) --------------------------------------------------------
+stru12_MemoryBlock::~stru12_MemoryBlock()
+{
+  stru12_MemoryBlock *v2; // esi@1
+  void *v3; // ST00_4@1
+
+  v2 = this;
+  v3 = this->pBlockBase;
+  this->pAlignedBlock = 0;
+  free(v3);
+  v2->pBlockBase = 0;
+  /*if ( a2 & 1 )
+    free(v2);*/
+}
+
+//----- (004898E6) --------------------------------------------------------
+void stru12::_4898E6()
+{
+  void *v1; // eax@1
+  void *v2; // edx@1
+  char *v3; // edi@2
+  double v4; // st7@2
+  char *v5; // ebx@2
+  double v6; // st6@3
+  double v7; // st5@3
+  double v8; // st4@3
+  int v9; // esi@3
+  double v10; // st3@3
+  float v11; // ST34_4@5
+  double v12; // st6@10
+  double v13; // ST0C_8@10
+  char *v14; // [sp+14h] [bp-44h]@2
+  char *v15; // [sp+18h] [bp-40h]@2
+  char *v16; // [sp+1Ch] [bp-3Ch]@2
+  char *v17; // [sp+20h] [bp-38h]@2
+  char *v18; // [sp+24h] [bp-34h]@2
+  float v19; // [sp+30h] [bp-28h]@3
+  float v20; // [sp+38h] [bp-20h]@3
+  char *v21; // [sp+3Ch] [bp-1Ch]@2
+  int v22; // [sp+40h] [bp-18h]@1
+  char *v23; // [sp+44h] [bp-14h]@2
+  char *v24; // [sp+48h] [bp-10h]@2
+  int v25; // [sp+4Ch] [bp-Ch]@2
+  float v26; // [sp+50h] [bp-8h]@3
+  float v27; // [sp+54h] [bp-4h]@3
+
+  v22 = 0;
+  v1 = this->pMemBlocks[1]->pAlignedBlock;
+  v2 = this->pMemBlocks[6]->pAlignedBlock;
+  if ( this->field_8C > 0 )
+  {
+    v24 = (char *)((char *)pMemBlocks[0]->pAlignedBlock - v1);
+    v23 = (char *)((char *)pMemBlocks[2]->pAlignedBlock - v1);
+    v18 = (char *)((char *)pMemBlocks[7]->pAlignedBlock - v2);
+    v17 = (char *)((char *)pMemBlocks[8]->pAlignedBlock - v2);
+    v25 = (int)v1 - (int)v2;
+    v16 = (char *)((char *)pMemBlocks[9]->pAlignedBlock - v2);
+    v3 = (char *)((char *)pMemBlocks[4]->pAlignedBlock - v2);
+    v15 = (char *)((char *)pMemBlocks[10]->pAlignedBlock - v2);
+    v4 = 1.0;
+    v5 = (char *)((char *)pMemBlocks[5]->pAlignedBlock - v2);
+    v21 = (char *)((char *)pMemBlocks[3]->pAlignedBlock - v2);
+    v14 = (char *)((char *)pMemBlocks[11]->pAlignedBlock - v2);
+    do
+    {
+      v26 = *(float *)&v24[(int)((char *)v2 + v25)] - (double)pIndoorCamera->pos.x;
+      v27 = *(float *)((char *)v2 + v25) - (double)pIndoorCamera->pos.y;
+      v6 = *(float *)&v23[(int)((char *)v2 + v25)] - (double)pIndoorCamera->pos.z;
+      v7 = pIndoorCamera->fRotationYCosine;
+      v8 = pIndoorCamera->fRotationYSine;
+      v20 = pIndoorCamera->fRotationXCosine;
+      v19 = pIndoorCamera->fRotationXSine;
+      v9 = (int)((char *)v2 + (int)v21);
+      v10 = v27 * pIndoorCamera->fRotationYSine + pIndoorCamera->fRotationYCosine * v26;
+      if ( pIndoorCamera->sRotationX )
+      {
+        v11 = v10;
+        *(float *)v9 = v11 * pIndoorCamera->fRotationXCosine + pIndoorCamera->fRotationXSine * v6;
+        *(float *)((char *)v2 + (int)v3) = v7 * v27 - v8 * v26;
+        *(float *)((char *)v2 + (int)v5) = v20 * v6 - v11 * v19;
+      }
+      else
+      {
+        *(float *)v9 = v10;
+        *(float *)((char *)v2 + (int)v3) = v7 * v27 - v8 * v26;
+        *(float *)((char *)v2 + (int)v5) = v6;
+      }
+      if ( *(float *)v9 >= 8.0 )
+      {
+        if ( (double)pOutdoorCamera->shading_dist_mist >= *(float *)v9 )
+        {
+          *(int *)v2 = 0;
+          v12 = v4 / (*(float *)v9 + 0.0000001) * (double)pOutdoorCamera->int_fov_rad;
+          *(float *)((char *)v2 + (int)v18) = (double)pViewport->uScreenCenterX
+                                               - v12 * *(float *)((char *)v2 + (int)v3);
+          *(float *)((char *)v2 + (int)v17) = (double)pViewport->uScreenCenterY
+                                               - v12 * *(float *)((char *)v2 + (int)v5);
+          *(float *)((char *)v2 + (int)v16) = v4
+                                               - v4 / (*(float *)v9 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+          *(float *)((char *)v2 + (int)v15) = v4 / (*(float *)v9 + 0.0000001);
+          v13 = *(float *)v9 + 6.7553994e15;
+          v4 = 1.0;
+          *(int *)((char *)v2 + (int)v14) = LODWORD(v13);
+        }
+        else
+        {
+          *(int *)v2 = 2;
+        }
+      }
+      else
+      {
+        *(int *)v2 = 1;
+      }
+      ++v22;
+      v2 = (char *)v2 + 4;
+    }
+    while ( v22 < this->field_8C );
+  }
+  this->field_8C = 0;
+}
+
+
+
+
+
+//----- (0048A959) --------------------------------------------------------
+unsigned int ReplaceHSV(unsigned int uColor, float h_replace, float s_replace, float v_replace)
+{
+  float r = ((uColor & 0x00FF0000) >> 16) / 255.0f,
+        g = ((uColor & 0x0000FF00) >> 8) / 255.0f,
+        b = (uColor & 0x000000FF) / 255.0f;
+
+  float h, s, v;
+  RGB2HSV(&h, &s, r, g, b, &v);
+
+  if ( h_replace != -1.0 )
+    h = h_replace;
+  if ( s_replace != -1.0 )
+    s = s_replace;
+  if ( v_replace != -1.0 )
+    v = v_replace;
+  HSV2RGB(&r, &g, &b, h, s, v);
+
+  return (((uint)floorf(r * 255.0f + 0.5f) & 0xFF) << 16) |
+         (((uint)floorf(g * 255.0f + 0.5f) & 0xFF) << 8) |
+         ((uint)floorf(b * 255.0f + 0.5f) & 0xFF);
+}
+
+
+//----- (0048B561) --------------------------------------------------------
+int _48B561_mess_with_scaling_along_z(/*int a1, */float a2)
+{
+  //v2 = a2 - 0.5;
+  //v3 = v2 + 6.7553994e15;
+  int v4 = floorf(a2 - 0.5f + 0.5f);
+  //v7 = (a2 - (double)SLODWORD(v3)) * 65536.0;
+  //v5 = v7 + 6.7553994e15;
+  //return LODWORD(v5) | (v4 << 16);
+  int v5 = floorf((a2 - v4) * 65536.0f + 0.5f);
+  return v5 | (v4 << 16);
+}
+
+
+
+
+//----- (004908DE) --------------------------------------------------------
+signed int __cdecl sub_4908DE()
+{
+  char *v0; // esi@1
+  signed int v1; // edx@2
+  char *v2; // eax@2
+  signed int v3; // ecx@2
+
+  v0 = (char *)pParty->pPlayers[0].pActiveSkills;
+  while ( 1 )
+  {
+    v1 = 0;
+    v2 = v0;
+    v3 = 37;
+    do
+    {
+      if ( *(short *)v2 )
+        ++v1;
+      v2 += 2;
+      --v3;
+    }
+    while ( v3 );
+    if ( v1 < 4 )
+      break;
+    v0 += 6972;
+    if ( (signed int)v0 >= (signed int)&pParty->field_777C[18] )
+      return 1;
+  }
+  return 0;
+}
+
+
+
+
+//----- (00491CB5) --------------------------------------------------------
+void __cdecl LoadPlayerPortraintsAndVoices()
+{
+  //Texture **v0; // ebx@1
+  //int v1; // eax@2
+  //int v2; // edi@3
+  char *v3; // esi@5
+  char *v4; // [sp+10h] [bp-4h]@1
+
+  pIcons_LOD->dword_011BA0 = pIcons_LOD->uNumLoadedFiles;
+
+  for (uint i = 0; i < 4; ++i)
+    for (uint j = 0; j < 56; ++j)
+    {
+      sprintf(pTmpBuf, "%s%02d", pPlayerPortraitsNames[pParty->pPlayers[i].uFace], j + 1);
+      pTextures_PlayerFaces[i][j] = pIcons_LOD->LoadTexturePtr(pTmpBuf, TEXTURE_16BIT_PALETTE);
+    }
+
+  pTexture_PlayerFaceEradicated = pIcons_LOD->LoadTexturePtr("ERADCATE", TEXTURE_16BIT_PALETTE);
+  pTexture_PlayerFaceDead = pIcons_LOD->LoadTexturePtr("DEAD", TEXTURE_16BIT_PALETTE);
+  pTexture_PlayerFaceMask = pIcons_LOD->LoadTexturePtr("FACEMASK", TEXTURE_16BIT_PALETTE);
+  
+  if (byte_4ED498)
+    for (uint i = 0; i < 4; ++i)
+    {
+      pSoundList->LoadSound(2 * (byte_4ED498 + 50 * pParty->pPlayers[i].uVoiceID) + 4998, 0);
+      pSoundList->LoadSound(2 * (byte_4ED498 + 50 * pParty->pPlayers[i].uVoiceID) + 4999, 0);
+    }
+}
+
+//----- (00491DE7) --------------------------------------------------------
+int __fastcall ReloadPlayerPortraits(int a1, int a2)
+{
+  int result; // eax@1
+  const char **v3; // ebp@1
+  Texture **v4; // ebx@1
+  int v5; // esi@2
+
+  result = 0;
+  v3 = &pPlayerPortraitsNames[a2];
+  v4 = pTextures_PlayerFaces[a1];
+  do
+  {
+    v5 = result + 1;
+    sprintf(pTmpBuf, "%s%02d", *v3, result + 1);
+    pIcons_LOD->ReloadTexture(*v4, pTmpBuf, 2);
+    result = v5;
+    ++v4;
+  }
+  while ( v5 < 56 );
+  return result;
+}
+
+
+//----- (00491E3A) --------------------------------------------------------
+void __cdecl sub_491E3A()
+{
+  Player *v0; // ebx@1
+  signed int v1; // esi@3
+  char *v2; // eax@4
+  unsigned int v3; // eax@7
+  unsigned int v4; // edx@8
+  char *v5; // ecx@9
+  int v6; // edi@17
+  Texture *v7; // ebx@18
+  struct IDirect3DTexture2 **v8; // eax@19
+  struct IDirect3DTexture2 *v9; // eax@20
+  struct IDirectDrawSurface **v10; // eax@22
+  struct IDirectDrawSurface *v11; // eax@23
+  int v12; // eax@26
+
+  v0 = pParty->pPlayers;
+  do
+  {
+    if ( byte_4ED498 )
+    {
+      v1 = 0;
+      if ( (signed int)pSoundList->uNumSounds <= 0 )
+      {
+LABEL_7:
+        v3 = 0;
+      }
+      else
+      {
+        v2 = (char *)&pSoundList->pSounds->uSoundID;
+        while ( *(int *)v2 != 2 * ((unsigned __int8)byte_4ED498 + 50 * v0->uVoiceID) + 4998 )
+        {
+          ++v1;
+          v2 += 120;
+          if ( v1 >= (signed int)pSoundList->uNumSounds )
+            goto LABEL_7;
+        }
+        v3 = v1;
+      }
+      pSoundList->_4A9DCD(v3, 1);
+      v4 = 0;
+      if ( (signed int)pSoundList->uNumSounds <= 0 )
+      {
+LABEL_12:
+        v4 = 0;
+      }
+      else
+      {
+        v5 = (char *)&pSoundList->pSounds->uSoundID;
+        while ( *(int *)v5 != 2 * ((unsigned __int8)byte_4ED498 + 50 * v0->uVoiceID) + 4999 )
+        {
+          ++v4;
+          v5 += 120;
+          if ( (signed int)v4 >= (signed int)pSoundList->uNumSounds )
+            goto LABEL_12;
+        }
+      }
+      pSoundList->_4A9DCD(v4, 1);
+    }
+    ++v0;
+  }
+  while ( (signed int)v0 < (signed int)pParty->pHirelings );
+  v6 = pIcons_LOD->uNumLoadedFiles - 1;
+  if ( v6 >= pIcons_LOD->dword_011BA0 )
+  {
+    v7 = &pIcons_LOD->pTextures[v6];
+    do
+    {
+      v7->Release();
+      v8 = pIcons_LOD->pHardwareTextures;
+      if ( v8 )
+      {
+        v9 = v8[v6];
+        if ( v9 )
+        {
+          v9->Release();
+          pIcons_LOD->pHardwareTextures[v6] = 0;
+        }
+      }
+      v10 = pIcons_LOD->pHardwareSurfaces;
+      if ( v10 )
+      {
+        v11 = v10[v6];
+        if ( v11 )
+        {
+          v11->Release();
+          pIcons_LOD->pHardwareSurfaces[v6] = 0;
+        }
+      }
+      --v6;
+      --v7;
+    }
+    while ( v6 >= pIcons_LOD->dword_011BA0 );
+  }
+  v12 = pIcons_LOD->dword_011BA0;
+  pIcons_LOD->dword_011BA0 = 0;
+  pIcons_LOD->uNumLoadedFiles = v12;
+}
+// 4ED498: using guessed type char byte_4ED498;
+
+//----- (00491F87) --------------------------------------------------------
+void __cdecl DrawHiredNPCs()
+{
+  int v6; // eax@15
+  char v7; // al@17
+  unsigned int v8; // eax@18
+  int v9; // esi@18
+  int v10; // eax@18
+  unsigned int v11; // eax@19
+  unsigned int v12; // esi@19
+  unsigned int v13; // eax@23
+  IconFrame *v14; // eax@24
+  unsigned int v15; // eax@26
+  char pContainer[20]; // [sp+Ch] [bp-30h]@18
+  unsigned int v17; // [sp+20h] [bp-1Ch]@19
+  signed int uFrameID; // [sp+24h] [bp-18h]@19
+  int i; // [sp+28h] [bp-14h]@15
+  unsigned int v20; // [sp+2Ch] [bp-10h]@20
+  unsigned int v21; // [sp+30h] [bp-Ch]@19
+  int v22; // [sp+34h] [bp-8h]@2
+  unsigned __int8 v23; // [sp+3Bh] [bp-1h]@2
+
+  if ( bNoNPCHiring != 1 )
+  {
+    v23 = 0;
+    v22 = 0;
+    for (uint i = 0; i < 2; ++i)
+    { 
+      if (pParty->pHirelings[i].pName)
+        pTmpBuf[v22++] = i;
+    }
+
+    for (uint i = 0; i < pNPCStats->uNumNewNPCs; ++i)
+    {
+      if (pNPCStats->pNewNPCData[i].uFlags & 0x80)
+      {
+        if (!pParty->pHirelings[0].pName || strcmp(pNPCStats->pNewNPCData[i].pName, pParty->pHirelings[0].pName))
+        {
+          if (!pParty->pHirelings[1].pName || strcmp(pNPCStats->pNewNPCData[i].pName, pParty->pHirelings[1].pName))
+            pTmpBuf[v22++] = i + 2;
+        }
+      }
+    }
+
+    v6 = (unsigned __int8)pParty->field_709;
+    for ( i = (unsigned __int8)pParty->field_709; i < v22; v6 = i++ + 1 )
+    {
+      if ( v23 >= 2u )
+        break;
+      v7 = pTmpBuf[v6];
+      if ( (unsigned __int8)v7 >= 2u )
+      {
+        sprintf(pContainer, "NPC%03d", pNPCStats->pNPCData[(unsigned __int8)v7 + 499].uPortraitID);
+        v15 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+        pRenderer->DrawTextureIndexed(pHiredNPCsIconsOffsetsX[v23], pHiredNPCsIconsOffsetsY[v23],
+          (Texture *)(v15 != -1 ? &pIcons_LOD->pTextures[v15] : 0));
+      }
+      else
+      {
+        sprintf(pContainer, "NPC%03d", pParty->pHirelings[(unsigned __int8)v7].uPortraitID);
+        v8 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+        v9 = v23;
+        pRenderer->DrawTextureIndexed(
+          pHiredNPCsIconsOffsetsX[v9],
+          pHiredNPCsIconsOffsetsY[v9],
+          (Texture *)(v8 != -1 ? &pIcons_LOD->pTextures[v8] : 0));
+        v10 = (unsigned __int8)pTmpBuf[i];
+        if ( pParty->pHirelings[v10].bDrawSomeAnim == 1 )
+        {
+          uFrameID = pParty->pHirelings[v10].evtb;
+          v11 = pHiredNPCsIconsOffsetsX[v9];
+          v12 = pHiredNPCsIconsOffsetsY[v9];
+          v17 = v11;
+          v21 = 0;
+          if ( (signed int)pIconsFrameTable->uNumIcons <= 0 )
+          {
+LABEL_23:
+            v13 = 0;
+          }
+          else
+          {
+            v20 = 0;
+            while ( _strcmpi("spell96", pIconsFrameTable->pIcons[v20 / 0x20].pAnimationName) )
+            {
+              ++v21;
+              v20 += 32;
+              if ( (signed int)v21 >= (signed int)pIconsFrameTable->uNumIcons )
+                goto LABEL_23;
+            }
+            v13 = v21;
+          }
+          v14 = pIconsFrameTable->GetFrame(v13, uFrameID);
+          pRenderer->DrawTextureTransparent(v17, v12, &pIcons_LOD->pTextures[v14->uTextureID]);
+        }
+      }
+      ++v23;
+    }
+  }
+}
+// 6BE3C5: using guessed type char bNoNPCHiring;
+
+
+
+//----- (004921C1) --------------------------------------------------------
+void GameUI_DrawPortraits(unsigned int _this)
+{
+  Texture *pFace; // eax@10
+  unsigned int v7; // eax@17
+  PlayerFrame *pFrame; // eax@21
+  unsigned int v9; // eax@27
+  bool v10; // eax@33
+  bool v11; // edi@40
+  bool v12; // edx@43
+  bool v13; // ecx@46
+  int v16; // eax@57
+  int v19; // eax@62
+  Texture *pPortrait; // [sp-4h] [bp-1Ch]@27
+  unsigned int v22; // [sp+14h] [bp-4h]@1
+
+  v22 = _this;
+  if ( qword_A750D8 )
+  {
+    qword_A750D8 -= (signed int)pMiscTimer->uTimeElapsed;
+    if ( qword_A750D8 <= 0 )
+    {
+      if ( pPlayers[word_A750E2]->CanAct() )
+        pPlayers[word_A750E2]->PlaySound(word_A750E0, 0);
+      qword_A750D8 = 0i64;
+    }
+  }
+
+  for (uint i = 0; i < 4; ++i)
+  {
+    auto pPlayer = pParty->pPlayers + i;
+
+    if (pPlayer->Eradicated())
+    {
+      pFace = pTexture_PlayerFaceEradicated;
+LABEL_27:
+      pPortrait = pFace;
+      v9 = pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i];
+      if ( pParty->pPartyBuffs[11].uExpireTime )
+        pRenderer->_4A6E7E(v9, 0x183u, pPortrait);
+      else
+        pRenderer->DrawTextureTransparent(v9 + 1, 0x184u, pPortrait);
+      auto _v1 = 0;
+      v10 = pPlayer->pPlayerBuffs[14].uExpireTime > 0;
+      if (pPlayer->pPlayerBuffs[1].uExpireTime > 0)
+        _v1 = 1;
+      v11 = pPlayer->pPlayerBuffs[8].uExpireTime > 0;
+      v12 = pPlayer->pPlayerBuffs[7].uExpireTime > 0;
+      v13 = pPlayer->pPlayerBuffs[13].uExpireTime > 0;
+      if ( v13 | v12 | v11 | _v1 | v10 )
+        sub_441A4E(i);
+      goto LABEL_50;
+    }
+    if (pPlayer->Dead())
+    {
+      pFace = pTexture_PlayerFaceDead;
+      goto LABEL_27;
+    }
+      v7 = 0;
+      for (uint j = 0; j < pPlayerFrameTable->uNumFrames; ++j)
+        if (pPlayerFrameTable->pFrames[j].uSequenceID == pPlayer->uExpressionID)
+        {
+          v7 = j;
+          break;
+        }
+    if ( v7 == 0 )
+      v7 = 1;
+    if (pPlayer->uExpressionID == 21 )
+      pFrame = pPlayerFrameTable->GetFrameBy_y(&pPlayer->field_1AA8, &pPlayer->field_1AA4, pMiscTimer->uTimeElapsed);
+    else
+      pFrame = pPlayerFrameTable->GetFrameBy_x(v7, pPlayer->uExpressionTimePassed);
+    if (pPlayer->field_1AA2 != pFrame->uTextureID - 1 || v22 )
+    {
+      pPlayer->field_1AA2 = pFrame->uTextureID - 1;
+      pFace = (Texture *)pTextures_PlayerFaces[i][pFrame->uTextureID];
+      goto LABEL_27;
+    }
+LABEL_50:
+    ;
+  }
+  if ( pParty->bTurnBasedModeOn == 1 )
+  {
+    if ( pTurnEngine->field_4 != 1 )
+    {
+      if ( (pTurnEngine->pQueue[0].uPackedID & 7) == 4 )
+      {
+        //v14 = 0;
+        if ( pTurnEngine->uActorQueueSize > 0 )
+        {
+          //v15 = (char *)pTurnEngine->pQueue;
+          for (uint i = 0; i < pTurnEngine->uActorQueueSize; ++i)
+          {
+            auto pElem = pTurnEngine->pQueue + i;
+
+            if ( (pElem->uPackedID & 7) != 4 )
+              break;
+            v16 = dword_5079D0;
+            if ( pParty->uFlags & 0x10 )
+            {
+              v16 = dword_5079CC;
+            }
+            else
+            {
+              if ( pParty->uFlags & 0x20 )
+                v16 = dword_5079C8;
+            }
+            pRenderer->DrawTextureTransparent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[pElem->uPackedID >> 3] - 4,
+              0x181u, (Texture *)(v16 != -1 ? &pIcons_LOD->pTextures[v16] : 0));
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    for (uint i = 0; i < 4; ++i)
+    {
+      auto pPlayer = pParty->pPlayers + i;
+      if (pPlayer->CanAct() && !pPlayer->uTimeToRecovery)
+      {
+        v19 = dword_5079D0;
+        if ( pParty->uFlags & 0x10 )
+        {
+          v19 = dword_5079CC;
+        }
+        else
+        {
+          if ( pParty->uFlags & 0x20 )
+            v19 = dword_5079C8;
+        }
+        pRenderer->DrawTextureTransparent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] - 4,
+          0x181u, (Texture *)(v19 != -1 ? &pIcons_LOD->pTextures[v19] : 0));
+      }
+    }
+  }
+}
+
+
+//----- (0049387A) --------------------------------------------------------
+int CycleCharacter(unsigned int _this)
+{
+  signed int result; // eax@1
+  signed int v2; // ecx@2
+  signed int v3; // ecx@8
+
+  result = uActiveCharacter;
+  if ( _this )
+  {
+    v2 = 0;
+    while ( 1 )
+    {
+      --result;
+      if ( result < 1 )
+        result = 4;
+      if ( !pPlayers[result]->uTimeToRecovery )
+        break;
+      ++v2;
+      if ( v2 >= 4 )
+        return uActiveCharacter;
+    }
+  }
+  else
+  {
+    v3 = 0;
+    while ( 1 )
+    {
+      ++result;
+      if ( result > 4 )
+        result = 1;
+      if ( !pPlayers[result]->uTimeToRecovery )
+        break;
+      ++v3;
+      if ( v3 >= 4 )
+        return uActiveCharacter;
+    }
+  }
+  return result;
+}
+
+//----- (004938D1) --------------------------------------------------------
+void __fastcall Rest(unsigned int uHoursToSleep)
+{
+  unsigned int v1; // esi@1
+  double v2; // st7@3
+  Player **v3; // esi@3
+
+  v1 = uHoursToSleep;
+  if ( uHoursToSleep > 240 )
+    InitializeActors();
+  v2 = (double)(7680 * v1) * 0.033333335;
+  pParty->uTimePlayed += (signed __int64)v2;
+  v3 = &pPlayers[1];
+  do
+  {
+    (*v3)->Recover((signed __int64)v2);
+    ++v3;
+  }
+  while ( (signed int)v3 <= (signed int)&pPlayers[4] );
+  _494035_timed_effects__water_walking_damage__etc();
+}
+
+//----- (00493938) --------------------------------------------------------
+int __cdecl _493938_regenerate()
+{
+  int v0; // edi@1
+  signed __int64 v1; // qax@1
+  int v2; // ecx@1
+  int result; // eax@1
+  int v4; // eax@2
+  int v5; // edi@5
+  char *v6; // ecx@5
+  char v7; // sf@5
+  char *v8; // ecx@10
+  int v9; // edi@15
+  signed int v10; // eax@15
+  __int16 *v11; // edx@16
+  int v12; // eax@20
+  int v13; // ebx@20
+  unsigned int *v14; // esi@21
+  unsigned int v15; // ecx@21
+  unsigned int v16; // eax@21
+  int v17; // edx@21
+  int v18; // eax@21
+  signed int v19; // eax@21
+  signed int v20; // ebx@25
+  Player *v21; // esi@25
+  ITEM_EQUIP_TYPE v22; // edi@30
+  //int v23; // edx@31
+  signed int v24; // ecx@32
+  signed int v25; // eax@33
+  int v26; // eax@35
+  int v27; // eax@36
+  int v28; // eax@37
+  int v29; // eax@40
+  int v30; // eax@41
+  signed int v31; // ecx@53
+  char *v32; // eax@53
+  char *v33; // edi@82
+  int v34; // ecx@88
+  int v35; // eax@88
+  char *v36; // edi@99
+  int v37; // edi@104
+  int v38; // edi@106
+  int v39; // edi@111
+  int v40; // ecx@113
+  char v41[400]; // [sp+4h] [bp-22Ch]@20
+  LayingItem a1; // [sp+194h] [bp-9Ch]@15
+  Vec3_int_ a3; // [sp+204h] [bp-2Ch]@15
+  int v44; // [sp+210h] [bp-20h]@22
+  int v45; // [sp+214h] [bp-1Ch]@25
+  int v46; // [sp+218h] [bp-18h]@25
+  int v47; // [sp+21Ch] [bp-14h]@25
+  int v48; // [sp+220h] [bp-10h]@25
+  int v49; // [sp+224h] [bp-Ch]@24
+  int v50; // [sp+228h] [bp-8h]@25
+  int v51; // [sp+22Ch] [bp-4h]@2
+
+  v0 = (signed int)(signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 60;
+  v1 = (signed __int64)((double)pParty->uLastRegenerationTime * 0.234375);
+  v2 = (signed int)v1 / 60;
+  result = (signed int)v1 / 60 + 5;
+  if ( v0 >= result )
+  {
+    v51 = 0;
+    v4 = (v0 - v2) / 5;
+    if (pParty->FlyActive())
+    {
+      if ( pParty->bFlying )
+      {
+        if ( !(pParty->pPartyBuffs[7].uFlags & 1) )
+        {
+          v5 = v4 * pParty->pPartyBuffs[7].uPower;
+          __debugbreak();
+          v6 = &stru_AA1058[4].pSounds[6972 * pParty->pPartyBuffs[7].uCaster + 2000];
+          v7 = *(int *)v6 - v5 < 0;
+          *(int *)v6 -= v5;
+          if ( v7 )
+          {
+            *(int *)v6 = 0;
+            pParty->uFlags &= 0xFFFFFFBFu;
+            pParty->bFlying = 0;
+            v51 = 1;
+          }
+        }
+      }
+    }
+    if (pParty->WaterWalkActive())
+    {
+      if (pParty->uFlags & 0x80 )
+      {
+        if ( !(pParty->pPartyBuffs[18].uFlags & 1) )
+        {
+          __debugbreak();
+          v8 = &stru_AA1058[4].pSounds[6972 * pParty->pPartyBuffs[18].uCaster + 2000];
+          v7 = *(int *)v8 - v4 < 0;
+          *(int *)v8 -= v4;
+          if ( v7 )
+          {
+            *(int *)v8 = 0;
+            LOBYTE(pParty->uFlags) &= 0x7Fu;
+            v51 = 1;
+          }
+        }
+      }
+    }
+    if (pParty->ImmolationActive())
+    {
+      //LayingItem::LayingItem(&a1);
+      v9 = 0;
+      a3.z = 0;
+      a3.y = 0;
+      a3.x = 0;
+      a1.stru_24.Reset();
+      a1.field_4C = pParty->pPartyBuffs[10].uPower;
+      a1.field_50 = pParty->ImmolationSkillLevel();
+      v10 = 0;
+      a1.uItemType = 1070;
+      a1.field_48 = 8;
+      if ( (signed int)pObjectList->uNumObjects <= 0 )
+      {
+LABEL_19:
+        LOWORD(v10) = 0;
+      }
+      else
+      {
+        v11 = &pObjectList->pObjects->uObjectID;
+        while ( stru_4E3ACC[8].uItemType != *v11 )
+        {
+          ++v10;
+          v11 += 28;
+          if ( v10 >= (signed int)pObjectList->uNumObjects )
+            goto LABEL_19;
+        }
+      }
+      a1.uObjectDescID = v10;
+      a1.field_60_distance_related_prolly_lod = 0;
+      v12 = 8 * pParty->pPartyBuffs[10].uCaster;
+      LOBYTE(v12) = v12 | 4;
+      a1.uAttributes = 0;
+      a1.uSectorID = 0;
+      a1.uSpriteFrameID = 0;
+      a1.field_58 = v12;
+      a1.uFacing = 0;
+      a1.uSoundID = 0;
+      v13 = sub_46A89E((int)v41, 100, 307);
+      if ( v13 > 0 )
+      {
+        do
+        {
+          v14 = (unsigned int *)&v41[4 * v9];
+          v15 = *v14;
+          v16 = *v14;
+          a1.vPosition.x = pActors[v16].vPosition.x;
+          v17 = pActors[v16].vPosition.y;
+          a1.vPosition.z = pActors[v16].vPosition.z;
+          v18 = 8 * v15;
+          LOBYTE(v18) = 8 * v15 | 3;
+          a1.vPosition.y = v17;
+          a1.field_5C = v18;
+          v19 = a1.Create(0, 0, 0, 0);
+          DamageMonsterFromParty(8 * v19 | 2, *v14, &a3);
+          ++v9;
+        }
+        while ( v9 < v13 );
+      }
+    }
+    v44 = 0;
+    if ( sub_476387() == 1 )
+      v44 = 1;
+    v49 = 0;
+LABEL_25:
+    v20 = 0;
+    v21 = &pParty->pPlayers[v49];
+    v50 = 0;
+    v47 = 0;
+    v45 = 0;
+    v48 = 0;
+    v46 = 0;
+    if ( v44 && v21->uClass == 31 )
+      v50 = 1;
+    if ( v21->uClass == 35 )
+      v48 = 1;
+    v22 = (ITEM_EQUIP_TYPE)0;
+    while ( 1 )
+    {
+      if ( v21->HasItemEquipped(v22) )
+      {
+        //v23 = v21->pEquipment.pIndices;
+        auto _idx = v21->pEquipment.pIndices[v22];
+        v24 = v21->pInventoryItems[_idx].uItemID;
+        if ( v24 > 134 )
+        {
+          if ( v24 == 529 )
+            goto LABEL_43;
+          if ( v24 == 535 )
+            goto LABEL_44;
+          if ( v24 == 515 )
+          {
+            v47 = 1;
+          }
+          else
+          {
+            if ( v24 == 532 )
+              goto LABEL_50;
+          }
+        }
+        else
+        {
+          v25 = v21->pInventoryItems[_idx].uAdditionalValue;
+          if ( v25 <= 50 )
+          {
+            if ( v25 != 50 )
+            {
+              v26 = v25 - 37;
+              if ( v26 )
+              {
+                v27 = v26 - 1;
+                if ( !v27 )
+                  goto LABEL_50;
+                v28 = v27 - 6;
+                if ( v28 )
+                {
+                  if ( v28 != 3 )
+                    goto LABEL_51;
+LABEL_50:
+                  v50 = 1;
+                  goto LABEL_51;
+                }
+              }
+            }
+LABEL_44:
+            v20 = 1;
+            goto LABEL_51;
+          }
+          v29 = v25 - 54;
+          if ( !v29 )
+            goto LABEL_44;
+          v30 = v29 - 1;
+          if ( !v30 )
+            goto LABEL_50;
+          if ( v30 == 11 )
+          {
+LABEL_43:
+            v20 = 1;
+            v50 = 1;
+            goto LABEL_51;
+          }
+        }
+      }
+LABEL_51:
+      v22 = (ITEM_EQUIP_TYPE)((int)v22 + 1);
+      if ( (signed int)v22 >= 16 )
+      {
+        if ( v48 )
+        {
+          v31 = 0;
+          v32 = (char *)v21->pInventoryItems;
+          while ( *(int *)v32 != 601 || (unsigned __int8)v32[26] != v49 + 1 )
+          {
+            ++v31;
+            v32 += 36;
+            if ( v31 >= 138 )
+              goto LABEL_59;
+          }
+          v48 = 0;
+          v45 = 1;
+        }
+LABEL_59:
+        if ( v21->pConditions[17] )
+          v46 = 1;
+        if ( v20 && !v21->pConditions[14] && !v21->pConditions[16] )
+        {
+          ++v21->sHealth;
+          if ( v21->sHealth > v21->GetMaxHealth() )
+            v21->sHealth = v21->GetMaxHealth();
+          if ( v21->pConditions[13] && v21->sHealth > 0 )
+          {
+            LODWORD(v21->pConditions[13]) = 0;
+            HIDWORD(v21->pConditions[13]) = 0;
+          }
+          v51 = 1;
+        }
+        if ( SHIDWORD(v21->pPlayerBuffs[12].uExpireTime) >= 0
+          && (SHIDWORD(v21->pPlayerBuffs[12].uExpireTime) > 0 || LODWORD(v21->pPlayerBuffs[12].uExpireTime))
+          && !v21->pConditions[14]
+          && !v21->pConditions[16] )
+        {
+          v21->sHealth += 5 * v21->pPlayerBuffs[12].uPower;
+          if ( v21->sHealth > v21->GetMaxHealth() )
+            v21->sHealth = v21->GetMaxHealth();
+          if ( v21->pConditions[13] && v21->sHealth > 0 )
+          {
+            LODWORD(v21->pConditions[13]) = 0;
+            HIDWORD(v21->pConditions[13]) = 0;
+          }
+          v51 = 1;
+        }
+        if ( v50 )
+        {
+          v33 = (char *)&v21->sMana;
+          ++*(int *)v33;
+          if ( v21->sMana > v21->GetMaxMana() )
+            *(int *)v33 = v21->GetMaxMana();
+          v51 = 1;
+        }
+        if ( v47 && !v21->pConditions[14] && !v21->pConditions[16] )
+        {
+          v34 = LODWORD(v21->pConditions[13]);
+          --v21->sHealth;
+          v35 = v21->sHealth;
+          if ( !(HIDWORD(v21->pConditions[13]) | v34) && v35 < 0 )
+            v21->pConditions[13] = pParty->uTimePlayed;
+          if ( v35 < 1 )
+          {
+            if ( v21->sHealth + v21->uEndurance + v21->GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0) >= 1
+              || (signed __int64)v21->pPlayerBuffs[11].uExpireTime > 0 )
+            {
+              v21->pConditions[13] = pParty->uTimePlayed;
+            }
+            else
+            {
+              if ( !v21->pConditions[14] )
+                v21->pConditions[14] = pParty->uTimePlayed;
+            }
+          }
+          v51 = 1;
+        }
+        if ( v45 )
+        {
+          v36 = (char *)&v21->sMana;
+          ++*(int *)v36;
+          if ( v21->sMana > v21->GetMaxMana() )
+            *(int *)v36 = v21->GetMaxMana();
+        }
+        if ( v48 && !v21->pConditions[14] && !v21->pConditions[16] )
+        {
+          v37 = v21->sHealth;
+          if ( v37 > v21->GetMaxHealth() / 2 )
+            v21->sHealth = v37 - 2;
+          v38 = v21->sMana;
+          if ( v38 > v21->GetMaxMana() / 2 )
+            v21->sMana = v38 - 2;
+        }
+        if ( v46 && !v21->pConditions[14] && !v21->pConditions[16] )
+        {
+          v39 = v21->sHealth;
+          if ( v39 > v21->GetMaxHealth() / 2 )
+            v21->sHealth = v39 - 1;
+          v40 = v21->sMana;
+          if ( v40 > 0 )
+            v21->sMana = v40 - 1;
+        }
+        ++v49;
+        if ( v49 >= 4 )
+        {
+          result = HIDWORD(pParty->uTimePlayed);
+          pParty->uLastRegenerationTime = pParty->uTimePlayed;
+          if ( !viewparams->bRedrawGameUI )
+          {
+            result = v51;
+            viewparams->bRedrawGameUI = v51;
+          }
+          return result;
+        }
+        goto LABEL_25;
+      }
+    }
+  }
+  return result;
+}
+
+
+
+//----- (00493F79) --------------------------------------------------------
+int sub_493F79(stru351 *_this, __int64 a2)
+{
+  signed __int64 v2; // ST2C_8@1
+  signed __int64 v3; // qax@1
+  signed __int64 v4; // ST1C_8@1
+  unsigned __int64 v5; // qax@1
+  unsigned int v6; // ebx@1
+  int result; // eax@1
+
+  v2 = (signed __int64)((double)a2 * 0.234375);
+  v3 = v2 / 60 / 60;
+  v4 = v3;
+  v5 = (unsigned int)v3 / 0x18;
+  v6 = (unsigned int)(v5 / 7) >> 2;
+  _this->field_0 = v2 % 60;
+  _this->field_4 = v2 / 60 % 60;
+  _this->field_8 = v4 % 24;
+  _this->field_10 = v5 / 7 & 3;
+  _this->field_C = (unsigned int)v5 % 0x1C;
+  result = v6 / 0xC + 1168;
+  _this->field_14 = v6 % 0xC;
+  _this->field_18 = result;
+  return result;
+}
+
+
+
+
+
+//----- (00494035) --------------------------------------------------------
+void __cdecl _494035_timed_effects__water_walking_damage__etc()
+{
+  signed __int64 v0; // qax@1
+  signed __int64 v1; // ST30_8@1
+  signed __int64 v2; // ST38_8@1
+  unsigned __int64 v3; // qax@1
+  unsigned int v4; // edi@1
+  //signed int v5; // eax@4
+  //char *v6; // ecx@5
+  //Player *v7; // esi@8
+  //char *v8; // ecx@12
+  Player *pPlayer; // esi@15
+  //void *v10; // esi@25
+  unsigned int v11; // ecx@27
+  signed int v12; // edi@29
+  Player *v13; // ecx@30
+  Player *v14; // esi@35
+  double v15; // st7@35
+  Player **v16; // esi@43
+  Player *v17; // edi@44
+  double v18; // st7@44
+  float v19; // ST28_4@48
+  double v20; // ST38_8@48
+  Player *v21; // esi@51
+  signed int v22; // edi@53
+  int v23; // eax@59
+  int v24; // ecx@60
+  int v25; // eax@63
+  int v26; // ecx@64
+  int v27; // eax@67
+  int v28; // ecx@68
+  int v29; // eax@71
+  int v30; // ecx@72
+  int v31; // eax@75
+  int v32; // ecx@76
+  int v33; // eax@79
+  int v34; // ecx@80
+  int v35; // eax@83
+  int v36; // ecx@84
+  int v37; // eax@87
+  int v38; // ecx@88
+  int v39; // eax@91
+  int v40; // ecx@92
+  int v41; // eax@95
+  int v42; // ecx@96
+  bool v43; // ebx@102
+  //SpellBuff *v44; // edi@104
+  //signed int v45; // ebp@104
+  bool v46; // edi@111
+  //SpellBuff *v47; // esi@113
+  //Player **v48; // esi@119
+  //signed int v49; // edi@121
+  //char *v50; // esi@122
+  signed int v51; // edx@128
+  signed int v52; // ecx@130
+  int v53; // eax@131
+  Player *v54; // eax@141
+  unsigned int v55; // [sp-8h] [bp-38h]@18
+  unsigned int v56; // [sp-8h] [bp-38h]@55
+  int v57; // [sp-4h] [bp-34h]@18
+  int v58; // [sp-4h] [bp-34h]@33
+  int v59; // [sp-4h] [bp-34h]@55
+  unsigned int v60; // [sp+10h] [bp-20h]@1
+  unsigned int v61; // [sp+14h] [bp-1Ch]@1
+  Player **v62; // [sp+14h] [bp-1Ch]@50
+  unsigned int a2; // [sp+18h] [bp-18h]@1
+  signed int a2a; // [sp+18h] [bp-18h]@47
+  signed int v65; // [sp+1Ch] [bp-14h]@47
+
+  a2 = pParty->uCurrentHour;
+  v61 = pParty->uDaysPlayed;
+  v60 = pEventTimer->uTimeElapsed;
+  pParty->uTimePlayed += (signed int)pEventTimer->uTimeElapsed;
+  v0 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 60;
+  v1 = v0;
+  v0 /= 60i64;
+  v2 = v0;
+  v3 = (unsigned int)v0 / 24;
+  v4 = (unsigned int)(v3 / 7) >> 2;
+  pParty->uCurrentTimeSecond = (signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) % 60;
+  pParty->uCurrentMinute = v1 % 60;
+  pParty->uCurrentMonthWeek = v3 / 7 & 3;
+  pParty->uCurrentHour = v2 % 24;
+  pParty->uDaysPlayed = (unsigned int)v3 % 28;
+  pParty->uCurrentMonth = v4 % 12;
+  pParty->uCurrentYear = v4 / 0xC + 1168;
+  if ( pParty->uCurrentHour >= 3 && ((signed int)a2 < 3 || (unsigned int)v3 % 28 > v61) )
+  {
+    pParty->pHirelings[0].bHasUsedTheAbility = false;
+    pParty->pHirelings[1].bHasUsedTheAbility = false;
+
+    for (uint i = 0; i < pNPCStats->uNumNewNPCs; ++i)
+      pNPCStats->pNewNPCData[i].bHasUsedTheAbility = false;
+
+    ++pParty->field_764;
+    if ( pParty->field_764 > 1u )
+    {
+      for (uint i = 0; i < 4; ++i)
+        pParty->pPlayers[i].SetCondition(1, 0);
+
+      if ( pParty->uNumFoodRations )
+      {
+        Party::TakeFood(1u);
+      }
+      else
+      {
+        for (uint i = 0; i < 4; ++i)
+          pParty->pPlayers[i].sHealth = pParty->pPlayers[i].sHealth / ((unsigned __int8)pParty->field_764 + 1) + 1;
+      }
+      if ( pParty->field_764 > 3u )
+      {
+        pPlayer = pParty->pPlayers;
+        do
+        {
+          pPlayer->Zero();
+          if ( !(pPlayer->pConditions[15] | pPlayer->pConditions[16] | pPlayer->pConditions[14]) )
+          {
+            if ( rand() % 100 < 5 * (unsigned __int8)pParty->field_764 )
+            {
+              v57 = 0;
+              v55 = 14;
+LABEL_21:
+              pPlayer->SetCondition(v55, v57);
+              goto LABEL_22;
+            }
+            if ( rand() % 100 < 10 * (unsigned __int8)pParty->field_764 )
+            {
+              v57 = 0;
+              v55 = 5;
+              goto LABEL_21;
+            }
+          }
+LABEL_22:
+          ++pPlayer;
+        }
+        while ( (signed int)pPlayer < (signed int)pParty->pHirelings );
+      }
+    }
+    if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+      pOutdoor->SetFog();
+
+    for (uint i = 0; i < 4; ++i)
+      pParty->pPlayers[i].uNumDivineInterventionCastsThisDay = 0;
+  }
+  v11 = LODWORD(pParty->uTimePlayed);
+  if ( pParty->uFlags & 4 && pParty->field_6FC < (signed __int64)pParty->uTimePlayed )
+  {
+    v12 = 1;
+    pParty->field_6FC = LODWORD(pParty->uTimePlayed) + 128;
+    viewparams->bRedrawGameUI = 1;
+    while ( 1 )
+    {
+      if ( pPlayers[v12]->WearsItem(516, 3)
+        || v13->HasEnchantedItemEquipped(71)
+        || (signed __int64)v13->pPlayerBuffs[23].uExpireTime > 0 )
+      {
+        v58 = 0;
+      }
+      else
+      {
+        v58 = 0;
+        if ( !sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(v12) )
+        {
+          v14 = pPlayers[v12];
+          v15 = (double)pPlayers[v12]->GetMaxHealth() * 0.1;
+          v14->ReceiveDamage((signed __int64)v15, 0);
+          if ( pParty->uFlags & 4 )
+          {
+            strcpy(GameUI_StatusBar_TimedString, pGlobalTXT_LocalizationStrings[660]);
+            GameUI_StatusBar_TimedStringTimeLeft = 128;
+          }
+          goto LABEL_39;
+        }
+        v13 = pPlayers[v12];
+      }
+      v13->PlayEmotion(37, v58);
+LABEL_39:
+      ++v12;
+      if ( v12 > 4 )
+      {
+        v11 = LODWORD(pParty->uTimePlayed);
+        break;
+      }
+    }
+  }
+  if ( pParty->uFlags & 0x200 && pParty->field_6FC < (signed __int64)__PAIR__(HIDWORD(pParty->uTimePlayed), v11) )
+  {
+    viewparams->bRedrawGameUI = 1;
+    pParty->field_6FC = v11 + 128;
+    v16 = &pPlayers[1];
+    do
+    {
+      v17 = *v16;
+      v18 = (double)(*v16)->GetMaxHealth() * 0.1;
+      v17->ReceiveDamage((signed __int64)v18, 0);
+      if ( pParty->uFlags & 0x200 )
+      {
+        strcpy(GameUI_StatusBar_TimedString, pGlobalTXT_LocalizationStrings[661]);
+        GameUI_StatusBar_TimedStringTimeLeft = 128;
+      }
+      ++v16;
+    }
+    while ( (signed int)v16 <= (signed int)&pPlayers[4] );
+  }
+  _493938_regenerate();
+  v65 = 4;
+  a2a = v60;
+  if ( pParty->uFlags2 & 2 )
+  {
+    v19 = (double)(signed int)v60 * 0.5;
+    v20 = v19 + 6.7553994e15;
+    a2a = LODWORD(v20);
+    if ( SLODWORD(v20) <= 0 )
+      a2a = 1;
+  }
+  v62 = &pPlayers[1];
+  do
+  {
+    v21 = *v62;
+    if ( (*v62)->uTimeToRecovery )
+      v21->Recover(a2a);
+    v22 = v21->sHealth;
+    if ( v21->GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0) + v22 + v21->uEndurance >= 1
+      || (signed __int64)v21->pPlayerBuffs[11].uExpireTime > 0 )
+    {
+      if ( v22 >= 1 )
+        goto LABEL_59;
+      v59 = 0;
+      v56 = 13;
+    }
+    else
+    {
+      v59 = 0;
+      v56 = 14;
+    }
+    v21->SetCondition(v56, v59);
+LABEL_59:
+    v23 = (int)&v21->field_E0;
+    if ( v21->field_E0 )
+    {
+      v24 = *(int *)v23 - v60;
+      if ( v24 > 0 )
+      {
+        *(int *)v23 = v24;
+      }
+      else
+      {
+        *(int *)v23 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v25 = (int)&v21->field_E4;
+    if ( v21->field_E4 )
+    {
+      v26 = *(int *)v25 - v60;
+      if ( v26 > 0 )
+      {
+        *(int *)v25 = v26;
+      }
+      else
+      {
+        *(int *)v25 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v27 = (int)&v21->field_E8;
+    if ( v21->field_E8 )
+    {
+      v28 = *(int *)v27 - v60;
+      if ( v28 > 0 )
+      {
+        *(int *)v27 = v28;
+      }
+      else
+      {
+        *(int *)v27 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v29 = (int)&v21->field_EC;
+    if ( v21->field_EC )
+    {
+      v30 = *(int *)v29 - v60;
+      if ( v30 > 0 )
+      {
+        *(int *)v29 = v30;
+      }
+      else
+      {
+        *(int *)v29 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v31 = (int)&v21->field_F0;
+    if ( v21->field_F0 )
+    {
+      v32 = *(int *)v31 - v60;
+      if ( v32 > 0 )
+      {
+        *(int *)v31 = v32;
+      }
+      else
+      {
+        *(int *)v31 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v33 = (int)&v21->field_F4;
+    if ( v21->field_F4 )
+    {
+      v34 = *(int *)v33 - v60;
+      if ( v34 > 0 )
+      {
+        *(int *)v33 = v34;
+      }
+      else
+      {
+        *(int *)v33 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v35 = (int)&v21->field_F8;
+    if ( v21->field_F8 )
+    {
+      v36 = *(int *)v35 - v60;
+      if ( v36 > 0 )
+      {
+        *(int *)v35 = v36;
+      }
+      else
+      {
+        *(int *)v35 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v37 = (int)&v21->field_FC;
+    if ( v21->field_FC )
+    {
+      v38 = *(int *)v37 - v60;
+      if ( v38 > 0 )
+      {
+        *(int *)v37 = v38;
+      }
+      else
+      {
+        *(int *)v37 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v39 = (int)&v21->field_100;
+    if ( v21->field_100 )
+    {
+      v40 = *(int *)v39 - v60;
+      if ( v40 > 0 )
+      {
+        *(int *)v39 = v40;
+      }
+      else
+      {
+        *(int *)v39 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    v41 = (int)&v21->field_104;
+    if ( v21->field_104 )
+    {
+      v42 = *(int *)v41 - v60;
+      if ( v42 > 0 )
+      {
+        *(int *)v41 = v42;
+      }
+      else
+      {
+        *(int *)v41 = 0;
+        viewparams->bRedrawGameUI = 1;
+      }
+    }
+    if ( v21->pConditions[2] | v21->pConditions[12] | v21->pConditions[13] | v21->pConditions[14] | v21->pConditions[15] | v21->pConditions[16] )
+      --v65;
+    v43 = (signed __int64)v21->pPlayerBuffs[7].uExpireTime > 0;
+
+    for (uint k = 0; k < 24; ++k)
+      v21->pPlayerBuffs[k]._4585CA(pParty->uTimePlayed);
+
+    if ( v43 && (signed __int64)v21->pPlayerBuffs[7].uExpireTime <= 0 )
+      v21->SetCondition(1u, 0);
+    ++v62;
+  }
+  while ( (signed int)v62 <= (signed int)&pPlayers[4] );
+  v46 = (signed __int64)pParty->pPartyBuffs[8].uExpireTime > 0;
+
+  for (uint i = 0; i < 20; ++i)
+  {
+    if (pParty->pPartyBuffs[i]._4585CA(pParty->uTimePlayed) == 1)
+      viewparams->bRedrawGameUI = 1;
+  }
+
+  if ( v46 && (signed __int64)pParty->pPartyBuffs[8].uExpireTime <= 0 )
+  {
+    for (uint i = 0; i < 4; ++i)
+      pParty->pPlayers[i].SetCondition(1, 0);
+  }
+
+  for (uint i = 0; i < 2; ++i)
+  {
+    auto pBuf = &pParty->pPartyBuffs[dword_4EE07C[i]];
+    if (pBuf->uExpireTime == 0)
+      continue;
+
+    if ( !(pBuf->uFlags & 1) )
+    {
+      if (!pPlayers[pBuf->uCaster]->CanAct())
+      {
+        pBuf->Reset();
+        if (dword_4EE07C[i] == 7 )
+          pParty->bFlying = false;
+      }
+    }
+  }
+
+  v51 = v65;
+  if ( v65 )
+    goto LABEL_135;
+  if ( pCurrentScreen != 5 )
+  {
+    v52 = (signed int)&pPlayers[1];
+    while ( 1 )
+    {
+      v53 = *(int *)v52;
+      if ( *(_QWORD *)(*(int *)v52 + 16) )
+        break;
+      v52 += 4;
+      if ( v52 > (signed int)&pPlayers[4] )
+        goto LABEL_135;
+    }
+    *(int *)(v53 + 16) = 0;
+    *(int *)(v53 + 20) = 0;
+    v51 = 1;
+LABEL_135:
+    if ( pCurrentScreen != 5
+      && (!v51 || dword_5C35C0) )
+      uGameState = 8;
+  }
+  if ( uActiveCharacter )
+  {
+    if ( pCurrentScreen != 5 )
+    {
+      v54 = pPlayers[uActiveCharacter];
+      if ( v54->pConditions[2]
+        || v54->pConditions[12]
+        || v54->pConditions[13]
+        || v54->pConditions[14]
+        || v54->pConditions[15]
+        || v54->pConditions[16] )
+      {
+        viewparams->bRedrawGameUI = 1;
+        uActiveCharacter = pParty->GetNextActiveCharacter();
+      }
+    }
+  }
+}
+
+//----- (00494820) --------------------------------------------------------
+unsigned int __fastcall sub_494820(unsigned int a1)
+{
+  signed int v1; // eax@1
+
+  v1 = 5;
+  if ( a1 % 0x18 >= 5 )
+    v1 = 29;
+  return v1 - a1 % 0x18;
+}
+
+//----- (00494836) --------------------------------------------------------
+int stru339_spell_sound::_494836(int uSoundID, int a6)
+{
+  int v3; // esi@1
+  int result; // eax@1
+  stru339_spell_sound *v5; // ebx@1
+  int *v6; // edi@2
+  unsigned int v7; // eax@3
+  int v8; // [sp+Ch] [bp-8h]@3
+  int v9; // [sp+10h] [bp-4h]@2
+  int a2a; // [sp+1Ch] [bp+8h]@1
+
+  v3 = 0;
+  result = word_4EE088_sound_ids[uSoundID];
+  v5 = this;
+  a2a = word_4EE088_sound_ids[uSoundID];
+  if ( result )
+  {
+    v9 = 0;
+    v6 = this->pSoundsOffsets;
+    do
+    {
+      v7 = a2a++;
+      result = pSoundList->LoadSound(v7, (char *)v5 + v3, 44744 - v3, &v8, a6);
+      if ( !result )
+        break;
+      a6 += 4;
+      result = v8 + 256;
+      *v6 = v3;
+      v3 += result;
+      ++v9;
+      *(v6 - 2) = result;
+      ++v6;
+    }
+    while ( v9 < 2 );
+  }
+  return result;
+}
+// 4EE088: using guessed type __int16 word_4EE088_sound_ids[];
+
+
+
+//----- (00494AED) --------------------------------------------------------
+unsigned int PlayerFrameTable::GetFrameIdBy_field0(int uField0)
+{
+  unsigned int _uNumFrames; // edx@1
+  unsigned int result; // eax@1
+  PlayerFrame *v4; // ecx@2
+
+  _uNumFrames = this->uNumFrames;
+  result = 0;
+  if ( (signed int)this->uNumFrames <= 0 )
+  {
+LABEL_5:
+    result = 0;
+  }
+  else
+  {
+    v4 = this->pFrames;
+    while ( v4->uSequenceID != uField0 )
+    {
+      ++result;
+      ++v4;
+      if ( (signed int)result >= (signed int)_uNumFrames )
+        goto LABEL_5;
+    }
+  }
+  return result;
+}
+
+//----- (00494B10) --------------------------------------------------------
+PlayerFrame *PlayerFrameTable::GetFrameBy_x(unsigned int uFramesetID, unsigned int uFrameID)
+{
+  unsigned int v3; // esi@1
+  PlayerFrame *v4; // edi@1
+  PlayerFrame *v5; // ecx@1
+  __int16 v6; // dx@2
+  int v7; // edx@3
+  char *i; // eax@3
+  int v9; // ecx@5
+  PlayerFrame *result; // eax@6
+
+  v3 = uFramesetID;
+  v4 = this->pFrames;
+  v5 = &v4[uFramesetID];
+  if ( v5->uFlags & 1 && (v6 = v5->uAnimLength) != 0 )
+  {
+    v7 = ((signed int)uFrameID >> 3) % (unsigned __int16)v6;
+    for ( i = (char *)&v5->uAnimTime; ; i += 10 )
+    {
+      v9 = *(short *)i;
+      if ( v7 <= v9 )
+        break;
+      v7 -= v9;
+      ++v3;
+    }
+    result = &v4[v3];
+  }
+  else
+  {
+    result = &v4[uFramesetID];
+  }
+  return result;
+}
+
+//----- (00494B5E) --------------------------------------------------------
+PlayerFrame *PlayerFrameTable::GetFrameBy_y(int *a2, int *a3, int a4)
+{
+  PlayerFrameTable *v4; // edi@1
+  int v5; // esi@1
+  int v6; // eax@2
+
+  v4 = this;
+  v5 = a4 + *a3;
+  if ( v5 < 8 * this->pFrames[*a2].uAnimTime )
+  {
+    *a3 = v5;
+  }
+  else
+  {
+    v6 = rand() % 4 + 21;
+    *a2 = v6;
+    *a3 = 8 * v5 % v4->pFrames[v6].uAnimTime;
+  }
+  return &v4->pFrames[*a2];
+}
+
+//----- (00494BC3) --------------------------------------------------------
+void PlayerFrameTable::ToFile()
+{
+  PlayerFrameTable *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  auto Str = this;
+
+  v1 = Str;
+  v2 = fopen("data\\dpft.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dpft.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pFrames, 0xAu, v1->uNumFrames, v3);
+  fclose(v3);
+}
+
+//----- (00494C0F) --------------------------------------------------------
+void PlayerFrameTable::FromFile(void *pSerialized)
+{
+  uNumFrames = *(int *)pSerialized;
+  pFrames = (PlayerFrame *)pAllocator->AllocNamedChunk(pFrames, 10 * uNumFrames, "P Frames");
+  memcpy(pFrames, (char *)pSerialized + 4, 10 * uNumFrames);
+}
+
+//----- (00494C5A) --------------------------------------------------------
+int PlayerFrameTable::FromFileTxt(const char *Args)
+{
+  PlayerFrameTable *v2; // ebx@1
+  FILE *v3; // eax@1
+  int v4; // esi@3
+  void *v5; // eax@10
+  FILE *v6; // ST0C_4@12
+  char *i; // eax@12
+  __int16 v8; // ax@15
+  const char *v9; // ST10_4@15
+  unsigned __int16 v10; // ax@15
+  const char *v11; // ST0C_4@15
+  int j; // esi@15
+  int v13; // eax@17
+  int v14; // edx@22
+  int v15; // ecx@23
+  int v16; // eax@24
+  signed int k; // eax@27
+  PlayerFrame *v18; // edx@28
+  int v19; // esi@28
+  int l; // ecx@29
+  char Buf; // [sp+Ch] [bp-2F8h]@3
+  FrameTableTxtLine v23; // [sp+200h] [bp-104h]@4
+  FrameTableTxtLine v24; // [sp+27Ch] [bp-88h]@4
+  int v25; // [sp+2F8h] [bp-Ch]@3
+  int v26; // [sp+2FCh] [bp-8h]@3
+  FILE *File; // [sp+300h] [bp-4h]@1
+  int Argsa; // [sp+30Ch] [bp+8h]@28
+
+  v2 = this;
+  //TileTable::dtor((TileTable *)this);
+  v3 = fopen(Args, "r");
+  File = v3;
+  if ( !v3 )
+    Abortf("PlayerFrameTable::load - Unable to open file: %s.", Args);
+  v4 = 0;
+  v25 = 0;
+  v26 = 1;
+  if ( fgets(&Buf, 490, v3) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v24, texture_frame_table_txt_parser(&Buf, &v23), sizeof(v24));
+      if ( v24.field_0 && *v24.pProperties[0] != 47 )
+      {
+        if ( v24.field_0 < 3 )
+          Abortf("PlayerFrameTable::load, too few arguments, %s line %i.", Args, v26);
+        ++v25;
+      }
+      ++v26;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v4 = v25;
+  }
+  v2->uNumFrames = v4;
+  v5 = pAllocator->AllocNamedChunk(v2->pFrames, 10 * v4, "P Frames");
+  v2->pFrames = (PlayerFrame *)v5;
+  if ( !v5 )
+    Abortf("PlayerFrameTable::load - Out of Memory!");
+  v6 = File;
+  v2->uNumFrames = 0;
+  fseek(v6, 0, 0);
+  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+  {
+    *strchr(&Buf, 10) = 0;
+    memcpy(&v24, texture_frame_table_txt_parser(&Buf, &v23), sizeof(v24));
+    if ( v24.field_0 && *v24.pProperties[0] != 47 )
+    {
+      v8 = atoi(v24.pProperties[0]);
+      v9 = v24.pProperties[1];
+      v2->pFrames[v2->uNumFrames].uSequenceID = v8;
+      v10 = atoi(v9);
+      v11 = v24.pProperties[2];
+      v2->pFrames[v2->uNumFrames].uTextureID = v10;
+      v2->pFrames[v2->uNumFrames].uAnimTime = atoi(v11);
+      v2->pFrames[v2->uNumFrames].uAnimLength = 0;
+      v2->pFrames[v2->uNumFrames].uFlags = 0;
+      for ( j = 3; j < v24.field_0; ++j )
+      {
+        if ( !_strcmpi(v24.pProperties[j], "New") )
+        {
+          v13 = (int)&v2->pFrames[v2->uNumFrames].uFlags;
+          *(char *)v13 |= 4u;
+        }
+      }
+      ++v2->uNumFrames;
+    }
+  }
+  fclose(File);
+  v14 = 0;
+  if ( (signed int)(v2->uNumFrames - 1) > 0 )
+  {
+    v15 = 0;
+    do
+    {
+      v16 = (int)&v2->pFrames[v15];
+      if ( !(*(char *)(v16 + 18) & 4) )
+        *(char *)(v16 + 8) |= 1u;
+      ++v14;
+      ++v15;
+    }
+    while ( v14 < (signed int)(v2->uNumFrames - 1) );
+  }
+  for ( k = 0; k < (signed int)v2->uNumFrames; *(short *)(Argsa + 6) = v19 )
+  {
+    v18 = v2->pFrames;
+    Argsa = (int)&v18[k];
+    v19 = *(short *)(Argsa + 4);
+    if ( *(char *)(Argsa + 8) & 1 )
+    {
+      ++k;
+      for ( l = (int)&v18[k]; *(char *)(l + 8) & 1; l += 10 )
+      {
+        v19 += *(short *)(l + 4);
+        ++k;
+      }
+      LOWORD(v19) = v18[k].uAnimTime + v19;
+    }
+    ++k;
+  }
+  return 1;
+}
+
+//----- (00494F3A) --------------------------------------------------------
+unsigned int IconFrameTable::FindIcon(const char *pIconName)
+{
+  IconFrameTable *v2; // esi@1
+  int v3; // ebx@1
+  unsigned int uID; // edi@1
+  unsigned int result; // eax@4
+
+  v2 = this;
+  v3 = 0;
+  uID = 0;
+  if ( (signed int)this->uNumIcons <= 0 )
+  {
+LABEL_4:
+    result = 0;
+  }
+  else
+  {
+    while ( _strcmpi(pIconName, v2->pIcons[v3].pAnimationName) )
+    {
+      ++uID;
+      ++v3;
+      if ( (signed int)uID >= (signed int)v2->uNumIcons )
+        goto LABEL_4;
+    }
+    result = uID;
+  }
+  return result;
+}
+
+//----- (00494F70) --------------------------------------------------------
+IconFrame *IconFrameTable::GetFrame(unsigned int uIconID, unsigned int uFrameID)
+{
+  IconFrame *v3; // edi@1
+  IconFrame *v4; // ecx@1
+  __int16 v5; // dx@2
+  int v6; // edx@3
+  unsigned int v7; // eax@3
+  char *i; // ecx@3
+  int v9; // esi@5
+  IconFrame *result; // eax@6
+
+  v3 = this->pIcons;
+  v4 = &v3[uIconID];
+  if ( v4->uFlags & 1 && (v5 = v4->uAnimLength) != 0 )
+  {
+    v6 = ((signed int)uFrameID >> 3) % (unsigned __int16)v5;
+    v7 = uIconID;
+    for ( i = (char *)&v4->uAnimTime; ; i += 32 )
+    {
+      v9 = *(short *)i;
+      if ( v6 <= v9 )
+        break;
+      v6 -= v9;
+      ++v7;
+    }
+    result = &v3[v7];
+  }
+  else
+  {
+    result = &v3[uIconID];
+  }
+  return result;
+}
+
+//----- (00494FBF) --------------------------------------------------------
+void IconFrameTable::InitializeAnimation(unsigned int uIconID)
+{
+  IconFrameTable *v2; // esi@1
+  unsigned int v3; // edi@3
+  const char *i; // eax@3
+  IconFrame *v5; // eax@5
+
+  v2 = this;
+  if ( (signed int)uIconID <= (signed int)this->uNumIcons && (uIconID & 0x80000000u) == 0 )
+  {
+    v3 = uIconID;
+    for ( i = this->pIcons[uIconID].pTextureName; ; i = v5[v3].pTextureName )
+    {
+      v2->pIcons[v3].uTextureID = pIcons_LOD->LoadTexture(i, TEXTURE_16BIT_PALETTE);
+      v5 = v2->pIcons;
+      if ( !(v5[v3].uFlags & 1) )
+        break;
+      ++v3;
+    }
+  }
+}
+
+//----- (0049500A) --------------------------------------------------------
+void IconFrameTable::ToFile()
+{
+  IconFrameTable *v1; // esi@1
+  FILE *v2; // eax@1
+  FILE *v3; // edi@1
+
+  auto Str = this;
+
+  v1 = Str;
+  v2 = fopen("data\\dift.bin", "wb");
+  v3 = v2;
+  if ( !v2 )
+    Abortf("Unable to save dift.bin!");
+  fwrite(v1, 4u, 1u, v2);
+  fwrite(v1->pIcons, 0x20u, v1->uNumIcons, v3);
+  fclose(v3);
+}
+
+//----- (00495056) --------------------------------------------------------
+void IconFrameTable::FromFile(void *pSerialized)
+{
+  uNumIcons = *(int *)pSerialized;
+  pIcons = (IconFrame *)pAllocator->AllocNamedChunk(pIcons, 32 * uNumIcons, "I Frames");
+  memcpy(pIcons, (char *)pSerialized + 4, 32 * uNumIcons);
+}
+
+//----- (0049509D) --------------------------------------------------------
+int IconFrameTable::FromFileTxt(const char *Args)
+{
+  IconFrameTable *v2; // ebx@1
+  FILE *v3; // eax@1
+  int v4; // esi@3
+  void *v5; // eax@10
+  FILE *v6; // ST0C_4@12
+  char *i; // eax@12
+  const char *v8; // ST00_4@15
+  int v9; // eax@16
+  int v10; // edx@20
+  int v11; // ecx@21
+  int v12; // eax@22
+  signed int j; // edx@25
+  IconFrame *v14; // ecx@26
+  int v15; // esi@26
+  int k; // eax@27
+  signed int result; // eax@11
+  char Buf; // [sp+Ch] [bp-2F8h]@3
+  FrameTableTxtLine v19; // [sp+200h] [bp-104h]@4
+  FrameTableTxtLine v20; // [sp+27Ch] [bp-88h]@4
+  int v21; // [sp+2F8h] [bp-Ch]@3
+  int v22; // [sp+2FCh] [bp-8h]@3
+  FILE *File; // [sp+300h] [bp-4h]@1
+  int Argsa; // [sp+30Ch] [bp+8h]@26
+
+  v2 = this;
+  //TileTable::dtor((TileTable *)this);
+  v3 = fopen(Args, "r");
+  File = v3;
+  if ( !v3 )
+    Abortf("IconFrameTable::load - Unable to open file: %s.", Args);
+  v4 = 0;
+  v21 = 0;
+  v22 = 1;
+  if ( fgets(&Buf, 490, v3) )
+  {
+    do
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v20, frame_table_txt_parser(&Buf, &v19), sizeof(v20));
+      if ( v20.field_0 && *v20.pProperties[0] != 47 )
+      {
+        if ( v20.field_0 < 3 )
+          Abortf("IconFrameTable::loadText, too few arguments, %s line %i.", Args, v22);
+        ++v21;
+      }
+      ++v22;
+    }
+    while ( fgets(&Buf, 490, File) );
+    v4 = v21;
+  }
+  v2->uNumIcons = v4;
+  v5 = pAllocator->AllocNamedChunk(v2->pIcons, 32 * v4, "I Frames");
+  v2->pIcons = (IconFrame *)v5;
+  if ( v5 )
+  {
+    v6 = File;
+    v2->uNumIcons = 0;
+    fseek(v6, 0, 0);
+    for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
+    {
+      *strchr(&Buf, 10) = 0;
+      memcpy(&v20, frame_table_txt_parser(&Buf, &v19), sizeof(v20));
+      if ( v20.field_0 && *v20.pProperties[0] != 47 )
+      {
+        strcpy(v2->pIcons[v2->uNumIcons].pAnimationName, v20.pProperties[0]);
+        strcpy(v2->pIcons[v2->uNumIcons].pTextureName, v20.pProperties[1]);
+        v8 = v20.pProperties[2];
+        v2->pIcons[v2->uNumIcons].uFlags = 0;
+        if ( !_strcmpi(v8, "new") )
+        {
+          v9 = (int)&v2->pIcons[v2->uNumIcons].uFlags;
+          *(char *)v9 |= 4u;
+        }
+        v2->pIcons[v2->uNumIcons].uAnimTime = atoi(v20.pProperties[3]);
+        v2->pIcons[v2->uNumIcons].uAnimLength = 0;
+        v2->pIcons[v2->uNumIcons++].uTextureID = 0;
+      }
+    }
+    fclose(File);
+    v10 = 0;
+    if ( (signed int)(v2->uNumIcons - 1) > 0 )
+    {
+      v11 = 0;
+      do
+      {
+        v12 = (int)&v2->pIcons[v11];
+        if ( !(*(char *)(v12 + 60) & 4) )
+          *(char *)(v12 + 28) |= 1u;
+        ++v10;
+        ++v11;
+      }
+      while ( v10 < (signed int)(v2->uNumIcons - 1) );
+    }
+    for ( j = 0; j < (signed int)v2->uNumIcons; *(short *)(Argsa + 26) = v15 )
+    {
+      v14 = v2->pIcons;
+      Argsa = (int)&v14[j];
+      v15 = *(short *)(Argsa + 24);
+      if ( *(char *)(Argsa + 28) & 1 )
+      {
+        ++j;
+        for ( k = (int)&v14[j]; *(char *)(k + 28) & 1; k += 32 )
+        {
+          v15 += *(short *)(k + 24);
+          ++j;
+        }
+        LOWORD(v15) = v14[j].uAnimTime + v15;
+      }
+      ++j;
+    }
+    result = 1;
+  }
+  else
+  {
+    fclose(File);
+    result = 0;
+  }
+  return result;
+}
+
+
+
+//----- (00495366) --------------------------------------------------------
+char *__fastcall sub_495366(unsigned __int8 a1, unsigned __int8 a2)
+{
+  int v2; // edi@1
+  int v3; // edx@2
+  int v4; // esi@3
+  int v5; // ebx@5
+  signed int v7; // [sp+Ch] [bp-14h]@1
+  signed int v8; // [sp+10h] [bp-10h]@1
+  int **v9; // [sp+14h] [bp-Ch]@4
+  signed int v10; // [sp+18h] [bp-8h]@3
+  unsigned __int8 v11; // [sp+1Ch] [bp-4h]@1
+
+  v2 = a1;
+  v11 = a2;
+  v8 = 0;
+  v7 = 0;
+  if ( dword_AE336C == a1 )
+  {
+    v3 = dword_AE3370;
+  }
+  else
+  {
+    v4 = a2;
+    dword_AE336C = a1;
+    v10 = 0;
+    if ( (signed int)pNPCStats->uNumNPCNames[v4] <= 0 )
+      goto LABEL_17;
+    v9 = (int **)((char *)pNPCStats->pNPCNames + v4 * 4);
+    do
+    {
+      v5 = tolower(*(char *)*v9);
+      if ( v5 == tolower(v2) )
+      {
+        if ( v8 )
+          v7 = v10;
+        else
+          v8 = v10;
+      }
+      ++v10;
+      v9 += 2;
+    }
+    while ( v10 < (signed int)pNPCStats->uNumNPCNames[v4] );
+    if ( v8 && v8 != v7 )
+      v3 = v8 + rand() % (v7 - v8);
+    else
+LABEL_17:
+      v3 = rand() % (signed int)pNPCStats->uNumNPCNames[v4];
+  }
+  dword_AE3370 = v3;
+  return pNPCStats->pNPCNames[0][v11 + 2 * v3];
+}
+// AE336C: using guessed type int dword_AE336C;
+// AE3370: using guessed type int dword_AE3370;
+
+//----- (00495430) --------------------------------------------------------
+char *__fastcall GetReputationString(signed int a1)
+{
+  char *result; // eax@2
+
+  if ( a1 < 25 )
+  {
+    if ( a1 < 6 )
+    {
+      if ( a1 < -5 )
+      {
+        result = pGlobalTXT_LocalizationStrings[402];
+        if ( a1 < -24 )
+          result = pGlobalTXT_LocalizationStrings[434];
+      }
+      else
+      {
+        result = pGlobalTXT_LocalizationStrings[399];
+      }
+    }
+    else
+    {
+      result = pGlobalTXT_LocalizationStrings[392];
+    }
+  }
+  else
+  {
+    result = pGlobalTXT_LocalizationStrings[379];
+  }
+  return result;
+}
+
+//----- (00495461) --------------------------------------------------------
+char *__fastcall sub_495461(char *lpsz, unsigned __int8 uPlayerID, ItemGen *a3, char *a4, int a5, __int64 *a6)
+{
+  unsigned __int8 v6; // bl@1
+  Player *pPlayer; // ebx@3
+  NPCData *v9; // eax@4
+  size_t v10; // eax@6
+  char *v11; // esi@7
+  int v12; // edx@7
+  ItemGen *v13; // edi@7
+  char v14; // cl@8
+  char *v15; // ecx@10
+  int v16; // edx@10
+  int v17; // eax@10
+  signed __int64 v18; // qax@18
+  unsigned int v19; // edi@32
+  unsigned __int8 *v20; // ebx@32
+  int v21; // ecx@34
+  __int16 v22; // ax@34
+  int v23; // edx@39
+  int v24; // eax@39
+  int v25; // eax@45
+  float *v26; // esi@68
+  float v27; // ST18_4@68
+  signed int v28; // eax@68
+  int v29; // eax@68
+  float v30; // ST18_4@72
+  signed int v31; // eax@72
+  float v32; // ST18_4@74
+  signed int v33; // eax@74
+  double v34; // st7@75
+  float v35; // ST18_4@76
+  signed int v36; // eax@76
+  float *v37; // esi@78
+  float v38; // ST18_4@78
+  int v39; // eax@78
+  float v40; // ST18_4@82
+  int v41; // eax@82
+  float v42; // ST18_4@83
+  int v43; // eax@83
+  float v44; // ST18_4@85
+  int v45; // eax@85
+  const char *v46; // eax@86
+  unsigned int v47; // eax@87
+  float v48; // ST18_4@97
+  __int64 v49; // ST14_8@107
+  int v50; // eax@107
+  int v51; // eax@108
+  Player *v52; // eax@109
+  int v53; // [sp-4h] [bp-13Ch]@107
+  int v54; // [sp+0h] [bp-138h]@107
+  __int16 v55[56]; // [sp+10h] [bp-128h]@34
+  stru351 v56; // [sp+80h] [bp-B8h]@107
+  stru351 v57; // [sp+9Ch] [bp-9Ch]@115
+  char a1[100]; // [sp+B8h] [bp-80h]@3
+  unsigned int v59; // [sp+11Ch] [bp-1Ch]@3
+  size_t v60; // [sp+120h] [bp-18h]@3
+  Player *v61; // [sp+124h] [bp-14h]@3
+  char *Str; // [sp+128h] [bp-10h]@1
+  int v63; // [sp+12Ch] [bp-Ch]@32
+  int v64; // [sp+130h] [bp-8h]@6
+  NPCData *v65; // [sp+134h] [bp-4h]@6
+
+  v6 = uPlayerID;
+  Str = lpsz;
+  if ( IsBadStringPtrA(lpsz, 1u) )
+    return "Invalid String Passed";
+  v60 = strlen(Str);
+  a1[0] = 0;
+  pPlayer = &pParty->pPlayers[v6];
+  v59 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v61 = pPlayer;
+  memset(pTmpBuf2, 0, 0x7D0u);
+  if ( dword_5C35D4 )
+    v9 = array_5913D8[(unsigned int)((char *)array_5913D8[6] + -(dword_591080 != 0) - 1)];
+  else
+    v9 = GetNPCData(uDialogue_SpeakingActorNPC_ID);
+  v65 = v9;
+  v10 = 0;
+  v64 = 0;
+  if ( (signed int)v60 > 0 )
+  {
+    v11 = a4;
+    v12 = v64;
+    v13 = a3;
+    while ( 1 )
+    {
+      v14 = Str[v12];
+      if ( v14 == 37 )
+        break;
+      pTmpBuf2[v10++] = v14;
+LABEL_119:
+      ++v12;
+      v64 = v12;
+      if ( v12 >= (signed int)v60 )
+        return pTmpBuf2;
+    }
+    v15 = &Str[v12 + 1];
+    v16 = (unsigned __int8)Str[v12 + 2];
+    v17 = v16 + 10 * (unsigned __int8)*v15 - 528;
+    if ( v17 <= 15 )
+    {
+      if ( v17 != 15 )
+      {
+        switch ( v16 + 10 * (unsigned __int8)*v15 )
+        {
+          case 0x211:
+            v11 = v65->pName;
+            goto LABEL_118;
+          case 0x212:
+            v11 = pPlayer->pName;
+            goto LABEL_118;
+          case 0x213:
+          case 0x219:
+            if ( v65->uSex )
+              v11 = pGlobalTXT_LocalizationStrings[384];// "her"
+            else
+              v11 = pGlobalTXT_LocalizationStrings[383];// "his"
+            goto LABEL_118;
+          case 0x215:
+            v18 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 60 / 60 % 24;
+            v11 = pGlobalTXT_LocalizationStrings[397];// "evening"
+            if ( SHIDWORD(v18) <= 0 && SHIDWORD(v18) >= 0 && (unsigned int)v18 >= 5 && SHIDWORD(v18) <= 0 )
+            {
+              if ( SHIDWORD(v18) >= 0 && (unsigned int)v18 >= 0xB )
+              {
+                if ( v18 < 20 )
+                  v11 = pGlobalTXT_LocalizationStrings[396];// "day"
+              }
+              else
+              {
+                v11 = pGlobalTXT_LocalizationStrings[395];// "morning"
+              }
+            }
+            goto LABEL_118;
+          case 0x216:
+            if ( pPlayer->uSex )
+              v11 = pGlobalTXT_LocalizationStrings[387];// "lady"
+            else
+              v11 = pGlobalTXT_LocalizationStrings[385];// "sir"
+            goto LABEL_118;
+          case 0x217:
+            if ( pPlayer->uSex )
+              goto LABEL_43;
+            v11 = pGlobalTXT_LocalizationStrings[386];// "Sir"
+            goto LABEL_118;
+          case 0x218:
+            v19 = 0;
+            v63 = 0;
+            v20 = (unsigned __int8 *)v61->field_152;
+            do
+            {
+              if ( (unsigned __int16)_449B57_test_bit(v20, word_4EE150[v19]) )
+              {
+                v21 = v63;
+                v22 = word_4EE150[v19];
+                ++v63;
+                v55[v21] = v22;
+              }
+              ++v19;
+            }
+            while ( v19 < 28 );
+            if ( v63 )
+            {
+              v23 = rand() % v63;
+              v24 = dword_A74CDC;
+              if ( dword_A74CDC == -1 )
+              {
+                v24 = v23;
+                dword_A74CDC = v23;
+              }
+              v11 = (char *)dword_723E80_award_related[2 * v55[v24]];
+            }
+            else
+            {
+              v11 = (char *)pNPCTopics[55].pText;
+            }
+            pPlayer = v61;
+            v13 = a3;
+            goto LABEL_118;
+          case 0x21A:
+            if ( pPlayer->uSex )
+LABEL_43:
+              v11 = pGlobalTXT_LocalizationStrings[389];// "Lady"
+            else
+              v11 = pGlobalTXT_LocalizationStrings[388];// "Lord"
+            goto LABEL_118;
+          case 0x21B:
+            v25 = GetPartyReputation();
+            goto LABEL_46;
+          case 0x21C:
+            v25 = v65->rep;
+LABEL_46:
+            if ( v25 >= 25 )
+            {
+              v11 = pGlobalTXT_LocalizationStrings[379];
+            }
+            else
+            {
+              if ( v25 < 6 )
+              {
+                if ( v25 >= -5 )
+                {
+                  v11 = pGlobalTXT_LocalizationStrings[399];
+                }
+                else
+                {
+                  if ( v25 < -24 )
+                    v11 = pGlobalTXT_LocalizationStrings[434];
+                  else
+                    v11 = pGlobalTXT_LocalizationStrings[402];
+                }
+              }
+              else
+              {
+                v11 = pGlobalTXT_LocalizationStrings[392];
+              }
+            }
+            goto LABEL_118;
+          case 0x21D:
+            v11 = sub_495366(pPlayer->pName[0], pPlayer->uSex);
+            goto LABEL_118;
+          case 0x21E:
+            goto LABEL_93;
+          case 0x214:
+            goto LABEL_117;
+          default:
+            goto LABEL_108;
+        }
+        goto LABEL_108;
+      }
+      v11 = pGlobalTXT_LocalizationStrings[393];// "daughter"
+LABEL_118:
+      strcat(pTmpBuf2, v11);
+      v10 = strlen(pTmpBuf2);
+      v64 += 2;
+      v12 = v64;
+      goto LABEL_119;
+    }
+    if ( v17 <= 29 )
+    {
+      if ( v17 == 29 )
+      {
+        //v34 = p2DEvents_minus1__20[13 * (signed int)a4];
+        v34 = p2DEvents[(signed int)a4 - 1].fPriceMultiplier;
+      }
+      else
+      {
+        if ( v16 + 10 * (unsigned __int8)*v15 == 544 )
+        {
+LABEL_93:
+          if ( v65->uSex )
+            v11 = pGlobalTXT_LocalizationStrings[391];// "sister"
+          else
+            v11 = pGlobalTXT_LocalizationStrings[390];// "brother"
+          goto LABEL_118;
+        }
+        if ( v16 + 10 * (unsigned __int8)*v15 == 545 )
+        {
+          v29 = *(&pNPCStats->field_13A58 + 5 * v65->uProfession) / 100;
+          goto LABEL_91;
+        }
+        if ( v16 + 10 * (unsigned __int8)*v15 == 551 )
+        {
+          v47 = pMapStats->GetMapInfo(pCurrentMapName);
+          if ( v47 )
+            v11 = pMapStats->pInfos[v47].pName;
+          else
+            v11 = pGlobalTXT_LocalizationStrings[394];// "Unknown"
+          goto LABEL_118;
+        }
+        if ( v16 + 10 * (unsigned __int8)*v15 == 552 )
+        {
+          v46 = v13->GetDisplayName();
+          sprintf(a1, format_4E2D80, v59, v46);
+LABEL_117:
+          v11 = a1;
+          goto LABEL_118;
+        }
+        if ( v16 + 10 * (unsigned __int8)*v15 == 553 )
+        {
+          //v37 = &p2DEvents_minus1__20[13 * (signed int)a4];
+          v37 = &p2DEvents[(signed int)a4 - 1].fPriceMultiplier;
+          v38 = *v37;
+          v39 = v13->GetValue();
+          v29 = pPlayer->_4B8233(v39, v38);
+          switch ( a5 )
+          {
+            case 3:
+              v44 = *v37;
+              v45 = v13->GetValue();
+              v29 = pPlayer->_4B8213(v45, v44);
+              break;
+            case 4:
+              v29 = pPlayer->_4B824B(*v37);
+              break;
+            case 5:
+              v42 = *v37;
+              v43 = v13->GetValue();
+              v29 = pPlayer->_4B8265(v43, v42);
+              break;
+            case 6:
+              v40 = *v37;
+              v41 = v13->GetValue();
+              v29 = pPlayer->_4B8213(v41, v40) / 2;
+              break;
+          }
+          goto LABEL_98;
+        }
+        if ( v16 + 10 * (unsigned __int8)*v15 != 555 )
+        {
+          if ( v16 + 10 * (unsigned __int8)*v15 == 556 )
+          {
+            //v11 = (char *)p2DEvents_minus1__10[13 * (signed int)a4];
+            v11 = (char *)p2DEvents[(signed int)a4 - 1].pProprieterTitle;
+            goto LABEL_118;
+          }
+LABEL_108:
+          strncpy(a1, v15, 2u);
+          v51 = atoi(a1);
+          sprintf(a1, "%lu", v51);
+          goto LABEL_117;
+        }
+        v26 = &p2DEvents[(signed int)a4 - 1].fPriceMultiplier;
+        v27 = *v26;
+        v28 = v13->GetValue();
+        v29 = pPlayer->_4B8142(v28, v27);
+        if ( a5 == 3 )
+        {
+          v35 = *v26;
+          v36 = v13->GetValue();
+          v29 = pPlayer->_4B8102(v36, v35);
+          if ( v13->uAttributes & 2 )
+          {
+LABEL_77:
+            v29 = 1;
+            goto LABEL_98;
+          }
+          goto LABEL_98;
+        }
+        if ( a5 != 4 )
+        {
+          if ( a5 == 5 )
+          {
+            v32 = *v26;
+            v33 = v13->GetValue();
+            v29 = pPlayer->_4B81C3(v33, v32);
+          }
+          else
+          {
+            if ( a5 == 6 )
+            {
+              v30 = *v26;
+              v31 = v13->GetValue();
+              v29 = pPlayer->_4B8102(v31, v30) / 2;
+              if ( v13->uAttributes & 2 )
+                v29 = 1;
+LABEL_91:
+              if ( v29 >= 1 )
+                goto LABEL_98;
+              goto LABEL_77;
+            }
+          }
+LABEL_98:
+          sprintf(a1, "%lu", v29);
+          goto LABEL_117;
+        }
+        v34 = *v26;
+      }
+      v48 = v34;
+      v29 = pPlayer->_4B8179(v48);
+      goto LABEL_98;
+    }
+    if ( v17 != 30 )
+    {
+      switch ( v17 )
+      {
+        case 31:
+          v52 = pPlayers[1];
+          break;
+        case 32:
+          v52 = pPlayers[2];
+          break;
+        case 33:
+          v52 = pPlayers[3];
+          break;
+        default:
+          if ( v17 != 34 )
+          {
+            if ( v17 <= 50 || v17 > 70 )
+              goto LABEL_108;
+            if ( v16 + 10 * (unsigned __int8)*v15 - 579 >= 20 )
+              goto LABEL_118;
+            HIDWORD(v49) = pParty->field_3C.field_440[2 * v17 + 1];
+            LODWORD(v49) = pParty->field_3C.field_440[2 * v17];
+            sub_493F79(&v56, v49);
+            v54 = v56.field_18;
+            v53 = v56.field_C + 1;
+            v50 = v56.field_14;
+LABEL_116:
+            sprintf(a1, pGlobalTXT_LocalizationStrings[378], aMonthNames[v50], v53, v54);
+            goto LABEL_117;
+          }
+          v52 = pPlayers[4];
+          break;
+      }
+      v11 = v52->pName;
+      goto LABEL_118;
+    }
+    if ( !a6 )
+      goto LABEL_118;
+    sub_493F79(&v57, *a6);
+    v54 = v57.field_18;
+    v53 = v57.field_C + 1;
+    v50 = v57.field_14;
+    goto LABEL_116;
+  }
+  return pTmpBuf2;
+}
+
+//----- (00495B39) --------------------------------------------------------
+void __cdecl PlayerCreationUI_Draw()
+{
+  const char *uTitleText; // ST10_4@3
+  int pTextCenter; // eax@3
+  IconFrame *v3; // eax@3
+  int v4; // ecx@7
+  GUIButton *uPosActiveItem; // edi@12
+  int v6; // esi@14
+  int uNumLet; // eax@14
+  char v8; // al@17
+  int v9; // ecx@17
+  char v10; // sf@17
+  int v11; // ecx@19
+  void *v12; // eax@20
+  int v13; // ecx@21
+  int v14; // ecx@22
+  char *v15; // ST14_4@24
+  size_t v16; // eax@28
+  int v17; // eax@33
+  enum CHARACTER_RACE uNumRace; // eax@35
+  int v19; // eax@36
+  int v20; // eax@37
+  int uNumMight; // eax@44
+  unsigned int v24; // eax@44
+  int v25; // eax@44
+  unsigned int v26; // eax@44
+  int v27; // eax@44
+  unsigned int v28; // eax@44
+  int v29; // eax@44
+  unsigned int v30; // eax@44
+  int v31; // eax@44
+  unsigned int v32; // eax@44
+  int v33; // eax@44
+  unsigned int v34; // eax@44
+  int v35; // eax@44
+  unsigned int v36; // eax@44
+  enum PLAYER_SKILL_TYPE v37; // eax@44
+  enum PLAYER_SKILL_TYPE v39; // eax@44
+  enum PLAYER_SKILL_TYPE v41; // eax@44
+  const char *v42; // edx@44
+  char *v43; // ST1C_4@44
+  int v45; // eax@44
+  enum PLAYER_SKILL_TYPE v46; // eax@46
+  const char *v47; // edx@46
+  char *v48; // ST1C_4@46
+  int v50; // eax@46
+  int v51; // eax@49
+  char *v52; // edi@52
+  char v53; // al@52
+  int uClassType; // edi@53
+  int v55; // ST0C_4@53
+  int v57; // eax@53
+  int v61; // ecx@55
+  int v64; // ST08_4@57
+  int v66; // ecx@57
+  int v71; // eax@59
+  int v75; // eax@61
+  int v80; // eax@63
+  int v85; // eax@65
+  int v89; // eax@67
+  int v94; // eax@69
+  enum PLAYER_SKILL_TYPE pSkillId; // edi@72
+  size_t pLenText; // eax@72
+  signed int v104; // ecx@72
+  int pColorText; // ecx@79
+  unsigned int v107; // ST0C_4@81
+  int pTextY; // ST08_4@81
+  int v111; // ST0C_4@82
+  signed int v113; // edi@82
+  int v114; // ST0C_4@82
+  const char *uRaceName; // [sp+0h] [bp-170h]@39
+  char pText[200]; // [sp+10h] [bp-160h]@14
+  GUIWindow pWindow; // [sp+D8h] [bp-98h]@83
+  int v119; // [sp+12Ch] [bp-44h]@18
+  size_t v120; // [sp+130h] [bp-40h]@25
+  int uY; // [sp+134h] [bp-3Ch]@18
+  int v122; // [sp+138h] [bp-38h]@18
+  int v123; // [sp+13Ch] [bp-34h]@11
+  void *v124; // [sp+140h] [bp-30h]@18
+  int uColor1; // [sp+144h] [bp-2Ch]@1
+  int v126; // [sp+148h] [bp-28h]@25
+  int uColorGreen; // [sp+14Ch] [bp-24h]@1
+  int v128; // [sp+150h] [bp-20h]@14
+  int v129; // [sp+154h] [bp-1Ch]@18
+  int uColorTeal; // [sp+158h] [bp-18h]@1
+  int uColorWhite; // [sp+15Ch] [bp-14h]@1
+  int uX; // [sp+160h] [bp-10h]@18
+  unsigned int v133; // [sp+164h] [bp-Ch]@25
+  int pOrder; // [sp+168h] [bp-8h]@14
+  char *Str; // [sp+16Ch] [bp-4h]@18
+  Player *pPlayer;
+  const char *pSkillName;
+
+  uColor1 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xD1, 0xBB, 0x61);
+  uColorTeal = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xF7, 0xF7);
+  uColorGreen = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFF, 0);
+  uColorWhite = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFF, 0xFF, 0xFF);
+  pRenderer->BeginScene();
+  pRenderer->DrawTextureRGB(0, 0, &pTexture_PCX);
+  uPlayerCreationUI_SkySliderPos = (GetTickCount() % 12800) / 20;
+  pRenderer->DrawTextureIndexed(uPlayerCreationUI_SkySliderPos, 2, pTexture_MAKESKY);
+  pRenderer->DrawTextureIndexed(uPlayerCreationUI_SkySliderPos - 640, 2, pTexture_MAKESKY);
+  //if (uPlayerCreationUI_SkySliderPos > 640)
+    //uPlayerCreationUI_SkySliderPos = 0;
+  pRenderer->DrawTextureTransparent(0, 0, pTexture_MAKETOP);
+  uTitleText = pGlobalTXT_LocalizationStrings[51];
+  uPlayerCreationUI_SelectedCharacter = (pGUIWindow_CurrentMenu->pCurrentPosActiveItem - pGUIWindow_CurrentMenu->pStartingPosActiveItem) / 7;
+  pTextCenter = pFontCChar->AlignText_Center(640, pGlobalTXT_LocalizationStrings[51]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCChar, pTextCenter + 1, 0, 0, uTitleText, 0, 0, 0);
+  pRenderer->DrawTextureTransparent(17, 35, pPlayerPortraits[pParty->pPlayers[0].uFace]);
+  pRenderer->DrawTextureTransparent(176, 35, pPlayerPortraits[pParty->pPlayers[1].uFace]);
+  pRenderer->DrawTextureTransparent(335, 35, pPlayerPortraits[pParty->pPlayers[2].uFace]);
+  pRenderer->DrawTextureTransparent(494, 35, pPlayerPortraits[pParty->pPlayers[3].uFace]);
+  v3 = pIconsFrameTable->GetFrame(uIconID_CharacterFrame, pEventTimer->uStartTime);
+  if ( uPlayerCreationUI_SelectedCharacter )
+  {
+    switch ( uPlayerCreationUI_SelectedCharacter )
+    {
+      case 1:
+        v4 = 171;
+        break;
+      case 2:
+        v4 = 329;
+        break;
+      case 3:
+        v4 = 488;
+        break;
+      default:
+        v4 = v123;
+        break;
+    }
+  }
+  else
+  {
+    v4 = 12;
+  }
+
+  pRenderer->DrawTextureTransparent(v4, 29, &pIcons_LOD->pTextures[v3->uTextureID]);
+  uPosActiveItem = pGUIWindow_CurrentMenu->GetControl(pGUIWindow_CurrentMenu->pCurrentPosActiveItem);
+  uPlayerCreationUI_ArrowAnim = 19 - (GetTickCount() % 500) / 25;
+  pRenderer->DrawTextureTransparent(uPosActiveItem->uZ - 4, uPosActiveItem->uY, pTextures_arrowl[uPlayerCreationUI_ArrowAnim]);
+  pRenderer->DrawTextureTransparent(uPosActiveItem->uX - 12, uPosActiveItem->uY, pTextures_arrowr[uPlayerCreationUI_ArrowAnim]);
+  //if (uPlayerCreationUI_ArrowAnim < 0)
+  //  uPlayerCreationUI_ArrowAnim = 18;
+  v6 = pFontCreate->uFontHeight - 2;
+  v128 = pFontCreate->uFontHeight - 2;
+  memset(pText, 0, 200);
+  strcpy(pText, pGlobalTXT_LocalizationStrings[205]);// "Skills"
+  uNumLet = strlen(pText) - 1;
+  pOrder = uNumLet;
+  if ( uNumLet >= 0 )
+  {
+    while ( 1 )
+    {
+      v8 = toupper((unsigned __int8)pText[uNumLet]);
+      v9 = pOrder;
+      v10 = pOrder-- - 1 < 0;
+      pText[v9] = v8;
+      if ( v10 )
+        break;
+      uNumLet = pOrder;
+    }
+  }
+  pOrder = 18;
+  v124 = 0;
+  uX = 32;
+  uY = 3 * v6 + 169;
+  v122 = 5 * v6 + 169;
+  v123 = 3 * v6 + 311;
+  v129 = 493;
+  //pPlayer = pParty->pPlayers;
+  v119 = 6 * v6 + 169;
+  //do
+  for ( pPlayer = pParty->pPlayers; (signed int)pPlayer->pName < (signed int)&pParty->pPickedItem.uNumCharges; pPlayer++)
+  {
+    Str = pPlayer->pName;
+	pGUIWindow_CurrentMenu->DrawText(pFontCreate, pOrder + 73, 100, 0, pClassNames[(unsigned __int8)pPlayer->uClass], 0, 0, 0);
+    pRenderer->DrawTextureTransparent(pOrder + 77, 50, pTexture_IC_KNIGHT[pPlayer->uClass/4]);
+    v11 = pGUIWindow_CurrentMenu->field_40;
+    if ( v11 && (v12 = pGUIWindow_CurrentMenu->ptr_1C, v12 == v124) )
+    {
+      v13 = v11 - 1;
+      if ( v13 )
+      {
+        v14 = v13 - 1;
+        if ( v14 )
+        {
+          if ( v14 == 1 )
+          {
+            pGUIWindow_CurrentMenu->field_40 = 0;
+            pGUIWindow_CurrentMenu->DrawTextInRect(pFontCreate, pOrder, 124, 0, Str, 130, 0);
+            SetCurrentMenuID(MENU_7);
+          }
+        }
+        else
+        {
+          pGUIWindow_CurrentMenu->field_40 = 0;
+          v120 = strlen((const char *)pKeyActionMap->pPressedKeysBuffer);
+          v126 = 0;
+          v133 = 0;
+          if ( strlen((const char *)pKeyActionMap->pPressedKeysBuffer) )//edit name
+          {
+            do
+            {
+              if ( pKeyActionMap->pPressedKeysBuffer[v133] == ' ' )
+                ++v126;
+              ++v133;
+              v16 = strlen((const char *)pKeyActionMap->pPressedKeysBuffer);
+            }
+            while ( v133 < v16 );
+          }
+          if ( v120 && v126 != v120 )
+            strcpy(Str, (const char *)pKeyActionMap->pPressedKeysBuffer);
+          pGUIWindow_CurrentMenu->DrawTextInRect(pFontCreate, pOrder, 0x7C, 0, Str, 130, 0);
+          *((short *)pPlayer->pName + 3323) = 1; //
+        }
+      }
+      else
+      {
+        v17 = pGUIWindow_CurrentMenu->DrawTextInRect(pFontCreate, 159 * (int)v12 + 18, 0x7Cu, 0, (const char *)pKeyActionMap->pPressedKeysBuffer, 120, 1);
+        pGUIWindow_CurrentMenu->DrawFlashingInputCursor(159 * (unsigned int)pGUIWindow_CurrentMenu->ptr_1C + v17 + 20, 124, pFontCreate);
+      }
+    }
+    else
+    {
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontCreate, pOrder, 0x7C, 0, pPlayer->pName, 130, 0);
+    }
+    uNumRace = pPlayer->GetRace();
+     switch (uNumRace)
+    {
+      case 0:  uRaceName = pGlobalTXT_LocalizationStrings[99]; break; // "Human"       
+      case 1:  uRaceName = pGlobalTXT_LocalizationStrings[103]; break; // "Dwarf"
+      case 2:  uRaceName = pGlobalTXT_LocalizationStrings[106]; break; // "Goblin"
+	  case 3:  uRaceName = pGlobalTXT_LocalizationStrings[101]; break; // "Elf"   
+    }; 
+	strcpy(pTmpBuf, uRaceName);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontCreate, pOrder + 72, v128 + 12, 0, pTmpBuf, 130, 0);
+    pTextCenter = pFontCreate->AlignText_Center(0x96, pText);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + uX - 24, 291, uColor1, pText, 0, 0, 0);
+    uNumMight = pPlayer->GetActualMight();
+    sprintf(pTmpBuf, "%s\r%03d%d", pGlobalTXT_LocalizationStrings[144], v129, uNumMight);// "Might"
+    LOWORD(v24) = pPlayer->GetStatColor(0);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX, 169, v24, pTmpBuf, 0, 0, 0);
+    v25 = pPlayer->GetActualIntelligence();
+    sprintf(pTmpBuf, "%s\r%03d%d", pGlobalTXT_LocalizationStrings[116], v129, v25);// "Intellect"
+    LOWORD(v26) = pPlayer->GetStatColor(1);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX, v128 + 169, v26, pTmpBuf, 0, 0, 0);
+    v27 = pPlayer->GetActualWillpower();
+    sprintf(pTmpBuf, "%s\r%03d%d", pGlobalTXT_LocalizationStrings[163], v129, v27);// "Personality"
+    LOWORD(v28) = pPlayer->GetStatColor(2);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX, 2 * v128 + 169, v28, pTmpBuf, 0, 0, 0);
+    v29 = pPlayer->GetActualEndurance();
+    sprintf(pTmpBuf, "%s\r%03d%d", pGlobalTXT_LocalizationStrings[75], v129, v29);// "Endurance"
+    LOWORD(v30) = pPlayer->GetStatColor(3);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX, uY, v30, pTmpBuf, 0, 0, 0);
+    v31 = pPlayer->GetActualAccuracy();
+    sprintf(pTmpBuf, "%s\r%03d%d", pGlobalTXT_LocalizationStrings[1], v129, v31);// "Accuracy"
+    LOWORD(v32) = pPlayer->GetStatColor(4);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX, 4 * v128 + 169, v32, pTmpBuf, 0, 0, 0);
+    v33 = pPlayer->GetActualSpeed();
+    sprintf(pTmpBuf, "%s\r%03d%d", pGlobalTXT_LocalizationStrings[211], v129, v33);// "Speed"
+    LOWORD(v34) = pPlayer->GetStatColor(5);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX, v122, v34, pTmpBuf, 0, 0, 0);
+    v35 = pPlayer->GetActualLuck();
+    sprintf(pTmpBuf, "%s\r%03d%d", pGlobalTXT_LocalizationStrings[136], v129, v35);// "Luck"
+    LOWORD(v36) = pPlayer->GetStatColor(6u);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX, v119, v36, pTmpBuf, 0, 0, 0);
+    v37 = pPlayer->GetSkillIdxByOrder(0);
+    pTextCenter = pFontCreate->AlignText_Center(0x96u, pSkillNames[v37]);
+    sprintf(pTmpBuf, "\t%03u%s", pTextCenter, pSkillNames[v37]);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX - 24, 311, uColorWhite, pTmpBuf, 0, 0, 0);
+    v39 = pPlayer->GetSkillIdxByOrder(1);
+    pTextCenter = pFontCreate->AlignText_Center(0x96u, pSkillNames[v39]);
+    sprintf(pTmpBuf, "\t%03u%s", pTextCenter, pSkillNames[v39]);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX - 24, v128 + 311, uColorWhite, pTmpBuf, 0, 0, 0);
+    v41 = pPlayer->GetSkillIdxByOrder(2);
+    pTextCenter = pFontCreate->AlignText_Center(150u, pSkillNames[v41]);
+    sprintf(pTmpBuf, "\t%03u%s", pTextCenter, pSkillNames[v41]);
+    v45 = uColorGreen;
+    if ( (signed int)v41 >= 37 )
+      v45 = uColorTeal;
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX - 24, 2 * v128 + 311, v45, pTmpBuf, 0, 0, 0);
+    v46 = pPlayer->GetSkillIdxByOrder(3);
+    pTextCenter = pFontCreate->AlignText_Center(150u, pSkillNames[v46]);
+    sprintf(pTmpBuf, "\t%03u%s", pTextCenter, pSkillNames[v46]);
+    v50 = uColorGreen;
+    if ( (signed int)v46 >= 37 )
+      v50 = uColorTeal;
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, uX - 24, v123, v50, pTmpBuf, 0, 0, 0);
+    //pPlayer++;
+    v124 = (char *)v124 + 1;
+    pOrder += 159;
+    v129 -= 158;
+    uX += 158;
+  }
+  //while ( (signed int)pPlayer->pName < (signed int)&pParty->pPickedItem.uNumCharges );
+  strcpy(pText, pGlobalTXT_LocalizationStrings[41]);// "Class"
+  v51 = strlen(pText) - 1;
+  pOrder = v51;
+  if ( v51 >= 0 )
+  {
+    while ( 1 )
+    {
+      v52 = &pText[v51];
+      v53 = toupper((unsigned __int8)pText[v51]);
+      v10 = pOrder-- - 1 < 0;
+      *v52 = v53;
+      if ( v10 )
+        break;
+      v51 = pOrder;
+    }
+  }
+  uClassType = pParty->pPlayers[uPlayerCreationUI_SelectedCharacter].uClass;
+  pTextCenter = pFontCreate->AlignText_Center(193u, pText);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 324, 395, uColor1, pText, 0, 0, 0);
+  v57 = uColorTeal;
+  if ( uClassType )
+    v57 = uColorWhite;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[0]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 323, 417, v57, pClassNames[0], 0, 0, 0);
+  v61 = uColorTeal;
+  if ( uClassType != PLAYER_CLASS_PALADIN )
+    v61 = uColorWhite;
+  uColorGreen = v128 + 417;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[12]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 323, v128 + 417, v61, pClassNames[12], 0, 0, 0);
+  v66 = uColorTeal;
+  if ( uClassType != PLAYER_CLASS_DRUID )
+    v66 = uColorWhite;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[20]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 323, 2 * v128 + 417, v66, pClassNames[20], 0, 0, 0);
+  v71 = uColorTeal;
+  if ( uClassType != PLAYER_CLASS_CLERIC )
+    v71 = uColorWhite;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[24]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 388, 417, v71, pClassNames[24], 0, 0, 0);
+  v75 = uColorTeal;
+  if ( uClassType != 28 )
+    v75 = uColorWhite;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[28]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 388, uColorGreen, v75, pClassNames[28], 0, 0, 0);
+  v80 = uColorTeal;
+  if ( uClassType != PLAYER_CLASS_SORCERER )
+    v80 = uColorWhite;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[32]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 388, 2 * v128 + 417, v80, pClassNames[32], 0, 0, 0);
+  v85 = uColorTeal;
+  if ( uClassType != PLAYER_CLASS_SHOOTER )
+    v85 = uColorWhite;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[16]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 453, 417, v85, pClassNames[16], 0, 0, 0);
+  v89 = uColorTeal;
+  if ( uClassType != PLAYER_CLASS_MONK )
+    v89 = uColorWhite;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[8]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 453, uColorGreen, v89, pClassNames[8], 0, 0, 0);
+  v94 = uColorTeal;
+  if ( uClassType != PLAYER_CLASS_THEIF )
+    v94 = uColorWhite;
+  pTextCenter = pFontCreate->AlignText_Center(65, pClassNames[4]);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 453, 2 * v128 + 417, v94, pClassNames[4], 0, 0, 0);
+  pTextCenter = pFontCreate->AlignText_Center(0xECu, pGlobalTXT_LocalizationStrings[20]); // "Available Skills"
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 37, 395, uColor1, pGlobalTXT_LocalizationStrings[20], 0, 0, 0);
+  //pOrder = 0;
+  //do
+  for (pOrder = 0; pOrder < 9; ++pOrder)
+  {
+    pSkillId = pParty->pPlayers[uPlayerCreationUI_SelectedCharacter].GetSkillIdxByOrder(pOrder + 4);
+    strcpy(pText, pSkillNames[pSkillId]);
+    pLenText = strlen(pText);
+    v104 = 0;
+    if ( (signed int)pLenText > 0 )
+    {
+	  if ( pText[v104] == 32 )
+	  {
+		pText[v104] = 0;
+	  }
+	  else
+	  {
+		//while ( pText[v104] != 32 )
+		for (v104 = 0; v104 < (signed int)pLenText || pText[v104] != 32; ++v104)
+		{
+		  //++v104;
+		  //if ( v104 >= (signed int)v103 )
+		   //break;
+		}
+	  }
+    }
+    uColorGreen = -5;
+    if ( (signed int)v124 > 2 )
+      uColorGreen = 0;
+    pColorText = uColorTeal;
+    if ( !pParty->pPlayers[uPlayerCreationUI_SelectedCharacter].pActiveSkills[pSkillId] )
+      pColorText = uColorWhite;
+	pTextCenter = pFontCreate->AlignText_Center(100, pText);
+    pGUIWindow_CurrentMenu->DrawText(pFontCreate, 100 * (pOrder / 3) + pTextCenter + uColorGreen + 17, v128 * (pOrder % 3) + 417, pColorText, pText, 0, 0, 0);
+    //++pOrder;
+  }
+  //while ( pOrder < 9 );
+  pTextCenter = pFontCreate->AlignText_Center(0x5C, pGlobalTXT_LocalizationStrings[30]);// "Bonus"
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 533, 394, uColor1, pGlobalTXT_LocalizationStrings[30], 0, 0, 0);
+  v113 = PlayerCreation_ComputeAttributeBonus();
+  sprintf(pTmpBuf, "%d", v113);
+  pTextCenter = pFontCreate->AlignText_Center(84, pTmpBuf);
+  pGUIWindow_CurrentMenu->DrawText(pFontCreate, pTextCenter + 530, 410, uColorWhite, pTmpBuf, 0, 0, 0);
+  if ( GameUI_StatusBar_TimedStringTimeLeft > GetTickCount() )
+  {
+    pWindow.Hint = pGlobalTXT_LocalizationStrings[412];// "Create Party cannot be completed unless you have assigned all characters 2 extra skills and have spent all of your bonus points."
+    if ( v113 < 0 )
+      pWindow.Hint = pGlobalTXT_LocalizationStrings[413];// "You can't spend more than 50 points."
+    pWindow.uFrameWidth = 300;
+    pWindow.uFrameHeight = 100;
+    pWindow.uFrameX = 170;
+    pWindow.uFrameY = 140;
+    pWindow.uFrameZ = 469;
+    pWindow.uFrameW = 239;
+    pWindow.DrawMessageBox(0);
+  }
+  pRenderer->EndScene();
+}
+
+//----- (0049695A) --------------------------------------------------------
+void __cdecl PlayerCreationUI_Initialize()
+{
+  unsigned int v0; // ebx@5
+  unsigned int v1; // eax@6
+  int v2; // ecx@6
+  unsigned int v3; // eax@8
+  signed int v4; // ecx@8
+  signed int uControlParam; // [sp+10h] [bp-Ch]@7
+  unsigned int uControlParama; // [sp+10h] [bp-Ch]@9
+  unsigned int uControlParamb; // [sp+10h] [bp-Ch]@11
+  unsigned int uControlParamc; // [sp+10h] [bp-Ch]@13
+  signed int uControlParamd; // [sp+10h] [bp-Ch]@15
+  signed int uX; // [sp+14h] [bp-8h]@5
+  unsigned int uXa; // [sp+14h] [bp-8h]@9
+  unsigned int uXb; // [sp+14h] [bp-8h]@11
+  unsigned int uXc; // [sp+14h] [bp-8h]@13
+  signed int uXd; // [sp+14h] [bp-8h]@16
+
+  if ( pMessageQueue_50CBD0->uNumMessages )
+    pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+  pAudioPlayer->SetMusicVolume((pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0));
+  ++pIcons_LOD->uTexturePacksCount;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  pCurrentScreen = 21;//îêíî Ñîçäàíèÿ ãðóïïû
+  uPlayerCreationUI_ArrowAnim = 0;
+  uPlayerCreationUI_SkySliderPos = 0;
+  uPlayerCreationUI_SelectedCharacter = 0;
+  v0 = LOBYTE(pFontCreate->uFontHeight) - 2;
+  pTexture_IC_KNIGHT[0] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_KNIGHT", TEXTURE_16BIT_PALETTE)];
+  pTexture_IC_KNIGHT[1] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_THIEF", TEXTURE_16BIT_PALETTE)];
+  pTexture_IC_KNIGHT[2] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_MONK", TEXTURE_16BIT_PALETTE)];
+  pTexture_IC_KNIGHT[3] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_PALAD", TEXTURE_16BIT_PALETTE)];
+  pTexture_IC_KNIGHT[4] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_ARCH", TEXTURE_16BIT_PALETTE)];
+  pTexture_IC_KNIGHT[5] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_RANGER", TEXTURE_16BIT_PALETTE)];
+  pTexture_IC_KNIGHT[6] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_CLER", TEXTURE_16BIT_PALETTE)];
+  pTexture_IC_KNIGHT[7] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_DRUID", TEXTURE_16BIT_PALETTE)];
+  pTexture_IC_KNIGHT[8] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("IC_SORC", TEXTURE_16BIT_PALETTE)];
+  pTexture_MAKETOP   = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("MAKETOP", TEXTURE_16BIT_PALETTE)];
+  uX = 0;
+  pTexture_MAKESKY = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("MAKESKY", TEXTURE_16BIT_PALETTE)];
+  do // load PlayerPortraits texture
+  {
+    sprintf(pTmpBuf, "%s01", pPlayerPortraitsNames[uX]);
+    v1 = pIcons_LOD->LoadTexture(pTmpBuf, TEXTURE_16BIT_PALETTE);
+    v2 = uX * 4;
+    ++uX;
+    *(Texture **)((char *)pPlayerPortraits + v2) = &pIcons_LOD->pTextures[v1];
+  }
+  while ( uX < 22 );
+  pTexture_PlayerFaceMask = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("FACEMASK", TEXTURE_16BIT_PALETTE)];
+  pTexture_buttminu  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("buttminu", TEXTURE_16BIT_PALETTE)];
+  pTexture_buttplus  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("buttplus", TEXTURE_16BIT_PALETTE)];
+  pTexture_pressrigh = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("presrigh", TEXTURE_16BIT_PALETTE)];
+  pTexture_presleft  = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("presleft", TEXTURE_16BIT_PALETTE)];
+  uControlParam = 1;
+  do
+  {
+    sprintf(pTmpBuf, "arrowl%d", uControlParam);
+    pTextures_arrowl[uControlParam] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pTmpBuf, TEXTURE_16BIT_PALETTE)];
+    sprintf(pTmpBuf, "arrowr%d", uControlParam);
+    v3 = pIcons_LOD->LoadTexture(pTmpBuf, TEXTURE_16BIT_PALETTE);
+    v4 = uControlParam++;
+    pTextures_arrowr[v4] = &pIcons_LOD->pTextures[v3];
+  }
+  while ( uControlParam < 20 );
+  pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0);
+  uControlParama = 0;
+  uXa = 8;
+  do
+  {
+    pGUIWindow_CurrentMenu->CreateButton(uXa, 120u, 145u, 25u, 1, 0, 0x3Cu, uControlParama, 0, "", 0);
+    uXa += 158;
+    ++uControlParama;
+  }
+  while ( (signed int)uXa < 640 );
+  pCreationUI_BtnPressLeft[0] = pGUIWindow_CurrentMenu->CreateButton(10, 32, 11, 13, 1, 0, 0xABu, 0, 0, "", pTexture_presleft, 0);
+  pCreationUI_BtnPressLeft[1] = pGUIWindow_CurrentMenu->CreateButton(169, 32, 11, 13, 1, 0, 0xABu, 1, 0, "", pTexture_presleft, 0);
+  pCreationUI_BtnPressLeft[2] = pGUIWindow_CurrentMenu->CreateButton(327, 32, 11, 13, 1, 0, 0xABu, 2, 0, "", pTexture_presleft, 0);
+  pCreationUI_BtnPressLeft[3] = pGUIWindow_CurrentMenu->CreateButton(486, 32, 11, 13, 1, 0, 0xABu, 3, 0, "", pTexture_presleft, 0);
+  pCreationUI_BtnPressRight[0] = pGUIWindow_CurrentMenu->CreateButton(74, 32, 11, 13, 1, 0, 0xACu, 0, 0, "", pTexture_pressrigh, 0);
+  pCreationUI_BtnPressRight[1] = pGUIWindow_CurrentMenu->CreateButton(233, 32, 11, 13, 1, 0, 0xACu, 1, 0, "", pTexture_pressrigh, 0);
+  pCreationUI_BtnPressRight[2] = pGUIWindow_CurrentMenu->CreateButton(391, 32, 11, 13, 1, 0, 0xACu, 2, 0, "", pTexture_pressrigh, 0);
+  pCreationUI_BtnPressRight[3] = pGUIWindow_CurrentMenu->CreateButton(549, 32, 11, 13, 1, 0, 0xACu, 3, 0, "", pTexture_pressrigh, 0);
+  pCreationUI_BtnPressLeft2[0] = pGUIWindow_CurrentMenu->CreateButton(10, 103, 11, 13, 1, 0, 0x90u, 0, 0, "", pTexture_presleft, 0);
+  pCreationUI_BtnPressLeft2[1] = pGUIWindow_CurrentMenu->CreateButton(169, 103, 11, 13, 1, 0, 0x90u, 1, 0, "", pTexture_presleft, 0);
+  pCreationUI_BtnPressLeft2[2] = pGUIWindow_CurrentMenu->CreateButton(327, 103, 11, 13, 1, 0, 0x90u, 2, 0, "", pTexture_presleft, 0);
+  pCreationUI_BtnPressLeft2[3] = pGUIWindow_CurrentMenu->CreateButton(486, 103, 11, 13, 1, 0, 0x90u, 3, 0, "", pTexture_presleft, 0);
+  pCreationUI_BtnPressRight2[0] = pGUIWindow_CurrentMenu->CreateButton(74, 103, 11, 13, 1, 0, 0x91u, 0, 0, "", pTexture_pressrigh, 0);
+  pCreationUI_BtnPressRight2[1] = pGUIWindow_CurrentMenu->CreateButton(233, 103, 11, 13, 1, 0, 0x91u, 1, 0, "", pTexture_pressrigh, 0);
+  pCreationUI_BtnPressRight2[2] = pGUIWindow_CurrentMenu->CreateButton(391, 103, 11, 13, 1, 0, 0x91u, 2, 0, "", pTexture_pressrigh, 0);
+  pCreationUI_BtnPressRight2[3] = pGUIWindow_CurrentMenu->CreateButton(549, 103, 11, 13, 1, 0, 0x91u, 3, 0, "", pTexture_pressrigh, 0);
+  uControlParamb = 0;
+  uXb = 8;
+  do
+  {
+    pGUIWindow_CurrentMenu->CreateButton(uXb, 308, 150, v0, 1, 0, 0x48u, uControlParamb, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXb, v0 + 308, 150, v0, 1, 0, 0x49u, uControlParamb, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXb, 2 * v0 + 308, 150u, v0, 1, 0, 0x4Au, uControlParamb, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXb, 3 * v0 + 308, 150u, v0, 1, 0, 0x4Bu, uControlParamb, 0, "", 0);
+    uXb += 158;
+    ++uControlParamb;
+  }
+  while ( (signed int)uXb < 640 );
+  pGUIWindow_CurrentMenu->CreateButton(5u, 21u, 0x99u, 0x16Du, 1, 0, 0x76u, 0, 0x31u, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(163u, 21u, 0x99u, 0x16Du, 1, 0, 0x76u, 1u, 0x32u, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(321u, 21u, 0x99u, 0x16Du, 1, 0, 0x76u, 2u, 0x33u, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(479u, 21u, 0x99u, 0x16Du, 1, 0, 0x76u, 3u, 0x34u, "", 0);
+  uXc = 23;
+  uControlParamc = 2;
+  do
+  {
+    pGUIWindow_CurrentMenu->CreateButton(uXc, 169, 120, 20, 1, 0, 0, uControlParamc - 2, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXc, v0 + 169, 120, 20, 1, 0, 0, uControlParamc - 1, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXc, 2 * v0 + 169, 120, 20, 1, 0, 0, uControlParamc, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXc, 3 * v0 + 169, 120, 20, 1, 0, 0, uControlParamc + 1, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXc, 4 * v0 + 169, 120, 20, 1, 0, 0, uControlParamc + 2, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXc, 5 * v0 + 169, 120, 20, 1, 0, 0, uControlParamc + 3, 0, "", 0);
+    pGUIWindow_CurrentMenu->CreateButton(uXc, 6 * v0 + 169, 120, 20, 1, 0, 0, uControlParamc + 4, 0, "", 0);
+    uControlParamc += 7;
+    uXc += 158;
+  }
+  while ( (signed int)uControlParamc < 30 );
+  pGUIWindow_CurrentMenu->_41D08F(28, 0, 7, 40);
+  pGUIWindow_CurrentMenu->CreateButton(323, 417, 65, v0, 1, 0, 0x41, 0, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(323, v0 + 417, 65, v0, 1, 0, 0x41, 0xC, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(323, 2 * v0 + 417, 65, v0, 1, 0, 0x41, 0x14, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(388, 417, 65, v0, 1, 0, 0x41, 0x18, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(388, v0 + 417, 65, v0, 1, 0, 0x41, 0x1C, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(388, 2 * v0 + 417, 65, v0, 1, 0, 0x41, 0x20, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(453, 417, 65, v0, 1, 0, 0x41, 0x10, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(453, v0 + 417, 65, v0, 1, 0, 0x41, 8, 0, "", 0);
+  pGUIWindow_CurrentMenu->CreateButton(453, 2 * v0 + 417, 65, v0, 1, 0, 0x41, 4, 0, "", 0);
+  uControlParamd = 0;
+  do
+  {
+    uXd = -5;
+    if ( uControlParamd <= 3 )
+      uXd = 0;
+    pGUIWindow_CurrentMenu->CreateButton(100 * (uControlParamd / 3) + uXd + 17, v0 * (uControlParamd % 3) + 417, 100, v0, 1, 0, 0x40,
+      uControlParamd, 0, "", 0);
+    ++uControlParamd;
+  }
+  while ( uControlParamd < 9 );
+  pPlayerCreationUI_BtnOK = pGUIWindow_CurrentMenu->CreateButton(580, 431, 51, 39, 1, 0, 0x42, 0, 0xD, "",
+                              (Texture *)(uTextureID_BUTTMAKE != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTMAKE] : 0), 0);
+  pPlayerCreationUI_BtnReset = pGUIWindow_CurrentMenu->CreateButton(527, 431, 51, 39, 1, 0, 0x43, 0, 0x43, "",
+                                 (Texture *)(uTextureID_BUTTMAKE2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTMAKE2] : 0), 0);
+  pPlayerCreationUI_BtnMinus = pGUIWindow_CurrentMenu->CreateButton(523, 393, 20, 35, 1, 0, 0x3F, 0, 0x2D, "", pTexture_buttminu, 0);
+  pPlayerCreationUI_BtnPlus = pGUIWindow_CurrentMenu->CreateButton(613, 393, 20, 35, 1, 0, 0x3E, 1, 0x2B, "", pTexture_buttplus, 0);
+  pFontCChar = LoadFont("cchar.fnt", "FONTPAL", 0);
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (0049750E) --------------------------------------------------------
+void __cdecl DeleteCCharFont()
+{
+  pAllocator->FreeChunk(pFontCChar);
+  pFontCChar = 0;
+}
+//----- (00497526) --------------------------------------------------------
+bool __cdecl PlayerCreationUI_Loop()
+{
+  RGBTexture *pTexture; // ebx@1
+  UINT v1; // esi@1
+  unsigned int v2; // ecx@3
+  LONG uMouseX; // edi@6
+  LONG uMouseY; // eax@6
+  GUIButton *pControlsHead; // edx@6
+  unsigned int pNumMessage; // ecx@7
+  int pControlParam; // esi@12
+  signed int v8; // edi@30
+  int v9; // edx@31
+  char *v10; // ebx@37
+  Player *v11; // esi@38
+  signed int uSpellBookPageCount; // ecx@40
+  int v13; // eax@40
+  signed int uSkillIdx; // eax@45
+  int v15; // eax@70
+  signed int v16; // ecx@70
+  unsigned int v18; // [sp-4h] [bp-84h]@48
+  ItemGen item; // [sp+Ch] [bp-74h]@37
+  char v20[32]; // [sp+30h] [bp-50h]@29
+  //char v21; // [sp+31h] [bp-4Fh]@29
+  //__int16 v22; // [sp+4Dh] [bp-33h]@29
+  char v23; // [sp+4Fh] [bp-31h]@29
+  MSG Msg; // [sp+50h] [bp-30h]@17
+  POINT v25; // [sp+6Ch] [bp-14h]@6
+  bool v26; // [sp+74h] [bp-Ch]@1
+  POINT v24; // [sp+78h] [bp-8h]@6
+  Player *pPlayer;
+
+  pTexture = &pTexture_PCX;
+  v1 = 0;
+  v26 = 0;
+  pTexture_PCX.Release();
+  pTexture_PCX.Load("makeme.pcx", 0);
+  if (pAsyncMouse)
+    pAsyncMouse->Resume();
+  v2 = 6;
+  pGUIWindow_CurrentMenu->field_40 = 0;
+LABEL_27:
+  SetCurrentMenuID((MENU_STATE)v2);
+  while ( GetCurrentMenuID() == MENU_CREATEPARTY )
+  {
+    if ( pAsyncMouse != (void *)v1 )
+      pAsyncMouse->_46B736_consume_click_lists(1);
+    uMouseX = pMouse->GetCursorPos(&v24)->x;
+    uMouseY = pMouse->GetCursorPos(&v25)->y;
+    pControlsHead = pGUIWindow_CurrentMenu->pControlsHead;
+    if ( pControlsHead != (GUIButton *)v1 )
+    {
+      pNumMessage = pMessageQueue_50CBD0->uNumMessages;
+      do
+      {
+        if ( uMouseX >= (signed int)pControlsHead->uX && uMouseX <= (signed int)pControlsHead->uZ 
+			&& uMouseY >= (signed int)pControlsHead->uY && uMouseY <= (signed int)pControlsHead->uW )//mouse movement
+        {
+          pControlParam = pControlsHead->uControlParam;
+          if ( (signed int)pNumMessage < 40 )
+          {
+            pMessageQueue_50CBD0->pMessages[pNumMessage].eType = (UIMessageType)pControlsHead->field_1C;
+            pTexture = &pTexture_PCX;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = pControlParam;
+            *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+            pNumMessage = pMessageQueue_50CBD0->uNumMessages + 1;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+          v1 = 0;
+        }
+        pControlsHead = pControlsHead->pNext;
+      }
+      while ( pControlsHead != (GUIButton *)v1 );
+    }
+    while ( PeekMessageA(&Msg, (HWND)v1, v1, v1, PM_REMOVE) )
+    {
+      if ( Msg.message == WM_QUIT )
+        Game_DeinitializeAndTerminate(0);
+      TranslateMessage(&Msg);
+      DispatchMessageA(&Msg);
+    }
+    if ( BYTE1(dword_6BE364_game_settings_1) & 1 )
+    {
+      WaitMessage();
+    }
+    else
+    {
+      PlayerCreationUI_Draw();
+      GUI_MainMenuMessageProc();
+      pRenderer->BeginScene();
+      GUI_UpdateWindows();
+      pRenderer->EndScene();
+      pRenderer->Present();
+      if ( uGameState == 1 )
+      {
+        v26 = 1;
+        v2 = 0;
+        goto LABEL_27;
+      }
+      if ( uGameState == 6 )
+      {
+        uGameState = v1;
+        v2 = 1;
+        goto LABEL_27;
+      }
+    }
+  }
+  pTexture->Release();
+  pGUIWindow_CurrentMenu->Release();
+  pIcons_LOD->_4114F2();
+  v20[0] = 0;
+  memset(&v20[1], 0, 0x1Cu);
+  *(_WORD*)&v20[29] = 0;
+  v20[31] = 0;
+  do
+  {
+    v8 = 0;
+    do
+    {
+      v9 = rand() % 32;
+      if ( !v20[v9] )
+        break;
+      ++v8;
+    }
+    while ( v8 < 10 );
+    if ( v8 == 10 )
+    {
+      v9 = 0;
+      if ( v20[0] )
+      {
+        do
+          ++v9;
+        while ( v20[v9] );
+      }
+    }
+    pParty->field_854[v1++] = v9;
+    v20[v9] = 1;
+  }
+  while ( (signed int)v1 < 32 );
+  item.Reset();
+  //v10 = (char *)&pParty->pPlayers[0].sResMagicBase;
+  for ( pPlayer = &pParty->pPlayers[0];  pPlayer < &pParty->pPlayers[4]; pPlayer++)
+  {
+    //v11 = pPlayer;
+    if ( !pPlayer->uClass )
+      pPlayer->sResMagicBase = 10;
+    //*((short *)v10 + 400) = 0;
+	pPlayer->pPlayerBuffs[22].uExpireTime = 0;
+    uSpellBookPageCount = 0;
+	for ( int i = 0; i < 9; i++)
+    {
+      if ( pPlayer->pActiveSkills[12+i] )
+		  ++uSpellBookPageCount;
+    }
+    pPlayer->pNumSpellBookPage = uSpellBookPageCount;
+    pItemsTable->GenerateItem(2, 40, &item);
+    pPlayer->AddItem2(-1, &item);
+    uSkillIdx = 0;
+    v24.y = 0;
+    do
+    {
+      if ( pPlayer->pActiveSkills[uSkillIdx] )
+      {
+        switch ( uSkillIdx )
+        {
+          case 0:
+            v18 = 61;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 1:
+            v18 = 1;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 2:
+            v18 = 15;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 3:
+            v18 = 23;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 4:
+            v18 = 31;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 5:
+            v18 = 47;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 6:
+            v18 = 50;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 8:
+            v18 = 84;
+  			pPlayer->AddItem(-1, v18);
+            break;
+          case 9:
+            v18 = 66;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 10:
+            v18 = 71;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 11:
+            v18 = 76;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 12:
+            pPlayer->AddItem(-1, 0x191);
+            pPlayer->spellbook.pFireSpellbook.bIsSpellbookAvailable = 1;
+            break;
+          case 13:
+            pPlayer->AddItem(-1, 0x19C);
+            pPlayer->spellbook.pAirSpellbook.bIsSpellbookAvailable = 1;
+            break;
+          case 14:
+            pPlayer->AddItem(-1, 0x1A7);
+			pPlayer->spellbook.pWaterSpellbook.bIsSpellbookAvailable = 1;
+            break;
+          case 15:
+            pPlayer->AddItem(-1, 0x1B2);
+			pPlayer->spellbook.pEarthSpellbook.bIsSpellbookAvailable = 1;
+            break;
+          case 16:
+            pPlayer->AddItem(-1, 0x1BD);
+			pPlayer->spellbook.pSpiritSpellbook.bIsSpellbookAvailable = 1;
+            break;
+          case 17:
+            pPlayer->AddItem(-1, 0x1C8);
+			pPlayer->spellbook.pMindSpellbook.bIsSpellbookAvailable = 1;
+            break;
+          case 18:
+            pPlayer->AddItem(-1, 0x1D3);
+			pPlayer->spellbook.pBodySpellbook.bIsSpellbookAvailable = 1;
+            break;
+          case 21:
+          case 23:
+          case 25:
+          case 26:
+          case 29:
+          case 36:
+            pPlayer->AddItem(-1, 0xDC);
+            v18 = 5 * (rand() % 3 + 40);
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 30:
+            v18 = 115;
+			pPlayer->AddItem(-1, v18);
+            break;
+          case 31:
+            v18 = 110;
+            pPlayer->AddItem(-1, v18);
+            break;
+          default:
+            break;
+        }
+		for ( int i = 0; i < 138; i++)
+        {
+          if ( &pPlayer->pInventoryItems[i] )
+            pPlayer->pInventoryItems[i].uAttributes |= 1;
+         }
+        pPlayer->sHealth = pPlayer->GetMaxHealth();
+        pPlayer->sMana = pPlayer->GetMaxMana();
+        uSkillIdx = v24.y;
+      }
+      ++uSkillIdx;
+      v24.y = uSkillIdx;
+    }
+    while ( uSkillIdx < 37 );
+    //v10 += 6972;
+	//pPlayer++;
+  }
+  //while ( (signed int)v10 < (signed int)((char *)&pParty->field_871C[455] + 2) );
+  pAudioPlayer->StopChannels(-1, -1);
+  if (pAsyncMouse)
+    pAsyncMouse->Suspend();
+  return v26;
+}
+
+//----- (004979D2) --------------------------------------------------------
+MENU_STATE __cdecl CreditsMenu__Loop()
+{
+  char *v0; // eax@5
+  char *v1; // edi@5
+  FILE *pFile; // eax@5
+  unsigned int pSize; // esi@7
+  GUIFont *pFont; // edx@9
+  GUIFont *pFont2; // ecx@9
+  __int16 pHeight; // ax@9
+  void *v7; // eax@9
+  unsigned int pNumPixels; // ST2C_4@9
+  unsigned int teal; // eax@9
+  unsigned int v10; // ST2C_4@19
+  MSG Msg; // [sp+84h] [bp-B8h]@10
+  int v17; // [sp+A0h] [bp-9Ch]@9
+  int pX; // [sp+A4h] [bp-98h]@9
+  unsigned int pY; // [sp+A8h] [bp-94h]@9
+  int v20; // [sp+ACh] [bp-90h]@9
+  int a4; // [sp+B0h] [bp-8Ch]@9
+  int pColor2; // [sp+F8h] [bp-44h]@9
+  int pColor1; // [sp+FCh] [bp-40h]@9
+  int a5; // [sp+128h] [bp-14h]@1
+  char *pString; // [sp+12Ch] [bp-10h]@9
+  char *ptr; // [sp+130h] [bp-Ch]@5
+  GUIFont *pFontQuick; // [sp+134h] [bp-8h]@1
+  GUIFont *pFontCChar; // [sp+138h] [bp-4h]@1
+  RGBTexture pTexture; // [sp+54h] [bp-E8h]@1
+  RGBTexture pTexture2; // [sp+100h] [bp-3Ch]@1
+  Texture pTexture3; // [sp+Ch] [bp-130h]@5
+  
+  a5 = 0;
+  pFontQuick = LoadFont("quick.fnt", "FONTPAL", 0);
+  pFontCChar = LoadFont("cchar.fnt", "FONTPAL", 0);
+  if ( pMessageQueue_50CBD0->uNumMessages )
+    pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+  ++pIcons_LOD->uTexturePacksCount;
+  if ( !pIcons_LOD->uNumPrevLoadedFiles )
+    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+  dword_A74C88 = 0;
+  pAudioPlayer->PlayMusicTrack(MUSIC_Credits);
+  pTexture.Load("mm6title.pcx", 0);
+  v0 = (char *)pEvents_LOD->LoadRaw("credits.txt", 0);
+  v1 = v0;
+  ptr = v0;
+  pFile = pEvents_LOD->FindContainer("credits.txt", 0);
+  if ( !pFile )
+    Abortf(pGlobalTXT_LocalizationStrings[63]); // "Might and Magic VII is having trouble loading files. 
+                                                // Please re-install to fix this problem. Note: Re-installing will not destroy your save games."
+  fread(&pTexture3, 1, 0x30, pFile);
+  pSize = pTexture3.uDecompressedSize;
+  if ( !pTexture3.uDecompressedSize )
+    pSize = pTexture3.uTextureSize;
+  memset(&pTexture3, 0, 0x48);
+  pFont = pFontCChar;
+  pFont2 = pFontQuick;
+  v1[pSize] = 0;
+  v20 = 250;
+  a4 = 440;
+  pX = 389;
+  pY = 19;
+  pTexture2.uWidth = 250;
+  pHeight = pFont2->GetStringHeight2(pFont, v1, (int)&pX, 0, 1);
+  pTexture2.uHeight = pHeight + 2 * a4;
+  pTexture2.uNumPixels = (signed __int16)pTexture2.uWidth * (signed __int16)pTexture2.uHeight;
+  v7 = pAllocator->AllocNamedChunk(pTexture2.pPixels, 2 * pTexture2.uNumPixels, "scrollermap");
+  pNumPixels = pTexture2.uNumPixels;
+  pTexture2.pPixels = (unsigned __int16 *)v7;
+  teal = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0xFFu);
+  fill_pixels_fast(teal, pTexture2.pPixels, pNumPixels);
+  pTexture2.field_20 = 0;
+  pTexture2.field_22 = 0;
+  pColor1 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0x70u, 0x8Fu, 0xFEu);
+  pColor2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xECu, 0xE6u, 0x9Cu);
+  pString = (char *)operator new(2 * pSize);
+  strncpy(pString, ptr, pSize);
+  pFontQuick->_44D2FD_prolly_draw_credits_entry(pFontCChar, 0, a4, (signed __int16)pTexture2.uWidth, (signed __int16)pTexture2.uHeight, pColor1, 
+	  pColor2, pString, pTexture2.pPixels, (signed __int16)pTexture2.uWidth);
+  free(pString);
+  pWindow_MainMenu = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, (int)ptr);
+  pWindow_MainMenu->CreateButton(0, 0, 0, 0, 1, 0, 0x71u, 0, 0x1Bu, "", 0);
+  pCurrentScreen = 9; // îêíî Credits
+  SetCurrentMenuID(MENU_Credits);
+  do
+  {
+    while ( PeekMessageA(&Msg, 0, 0, 0, 1) )
+    {
+      if ( Msg.message == 18 )
+        Game_DeinitializeAndTerminate(0);
+      TranslateMessage(&Msg);
+      DispatchMessageA(&Msg);
+    }
+    if ( BYTE1(dword_6BE364_game_settings_1) & 1 )
+    {
+      WaitMessage();
+    }
+    else
+    {
+      if (pAsyncMouse)
+        pAsyncMouse->_46B736_consume_click_lists(1);
+      pRenderer->BeginScene();
+      pRenderer->DrawTextureRGB(0, 0, &pTexture);
+      pRenderer->Clip(pX, pY, pX + v20, pY + a4);
+      pRenderer->_4A5D33(pX, pY, 0, a5, &pTexture2);
+      pRenderer->ResetClip();
+      pRenderer->EndScene();
+      ++a5;
+      if ( a5 >= (signed __int16)pTexture2.uHeight )
+        SetCurrentMenuID(MENU_MAIN);
+      pRenderer->Present();
+	  pCurrentScreen = 0;//Ritor1: temporarily, must be corrected GUI_MainMenuMessageProc()
+      GUI_MainMenuMessageProc();
+    }
+  }
+  while ( GetCurrentMenuID() == MENU_Credits );
+  pAudioPlayer->_4AA258(1);
+  pAllocator->FreeChunk(ptr);
+  pAllocator->FreeChunk(pFontQuick);
+  pAllocator->FreeChunk(pFontCChar);
+  pWindow_MainMenu->Release();
+  pIcons_LOD->_4114F2();
+  pTexture.Release();
+  pTexture2.Release();
+  return MENU_MAIN;     // return MENU_Main
+}
+
+//----- (0049B04D) --------------------------------------------------------
+int stru154::_49B04D(ODMFace *a2, BSPVertexBuffer *a3)
+{
+  stru154 *v3; // edi@1
+  signed int v4; // eax@1
+  signed int result; // eax@9
+  signed int v6; // [sp-8h] [bp-18h]@8
+  Vec3_float_ v; // [sp+4h] [bp-Ch]@1
+
+  v.x = 0.0;
+  v3 = this;
+  v.y = 0.0;
+  v.z = 0.0;
+  _49B13D(a2, a3, &v, (float *)&a3);
+  v4 = 2;
+  if ( a2->pFacePlane.vNormal.z )
+  {
+    if ( !a2->pFacePlane.vNormal.x && !a2->pFacePlane.vNormal.y )
+      v4 = 1;
+  }
+  else
+  {
+    v4 = 0;
+  }
+  if ( v4 )
+  {
+    if ( v4 == 1 )
+      v6 = 3;
+    else
+      v6 = 4;
+    result = v6;
+  }
+  else
+  {
+    result = 1;
+  }
+  v3->face_plane.vNormal.x = v.x;
+  v3->face_plane.vNormal.y = v.y;
+  v3->face_plane.vNormal.z = v.z;
+  v3->face_plane.dist = *(float *)&a3;
+  v3->polygonType = (PolygonType)result;
+  return result;
+}
+
+//----- (0049B0C9) --------------------------------------------------------
+int stru154::_49B0C9(Vec3_float_ *pNormal, float dist)
+{
+  signed int v3; // esi@1
+  signed int result; // eax@9
+  double v5; // st7@12
+  double v6; // st6@12
+  double v7; // st5@12
+  signed int v8; // [sp+0h] [bp-4h]@8
+
+  v3 = 2;
+  if ( pNormal->z == 0.0 )
+  {
+    v3 = 0;
+  }
+  else
+  {
+    if ( pNormal->x == 0.0 && pNormal->y == 0.0 )
+      v3 = 1;
+  }
+  if ( v3 )
+  {
+    if ( v3 == 1 )
+      v8 = 3;
+    else
+      v8 = 4;
+    result = v8;
+  }
+  else
+  {
+    result = 1;
+  }
+  v5 = pNormal->z;
+  v6 = pNormal->y;
+  v7 = pNormal->x;
+  this->polygonType = (PolygonType)result;
+  this->face_plane.vNormal.x = v7;
+  this->face_plane.dist = dist;
+  this->face_plane.vNormal.y = v6;
+  this->face_plane.vNormal.z = v5;
+  return result;
+}
+
+//----- (0049B13D) --------------------------------------------------------
+int stru154::_49B13D(ODMFace *pFace, BSPVertexBuffer *pVertices, Vec3_float_ *a3, float *a4)
+{
+  ODMFace *v5; // ebx@1
+  int v6; // eax@1
+  unsigned __int16 *v7; // ebx@2
+  Vec3_int_ *v8; // eax@3
+  Vec3_int_ *v9; // ecx@3
+  double v10; // st7@3
+  int v11; // ecx@3
+  Vec3_int_ *v12; // ecx@3
+  double v13; // st7@3
+  double v14; // st6@3
+  double v15; // st5@3
+  int v16; // ecx@3
+  Vec3_int_ *v17; // eax@3
+  double v18; // st5@3
+  Vec3_float_ *v19; // eax@3
+  int result; // eax@8
+  float v21; // ecx@10
+  double v22; // st7@10
+  double v23; // st6@10
+  Vec3_float_ v2; // [sp+4h] [bp-64h]@3
+  float v25; // [sp+18h] [bp-50h]@3
+  float v26; // [sp+1Ch] [bp-4Ch]@3
+  float v27; // [sp+20h] [bp-48h]@3
+  float v28; // [sp+24h] [bp-44h]@3
+  float v29; // [sp+2Ch] [bp-3Ch]@3
+  float v30; // [sp+30h] [bp-38h]@3
+  float v31; // [sp+34h] [bp-34h]@3
+  float v32; // [sp+38h] [bp-30h]@3
+  float v33; // [sp+3Ch] [bp-2Ch]@3
+  Vec3_float_ v1; // [sp+40h] [bp-28h]@1
+  float v35; // [sp+4Ch] [bp-1Ch]@3
+  float v36; // [sp+50h] [bp-18h]@3
+  float v37; // [sp+54h] [bp-14h]@3
+  Vec3_float_ v38; // [sp+58h] [bp-10h]@3
+  int v39; // [sp+64h] [bp-4h]@1
+
+  v39 = 0;
+  v1.x = 0.0;
+  v5 = pFace;
+  v6 = pFace->uNumVertices;
+  v1.y = 0.0;
+  v1.z = 0.0;
+  if ( v6 - 1 <= 0 )
+  {
+LABEL_8:
+    a3->x = (double)(v5->pFacePlane.vNormal.x & 0xFFFF) * 0.000015259022 + (double)(v5->pFacePlane.vNormal.x >> 16);
+    a3->y = (double)(v5->pFacePlane.vNormal.y & 0xFFFF) * 0.000015259022 + (double)(v5->pFacePlane.vNormal.y >> 16);
+    a3->z = (double)(v5->pFacePlane.vNormal.z & 0xFFFF) * 0.000015259022 + (double)(v5->pFacePlane.vNormal.z >> 16);
+    result = (int)a4;
+    *a4 = (double)(v5->pFacePlane.dist & 0xFFFF) * 0.000015259022 + (double)(v5->pFacePlane.dist >> 16);
+  }
+  else
+  {
+    v7 = &pFace->pVertexIDs[1];
+    while ( 1 )
+    {
+      v8 = pVertices->pVertices;
+      v9 = &v8[*(v7 - 1)];
+      v35 = (double)v9->x;
+      v36 = (double)v9->y;
+      v10 = (double)v9->z;
+      v11 = *v7;
+      v37 = v10;
+      v12 = &v8[v11];
+      v13 = (double)v12->x;
+      v14 = (double)v12->y;
+      v15 = (double)v12->z;
+      v16 = v7[1];
+      v25 = v15;
+      v17 = &v8[v16];
+      v18 = (double)v17->x;
+      v29 = (double)v17->y;
+      v30 = (double)v17->z;
+      v31 = v13 - v35;
+      v32 = v14 - v36;
+      v33 = v25 - v37;
+      v1.x = v31;
+      v26 = v18 - v13;
+      v1.y = v32;
+      v27 = v29 - v14;
+      v1.z = v33;
+      v28 = v30 - v25;
+      v19 = Vec3_float_::Cross(&v1, &v2, v26, v27, v28);
+      v38.x = v19->x;
+      v38.y = v19->y;
+      v38.z = v19->z;
+      if ( v38.x != 0.0 )
+        break;
+      if ( v38.y != 0.0 || v38.z != 0.0 )
+        break;
+      ++v39;
+      ++v7;
+      if ( v39 >= pFace->uNumVertices - 1 )
+      {
+        v5 = pFace;
+        goto LABEL_8;
+      }
+    }
+    v38.Normalize();
+    v21 = v38.y;
+    a3->x = v38.x;
+    v22 = v37 * v38.z;
+    v23 = v36 * v38.y;
+    a3->y = v21;
+    a3->z = v38.z;
+    result = (int)a4;
+    *a4 = -(v22 + v23 + v35 * v38.x);
+  }
+  return result;
+}
+
+
+
+
+
+//----- (0049D700) --------------------------------------------------------
+unsigned int __fastcall GetMaxMipLevels(unsigned int uDim)
+{
+  unsigned int v1; // eax@1
+  int v2; // ecx@1
+  unsigned int v3; // eax@1
+
+  v1 = uDim;
+  v2 = 0;
+  v3 = v1 - 1;
+  while ( v3 & 1 )
+  {
+    v3 >>= 1;
+    ++v2;
+  }
+  return v3 == 0 ? v2 : 0;
+}
+
+
+
+
+
+
+
+
+
+
+//----- (004A19D8) --------------------------------------------------------
+int __fastcall sub_4A19D8(unsigned int a1, unsigned int a2)
+{
+  signed __int64 v2; // ST10_8@1
+  double v3; // st7@1
+  float v4; // ST24_4@1
+  double v5; // ST10_8@1
+  int v6; // ST1C_4@1
+  float v7; // ST24_4@1
+  double v8; // ST10_8@1
+  unsigned __int8 v9; // ST20_1@1
+  float v10; // ST24_4@1
+  double v11; // ST10_8@1
+  float v12; // ST24_4@1
+  double v13; // ST08_8@1
+
+  v2 = a1 >> 24;
+  v3 = (double)v2 * 0.0039215689;
+  LODWORD(v2) = a2 >> 24;
+  v4 = v3 * (double)v2 * 0.0039215689 * 255.0;
+  v5 = v4 + 6.7553994e15;
+  v6 = LODWORD(v5);
+  v7 = (double)((a1 >> 16) & 0xFFi64) * 0.0039215689 * (double)((a2 >> 16) & 0xFF) * 0.0039215689 * 255.0;
+  v8 = v7 + 6.7553994e15;
+  v9 = LOBYTE(v8);
+  v10 = (double)((unsigned __int16)a1 >> 8) * 0.0039215689 * (double)((unsigned __int16)a2 >> 8) * 0.0039215689 * 255.0;
+  v11 = v10 + 6.7553994e15;
+  v12 = (double)(a1 & 0xFFi64) * 0.0039215689 * (double)(unsigned __int8)a2 * 0.0039215689 * 255.0;
+  v13 = v12 + 6.7553994e15;
+  return LOBYTE(v13) | ((LOBYTE(v11) | (((v6 << 8) | v9) << 8)) << 8);
+}
+
+
+
+//----- (004A46E6) --------------------------------------------------------
+int __fastcall sr_4A46E6_draw_particle_segment(unsigned int x, signed int y, signed int _z, int a4, unsigned int lightColor)
+{
+  int v5; // eax@1
+  int z; // eax@1
+  unsigned int v7; // eax@9
+  unsigned int v8; // ecx@9
+  int v9; // eax@9
+  unsigned int v10; // eax@10
+  int *v11; // esi@10
+  int *v12; // edi@10
+  int v13; // ecx@10
+  int v14; // edx@10
+  unsigned int v15; // eax@22
+  int *v16; // esi@22
+  int *v17; // edi@22
+  int v18; // ecx@22
+  int v19; // edx@22
+  unsigned __int16 *pTarget; // [sp+Ch] [bp-8h]@9
+  int *pTargetZ; // [sp+10h] [bp-4h]@9
+  unsigned int v22; // [sp+1Ch] [bp+8h]@9
+  signed int v23; // [sp+20h] [bp+Ch]@1
+
+  v5 = a4;
+  v23 = _z >> 16;
+  z = x + v5;
+  if ( z >= (signed int)pViewport->uViewportX
+    && (signed int)x <= (signed int)pViewport->uViewportZ
+    && y >= (signed int)pViewport->uViewportY
+    && y <= (signed int)pViewport->uViewportW )
+  {
+    if ( (signed int)x < (signed int)pViewport->uViewportX )
+      x = pViewport->uViewportX;
+    if ( z > (signed int)pViewport->uViewportZ )
+      z = pViewport->uViewportZ;
+    pTarget = &pRenderer->pTargetSurface[x + y * pRenderer->uTargetSurfacePitch];
+    v22 = z - x;
+    pTargetZ = &pRenderer->pActiveZBuffer[x + 640 * y];
+    v7 = lightColor >> 3;
+    v8 = lightColor & 0xF0;
+    v9 = v7 & 0x1E0000;
+    if ( pRenderer->uTargetGBits == 5 )
+    {
+      v10 = (v8 | (((unsigned __int16)(lightColor & 0xF000) | (unsigned int)v9) >> 3)) >> 4;
+      v11 = (int *)pTarget;
+      v12 = pTargetZ;
+      v13 = v22;
+      v14 = (v10 << 16) | v10;
+      z = (unsigned __int8)pTarget & 2;
+      if ( (unsigned __int8)pTarget & 2 )
+      {
+        z = (unsigned int)*pTargetZ >> 16;
+        if ( z > v23 )
+        {
+          z = v14 + ((*pTarget & 0x7BDEu) >> 1);
+          *pTarget = z;
+        }
+        v13 = v22 - 1;
+        v11 = (int *)(pTarget + 1);
+        v12 = pTargetZ + 1;
+      }
+      while ( v13 != 1 )
+      {
+        if ( v13 < 1 )
+          return z;
+        z = (unsigned int)*v12 >> 16;
+        if ( z <= v23 )
+        {
+          v13 -= 2;
+          ++v11;
+          v12 += 2;
+        }
+        else
+        {
+          v12 += 2;
+          z = v14 + ((*v11 & 0x7BDE7BDEu) >> 1);
+          v13 -= 2;
+          *v11 = z;
+          ++v11;
+        }
+      }
+      z = (unsigned int)*v12 >> 16;
+      if ( z > v23 )
+      {
+        z = v14 + ((*(short *)v11 & 0x7BDEu) >> 1);
+        *(short *)v11 = z;
+      }
+    }
+    else
+    {
+      v15 = (v8 | (((unsigned __int16)(lightColor & 0xF800) | (unsigned int)v9) >> 2)) >> 4;
+      v16 = (int *)pTarget;
+      v17 = pTargetZ;
+      v18 = v22;
+      v19 = (v15 << 16) | v15;
+      z = (unsigned __int8)pTarget & 2;
+      if ( (unsigned __int8)pTarget & 2 )
+      {
+        z = (unsigned int)*pTargetZ >> 16;
+        if ( z > v23 )
+        {
+          z = v19 + ((*pTarget & 0xF7DEu) >> 1);
+          *pTarget = z;
+        }
+        v18 = v22 - 1;
+        v16 = (int *)(pTarget + 1);
+        v17 = pTargetZ + 1;
+      }
+      while ( v18 != 1 )
+      {
+        if ( v18 < 1 )
+          return z;
+        z = (unsigned int)*v17 >> 16;
+        if ( z <= v23 )
+        {
+          v18 -= 2;
+          ++v16;
+          v17 += 2;
+        }
+        else
+        {
+          v17 += 2;
+          z = v19 + ((*v16 & 0xF7DEF7DEu) >> 1);
+          v18 -= 2;
+          *v16 = z;
+          ++v16;
+        }
+      }
+      z = (unsigned int)*v17 >> 16;
+      if ( z > v23 )
+      {
+        z = v19 + ((*(short *)v16 & 0xF7DEu) >> 1);
+        *(short *)v16 = z;
+      }
+    }
+  }
+  return z;
+}
+
+
+//----- (004A57E9) --------------------------------------------------------
+void __cdecl Present_ColorKey()
+{
+  HRESULT v0; // eax@3
+  HRESULT v1; // eax@3
+  HRESULT v2; // eax@3
+  HRESULT v3; // eax@3
+  HRESULT v4; // eax@3
+  RECT a2; // [sp+4h] [bp-14h]@3
+  //CheckHRESULT_stru0 this; // [sp+14h] [bp-4h]@3
+
+  if ( !pRenderer->uNumSceneBegins )
+  {
+    if ( pRenderer->field_40110 )
+    {
+      a2.bottom = pViewport->uViewportY;
+      a2.left = 0;
+      a2.top = 0;
+      a2.right = 640;
+      ErrD3D(pRenderer->pBackBuffer4->BltFast(0, 0, pRenderer->pColorKeySurface4, &a2, 16u));
+      a2.right = 640;
+      a2.left = 0;
+      a2.top = pViewport->uViewportW + 1;
+      a2.bottom = 480;
+      ErrD3D(pRenderer->pBackBuffer4->BltFast(
+             0,
+             pViewport->uViewportW + 1,
+             pRenderer->pColorKeySurface4,
+             &a2,
+             16u));
+      a2.right = pViewport->uViewportX;
+      a2.bottom = pViewport->uViewportW + 1;
+      a2.left = 0;
+      a2.top = pViewport->uViewportY;
+      ErrD3D(pRenderer->pBackBuffer4->BltFast(
+             0,
+             pViewport->uViewportY,
+             pRenderer->pColorKeySurface4,
+             &a2,
+             16u));
+      a2.left = pViewport->uViewportZ;
+      a2.top = pViewport->uViewportY;
+      a2.right = 640;
+      a2.bottom = pViewport->uViewportW + 1;
+      ErrD3D(pRenderer->pBackBuffer4->BltFast(
+             pViewport->uViewportZ,
+             pViewport->uViewportY,
+             pRenderer->pColorKeySurface4,
+             &a2,
+             16u));
+      a2.right = pViewport->uViewportZ;
+      a2.bottom = pViewport->uViewportW + 1;
+      a2.left = pViewport->uViewportX;
+      a2.top = pViewport->uViewportY;
+      ErrD3D(pRenderer->pBackBuffer4->BltFast(
+             pViewport->uViewportX,
+             pViewport->uViewportY,
+             pRenderer->pColorKeySurface4,
+             &a2,
+             17u));
+    }
+  }
+}
+
+//----- (004A597D) --------------------------------------------------------
+void Present_NoColorKey()
+{
+  //unsigned __int16 *v0; // eax@4
+  unsigned __int16 *v1; // esi@4
+  void *v2; // edi@4
+  //signed int v4; // ebx@4
+  //signed int v5; // ebx@6
+  //void *v6; // edi@7
+  //const void *v7; // esi@7
+  signed int v8; // ebx@8
+  int v9; // eax@10
+  unsigned int v10; // esi@10
+  unsigned __int32 v11; // edi@10
+  //int v12; // ecx@10
+  unsigned int v13; // ebx@10
+  int v14; // eax@11
+  int v15; // eax@13
+  int v16; // eax@14
+  int v17; // eax@16
+  HRESULT v18; // eax@22
+  DDSURFACEDESC2 Dst; // [sp+Ch] [bp-98h]@3
+  int v20; // [sp+88h] [bp-1Ch]@10
+  int v21; // [sp+8Ch] [bp-18h]@10
+  __int32 v22; // [sp+90h] [bp-14h]@10
+  //unsigned __int32 v23; // [sp+94h] [bp-10h]@10
+  unsigned int v24; // [sp+98h] [bp-Ch]@4
+  //unsigned int _this; // [sp+9Ch] [bp-8h]@10
+  //LPVOID v26; // [sp+A0h] [bp-4h]@4
+
+  if ( !pRenderer->uNumSceneBegins )
+  {
+    if ( pRenderer->field_40110 )
+    {
+      memset(&Dst, 0, 0x7Cu);
+      Dst.dwSize = 124;
+      if ( pRenderer->LockSurface_DDraw4(pRenderer->pBackBuffer4, &Dst, 1u) )
+      {
+        //v26 = Dst.lpSurface;
+        pRenderer->pCurrentlyLockedSurfaceDataPtr = (unsigned __int16 *)Dst.lpSurface;
+        v24 = pRenderer->uTargetGMask | pRenderer->uTargetBMask |
+              ((pRenderer->uTargetGMask | pRenderer->uTargetBMask) << 16);
+        pRenderer->pCurrentlyLockedSoftSurface = pRenderer->pTargetSurface;
+        pRenderer->uCurrentlyLockedSurfacePitch = Dst.lPitch;
+        v1 = pRenderer->pTargetSurface;
+        v2 = Dst.lpSurface;
+
+
+        /*for (uint y = 0; y < 480; ++y)
+        {
+          auto pDst = (unsigned short *)((char *)Dst.lpSurface + y * Dst.lPitch);
+          for (uint x = 0; x < 640; ++x)
+            pDst[x] = pRenderer->uTargetRMask | pRenderer->uTargetBMask;
+        }*/
+        
+        auto pSrc = pRenderer->pTargetSurface;
+        auto pDst = (__int16 *)Dst.lpSurface;
+
+        for (uint y = 0; y < 8; ++y)
+          memcpy(pDst + y * Dst.lPitch / 2,
+
+		  pSrc + y * 640, 640 * sizeof(__int16));
+
+        for (uint y = 8; y < 352; ++y)
+        {
+          memcpy(pDst + y * Dst.lPitch / 2,
+                 pSrc + y * 640, 8 * sizeof(__int16));
+          memcpy(pDst + 8 + 460/*462*/ + y * Dst.lPitch / 2,
+                 pSrc + 8 + 460/*462*/ + y * 640, 174/*172*/ * sizeof(__int16));
+        }
+
+        for (uint y = 351/*352*/; y < 480; ++y)
+          memcpy(pDst + y * Dst.lPitch / 2,
+                 pSrc + y * 640, 640 * sizeof(__int16));
+
+
+        auto pSrc_x1y1 = pSrc + 640 * pViewport->uViewportY + pViewport->uViewportX;
+        //_this = (unsigned int)&pSrc[2 * (((signed int)pViewport->uViewportX >> 1) + 320 * pViewport->uViewportY)];
+        auto pDst_x1y1 = pDst + Dst.lPitch * pViewport->uViewportY + pViewport->uViewportX;
+        //v23 = (unsigned __int32)((char *)v26 + 4 * (((signed int)pViewport->uViewportX >> 1) + (Dst.lPitch >> 2) * pViewport->uViewportY));
+        v9 = ((signed int)pViewport->uViewportX >> 1) - ((signed int)pViewport->uViewportZ >> 1);
+        //v20 = ((signed int)pViewport->uViewportZ >> 1) - ((signed int)pViewport->uViewportX >> 1);
+        v22 = 4 * ((Dst.lPitch / 4) + v9);
+        v21 = 4 * v9 + 1280;
+
+        auto uNumLines = pViewport->uViewportW - pViewport->uViewportY + 1;
+        //v26 = (LPVOID)(pViewport->uViewportW - pViewport->uViewportY + 1);
+        v10 = (int)pSrc_x1y1;
+        v11 = (int)pDst_x1y1;
+        auto uHalfWidth = v20 = (pViewport->uViewportZ - pViewport->uViewportX) / 2;
+        v13 = v24;
+
+        for (uint y = pViewport->uViewportY; y < pViewport->uViewportW + 1; ++y)
+        {
+          //memcpy(pDst + pViewport->uViewportX + y * Dst.lPitch / 2,
+          //       pSrc + pViewport->uViewportX + y * 640, (pViewport->uViewportZ - pViewport->uViewportX) * sizeof(__int16));
+          for (uint x = pViewport->uViewportX; x < pViewport->uViewportZ; ++x)
+          {
+            if (pSrc[y * 640 + x] != (pRenderer->uTargetGMask | pRenderer->uTargetBMask))
+              pDst[y * Dst.lPitch / 2 + x] = pSrc[y * 640 + x];
+          }
+        }
+
+              ErrD3D(pRenderer->pBackBuffer4->Unlock(0));
+
+       /* while ( 1 )
+        {
+          while ( 1 )
+          {
+            v14 = *(int *)v10;
+            v10 += 4;
+            if ( v14 == v13 )
+              break;
+            if ( (short)v14 == (short)v13 )
+            {
+              *(int *)v11 = *(int *)v11 & 0xFFFF | v14 & 0xFFFF0000;
+              v11 += 4;
+              --uHalfWidth;
+              if ( !uHalfWidth )
+                goto LABEL_21;
+            }
+            else
+            {
+              v15 = __ROL__(v14, 16);
+              if ( (short)v15 == (short)v13 )
+              {
+                v17 = __ROR__(v15, 16);
+                *(int *)v11 = *(int *)v11 & 0xFFFF0000 | (unsigned __int16)v17;
+                v11 += 4;
+                --uHalfWidth;
+                if ( !uHalfWidth )
+                  goto LABEL_21;
+              }
+              else
+              {
+                v16 = __ROR__(v15, 16);
+                *(int *)v11 = v16;
+                v11 += 4;
+                --uHalfWidth;
+                if ( !uHalfWidth )
+                  goto LABEL_21;
+              }
+            }
+          }
+          v11 += 4;
+          --uHalfWidth;
+          if ( !uHalfWidth )
+          {
+LABEL_21:
+            v10 += v21;
+            v11 += v22;
+            uHalfWidth = v20;
+            if ( !--uNumLines )
+            {
+              ErrD3D(pRenderer->pBackBuffer4->Unlock(0));
+              return;
+            }
+          }
+        }*/
+      }
+    }
+  }
+}
+
+
+
+//----- (004A7063) --------------------------------------------------------
+int __thiscall sub_4A7063(unsigned int uDiffuse, float a2)
+{
+  float v2; // ST1C_4@1
+  double v3; // ST14_8@1
+  signed int v4; // ebx@1
+  float v5; // ST1C_4@1
+  double v6; // ST14_8@1
+  signed int v7; // edi@1
+  double v8; // ST0C_8@1
+  signed int v9; // esi@1
+  signed int v10; // ecx@1
+  double v12; // [sp+8h] [bp-18h]@1
+  unsigned __int64 v13; // [sp+18h] [bp-8h]@1
+
+  v2 = (double)(uDiffuse >> 24) * a2;
+  v3 = v2 + 6.7553994e15;
+  v4 = LODWORD(v3);
+  v5 = (double)((uDiffuse >> 16) & 0xFF) * a2;
+  v6 = v5 + 6.7553994e15;
+  v7 = LODWORD(v6);
+  *((float *)&v6 + 1) = (double)((unsigned __int16)uDiffuse >> 8) * a2;
+  v8 = *((float *)&v6 + 1) + 6.7553994e15;
+  v13 = __PAIR__(LODWORD(v6), LODWORD(v8));
+  v9 = LODWORD(v8);
+  *((float *)&v6 + 1) = (double)(unsigned __int8)uDiffuse * a2;
+  v12 = *((float *)&v6 + 1) + 6.7553994e15;
+  v10 = LODWORD(v12);
+  if ( v4 > 255 )
+    v4 = 255;
+  if ( v4 < 0 )
+    v4 = 0;
+  if ( SHIDWORD(v13) > 255 )
+    v7 = 255;
+  if ( v7 < 0 )
+    v7 = 0;
+  if ( (signed int)v13 > 255 )
+    v9 = 255;
+  if ( v9 < 0 )
+    v9 = 0;
+  if ( SLODWORD(v12) > 255 )
+    v10 = 255;
+  if ( v10 < 0 )
+    v10 = 0;
+  return v10 | ((v9 | ((v7 | (v4 << 8)) << 8)) << 8);
+}
+
+
+
+
+
+//----- (004AC1C9) --------------------------------------------------------
+int __thiscall sub_4AC1C9(unsigned int _this, Vec4_int_ *a2)
+{
+  unsigned int v2; // esi@1
+  __int16 v3; // di@1
+  signed int v4; // ebx@1
+  int v5; // ecx@3
+  Vec4_int_ *v6; // eax@10
+  Vec4_int_ *v7; // esi@14
+  int result; // eax@16
+  char *v9; // esi@16
+  Vec4_int_ a1; // [sp+Ch] [bp-34h]@10
+  Vec4_int_ v11; // [sp+1Ch] [bp-24h]@14
+  Vec4_int_ Dst; // [sp+2Ch] [bp-14h]@1
+  int v13; // [sp+3Ch] [bp-4h]@1
+
+  v2 = _this;
+  v3 = sub_4382BC(_this);
+  v13 = sub_4383ED();
+  v4 = 0;
+  memset(&Dst, 0, 0x10u);
+  if ( v3 < 0 )
+    goto LABEL_19;
+  if ( (signed int)v2 > 0 )
+  {
+    if ( (signed int)v2 > 150 )
+    {
+      v5 = (int)a2;
+    }
+    else
+    {
+      v5 = 4000 * v2;
+      v4 = 1;
+    }
+  }
+  else
+  {
+    v5 = 4000 * dword_4F031C[(unsigned __int16)v3];
+  }
+  if ( v13 & 0x10 && !v4 )
+  {
+    if ( v2 )
+      v6 = sub_4AC4FD_get_cpu_clocks_rdtsc(v5, &a1);
+    else
+      v6 = sub_4AC33A_get_cpu_clocks_QPC(v5, &a1);
+    goto LABEL_14;
+  }
+  if ( (unsigned __int16)v3 < 3u )
+  {
+LABEL_19:
+    v7 = &Dst;
+    goto LABEL_16;
+  }
+  v6 = sub_4AC277(v5, &a1);
+LABEL_14:
+  v11.x = v6->x;
+  v11.y = v6->y;
+  v11.z = v6->z;
+  v11.w = v6->w;
+  v7 = &v11;
+LABEL_16:
+  result = (int)a2;
+  a2->x = v7->x;
+  v9 = (char *)&v7->y;
+  a2->y = *(int *)v9;
+  v9 += 4;
+  a2->z = *(int *)v9;
+  a2->w = *((int *)v9 + 1);
+  return result;
+}
+// 4F031C: using guessed type int dword_4F031C[];
+
+//----- (004AC277) --------------------------------------------------------
+Vec4_int_ *__thiscall sub_4AC277(unsigned int _this, Vec4_int_ *a2)
+{
+  __debugbreak();
+  return 0;
+  /*signed int v2; // esi@1
+  signed __int16 v4; // bx@3
+  int v10; // esi@8
+  int v11; // eax@10
+  Vec4_int_ *result; // eax@13
+  Vec4_int_ Dst; // [sp+8h] [bp-30h]@1
+  LARGE_INTEGER Frequency; // [sp+18h] [bp-20h]@1
+  LARGE_INTEGER PerformanceCount; // [sp+20h] [bp-18h]@3
+  LARGE_INTEGER v16; // [sp+28h] [bp-10h]@5
+  int v17; // [sp+30h] [bp-8h]@1
+  int v18; // [sp+34h] [bp-4h]@2
+
+  v17 = _this;
+  v2 = -1;
+  memset(&Dst, 0, 0x10u);
+  if ( QueryPerformanceFrequency(&Frequency) )
+  {
+    v18 = 10;
+    do
+    {
+      QueryPerformanceCounter(&PerformanceCount);
+      _EAX = -2147483648;
+      v4 = 4000;
+      do
+      {
+        __asm { bsf     ecx, eax }
+        --v4;
+      }
+      while ( v4 );
+      QueryPerformanceCounter(&v16);
+      if ( (signed int)v16.s.LowPart - (signed int)PerformanceCount.s.LowPart < (unsigned int)v2 )
+        v2 = v16.s.LowPart - PerformanceCount.s.LowPart;
+      --v18;
+    }
+    while ( v18 );
+    v10 = 100000 * v2 / (Frequency.s.LowPart / 0xA);
+    if ( v10 % Frequency.s.LowPart > Frequency.s.LowPart >> 1 )
+      ++v10;
+    v11 = v17 / (unsigned int)v10;
+    Dst.z = v17 / (unsigned int)v10;
+    if ( v17 % (unsigned int)v10 > (unsigned int)v10 >> 1 )
+      ++v11;
+    Dst.x = v17;
+    Dst.y = v10;
+    Dst.w = v11;
+  }
+  result = a2;
+  a2->x = Dst.x;
+  a2->y = Dst.y;
+  a2->z = Dst.z;
+  a2->w = Dst.w;
+  return result;*/
+}
+
+//----- (004AC33A) --------------------------------------------------------
+Vec4_int_ *__thiscall sub_4AC33A_get_cpu_clocks_QPC(int _this, Vec4_int_ *a1)
+{
+  __debugbreak();
+  return 0;
+  /*int v2; // esi@1
+  int v3; // ebx@1
+  unsigned __int64 v4; // qax@4
+  unsigned __int64 v5; // qax@7
+  DWORD v6; // edi@7
+  DWORD v7; // eax@7
+  unsigned int v8; // ecx@10
+  unsigned __int64 v9; // qax@10
+  unsigned int v10; // edi@10
+  int v11; // eax@14
+  unsigned int v12; // ecx@19
+  Vec4_int_ *result; // eax@24
+  int Dst; // [sp+Ch] [bp-4Ch]@1
+  int v15; // [sp+10h] [bp-48h]@23
+  int v16; // [sp+14h] [bp-44h]@21
+  int v17; // [sp+18h] [bp-40h]@21
+  LARGE_INTEGER Frequency; // [sp+1Ch] [bp-3Ch]@1
+  LARGE_INTEGER PerformanceCount; // [sp+24h] [bp-34h]@2
+  LARGE_INTEGER v20; // [sp+2Ch] [bp-2Ch]@2
+  int v21; // [sp+34h] [bp-24h]@2
+  int v22; // [sp+38h] [bp-20h]@2
+  int v23; // [sp+3Ch] [bp-1Ch]@4
+  int v24; // [sp+40h] [bp-18h]@7
+  int nPriority; // [sp+44h] [bp-14h]@2
+  unsigned int v26; // [sp+48h] [bp-10h]@1
+  unsigned int v27; // [sp+4Ch] [bp-Ch]@1
+  HANDLE hThread; // [sp+50h] [bp-8h]@1
+  int v29; // [sp+54h] [bp-4h]@1
+
+  v2 = 0;
+  v3 = 0;
+  v29 = 0;
+  v27 = 0;
+  v26 = 0;
+  hThread = GetCurrentThread();
+  memset(&Dst, 0, 0x10u);
+  if ( QueryPerformanceFrequency(&Frequency) )
+  {
+    do
+    {
+      ++v29;
+      v22 = v2;
+      v21 = v3;
+      QueryPerformanceCounter(&PerformanceCount);
+      v20 = PerformanceCount;
+      nPriority = GetThreadPriority(hThread);
+      if ( nPriority != 2147483647 )
+        SetThreadPriority(hThread, 15);
+      while ( v20.s.LowPart - PerformanceCount.s.LowPart < 0x32 )
+      {
+        QueryPerformanceCounter(&v20);
+        v4 = __rdtsc();
+        v23 = v4;
+      }
+      PerformanceCount = v20;
+      do
+      {
+        QueryPerformanceCounter(&v20);
+        v5 = __rdtsc();
+        v24 = v5;
+        v6 = v20.s.LowPart;
+        v7 = PerformanceCount.s.LowPart;
+      }
+      while ( v20.s.LowPart - PerformanceCount.s.LowPart < 0x3E8 );
+      if ( nPriority != 2147483647 )
+      {
+        SetThreadPriority(hThread, nPriority);
+        v7 = PerformanceCount.s.LowPart;
+        v6 = v20.s.LowPart;
+      }
+      v8 = v24 - v23;
+      v27 += v24 - v23;
+      v9 = (100000 * v6 - 100000 * v7) / (Frequency.s.LowPart / 0xA);
+      v10 = v9;
+      v26 += v9;
+      if ( v9 % Frequency.s.LowPart > Frequency.s.LowPart >> 1 )
+        v10 = v9 + 1;
+      v3 = v8 / v10;
+      if ( v8 % v10 > v10 >> 1 )
+        v3 = v8 / v10 + 1;
+      v2 = v21;
+      v11 = v3 + v22 + v21;
+    }
+    while ( v29 < 3
+         || v29 < 20
+         && ((unsigned int)(3 * v3 - v11) > 3 || (unsigned int)(3 * v21 - v11) > 3 || (unsigned int)(3 * v22 - v11) > 3) );
+    v12 = 10 * v27 / v26;
+    if ( 100 * v27 / v26 - 10 * v12 >= 6 )
+      ++v12;
+    v16 = v27 / v26;
+    v17 = v27 / v26;
+    if ( v12 - 10 * v27 / v26 >= 6 )
+      v17 = v27 / v26 + 1;
+    v15 = v26;
+    Dst = v27;
+  }
+  result = a1;
+  a1->x = Dst;
+  a1->y = v15;
+  a1->z = v16;
+  a1->w = v17;
+  return result;*/
+}
+
+//----- (004AC4FD) --------------------------------------------------------
+Vec4_int_ *__thiscall sub_4AC4FD_get_cpu_clocks_rdtsc(int _this, Vec4_int_ *a1)
+{
+  __debugbreak();
+  return 0;
+  /*int v2; // eax@1
+  int v3; // eax@4
+  bool v4; // eax@5
+  unsigned __int64 v5; // kr00_8@8
+  int v6; // edi@9
+  int v7; // eax@9
+  bool v8; // eax@10
+  unsigned __int64 v9; // kr08_8@13
+  unsigned int v10; // eax@15
+  Vec4_int_ *result; // eax@17
+  int Dst; // [sp+Ch] [bp-2Ch]@1
+  int v13; // [sp+10h] [bp-28h]@17
+  int v14; // [sp+14h] [bp-24h]@15
+  int v15; // [sp+18h] [bp-20h]@17
+  unsigned int v16; // [sp+1Ch] [bp-1Ch]@8
+  unsigned int v17; // [sp+20h] [bp-18h]@8
+  unsigned int v18; // [sp+24h] [bp-14h]@13
+  int nPriority; // [sp+28h] [bp-10h]@1
+  __int64 v20; // [sp+2Ch] [bp-Ch]@1
+  int v21; // [sp+34h] [bp-4h]@3
+
+  HIDWORD(v20) = GetCurrentThread();
+  memset(&Dst, 0, 0x10u);
+  v2 = GetThreadPriority(HIDWORD(v20));
+  nPriority = v2;
+  if ( v2 != 0x7FFFFFFF )
+    SetThreadPriority(HIDWORD(v20), v2 + 1);
+  __outbyte(0x70u, 0);
+  v21 = __inbyte(0x71u);
+  do
+  {
+    __outbyte(0x70u, 0);
+    LODWORD(v20) = __inbyte(0x71u);
+    v3 = v20 - v21;
+    if ( (signed int)v20 >= v21 )
+      v4 = v3 > 0;
+    else
+      v4 = v3 + 10;
+  }
+  while ( !v4 );
+  v5 = __rdtsc();
+  v16 = HIDWORD(v5);
+  v17 = v5;
+  do
+  {
+    __outbyte(0x70u, 0);
+    v21 = __inbyte(0x71u);
+    v6 = v21;
+    v7 = v21 - v20;
+    if ( v21 >= (signed int)v20 )
+      v8 = v7 > 0;
+    else
+      v8 = v7 + 10;
+  }
+  while ( !v8 );
+  v9 = __rdtsc();
+  v18 = HIDWORD(v9);
+  v21 = v9;
+  if ( nPriority != 0x7FFFFFFF )
+    SetThreadPriority(HIDWORD(v20), nPriority);
+  nPriority = v21;
+  *(__int64 *)((char *)&v20 + 4) = __PAIR__(v18, v21) - __PAIR__(v16, v17);
+  Dst = HIDWORD(v20);
+  v10 = HIDWORD(v20) / 0xF4240;
+  v14 = HIDWORD(v20) / 0xF4240;
+  if ( HIDWORD(v20) / 0x186A0 - 10 * HIDWORD(v20) / 0xF4240 >= 6 )
+    ++v10;
+  v15 = v10;
+  result = a1;
+  v13 = 1000000 * v6 - 1000000 * v20;
+  a1->x = Dst;
+  a1->y = v13;
+  a1->z = v14;
+  a1->w = v15;
+  return result;*/
+}
+
+
+
+//----- (004AD504) --------------------------------------------------------
+int __fastcall sub_4AD504(unsigned int uFaceID)
+{
+  int result; // eax@1
+  unsigned int v2; // ebx@1
+  BLVFace *v3; // esi@3
+  Texture *v4; // edi@6
+  int v5; // eax@7
+  int v6; // edx@7
+  int v7; // ecx@7
+  int v8; // ebx@8
+  int v9; // eax@8
+  int v10; // ebx@8
+  unsigned int v11; // ebx@9
+  int v12; // esi@10
+  int v13; // eax@13
+  unsigned __int16 *v14; // eax@13
+  unsigned int v15; // eax@14
+  unsigned __int16 *v16; // ebx@14
+  int v17; // eax@15
+  int v18; // ebx@15
+  int v19; // esi@15
+  int v20; // ecx@15
+  int v21; // eax@15
+  stru193_math *v22; // ebx@15
+  int v23; // eax@15
+  char *v24; // esi@16
+  int v25; // eax@18
+  int v26; // eax@18
+  int v27; // eax@20
+  signed int v28; // esi@20
+  signed int v29; // edx@20
+  signed int v30; // esi@20
+  signed int v31; // edi@20
+  int v32; // esi@20
+  int v33; // eax@26
+  int *v34; // esi@27
+  unsigned __int16 *v35; // edi@27
+  unsigned int v36; // edx@27
+  int v37; // ebx@27
+  char v38; // cl@27
+  char v39; // ch@27
+  int v40; // ebx@29
+  int v41; // edx@29
+  unsigned int v42; // ebx@30
+  int v43; // edx@30
+  int v44; // eax@33
+  int *v45; // esi@34
+  unsigned __int16 *v46; // edi@34
+  unsigned int v47; // edx@34
+  int v48; // ebx@34
+  char v49; // cl@34
+  char v50; // ch@34
+  int v51; // ebx@36
+  int v52; // edx@36
+  unsigned __int16 v53; // bx@37
+  int v54; // edx@37
+  int v55; // eax@40
+  int v56; // eax@41
+  int *v57; // esi@42
+  unsigned __int16 *v58; // edi@42
+  unsigned int v59; // edx@42
+  int v60; // ebx@42
+  char v61; // cl@42
+  char v62; // ch@42
+  unsigned int v63; // ebx@44
+  int v64; // edx@44
+  unsigned int v65; // ebx@44
+  int v66; // edx@44
+  unsigned int v67; // ebx@45
+  int v68; // edx@45
+  int v69; // ebx@45
+  int v70; // edx@45
+  int v71; // eax@48
+  int *v72; // esi@49
+  unsigned __int16 *v73; // edi@49
+  unsigned int v74; // edx@49
+  int v75; // ebx@49
+  char v76; // cl@49
+  char v77; // ch@49
+  unsigned int v78; // ebx@51
+  int v79; // edx@51
+  unsigned int v80; // ebx@51
+  int v81; // edx@51
+  unsigned int v82; // ebx@52
+  int v83; // edx@52
+  int v84; // ebx@52
+  int v85; // edx@52
+  unsigned __int8 *v86; // [sp+Ch] [bp-98h]@9
+  unsigned __int8 *v87; // [sp+10h] [bp-94h]@9
+  unsigned __int8 *v88; // [sp+14h] [bp-90h]@9
+  unsigned __int8 *v89; // [sp+18h] [bp-8Ch]@9
+  int v90; // [sp+1Ch] [bp-88h]@20
+  BLVFace *v91; // [sp+20h] [bp-84h]@3
+  int v92; // [sp+24h] [bp-80h]@7
+  int i; // [sp+28h] [bp-7Ch]@7
+  unsigned __int16 *v94; // [sp+2Ch] [bp-78h]@9
+  unsigned int v95; // [sp+30h] [bp-74h]@1
+  Texture *v96; // [sp+34h] [bp-70h]@6
+  int v97; // [sp+38h] [bp-6Ch]@15
+  unsigned int v98; // [sp+3Ch] [bp-68h]@9
+  int v99; // [sp+40h] [bp-64h]@9
+  int v100; // [sp+44h] [bp-60h]@24
+  int v101; // [sp+48h] [bp-5Ch]@10
+  int v102; // [sp+4Ch] [bp-58h]@20
+  int v103; // [sp+50h] [bp-54h]@20
+  int v104; // [sp+54h] [bp-50h]@9
+  unsigned __int8 *v105; // [sp+58h] [bp-4Ch]@20
+  int v106; // [sp+5Ch] [bp-48h]@24
+  int v107; // [sp+60h] [bp-44h]@20
+  int v108; // [sp+64h] [bp-40h]@20
+  int v109; // [sp+68h] [bp-3Ch]@20
+  int v110; // [sp+6Ch] [bp-38h]@15
+  int v111; // [sp+70h] [bp-34h]@20
+  int a1; // [sp+74h] [bp-30h]@12
+  int a2; // [sp+78h] [bp-2Ch]@9
+  int *v114; // [sp+7Ch] [bp-28h]@16
+  int v115; // [sp+80h] [bp-24h]@18
+  int v116; // [sp+84h] [bp-20h]@7
+  unsigned int v117; // [sp+88h] [bp-1Ch]@15
+  unsigned int v118; // [sp+8Ch] [bp-18h]@24
+  int *v119; // [sp+90h] [bp-14h]@13
+  int v120; // [sp+94h] [bp-10h]@15
+  unsigned int v121; // [sp+98h] [bp-Ch]@15
+  unsigned __int16 *v122; // [sp+9Ch] [bp-8h]@15
+  unsigned int v123; // [sp+A0h] [bp-4h]@13
+
+  result = pRenderer->uTargetSurfacePitch;
+  v2 = uFaceID;
+  v95 = pRenderer->uTargetSurfacePitch;
+  if ( (uFaceID & 0x80000000u) == 0 )
+  {
+    if ( (signed int)uFaceID < (signed int)pIndoor->uNumFaces )
+    {
+      v3 = &pIndoor->pFaces[uFaceID];
+      v91 = &pIndoor->pFaces[uFaceID];
+      if ( !pRenderer->pRenderD3D )
+      {
+        result = sub_423B5D(uFaceID);
+        if ( result )
+        {
+          result = sub_424829(result, &stru_F8A590, pBLVRenderParams->field_7C, v2);
+          if ( result )
+          {
+            result = (int)v3->GetTexture();
+            v4 = (Texture *)result;
+            v96 = (Texture *)result;
+            if ( result )
+            {
+              v5 = *(short *)(result + 38);
+              LOBYTE(v3->uAttributes) |= 0x80u;
+              v92 = v5;
+              sub_4AE5F1(v2);
+              ++pBLVRenderParams->field_84;
+              v6 = stru_F8AD28.pDeltaUV[0];
+              v116 = stru_F8AD28.pDeltaUV[1];
+              v7 = 0;
+              for ( i = bUseLoResSprites; v7 < stru_F8AD28.uNumLightsApplied; *(int *)v9 = v10 )
+              {
+                v8 = v116;
+                stru_F8AD28._blv_lights_xs[v7] += v6;
+                v9 = 4 * v7 + 16297672;
+                v10 = v8 - stru_F8AD28._blv_lights_ys[v7++];
+              }
+              v94 = sr_sub_47C24C_get_palette(v3, v92, 0, 1);
+              result = stru_F8A590._viewport_space_y;
+              a2 = stru_F8A590._viewport_space_y;
+              v11 = stru_F8A590._viewport_space_y * pRenderer->uTargetSurfacePitch;
+              v99 = 640 * stru_F8A590._viewport_space_y;
+              v86 = v4->pLevelOfDetail0;
+              v87 = v4->pLevelOfDetail1;
+              v88 = v4->pLevelOfDetail2;
+              v89 = v4->pLevelOfDetail3;
+              v98 = stru_F8A590._viewport_space_y * pRenderer->uTargetSurfacePitch;
+              v104 = 2 * pBLVRenderParams->field_0_timer_;
+              if ( stru_F8A590._viewport_space_y <= stru_F8A590._viewport_space_w )
+              {
+                v12 = 2 * stru_F8A590._viewport_space_y;
+                v101 = 2 * stru_F8A590._viewport_space_y;
+                while ( 1 )
+                {
+                  a1 = *(__int16 *)((char *)stru_F8A590.array_18 + v12);
+                  sub_4AE313(a1, result, &stru_F81018.field_0);
+                  if ( LOBYTE(viewparams->field_20) )
+                  {
+                    v15 = v95 * (v12 - pBLVRenderParams->uViewportY);
+                    v119 = &pBLVRenderParams->pTargetZBuffer[2
+                                                          * (*(__int16 *)((char *)stru_F8A590.array_18 + v12)
+                                                           + 320 * (v12 - pBLVRenderParams->uViewportY))
+                                                          - pBLVRenderParams->uViewportX];
+                    v16 = &pBLVRenderParams->pRenderTarget[v15
+                                                        + 2 * *(__int16 *)((char *)stru_F8A590.array_18 + v12)
+                                                        - pBLVRenderParams->uViewportX];
+                    v14 = &pBLVRenderParams->pRenderTarget[v15
+                                                        + 2 * *(__int16 *)((char *)stru_F8A590.array_3D8 + v12)
+                                                        - pBLVRenderParams->uViewportX];
+                    v123 = (unsigned int)v16;
+                  }
+                  else
+                  {
+                    v13 = *(__int16 *)((char *)stru_F8A590.array_18 + v12);
+                    v119 = &pBLVRenderParams->pTargetZBuffer[v13 + v99];
+                    v123 = (unsigned int)&pBLVRenderParams->pRenderTarget[v13 + v11];
+                    v14 = &pBLVRenderParams->pRenderTarget[v11 + *(__int16 *)((char *)stru_F8A590.array_3D8 + v12)];
+                  }
+                  v117 = (unsigned int)v14;
+                  HIWORD(v17) = HIWORD(stru_F81018.field_0.field_0);
+                  v18 = stru_F81018.field_0.field_10;
+                  LOWORD(v17) = 0;
+                  v97 = stru_F8AD28.field_0 | v17;
+                  v110 = sub_4AE491(SHIWORD(stru_F81018.field_0.field_4), SHIWORD(stru_F81018.field_0.field_8));
+                  v19 = stru_F81018.field_0.field_4 >> i;
+                  v20 = 11 - v18;
+                  v116 = stru_F81018.field_0.field_8 >> i;
+                  v21 = stru_F81018.field_0.field_8 >> i >> (11 - v18);
+                  v22 = stru_5C6E00;
+                  v122 = (unsigned __int16 *)v20;
+                  v121 = (stru_F81018.field_0.field_4 >> i) + 4 * stru_5C6E00->SinCos(v104 + v21);
+                  v23 = stru_5C6E00->SinCos(v104 + (v19 >> (char)v122) - stru_5C6E00->uIntegerHalfPi);
+                  v120 = v116 + 4 * v23;
+                  if ( v123 < v117 )
+                  {
+                    v24 = (char *)&stru_F81018.field_34.field_8;
+                    v114 = &stru_F81018.field_34.field_8;
+                    a1 += 16;
+                    while ( 1 )
+                    {
+                      sub_4AE313(a1, a2, (stru337_stru0 *)(v24 - 8));
+                      v25 = *((int *)v24 - 2);
+                      LOWORD(v25) = 0;
+                      v115 = v97;
+                      v26 = stru_F8AD28.field_0 | v25;
+                      if ( v97 <= (unsigned int)v26 )
+                        v115 = v26;
+                      v97 = v26;
+                      v27 = *((int *)v24 - 11);
+                      v28 = *((int *)v24 - 1);
+                      v105 = (&v86)[4 * v27];
+                      v111 = v27 + 16;
+                      v29 = v4->uWidthMinus1;
+                      v109 = v27 + v27 + 16 - v4->uWidthLn2;
+                      v107 = v29 >> v27;
+                      v30 = v28 >> i;
+                      v102 = v4->uHeightMinus1 >> v27 << (v27 + 16);
+                      v31 = *v114 >> i;
+                      v122 = (unsigned __int16 *)(11 - v27);
+                      v116 = v30 + 4 * stru_5C6E00->SinCos(v104 + (v31 >> (11 - v27)));
+                      v90 = v31 + 4 * stru_5C6E00->SinCos(v104 + (v30 >> (char)v122) - stru_5C6E00->uIntegerHalfPi);
+                      v108 = (signed int)(v116 - v121) >> 4;
+                      v103 = (v90 - v120) >> 4;
+                      v32 = v123 + 32;
+                      if ( LOBYTE(viewparams->field_20) )
+                        v32 = v123 + 64;
+                      if ( v32 > v117 )
+                        v32 = v117;
+                      v118 = v32;
+                      v100 = sub_4AE491(*((short *)v114 - 1), *((short *)v114 + 1));
+                      v106 = (signed int)(v32 - v123) >> 1;
+                      if ( v110 >> 16 == v100 >> 16 )
+                      {
+                        v122 = sr_sub_47C24C_get_palette(v91, v92, v110 >> 16, 1);
+                        if ( LOBYTE(viewparams->field_20) )
+                        {
+                          v44 = v123;
+                          if ( v123 < v118 )
+                          {
+                            v45 = v119;
+                            v46 = v122;
+                            v47 = v121;
+                            v48 = v120;
+                            v49 = v111;
+                            v50 = v109;
+                            if ( v106 & 2 )
+                            {
+                              *v119 = v115;
+                              v45 -= 2;
+                              v44 = v123 + 4;
+                              goto LABEL_37;
+                            }
+                            do
+                            {
+                              v44 += 8;
+                              v51 = *(&v105[v107 & (v47 >> v49)] + ((v102 & (unsigned int)v48) >> v50));
+                              v52 = v115;
+                              LOWORD(v51) = v46[v51];
+                              *v45 = v115;
+                              v45[1] = v52;
+                              v45[640] = v52;
+                              v45[641] = v52;
+                              *(short *)(v44 - 8) = v51;
+                              *(short *)(v44 - 6) = v51;
+                              *(short *)(v44 + 1272) = v51;
+                              *(short *)(v44 + 1274) = v51;
+                              v45[2] = v52;
+                              v45[3] = v52;
+                              v45[642] = v52;
+                              v45[643] = v52;
+                              v121 += v108;
+                              v120 += v103;
+                              v47 = v121;
+                              v48 = v120;
+LABEL_37:
+                              v45 += 4;
+                              v53 = v46[*(&v105[v107 & (v47 >> v49)] + ((v102 & (unsigned int)v48) >> v50))];
+                              v54 = v108;
+                              *(short *)(v44 - 4) = v53;
+                              *(short *)(v44 - 2) = v53;
+                              *(short *)(v44 + 1276) = v53;
+                              *(short *)(v44 + 1278) = v53;
+                              v121 += v54;
+                              v120 += v103;
+                              v47 = v121;
+                              v48 = v120;
+                            }
+                            while ( v44 < v118 );
+                            v123 = v44;
+                            v119 = v45;
+                          }
+                        }
+                        else
+                        {
+                          v33 = v123;
+                          if ( v123 < v118 )
+                          {
+                            v34 = v119;
+                            v35 = v122;
+                            v36 = v121;
+                            v37 = v120;
+                            v38 = v111;
+                            v39 = v109;
+                            if ( v106 & 1 )
+                            {
+                              *v119 = v115;
+                              --v34;
+                              v33 = v123 + 2;
+                              goto LABEL_30;
+                            }
+                            do
+                            {
+                              v33 += 4;
+                              v40 = *(&v105[v107 & (v36 >> v38)] + ((v102 & (unsigned int)v37) >> v39));
+                              v41 = v115;
+                              LOWORD(v40) = v35[v40];
+                              *v34 = v115;
+                              *(short *)(v33 - 4) = v40;
+                              v34[1] = v41;
+                              v121 += v108;
+                              v120 += v103;
+                              v36 = v121;
+                              v37 = v120;
+LABEL_30:
+                              v42 = (unsigned int)(&v105[v107 & (v36 >> v38)] + ((v102 & (unsigned int)v37) >> v39));
+                              v34 += 2;
+                              v43 = v108;
+                              *(short *)(v33 - 2) = v35[*(char *)v42];
+                              v121 += v43;
+                              v120 += v103;
+                              v36 = v121;
+                              v37 = v120;
+                            }
+                            while ( v33 < v118 );
+                            v123 = v33;
+                            v119 = v34;
+                          }
+                        }
+                      }
+                      else
+                      {
+                        v55 = v110 - ((v100 - v110) >> 4);
+                        v110 = (v100 - v110) >> 4;
+                        v122 = (unsigned __int16 *)v55;
+                        if ( LOBYTE(viewparams->field_20) )
+                        {
+                          v71 = v123;
+                          if ( v123 < v118 )
+                          {
+                            v72 = v119;
+                            v73 = v94;
+                            v74 = v121;
+                            v75 = v120;
+                            v76 = v111;
+                            v77 = v109;
+                            if ( v106 & 2 )
+                            {
+                              *v119 = v115;
+                              v72 += 2;
+                              v71 = v123 + 4;
+                              goto LABEL_52;
+                            }
+                            do
+                            {
+                              v78 = (v107 & (v74 >> v76)) + ((v102 & (unsigned int)v75) >> v77);
+                              v79 = (int)((char *)v122 + v110);
+                              v71 += 8;
+                              v122 = (unsigned __int16 *)v79;
+                              v80 = ((v79 & 0xFFFF0000u) >> 8) + v105[v78];
+                              v81 = v115;
+                              LOWORD(v80) = v73[v80];
+                              *v72 = v115;
+                              v72[1] = v81;
+                              v72[640] = v81;
+                              v72[641] = v81;
+                              *(short *)(v71 - 8) = v80;
+                              *(short *)(v71 - 6) = v80;
+                              *(short *)(v71 + 1272) = v80;
+                              *(short *)(v71 + 1274) = v80;
+                              v72[2] = v81;
+                              v72[3] = v81;
+                              v72[642] = v81;
+                              v72[643] = v81;
+                              v121 += v108;
+                              v120 += v103;
+                              v74 = v121;
+                              v75 = v120;
+                              v72 += 4;
+LABEL_52:
+                              v82 = (v107 & (v74 >> v76)) + ((v102 & (unsigned int)v75) >> v77);
+                              v83 = (int)((char *)v122 + v110);
+                              v84 = v105[v82];
+                              v122 = (unsigned __int16 *)v83;
+                              LOWORD(v84) = v73[((v83 & 0xFFFF0000u) >> 8) + v84];
+                              v85 = v108;
+                              *(short *)(v71 - 4) = v84;
+                              *(short *)(v71 - 2) = v84;
+                              *(short *)(v71 + 1276) = v84;
+                              *(short *)(v71 + 1278) = v84;
+                              v121 += v85;
+                              v120 += v103;
+                              v74 = v121;
+                              v75 = v120;
+                            }
+                            while ( v71 < v118 );
+                            v123 = v71;
+                            v119 = v72;
+                          }
+                        }
+                        else
+                        {
+                          v56 = v123;
+                          if ( v123 < v118 )
+                          {
+                            v57 = v119;
+                            v58 = v94;
+                            v59 = v121;
+                            v60 = v120;
+                            v61 = v111;
+                            v62 = v109;
+                            if ( v106 & 1 )
+                            {
+                              *v119 = v115;
+                              ++v57;
+                              v56 = v123 + 2;
+                              goto LABEL_45;
+                            }
+                            do
+                            {
+                              v63 = (v107 & (v59 >> v61)) + ((v102 & (unsigned int)v60) >> v62);
+                              v64 = (int)((char *)v122 + v110);
+                              v56 += 4;
+                              v122 = (unsigned __int16 *)v64;
+                              v65 = ((v64 & 0xFFFF0000u) >> 8) + v105[v63];
+                              v66 = v115;
+                              LOWORD(v65) = v58[v65];
+                              *v57 = v115;
+                              *(short *)(v56 - 4) = v65;
+                              v57[1] = v66;
+                              v121 += v108;
+                              v120 += v103;
+                              v59 = v121;
+                              v60 = v120;
+                              v57 += 2;
+LABEL_45:
+                              v67 = (v107 & (v59 >> v61)) + ((v102 & (unsigned int)v60) >> v62);
+                              v68 = (int)((char *)v122 + v110);
+                              v69 = v105[v67];
+                              v122 = (unsigned __int16 *)v68;
+                              LOWORD(v69) = v58[((v68 & 0xFFFF0000u) >> 8) + v69];
+                              v70 = v108;
+                              *(short *)(v56 - 2) = v69;
+                              v121 += v70;
+                              v120 += v103;
+                              v59 = v121;
+                              v60 = v120;
+                            }
+                            while ( v56 < v118 );
+                            v123 = v56;
+                            v119 = v57;
+                          }
+                        }
+                      }
+                      v114 += 13;
+                      v110 = v100;
+                      a1 += 16;
+                      v4 = v96;
+                      v121 = v116;
+                      v120 = v90;
+                      if ( v123 >= v117 )
+                        break;
+                      v24 = (char *)v114;
+                      v22 = stru_5C6E00;
+                    }
+                  }
+                  ++a2;
+                  v98 += v95;
+                  result = a2;
+                  v101 += 2;
+                  v99 += 640;
+                  if ( a2 > stru_F8A590._viewport_space_w )
+                    break;
+                  v12 = v101;
+                  result = a2;
+                  v11 = v98;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return result;
+}
+// 4AE491: using guessed type int __fastcall sub_4AE491(int, int);
+
+//----- (004ADD1D) --------------------------------------------------------
+void __fastcall sub_4ADD1D(int uFaceID)
+{
+  int v1; // edi@1
+  BLVFace *v2; // esi@3
+  signed int v3; // ebx@4
+  Texture *v4; // edi@9
+  signed int v5; // eax@9
+  char *v6; // edi@12
+  signed int v7; // eax@15
+  unsigned int v8; // eax@16
+  __int16 v9; // cx@19
+  unsigned __int8 *v10; // eax@19
+  unsigned __int16 *v11; // eax@19
+  int v12; // edi@19
+  int v13; // ebx@20
+  stru352 *v14; // esi@20
+  DWORD v15; // eax@22
+  signed int v16; // ecx@22
+  signed int v17; // ST68_4@22
+  int v18; // eax@22
+  int v19; // ecx@22
+  unsigned int v20; // esi@23
+  int v21; // edi@23
+  int v22; // eax@23
+  int *v23; // ebx@24
+  int v24; // edx@24
+  int v25; // ebx@25
+  unsigned __int16 v26; // cx@25
+  int v27; // edx@26
+  unsigned __int16 v28; // cx@26
+  unsigned __int8 v29; // sf@27
+  unsigned __int8 v30; // of@27
+  unsigned int v31; // esi@29
+  int v32; // edi@29
+  unsigned __int16 *v33; // eax@29
+  int *v34; // ebx@30
+  int v35; // edx@30
+  int v36; // ebx@31
+  unsigned __int16 v37; // cx@31
+  int v38; // edx@32
+  unsigned __int16 v39; // cx@32
+  Texture *v40; // [sp-10h] [bp-6Ch]@16
+  int v41; // [sp-Ch] [bp-68h]@15
+  unsigned int v42; // [sp+10h] [bp-4Ch]@1
+  signed int v43; // [sp+14h] [bp-48h]@12
+  signed int v44; // [sp+14h] [bp-48h]@22
+  int v45; // [sp+1Ch] [bp-40h]@22
+  int v46; // [sp+20h] [bp-3Ch]@22
+  int v47; // [sp+24h] [bp-38h]@19
+  char v48; // [sp+28h] [bp-34h]@19
+  int v49; // [sp+2Ch] [bp-30h]@19
+  unsigned __int8 *v50; // [sp+30h] [bp-2Ch]@19
+  unsigned __int16 *v51; // [sp+34h] [bp-28h]@19
+  int v52; // [sp+38h] [bp-24h]@22
+  int v53; // [sp+3Ch] [bp-20h]@22
+  signed int v54; // [sp+40h] [bp-1Ch]@12
+  int v55; // [sp+40h] [bp-1Ch]@20
+  int v56; // [sp+44h] [bp-18h]@20
+  stru352 *i; // [sp+48h] [bp-14h]@20
+  unsigned __int16 *v58; // [sp+4Ch] [bp-10h]@23
+  int v59; // [sp+50h] [bp-Ch]@4
+  int v60; // [sp+50h] [bp-Ch]@19
+  int v61; // [sp+54h] [bp-8h]@22
+  int *v62; // [sp+58h] [bp-4h]@23
+  int *v63; // [sp+58h] [bp-4h]@29
+
+  v1 = uFaceID;
+  v42 = pRenderer->uTargetSurfacePitch;
+  if ( uFaceID >= 0 && uFaceID < (signed int)pIndoor->uNumFaces )
+  {
+    v2 = &pIndoor->pFaces[uFaceID];
+    if ( pRenderer->pRenderD3D )
+    {
+      v3 = sub_424579(uFaceID, &stru_F8AD28);
+      v59 = v3;
+    }
+    else
+    {
+      v59 = sub_423B5D(uFaceID);
+      v3 = v59;
+    }
+    if ( v3 && (pRenderer->pRenderD3D || sub_424829(v3, &stru_F8A590, pBLVRenderParams->field_7C, v1)) )
+    {
+      v4 = v2->GetTexture();
+      v5 = 0;
+      if ( v4 )
+      {
+        if ( pRenderer->pRenderD3D )
+        {
+          if ( v3 > 0 )
+          {
+            v54 = v3;
+            v43 = v3;
+            v6 = (char *)&array_507D30[0].v;
+            do
+            {
+              *((float *)v6 - 1) = (double)((GetTickCount() >> 5) - pBLVRenderParams->vPartyPos.x) + *((float *)v6 - 1);
+              *(float *)v6 = (double)(pBLVRenderParams->vPartyPos.y + (GetTickCount() >> 5)) + *(float *)v6;
+              v6 += 48;
+              --v54;
+            }
+            while ( v54 );
+            v3 = v59;
+            v5 = v43;
+          }
+          v7 = v5;
+          v41 = stru_F8AD28.field_0;
+          array_507D30[v7].u = array_507D30[v7].u * 0.25;
+          array_507D30[v7].v = array_507D30[v7].v * 0.25;
+          if ( BYTE1(v2->uAttributes) & 0x40 )
+          {
+            v40 = v2->GetTexture();
+            v8 = pTextureFrameTable->GetFrameTexture(v2->uBitmapID, pBLVRenderParams->field_0_timer_);
+          }
+          else
+          {
+            v40 = v2->GetTexture();
+            v8 = v2->uBitmapID;
+          }
+          pRenderer->DrawIndoorPolygon(v3, v2, pBitmaps_LOD->pHardwareTextures[v8], v40, v41, -1, 0);
+        }
+        else
+        {
+          v49 = v4->uWidthMinus1;
+          v47 = v4->uHeightMinus1 << 16;
+          v9 = 16 - v4->uWidthLn2;
+          v10 = v4->pLevelOfDetail0;
+          LOBYTE(v2->uAttributes) |= 0x80u;
+          v48 = v9;
+          v50 = v10;
+          sub_4AF412();
+          ++pBLVRenderParams->uNumFacesRenderedThisFrame;
+          v11 = sr_sub_47C24C_get_palette(v2, v4->palette_id2, 0, 1);
+          v12 = stru_F8A590._viewport_space_y;
+          v51 = v11;
+          v60 = stru_F8A590._viewport_space_y;
+          if ( stru_F8A590._viewport_space_y <= stru_F8A590._viewport_space_w )
+          {
+            v13 = 2 * stru_F8A590._viewport_space_y;
+            v14 = &stru_F83B80[stru_F8A590._viewport_space_y];
+            v55 = 2 * stru_F8A590._viewport_space_y;
+            v56 = 640 * stru_F8A590._viewport_space_y;
+            for ( i = &stru_F83B80[stru_F8A590._viewport_space_y]; ; v14 = i )
+            {
+              sub_4AE1E7(v12, *(__int16 *)((char *)stru_F8A590.array_18 + v13), v12);
+              v14->field_0 += (GetTickCount() << 11) - (pBLVRenderParams->vPartyPos.x << 16);
+              v15 = GetTickCount();
+              v16 = v14->field_0;
+              v14->field_4 += (32 * pBLVRenderParams->vPartyPos.y + v15) << 11;
+              v45 = v14->field_4 >> 3;
+              v44 = v16 >> 3;
+              v17 = (signed int)((unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)v14->field_28) >> 16) >> 3;
+              v52 = (unsigned __int64)(v17 * (signed __int64)-pBLVRenderParams->sSineY) >> 16;
+              v53 = (unsigned __int64)(v17 * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+              v18 = v14->field_28;
+              v19 = *(__int16 *)((char *)stru_F8A590.array_18 + v13);
+              LOWORD(v18) = 0;
+              v46 = stru_F8AD28.field_0 | v18;
+              v61 = *(__int16 *)((char *)stru_F8A590.array_3D8 + v13) - v19;
+              if ( LOBYTE(viewparams->field_20) )
+              {
+                v63 = &pBLVRenderParams->pTargetZBuffer[2 * (v19 + 320 * (v13 - pBLVRenderParams->uViewportY))
+                                                     - pBLVRenderParams->uViewportX];
+                v31 = v44;
+                v32 = v45;
+                v33 = &pBLVRenderParams->pRenderTarget[v42 * (v13 - pBLVRenderParams->uViewportY)
+                                                    + 2 * v19
+                                                    - pBLVRenderParams->uViewportX];
+                if ( v61 & 1 )
+                {
+                  --v61;
+                  v33 = &pBLVRenderParams->pRenderTarget[v42 * (v13 - pBLVRenderParams->uViewportY)
+                                                      + 2 * v19
+                                                      - pBLVRenderParams->uViewportX
+                                                      - 2];
+                  v34 = &pBLVRenderParams->pTargetZBuffer[2 * (v19 + 320 * (v13 - pBLVRenderParams->uViewportY))
+                                                       - pBLVRenderParams->uViewportX];
+                  v35 = v46;
+                  v63 += 2;
+                  goto LABEL_32;
+                }
+                while ( 1 )
+                {
+                  v30 = __OFSUB__(v61, 2);
+                  v29 = v61 - 2 < 0;
+                  v61 -= 2;
+                  if ( v29 ^ v30 )
+                    break;
+                  v36 = *(&v50[v49 & (v31 >> 16)] + ((v47 & (unsigned int)v32) >> v48));
+                  v31 += v52;
+                  v37 = v51[v36];
+                  v32 += v53;
+                  v34 = v63;
+                  v35 = v46;
+                  *v33 = v37;
+                  v33[1] = v37;
+                  v33[640] = v37;
+                  v33[641] = v37;
+                  v63 += 4;
+                  v34[2] = v46;
+                  v34[3] = v46;
+                  v34[642] = v46;
+                  v34[643] = v46;
+LABEL_32:
+                  *v34 = v35;
+                  v34[1] = v35;
+                  v34[640] = v35;
+                  v34[641] = v35;
+                  v38 = v49 & (v31 >> 16);
+                  v33 += 4;
+                  v31 += v52;
+                  v39 = v51[*(&v50[v38] + ((v47 & (unsigned int)v32) >> v48))];
+                  v32 += v53;
+                  *(v33 - 2) = v39;
+                  *(v33 - 1) = v39;
+                  v33[638] = v39;
+                  v33[639] = v39;
+                }
+              }
+              else
+              {
+                v58 = &pBLVRenderParams->pRenderTarget[v19 + v12 * pRenderer->uTargetSurfacePitch];
+                v62 = &pBLVRenderParams->pTargetZBuffer[v56 + v19];
+                v20 = v44;
+                v21 = v45;
+                v22 = (int)v58;
+                if ( v61 & 1 )
+                {
+                  --v61;
+                  v22 = (int)(v58 - 1);
+                  v23 = &pBLVRenderParams->pTargetZBuffer[v56 + v19];
+                  v24 = v46;
+                  ++v62;
+                  goto LABEL_26;
+                }
+                while ( 1 )
+                {
+                  v30 = __OFSUB__(v61, 2);
+                  v29 = v61 - 2 < 0;
+                  v61 -= 2;
+                  if ( v29 ^ v30 )
+                    break;
+                  v25 = *(&v50[v49 & (v20 >> 16)] + ((v47 & (unsigned int)v21) >> v48));
+                  v20 += v52;
+                  v26 = v51[v25];
+                  v21 += v53;
+                  v23 = v62;
+                  v24 = v46;
+                  *(short *)v22 = v26;
+                  v62 += 2;
+                  v23[1] = v46;
+LABEL_26:
+                  *v23 = v24;
+                  v27 = v49 & (v20 >> 16);
+                  v22 += 4;
+                  v20 += v52;
+                  v28 = v51[*(&v50[v27] + ((v47 & (unsigned int)v21) >> v48))];
+                  v21 += v53;
+                  *(short *)(v22 - 2) = v28;
+                }
+              }
+              ++v60;
+              ++i;
+              v56 += 640;
+              v55 += 2;
+              if ( v60 > stru_F8A590._viewport_space_w )
+                break;
+              v13 = v55;
+              v12 = v60;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+//----- (004AE1E7) --------------------------------------------------------
+int __fastcall sub_4AE1E7(int a1, int a2, int a3)
+{
+  int v3; // ebx@1
+  int v4; // edi@1
+  int v5; // esi@1
+  signed __int64 v6; // qtt@3
+  int v7; // esi@3
+  int v8; // eax@5
+  int result; // eax@5
+  int v10; // edx@5
+  int v11; // [sp+Ch] [bp-8h]@1
+  int v12; // [sp+1Ch] [bp+8h]@2
+
+  v3 = pBLVRenderParams->uViewportCenterY - a3;
+  v4 = pBLVRenderParams->uViewportCenterX - a2;
+  v11 = a1;
+  v5 = (pBLVRenderParams->uViewportCenterY - a3) * stru_F8AD28.vec_80.y
+     + stru_F8AD28.field_7C
+     + (pBLVRenderParams->uViewportCenterX - a2) * stru_F8AD28.vec_80.x;
+  if ( v5 && (v12 = abs(stru_F8AD28.vec_80.z) >> 14, v12 <= abs(v5)) )
+  {
+    LODWORD(v6) = stru_F8AD28.vec_80.z << 16;
+    HIDWORD(v6) = stru_F8AD28.vec_80.z >> 16;
+    v7 = v6 / (v3 * stru_F8AD28.vec_80.y + stru_F8AD28.field_7C + v4 * stru_F8AD28.vec_80.x);
+  }
+  else
+  {
+    v7 = 1073741824;
+  }
+  v8 = stru_F8AD28.vec_9C.z;
+  stru_F83B80[v11].field_0 = ((unsigned __int64)((v3 * stru_F8AD28.vec_8C.z
+                                                + stru_F8AD28.vec_8C.x
+                                                + v4 * stru_F8AD28.vec_8C.y)
+                                               * (signed __int64)v7) >> 16)
+                           + stru_F8AD28.field_98;
+  result = (unsigned __int64)((v3 * v8 + stru_F8AD28.vec_9C.x + v4 * stru_F8AD28.vec_9C.y) * (signed __int64)v7) >> 16;
+  v10 = result + stru_F8AD28.field_A8;
+  stru_F83B80[v11].field_28 = v7;
+  stru_F83B80[v11].field_4 = v10;
+  return result;
+}
+
+//----- (004AE313) --------------------------------------------------------
+int __fastcall sub_4AE313(int viewport_space_x, int viewport_space_y, stru337_stru0 *p)
+{
+  int _dy; // ebx@1
+  int _dx; // edi@1
+  int v5; // ecx@1
+  int v6; // esi@1
+  int v7; // ST18_4@2
+  signed __int64 v8; // qtt@3
+  unsigned int v9; // ecx@3
+  int result; // eax@8
+  int v11; // [sp+Ch] [bp-8h]@1
+
+  _dy = pBLVRenderParams->uViewportCenterY - viewport_space_y;
+  _dx = pBLVRenderParams->uViewportCenterX - viewport_space_x;
+  ++pBLVRenderParams->field_88;
+  v5 = (pBLVRenderParams->uViewportCenterY - viewport_space_y) * stru_F8AD28.vec_80.y + stru_F8AD28.field_7C;
+  v6 = v5 + _dx * stru_F8AD28.vec_80.x;
+  v11 = v5 + _dx * stru_F8AD28.vec_80.x;
+  if ( v5 + _dx * stru_F8AD28.vec_80.x && (v7 = abs(stru_F8AD28.vec_80.z) >> 14, v7 <= abs(v6)) )
+  {
+    LODWORD(v8) = stru_F8AD28.vec_80.z << 16;
+    HIDWORD(v8) = stru_F8AD28.vec_80.z >> 16;
+    v9 = v8 / v11;
+  }
+  else
+  {
+    v9 = 0x40000000u;
+  }
+  if ( (signed int)v9 >= stru_F8AD28.field_34 )
+    p->field_0 = v9;
+  else
+    p->field_0 = stru_F8AD28.field_34;
+  p->field_4 = ((unsigned __int64)((_dy * stru_F8AD28.vec_8C.z + stru_F8AD28.vec_8C.x + _dx * stru_F8AD28.vec_8C.y)
+                                 * (signed __int64)(signed int)v9) >> 16)
+             + stru_F8AD28.field_98
+             + (stru_F8AD28.pDeltaUV[0] << 16);
+  p->field_8 = ((unsigned __int64)((_dy * stru_F8AD28.vec_9C.z + stru_F8AD28.vec_9C.x + _dx * stru_F8AD28.vec_9C.y)
+                                 * (signed __int64)(signed int)v9) >> 16)
+             + stru_F8AD28.field_A8
+             + (stru_F8AD28.pDeltaUV[1] << 16);
+  result = abs((__int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)(signed int)v9) >> 16);
+  if ( result < 369620 || bUseLoResSprites )
+  {
+    if ( result < 184810 )
+      p->field_10 = result > 92405;
+    else
+      p->field_10 = 2;
+  }
+  else
+  {
+    p->field_10 = 3;
+  }
+  return result;
+}
+
+//----- (004AE491) --------------------------------------------------------
+int __fastcall sub_4AE491(signed int a1, signed int a2)
+{
+  signed int v2; // eax@1
+  signed int v3; // edi@1
+  int v4; // ecx@1
+  int v5; // esi@2
+  int v6; // eax@2
+  int v7; // ebx@2
+  unsigned int v8; // ecx@2
+  int v9; // edx@5
+  int v10; // edx@7
+  unsigned int v11; // eax@8
+  int v13; // [sp+4h] [bp-18h]@2
+  int v14; // [sp+8h] [bp-14h]@2
+  signed int v15; // [sp+Ch] [bp-10h]@1
+  int v16; // [sp+14h] [bp-8h]@1
+  int v17; // [sp+18h] [bp-4h]@1
+
+  v2 = a1 >> SLOBYTE(stru_F8AD28.field_38);
+  v3 = a2 >> SLOBYTE(stru_F8AD28.field_38);
+  v17 = stru_F8AD28.uCurrentAmbientLightLevel;
+  v4 = 0;
+  v15 = v2;
+  v16 = 0;
+  if ( stru_F8AD28.uNumLightsApplied > 0 )
+  {
+    do
+    {
+      v5 = v16;
+      v13 = abs(v2 - stru_F8AD28._blv_lights_xs[v16]);
+      v14 = abs(v3 - stru_F8AD28._blv_lights_ys[v16]);
+      v6 = stru_F8AD28._blv_lights_light_dot_faces[v16];
+      v7 = v13;
+      v8 = v14;
+      if ( v6 < v13 )
+      {
+        v6 = v13;
+        v7 = stru_F8AD28._blv_lights_light_dot_faces[v16];
+      }
+      if ( v6 < v14 )
+      {
+        v9 = v6;
+        v6 = v14;
+        v8 = v9;
+      }
+      if ( v7 < (signed int)v8 )
+      {
+        v10 = v8;
+        v8 = v7;
+        v7 = v10;
+      }
+      v11 = ((unsigned int)(11 * v7) >> 5) + (v8 >> 2) + v6;
+      if ( (signed int)v11 < stru_F8AD28._blv_lights_radii[v5] )
+        v17 += 30 * (v11 * stru_F8AD28._blv_lights_inv_radii[v5] - 65536);
+      ++v16;
+      v2 = v15;
+    }
+    while ( v16 < stru_F8AD28.uNumLightsApplied );
+    v4 = 0;
+  }
+  if ( stru_F8AD28.field_3E4 != v4 )
+    v17 -= stru_F8AD28.field_3E8 * (v2 - stru_F8AD28.field_3F0) + stru_F8AD28.field_3EC * (v3 - stru_F8AD28.field_3F4);
+  if ( v17 >= v4 )
+  {
+    if ( v17 > 2031616 )
+      v17 = 2031616;
+  }
+  else
+  {
+    v17 = v4;
+  }
+  ++pBLVRenderParams->field_8C;
+  return v17;
+}
+// 4AE491: using guessed type int __fastcall sub_4AE491(int, int);
+
+
+
+
+//----- (004AE5F1) --------------------------------------------------------
+void __fastcall sub_4AE5F1(unsigned int uFaceID)
+{
+  BLVFace *v1; // esi@1
+  BLVFaceExtra *v2; // ebx@1
+  int v3; // eax@1
+  int v4; // edi@1
+  Texture *v5; // edi@1
+  int v6; // eax@1
+  unsigned int v7; // eax@1
+  unsigned int v8; // ecx@1
+  unsigned int v9; // eax@1
+  unsigned int v10; // ecx@5
+  int v11; // edi@10
+  int v12; // ecx@10
+  int v13; // eax@10
+  int v14; // edx@10
+  int v15; // ebx@12
+  double v16; // st7@16
+  int v17; // eax@16
+  char *v18; // ebx@17
+  int v19; // ecx@19
+  int v20; // eax@19
+  int v21; // edx@21
+  int v22; // eax@23
+  int v23; // ST04_4@26
+  int v24; // edi@26
+  double v25; // st6@26
+  int v26; // eax@26
+  double v27; // st6@26
+  int v28; // ecx@26
+  char v29; // al@26
+  int v30; // edx@28
+  int v31; // ecx@28
+  BLVLightMM7 *v32; // ecx@32
+  int v33; // edi@33
+  int v34; // edx@33
+  int v35; // eax@33
+  int v36; // edi@35
+  int v37; // edx@37
+  int v38; // ebx@39
+  int v39; // edi@42
+  int v40; // eax@42
+  char *v41; // ebx@45
+  signed int v42; // ecx@47
+  int v43; // edi@47
+  int v44; // eax@49
+  int v45; // edx@51
+  int v46; // eax@53
+  int v47; // ST04_4@55
+  int v48; // edi@55
+  double v49; // st6@55
+  int v50; // eax@55
+  double v51; // st6@55
+  int v52; // eax@55
+  int v53; // ecx@57
+  int v54; // ecx@58
+  int v55; // ecx@59
+  int v56; // edx@62
+  int v57; // ecx@62
+  int v58; // eax@63
+  int v59; // edx@64
+  int v60; // ecx@67
+  int v61; // edx@67
+  int v62; // eax@68
+  int v63; // edx@69
+  signed int v64; // ecx@72
+  double v65; // st7@75
+  Vec3_int_ v66; // [sp+Ch] [bp-34h]@9
+  Vec3_int_ v67; // [sp+18h] [bp-28h]@9
+  BLVFaceExtra *v68; // [sp+24h] [bp-1Ch]@1
+  int v69; // [sp+28h] [bp-18h]@10
+  int v70; // [sp+2Ch] [bp-14h]@10
+  int X; // [sp+30h] [bp-10h]@10
+  int v72; // [sp+34h] [bp-Ch]@10
+  int v73; // [sp+38h] [bp-8h]@10
+  int v74; // [sp+3Ch] [bp-4h]@10
+
+  v1 = &pIndoor->pFaces[uFaceID];
+  v2 = &pIndoor->pFaceExtras[v1->uFaceExtraID];
+  v3 = v1->uBitmapID;
+  v4 = v1->uBitmapID;
+  v68 = v2;
+  v5 = (Texture *)(v4 != -1 ? (int)&pBitmaps_LOD->pTextures[v3] : 0);
+  v6 = 8 * uFaceID;
+  LOBYTE(v6) = 8 * uFaceID | 6;
+  stru_F8AD28.field_0 = v6;
+  stru_F8AD28.plane_4.vNormal.x = v1->pFacePlane_old.vNormal.x;
+  stru_F8AD28.plane_4.vNormal.y = v1->pFacePlane_old.vNormal.y;
+  stru_F8AD28.plane_4.vNormal.z = v1->pFacePlane_old.vNormal.z;
+  stru_F8AD28.plane_4.dist = v1->pFacePlane_old.dist;
+  stru_F8AD28.pDeltaUV[0] = v2->sTextureDeltaU;
+  stru_F8AD28.pDeltaUV[1] = v2->sTextureDeltaV;
+  v7 = GetTickCount();
+  v8 = v1->uAttributes;
+  v9 = v7 >> 3;
+  if ( v8 & 4 )
+  {
+    stru_F8AD28.pDeltaUV[1] -= v9 & v5->uHeightMinus1;
+  }
+  else
+  {
+    if ( v8 & 0x20 )
+      stru_F8AD28.pDeltaUV[1] += v9 & v5->uHeightMinus1;
+  }
+  v10 = v1->uAttributes;
+  if ( BYTE1(v10) & 8 )
+  {
+    stru_F8AD28.pDeltaUV[0] -= v9 & v5->uWidthMinus1;
+  }
+  else
+  {
+    if ( v10 & 0x40 )
+      stru_F8AD28.pDeltaUV[0] += v9 & v5->uWidthMinus1;
+  }
+  v1->_get_normals(&v67, &v66);
+  stru_F8AD28.vec_14.x = v67.x;
+  stru_F8AD28.vec_14.y = v67.y;
+  stru_F8AD28.vec_14.z = v67.z;
+  stru_F8AD28.vec_20.x = v66.x;
+  stru_F8AD28.vec_20.y = v66.y;
+  stru_F8AD28.vec_20.z = v66.z;
+  stru_F8AD28.uDefaultAmbientLightLevel = v2->field_22;
+  if ( pBLVRenderParams->sPartyRotX )
+  {
+    v74 = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    v74 = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v74;
+    X = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+    stru_F8AD28.rotated_normal.x = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - X;
+    stru_F8AD28.rotated_normal.y = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
+                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                                 + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
+                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.rotated_normal.z = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+                                 + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.z
+                                                     * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    v70 = (unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    v74 = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v70;
+    v70 = (unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+    stru_F8AD28.vec_60.y = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v70;
+    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.field_6C = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    v70 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    v74 = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v70;
+    X = (unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    v72 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+    v70 = (unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+    stru_F8AD28.vec_70.x = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v70;
+    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.vec_70.z = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    v74 = pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.y
+        - pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.x;
+    v11 = -(pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.y
+          + pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.x);
+    v73 = -65536 * pBLVRenderParams->vPartyPos.z;
+    v70 = (unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+    v12 = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v70;
+    v69 = (unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+    v13 = pBLVRenderParams->vPartyPos.y;
+    v70 = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+        + ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    v14 = pBLVRenderParams->vPartyPos.x;
+  }
+  else
+  {
+    v70 = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    stru_F8AD28.rotated_normal.x = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
+                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                                 - v70;
+    stru_F8AD28.rotated_normal.z = stru_F8AD28.plane_4.vNormal.z;
+    stru_F8AD28.rotated_normal.y = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
+                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                                 + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
+                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    v70 = (unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    stru_F8AD28.vec_60.y = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                         - v70;
+    stru_F8AD28.field_6C = stru_F8AD28.vec_14.z;
+    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    v70 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    stru_F8AD28.vec_70.x = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                         - v70;
+    v69 = (unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    v14 = pBLVRenderParams->vPartyPos.x;
+    stru_F8AD28.vec_70.z = stru_F8AD28.vec_20.z;
+    v13 = pBLVRenderParams->vPartyPos.y;
+    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    v12 = pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.y
+        - pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.x;
+    v11 = -(pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.y
+          + pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.x);
+    v70 = -65536 * pBLVRenderParams->vPartyPos.z;
+  }
+  stru_F8AD28.field_7C = stru_F8AD28.rotated_normal.x;
+  stru_F8AD28.vec_60.x = stru_F8AD28.plane_4.vNormal.z * pBLVRenderParams->vPartyPos.z
+                       + stru_F8AD28.plane_4.dist
+                       + stru_F8AD28.plane_4.vNormal.y * v13
+                       + stru_F8AD28.plane_4.vNormal.x * v14;
+  stru_F8AD28.vec_80.x = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44)
+                                          * (signed __int64)stru_F8AD28.rotated_normal.y) >> 16;
+  stru_F8AD28.vec_80.y = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44)
+                                          * (signed __int64)stru_F8AD28.rotated_normal.z) >> 16;
+  stru_F8AD28.vec_80.z = -stru_F8AD28.vec_60.x;
+  stru_F8AD28.vec_8C.x = stru_F8AD28.vec_60.y;
+  stru_F8AD28.vec_8C.y = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)stru_F8AD28.vec_60.z) >> 16;
+  stru_F8AD28.vec_8C.z = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)stru_F8AD28.field_6C) >> 16;
+  X = (unsigned __int64)(stru_F8AD28.vec_60.y * (signed __int64)v12) >> 16;
+  v15 = v70;
+  v70 = (unsigned __int64)(stru_F8AD28.field_6C * (signed __int64)v70) >> 16;
+  stru_F8AD28.vec_9C.x = stru_F8AD28.vec_70.x;
+  stru_F8AD28.field_98 = -(X + ((unsigned __int64)(stru_F8AD28.vec_60.z * (signed __int64)v11) >> 16) + v70);
+  stru_F8AD28.vec_9C.y = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)stru_F8AD28.vec_70.y) >> 16;
+  stru_F8AD28.vec_9C.z = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)stru_F8AD28.vec_70.z) >> 16;
+  X = (unsigned __int64)(stru_F8AD28.vec_70.x * (signed __int64)v12) >> 16;
+  v69 = (unsigned __int64)(stru_F8AD28.vec_70.y * (signed __int64)v11) >> 16;
+  v70 = (unsigned __int64)(stru_F8AD28.vec_70.z * (signed __int64)v15) >> 16;
+  stru_F8AD28.field_38 = 0;
+  stru_F8AD28.field_A8 = -(X
+                         + ((unsigned __int64)(stru_F8AD28.vec_70.y * (signed __int64)v11) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_70.z * (signed __int64)v15) >> 16));
+  if ( *(int *)&v68->field_4 || *(int *)&v68->field_8 )
+  {
+    stru_F8AD28.field_3E4 = 1;
+    stru_F8AD28.field_3E8 = *(int *)&v68->field_4;
+    stru_F8AD28.field_3EC = *(int *)&v68->field_8;
+    stru_F8AD28.field_3F0 = v68->field_1E;
+    stru_F8AD28.field_3F4 = v68->field_20;
+  }
+  else
+  {
+    stru_F8AD28.field_3E4 = 0;
+  }
+  v16 = 0.0039215689;
+  v17 = 116 * v1->uSectorID;
+  v69 = v17;
+  v74 = 0;
+  v73 = 0;
+  stru_F8AD28.uCurrentAmbientLightLevel = (stru_F8AD28.uDefaultAmbientLightLevel + *(__int16 *)((char *)&pIndoor->pSectors->uMinAmbientLightLevel + v17)) << 16;
+  v70 = pMobileLightsStack->uNumLightsActive;
+  if ( pMobileLightsStack->uNumLightsActive > 0 )
+  {
+    v18 = (char *)&pMobileLightsStack->pLights[0].vPosition.y;
+    do
+    {
+      if ( v74 >= 20 )
+        break;
+      v19 = *((short *)v18 + 2);
+      v20 = *((short *)v18 - 1);
+      if ( v20 > v1->pBounding.x1 - v19 )
+      {
+        if ( v20 < v19 + v1->pBounding.x2 )
+        {
+          v21 = *(short *)v18;
+          if ( v21 > v1->pBounding.y1 - v19 )
+          {
+            if ( v21 < v19 + v1->pBounding.y2 )
+            {
+              v22 = *((short *)v18 + 1);
+              if ( v22 > v1->pBounding.z1 - v19 )
+              {
+                if ( v22 < v19 + v1->pBounding.z2 )
+                {
+                  X = (v1->pFacePlane_old.dist
+                     + *((short *)v18 + 1) * v1->pFacePlane_old.vNormal.z
+                     + v21 * v1->pFacePlane_old.vNormal.y
+                     + *((short *)v18 - 1) * v1->pFacePlane_old.vNormal.x) >> 16;
+                  if ( X <= v19 )
+                  {
+                    v23 = X;
+                    v24 = v74;
+                    stru_F8AD28._blv_lights_radii[v74] = v19;
+                    stru_F8AD28._blv_lights_inv_radii[v24] = 65536 / v19;
+                    *(int *)((char *)&stru_F8AD28.field_240 + v24 * 4) = *((short *)v18 + 5) << 16;
+                    stru_F8AD28._blv_lights_xs[v24] = *((short *)v18 - 1);
+                    stru_F8AD28._blv_lights_ys[v24] = *(short *)v18;
+                    stru_F8AD28._blv_lights_zs[v24] = *((short *)v18 + 1);
+                    v68 = (BLVFaceExtra *)(unsigned __int8)v18[6];
+                    v25 = (double)(signed int)v68 * v16;
+                    v68 = (BLVFaceExtra *)(unsigned __int8)v18[7];
+                    v26 = (unsigned __int8)v18[8];
+                    *(float *)(v24 * 4 + 16297992) = v25;
+                    v27 = (double)(signed int)v68;
+                    v68 = (BLVFaceExtra *)v26;
+                    *(float *)(v24 * 4 + 16298072) = v27 * v16;
+                    *(float *)(v24 * 4 + 16298152) = (double)(signed int)v68 * v16;
+                    v16 = 0.0039215689;
+                    stru_F8AD28._blv_lights_light_dot_faces[v24] = abs(v23);
+                    v28 = v74;
+                    v29 = v18[9];
+                    ++v74;
+                    stru_F8AD28._blv_lights_types[v28] = v29;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      ++v73;
+      v18 += 18;
+      v17 = v69;
+    }
+    while ( v73 < v70 );
+  }
+  v30 = 0;
+  v73 = 0;
+  v31 = *(__int16 *)((char *)&pIndoor->pSectors->uNumLights + v17);
+  v70 = *(__int16 *)((char *)&pIndoor->pSectors->uNumLights + v17);
+  if ( v31 > 0 )
+  {
+    while ( v74 < 20 )
+    {
+      v32 = &pIndoor->pLights[*(&(*(BLVLightMM7 **)((char *)&pIndoor->pSectors->pLights + v17))->vPosition.x + v30)];
+      if ( !(v32->uAtributes & 8) )
+      {
+        v33 = v1->pBounding.x1;
+        v34 = v32->vPosition.x;
+        X = v32->uBrightness;
+        v35 = v32->uRadius;
+        v68 = (BLVFaceExtra *)v32->uRadius;
+        if ( v34 > v33 - v35 )
+        {
+          if ( v34 < v35 + v1->pBounding.x2 )
+          {
+            v36 = v32->vPosition.y;
+            if ( v36 > v1->pBounding.y1 - v35 )
+            {
+              if ( v36 < v35 + v1->pBounding.y2 )
+              {
+                v37 = v32->vPosition.z;
+                if ( v37 > v1->pBounding.z1 - v35 )
+                {
+                  if ( v37 < v35 + v1->pBounding.z2 )
+                  {
+                    v38 = (v1->pFacePlane_old.dist
+                         + v32->vPosition.x * v1->pFacePlane_old.vNormal.x
+                         + v37 * v1->pFacePlane_old.vNormal.z
+                         + v36 * v1->pFacePlane_old.vNormal.y) >> 16;
+                    if ( v38 >= 0 )
+                    {
+                      if ( v38 <= v35 && v35 )
+                      {
+                        v39 = v74;
+                        stru_F8AD28._blv_lights_radii[v74] = v35;
+                        stru_F8AD28._blv_lights_inv_radii[v39] = 65536 / (signed int)v68;
+                        *(int *)((char *)&stru_F8AD28.field_240 + v39 * 4) = X << 16;
+                        stru_F8AD28._blv_lights_xs[v39] = v32->vPosition.x;
+                        stru_F8AD28._blv_lights_ys[v39] = v32->vPosition.y;
+                        stru_F8AD28._blv_lights_zs[v39] = v32->vPosition.z;
+                        v68 = (BLVFaceExtra *)v32->uRed;
+                        stru_F8AD28._blv_lights_rs[v39] = (double)(signed int)v68 * v16;
+                        v68 = (BLVFaceExtra *)v32->uGreen;
+                        stru_F8AD28._blv_lights_gs[v39] = (double)(signed int)v68 * v16;
+                        v68 = (BLVFaceExtra *)v32->uBlue;
+                        stru_F8AD28._blv_lights_bs[v39] = (double)(signed int)v68 * v16;
+                        v16 = 0.0039215689;
+                        stru_F8AD28._blv_lights_light_dot_faces[v39] = abs(v38);
+                        v40 = v74++;
+                        stru_F8AD28._blv_lights_types[v40] = 1;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      v30 = v73++ + 1;
+      if ( v73 >= v70 )
+        break;
+      v17 = v69;
+    }
+  }
+  v73 = 0;
+  if ( pStationaryLightsStack->uNumLightsActive > 0 )
+  {
+    v41 = (char *)&pStationaryLightsStack->pLights[0].vPosition.y;
+    do
+    {
+      if ( v74 >= 20 )
+        break;
+      v42 = *((short *)v41 + 2);
+      v43 = *((short *)v41 - 1);
+      if ( v43 > v1->pBounding.x1 - v42 )
+      {
+        if ( v43 < v42 + v1->pBounding.x2 )
+        {
+          v44 = *(short *)v41;
+          if ( v44 > v1->pBounding.y1 - v42 )
+          {
+            if ( v44 < v42 + v1->pBounding.y2 )
+            {
+              v45 = *((short *)v41 + 1);
+              if ( v45 > v1->pBounding.z1 - v42 )
+              {
+                if ( v45 < v42 + v1->pBounding.z2 )
+                {
+                  v46 = (v1->pFacePlane_old.dist
+                       + *(short *)v41 * v1->pFacePlane_old.vNormal.y
+                       + v43 * v1->pFacePlane_old.vNormal.x
+                       + v45 * v1->pFacePlane_old.vNormal.z) >> 16;
+                  v69 = v46;
+                  if ( v46 >= 0 )
+                  {
+                    if ( v46 <= v42 )
+                    {
+                      v47 = v69;
+                      v48 = v74;
+                      stru_F8AD28._blv_lights_radii[v74] = v42;
+                      stru_F8AD28._blv_lights_inv_radii[v48] = 65536 / v42;
+                      stru_F8AD28._blv_lights_xs[v48] = *((short *)v41 - 1);
+                      stru_F8AD28._blv_lights_ys[v48] = *(short *)v41;
+                      stru_F8AD28._blv_lights_zs[v48] = *((short *)v41 + 1);
+                      v68 = (BLVFaceExtra *)(unsigned __int8)v41[6];
+                      v49 = (double)(signed int)v68 * v16;
+                      v68 = (BLVFaceExtra *)(unsigned __int8)v41[7];
+                      v50 = (unsigned __int8)v41[8];
+                      stru_F8AD28._blv_lights_rs[v48] = v49;
+                      v51 = (double)(signed int)v68;
+                      v68 = (BLVFaceExtra *)v50;
+                      stru_F8AD28._blv_lights_gs[v48] = v51 * v16;
+                      stru_F8AD28._blv_lights_bs[v48] = (double)(signed int)v68 * v16;
+                      v16 = 0.0039215689;
+                      stru_F8AD28._blv_lights_light_dot_faces[v48] = abs(v47);
+                      v52 = v74++;
+                      stru_F8AD28._blv_lights_types[v52] = 1;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      ++v73;
+      v41 += 12;
+    }
+    while ( v73 < pStationaryLightsStack->uNumLightsActive );
+  }
+  stru_F8AD28.uNumLightsApplied = v74;
+  v53 = v1->pBounding.x2;
+  if ( pBLVRenderParams->vPartyPos.x <= v53 )
+  {
+    v55 = v1->pBounding.x1;
+    if ( pBLVRenderParams->vPartyPos.x >= v55 )
+      v54 = 0;
+    else
+      v54 = v55 - pBLVRenderParams->vPartyPos.x;
+  }
+  else
+  {
+    v54 = pBLVRenderParams->vPartyPos.x - v53;
+  }
+  v56 = v1->pBounding.y2;
+  v57 = v54 * v54;
+  if ( pBLVRenderParams->vPartyPos.y <= v56 )
+  {
+    v59 = v1->pBounding.y1;
+    if ( pBLVRenderParams->vPartyPos.y >= v59 )
+      v58 = 0;
+    else
+      v58 = v59 - pBLVRenderParams->vPartyPos.y;
+  }
+  else
+  {
+    v58 = pBLVRenderParams->vPartyPos.y - v56;
+  }
+  v60 = v58 * v58 + v57;
+  v61 = v1->pBounding.z2;
+  if ( pBLVRenderParams->vPartyPos.z <= v61 )
+  {
+    v63 = v1->pBounding.z1;
+    if ( pBLVRenderParams->vPartyPos.z >= v63 )
+      v62 = 0;
+    else
+      v62 = v63 - pBLVRenderParams->vPartyPos.z;
+  }
+  else
+  {
+    v62 = pBLVRenderParams->vPartyPos.z - v61;
+  }
+  v64 = v62 * v62 + v60;
+  if ( v64 )
+    stru_F8AD28.field_34 = sub_452A9E(v64) << 16;
+  else
+    stru_F8AD28.field_34 = 0;
+  v68 = (BLVFaceExtra *)abs(stru_F8AD28.rotated_normal.y);
+  v65 = (double)(signed int)v68;
+  if ( v65 >= 655.36 )
+  {
+    if ( v65 >= 26214.4 )
+    {
+      if ( v65 >= 45875.2 )
+      {
+        stru_F8AD28.field_44 = 8;
+        stru_F8AD28.field_48 = 3;
+      }
+      else
+      {
+        stru_F8AD28.field_44 = 16;
+        stru_F8AD28.field_48 = 4;
+      }
+    }
+    else
+    {
+      stru_F8AD28.field_44 = 32;
+      stru_F8AD28.field_48 = 5;
+    }
+  }
+  else
+  {
+    stru_F8AD28.field_44 = 64;
+    stru_F8AD28.field_48 = 6;
+  }
+}
+// 519AB4: using guessed type int uNumStationaryLightsApplied;
+
+//----- (004AF412) --------------------------------------------------------
+int __cdecl sub_4AF412()
+{
+  int v0; // ST20_4@2
+  int v1; // ST20_4@2
+  int v2; // ST20_4@2
+  int v3; // esi@2
+  int v4; // ST20_4@2
+  int v5; // ecx@2
+  int v6; // ebx@2
+  int v7; // edi@2
+  int v8; // edx@2
+  int v9; // eax@2
+  int result; // eax@4
+
+  stru_F8AD28.plane_4.vNormal.z = -65536;
+  stru_F8AD28.vec_20.y = -65536;
+  stru_F8AD28.plane_4.vNormal.x = 0;
+  stru_F8AD28.plane_4.vNormal.y = 0;
+  stru_F8AD28.plane_4.dist = (pBLVRenderParams->vPartyPos.z + 800) << 16;
+  stru_F8AD28.vec_14.x = 65536;
+  stru_F8AD28.vec_14.y = 0;
+  stru_F8AD28.vec_14.z = 0;
+  stru_F8AD28.vec_20.x = 0;
+  stru_F8AD28.vec_20.z = 0;
+  stru_F8AD28.uDefaultAmbientLightLevel = 0;
+  if ( pBLVRenderParams->sPartyRotX )
+  {
+    v0 = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+       - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+    stru_F8AD28.rotated_normal.x = ((unsigned __int64)(v0 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
+                                 - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.z
+                                                     * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+    stru_F8AD28.rotated_normal.y = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
+                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                                 + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
+                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.rotated_normal.z = ((unsigned __int64)(v0 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+                                 + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.z
+                                                     * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    v1 = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+       - ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+    stru_F8AD28.vec_60.y = ((unsigned __int64)(v1 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
+                         - ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.field_6C = ((unsigned __int64)(v1 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    v2 = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+       - ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+    stru_F8AD28.vec_70.x = ((unsigned __int64)(v2 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
+                         - ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.vec_70.z = ((unsigned __int64)(v2 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    v3 = -(pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.y
+         + pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.x);
+    v4 = pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.y
+       - pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.x;
+    v5 = ((unsigned __int64)(v4 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
+       - ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+    v6 = pBLVRenderParams->vPartyPos.z;
+    v7 = ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
+       + ((unsigned __int64)(v4 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+    v8 = pBLVRenderParams->vPartyPos.y;
+    v9 = pBLVRenderParams->vPartyPos.x;
+  }
+  else
+  {
+    stru_F8AD28.rotated_normal.x = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
+                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                                 - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
+                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+    stru_F8AD28.rotated_normal.z = stru_F8AD28.plane_4.vNormal.z;
+    stru_F8AD28.rotated_normal.y = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
+                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                                 + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
+                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.vec_60.y = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                         - ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+    stru_F8AD28.field_6C = stru_F8AD28.vec_14.z;
+    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.vec_70.x = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                         - ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+    v8 = pBLVRenderParams->vPartyPos.y;
+    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.vec_70.z = stru_F8AD28.vec_20.z;
+    v9 = pBLVRenderParams->vPartyPos.x;
+    v5 = pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.y
+       - pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.x;
+    v6 = pBLVRenderParams->vPartyPos.z;
+    v3 = -(pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.y
+         + pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.x);
+    v7 = -65536 * pBLVRenderParams->vPartyPos.z;
+  }
+  stru_F8AD28.field_7C = stru_F8AD28.rotated_normal.x;
+  stru_F8AD28.vec_60.x = stru_F8AD28.plane_4.vNormal.y * v8
+                       + stru_F8AD28.plane_4.dist
+                       + stru_F8AD28.plane_4.vNormal.x * v9
+                       + stru_F8AD28.plane_4.vNormal.z * v6;
+  stru_F8AD28.vec_80.x = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44)
+                                          * (signed __int64)stru_F8AD28.rotated_normal.y) >> 16;
+  stru_F8AD28.vec_80.y = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44)
+                                          * (signed __int64)stru_F8AD28.rotated_normal.z) >> 16;
+  stru_F8AD28.vec_80.z = -stru_F8AD28.vec_60.x;
+  stru_F8AD28.vec_8C.x = stru_F8AD28.vec_60.y;
+  stru_F8AD28.vec_8C.y = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)stru_F8AD28.vec_60.z) >> 16;
+  stru_F8AD28.vec_8C.z = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)stru_F8AD28.field_6C) >> 16;
+  stru_F8AD28.vec_9C.x = stru_F8AD28.vec_70.x;
+  stru_F8AD28.field_98 = -(((unsigned __int64)(stru_F8AD28.vec_60.y * (signed __int64)v5) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_60.z * (signed __int64)v3) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.field_6C * (signed __int64)v7) >> 16));
+  stru_F8AD28.vec_9C.y = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)stru_F8AD28.vec_70.y) >> 16;
+  stru_F8AD28.vec_9C.z = (unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)stru_F8AD28.vec_70.z) >> 16;
+  result = 0;
+  stru_F8AD28.field_A8 = -(((unsigned __int64)(stru_F8AD28.vec_70.x * (signed __int64)v5) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_70.y * (signed __int64)v3) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_70.z * (signed __int64)v7) >> 16));
+  stru_F8AD28.field_38 = 0;
+  stru_F8AD28.field_3E4 = 0;
+  stru_F8AD28.uCurrentAmbientLightLevel = 0;
+  stru_F8AD28.uNumLightsApplied = 0;
+  stru_F8AD28.field_34 = 0;
+  return result;
+}
+
+
+
+
+
+
+//----- (004B1447) --------------------------------------------------------
+Player *__fastcall sub_4B1447_party_fine(int a1, int a2, int a3)
+{
+  signed int v3; // esi@1
+  char v4; // sf@8
+  int v5; // eax@8
+  unsigned __int64 v6; // qax@12
+  DDM_DLV_Header *v7; // eax@14
+  Player **v8; // edi@18
+  Player *result; // eax@19
+  char *v10; // esi@20
+
+  v3 = 0;
+  if ( a2 )
+  {
+    if ( a2 != 1 )
+    {
+      if ( a2 == 2 )
+        v3 = 2;
+      goto LABEL_13;
+    }
+    v3 = 2;
+  }
+  else
+  {
+    v3 = 1;
+  }
+  if ( pParty->uFine < 4000000 )
+  {
+    v4 = a3 + pParty->uFine < 0;
+    v5 = a3 + pParty->uFine;
+    pParty->uFine += a3;
+    if ( v4 )
+    {
+      v5 = 0;
+      pParty->uFine = 0;
+    }
+    if ( v5 > 4000000 )
+      pParty->uFine = 4000000;
+  }
+  v6 = pParty->uTimePlayed + 368640;
+  pParty->field_3C._shop_ban_times[2 * a1] = LODWORD(pParty->uTimePlayed) + 368640;
+  pParty->field_3C._shop_ban_times[2 * a1 + 1] = HIDWORD(v6);
+LABEL_13:
+  *(int *)&pParty->field_16154[4 * a1] = 1;
+  if ( v3 )
+  {
+    v7 = &pOutdoor->ddm;
+    if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+      v7 = &pIndoor->dlv;
+    v7->uReputation += v3;
+    if ( v7->uReputation > 10000 )
+      v7->uReputation = 10000;
+  }
+  v8 = &pPlayers[1];
+  do
+  {
+    result = *v8;
+    if ( pParty->uFine )
+    {
+      v10 = result->field_152;
+      result = (Player *)_449B57_test_bit((unsigned __int8 *)result->field_152, 1);
+      if ( !(short)result )
+        result = (Player *)_449B7E_toggle_bit((unsigned char *)v10, 1, 1u);
+    }
+    ++v8;
+  }
+  while ( (signed int)v8 <= (signed int)&pPlayers[4] );
+  return result;
+}
+
+//----- (004B1523) --------------------------------------------------------
+char *__thiscall sub_4B1523(int *_this)
+{
+  int v1; // esi@1
+  int v2; // edx@1
+  unsigned int v3; // eax@2
+  int v4; // eax@4
+  LONG v5; // ecx@4
+  int v6; // eax@10
+  char *v7; // ST44_4@12
+  unsigned __int16 v8; // ax@12
+  GUIWindow a1; // [sp+Ch] [bp-68h]@4
+  unsigned int v11; // [sp+60h] [bp-14h]@1
+  POINT a2; // [sp+64h] [bp-10h]@1
+  int v13; // [sp+6Ch] [bp-8h]@4
+  int v14; // [sp+70h] [bp-4h]@4
+
+  v1 = *_this - 399;
+  v2 = (*_this - 400) % 11 + 1;
+  v11 = 4 * (*_this - 400) / 11;
+  sprintf(pTmpBuf, "%s%03d", spellbook_texture_filename_suffices[v11 / 4], v2);
+  if ( pMouse->GetCursorPos(&a2)->y <= 320 )
+    v3 = pMouse->GetCursorPos(&a2)->y + 30;
+  else
+    v3 = 30;
+  a1.Hint = 0;
+  a1.uFrameY = v3;
+  a1.uFrameWidth = 328;
+  a1.uFrameHeight = 68;
+  a1.uFrameX = 90;
+  a1.uFrameZ = 417;
+  a1.uFrameW = v3 + 67;
+  a2.y = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[431]);
+  v14 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[433]);
+  v13 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[432]);
+  v4 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[96]);
+  v5 = a2.y;
+  if ( v14 > a2.y )
+    v5 = v14;
+  if ( v13 > v5 )
+    v5 = v13;
+  if ( v4 > v5 )
+    v5 = v4;
+  sprintf(
+    pTmpBuf2,
+    "%s\n\n%s\t%03d:\t%03d%s\t000\n%s\t%03d:\t%03d%s\t000\n%s\t%03d:\t%03d%s\t000\n%s\t%03d:\t%03d%s",
+    pSpellStats->pInfos[v1].pDescription,
+    pGlobalTXT_LocalizationStrings[431],        // "Normal"
+    v5 + 3,
+    v5 + 10,
+    pSpellStats->pInfos[v1].pBasicSkillDesc,
+    pGlobalTXT_LocalizationStrings[433],        // "Expert"
+    v5 + 3,
+    v5 + 10,
+    pSpellStats->pInfos[v1].pExpertSkillDesc,
+    pGlobalTXT_LocalizationStrings[432],        // "Master"
+    v5 + 3,
+    v5 + 10,
+    pSpellStats->pInfos[v1].pMasterSkillDesc,
+    pGlobalTXT_LocalizationStrings[96],         // "Grand"
+    v5 + 3,
+    v5 + 10,
+    pSpellStats->pInfos[v1].pGrandmasterSkillDesc);
+  v6 = pFontSmallnum->CalcTextHeight(pTmpBuf2, &a1, 0, 0);
+  a1.uFrameHeight += v6;
+  if ( (signed int)a1.uFrameHeight < 150 )
+    a1.uFrameHeight = 150;
+  a1.uFrameWidth = 460;
+  a1.DrawMessageBox(0);
+  a1.uFrameWidth -= 12;
+  a1.uFrameHeight -= 12;
+  v7 = pSpellStats->pInfos[v1].pName;
+  a1.uFrameZ = a1.uFrameX + a1.uFrameWidth - 1;
+  a1.uFrameW = a1.uFrameHeight + a1.uFrameY - 1;
+  v8 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  a1.DrawTitleText(pFontArrus, 0x78u, 0xCu, v8, v7, 3u);
+  a1.DrawText(pFontSmallnum, 120, 44, 0, pTmpBuf2, 0, 0, 0);
+  a1.uFrameZ = a1.uFrameX + 107;
+  a1.uFrameWidth = 108;
+  a1.DrawTitleText(pFontComic, 0xCu, 0x4Bu, 0, pSkillNames[v11 / 4 + 12], 3u);
+  sprintf(pTmpBuf, "%s\n%d", pGlobalTXT_LocalizationStrings[522], *(&pSpellDatas[0].uNormalLevelMana + 10 * v1));
+  return a1.DrawTitleText(
+           pFontComic,
+           0xCu,
+           a1.uFrameHeight - LOBYTE(pFontComic->uFontHeight) - 16,
+           0,
+           pTmpBuf,
+           3u);
+}
+
+
+//----- (004B1784) --------------------------------------------------------
+bool __cdecl sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win()
+{
+  Player *pPlayer; // ebx@1
+  bool result; // eax@2
+  unsigned __int16 v2; // ST0C_2@3
+  int v3; // eax@3
+  GUIWindow v4; // [sp+4h] [bp-54h]@3
+
+  pPlayer = pPlayers[uActiveCharacter];
+  if ( pPlayer->CanAct() )
+  {
+    pDialogueWindow->pNumPresenceButton = dword_F8B1E0;
+    result = 1;
+  }
+  else
+  {
+    pDialogueWindow->pNumPresenceButton = 0;
+    memcpy(&v4, pPrimaryWindow, sizeof(v4));
+    v4.uFrameX = 483;
+    v4.uFrameWidth = 148;
+    v4.uFrameZ = 334;
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[427], pPlayer->pName, pGlobalTXT_LocalizationStrings[562]);// 
+                                                // "%s is in no condition to %s"
+                                                // "do anything"
+    v2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+    v3 = pFontArrus->CalcTextHeight(pTmpBuf, &v4, 0, 0);
+    v4.DrawTitleText(pFontArrus, 0, (212 - v3) / 2 + 101, v2, pTmpBuf, 3u);
+    result = 0;
+  }
+  return result;
+}
+// F8B1E0: using guessed type int dword_F8B1E0;
+
+
+
+//----- (004B1A2D) --------------------------------------------------------
+void __cdecl sub_4B1A2D()
+{
+  Player *v0; // edi@1
+  POINT *v1; // esi@5
+  unsigned int v2; // eax@5
+  int v3; // ecx@5
+  POINT *v4; // esi@12
+  int v5; // eax@12
+  unsigned int v6; // eax@13
+  ItemGen *v7; // ecx@13
+  signed int v8; // esi@17
+  unsigned int v9; // eax@19
+  char v10; // [sp+8h] [bp-44h]@12
+  char v11; // [sp+10h] [bp-3Ch]@12
+  char v12; // [sp+18h] [bp-34h]@18
+  char v13; // [sp+20h] [bp-2Ch]@17
+  char v14; // [sp+28h] [bp-24h]@17
+  char v15; // [sp+30h] [bp-1Ch]@17
+  char v16; // [sp+38h] [bp-14h]@5
+  POINT a2; // [sp+40h] [bp-Ch]@5
+  int v18; // [sp+48h] [bp-4h]@5
+
+  v0 = pPlayers[uActiveCharacter];
+  if ( dword_F8B198 <= 0 )
+    return;
+  if ( dword_F8B198 <= 4 )
+  {
+    if ( dword_F8B19C != 2 )
+    {
+      if ( dword_F8B19C <= 2 )
+        return;
+      if ( dword_F8B19C <= 5 || dword_F8B19C == 94 )
+      {
+        v8 = pMouse->GetCursorPos((POINT *)&v15)->x - 14;
+        v18 = (v8 >> 5) + 14 * ((pMouse->GetCursorPos((POINT *)&v14)->y - 17) >> 5);
+        if ( pMouse->GetCursorPos((POINT *)&v13)->x <= 13
+          || pMouse->GetCursorPos((POINT *)&v12)->x >= 462
+          || (v9 = v0->GetItemIDAtInventoryIndex(&v18)) == 0 )
+          return;
+        v7 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v9 + 5];
+LABEL_15:
+        GameUI_DrawItemInfo(v7);
+        return;
+      }
+      if ( dword_F8B19C != 95 )
+        return;
+    }
+    v4 = pMouse->GetCursorPos((POINT *)&v11);
+    v5 = pRenderer->pActiveZBuffer[v4->x + pSRZBufferLineOffsets[pMouse->GetCursorPos((POINT *)&v10)->y]] & 0xFFFF;
+    v18 = v5;
+    if ( !v5 )
+      return;
+    v6 = 9 * (v5 + 12 * (unsigned int)ptr_507BC0->ptr_1C);
+    v7 = (ItemGen *)((char *)&pParty->pPickedItem + 4 * v6 + 4);
+    if ( dword_F8B19C != 2 )
+      v7 = (ItemGen *)&pParty->field_C59C[v6 + 715];
+    goto LABEL_15;
+  }
+  if ( dword_F8B198 <= 16 && dword_F8B19C == 18 )
+  {
+    v1 = pMouse->GetCursorPos(&a2);
+    v2 = v1->x + pSRZBufferLineOffsets[pMouse->GetCursorPos((POINT *)&v16)->y];
+    v3 = pRenderer->pActiveZBuffer[v2] & 0xFFFF;
+    v18 = pRenderer->pActiveZBuffer[v2] & 0xFFFF;
+    if ( v18 )
+      sub_4B1523((int *)&pParty->pPlayers[1].uExpressionTimeLength + 9 * (v3 + 12 * (unsigned int)ptr_507BC0->ptr_1C));
+  }
+}
+// F8B198: using guessed type int dword_F8B198;
+// F8B19C: using guessed type int dword_F8B19C;
+
+//----- (004B1BDB) --------------------------------------------------------
+void __stdcall RestAndHeal(__int64 uNumMinutes)
+{
+  signed __int64 v1; // ST2C_8@1
+  signed __int64 v2; // qax@1
+  signed __int64 v3; // ST1C_8@1
+  unsigned __int64 v4; // qax@1
+  unsigned int v5; // ebx@1
+  void *v6; // ebx@1
+
+  pParty->pHirelings[0].bHasUsedTheAbility = 0;
+  pParty->pHirelings[1].bHasUsedTheAbility = 0;
+  pParty->uTimePlayed += (signed __int64)((double)(7680 * uNumMinutes) * 0.033333335);
+  v1 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375);
+  v2 = v1 / 60 / 60;
+  v3 = v2;
+  v4 = (unsigned int)v2 / 0x18;
+  v5 = (unsigned int)(v4 / 7) >> 2;
+  pParty->uCurrentTimeSecond = v1 % 60;
+  pParty->uCurrentMinute = v1 / 60 % 60;
+  pParty->uCurrentHour = v3 % 24;
+  pParty->uCurrentMonthWeek = v4 / 7 & 3;
+  pParty->uDaysPlayed = (unsigned int)v4 % 0x1C;
+  pParty->uCurrentMonth = v5 % 0xC;
+  pParty->uCurrentYear = v5 / 0xC + 1168;
+  pParty->RestAndHeal();
+  dword_507B94 = 1;
+  v6 = &pParty->pPlayers[0].uNumDivineInterventionCastsThisDay;
+  do
+  {
+    *((short *)v6 - 258) = 0;
+    memset(v6, 0, 4u);
+    v6 = (char *)v6 + 6972;
+  }
+  while ( (signed int)v6 < (signed int)&pParty->field_871C[694] );
+  pParty->_4909F4();
+}
+// 507B94: using guessed type int dword_507B94;
+
+//----- (004B1D27) --------------------------------------------------------
+void __cdecl sub_4B1D27()
+{
+  int v0; // edx@2
+  unsigned int v1; // ecx@7
+  signed int v2; // edi@10
+  int v3; // esi@10
+  __int16 v4; // ax@15
+  signed int v5; // edi@20
+  int v6; // esi@20
+  int v7[4]; // [sp+Ch] [bp-10h]@12
+
+  if ( dword_F8B198 > 0 )
+  {
+    v0 = 3;
+    if ( dword_F8B198 > 3 )
+    {
+      if ( dword_F8B198 == 22 )
+      {
+        if ( !dword_F8B1E4 )
+          return;
+      }
+      else
+      {
+        if ( dword_F8B198 != 23 )
+          return;
+      }
+      v1 = (unsigned int)ptr_507BC0->ptr_1C;
+LABEL_28:
+      HousePlaySomeSound(v1, v0);
+      return;
+    }
+    v1 = (unsigned int)ptr_507BC0->ptr_1C;
+    if ( (signed __int64)__PAIR__(pParty->field_3C._shop_ban_times[2 * v1 + 1], pParty->field_3C._shop_ban_times[2 * v1]) <= (signed __int64)pParty->uTimePlayed )
+    {
+      if ( pParty->uNumGold <= 0x2710 )
+      {
+        if ( !dword_F8B1E4 )
+          return;
+        v0 = 4;
+        goto LABEL_28;
+      }
+      HousePlaySomeSound(v1, dword_F8B1E4 + 3);
+      if ( !dword_F8B1E4 && !qword_A750D8 )
+      {
+        v5 = 0;
+        v6 = 1;
+        do
+        {
+          if ( pPlayers[v6]->CanAct() )
+            v7[v5++] = v6;
+          ++v6;
+        }
+        while ( v6 <= 4 );
+        if ( v5 )
+        {
+          qword_A750D8 = 256i64;
+          word_A750E0 = 80;
+          v4 = LOWORD(v7[rand() % v5]);
+          goto LABEL_16;
+        }
+      }
+    }
+    else
+    {
+      if ( !qword_A750D8 )
+      {
+        v2 = 0;
+        v3 = 1;
+        do
+        {
+          if ( pPlayers[v3]->CanAct() )
+            v7[v2++] = v3;
+          ++v3;
+        }
+        while ( v3 <= 4 );
+        if ( v2 )
+        {
+          qword_A750D8 = 256i64;
+          word_A750E0 = 80;
+          v4 = LOWORD(v7[rand() % v2]);
+LABEL_16:
+          word_A750E2 = v4;
+          return;
+        }
+      }
+    }
+  }
+}
+
+//----- (004B1E92) --------------------------------------------------------
+void __fastcall HousePlaySomeSound(unsigned int uHouseID, int a2)
+{
+  //if ( BYTE1(pAnimatedRooms[p2DEvents_minus1___02[26 * uHouseID]].field_C) )
+  if ( BYTE1(pAnimatedRooms[p2DEvents[uHouseID - 1].uAnimationID].field_C) )
+    pAudioPlayer->PlaySound(
+      //(SoundID)(a2 + 100 * (BYTE1(pAnimatedRooms[p2DEvents_minus1___02[26 * uHouseID]].field_C) + 300)),
+      (SoundID)(a2 + 100 * (BYTE1(pAnimatedRooms[p2DEvents[uHouseID - 1].uAnimationID].field_C) + 300)),
+      806,
+      0,
+      -1,
+      0,
+      0,
+      0,
+      0);
+}
+
+//----- (004B1ECE) --------------------------------------------------------
+void __cdecl sub_4B1ECE()
+{
+  __int16 *v0; // edi@1
+  int v1; // ebx@3
+  Player *v2; // esi@3
+  int v3; // eax@4
+  signed int v4; // eax@9
+  int v5; // ebx@11
+  char *v6; // esi@13
+  char *v7; // eax@14
+  signed int v8; // edi@14
+  int v9; // [sp+Ch] [bp-Ch]@11
+  signed int v10; // [sp+10h] [bp-8h]@13
+  int v11; // [sp+14h] [bp-4h]@1
+  char *v12; // [sp+14h] [bp-4h]@11
+
+  dword_F8B1A8 = 0;
+  v11 = 0;
+  uDialogueType = 84;
+  ptr_F8B1E8 = (char *)pNPCTopics[667].pText;
+  v0 = _4F0882_evt_VAR_PlayerItemInHands_vals;
+  while ( 1 )
+  {
+    if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, *(v0 - 1)) )
+    {
+      v1 = 0;
+      v2 = pParty->pPlayers;
+      do
+      {
+        LOBYTE(v3) = v2->CompareVariable(VAR_PlayerItemInHands, *v0);
+        if ( v3 )
+          break;
+        ++v2;
+        ++v1;
+      }
+      while ( (signed int)v2 < (signed int)pParty->pHirelings );
+      if ( v1 == 4 )
+        break;
+    }
+    ++v11;
+    v0 += 2;
+    if ( (signed int)v0 >= (signed int)((char *)dword_4F08EC + 2) )
+      goto LABEL_10;
+  }
+  ptr_F8B1E8 = (char *)pNPCTopics[666].pText;
+  v4 = _4F0882_evt_VAR_PlayerItemInHands_vals[2 * v11];
+  dword_F8B1A8 = _4F0882_evt_VAR_PlayerItemInHands_vals[2 * v11];
+  pParty->pPlayers[0].AddVariable(VAR_PlayerItemInHands, v4);
+LABEL_10:
+  if ( dword_F8B1A8 == 601 )
+  {
+    v5 = 0;
+    v12 = (char *)&pParty->pPlayers[0].uClass;
+    v9 = 0;
+    while ( 1 )
+    {
+      if ( *v12 == 35 )
+      {
+        v10 = 0;
+        v6 = &pParty->pPlayers[0].pInventoryItems[0].field_1A;
+        do
+        {
+          v7 = v6;
+          v8 = 138;
+          do
+          {
+            if ( *(int *)(v7 - 26) == 601 )
+            {
+              if ( !*v7 )
+                v9 = (int)(v7 - 26);
+              if ( (unsigned __int8)*v7 == v5 )
+                v10 = 1;
+            }
+            v7 += 36;
+            --v8;
+          }
+          while ( v8 );
+          v6 += 6972;
+        }
+        while ( (signed int)v6 < (signed int)((char *)&pParty->field_777C[91] + 2) );
+        if ( !v10 )
+          break;
+      }
+      v12 += 6972;
+      ++v5;
+      if ( (signed int)v12 >= (signed int)((char *)&pParty->pPickedItem.uExpireTime + 5) )
+        return;
+    }
+    if ( v9 )
+      *(char *)(v9 + 26) = v5;
+  }
+}
+// 4F08EC: using guessed type int dword_4F08EC[];
+// 722B3C: using guessed type int dword_722B3C;
+// 722B44: using guessed type int dword_722B44;
+// F8B1A8: using guessed type int dword_F8B1A8;
+
+//----- (004B2001) --------------------------------------------------------
+void __fastcall sub_4B2001(signed int a1)
+{
+  signed int v1; // eax@1
+  NPCData *v2; // ebp@1
+  int v3; // ecx@8
+  Player *v4; // esi@20
+  int v5; // eax@28
+  int v6; // eax@31
+  int v7; // eax@34
+  int v8; // eax@37
+  int v9; // eax@40
+  unsigned int v10; // eax@43
+  unsigned int v11; // eax@48
+  char *v12; // eax@53
+  char *v13; // eax@56
+  char *v14; // eax@57
+  char *v15; // eax@58
+  unsigned int v16; // ebp@62
+  char *v17; // ecx@63
+  char *v18; // eax@65
+  const char *v19; // ecx@68
+  unsigned int v20; // eax@69
+  unsigned int v21; // ecx@70
+  char *v22; // [sp-Ch] [bp-18h]@73
+  int v23; // [sp-8h] [bp-14h]@49
+  char *v24; // [sp-8h] [bp-14h]@73
+  int v25; // [sp-4h] [bp-10h]@49
+
+  v1 = a1;
+  uDialogueType = a1 + 1;
+  v2 = array_5913D8[(unsigned int)((char *)array_5913D8[6] + -(dword_591080 != 0) - 1)];
+  if ( a1 <= 23 )
+  {
+    if ( a1 == 23 )
+    {
+      v3 = v2->evte;
+    }
+    else
+    {
+      if ( a1 == 13 )
+      {
+        ptr_F8B1E8 = (char *)*(&pNPCStats->field_13A64 + 5 * v2->uProfession);
+        ptr_F8B1E8 = sub_495461((char *)ptr_F8B1E8, uActiveCharacter - 1, 0, 0, 0, 0);
+        sub_4B40E6();
+        byte_F8B1EC = 0;
+        goto _return;
+      }
+      switch ( a1 )
+      {
+        case 19:
+          v3 = v2->bDrawSomeAnim;
+          break;
+        case 20:
+          v3 = v2->evtb;
+          break;
+        case 21:
+          v3 = v2->evtc;
+          break;
+        default:
+          if ( a1 != 22 )
+            goto _return;
+          v3 = v2->evtd;
+          break;
+      }
+    }
+    goto LABEL_84;
+  }
+  if ( a1 == 24 )
+  {
+    v3 = v2->evtf;
+LABEL_84:
+    if ( v3 < 200 || v3 > 310 )
+    {
+      if ( v3 < 400 || v3 > 410 )
+      {
+        if ( v3 == 139 )
+        {
+          sub_4B1ECE();
+        }
+        else
+        {
+          if ( v3 == 311 )
+          {
+            sub_4BBA85_bounties();
+          }
+          else
+          {
+            ptr_F8B1E8 = 0;
+            _5C3420_pDecoration = (LevelDecoration *)1;
+            EventProcessor(v3, 0, 1);
+            _5C3420_pDecoration = 0;
+          }
+        }
+      }
+      else
+      {
+        dword_F8B1D8 = v1;
+        sub_4B3EF0(v3 - 400);
+      }
+    }
+    else
+    {
+      sub_4B3FE5(v3);
+    }
+    goto _return;
+  }
+  if ( a1 != 76 )
+  {
+    if ( a1 == 77 )
+    {
+      v16 = v2->uProfession;
+      if ( byte_F8B1EC )
+        v17 = (char *)*(&pNPCStats->field_13A64 + 5 * v16);
+      else
+        v17 = (char *)*(&pNPCStats->field_13A5C + 5 * v16);
+      ptr_F8B1E8 = v17;
+      v18 = sub_495461(v17, uActiveCharacter - 1, 0, 0, 0, 0);
+      byte_F8B1EC ^= 1u;
+      ptr_F8B1E8 = v18;
+    }
+    else
+    {
+      if ( a1 == 79 )
+      {
+        if ( dword_F8B1A8 )
+        {
+          Party::TakeGold(dword_F8B1B4);
+          if ( uActiveCharacter )
+          {
+            v12 = (char *)&pPlayers[uActiveCharacter]->pActiveSkills[dword_F8B1AC_something_todo_with_awards];
+            *(short *)v12 &= 0x3Fu;
+            switch ( dword_F8B1B0 )
+            {
+              case 2:
+                v15 = (char *)&pPlayers[uActiveCharacter]->pActiveSkills[dword_F8B1AC_something_todo_with_awards];
+                *v15 |= 0x40u;
+                break;
+              case 3:
+                v14 = (char *)&pPlayers[uActiveCharacter]->pActiveSkills[dword_F8B1AC_something_todo_with_awards];
+                *v14 |= 0x80u;
+                break;
+              case 4:
+                v13 = (char *)&pPlayers[uActiveCharacter]->pActiveSkills[dword_F8B1AC_something_todo_with_awards];
+                v13[1] |= 1u;
+                break;
+            }
+            pPlayers[uActiveCharacter]->PlaySound(85, 0);
+          }
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+          {
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+            *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+        }
+      }
+      else
+      {
+        if ( a1 == 82 && dword_F8B1A8 )
+        {
+          Party::TakeGold(dword_F8B1B4);
+          v4 = pParty->pPlayers;
+          do
+          {
+            v4->SetVariable(VAR_Award, dword_F8B1AC_something_todo_with_awards);
+            ++v4;
+          }
+          while ( (signed int)v4 < (signed int)pParty->pHirelings );
+          switch ( dword_F8B1D8 )
+          {
+            case 19:
+              v10 = v2->bDrawSomeAnim;
+              if ( (signed int)v10 >= 400 && (signed int)v10 <= 416 )
+                v2->bDrawSomeAnim = 0;
+              break;
+            case 20:
+              v9 = v2->evtb;
+              if ( v9 >= 400 && v9 <= 416 )
+                v2->evtb = 0;
+              break;
+            case 21:
+              v8 = v2->evtc;
+              if ( v8 >= 400 && v8 <= 416 )
+                v2->evtc = 0;
+              break;
+            case 22:
+              v7 = v2->evtd;
+              if ( v7 >= 400 && v7 <= 416 )
+                v2->evtd = 0;
+              break;
+            case 23:
+              v6 = v2->evte;
+              if ( v6 >= 400 && v6 <= 416 )
+                v2->evte = 0;
+              break;
+            case 24:
+              v5 = v2->evtf;
+              if ( v5 >= 400 )
+              {
+                if ( v5 <= 416 )
+                  v2->evtf = 0;
+              }
+              break;
+          }
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+          {
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+            *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+          v11 = uActiveCharacter;
+          if ( uActiveCharacter )
+          {
+            v25 = 0;
+            v23 = 86;
+LABEL_50:
+            pPlayers[v11]->PlaySound(v23, v25);
+            goto _return;
+          }
+        }
+      }
+    }
+    goto _return;
+  }
+  if ( pParty->pHirelings[0].pName && pParty->pHirelings[1].pName )
+  {
+    v19 = pGlobalTXT_LocalizationStrings[533];  // ""I cannot join you, you're party is full""
+LABEL_77:
+    ShowStatusBarString(v19, 2u);
+    goto _return;
+  }
+  v20 = v2->uProfession;
+  if ( v20 != 51 )
+  {
+    v21 = *(&pNPCStats->field_13A58 + 5 * v20);
+    if ( pParty->uNumGold < v21 )
+    {
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
+      byte_F8B1EC = 0;
+      uDialogueType = 13;
+      ptr_F8B1E8 = (char *)*(&pNPCStats->field_13A64 + 5 * v2->uProfession);
+      ptr_F8B1E8 = sub_495461((char *)ptr_F8B1E8, uActiveCharacter - 1, 0, 0, 0, 0);
+      if ( uActiveCharacter )
+        pPlayers[uActiveCharacter]->PlaySound(38, 0);
+      v19 = pGlobalTXT_LocalizationStrings[155];
+      goto LABEL_77;
+    }
+    Party::TakeGold(v21);
+  }
+  LOBYTE(v2->uFlags) |= 0x80u;
+  pParty->field_709 = 0;
+  sub_44A56A();
+  if ( pParty->pHirelings[0].pName )
+  {
+    memcpy(&pParty->pHirelings[1], v2, sizeof(pParty->pHirelings[1]));
+    v24 = v2->pName;
+    v22 = pParty->pHireling2Name;
+  }
+  else
+  {
+    memcpy(pParty->pHirelings, v2, 0x4Cu);
+    v24 = v2->pName;
+    v22 = pParty->pHireling1Name;
+  }
+  strcpy(v22, v24);
+  pParty->field_709 = 0;
+  sub_44A56A();
+  PrepareHouse((unsigned int)ptr_507BC0->ptr_1C);
+  dword_F8B19C = 1;
+  if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+  {
+    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+    *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+    ++pMessageQueue_50CBD0->uNumMessages;
+  }
+  v11 = uActiveCharacter;
+  if ( uActiveCharacter )
+  {
+    v25 = 0;
+    v23 = 61;
+    goto LABEL_50;
+  }
+_return:
+  pVideoPlayer->_4BF5B2();
+}
+
+
+//----- (004B254D) --------------------------------------------------------
+char *__thiscall _4B254D_SkillMasteryTeacher(int _this)
+{
+  Player *v1; // esi@1
+  int v2; // edx@1
+  int v3; // ecx@1
+  int v4; // edi@1
+  int v5; // eax@7
+  int v6; // eax@7
+  int v7; // ebx@7
+  int v8; // ebx@8
+  signed int v9; // esi@8
+  int v10; // eax@8
+  char *v11; // ecx@8
+  int v12; // edi@9
+  char *v13; // edx@9
+  signed int v14; // edi@10
+  unsigned int v16; // eax@29
+  int v17; // eax@36
+  char v18; // cl@46
+  __int16 v19; // dx@56
+  int v20; // eax@60
+  char *v21; // [sp-Ch] [bp-38h]@82
+  const char *v22; // [sp-8h] [bp-34h]@21
+  unsigned int v23; // [sp-8h] [bp-34h]@38
+  char *v24; // [sp-8h] [bp-34h]@82
+  char *v25; // [sp-4h] [bp-30h]@14
+  int v26; // [sp-4h] [bp-30h]@38
+  int v27; // [sp-4h] [bp-30h]@82
+  char v28[4]; // [sp+Ch] [bp-20h]@9
+  int v29; // [sp+10h] [bp-1Ch]@13
+  int v30; // [sp+14h] [bp-18h]@15
+  int v31; // [sp+18h] [bp-14h]@16
+  unsigned __int16 a1[2]; // [sp+1Ch] [bp-10h]@7
+  int v33; // [sp+20h] [bp-Ch]@7
+  int v34; // [sp+24h] [bp-8h]@7
+  char *v35; // [sp+28h] [bp-4h]@1
+
+  v1 = pPlayers[uActiveCharacter];
+  dword_F8B1A8 = 0;
+  v2 = (_this - 200) % 3;
+  v3 = (_this - 200) / 3;
+  v4 = v2;
+  v35 = (char *)pNPCTopics[127].pText;
+  dword_F8B1AC_something_todo_with_awards = v3;
+  if ( v2 )
+  {
+    if ( v2 == 1 )
+    {
+      dword_F8B1B4 = 5000;
+      dword_F8B1B0 = 3;
+    }
+    else
+    {
+      if ( v2 == 2 )
+      {
+        dword_F8B1B4 = 8000;
+        dword_F8B1B0 = 4;
+      }
+    }
+  }
+  else
+  {
+    dword_F8B1B4 = 2000;
+    dword_F8B1B0 = 2;
+  }
+  v5 = v1->uClass;
+  v33 = v5;
+  v6 = byte_4ED970_skill_learn_ability_by_class_table[v5][v3];
+  *(int *)a1 = v1->pActiveSkills[v3];
+  v7 = a1[0] & 0x3F;
+  v34 = v2 + 2;
+  if ( v6 < v2 + 2 )
+  {
+    v8 = v33;
+    v9 = 0;
+    v10 = v33 - v33 % 4;
+    v11 = &byte_4ED970_skill_learn_ability_by_class_table[v33 - v33 % 4][v3];
+    do
+    {
+      v12 = (unsigned __int8)*v11;
+      v13 = &v28[4 * v9];
+      *(int *)v13 = 0;
+      if ( v12 < v34 )
+      {
+        v14 = 1;
+      }
+      else
+      {
+        v14 = 1;
+        *(int *)v13 = 1;
+      }
+      ++v9;
+      v11 += 37;
+    }
+    while ( v9 < 4 );
+    if ( v29 == v14 )
+    {
+      v25 = pClassNames[v10 + 1];
+    }
+    else
+    {
+      if ( v30 == v14 )
+      {
+        if ( v31 == v14 )
+        {
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[634], pClassNames[v10 + 2], pClassNames[v10 + 3]);
+          return pTmpBuf;
+        }
+        v25 = pClassNames[v10 + 2];
+      }
+      else
+      {
+        if ( v31 != v14 )
+        {
+          v25 = pClassNames[v8];
+          v22 = pGlobalTXT_LocalizationStrings[632];
+          goto LABEL_23;
+        }
+        v25 = pClassNames[v10 + 3];
+      }
+    }
+    v22 = pGlobalTXT_LocalizationStrings[633];
+LABEL_23:
+    sprintf(pTmpBuf, v22, v25);
+    return pTmpBuf;
+  }
+  if ( !v1->CanAct() )
+    return (char *)pNPCTopics[122].pText;
+  if ( !v7 )
+    return (char *)pNPCTopics[131].pText;
+  v16 = SkillToMastery(a1[0]);
+  if ( (signed int)v16 > v4 + 1 )
+    return (char *)pNPCTopics[v4 + 128].pText;
+  if ( v34 != 2 )
+  {
+    if ( v34 == 3 )
+    {
+      if ( (signed int)v16 >= 2 && v7 >= 7 )
+      {
+        v17 = dword_F8B1AC_something_todo_with_awards;
+        switch ( dword_F8B1AC_something_todo_with_awards )
+        {
+          default:
+            goto LABEL_41;
+          case 12:
+          case 13:
+          case 14:
+          case 15:
+          case 16:
+          case 17:
+          case 18:
+            dword_F8B1B4 = 4000;
+            goto LABEL_42;
+          case 19:
+            v19 = 114;
+            goto LABEL_57;
+          case 20:
+            v19 = 110;
+LABEL_57:
+            if ( !(unsigned __int16)_449B57_test_bit(pParty->_award_bits, v19) )
+              return v35;
+            goto LABEL_40;
+          case 22:
+            v20 = v1->GetBaseWillpower();
+            goto LABEL_61;
+          case 24:
+            dword_F8B1B4 = 2500;
+            v20 = v1->GetBaseEndurance();
+            goto LABEL_61;
+          case 36:
+            v20 = v1->GetBaseIntelligence();
+LABEL_61:
+            if ( v20 < 50 )
+              return v35;
+            goto LABEL_40;
+          case 21:
+          case 23:
+          case 25:
+          case 26:
+          case 29:
+          case 32:
+          case 34:
+          case 35:
+            dword_F8B1B4 = 2500;
+            goto LABEL_42;
+          case 8:
+          case 9:
+          case 10:
+          case 11:
+            dword_F8B1B4 = 3000;
+            goto LABEL_42;
+          case 7:
+            goto LABEL_67;
+        }
+        goto LABEL_67;
+      }
+    }
+    else
+    {
+      if ( v34 != 4 )
+      {
+LABEL_40:
+        v17 = dword_F8B1AC_something_todo_with_awards;
+        goto LABEL_41;
+      }
+      if ( (signed int)v16 >= 3 && v7 >= 10 )
+      {
+        v17 = dword_F8B1AC_something_todo_with_awards;
+        switch ( dword_F8B1AC_something_todo_with_awards )
+        {
+          case 19:
+            if ( v1->_49327B(0x22u, 1) == 1 )
+              goto LABEL_40;
+            v26 = 1;
+            v23 = 26;
+            goto LABEL_39;
+          default:
+            goto LABEL_41;
+          case 20:
+            if ( v1->_49327B(0x23u, 1) == 1 )
+              goto LABEL_40;
+            v26 = 1;
+            v23 = 27;
+LABEL_39:
+            if ( v1->_49327B(v23, v26) == 1 )
+              goto LABEL_40;
+            return v35;
+          case 30:
+            v18 = LOBYTE(v1->pActiveSkills[31]);
+            goto LABEL_47;
+          case 31:
+            v18 = LOBYTE(v1->pActiveSkills[30]);
+LABEL_47:
+            if ( (v18 & 0x3Fu) < 0xA )
+              return v35;
+            goto LABEL_41;
+          case 21:
+          case 23:
+          case 24:
+          case 25:
+          case 26:
+          case 29:
+          case 32:
+          case 34:
+          case 35:
+            dword_F8B1B4 = 6000;
+            goto LABEL_42;
+          case 8:
+          case 9:
+          case 10:
+          case 11:
+            dword_F8B1B4 = 7000;
+            goto LABEL_42;
+          case 7:
+            break;
+        }
+LABEL_67:
+        dword_F8B1B4 = 0;
+        goto LABEL_41;
+      }
+    }
+    return v35;
+  }
+  if ( v7 < 4 )
+    return v35;
+  v17 = dword_F8B1AC_something_todo_with_awards;
+  if ( dword_F8B1AC_something_todo_with_awards > 27 )
+  {
+    if ( dword_F8B1AC_something_todo_with_awards != 29
+      && dword_F8B1AC_something_todo_with_awards != 32
+      && (dword_F8B1AC_something_todo_with_awards <= 33 || dword_F8B1AC_something_todo_with_awards > 35) )
+    {
+LABEL_41:
+      if ( !dword_F8B1B4 )
+        goto LABEL_79;
+      goto LABEL_42;
+    }
+LABEL_87:
+    dword_F8B1B4 = 500;
+    goto LABEL_41;
+  }
+  if ( dword_F8B1AC_something_todo_with_awards >= 23 )
+    goto LABEL_87;
+  if ( dword_F8B1AC_something_todo_with_awards == 7 )
+  {
+    dword_F8B1B4 = 0;
+    goto LABEL_79;
+  }
+  if ( dword_F8B1AC_something_todo_with_awards <= 7 )
+    goto LABEL_41;
+  if ( dword_F8B1AC_something_todo_with_awards > 18 )
+  {
+    if ( dword_F8B1AC_something_todo_with_awards != 21 )
+      goto LABEL_41;
+    goto LABEL_87;
+  }
+  dword_F8B1B4 = 1000;
+LABEL_42:
+  if ( dword_F8B1B4 > pParty->uNumGold )
+    return (char *)pNPCTopics[124].pText;
+LABEL_79:
+  dword_F8B1A8 = 1;
+  if ( v34 == 2 )
+  {
+    v27 = dword_F8B1B4;
+    v24 = pSkillNames[v17];
+    v21 = pGlobalTXT_LocalizationStrings[433];
+    goto LABEL_90;
+  }
+  if ( v34 == 3 )
+  {
+    v27 = dword_F8B1B4;
+    v24 = pSkillNames[v17];
+    v21 = pGlobalTXT_LocalizationStrings[432];
+    goto LABEL_90;
+  }
+  if ( v34 == 4 )
+  {
+    v27 = dword_F8B1B4;
+    v24 = pSkillNames[v17];
+    v21 = pGlobalTXT_LocalizationStrings[225];
+LABEL_90:
+    sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[534], v21, v24, v27);
+  }
+  return pTmpBuf2;
+}
+
+
+
+//----- (004B29F2) --------------------------------------------------------
+const char *__fastcall sub_4B29F2(int a1)
+{
+  int v1; // esi@1
+  Player *v2; // edi@1
+  int v3; // eax@1
+  Player *v4; // ecx@1
+
+  v1 = a1;
+  dword_F8B1A8 = 0;
+  v2 = pPlayers[uActiveCharacter];
+  v3 = a1 + 50;
+  v4 = pPlayers[uActiveCharacter];
+  dword_F8B1AC_something_todo_with_awards = v3;
+  dword_F8B1B4 = dword_4F08EC[v1];
+  if ( v4->CanAct() )
+  {
+    if ( (unsigned __int16)_449B57_test_bit((unsigned __int8 *)v2->field_152, dword_F8B1AC_something_todo_with_awards) )
+    {
+      return pNPCTopics[123].pText;
+    }
+    else
+    {
+      if ( dword_F8B1B4 <= pParty->uNumGold )
+      {
+        dword_F8B1A8 = 1;
+        return pNPCTopics[v1 + 110].pText;
+      }
+      else
+      {
+        return pNPCTopics[124].pText;
+      }
+    }
+  }
+  else
+  {
+    return pNPCTopics[122].pText;
+  }
+}
+
+
+//----- (004B2A74) --------------------------------------------------------
+char __cdecl sub_4B2A74()
+{
+  char *v0; // esi@3
+  char *v1; // ST1C_4@3
+  char *v2; // eax@3
+  const char *v3; // ST1C_4@5
+  int v4; // eax@5
+  unsigned int i; // eax@5
+  NPCData *v6; // esi@6
+  unsigned __int16 v7; // bx@6
+  unsigned int v8; // eax@6
+  int v9; // eax@11
+  unsigned int v10; // ecx@12
+  int v11; // eax@12
+  int v12; // esi@12
+  char *v13; // eax@12
+  GUIWindow *v14; // ebx@13
+  char *v15; // esi@14
+  GUIButton *v16; // eax@15
+  unsigned int v17; // ecx@15
+  int v18; // ecx@17
+  int v19; // ecx@18
+  int v20; // ecx@19
+  int v21; // ecx@20
+  int v22; // ecx@21
+  unsigned int v23; // ecx@23
+  int v24; // ecx@35
+  int v25; // ecx@36
+  int v26; // ecx@37
+  int v27; // ecx@38
+  int v28; // ecx@39
+  char *v29; // esi@42
+  unsigned int v30; // ST20_4@42
+  int v31; // ST1C_4@42
+  unsigned int v32; // eax@42
+  char *v33; // eax@43
+  int v34; // esi@51
+  int v35; // eax@51
+  unsigned int v36; // edi@51
+  GUIButton *v37; // eax@52
+  int v38; // eax@52
+  signed int v39; // ecx@54
+  int v40; // edi@57
+  GUIButton *v41; // eax@60
+  GUIButton *v42; // esi@60
+  const char *v43; // ebx@60
+  int v44; // eax@60
+  unsigned int v45; // ecx@60
+  unsigned __int16 v46; // ax@60
+  GUIFont *v47; // ebx@64
+  int v48; // esi@64
+  char *v49; // eax@66
+  GUIWindow w; // [sp+Ch] [bp-110h]@64
+  GUIWindow v52; // [sp+60h] [bp-BCh]@13
+  GUIWindow a1; // [sp+B4h] [bp-68h]@1
+  unsigned int v54; // [sp+108h] [bp-14h]@14
+  int v55; // [sp+10Ch] [bp-10h]@6
+  int v56; // [sp+110h] [bp-Ch]@13
+  char *pInString; // [sp+114h] [bp-8h]@12
+  NPCData *v58; // [sp+118h] [bp-4h]@6
+
+  memcpy(&a1, pDialogueWindow, sizeof(a1));
+  if ( array_5913D8[6] == (NPCData *)uNumDialogueNPCPortraits && uHouse_ExitPic )
+  {
+    v0 = pMapStats->pInfos[uHouse_ExitPic].pName;
+    v1 = pMapStats->pInfos[uHouse_ExitPic].pName;
+    a1.uFrameX = 493;
+    a1.uFrameWidth = 126;
+    a1.uFrameZ = 366;
+    a1.DrawTitleText(pFontCreate, 0, 2u, 0, v1, 3u);
+    a1.uFrameX = 483;
+    a1.uFrameWidth = 148;
+    a1.uFrameZ = 334;
+    v2 = (&off_4EB080)[4 * uHouse_ExitPic];
+    if ( !v2 )
+    {
+      sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[411], v0);
+      v2 = pTmpBuf;
+    }
+    v3 = v2;
+    v4 = pFontCreate->CalcTextHeight(v2, &a1, 0, 0);
+    LOBYTE(i) = (unsigned int)a1.DrawTitleText(pFontCreate, 0, (212 - v4) / 2 + 101, 0, v3, 3u);
+    return i;
+  }
+  a1.uFrameWidth -= 10;
+  a1.uFrameZ -= 10;
+  v58 = array_5913D8[(unsigned int)((char *)array_5913D8[6] + -(dword_591080 != 0) - 1)];
+  v6 = v58;
+  v55 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  v7 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0x15u, 0x99u, 0xE9u);
+  v8 = v6->uProfession;
+  if ( v8 )
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[429], v6->pName, aNPCProfessionNames[v8]);
+  else
+    strcpy(pTmpBuf, v6->pName);
+  a1.DrawTitleText(pFontCreate, 0x1E3u, 0x71u, v7, pTmpBuf, 3u);
+  if ( !dword_591080 )
+  {
+    if ( !uDialogueType )
+    {
+      v9 = v6->greet;
+      if ( v9 )
+      {
+        v10 = v6->uFlags;
+        a1.uFrameWidth = 460;
+        a1.uFrameZ = 452;
+        pInString = (char *)*(&pNPCStats->field_17884 + ((v10 & 3) == 2) + 2 * v9);
+        v11 = pFontArrus->CalcTextHeight(pInString, &a1, 13, 0);
+        v12 = v11 + 7;
+        pRenderer->_4A6A68(
+          8u,
+          352 - (v11 + 7),
+          (Texture *)(uTextureID_Leather != -1 ? &pIcons_LOD->pTextures[uTextureID_Leather] : 0),
+          (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - (v11 + 7));
+        pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
+        v13 = FitTextInAWindow(pInString, pFontArrus, &a1, 0xDu, 0);
+        pDialogueWindow->DrawText(pFontArrus, 13, 354 - v12, 0, v13, 0, 0, 0);
+      }
+    }
+  }
+  v14 = pDialogueWindow;
+  memcpy(&v52, pDialogueWindow, sizeof(v52));
+  v52.uFrameX = 483;
+  v52.uFrameWidth = 148;
+  v52.uFrameZ = 334;
+  v56 = v52.pStartingPosActiveItem;
+  if ( v52.pStartingPosActiveItem < v52.pStartingPosActiveItem + v52.pNumPresenceButton )
+  {
+    v15 = (char *)v54;
+    while ( 1 )
+    {
+      v16 = v52.GetControl(v56);
+      v17 = v16->uControlParam;
+      pInString = (char *)v16;
+      if ( (signed int)v17 > 24 )
+      {
+        v24 = v17 - 76;
+        if ( !v24 )
+        {
+          v15 = pGlobalTXT_LocalizationStrings[406];
+          goto LABEL_49;
+        }
+        v25 = v24 - 1;
+        if ( !v25 )
+        {
+          v15 = pGlobalTXT_LocalizationStrings[407];
+          goto LABEL_49;
+        }
+        v26 = v25 - 2;
+        if ( !v26 )
+        {
+          v33 = _4B254D_SkillMasteryTeacher((int)v52.ptr_1C);
+LABEL_44:
+          v15 = v33;
+LABEL_45:
+          v16 = (GUIButton *)pInString;
+          goto LABEL_49;
+        }
+        v27 = v26 - 3;
+        if ( !v27 )
+        {
+          v33 = (char *)sub_4B29F2((int)v52.ptr_1C);
+          goto LABEL_44;
+        }
+        v28 = v27 - 1;
+        if ( !v28 )
+        {
+          v29 = (char *)&pMonsterStats + 88 * word_F8B1A0;
+          v30 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+          v31 = *(int *)v29;
+          v32 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+          sprintf(pTmpBuf, &byte_4F0F98, v32, v31, v30);
+          sprintf(pTmpBuf2, dword_F8B1A4, pTmpBuf, 100 * (unsigned __int8)v29[8]);
+          ptr_F8B1E8 = pTmpBuf2;
+          v15 = "";
+          goto LABEL_45;
+        }
+        if ( v28 != 10 )
+          goto LABEL_41;
+      }
+      else
+      {
+        if ( v17 == 24 )
+        {
+          v23 = v58->evtf;
+LABEL_33:
+          v15 = (&dword_721660)[8 * v23];
+          if ( !v15 )
+          {
+            v16->uControlParam = 0;
+            v15 = "";
+          }
+          goto LABEL_49;
+        }
+        v18 = v17 - 13;
+        if ( v18 )
+        {
+          v19 = v18 - 6;
+          if ( !v19 )
+          {
+            v23 = v58->bDrawSomeAnim;
+            goto LABEL_33;
+          }
+          v20 = v19 - 1;
+          if ( !v20 )
+          {
+            v15 = (&dword_721660)[8 * v58->evtb];
+            if ( !v15 )
+            {
+              v16->uControlParam = 0;
+              v15 = "";
+            }
+            if ( uDialogueType != 84 )
+              goto LABEL_49;
+            sprintf(pTmpBuf, format_4E2D80, v55, pItemsTable->pItems[dword_F8B1A8].pUnidentifiedName);
+            sprintf(pTmpBuf2, ptr_F8B1E8, pTmpBuf);
+            ptr_F8B1E8 = pTmpBuf2;
+            goto LABEL_45;
+          }
+          v21 = v20 - 1;
+          if ( !v21 )
+          {
+            v23 = v58->evtc;
+            goto LABEL_33;
+          }
+          v22 = v21 - 1;
+          if ( !v22 )
+          {
+            v23 = v58->evtd;
+            goto LABEL_33;
+          }
+          if ( v22 == 1 )
+          {
+            v23 = v58->evte;
+            goto LABEL_33;
+          }
+LABEL_41:
+          v15 = "";
+          goto LABEL_49;
+        }
+        v15 = pGlobalTXT_LocalizationStrings[122];
+      }
+LABEL_49:
+      strcpy(v16->pButtonName, v15);
+      ++v56;
+      if ( v56 >= v52.pStartingPosActiveItem + v52.pNumPresenceButton )
+      {
+        v14 = pDialogueWindow;
+        break;
+      }
+    }
+  }
+  v34 = 0;
+  v54 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v35 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  v36 = v14->pStartingPosActiveItem;
+  v55 = v35;
+  for ( i = v36 + v14->pNumPresenceButton; (signed int)v36 < (signed int)i; i = pDialogueWindow->pNumPresenceButton
+                                                                    + pDialogueWindow->pStartingPosActiveItem )
+  {
+    v37 = v14->GetControl(v36);
+    v38 = pFontArrus->CalcTextHeight(v37->pButtonName, &v52, 0, 0);
+    v14 = pDialogueWindow;
+    v34 += v38;
+    ++v36;
+  }
+  v39 = v14->pNumPresenceButton;
+  if ( v39 )
+  {
+    v58 = (NPCData *)((174 - v34) / v39);
+    if ( (signed int)v58 > 32 )
+      v58 = (NPCData *)32;
+    pInString = (char *)2;
+    v40 = (174 - (signed int)v58 * v39 - v34) / 2 - (signed int)v58 / 2 + 138;
+    v56 = v14->pStartingPosActiveItem;
+    i = v56;
+    if ( (signed int)i < (signed int)(i + v39) )
+    {
+      while ( 1 )
+      {
+        v41 = v14->GetControl(i);
+        v42 = v41;
+        v43 = v41->pButtonName;
+        v41->uY = (unsigned int)((char *)v58 + v40);
+        v44 = pFontArrus->CalcTextHeight(v41->pButtonName, &v52, 0, 0);
+        v45 = v42->uY;
+        v42->uHeight = v44;
+        v40 = v45 + v44 - 1;
+        v42->uW = v40;
+        v46 = v55;
+        if ( (char *)pDialogueWindow->pCurrentPosActiveItem != pInString )
+          v46 = v54;
+        v52.DrawTitleText(pFontArrus, 0, v45, v46, v43, 3u);
+        v14 = pDialogueWindow;
+        ++pInString;
+        ++v56;
+        i = pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem;
+        if ( v56 >= (signed int)i )
+          break;
+        i = v56;
+      }
+    }
+  }
+  if ( ptr_F8B1E8 )
+  {
+    w.uFrameWidth = 458;
+    w.uFrameZ = 457;
+    v47 = pFontArrus;
+    v48 = pFontArrus->CalcTextHeight(ptr_F8B1E8, &w, 13, 0) + 7;
+    if ( 352 - v48 < 8 )
+    {
+      v47 = pFontCreate;
+      v48 = pFontCreate->CalcTextHeight(ptr_F8B1E8, &w, 13, 0) + 7;
+    }
+    pRenderer->_4A6A68(
+      8u,
+      352 - v48,
+      (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
+      (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v48);
+    pRenderer->DrawTextureIndexed(8u, 347 - v48, pTexture_591428);
+    v49 = FitTextInAWindow(ptr_F8B1E8, v47, &w, 0xDu, 0);
+    LOBYTE(i) = a1.DrawText(v47, 13, 354 - v48, 0, v49, 0, 0, 0);
+  }
+  return i;
+}
+
+
+
+
+
+//----- (004B36CC) --------------------------------------------------------
+GUIButton *__fastcall sub_4B36CC(int a1, unsigned int a2)
+{
+  return pDialogueWindow->CreateButton(
+           0x1E0u,
+           30 * a1 + 146,
+           0x8Cu,
+           0x1Eu,
+           1,
+           0,
+           0x195u,
+           a2,
+           0,
+           "",
+           0);
+}
+
+//----- (004B3703) --------------------------------------------------------
+int __thiscall sub_4B3703(void *_this)
+{
+  signed int v1; // edi@1
+  int v2; // eax@1
+  char *v3; // ecx@1
+  signed int v4; // ebx@1
+  int v5; // ecx@2
+  int v6; // ecx@3
+  int v7; // ecx@4
+  int v8; // ecx@5
+  int v9; // ecx@6
+  signed int v10; // ebx@13
+  signed int v11; // edi@14
+  signed int v12; // esi@15
+  unsigned int v13; // ecx@16
+  int v14; // ecx@16
+  int v15; // ecx@17
+  int v16; // ecx@19
+  int v17; // ecx@20
+  int v18; // ecx@21
+  signed int v19; // esi@32
+  char *v20; // ecx@33
+  int v21; // ecx@34
+  int v22; // ecx@36
+  int v23; // ecx@37
+  int v24; // ecx@38
+  int v25; // ecx@39
+  int v26; // ecx@40
+  int v27; // ecx@41
+  int *v28; // esi@54
+  unsigned int v29; // edx@56
+  char *v30; // ecx@65
+  int v31; // ecx@106
+  int result; // eax@107
+  int v33; // [sp-4h] [bp-2Ch]@23
+  int v34; // [sp-4h] [bp-2Ch]@43
+  int v35[5]; // [sp+Ch] [bp-1Ch]@8
+  int a2; // [sp+20h] [bp-8h]@1
+  int v37; // [sp+24h] [bp-4h]@1
+
+  v1 = 0;
+  v2 = 0;
+  v3 = (char *)_this - 1;
+  a2 = 0;
+  v37 = 0;
+  dword_F8B1DC = 0;
+  v4 = 2;
+  if ( !v3 )
+  {
+    while ( 1 )
+    {
+      v19 = 1;
+      do
+      {
+        v20 = (char *)ptr_507BC0->ptr_1C + 4 * (unsigned int)ptr_507BC0->ptr_1C + v19;
+        if ( v1 )
+          v21 = word_4F063E[(signed int)v20];
+        else
+          v21 = word_4F03FE[(signed int)v20];
+        v22 = v21 - 23;
+        if ( v22 )
+        {
+          v23 = v22 - 1;
+          if ( v23 )
+          {
+            v24 = v23 - 1;
+            if ( v24 )
+            {
+              v25 = v24 - 1;
+              if ( v25 )
+              {
+                v26 = v25 - 1;
+                if ( v26 )
+                {
+                  v27 = v26 - 1;
+                  if ( v27 )
+                  {
+                    if ( v27 != v4 )
+                      goto LABEL_51;
+                    v34 = 36;
+                  }
+                  else
+                  {
+                    v34 = 42;
+                  }
+                }
+                else
+                {
+                  v34 = 41;
+                }
+              }
+              else
+              {
+                v34 = 40;
+              }
+            }
+            else
+            {
+              v34 = 39;
+            }
+          }
+          else
+          {
+            v34 = 38;
+          }
+        }
+        else
+        {
+          v34 = 37;
+        }
+        v37 = sub_4BE571(v34, v35, v37, 5);
+        v2 = dword_F8B1DC;
+        v4 = 2;
+LABEL_51:
+        ++v19;
+      }
+      while ( v19 <= 4 );
+      ++v1;
+      if ( v1 >= v4 )
+        goto LABEL_53;
+    }
+  }
+  v5 = (int)(v3 - 1);
+  if ( !v5 )
+  {
+    v10 = 0;
+    while ( 1 )
+    {
+      v11 = 0;
+      do
+      {
+        v12 = 1;
+        do
+        {
+          v13 = v11 + 2 * (unsigned int)ptr_507BC0->ptr_1C - 30;
+          v14 = v12 + 4 * v13 + v13;
+          if ( v10 )
+            v15 = word_4F06D8[v14];
+          else
+            v15 = word_4F0498[v14];
+          v16 = v15 - 31;
+          if ( v16 )
+          {
+            v17 = v16 - 1;
+            if ( v17 )
+            {
+              v18 = v17 - 1;
+              if ( v18 )
+              {
+                if ( v18 != 1 )
+                  goto LABEL_28;
+                v33 = 44;
+              }
+              else
+              {
+                v33 = 47;
+              }
+            }
+            else
+            {
+              v33 = 46;
+            }
+          }
+          else
+          {
+            v33 = 45;
+          }
+          v37 = sub_4BE571(v33, v35, v37, 5);
+          v2 = dword_F8B1DC;
+LABEL_28:
+          ++v12;
+        }
+        while ( v12 <= 4 );
+        ++v11;
+      }
+      while ( v11 < 2 );
+      ++v10;
+      if ( v10 >= 2 )
+        goto LABEL_53;
+    }
+  }
+  v6 = v5 - 1;
+  if ( v6 )
+  {
+    v7 = v6 - 1;
+    if ( v7 )
+    {
+      v8 = v7 - 17;
+      if ( v8 )
+      {
+        v9 = v8 - 2;
+        if ( v9 )
+        {
+          if ( v9 == 7 )
+          {
+            v37 = 2;
+            v35[0] = 69;
+            v35[1] = 60;
+          }
+        }
+        else
+        {
+          v37 = 3;
+          v35[0] = 67;
+          v35[1] = 66;
+          v35[2] = 58;
+        }
+      }
+      else
+      {
+        v37 = 3;
+        v35[0] = 70;
+        v35[1] = 65;
+        v35[2] = 62;
+      }
+    }
+    else
+    {
+      v37 = 2;
+      v35[0] = 71;
+      v35[1] = 68;
+    }
+  }
+  else
+  {
+    v37 = 2;
+    v35[0] = 57;
+    v35[1] = 59;
+  }
+LABEL_53:
+  if ( v37 > 0 )
+  {
+    v28 = v35;
+    while ( 1 )
+    {
+      v29 = *v28;
+      if ( *v28 <= 47 )
+        break;
+      if ( (signed int)v29 <= 66 )
+      {
+        if ( v29 == 66 )
+        {
+          v30 = pSkillNames[30];
+          goto LABEL_106;
+        }
+        if ( v29 == 57 )
+        {
+          v30 = pSkillNames[21];
+          goto LABEL_106;
+        }
+        if ( v29 == 58 )
+        {
+          v30 = pSkillNames[22];
+          goto LABEL_106;
+        }
+        if ( v29 == 60 )
+        {
+          v30 = pSkillNames[24];
+          goto LABEL_106;
+        }
+        if ( v29 == 62 )
+        {
+          v30 = pSkillNames[26];
+          goto LABEL_106;
+        }
+        if ( v29 == 65 )
+        {
+          v30 = pSkillNames[29];
+          goto LABEL_106;
+        }
+        goto LABEL_100;
+      }
+      switch ( v29 )
+      {
+        case 0x43u:
+          v30 = pSkillNames[31];
+          break;
+        case 0x44u:
+          v30 = pSkillNames[32];
+          break;
+        case 0x45u:
+          v30 = pSkillNames[33];
+          break;
+        case 0x46u:
+          v30 = pSkillNames[34];
+          break;
+        default:
+          if ( v29 != 71 )
+            goto LABEL_100;
+          v30 = pSkillNames[35];
+          break;
+      }
+LABEL_106:
+      pShopOptions[v2] = v30;
+      v31 = a2++;
+      dword_F8B1DC = v2 + 1;
+      sub_4B36CC(v31, v29);
+      ++v28;
+      if ( a2 >= v37 )
+        goto LABEL_107;
+      v2 = dword_F8B1DC;
+    }
+    if ( *v28 == 47 )
+    {
+      v30 = pSkillNames[11];
+      goto LABEL_106;
+    }
+    if ( (signed int)v29 > 40 )
+    {
+      if ( v29 == 41 )
+      {
+        v30 = pSkillNames[5];
+        goto LABEL_106;
+      }
+      if ( v29 == 42 )
+      {
+        v30 = pSkillNames[6];
+        goto LABEL_106;
+      }
+      if ( v29 == 44 )
+      {
+        v30 = pSkillNames[8];
+        goto LABEL_106;
+      }
+      if ( v29 == 45 )
+      {
+        v30 = pSkillNames[9];
+        goto LABEL_106;
+      }
+      if ( v29 == 46 )
+      {
+        v30 = pSkillNames[10];
+        goto LABEL_106;
+      }
+    }
+    else
+    {
+      if ( v29 == 40 )
+      {
+        v30 = pSkillNames[4];
+        goto LABEL_106;
+      }
+      if ( v29 == 5 )
+      {
+        v30 = pSkillNames[23];
+        goto LABEL_106;
+      }
+      if ( v29 == 36 )
+      {
+        v30 = pSkillNames[0];
+        goto LABEL_106;
+      }
+      if ( v29 == 37 )
+      {
+        v30 = pSkillNames[1];
+        goto LABEL_106;
+      }
+      if ( v29 == 38 )
+      {
+        v30 = pSkillNames[2];
+        goto LABEL_106;
+      }
+      if ( v29 == 39 )
+      {
+        v30 = pSkillNames[3];
+        goto LABEL_106;
+      }
+    }
+LABEL_100:
+    v30 = pGlobalTXT_LocalizationStrings[127];
+    goto LABEL_106;
+  }
+LABEL_107:
+  pDialogueWindow->_41D08F(a2, 1, 0, 2);
+  result = pDialogueWindow->pNumPresenceButton;
+  dword_F8B1E0 = pDialogueWindow->pNumPresenceButton;
+  return result;
+}
+
+
+//----- (004B3A72) --------------------------------------------------------
+int __thiscall sub_4B3A72(int a1)
+{
+  int v1; // esi@1
+  int result; // eax@4
+
+  v1 = 0;
+  if ( a1 == 21 )
+  {
+    sub_4B36CC(0, 0x66u);
+    v1 = 2;
+    sub_4B36CC(1, 0x67u);
+    if ( pParty->HasItem(0x28Bu) )
+    {
+      v1 = 3;
+      sub_4B36CC(2, 0x68u);
+    }
+  }
+  pDialogueWindow->_41D08F(v1, 1, 0, 2);
+  result = pDialogueWindow->pNumPresenceButton;
+  dword_F8B1E0 = pDialogueWindow->pNumPresenceButton;
+  return result;
+}
+// F8B1E0: using guessed type int dword_F8B1E0;
+
+//----- (004B3AD4) --------------------------------------------------------
+int __fastcall sub_4B3AD4(signed int a1)
+{
+  int result; // eax@7
+  int v2; // [sp-10h] [bp-10h]@4
+  int v3; // [sp-Ch] [bp-Ch]@4
+  int v4; // [sp-8h] [bp-8h]@4
+  int v5; // [sp-4h] [bp-4h]@4
+
+  if ( a1 > 0 )
+  {
+    if ( a1 <= 3 )
+    {
+      sub_4B36CC(0, 3u);
+      sub_4B36CC(1, 4u);
+      sub_4B36CC(2, 5u);
+      v5 = 2;
+      v4 = 0;
+      v3 = 1;
+      v2 = 3;
+      goto LABEL_6;
+    }
+    if ( a1 == 4 )
+    {
+      sub_4B36CC(0, 3u);
+      sub_4B36CC(1, 4u);
+      v5 = 2;
+      v4 = 0;
+      v3 = 1;
+      v2 = 2;
+LABEL_6:
+      pDialogueWindow->_41D08F(v2, v3, v4, v5);
+      goto LABEL_7;
+    }
+  }
+LABEL_7:
+  result = pDialogueWindow->pNumPresenceButton;
+  dword_F8B1E0 = pDialogueWindow->pNumPresenceButton;
+  return result;
+}
+// F8B1E0: using guessed type int dword_F8B1E0;
+
+//----- (004B3B42) --------------------------------------------------------
+int __fastcall sub_4B3B42(signed int a1)
+{
+  int v1; // ecx@18
+  int v2; // ecx@19
+  int v3; // ecx@20
+  signed int v4; // esi@22
+  signed int v5; // eax@22
+  unsigned int v6; // edx@24
+  int v7; // ecx@24
+  int result; // eax@43
+  int v9; // [sp-10h] [bp-14h]@28
+  int v10; // [sp-Ch] [bp-10h]@28
+  int v11; // [sp-8h] [bp-Ch]@28
+  unsigned int v12; // [sp-4h] [bp-8h]@4
+  unsigned int v13; // [sp-4h] [bp-8h]@5
+  unsigned int v14; // [sp-4h] [bp-8h]@9
+  unsigned int v15; // [sp-4h] [bp-8h]@10
+  unsigned int v16; // [sp-4h] [bp-8h]@14
+  int v17; // [sp-4h] [bp-8h]@28
+
+  if ( a1 > 13 )
+  {
+    if ( a1 > 22 )
+    {
+      if ( a1 == 23 )
+      {
+        sub_4B36CC(0, 0xAu);
+        sub_4B36CC(1, 0xBu);
+        v14 = 96;
+LABEL_41:
+        sub_4B36CC(2, v14);
+        v17 = 2;
+        v11 = 0;
+        v10 = 1;
+        v9 = 3;
+        goto LABEL_42;
+      }
+      if ( a1 <= 26 )
+        goto LABEL_43;
+      if ( a1 > 28 )
+      {
+        if ( a1 != 30 )
+          goto LABEL_43;
+        sub_4B36CC(0, 0x11u);
+        v16 = 96;
+        goto LABEL_37;
+      }
+      sub_4B36CC(0, 0x69u);
+      sub_4B36CC(1, 0x6Au);
+      sub_4B36CC(2, 0x6Bu);
+      v12 = 108;
+    }
+    else
+    {
+      if ( a1 == 22 )
+      {
+        sub_4B36CC(0, 7u);
+        v16 = 8;
+        goto LABEL_37;
+      }
+      v1 = a1 - 14;
+      if ( !v1 )
+      {
+        sub_4B36CC(0, 0x12u);
+        sub_4B36CC(1, 0x30u);
+        sub_4B36CC(2, 0x31u);
+        sub_4B36CC(3, 0x32u);
+        sub_4B36CC(4, 0x33u);
+        v17 = 2;
+        v11 = 0;
+        v10 = 1;
+        v9 = 5;
+        goto LABEL_42;
+      }
+      v2 = v1 - 1;
+      if ( v2 )
+      {
+        v3 = v2 - 2;
+        if ( v3 )
+        {
+          if ( v3 != 4 )
+            goto LABEL_43;
+          sub_4B36CC(0, 0xFu);
+          sub_4B36CC(1, 0x10u);
+          v4 = 3;
+          sub_4B36CC(2, 0x60u);
+          v5 = (signed int)ptr_507BC0->ptr_1C;
+          if ( v5 < 108 || v5 > 120 )
+            goto LABEL_28;
+          v4 = 4;
+          v6 = 101;
+          v7 = 3;
+        }
+        else
+        {
+          v4 = 1;
+          sub_4B36CC(0, 0x63u);
+          if ( !pParty->uFine )
+          {
+LABEL_28:
+            v17 = 2;
+            v11 = 0;
+            v10 = 1;
+            v9 = v4;
+LABEL_42:
+            pDialogueWindow->_41D08F(v9, v10, v11, v17);
+            goto LABEL_43;
+          }
+          v4 = 2;
+          v7 = 1;
+          v6 = 100;
+        }
+        sub_4B36CC(v7, v6);
+        goto LABEL_28;
+      }
+      sub_4B36CC(0, 0x12u);
+      sub_4B36CC(1, 0x34u);
+      sub_4B36CC(2, 0x35u);
+      v12 = 54;
+    }
+LABEL_39:
+    sub_4B36CC(3, v12);
+    v17 = 2;
+    v11 = 0;
+    v10 = 1;
+    v9 = 4;
+    goto LABEL_42;
+  }
+  if ( a1 == 13 )
+  {
+    sub_4B36CC(0, 0x12u);
+    v16 = 56;
+LABEL_37:
+    sub_4B36CC(1, v16);
+    v17 = 2;
+    v11 = 0;
+    v10 = 1;
+    v9 = 2;
+    goto LABEL_42;
+  }
+  switch ( a1 )
+  {
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      sub_4B36CC(0, 2u);
+      sub_4B36CC(1, 0x5Fu);
+      sub_4B36CC(2, 0x5Eu);
+      v12 = 96;
+      goto LABEL_39;
+    case 5:
+      sub_4B36CC(0, 0x12u);
+      v13 = 48;
+      goto LABEL_9;
+    case 6:
+      sub_4B36CC(0, 0x12u);
+      v13 = 49;
+      goto LABEL_9;
+    case 7:
+      sub_4B36CC(0, 0x12u);
+      v13 = 50;
+      goto LABEL_9;
+    case 8:
+      sub_4B36CC(0, 0x12u);
+      v13 = 51;
+LABEL_9:
+      sub_4B36CC(1, v13);
+      v14 = 72;
+      goto LABEL_41;
+    case 9:
+      sub_4B36CC(0, 0x12u);
+      v15 = 52;
+      goto LABEL_13;
+    case 10:
+      sub_4B36CC(0, 0x12u);
+      v15 = 53;
+      goto LABEL_13;
+    case 11:
+      sub_4B36CC(0, 0x12u);
+      v15 = 54;
+LABEL_13:
+      sub_4B36CC(1, v15);
+      v14 = 61;
+      goto LABEL_41;
+    case 12:
+      sub_4B36CC(0, 0x12u);
+      v16 = 55;
+      goto LABEL_37;
+    default:
+      break;
+  }
+LABEL_43:
+  result = pDialogueWindow->pNumPresenceButton;
+  dword_F8B1E0 = pDialogueWindow->pNumPresenceButton;
+  return result;
+}
+// F8B1E0: using guessed type int dword_F8B1E0;
+
+//----- (004B3E1E) --------------------------------------------------------
+void __cdecl sub_4B3E1E()
+{
+  NPCData *v0; // ST40_4@1
+  signed int v1; // edi@1
+  GUIWindow *v2; // ecx@1
+
+  v0 = GetNPCData(uDialogue_SpeakingActorNPC_ID);
+  v1 = 0;
+  pDialogueWindow->eWindowType = WINDOW_MainMenu;
+  pDialogueWindow->Release();
+  v2 = GUIWindow::Create(0, 0, 640, 480, WINDOW_A, 1, 0);
+  pDialogueWindow = v2;
+  if ( *(&pNPCStats->field_13A5C + 5 * v0->uProfession) )
+  {
+    v2->CreateButton(
+      0x1E0u,
+      0xA0u,
+      0x8Cu,
+      0x1Eu,
+      1,
+      0,
+      0x88u,
+      0x4Du,
+      0,
+      pGlobalTXT_LocalizationStrings[407],
+      0);
+    v1 = 1;
+  }
+  pDialogueWindow->CreateButton(
+    0x1E0u,
+    30 * v1 + 160,
+    0x8Cu,
+    0x1Eu,
+    1,
+    0,
+    0x88u,
+    0x4Cu,
+    0,
+    pGlobalTXT_LocalizationStrings[406],
+    0);
+  pDialogueWindow->_41D08F(v1 + 1, 1, 0, 1);
+}
+
+//----- (004B3EF0) --------------------------------------------------------
+void __fastcall sub_4B3EF0(int a4)
+{
+  int v1; // edi@1
+
+  v1 = a4;
+  uDialogueType = 81;
+  ptr_F8B1E8 = (char *)pNPCTopics[a4 + 99].pText;
+  sub_4B29F2(a4);
+  pDialogueWindow->Release();
+  pDialogueWindow = GUIWindow::Create(0, 0, 640, 0x15E, WINDOW_MainMenu, v1, 0);
+  pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                 0x1D7,
+                 0x1BD,
+                 0xA9,
+                 0x23,
+                 1,
+                 0,
+                 0x71,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[34],
+                 (Texture *)(uTextureID_506438 != -1 ? &pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                 0);
+  pDialogueWindow->CreateButton(0, 0, 0, 0, 1, 0, 0x51u, 0, 0, "", 0);
+  pDialogueWindow->CreateButton(
+    0x1E0u,
+    0xA0u,
+    0x8Cu,
+    0x1Eu,
+    1,
+    0,
+    0xAFu,
+    0x52u,
+    0,
+    pGlobalTXT_LocalizationStrings[122],
+    0);
+  pDialogueWindow->_41D08F(1, 1, 0, 2);
+  dword_F8B19C = -1;
+}
+// F8B19C: using guessed type int dword_F8B19C;
+
+//----- (004B3FE5) --------------------------------------------------------
+void __fastcall sub_4B3FE5(int a4)
+{
+  int v1; // edi@1
+  char *v2; // edi@1
+
+  v1 = a4;
+  uDialogueType = 78;
+  ptr_F8B1E8 = (char *)pNPCTopics[a4 + 168].pText;
+  _4B254D_SkillMasteryTeacher(a4);
+  pDialogueWindow->Release();
+  pDialogueWindow = GUIWindow::Create(0, 0, 640, 0x15Eu, WINDOW_MainMenu, v1, 0);
+  v2 = "";
+  pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                 0x1D7u,
+                 0x1BDu,
+                 0xA9u,
+                 0x23u,
+                 1,
+                 0,
+                 0x71u,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[34],
+                 (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                 0);
+  pDialogueWindow->CreateButton(0, 0, 0, 0, 1, 0, 0x51u, 0, 0, "", 0);
+  if ( dword_F8B1A8 )
+    v2 = pGlobalTXT_LocalizationStrings[535];
+  pDialogueWindow->CreateButton(0x1E0u, 0xA0u, 0x8Cu, 0x1Eu, 1, 0, 0xAFu, 0x4Fu, 0, v2, 0);
+  pDialogueWindow->_41D08F(1, 1, 0, 2);
+  dword_F8B19C = -1;
+}
+// F8B19C: using guessed type int dword_F8B19C;
+// F8B1A8: using guessed type int dword_F8B1A8;
+
+//----- (004B40E6) --------------------------------------------------------
+void __cdecl sub_4B40E6()
+{
+  signed int v0; // ebx@1
+  NPCData *v1; // edi@1
+
+  v0 = 0;
+  v1 = array_5913D8[(unsigned int)((char *)array_5913D8[6] + -(dword_591080 != 0) - 1)];
+  pDialogueWindow->Release();
+  pDialogueWindow = GUIWindow::Create(0, 0, 640, 0x15Eu, WINDOW_MainMenu, 0, 0);
+  pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                 0x1D7u,
+                 0x1BDu,
+                 0xA9u,
+                 0x23u,
+                 1,
+                 0,
+                 0x71u,
+                 0,
+                 0,
+                 pGlobalTXT_LocalizationStrings[34],
+                 (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                 0);
+  pDialogueWindow->CreateButton(0, 0, 0, 0, 1, 0, 0x51u, 0, 0, "", 0);
+  if ( *(&pNPCStats->field_13A5C + 5 * v1->uProfession) )
+  {
+    pDialogueWindow->CreateButton(
+      0x1E0u,
+      0xA0u,
+      0x8Cu,
+      0x1Eu,
+      1,
+      0,
+      0xAFu,
+      0x4Du,
+      0,
+      pGlobalTXT_LocalizationStrings[407],
+      0);
+    v0 = 1;
+  }
+  pDialogueWindow->CreateButton(
+    0x1E0u,
+    30 * v0 + 160,
+    0x8Cu,
+    0x1Eu,
+    1,
+    0,
+    0xAFu,
+    0x4Cu,
+    0,
+    pGlobalTXT_LocalizationStrings[406],
+    0);
+  pDialogueWindow->_41D08F(v0 + 1, 1, 0, 2);
+  dword_F8B19C = -1;
+}
+
+
+//----- (004B4224) --------------------------------------------------------
+GUIButton *_4B4224_UpdateNPCTopics(int _this)
+{
+  int v1; // ebx@1
+  GUIButton *result; // eax@3
+  int i; // ebp@5
+  signed int v4; // ebp@9
+  void *v5; // ecx@14
+  bool v6; // eax@16
+  void *v7; // ecx@19
+  bool v8; // eax@21
+  void *v9; // ecx@24
+  bool v10; // eax@26
+  void *v11; // ecx@29
+  bool v12; // eax@31
+  void *v13; // ecx@34
+  bool v14; // eax@36
+  void *v15; // ecx@39
+  bool v16; // eax@41
+  NPCData *v17; // [sp+10h] [bp-4h]@4
+
+  v1 = 0;
+  array_5913D8[6] = (NPCData *)(_this + 1);
+  if ( _this + 1 == uNumDialogueNPCPortraits && uHouse_ExitPic )
+  {
+    pDialogueWindow->Release();
+    pDialogueWindow = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0);
+    sprintf(byte_591098, pGlobalTXT_LocalizationStrings[411], pMapStats->pInfos[uHouse_ExitPic].pName);
+    pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                   0x236u,
+                   0x1BDu,
+                   0x4Bu,
+                   0x21u,
+                   1,
+                   0,
+                   0x71u,
+                   0,
+                   0x4Eu,
+                   pGlobalTXT_LocalizationStrings[34],// "Cancel"
+                   (Texture *)(uTextureID_BUTTDESC2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTDESC2] : 0),
+                   0);
+    pBtn_YES = pDialogueWindow->CreateButton(
+                   486u,
+                   445u,
+                   75u,
+                   33u,
+                   1,
+                   0,
+                   0xBFu,
+                   1u,
+                   0x59u,
+                   byte_591098,
+                   (Texture *)(uTextureID_BUTTYES2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTYES2] : 0),
+                   0);
+    pDialogueWindow->CreateButton(
+      _4E5E50_transui_x,
+      _4E5EE0_transui_y,
+      63u,
+      73u,
+      1,
+      0,
+      0xBFu,
+      1u,
+      0x20u,
+      byte_591098,
+      0);
+    result = pDialogueWindow->CreateButton(8u, 8u, 460u, 344u, 1, 0, 0xBFu, 1u, 0x59u, byte_591098, 0);
+  }
+  else
+  {
+    v17 = array_5913D8[_this + 1 - ((dword_591080 != 0) + 1)];
+    if ( dword_F8B19C == -1 )
+    {
+      pDialogueWindow->Release();
+    }
+    else
+    {
+      for ( i = 0; i < uNumDialogueNPCPortraits; ++i )
+        GUIButton::_41D0D8((GUIButton *)array_5913D8[i + 7]);
+    }
+    v4 = 1;
+    pDialogueWindow = GUIWindow::Create(0, 0, 640, 0x159u, WINDOW_MainMenu, 0, 0);
+    pBtn_ExitCancel = pDialogueWindow->CreateButton(
+                   471u,
+                   445u,
+                   169u,
+                   35u,
+                   1,
+                   0,
+                   0x71u,
+                   0,
+                   0,
+                   pGlobalTXT_LocalizationStrings[74],// "End Conversation"
+                   (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0),
+                   0);
+    pDialogueWindow->CreateButton(8u, 8u, 0x1C2u, 0x140u, 1, 0, 0x51u, 0, 0, "", 0);
+    if ( array_5913D8[6] == (NPCData *)1 && dword_591080 )
+    {
+      result = (GUIButton *)sub_4B3B42(dword_F8B198);
+    }
+    else
+    {
+      if ( v17->joins )
+      {
+        v1 = 1;
+        pDialogueWindow->CreateButton(480u, 160u, 140u, 30u, 1, 0, 0xAFu, 0xDu, 0, "", 0);
+      }
+      v5 = (void *)v17->bDrawSomeAnim;
+      if ( v5 )
+      {
+        if ( v1 < 4 )
+        {
+          v6 = sub_4466C4(v5);
+          if ( v6 == 1 || v6 == 2 )
+            pDialogueWindow->CreateButton(
+              480u,
+              30 * v1++ + 160,
+              140u,
+              30u,
+              1,
+              0,
+              0xAFu,
+              0x13u,
+              0,
+              "",
+              0);
+        }
+      }
+      v7 = (void *)v17->evtb;
+      if ( v7 )
+      {
+        if ( v1 < 4 )
+        {
+          v8 = sub_4466C4(v7);
+          if ( v8 == 1 || v8 == 2 )
+            pDialogueWindow->CreateButton(
+              480u,
+              30 * v1++ + 160,
+              140u,
+              30u,
+              1,
+              0,
+              0xAFu,
+              0x14u,
+              0,
+              "",
+              0);
+        }
+      }
+      v9 = (void *)v17->evtc;
+      if ( v9 )
+      {
+        if ( v1 < 4 )
+        {
+          v10 = sub_4466C4(v9);
+          if ( v10 == 1 || v10 == 2 )
+            pDialogueWindow->CreateButton(
+              480u,
+              30 * v1++ + 160,
+              140u,
+              30u,
+              1,
+              0,
+              0xAFu,
+              0x15u,
+              0,
+              "",
+              0);
+        }
+      }
+      v11 = (void *)v17->evtd;
+      if ( v11 )
+      {
+        if ( v1 < 4 )
+        {
+          v12 = sub_4466C4(v11);
+          if ( v12 == 1 || v12 == 2 )
+            pDialogueWindow->CreateButton(
+              0x1E0u,
+              30 * v1++ + 160,
+              0x8Cu,
+              0x1Eu,
+              1,
+              0,
+              0xAFu,
+              0x16u,
+              0,
+              "",
+              0);
+        }
+      }
+      v13 = (void *)v17->evte;
+      if ( v13 )
+      {
+        if ( v1 < 4 )
+        {
+          v14 = sub_4466C4(v13);
+          if ( v14 == 1 || v14 == 2 )
+            pDialogueWindow->CreateButton(
+              0x1E0u,
+              30 * v1++ + 160,
+              0x8Cu,
+              0x1Eu,
+              1,
+              0,
+              0xAFu,
+              0x17u,
+              0,
+              "",
+              0);
+        }
+      }
+      v15 = (void *)v17->evtf;
+      if ( v15 )
+      {
+        if ( v1 < 4 )
+        {
+          v16 = sub_4466C4(v15);
+          if ( v16 == 1 || v16 == 2 )
+            pDialogueWindow->CreateButton(
+              0x1E0u,
+              30 * v1++ + 160,
+              0x8Cu,
+              0x1Eu,
+              1,
+              0,
+              0xAFu,
+              0x18u,
+              0,
+              "",
+              0);
+        }
+      }
+      pDialogueWindow->_41D08F(v1, 1, 0, 2);
+      v4 = 1;
+      result = (GUIButton *)pDialogueWindow->pNumPresenceButton;
+      dword_F8B1E0 = pDialogueWindow->pNumPresenceButton;
+    }
+    dword_F8B19C = v4;
+  }
+  return result;
+}
+
+
+
+//----- (004B46A5) --------------------------------------------------------
+char __fastcall sub_4B46A5(const char *Str, int a5)
+{
+  const char *v2; // esi@1
+  int v3; // edi@1
+  int v4; // eax@1
+
+  v2 = Str;
+  v3 = a5;
+  pRenderer->DrawTextureRGB(0, 0x160u, pTexture_StatusBar);
+  v4 = pFontLucida->AlignText_Center(0x1C2u, v2);
+  return pPrimaryWindow->DrawText(pFontLucida, v4 + 11, 357, v3, v2, 0, 0, 0);
+}
+
+//----- (004B46F8) --------------------------------------------------------
+int __fastcall sub_4B46F8(int a1)
+{
+  int v1; // eax@1
+  int i; // edx@1
+
+  v1 = 0;
+  for ( i = 0; i < a1; ++i )
+    v1 += i + 1;
+  return 1000 * v1;
+}
+
+//----- (004B4710) --------------------------------------------------------
+int __cdecl ui_training()
+{
+  Player *v0; // ebx@1
+  int color2; // eax@1
+  unsigned int v2; // ecx@1
+  int v3; // eax@1
+  signed int v4; // edx@1
+  int v5; // edi@3
+  unsigned int v6; // esi@3
+  void *v7; // ecx@3
+  int v8; // edx@4
+  double v9; // st7@6
+  signed int v10; // esi@6
+  int v11; // ecx@6
+  int result; // eax@9
+  GUIWindow *v13; // edi@14
+  signed int v14; // esi@14
+  unsigned int v15; // esi@16
+  int v16; // eax@16
+  unsigned int v17; // eax@17
+  int v18; // eax@19
+  int v19; // ecx@24
+  GUIButton *v20; // eax@26
+  GUIButton *v21; // esi@26
+  int v22; // eax@26
+  const char *v23; // eax@28
+  int v24; // eax@28
+  unsigned int v25; // ecx@28
+  int v26; // eax@28
+  unsigned __int16 v27; // ax@28
+  int v28; // eax@32
+  unsigned __int16 v29; // ST14_2@34
+  int v30; // eax@34
+  const char *v31; // ST18_4@36
+  unsigned __int16 v32; // ST14_2@36
+  int v33; // eax@36
+  int v34; // eax@37
+  unsigned int v35; // edi@38
+  unsigned int v36; // eax@38
+  int v37; // ecx@41
+  char *v38; // eax@41
+  int *v39; // eax@45
+  unsigned int v40; // eax@46
+  void *v41; // ecx@46
+  unsigned int v42; // eax@46
+  GUIWindow *v43; // ecx@59
+  int v44; // edx@59
+  char **v45; // esi@60
+  int v46; // eax@62
+  int v47; // eax@68
+  int v48; // edx@69
+  int v49; // ebx@69
+  unsigned __int8 v50; // sf@69
+  char **v51; // edi@70
+  GUIButton *v52; // eax@71
+  GUIButton *v53; // esi@71
+  int v54; // eax@71
+  unsigned int v55; // ecx@71
+  int v56; // eax@71
+  unsigned __int16 v57; // ax@71
+  unsigned __int16 v58; // [sp-Ch] [bp-90h]@38
+  const char *v59; // [sp-Ch] [bp-90h]@63
+  char *v60; // [sp-8h] [bp-8Ch]@38
+  char *v61; // [sp-8h] [bp-8Ch]@63
+  unsigned int v62; // [sp-4h] [bp-88h]@38
+  int v63; // [sp-4h] [bp-88h]@52
+  char *v64; // [sp-4h] [bp-88h]@63
+  GUIWindow v65; // [sp+Ch] [bp-78h]@1
+  __int64 v66; // [sp+60h] [bp-24h]@3
+  unsigned int white; // [sp+68h] [bp-1Ch]@1
+  int v68; // [sp+6Ch] [bp-18h]@3
+  int v69; // [sp+70h] [bp-14h]@6
+  unsigned int i; // [sp+74h] [bp-10h]@1
+  int v71; // [sp+78h] [bp-Ch]@1
+  int v72; // [sp+7Ch] [bp-8h]@16
+  int v73; // [sp+80h] [bp-4h]@14
+
+  v0 = pPlayers[uActiveCharacter];
+  memcpy(&v65, ptr_507BC0, sizeof(v65));
+  v65.uFrameX = 483;
+  v65.uFrameWidth = 148;
+  v65.uFrameZ = 334;
+  white = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  color2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  v2 = v0->uLevel;
+  v71 = color2;
+  v3 = 0;
+  v4 = 0;
+  for ( i = v2; v4 < (signed int)v2; ++v4 )
+    v3 += v4 + 1;
+  v5 = 1000 * v3;
+  v6 = HIDWORD(v0->uExperience);
+  v7 = ptr_507BC0->ptr_1C;
+  v68 = (unsigned __int16)word_4F0866[(signed int)v7];
+  v66 = 1000 * v3;
+  if ( (signed __int64)__PAIR__(v6, LODWORD(v0->uExperience)) >= v66 )
+  {
+    v8 = v0->uClass % 4 + 1;
+    if ( v8 == 4 )
+      v8 = 3;
+    v9 = (double)(signed int)i;
+    i = 0;
+    v69 = v8;
+    //v10 = (signed __int64)(v9 * p2DEvents_minus1__20[13 * (signed int)v7] * (double)v8);
+    v10 = (signed __int64)(v9 * p2DEvents[(signed int)v7 - 1].fPriceMultiplier * (double)v8);
+    v11 = v10 * (100 - v0->GetMerchant()) / 100;
+    if ( v11 < v10 / 3 )
+      v11 = v10 / 3;
+    i = v11;
+  }
+  result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+  if ( result )
+  {
+    if ( dword_F8B19C != 1 )
+    {
+      if ( dword_F8B19C != 17 )
+      {
+        result = dword_F8B19C - 96;
+        if ( dword_F8B19C == 96 )
+        {
+          result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+          if ( result )
+          {
+            i = 0;
+            v13 = pDialogueWindow;
+            //v14 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (unsigned int)ptr_507BC0->ptr_1C] * 500.0);
+            v14 = (signed __int64)(p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].flt_24 * 500.0);
+            v73 = v14 * (100 - v0->GetMerchant()) / 100;
+            if ( v73 < v14 / 3 )
+              v73 = v14 / 3;
+            v15 = v13->pStartingPosActiveItem;
+            v16 = v13->pNumPresenceButton;
+            v72 = 0;
+            if ( (signed int)v15 >= (signed int)(v15 + v16) )
+              goto LABEL_76;
+            do
+            {
+              v17 = v13->GetControl(v15)->uControlParam - 36;
+              if ( byte_4ED970_skill_learn_ability_by_class_table[v0->uClass][v17] && !v0->pActiveSkills[v17] )
+              {
+                v18 = pFontArrus->CalcTextHeight(pSkillNames[v17], &v65, 0, 0);
+                i += v18;
+                ++v72;
+              }
+              ++v15;
+            }
+            while ( (signed int)v15 < v13->pNumPresenceButton + v13->pStartingPosActiveItem );
+            if ( v72 )
+            {
+              sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], v73);// "Skill Cost: %lu"
+              v65.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+              v73 = (signed int)(149 - i) / v72;
+              if ( v73 > 32 )
+                v73 = 32;
+              result = v13->pStartingPosActiveItem;
+              v19 = (signed int)(149 - v72 * v73 - i) / 2 - v73 / 2 + 162;
+              i = result;
+              v68 = v19;
+              if ( result < result + v13->pNumPresenceButton )
+              {
+                v72 = 2;
+                do
+                {
+                  v20 = v13->GetControl(i);
+                  v21 = v20;
+                  v22 = v20->uControlParam - 36;
+                  if ( !byte_4ED970_skill_learn_ability_by_class_table[v0->uClass][v22] || v0->pActiveSkills[v22] )
+                  {
+                    v21->uW = 0;
+                    v21->uHeight = 0;
+                    v21->uY = 0;
+                  }
+                  else
+                  {
+                    v23 = pSkillNames[v22];
+                    v21->uY = v73 + v68;
+                    HIDWORD(v66) = (int)v23;
+                    v24 = pFontArrus->CalcTextHeight(v23, &v65, 0, 0);
+                    v25 = v21->uY;
+                    v21->uHeight = v24;
+                    v26 = v25 + v24 - 1;
+                    v21->uW = v26;
+                    v68 = v26;
+                    v27 = v71;
+                    if ( pDialogueWindow->pCurrentPosActiveItem != v72 )
+                      v27 = white;
+                    v65.DrawTitleText(pFontArrus, 0, v25, v27, (char *)HIDWORD(v66), 3u);
+                  }
+                  v28 = v13->pStartingPosActiveItem;
+                  ++i;
+                  result = v13->pNumPresenceButton + v28;
+                  ++v72;
+                }
+                while ( (signed int)i < result );
+              }
+            }
+            else
+            {
+LABEL_76:
+              sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], v0->pName, pClassNames[v0->uClass]);// 
+                                                // "Seek knowledge elsewhere %s the %s"
+              strcat(pTmpBuf, "\n \n");
+              strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);// "I can offer you nothing further."
+              v29 = v71;
+              v30 = pFontArrus->CalcTextHeight(pTmpBuf, &v65, 0, 0);
+              result = (int)v65.DrawTitleText(pFontArrus, 0, (174 - v30) / 2 + 138, v29, pTmpBuf, 3u);
+            }
+          }
+        }
+        return result;
+      }
+      if ( !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+      {
+        v31 = pNPCTopics[122].pText;
+        v32 = v71;
+        v33 = pFontArrus->CalcTextHeight(pNPCTopics[122].pText, &v65, 0, 0);
+        v65.DrawTitleText(pFontArrus, 0, (212 - v33) / 2 + 101, v32, v31, 3u);
+        result = (int)pDialogueWindow;
+        pDialogueWindow->pNumPresenceButton = 0;
+        return result;
+      }
+      v34 = v0->uLevel;
+      if ( v34 < v68 )
+      {
+        if ( (signed __int64)v0->uExperience >= v66 )
+        {
+          if ( pParty->uNumGold >= i )
+          {
+            Party::TakeGold(i);
+            HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 2);
+            ++v0->uLevel;
+            v0->uSkillPoints += v0->uLevel / 10 + 5;
+            v0->sHealth = v0->GetMaxHealth();
+            v0->sMana = v0->GetMaxMana();
+            v37 = 0;
+            v38 = byte_F8B148;
+            do
+            {
+              if ( *(int *)v38 > v37 )
+                v37 = *(int *)v38;
+              v38 += 4;
+            }
+            while ( (signed int)v38 < (signed int)word_F8B158 );
+            v39 = &dword_F8B144 + uActiveCharacter;
+            ++*v39;
+            if ( *v39 > v37 )
+            {
+              v40 = sub_494820(pParty->uCurrentHour);
+              v41 = ptr_507BC0->ptr_1C;
+              v42 = 60 * (v40 + 4) - pParty->uCurrentMinute;
+              if ( v41 == (void *)94 || v41 == (void *)95 )
+                v42 += 720;
+              RestAndHeal((signed int)(v42 + 10080));
+              if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
+                pOutdoor->SetFog();
+            }
+            v0->PlaySound(87, 0);
+            sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[430], v0->pName, v0->uLevel, v0->uLevel / 10 + 5);// 
+                                                // "%s is now Level %lu and has earned %lu Skill Points!"
+            ShowStatusBarString(pTmpBuf, 2u);
+            goto LABEL_56;
+          }
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);// "You don't have enough gold"
+          v63 = 4;
+LABEL_55:
+          HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, v63);
+LABEL_56:
+          result = pMessageQueue_50CBD0->uNumMessages;
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+          {
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+            result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
+            *(&pMessageQueue_50CBD0->uNumMessages + result) = 0;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+          return result;
+        }
+        sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[538], v5 - LODWORD(v0->uExperience), v34 + 1);// 
+                                                // "You need %d more experience to train to level %d"
+        v35 = 0;
+        v62 = 3;
+        v60 = pTmpBuf;
+        v58 = v71;
+        v36 = (212 - pFontArrus->CalcTextHeight(pTmpBuf, &v65, 0, 0)) / 2 + 88;
+      }
+      else
+      {
+        sprintf(pTmpBuf, "%s\n \n%s", pGlobalTXT_LocalizationStrings[536], pGlobalTXT_LocalizationStrings[529]);// 
+                                                // ""With your skills, you should be working here as a teacher.""
+                                                // ""Sorry, but we are unable to train you.""
+        v35 = 0;
+        v62 = 3;
+        v60 = pTmpBuf;
+        v58 = v71;
+        v36 = (212 - pFontArrus->CalcTextHeight(pTmpBuf, &v65, 0, 0)) / 2 + 101;
+      }
+      v65.DrawTitleText(pFontArrus, v35, v36, v58, v60, v62);
+      v63 = 3;
+      goto LABEL_55;
+    }
+    result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+    if ( result )
+    {
+      v43 = pDialogueWindow;
+      v72 = 0;
+      pShopOptions[0] = pTmpBuf;
+      pShopOptions[1] = pGlobalTXT_LocalizationStrings[160];// "Learn Skills"
+      v44 = pDialogueWindow->pNumPresenceButton;
+      v73 = pDialogueWindow->pStartingPosActiveItem;
+      if ( v73 < v73 + v44 )
+      {
+        v45 = pShopOptions;
+        do
+        {
+          if ( v43->GetControl(v73)->uControlParam == 17 )
+          {
+            v46 = v0->uLevel;
+            if ( v46 < v68 )
+            {
+              if ( (signed __int64)v0->uExperience < v66 )
+              {
+                v64 = (char *)(v46 + 1);
+                v61 = (char *)(v5 - LODWORD(v0->uExperience));
+                v59 = pGlobalTXT_LocalizationStrings[538];// "You need %d more experience to train to level %d"
+              }
+              else
+              {
+                v64 = (char *)i;
+                v61 = (char *)(v46 + 1);
+                v59 = pGlobalTXT_LocalizationStrings[537];// "Train to level %d for %d gold"
+              }
+            }
+            else
+            {
+              v64 = pGlobalTXT_LocalizationStrings[529];// ""Sorry, but we are unable to train you.""
+              v61 = pGlobalTXT_LocalizationStrings[536];// ""With your skills, you should be working here as a teacher.""
+              v59 = "%s\n \n%s";
+            }
+            sprintf(*v45, v59, v61, v64);
+          }
+          v47 = pFontArrus->CalcTextHeight(*v45, &v65, 0, 0);
+          v43 = pDialogueWindow;
+          v72 += v47;
+          ++v45;
+          ++v73;
+        }
+        while ( v73 < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem );
+      }
+      HIDWORD(v66) = (174 - v72) / 2;
+      result = v43->pStartingPosActiveItem;
+      v48 = result + v43->pNumPresenceButton;
+      v49 = (2 * (87 - (174 - v72) / 2) - v72) / 2 - (174 - v72) / 2 / 2 + 138;
+      v50 = -v43->pNumPresenceButton < 0;
+      v73 = v43->pStartingPosActiveItem;
+      if ( v50 ^ __OFSUB__(result, v48) )
+      {
+        i = 2;
+        v51 = pShopOptions;
+        do
+        {
+          v52 = v43->GetControl(v73);
+          v53 = v52;
+          v52->uY = HIDWORD(v66) + v49;
+          v54 = pFontArrus->CalcTextHeight(*v51, &v65, 0, 0);
+          v55 = v53->uY;
+          v53->uHeight = v54;
+          v56 = v54 + v55 - 1;
+          v53->uW = v56;
+          v49 = v56;
+          v57 = v71;
+          if ( pDialogueWindow->pCurrentPosActiveItem != i )
+            v57 = white;
+          v65.DrawTitleText(pFontArrus, 0, v55, v57, *v51, 3u);
+          v43 = pDialogueWindow;
+          ++i;
+          ++v51;
+          ++v73;
+          result = pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem;
+        }
+        while ( v73 < result );
+      }
+    }
+  }
+  return result;
+}
+
+
+
+
+
+
+
+
+
+//----- (004B4FCF) --------------------------------------------------------
+int __cdecl ui_shop_teachers()
+{
+  Player *v0; // ebx@1
+  int result; // eax@6
+  signed int v2; // esi@8
+  unsigned int v3; // ebx@10
+  char *v4; // eax@11
+  char *v5; // eax@12
+  unsigned int v6; // eax@12
+  int v7; // ST08_4@14
+  int v8; // eax@14
+  unsigned __int8 v9; // dl@14
+  char *v10; // ecx@14
+  signed int v11; // esi@16
+  int v12; // ST08_4@19
+  int v13; // eax@19
+  int v14; // edi@21
+  char **v15; // esi@21
+  int v16; // eax@22
+  GUIWindow *v17; // ecx@23
+  int v18; // edx@23
+  int v19; // edi@23
+  unsigned __int8 v20; // sf@23
+  GUIButton *v21; // esi@25
+  const char **v22; // eax@25
+  int v23; // eax@25
+  unsigned int v24; // ecx@25
+  const char **v25; // edx@25
+  unsigned __int16 v26; // ax@25
+  signed int v27; // esi@30
+  int v28; // ST08_4@34
+  int v29; // eax@34
+  char *v30; // edx@35
+  GUIWindow *v31; // edi@40
+  void *v32; // eax@40
+  signed int v33; // esi@40
+  unsigned int v34; // esi@42
+  int v35; // eax@42
+  unsigned int v36; // eax@43
+  int v37; // eax@45
+  int v38; // ecx@50
+  GUIButton *v39; // eax@52
+  GUIButton *v40; // esi@52
+  int v41; // eax@52
+  char *v42; // eax@54
+  int v43; // eax@54
+  unsigned int v44; // ecx@54
+  int v45; // edx@54
+  int v46; // eax@54
+  unsigned __int16 v47; // ax@54
+  int v48; // eax@58
+  signed int v49; // esi@62
+  Texture *v50; // ecx@64
+  unsigned int v51; // edi@64
+  unsigned int v52; // esi@66
+  int v53; // edx@70
+  Texture *v54; // ecx@76
+  unsigned int v55; // edi@76
+  unsigned int v56; // esi@76
+  int v57; // edx@80
+  Texture *v58; // ecx@86
+  unsigned int v59; // edi@86
+  unsigned int v60; // esi@88
+  int v61; // edx@92
+  Texture *v62; // ecx@98
+  unsigned int v63; // edi@98
+  unsigned int v64; // esi@100
+  int v65; // edx@104
+  signed int v66; // ecx@109
+  SHORT v67; // di@117
+  bool v68; // eax@117
+  const char *v69; // ecx@119
+  POINT *v70; // esi@124
+  int v71; // ecx@125
+  int v72; // eax@125
+  int v73; // ecx@125
+  ItemGen *v74; // esi@125
+  int v75; // eax@130
+  int v76; // esi@131
+  char **v77; // edi@131
+  int v78; // eax@132
+  GUIWindow *v79; // ecx@133
+  int v80; // edx@133
+  int v81; // edi@133
+  GUIButton *v82; // esi@135
+  const char **v83; // eax@135
+  int v84; // eax@135
+  unsigned int v85; // ecx@135
+  int v86; // edx@135
+  unsigned __int16 v87; // ax@135
+  GUIWindow *v88; // [sp-18h] [bp-110h]@35
+  int v89; // [sp-14h] [bp-10Ch]@35
+  ItemGen *v90; // [sp-10h] [bp-108h]@14
+  int v91; // [sp-10h] [bp-108h]@35
+  unsigned __int16 v92; // [sp-Ch] [bp-104h]@12
+  void *v93; // [sp-Ch] [bp-104h]@14
+  int v94; // [sp-8h] [bp-100h]@11
+  char *v95; // [sp-8h] [bp-100h]@12
+  __int64 *v96; // [sp-4h] [bp-FCh]@11
+  unsigned int v97; // [sp-4h] [bp-FCh]@12
+  POINT v98; // [sp+Ch] [bp-ECh]@8
+  POINT v99; // [sp+14h] [bp-E4h]@16
+  POINT v100; // [sp+1Ch] [bp-DCh]@124
+  POINT v101; // [sp+24h] [bp-D4h]@17
+  POINT v102; // [sp+2Ch] [bp-CCh]@124
+  POINT v103; // [sp+34h] [bp-C4h]@9
+  POINT v104; // [sp+3Ch] [bp-BCh]@31
+  POINT v105; // [sp+44h] [bp-B4h]@16
+  POINT v106; // [sp+4Ch] [bp-ACh]@30
+  POINT v107; // [sp+54h] [bp-A4h]@16
+  POINT v108; // [sp+5Ch] [bp-9Ch]@30
+  POINT a2; // [sp+64h] [bp-94h]@8
+  POINT v110; // [sp+6Ch] [bp-8Ch]@30
+  POINT v111; // [sp+74h] [bp-84h]@8
+  GUIWindow v112; // [sp+7Ch] [bp-7Ch]@1
+  char *Str; // [sp+D0h] [bp-28h]@54
+  int v114; // [sp+D4h] [bp-24h]@23
+  unsigned int color2; // [sp+D8h] [bp-20h]@1
+  unsigned int white; // [sp+DCh] [bp-1Ch]@1
+  __int32 v117; // [sp+E0h] [bp-18h]@8
+  int v118; // [sp+E4h] [bp-14h]@40
+  const char **v119; // [sp+E8h] [bp-10h]@24
+  Player *_this; // [sp+ECh] [bp-Ch]@1
+  unsigned __int8 uPlayerID; // [sp+F3h] [bp-5h]@14
+  int v122; // [sp+F4h] [bp-4h]@23
+
+  v0 = pPlayers[uActiveCharacter];
+  _this = pPlayers[uActiveCharacter];
+  memcpy(&v112, ptr_507BC0, sizeof(v112));
+  v112.uFrameX = 483;
+  v112.uFrameWidth = 148;
+  v112.uFrameZ = 334;
+  white = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  color2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  if ( dword_F8B19C > 5 )
+  {
+    if ( dword_F8B19C == 94 )
+    {
+      draw_leather();
+      CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+      pShopOptions[0] = pGlobalTXT_LocalizationStrings[200];// "Sell"
+      pShopOptions[1] = pGlobalTXT_LocalizationStrings[113];// "Identify"
+      pShopOptions[2] = pGlobalTXT_LocalizationStrings[179];// "Repair"
+      v76 = 0;
+      v77 = pShopOptions;
+      do
+      {
+        v78 = pFontArrus->CalcTextHeight(*v77, &v112, 0, 0);
+        ++v77;
+        v76 += v78;
+      }
+      while ( (signed int)v77 < (signed int)&pShopOptions[3] );
+      v79 = pDialogueWindow;
+      _this = (Player *)((174 - v76) / 3);
+      result = pDialogueWindow->pStartingPosActiveItem;
+      v80 = result + pDialogueWindow->pNumPresenceButton;
+      v81 = (3 * (58 - (signed int)_this) - v76) / 2 - (174 - v76) / 3 / 2 + 138;
+      v20 = -pDialogueWindow->pNumPresenceButton < 0;
+      v118 = pDialogueWindow->pStartingPosActiveItem;
+      if ( v20 ^ __OFSUB__(result, v80) )
+      {
+        v122 = 2;
+        v119 = (const char **)pShopOptions;
+        do
+        {
+          v82 = v79->GetControl(v118);
+          v83 = v119;
+          v82->uY = (unsigned int)((char *)_this + v81);
+          v84 = pFontArrus->CalcTextHeight(*v83, &v112, 0, 0);
+          v85 = v82->uY;
+          v86 = v122;
+          v82->uHeight = v84;
+          v81 = v84 + v85 - 1;
+          v82->uW = v81;
+          v87 = color2;
+          if ( pDialogueWindow->pCurrentPosActiveItem != v86 )
+            v87 = white;
+          v112.DrawTitleText(pFontArrus, 0, v85, v87, *v119, 3u);
+          v79 = pDialogueWindow;
+          ++v122;
+          ++v119;
+          ++v118;
+          result = pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem;
+        }
+        while ( v118 < result );
+      }
+      return result;
+    }
+    if ( dword_F8B19C != 95 )
+    {
+      result = dword_F8B19C - 96;
+      if ( dword_F8B19C == 96 )
+      {
+        result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+        if ( result )
+        {
+          v31 = pDialogueWindow;
+          v3 = 0;
+          v32 = ptr_507BC0->ptr_1C;
+          v118 = 0;
+            //v33 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (signed int)v32] * 500.0);
+            v33 = (signed __int64)(p2DEvents[(signed int)v32 - 1].flt_24 * 500.0);
+          v119 = (const char **)(v33 * (100 - _this->GetMerchant()) / 100);
+          if ( (signed int)v119 < v33 / 3 )
+            v119 = (const char **)(v33 / 3);
+          v34 = v31->pStartingPosActiveItem;
+          v35 = v34 + v31->pNumPresenceButton;
+          v122 = 0;
+          if ( (signed int)v34 >= v35 )
+            goto LABEL_140;
+          do
+          {
+            v36 = v31->GetControl(v34)->uControlParam - 36;
+            if ( byte_4ED970_skill_learn_ability_by_class_table[_this->uClass][v36] && !_this->pActiveSkills[v36] )
+            {
+              v37 = pFontArrus->CalcTextHeight(pSkillNames[v36], &v112, 0, 0);
+              v118 += v37;
+              ++v122;
+            }
+            ++v34;
+          }
+          while ( (signed int)v34 < v31->pNumPresenceButton + v31->pStartingPosActiveItem );
+          if ( !v122 )
+          {
+LABEL_140:
+            sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], _this->pName, pClassNames[_this->uClass]);// 
+                                                // "Seek knowledge elsewhere %s the %s"
+            strcat(pTmpBuf, "\n \n");
+            strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);// "I can offer you nothing further."
+            v30 = pTmpBuf;
+            v97 = 3;
+            v95 = pTmpBuf;
+            v92 = color2;
+            v91 = 0;
+            v89 = 0;
+            v88 = &v112;
+            goto LABEL_61;
+          }
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], v119);// "Skill Cost: %lu"
+          v112.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+          v119 = (const char **)((149 - v118) / v122);
+          if ( (149 - v118) / v122 > 32 )
+            v119 = (const char **)32;
+          result = v31->pStartingPosActiveItem;
+          v38 = (149 - v122 * (signed int)v119 - v118) / 2 - (signed int)v119 / 2 + 162;
+          v118 = result;
+          v114 = v38;
+          if ( result < result + v31->pNumPresenceButton )
+          {
+            v122 = 2;
+            do
+            {
+              v39 = v31->GetControl(v118);
+              v40 = v39;
+              v41 = v39->uControlParam - 36;
+              if ( !byte_4ED970_skill_learn_ability_by_class_table[_this->uClass][v41] || _this->pActiveSkills[v41] )
+              {
+                v40->uW = 0;
+                v40->uHeight = 0;
+                v40->uY = 0;
+              }
+              else
+              {
+                v42 = pSkillNames[v41];
+                v40->uY = (unsigned int)((char *)v119 + v114);
+                Str = v42;
+                v43 = pFontArrus->CalcTextHeight(v42, &v112, 0, 0);
+                v44 = v40->uY;
+                v45 = v122;
+                v40->uHeight = v43;
+                v46 = v44 + v43 - 1;
+                v40->uW = v46;
+                v114 = v46;
+                v47 = color2;
+                if ( pDialogueWindow->pCurrentPosActiveItem != v45 )
+                  v47 = white;
+                v112.DrawTitleText(pFontArrus, 0, v44, v47, Str, 3u);
+              }
+              v48 = v31->pStartingPosActiveItem;
+              ++v118;
+              result = v31->pNumPresenceButton + v48;
+              ++v122;
+            }
+            while ( v118 < result );
+          }
+        }
+      }
+      return result;
+    }
+  }
+  else
+  {
+    if ( dword_F8B19C == 5 )
+    {
+      draw_leather();
+      CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+      sub_4B46A5(pGlobalTXT_LocalizationStrings[198], 0);// "Select the Item to Repair"
+      result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+      if ( !result
+        || (v27 = pMouse->GetCursorPos(&v110)->x - 14,
+            v117 = (v27 >> 5) + 14 * ((pMouse->GetCursorPos(&v108)->y - 17) >> 5),
+            result = (int)pMouse->GetCursorPos(&v106),
+            *(int *)result <= 13)
+        || (result = (int)pMouse->GetCursorPos(&v104), *(int *)result >= 462)
+        || (result = v0->GetItemIDAtInventoryIndex((int *)&v117), v3 = 0, !result)
+        || (result *= 9, !(_this->field_1F5[4 * result + 15] & 2)) )
+        return result;
+      v96 = 0;
+      v94 = 5;
+      v93 = ptr_507BC0->ptr_1C;
+      v90 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5];
+      v28 = (int)ptr_507BC0->ptr_1C;
+      uPlayerID = uActiveCharacter - 1;
+      v29 = _this->_490EEE((ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5], 3, v28, 5);
+      v9 = uPlayerID;
+      v10 = (char *)pMerchantsRepairPhrases[v29];
+      goto LABEL_35;
+    }
+    if ( dword_F8B19C == 1 )
+    {
+      result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+      if ( result )
+      {
+        pShopOptions[0] = pGlobalTXT_LocalizationStrings[134];// "Buy Standard"
+        pShopOptions[1] = pGlobalTXT_LocalizationStrings[152];// "Buy Special"
+        pShopOptions[2] = pGlobalTXT_LocalizationStrings[159];// "Display Inventory"
+        v14 = 0;
+        pShopOptions[3] = pGlobalTXT_LocalizationStrings[160];// "Learn Skills"
+        v15 = pShopOptions;
+        do
+        {
+          v16 = pFontArrus->CalcTextHeight(*v15, &v112, 0, 0);
+          ++v15;
+          v14 += v16;
+        }
+        while ( (signed int)v15 < (signed int)&unk_F8B1C8 );
+        v17 = pDialogueWindow;
+        v114 = (174 - v14) / 4;
+        result = pDialogueWindow->pStartingPosActiveItem;
+        v18 = result + pDialogueWindow->pNumPresenceButton;
+        v19 = (174 - 4 * (174 - v14) / 4 - v14) / 2 - (174 - v14) / 4 / 2 + 138;
+        v20 = -pDialogueWindow->pNumPresenceButton < 0;
+        v122 = pDialogueWindow->pStartingPosActiveItem;
+        if ( v20 ^ __OFSUB__(result, v18) )
+        {
+          v119 = (const char **)2;
+          _this = (Player *)pShopOptions;
+          do
+          {
+            v21 = v17->GetControl(v122);
+            v22 = (const char **)_this;
+            v21->uY = v114 + v19;
+            v23 = pFontArrus->CalcTextHeight(*v22, &v112, 0, 0);
+            v24 = v21->uY;
+            v25 = v119;
+            v21->uHeight = v23;
+            v19 = v24 + v23 - 1;
+            v21->uW = v19;
+            v26 = color2;
+            if ( (const char **)pDialogueWindow->pCurrentPosActiveItem != v25 )
+              v26 = white;
+            v112.DrawTitleText(pFontArrus, 0, v24, v26, (const char *)LODWORD(_this->pConditions[0]), 3u);
+            v17 = pDialogueWindow;
+            v119 = (const char **)((char *)v119 + 1);
+            _this = (Player *)((char *)_this + 4);
+            ++v122;
+            result = pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem;
+          }
+          while ( v122 < result );
+        }
+      }
+      return result;
+    }
+    if ( dword_F8B19C != 2 )
+    {
+      if ( dword_F8B19C != 3 )
+      {
+        result = dword_F8B19C - 4;
+        if ( dword_F8B19C == 4 )
+        {
+          draw_leather();
+          CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+          sub_4B46A5(pGlobalTXT_LocalizationStrings[197], 0);// "Select the Item to Identify"
+          result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+          if ( result )
+          {
+            v2 = pMouse->GetCursorPos(&a2)->x - 14;
+            v117 = (v2 >> 5) + 14 * ((pMouse->GetCursorPos(&v98)->y - 17) >> 5);
+            result = (int)pMouse->GetCursorPos(&v111);
+            if ( *(int *)result > 13 )
+            {
+              result = (int)pMouse->GetCursorPos(&v103);
+              if ( *(int *)result < 462 )
+              {
+                result = v0->GetItemIDAtInventoryIndex((int *)&v117);
+                v3 = 0;
+                if ( result )
+                {
+                  v96 = 0;
+                  v94 = 4;
+                  v4 = &_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
+                  if ( v4[20] & 1 )
+                  {
+                    v5 = sub_495461("%24", uActiveCharacter - 1, (ItemGen *)v4, (char *)ptr_507BC0->ptr_1C, 4, 0);
+                    v97 = 3;
+                    v95 = v5;
+                    v92 = white;
+                    v6 = (212 - pFontArrus->CalcTextHeight(v5, &v112, 0, 0)) / 2 + 101;
+                    return (int)v112.DrawTitleText(pFontArrus, v3, v6, v92, v95, v97);
+                  }
+                  v93 = ptr_507BC0->ptr_1C;
+                  v90 = (ItemGen *)v4;
+                  v7 = (int)ptr_507BC0->ptr_1C;
+                  uPlayerID = uActiveCharacter - 1;
+                  v8 = ((Player *)_this)->_490EEE((ItemGen *)v4, 3, v7, 4);
+                  v9 = uPlayerID;
+                  v10 = (char *)pMerchantsIdentifyPhrases[v8];
+                  goto LABEL_35;
+                }
+              }
+            }
+          }
+        }
+        return result;
+      }
+      draw_leather();
+      CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+      sub_4B46A5(pGlobalTXT_LocalizationStrings[199], 0);// "Select the Item to Sell"
+      result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+      if ( !result
+        || (v11 = pMouse->GetCursorPos(&v107)->x - 14,
+            v117 = (v11 >> 5) + 14 * ((pMouse->GetCursorPos(&v99)->y - 17) >> 5),
+            result = (int)pMouse->GetCursorPos(&v105),
+            *(int *)result <= 13)
+        || (result = (int)pMouse->GetCursorPos(&v101), *(int *)result >= 462)
+        || (result = v0->GetItemIDAtInventoryIndex((int *)&v117), v3 = 0, !result) )
+        return result;
+      v96 = 0;
+      v94 = 3;
+      v93 = ptr_507BC0->ptr_1C;
+      v90 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
+      v12 = (int)ptr_507BC0->ptr_1C;
+      uPlayerID = uActiveCharacter - 1;
+      v13 = _this->_490EEE(v90, 3, v12, 3);
+      v9 = uPlayerID;
+      v10 = (char *)pMerchantsSellPhrases[v13];
+LABEL_35:
+      v30 = sub_495461(v10, v9, v90, (char *)v93, v94, v96);
+      v97 = 3;
+      v95 = v30;
+      v92 = white;
+      v91 = v3;
+      v89 = v3;
+      v88 = &v112;
+LABEL_61:
+      v6 = (174 - pFontArrus->CalcTextHeight(v30, v88, v89, v91)) / 2 + 138;
+      return (int)v112.DrawTitleText(pFontArrus, v3, v6, v92, v95, v97);
+    }
+  }
+  pRenderer->DrawTextureIndexed(8u, 8u, dword_F8B164);
+  v3 = 0;
+  v49 = 0;
+  v122 = 0;
+  if ( dword_F8B19C == 2 )
+  {
+    do
+    {
+      if ( pParty->field_777C[9 * (v49 + 12 * (unsigned int)ptr_507BC0->ptr_1C)] )
+      {
+        v50 = dword_F8B168[v49];
+        v51 = 152 - v50->uTextureHeight;
+        if ( (signed int)v51 < 1 )
+          v51 = 0;
+        v52 = 75 * v49 - v50->uTextureWidth / 2 + 40;
+        if ( v122 )
+        {
+          if ( v122 == 5 )
+          {
+            v53 = dword_F8B168[5]->uTextureWidth;
+            if ( (signed int)v52 > 457 - v53 )
+              v52 = 457 - v53;
+          }
+        }
+        else
+        {
+          if ( (signed int)v52 < 18 )
+            v52 = 18;
+        }
+        pRenderer->DrawTextureTransparent(v52, v51, v50);
+        sub_40F92A(&pRenderer->pActiveZBuffer[v52 + 640 * v51], dword_F8B168[v122], v122 + 1);
+        v49 = v122;
+      }
+      ++v49;
+      v122 = v49;
+    }
+    while ( v49 < 6 );
+    v122 = 0;
+    do
+    {
+      if ( pParty->field_777C[9 * (v122 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 54] )
+      {
+        v54 = dword_F8B168[v122 + 6];
+        v55 = 306 - v54->uTextureHeight;
+        v56 = 75 * v122 - v54->uTextureWidth / 2 + 40;
+        if ( v122 )
+        {
+          if ( v122 == 5 )
+          {
+            v57 = dword_F8B168[11]->uTextureWidth;
+            if ( (signed int)v56 > 457 - v57 )
+              v56 = 457 - v57;
+          }
+        }
+        else
+        {
+          if ( (signed int)v56 < 18 )
+            v56 = 18;
+        }
+        pRenderer->DrawTextureTransparent(v56, v55, v54);
+        sub_40F92A(&pRenderer->pActiveZBuffer[v56 + 640 * v55], dword_F8B168[v122 + 6], v122 + 7);
+      }
+      ++v122;
+    }
+    while ( v122 < 6 );
+  }
+  else
+  {
+    do
+    {
+      if ( pParty->field_C59C[9 * (v49 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] )
+      {
+        v58 = dword_F8B168[v49];
+        v59 = 152 - v58->uTextureHeight;
+        if ( (signed int)v59 < 1 )
+          v59 = 0;
+        v60 = 75 * v49 - v58->uTextureWidth / 2 + 40;
+        if ( v122 )
+        {
+          if ( v122 == 5 )
+          {
+            v61 = dword_F8B168[5]->uTextureWidth;
+            if ( (signed int)v60 > 457 - v61 )
+              v60 = 457 - v61;
+          }
+        }
+        else
+        {
+          if ( (signed int)v60 < 18 )
+            v60 = 18;
+        }
+        pRenderer->DrawTextureTransparent(v60, v59, v58);
+        sub_40F92A(&pRenderer->pActiveZBuffer[v60 + 640 * v59], dword_F8B168[v122], v122 + 1);
+        v49 = v122;
+      }
+      ++v49;
+      v122 = v49;
+    }
+    while ( v49 < 6 );
+    v122 = 0;
+    do
+    {
+      if ( pParty->field_C59C[9 * (v122 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 778] )
+      {
+        v62 = dword_F8B168[v122 + 6];
+        v63 = 306 - v62->uTextureHeight;
+        if ( (signed int)v63 < 1 )
+          v63 = 0;
+        v64 = 75 * v122 - v62->uTextureWidth / 2 + 40;
+        if ( v122 )
+        {
+          if ( v122 == 5 )
+          {
+            v65 = dword_F8B168[11]->uTextureWidth;
+            if ( (signed int)v64 > 457 - v65 )
+              v64 = 457 - v65;
+          }
+        }
+        else
+        {
+          if ( (signed int)v64 < 18 )
+            v64 = 18;
+        }
+        pRenderer->DrawTextureTransparent(v64, v63, v62);
+        sub_40F92A(&pRenderer->pActiveZBuffer[v64 + 640 * v63], dword_F8B168[v122 + 6], v122 + 7);
+      }
+      ++v122;
+    }
+    while ( v122 < 6 );
+  }
+  result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+  if ( result )
+  {
+    v66 = 0;
+    v117 = 0;
+    if ( dword_F8B19C == 2 )
+    {
+      do
+      {
+        if ( pParty->field_777C[9 * (v66 + 12 * (unsigned int)ptr_507BC0->ptr_1C)] )
+          ++v117;
+        ++v66;
+      }
+      while ( v66 < 12 );
+    }
+    else
+    {
+      do
+      {
+        if ( pParty->field_C59C[9 * (v66 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 724] )
+          ++v117;
+        ++v66;
+      }
+      while ( v66 < 12 );
+    }
+    v67 = GetAsyncKeyState(VK_CONTROL);
+    v68 = _this->CanSteal();
+    Str = (char *)v68;
+    if ( v67 && v68 )
+    {
+      v69 = pGlobalTXT_LocalizationStrings[185];// "Steal item"
+    }
+    else
+    {
+      v69 = pGlobalTXT_LocalizationStrings[195];// "Select the Item to Buy"
+      if ( dword_F8B19C != 2 )
+        v69 = pGlobalTXT_LocalizationStrings[196];// "Select the Special Item to Buy"
+    }
+    sub_4B46A5(v69, 0);
+    if ( !v117 )
+      return (int)v112._4B1854(
+                    __PAIR__(
+                      pParty->field_3C.field_50[2 * (unsigned int)ptr_507BC0->ptr_1C + 1],
+                      pParty->field_3C.field_50[2 * (unsigned int)ptr_507BC0->ptr_1C])
+                  - pParty->uTimePlayed);
+    v70 = pMouse->GetCursorPos(&v102);
+    result = v70->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v100)->y];
+    if ( pRenderer->pActiveZBuffer[result] & 0xFFFF )
+    {
+      v71 = (pRenderer->pActiveZBuffer[result] & 0xFFFF) - 1;
+      v117 = v71;
+      v72 = (int)ptr_507BC0->ptr_1C;
+      v73 = 9 * (v71 + 12 * v72);
+      v74 = (ItemGen *)&pParty->field_777C[v73];
+      if ( dword_F8B19C != 2 )
+        v74 = (ItemGen *)&pParty->field_C59C[v73 + 724];
+      if ( v67 && Str )
+      {
+        v10 = pGlobalTXT_LocalizationStrings[181];// "Steal %24"
+        v96 = 0;
+        v94 = 2;
+        v93 = ptr_507BC0->ptr_1C;
+        v90 = v74;
+        v9 = uActiveCharacter - 1;
+      }
+      else
+      {
+        v96 = 0;
+        v94 = 2;
+        v93 = ptr_507BC0->ptr_1C;
+        v90 = v74;
+        uPlayerID = uActiveCharacter - 1;
+        v75 = _this->_490EEE(v74, 3, v72, 2);
+        v9 = uPlayerID;
+        v10 = (char *)pMerchantsBuyPhrases[v75];
+      }
+      goto LABEL_35;
+    }
+  }
+  return result;
+}
+
+//----- (004BC49B) --------------------------------------------------------
+void __thiscall sub_4BC49B(unsigned int _this)
+{
+  unsigned int v1; // esi@1
+  NPCData *v2; // ebp@1
+  unsigned int v3; // eax@1
+  int v4; // ecx@10
+  signed int v5; // edi@14
+  char *v6; // esi@15
+  const char *v7; // ecx@22
+  signed int v8; // edi@37
+  unsigned int v9; // eax@56
+  unsigned int v10; // ecx@57
+  void *v11; // [sp-Ch] [bp-1Ch]@46
+  int v12; // [sp-8h] [bp-18h]@46
+  char *v13; // [sp-8h] [bp-18h]@60
+  size_t v14; // [sp-4h] [bp-14h]@46
+  const char *v15; // [sp-4h] [bp-14h]@60
+
+  v1 = _this;
+  v2 = GetNPCData(uDialogue_SpeakingActorNPC_ID);
+  v3 = v1;
+  uDialogueType = v1;
+  if ( !v2->uFlags )
+  {
+    v2->uFlags = 1;
+    v3 = uDialogueType;
+  }
+  if ( (signed int)v3 > 22 )
+  {
+    if ( v3 == 23 )
+    {
+      v4 = v2->evte;
+      goto LABEL_74;
+    }
+    if ( v3 == 24 )
+    {
+      v4 = v2->evtf;
+      goto LABEL_74;
+    }
+    if ( v3 != 76 )
+    {
+      if ( v3 == 77 )
+      {
+        byte_F8B1EC ^= 1u;
+      }
+      else
+      {
+        if ( (signed int)v3 > 84 && (signed int)v3 <= 88 )
+        {
+          ArenaFight();
+          return;
+        }
+      }
+      goto LABEL_87;
+    }
+    if ( v2->uFlags & 0x80 )
+    {
+      v8 = 0;
+      if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+      {
+        v6 = (char *)pNPCStats->pNewNPCData;
+        while ( !(v6[8] & 0x80) || strcmp(v2->pName, *(const char **)v6) )
+        {
+          ++v8;
+          v6 += 76;
+          if ( v8 >= (signed int)pNPCStats->uNumNewNPCs )
+            goto LABEL_44;
+        }
+        goto LABEL_43;
+      }
+LABEL_44:
+      if ( !pParty->pHirelings[0].pName || _strcmpi(pParty->pHirelings[0].pName, v2->pName) )
+      {
+        if ( !pParty->pHirelings[1].pName || _strcmpi(pParty->pHirelings[1].pName, v2->pName) )
+        {
+LABEL_51:
+          pParty->field_709 = 0;
+          sub_44A56A();
+          dword_591084 = 0;
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+          {
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+            *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+          goto LABEL_89;
+        }
+        v14 = 76;
+        v12 = 0;
+        v11 = &pParty->pHirelings[1];
+      }
+      else
+      {
+        v14 = 76;
+        v12 = 0;
+        v11 = pParty->pHirelings;
+      }
+      memset(v11, v12, v14);
+      goto LABEL_51;
+    }
+    if ( pParty->pHirelings[0].pName && pParty->pHirelings[1].pName )
+    {
+      v7 = pGlobalTXT_LocalizationStrings[533]; // ""I cannot join you, you're party is full""
+LABEL_64:
+      ShowStatusBarString(v7, 2u);
+      goto LABEL_87;
+    }
+    v9 = v2->uProfession;
+    if ( v9 != 51 )
+    {
+      v10 = *(&pNPCStats->field_13A58 + 5 * v9);
+      if ( pParty->uNumGold < v10 )
+      {
+        ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);// "You don't have enough gold"
+        byte_F8B1EC = 0;
+        uDialogueType = 13;
+        if ( uActiveCharacter )
+          pPlayers[uActiveCharacter]->PlaySound(38, 0);
+        v7 = pGlobalTXT_LocalizationStrings[155];
+        goto LABEL_64;
+      }
+      Party::TakeGold(v10);
+    }
+    LOBYTE(v2->uFlags) |= 0x80u;
+    if ( pParty->pHirelings[0].pName )
+    {
+      memcpy(&pParty->pHirelings[1], v2, sizeof(pParty->pHirelings[1]));
+      v15 = v2->pName;
+      v13 = pParty->pHireling2Name;
+    }
+    else
+    {
+      memcpy(pParty->pHirelings, v2, 0x4Cu);
+      v15 = v2->pName;
+      v13 = pParty->pHireling1Name;
+    }
+    strcpy(v13, v15);
+    pParty->field_709 = 0;
+    sub_44A56A();
+    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+      *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+    if ( (uDialogue_SpeakingActorNPC_ID & 0x80000000u) == 0 )
+      pDialogue_SpeakingActor->uAIState = Removed;
+    if ( uActiveCharacter )
+      pPlayers[uActiveCharacter]->PlaySound(61, 0);
+    goto LABEL_87;
+  }
+  if ( v3 == 22 )
+  {
+    v4 = v2->evtd;
+    goto LABEL_74;
+  }
+  if ( v3 == 9 )
+  {
+    if ( !sub_4BB756(v2->uProfession) )
+    {
+      if ( v2->uProfession != 41 )
+        v2->bHasUsedTheAbility = 1;
+      if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+      {
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+        *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+        ++pMessageQueue_50CBD0->uNumMessages;
+      }
+      goto LABEL_87;
+    }
+    v7 = pGlobalTXT_LocalizationStrings[140];
+    goto LABEL_64;
+  }
+  if ( v3 == 13 )
+  {
+    if ( !(v2->uFlags & 0x80) )
+    {
+      sub_4B3E1E();
+      byte_F8B1EC = 0;
+      goto LABEL_87;
+    }
+    v5 = 0;
+    if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+    {
+      v6 = (char *)pNPCStats->pNewNPCData;
+      while ( !(v6[8] & 0x80) || strcmp(v2->pName, *(const char **)v6) )
+      {
+        ++v5;
+        v6 += 76;
+        if ( v5 >= (signed int)pNPCStats->uNumNewNPCs )
+          goto LABEL_44;
+      }
+LABEL_43:
+      v6[8] &= 0x7Fu;
+      goto LABEL_44;
+    }
+    goto LABEL_44;
+  }
+  if ( v3 == 19 )
+  {
+    v4 = v2->bDrawSomeAnim;
+    goto LABEL_74;
+  }
+  if ( v3 == 20 )
+  {
+    v4 = v2->evtb;
+    goto LABEL_74;
+  }
+  if ( v3 == 21 )
+  {
+    v4 = v2->evtc;
+LABEL_74:
+    if ( v4 < 200 || v4 > 310 )
+    {
+      if ( v4 < 400 || v4 > 410 )
+      {
+        switch ( v4 )
+        {
+          case 139:
+            sub_4B1ECE();
+            break;
+          case 311:
+            sub_4BBA85_bounties();
+            break;
+          case 399:
+            sub_4BBCDD();
+            break;
+          default:
+            _5C3420_pDecoration = (LevelDecoration *)1;
+            ptr_F8B1E8 = 0;
+            EventProcessor(v4, 0, 1);
+            _5C3420_pDecoration = 0;
+            break;
+        }
+      }
+      else
+      {
+        dword_F8B1D8 = v3;
+        sub_4B3EF0(v4 - 400);
+      }
+    }
+    else
+    {
+      sub_4B3FE5(v4);
+    }
+  }
+LABEL_87:
+  if ( !dword_7241C8 )
+    pGame->Draw();
+LABEL_89:
+  dword_7241C8 = 0;
+}
+
+
+
+//----- (004BDAAF) --------------------------------------------------------
+bool __fastcall sub_4BDAAF(ItemGen *a1, int _2da_idx)
+{
+  int v2; // edx@1
+  unsigned int v3; // esi@1
+  unsigned int v4; // eax@1
+  signed int v5; // edi@1
+  int v6; // edx@8
+  int v7; // edx@9
+  int v8; // edx@10
+  unsigned __int8 v9; // zf@16
+  char v10; // sf@16
+  unsigned __int8 v11; // of@16
+
+  auto a2 = _2da_idx;
+  //v2 = p2DEvents_minus1___00[26 * a2];
+  v2 = p2DEvents[a2 - 1].uType;
+  v3 = a1->uItemID;
+  v4 = a1->uItemID;
+  v5 = pItemsTable->pItems[v4].uEquipType;
+  if ( (v2 != 4 || (signed int)v3 < 740 || (signed int)v3 > 771)
+    && ((signed int)v3 >= 600 || (signed int)v3 >= 529 && (signed int)v3 <= 599)
+    || BYTE1(a1->uAttributes) & 1 )
+    return 0;
+  v6 = v2 - 1;
+  if ( !v6 )
+  {
+    v11 = __OFSUB__(v5, 2);
+    v9 = v5 == 2;
+    v10 = v5 - 2 < 0;
+    goto LABEL_23;
+  }
+  v7 = v6 - 1;
+  if ( v7 )
+  {
+    v8 = v7 - 1;
+    if ( !v8 )
+    {
+      if ( pItemsTable->pItems[v4].uSkillType != 38 )
+        return v5 == 16;
+      return 1;
+    }
+    if ( v8 != 1 || v5 < 13 )
+      return 0;
+    if ( v5 <= 14 )
+      return 1;
+    if ( v5 != 17 || (signed int)v3 < 740 )
+      return 0;
+    v11 = __OFSUB__(v3, 771);
+    v9 = v3 == 771;
+    v10 = ((v3 - 771) & 0x80000000u) != 0;
+LABEL_23:
+    if ( !((unsigned __int8)(v10 ^ v11) | v9) )
+      return 0;
+    return 1;
+  }
+  if ( v5 >= 3 )
+  {
+    v11 = __OFSUB__(v5, 9);
+    v9 = v5 == 9;
+    v10 = v5 - 9 < 0;
+    goto LABEL_23;
+  }
+  return 0;
+}
+
+
+
+//----- (004B5D7C) --------------------------------------------------------
+int __cdecl sub_4B5D7C()
+{
+  GUIWindow *v0; // ebx@1
+  Player *v1; // edi@1
+  signed int v2; // ebx@1
+  int v3; // edi@6
+  int result; // eax@11
+  unsigned int v5; // ebx@13
+  int v6; // esi@13
+  signed int v7; // esi@17
+  int v8; // esi@22
+  signed int v9; // ecx@22
+  char *v10; // eax@22
+  const char *v11; // ecx@26
+  POINT *v12; // esi@30
+  int v13; // ecx@30
+  void *v14; // ST1C_4@31
+  ItemGen *v15; // ST18_4@31
+  int v16; // ST10_4@31
+  int v17; // eax@31
+  char *v18; // edx@31
+  int v19; // eax@32
+  GUIWindow *v20; // edi@35
+  int v21; // esi@35
+  int v22; // eax@35
+  unsigned int v23; // eax@36
+  int v24; // eax@39
+  int v25; // eax@40
+  int v26; // ecx@47
+  GUIButton *v27; // eax@49
+  GUIButton *v28; // esi@49
+  unsigned int v29; // eax@49
+  char *v30; // eax@52
+  int v31; // eax@55
+  unsigned int v32; // ecx@55
+  int v33; // eax@55
+  unsigned __int16 v34; // ax@55
+  int v35; // eax@58
+  const char *v36; // ST20_4@61
+  unsigned __int16 v37; // ST1C_2@61
+  int v38; // eax@61
+  GUIWindow *v39; // [sp-18h] [bp-304h]@31
+  int v40; // [sp-14h] [bp-300h]@31
+  int v41; // [sp-10h] [bp-2FCh]@31
+  unsigned __int16 v42; // [sp-Ch] [bp-2F8h]@31
+  char *v43; // [sp-8h] [bp-2F4h]@31
+  unsigned int v44; // [sp-4h] [bp-2F0h]@31
+  char Dest[100]; // [sp+Ch] [bp-2E0h]@3
+  char v46[100]; // [sp+70h] [bp-27Ch]@3
+  char v47[100]; // [sp+D4h] [bp-218h]@3
+  char v48[100]; // [sp+138h] [bp-1B4h]@3
+  char v49[100]; // [sp+19Ch] [bp-150h]@3
+  POINT v50; // [sp+264h] [bp-88h]@30
+  POINT v51; // [sp+26Ch] [bp-80h]@30
+  GUIWindow v52; // [sp+274h] [bp-78h]@1
+  signed int v53; // [sp+27Ch] [bp-70h]@1
+  signed int v54; // [sp+284h] [bp-68h]@1
+  int v55; // [sp+2C8h] [bp-24h]@47
+  int v56; // [sp+2CCh] [bp-20h]@1
+  int v57; // [sp+2D0h] [bp-1Ch]@1
+  Player *v58; // [sp+2D4h] [bp-18h]@1
+  unsigned __int8 uPlayerID; // [sp+2DBh] [bp-11h]@31
+  char *Str; // [sp+2DCh] [bp-10h]@35
+  int v61; // [sp+2E0h] [bp-Ch]@35
+  unsigned int v62; // [sp+2E4h] [bp-8h]@13
+  int v63; // [sp+2E8h] [bp-4h]@1
+
+  v0 = ptr_507BC0;
+  memcpy(&v52, ptr_507BC0, sizeof(v52));
+  v58 = pPlayers[uActiveCharacter];
+  v1 = v58;
+  v52.uFrameX = 483;
+  v53 = 148;
+  v54 = 334;
+  v56 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v57 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  //v2 = (signed __int64)(p2DEvents_minus1__20[13 * (unsigned int)v0->ptr_1C] * 500.0);
+  v2 = (signed __int64)(p2DEvents[(unsigned int)v0->ptr_1C - 1].fPriceMultiplier * 500.0);
+  v63 = v2 * (100 - v1->GetMerchant()) / 100;
+  if ( v63 < v2 / 3 )
+    v63 = v2 / 3;
+  strcpy(Dest, "");
+  strcpy(v46, "");
+  strcpy(v47, "");
+  strcpy(v48, "");
+  strcpy(v49, "");
+  if ( dword_F8B19C != 1 )
+  {
+    if ( dword_F8B19C != 18 )
+    {
+      if ( sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+      {
+        v3 = (int)(&v1->uIntelligence + dword_F8B19C);
+        if ( *(short *)v3 )
+        {
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[403], pClassNames[dword_F8B19C + 20]);
+          ShowStatusBarString(pTmpBuf, 2u);
+          pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+        }
+        else
+        {
+          if ( pParty->uNumGold < v63 )
+          {
+            ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
+            HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 2);
+          }
+          else
+          {
+            Party::TakeGold(v63);
+            *(short *)v3 = 1;
+          }
+        }
+      }
+      result = pMessageQueue_50CBD0->uNumMessages;
+      if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+      {
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+        result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
+        *(&pMessageQueue_50CBD0->uNumMessages + result) = 0;
+        ++pMessageQueue_50CBD0->uNumMessages;
+      }
+      return result;
+    }
+    pRenderer->DrawTextureIndexed(8u, 8u, dword_F8B164);
+    v5 = 0;
+    v6 = 0;
+    v62 = 0;
+    v63 = 32;
+    do
+    {
+      if ( *(&pParty->pPlayers[1].pInstalledBeacons[0].field_18 + 9 * (v6 + 12 * (unsigned int)ptr_507BC0->ptr_1C)) )
+      {
+        pRenderer->DrawTextureTransparent(v63, 0x5Au, dword_F8B168[v6]);
+        ZBuffer_DoFill((int *)((char *)pRenderer->pActiveZBuffer + v62 + 230528), dword_F8B168[v6], v6 + 1);
+        v1 = v58;
+      }
+      v63 += 70;
+      v62 += 280;
+      ++v6;
+    }
+    while ( v63 < 452 );
+    v62 = 1680;
+    v7 = 6;
+    v63 = 32;
+    do
+    {
+      if ( *(&pParty->pPlayers[1].pInstalledBeacons[0].field_18 + 9 * (v7 + 12 * (unsigned int)ptr_507BC0->ptr_1C)) )
+      {
+        pRenderer->DrawTextureTransparent(v63, 0xFAu, dword_F8B168[v7]);
+        ZBuffer_DoFill((int *)((char *)pRenderer->pActiveZBuffer + v62 + 638448), dword_F8B168[v7], v7 + 1);
+        v1 = v58;
+      }
+      v63 += 70;
+      v62 += 280;
+      ++v7;
+    }
+    while ( v63 < 452 );
+    result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+    if ( result )
+    {
+      v8 = 0;
+      v9 = 12;
+      v10 = (char *)(&pParty->pPlayers[1].pInstalledBeacons[0].field_18 + 108 * (unsigned int)ptr_507BC0->ptr_1C);
+      do
+      {
+        if ( *(int *)v10 )
+          ++v8;
+        v10 += 36;
+        --v9;
+      }
+      while ( v9 );
+      GetAsyncKeyState(17);
+      v11 = pGlobalTXT_LocalizationStrings[195];
+      if ( dword_F8B19C != 2 )
+        v11 = pGlobalTXT_LocalizationStrings[196];
+      sub_4B46A5(v11, 0);
+      if ( !v8 )
+        return (int)v52._4B1854(
+                      __PAIR__(
+                        *(int *)&stru_AA1058[3].pSounds[8 * (unsigned int)ptr_507BC0->ptr_1C + 44472],
+                        *(int *)&stru_AA1058[3].pSounds[8 * (unsigned int)ptr_507BC0->ptr_1C + 44468])
+                    - pParty->uTimePlayed);
+      v12 = pMouse->GetCursorPos(&v51);
+      result = v12->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v50)->y];
+      v13 = pRenderer->pActiveZBuffer[result] & 0xFFFF;
+      if ( pRenderer->pActiveZBuffer[result] & 0xFFFF )
+      {
+        v14 = ptr_507BC0->ptr_1C;
+        v15 = (ItemGen *)(&pParty->pPlayers[1].uExpressionTimeLength + 18 * (v13 + 12 * (int)v14));
+        v16 = (int)ptr_507BC0->ptr_1C;
+        uPlayerID = uActiveCharacter - 1;
+        v17 = v1->_490EEE(
+                (ItemGen *)&pParty->pPlayers[1].uExpressionTimeLength + v13 + 12 * (int)v14,
+                3,
+                v16,
+                2);
+        v18 = sub_495461((char *)pMerchantsBuyPhrases[v17], uPlayerID, v15, (char *)v14, 2, 0);
+        v44 = 3;
+        v43 = v18;
+        v42 = v56;
+        v41 = 0;
+        v40 = 0;
+        v39 = &v52;
+LABEL_32:
+        v19 = pFontArrus->CalcTextHeight(v18, v39, v40, v41);
+        return (int)v52.DrawTitleText(pFontArrus, v5, (174 - v19) / 2 + 138, v42, v43, v44);
+      }
+    }
+    return result;
+  }
+  if ( !(unsigned __int16)_449B57_test_bit(
+                            (unsigned __int8 *)v1->field_152,
+                            word_4F0704[2 * (unsigned int)ptr_507BC0->ptr_1C]) )
+  {
+    v36 = pNPCTopics[121].pText;
+    v37 = v57;
+    v38 = pFontArrus->CalcTextHeight(pNPCTopics[121].pText, &v52, 0, 0);
+    v52.DrawTitleText(pFontArrus, 0, (212 - v38) / 2 + 101, v37, v36, 3u);
+    result = (int)pDialogueWindow;
+    pDialogueWindow->pNumPresenceButton = 0;
+    return result;
+  }
+  result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+  if ( !result )
+    return result;
+  v20 = pDialogueWindow;
+  v5 = 0;
+  v62 = 0;
+  Str = 0;
+  v21 = pDialogueWindow->pStartingPosActiveItem;
+  v22 = v21 + pDialogueWindow->pNumPresenceButton;
+  v61 = 0;
+  if ( v21 >= v22 )
+    goto LABEL_64;
+  do
+  {
+    v23 = v20->GetControl(v21)->uControlParam;
+    if ( v23 == 18 )
+    {
+      v25 = pFontArrus->CalcTextHeight(pGlobalTXT_LocalizationStrings[400], &v52, 0, 0);
+      v62 += v25;
+      ++v61;
+    }
+    else
+    {
+      __debugbreak();
+      //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+
+      //if ( *(&byte_4ED94C[37 * v58->uClass] + v23) && !*(&v58->uIntelligence + v23) )
+      {
+        v24 = pFontArrus->CalcTextHeight(pClassNames[v23 + 20], &v52, 0, 0);
+        v62 += v24;
+        ++v61;
+        ++Str;
+      }
+    }
+    ++v21;
+  }
+  while ( v21 < v20->pNumPresenceButton + v20->pStartingPosActiveItem );
+  if ( !v61 )
+  {
+LABEL_64:
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], v58->pName, pClassNames[v58->uClass]);
+    strcat(pTmpBuf, "\n \n");
+    strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);
+    v18 = pTmpBuf;
+    v44 = 3;
+    v43 = pTmpBuf;
+    v42 = v57;
+    v41 = 0;
+    v40 = 0;
+    v39 = &v52;
+    goto LABEL_32;
+  }
+  if ( Str )
+  {
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], v63);
+    v52.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+  }
+  v63 = (signed int)(149 - v62) / v61;
+  if ( v63 > 32 )
+    v63 = 32;
+  result = v20->pStartingPosActiveItem;
+  v26 = (signed int)(149 - v61 * v63 - v62) / 2 - v63 / 2 + 162;
+  v62 = result;
+  v55 = v26;
+  if ( result < result + v20->pNumPresenceButton )
+  {
+    v61 = 2;
+    while ( 1 )
+    {
+      v27 = v20->GetControl(v62);
+      v28 = v27;
+      v29 = v27->uControlParam;
+      if ( v29 == 18 )
+        break;
+
+      __debugbreak();
+      //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+
+      //if ( *(&byte_4ED94C[37 * v58->uClass] + v29) && !*(&v58->uIntelligence + v29) )
+      {
+        v30 = pClassNames[v29 + 20];
+LABEL_55:
+        Str = v30;
+        v28->uY = v63 + v55;
+        v31 = pFontArrus->CalcTextHeight(v30, &v52, 0, 0);
+        v32 = v28->uY;
+        v28->uHeight = v31;
+        v33 = v32 + v31 - 1;
+        v28->uW = v33;
+        v55 = v33;
+        v34 = v57;
+        if ( pDialogueWindow->pCurrentPosActiveItem != v61 )
+          v34 = v56;
+        v52.DrawTitleText(pFontArrus, 0, v32, v34, Str, 3u);
+        goto LABEL_58;
+      }
+      v28->uW = 0;
+      v28->uHeight = 0;
+      v28->uY = 0;
+LABEL_58:
+      v35 = v20->pStartingPosActiveItem;
+      ++v62;
+      result = v20->pNumPresenceButton + v35;
+      ++v61;
+      if ( (signed int)v62 >= result )
+        return result;
+    }
+    v30 = pGlobalTXT_LocalizationStrings[400];
+    goto LABEL_55;
+  }
+  return result;
+}
+
+
+
+//----- (004B705E) --------------------------------------------------------
+int __cdecl sub_4B705E()
+{
+  GUIWindow *v0; // ebx@1
+  Player *v1; // esi@1
+  int v2; // edi@1
+  int result; // eax@4
+  GUIWindow *v4; // edi@6
+  void *v5; // eax@6
+  int v6; // eax@6
+  unsigned int v7; // eax@8
+  int v8; // ecx@8
+  unsigned int v9; // eax@9
+  int v10; // eax@11
+  int v11; // eax@12
+  GUIWindow *v12; // ecx@16
+  int v13; // edx@16
+  GUIButton *v14; // eax@19
+  GUIButton *v15; // edi@19
+  int v16; // eax@19
+  const char *v17; // eax@21
+  int v18; // eax@21
+  unsigned int v19; // ecx@21
+  int v20; // eax@21
+  unsigned __int16 v21; // ax@21
+  unsigned __int16 v22; // ST14_2@27
+  int v23; // eax@27
+  double v24; // st7@28
+  unsigned int v25; // ebx@28
+  DDM_DLV_Header *v26; // edi@29
+  int v27; // eax@31
+  int v28; // eax@32
+  unsigned int v29; // ecx@34
+  unsigned int v30; // edx@36
+  unsigned int v31; // edx@38
+  unsigned int v32; // edx@40
+  unsigned int v33; // edx@42
+  unsigned int v34; // edx@44
+  int v35; // edi@50
+  signed int v36; // eax@50
+  unsigned __int8 v37; // al@54
+  int v38; // ecx@54
+  GUIWindow *v39; // eax@56
+  unsigned __int8 v40; // al@61
+  GUIButton *v41; // edi@64
+  int v42; // esi@66
+  GUIWindow *v43; // ecx@66
+  int v44; // edi@66
+  int v45; // eax@68
+  signed int v46; // edi@69
+  int v47; // edi@71
+  GUIButton *v48; // eax@73
+  const char *v49; // edx@73
+  GUIButton *v50; // esi@73
+  int v51; // eax@73
+  unsigned int v52; // ecx@73
+  unsigned __int16 v53; // ax@73
+  char a1[100]; // [sp+10h] [bp-1B4h]@64
+  char Dest; // [sp+74h] [bp-150h]@66
+  char v56; // [sp+D8h] [bp-ECh]@66
+  GUIWindow v57; // [sp+13Ch] [bp-88h]@1
+  __int64 v58; // [sp+190h] [bp-34h]@1
+  __int64 v59; // [sp+198h] [bp-2Ch]@1
+  __int64 v60; // [sp+1A0h] [bp-24h]@1
+  GUIWindow *v61; // [sp+1ACh] [bp-18h]@6
+  unsigned int v62; // [sp+1B0h] [bp-14h]@8
+  unsigned __int8 v63; // [sp+1B7h] [bp-Dh]@64
+  int v64; // [sp+1B8h] [bp-Ch]@6
+  unsigned int v65; // [sp+1BCh] [bp-8h]@6
+  DDM_DLV_Header *v66; // [sp+1C0h] [bp-4h]@6
+
+  v0 = ptr_507BC0;
+  memcpy(&v57, ptr_507BC0, sizeof(v57));
+  v57.uFrameX = 483;
+  v57.uFrameWidth = 148;
+  v57.uFrameZ = 334;
+  HIDWORD(v58) = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  HIDWORD(v59) = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v1 = pPlayers[uActiveCharacter];
+  //v2 = pPlayers[uActiveCharacter]->_4B807C(p2DEvents_minus1__20[13 * (unsigned int)v0->ptr_1C]);
+  v2 = pPlayers[uActiveCharacter]->_4B807C(p2DEvents[(unsigned int)v0->ptr_1C - 1].fPriceMultiplier);
+  HIDWORD(v60) = v2;
+  if ( dword_F8B19C != 1 )
+  {
+    if ( dword_F8B19C != 10 )
+    {
+      if ( dword_F8B19C != 11 )
+      {
+        result = dword_F8B19C - 96;
+        if ( dword_F8B19C == 96 )
+        {
+          result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+          if ( result )
+          {
+            v4 = pDialogueWindow;
+            v61 = pDialogueWindow;
+            v5 = ptr_507BC0->ptr_1C;
+            v66 = 0;
+            //v65 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (signed int)v5] * 500.0);
+            v65 = (signed __int64)(p2DEvents[(signed int)v5 - 1].flt_24 * 500.0);
+            v6 = v1->GetMerchant();
+            v64 = (signed int)(v65 * (100 - v6)) / 100;
+            if ( v64 < (signed int)v65 / 3 )
+              v64 = (signed int)v65 / 3;
+            v7 = v4->pStartingPosActiveItem;
+            v8 = v7 + v4->pNumPresenceButton;
+            v65 = 0;
+            v62 = v7;
+            if ( (signed int)v7 >= v8 )
+              goto LABEL_78;
+            do
+            {
+              v9 = v4->GetControl(v62)->uControlParam - 36;
+              if ( byte_4ED970_skill_learn_ability_by_class_table[v1->uClass][v9] && !v1->pActiveSkills[v9] )
+              {
+                v10 = pFontArrus->CalcTextHeight(pSkillNames[v9], &v57, 0, 0);
+                v66 = (DDM_DLV_Header *)((char *)v66 + v10);
+                ++v65;
+              }
+              v11 = v4->pStartingPosActiveItem;
+              ++v62;
+            }
+            while ( (signed int)v62 < v4->pNumPresenceButton + v11 );
+            if ( v65 )
+            {
+              sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], v64);
+              v57.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+              v64 = (149 - (signed int)v66) / (signed int)v65;
+              if ( v64 > 32 )
+                v64 = 32;
+              v65 = (signed int)(149 - v65 * v64 - (int)v66) / 2 - v64 / 2 + 162;
+              v12 = v61;
+              result = v61->pStartingPosActiveItem;
+              v13 = result + v61->pNumPresenceButton;
+              v62 = v61->pStartingPosActiveItem;
+              if ( result < v13 )
+              {
+                v66 = (DDM_DLV_Header *)2;
+                while ( 1 )
+                {
+                  v14 = v12->GetControl(v62);
+                  v15 = v14;
+                  v16 = v14->uControlParam - 36;
+                  if ( !byte_4ED970_skill_learn_ability_by_class_table[v1->uClass][v16] || v1->pActiveSkills[v16] )
+                  {
+                    v15->uW = 0;
+                    v15->uHeight = 0;
+                    v15->uY = 0;
+                  }
+                  else
+                  {
+                    v17 = pSkillNames[v16];
+                    v15->uY = v64 + v65;
+                    HIDWORD(v60) = (uint32)v17;
+                    v18 = pFontArrus->CalcTextHeight(v17, &v57, 0, 0);
+                    v19 = v15->uY;
+                    v15->uHeight = v18;
+                    v20 = v19 + v18 - 1;
+                    v15->uW = v20;
+                    v65 = v20;
+                    v21 = WORD2(v59);
+                    if ( (DDM_DLV_Header *)pDialogueWindow->pCurrentPosActiveItem != v66 )
+                      v21 = WORD2(v58);
+                    v57.DrawTitleText(pFontArrus, 0, v19, v21, (const char *)HIDWORD(v60), 3u);
+                  }
+                  result = (int)v61;
+                  ++v62;
+                  v66 = (DDM_DLV_Header *)((char *)v66 + 1);
+                  if ( (signed int)v62 >= v61->pNumPresenceButton + v61->pStartingPosActiveItem )
+                    break;
+                  v12 = v61;
+                }
+              }
+            }
+            else
+            {
+LABEL_78:
+              sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], v1->pName, pClassNames[v1->uClass]);
+              strcat(pTmpBuf, "\n \n");
+              strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);
+              v22 = WORD2(v59);
+              v23 = pFontArrus->CalcTextHeight(pTmpBuf, &v57, 0, 0);
+              result = (int)v57.DrawTitleText(pFontArrus, 0, (174 - v23) / 2 + 138, v22, pTmpBuf, 3u);
+            }
+          }
+        }
+        return result;
+      }
+      //v24 = p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C];
+      v24 = p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].fPriceMultiplier;
+      v25 = 0;
+      if ( pParty->uNumGold >= (unsigned int)(signed __int64)v24 )
+      {
+        Party::TakeGold((signed __int64)v24);
+        v26 = &pOutdoor->ddm;
+        if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+          v26 = &pIndoor->dlv;
+        v27 = v26->uReputation;
+        v66 = v26;
+        if ( v27 > -5 )
+        {
+          v28 = v27 - 1;
+          v26->uReputation = v28;
+          if ( v28 < -5 )
+            v26->uReputation = -5;
+        }
+        v29 = uActiveCharacter;
+        if ( (unsigned __int8)byte_F8B1EF[uActiveCharacter] == pParty->uDaysPlayed % 7 )
+        {
+          if ( v26->uReputation <= -5 )
+          {
+            v30 = pParty->uDaysPlayed % 7 + 1;
+            LOBYTE(v30) = v30 | 0x80;
+            _42777D_CastSpell_UseWand_ShootArrow(12, uActiveCharacter - 1, v30, 48, 0);
+            v29 = uActiveCharacter;
+          }
+          if ( v26->uReputation <= -10 )
+          {
+            v31 = pParty->uDaysPlayed % 7 + 1;
+            LOBYTE(v31) = v31 | 0x80;
+            _42777D_CastSpell_UseWand_ShootArrow(50, v29 - 1, v31, 48, 0);
+            v29 = uActiveCharacter;
+            v26 = v66;
+          }
+          if ( v26->uReputation <= -15 )
+          {
+            v32 = pParty->uDaysPlayed % 7 + 1;
+            LOBYTE(v32) = v32 | 0x80;
+            _42777D_CastSpell_UseWand_ShootArrow(75, v29 - 1, v32, 48, 0);
+            v29 = uActiveCharacter;
+            v26 = v66;
+          }
+          if ( v26->uReputation <= -20 )
+          {
+            v33 = pParty->uDaysPlayed % 7 + 1;
+            LOBYTE(v33) = v33 | 0x80;
+            _42777D_CastSpell_UseWand_ShootArrow(86, v29 - 1, v33, 48, 0);
+            v29 = uActiveCharacter;
+            v26 = v66;
+          }
+          if ( v26->uReputation <= -25 )
+          {
+            v34 = pParty->uDaysPlayed % 7 + 1;
+            LOBYTE(v34) = v34 | 0x80;
+            _42777D_CastSpell_UseWand_ShootArrow(85, v29 - 1, v34, 48, 0);
+            v29 = uActiveCharacter;
+          }
+        }
+        ++byte_F8B1EF[v29];
+        v1->PlaySound(83, 0);
+        ShowStatusBarString(pGlobalTXT_LocalizationStrings[527], 2u);
+        goto LABEL_46;
+      }
+      goto LABEL_55;
+    }
+    result = v1->_4B6FF9();
+    if ( !result )
+      return result;
+    v25 = 0;
+    if ( pParty->uNumGold < v2 )
+    {
+LABEL_55:
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
+      HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 2);
+      goto LABEL_46;
+    }
+    Party::TakeGold(v2);
+    v35 = LODWORD(v1->pConditions[17]);
+    v59 = v1->pConditions[14];
+    v58 = v1->pConditions[15];
+    v60 = v1->pConditions[16];
+    v61 = (GUIWindow *)HIDWORD(v1->pConditions[17]);
+    memset(v1, 0, 0xA0u);
+    v1->sHealth = v1->GetMaxHealth();
+    v1->sMana = v1->GetMaxMana();
+    v36 = (signed int)ptr_507BC0->ptr_1C;
+    if ( v36 != 78 && (v36 <= 80 || v36 > 82) )
+    {
+      if ( (unsigned int)v61 | v35 )
+      {
+        v37 = LOBYTE(v1->field_1928);
+        v38 = v1->field_1924;
+        v1->uFace = v37;
+        v1->uVoiceID = v38;
+        ReloadPlayerPortraits(uActiveCharacter - 1, (char)v37);
+      }
+      goto LABEL_63;
+    }
+    v39 = v61;
+    if ( (unsigned int)v61 | v35 )
+    {
+      LODWORD(v1->pConditions[17]) = v35;
+    }
+    else
+    {
+      if ( !v60 && !v58 && !v59 )
+        goto LABEL_63;
+      v1->field_1928 = v1->uFace;
+      v1->field_1924 = v1->uVoiceID;
+      v1->SetCondition(0x11u, 1);
+      v1->uVoiceID = (v1->GetSexByVoice() != 0) + 23;
+      v40 = (v1->GetSexByVoice() != 0) + 23;
+      v1->uFace = v40;
+      ReloadPlayerPortraits(uActiveCharacter - 1, (char)v40);
+      LODWORD(v1->pConditions[17]) = LODWORD(pParty->uTimePlayed);
+      v39 = (GUIWindow *)HIDWORD(pParty->uTimePlayed);
+    }
+    HIDWORD(v1->pConditions[17]) = (int)v39;
+LABEL_63:
+    pAudioPlayer->PlaySound((SoundID)(SOUND_GoldReceived|0x2), -1, 0, -1, 0, 0, 0, 0);
+    v1->PlaySound(82, 0);
+    pOtherOverlayList->_4418B1(20, uActiveCharacter + 99, 0, 65536);
+LABEL_46:
+    result = pMessageQueue_50CBD0->uNumMessages;
+    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+      result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
+      *(&pMessageQueue_50CBD0->uNumMessages + result) = v25;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+    return result;
+  }
+  v63 = 1;
+  v41 = pDialogueWindow->GetControl(pDialogueWindow->pStartingPosActiveItem);
+  strcpy(a1, "");
+  v41->uHeight = 0;
+  v41->uY = 0;
+  if ( v1->_4B6FF9() )
+  {
+    sprintf(a1, "%s %d %s", pGlobalTXT_LocalizationStrings[104], HIDWORD(v60), pGlobalTXT_LocalizationStrings[97]);
+    v63 = 0;
+  }
+  strcpy(&Dest, pGlobalTXT_LocalizationStrings[68]);
+  strcpy(&v56, pGlobalTXT_LocalizationStrings[160]);
+  v42 = v63;
+  v43 = pDialogueWindow;
+  v44 = v63;
+  v66 = 0;
+  if ( v63 < pDialogueWindow->pNumPresenceButton )
+  {
+    v61 = (GUIWindow *)&a1[100 * v63];
+    do
+    {
+      v45 = pFontArrus->CalcTextHeight((const char *)v61, &v57, 0, 0);
+      v66 = (DDM_DLV_Header *)((char *)v66 + v45);
+      v43 = pDialogueWindow;
+      v61 = (GUIWindow *)((char *)v61 + 100);
+      ++v44;
+    }
+    while ( v44 < pDialogueWindow->pNumPresenceButton );
+  }
+  v46 = v43->pNumPresenceButton - v42;
+  v64 = (174 - (signed int)v66) / v46;
+  if ( v64 > 32 )
+    v64 = 32;
+  result = v43->pStartingPosActiveItem;
+  v47 = (174 - v64 * v46 - (signed int)v66) / 2 - v64 / 2 + 138;
+  v65 = v42 + result;
+  if ( v42 + result < result + v43->pNumPresenceButton )
+  {
+    v61 = (GUIWindow *)(v42 + 2);
+    v66 = (DDM_DLV_Header *)&a1[100 * v42];
+    do
+    {
+      v48 = v43->GetControl(v65);
+      v49 = (const char *)v66;
+      v50 = v48;
+      v48->uY = v64 + v47;
+      v51 = pFontArrus->CalcTextHeight(v49, &v57, 0, 0);
+      v52 = v50->uY;
+      v50->uHeight = v51;
+      v47 = v52 + v51 - 1;
+      v50->uW = v47;
+      v53 = WORD2(v59);
+      if ( (GUIWindow *)pDialogueWindow->pCurrentPosActiveItem != v61 )
+        v53 = WORD2(v58);
+      v57.DrawTitleText(pFontArrus, 0, v52, v53, (const char *)v66, 3u);
+      v43 = pDialogueWindow;
+      v66 = (DDM_DLV_Header *)((char *)v66 + 100);
+      v61 = (GUIWindow *)((char *)v61 + 1);
+      ++v65;
+      result = pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem;
+    }
+    while ( (signed int)v65 < result );
+  }
+  return result;
+}
+
+
+
+//----- (004B8F94) --------------------------------------------------------
+void *__cdecl sub_4B8F94()
+{
+  GUIWindow *v0; // edi@1
+  signed int v1; // ebp@1
+  int v2; // ebx@1
+  signed int v3; // esi@1
+  int v4; // eax@3
+  int v5; // ebx@3
+  int v6; // ecx@3
+  bool v7; // eax@5
+  bool v8; // ST1C_4@5
+  int v9; // eax@5
+  int v10; // eax@10
+  void *result; // eax@15
+  signed int v12; // [sp-4h] [bp-18h]@7
+
+  v0 = ptr_507BC0;
+  v1 = 0;
+  v2 = (int)&ptr_507BC0->ptr_1C;
+  v3 = (signed int)ptr_507BC0->ptr_1C;
+  //if ( _4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * (unsigned int)ptr_507BC0->ptr_1C]] )
+  if ( _4F063C_smthn_by_2da_uType[p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].uType] )
+  {
+    while ( v3 > 14 )
+    {
+      if ( v3 <= 28 )
+      {
+        v7 = v1 > 3;
+        v8 = v7;
+        v9 = 5 * (v7 + 2 * v3 - 30);
+        v3 = (signed int)v0->ptr_1C;
+        v5 = word_4F06D8[v9];
+        v6 = word_4F05AE[5 * (v8 + 2 * v3) + rand() % 4];
+        goto LABEL_13;
+      }
+      if ( v3 <= 41 )
+      {
+        v5 = word_4F07B6[v3];
+        v12 = 22;
+        goto LABEL_12;
+      }
+      if ( v3 <= 53 )
+      {
+        if ( v1 >= 6 )
+        {
+          v5 = word_4F07B6[v3 + 1];
+          v12 = 44;
+LABEL_12:
+          v6 = v12;
+LABEL_13:
+          pItemsTable->GenerateItem(v5, v6, (ItemGen *)&pParty->field_C59C[9 * (v1 + 12 * v3) + 724]);
+          v0 = ptr_507BC0;
+          v2 = (int)&ptr_507BC0->ptr_1C;
+          pParty->field_C59C[9 * (v1 + 12 * (unsigned int)ptr_507BC0->ptr_1C) + 729] = 1;
+          goto LABEL_14;
+        }
+        auto _a = (ItemGen *)&pParty->field_C59C[9 * (v1 + 12 * v3) + 724];
+        _a->Reset();
+        v2 = (int)&v0->ptr_1C;
+        v10 = rand();
+        v0 = ptr_507BC0;
+        pParty->field_C59C[9 * (v1 + 12 * *(int *)v2) + 724] = v10 % 32 + 740;
+      }
+LABEL_14:
+      v3 = *(int *)v2;
+      ++v1;
+      //if ( v1 >= (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents_minus1___00[26 * *(int *)v2]] )
+      if ( v1 >= (unsigned __int8)_4F063C_smthn_by_2da_uType[p2DEvents[*(int *)v2 - 1].uType] )
+        goto LABEL_15;
+    }
+    v4 = 5 * v3;
+    v3 = (signed int)v0->ptr_1C;
+    v5 = word_4F063E[v4];
+    v6 = word_4F063E[5 * v3 + rand() % 4 + 1];
+    goto LABEL_13;
+  }
+LABEL_15:
+  result = v0->ptr_1C;
+  *(int *)&pParty->field_16154[4 * (int)result] = 0;
+  return result;
+}
+
+
+//----- (004B6478) --------------------------------------------------------
+int __cdecl sub_4B6478()
+{
+  GUIWindow *v0; // ebx@1
+  Player *v1; // edi@1
+  unsigned int v2; // eax@1
+  signed int v3; // esi@1
+  int v4; // ebx@1
+  unsigned int v5; // esi@5
+  int v6; // edi@6
+  int result; // eax@13
+  GUIWindow *v8; // ebx@17
+  int v9; // eax@17
+  int v10; // ecx@17
+  unsigned int v11; // ecx@18
+  int v12; // eax@20
+  int v13; // eax@21
+  GUIButton *v14; // esi@27
+  int v15; // ecx@27
+  unsigned int v16; // eax@28
+  const char *v17; // ebx@29
+  int v18; // eax@29
+  unsigned int v19; // ecx@29
+  int v20; // eax@29
+  unsigned __int16 v21; // ax@29
+  unsigned __int16 v22; // ST14_2@36
+  int v23; // eax@36
+  const char *v24; // ST18_4@37
+  unsigned __int16 v25; // ST14_2@37
+  int v26; // eax@37
+  int v27; // [sp-4h] [bp-80h]@8
+  GUIWindow v28; // [sp+Ch] [bp-70h]@1
+  GUIWindow *v29; // [sp+60h] [bp-1Ch]@17
+  unsigned int v30; // [sp+64h] [bp-18h]@1
+  int v31; // [sp+68h] [bp-14h]@1
+  int v32; // [sp+6Ch] [bp-10h]@1
+  int v33; // [sp+70h] [bp-Ch]@17
+  int v34; // [sp+74h] [bp-8h]@17
+  int v35; // [sp+78h] [bp-4h]@17
+
+  v0 = ptr_507BC0;
+  memcpy(&v28, ptr_507BC0, sizeof(v28));
+  v1 = pPlayers[uActiveCharacter];
+  v28.uFrameX = 483;
+  v28.uFrameWidth = 148;
+  v28.uFrameZ = 334;
+  v30 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v31 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v2 = 52 * (unsigned int)v0->ptr_1C;
+  //v32 = (unsigned __int8)(((p2DEvents_minus1___00[v2 / 2] != 18) - 1) & 0x96) + 100;
+  v32 = (unsigned __int8)(((p2DEvents[(unsigned int)v0->ptr_1C - 1].uType != 18) - 1) & 0x96) + 100;
+  //v3 = (signed __int64)((double)v32 * p2DEvents_minus1__20[v2 / 4]);
+  v3 = (signed __int64)((double)v32 * p2DEvents[(unsigned int)v0->ptr_1C - 1].fPriceMultiplier);
+  v4 = v3 * (100 - v1->GetMerchant()) / 100;
+  v32 = v4;
+  if ( v4 < v3 / 3 )
+  {
+    v4 = v3 / 3;
+    v32 = v3 / 3;
+  }
+  if ( dword_F8B19C != 1 )
+  {
+    if ( sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+    {
+      v5 = 0;
+
+      __debugbreak();
+      //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+
+      if (false
+      //if ( !*(&byte_4ED94C[37 * v1->uClass / 3] + dword_F8B19C)
+        || (v6 = (int)(&v1->uIntelligence + dword_F8B19C), *(short *)v6) )
+      {
+        pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+      }
+      else
+      {
+        if ( pParty->uNumGold < v4 )
+        {
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
+          v27 = 4;
+        }
+        else
+        {
+          Party::TakeGold(v4);
+          *(short *)v6 = 1;
+          v27 = 2;
+        }
+        HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, v27);
+      }
+    }
+    else
+    {
+      v5 = 0;
+    }
+    result = pMessageQueue_50CBD0->uNumMessages;
+    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+      result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
+      *(&pMessageQueue_50CBD0->uNumMessages + result) = v5;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+    return result;
+  }
+  if ( !(unsigned __int16)_449B57_test_bit(
+                            (unsigned __int8 *)v1->field_152,
+                            word_4F0754[2 * (unsigned int)ptr_507BC0->ptr_1C]) )
+  {
+    v24 = pNPCTopics[171].pText;
+    v25 = v31;
+    v26 = pFontArrus->CalcTextHeight(pNPCTopics[171].pText, &v28, 0, 0);
+    v28.DrawTitleText(pFontArrus, 0, (212 - v26) / 2 + 101, v25, v24, 3u);
+    result = (int)pDialogueWindow;
+    pDialogueWindow->pNumPresenceButton = 0;
+    return result;
+  }
+  result = sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+  if ( !result )
+    return result;
+  v8 = pDialogueWindow;
+  v33 = 0;
+  v34 = 0;
+  v29 = pDialogueWindow;
+  v9 = pDialogueWindow->pStartingPosActiveItem;
+  v10 = v9 + pDialogueWindow->pNumPresenceButton;
+  v35 = pDialogueWindow->pStartingPosActiveItem;
+  if ( v9 >= v10 )
+    goto LABEL_40;
+  do
+  {
+    v11 = v8->GetControl(v35)->uControlParam - 36;
+    if ( byte_4ED970_skill_learn_ability_by_class_table[v1->uClass / 3][v11] && !v1->pActiveSkills[v11] )
+    {
+      v12 = pFontArrus->CalcTextHeight(pSkillNames[v11], &v28, 0, 0);
+      v33 += v12;
+      ++v34;
+    }
+    v13 = v8->pStartingPosActiveItem;
+    ++v35;
+  }
+  while ( v35 < v8->pNumPresenceButton + v13 );
+  if ( !v34 )
+  {
+LABEL_40:
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[544], v1->pName, pClassNames[v1->uClass]);
+    strcat(pTmpBuf, "\n \n");
+    strcat(pTmpBuf, pGlobalTXT_LocalizationStrings[528]);
+    v22 = v31;
+    v23 = pFontArrus->CalcTextHeight(pTmpBuf, &v28, 0, 0);
+    return (int)v28.DrawTitleText(pFontArrus, 0, (174 - v23) / 2 + 138, v22, pTmpBuf, 3u);
+  }
+  sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[401], v32);
+  v28.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+  v32 = (149 - v33) / v34;
+  if ( (149 - v33) / v34 > 32 )
+    v32 = 32;
+  result = v8->pStartingPosActiveItem;
+  v35 = result;
+  v34 = (149 - v34 * v32 - v33) / 2 - v32 / 2 + 162;
+  if ( result < result + v8->pNumPresenceButton )
+  {
+    v33 = 2;
+    do
+    {
+      v14 = v8->GetControl(v35);
+      v15 = v14->uControlParam - 36;
+      if ( byte_4ED970_skill_learn_ability_by_class_table[v1->uClass / 3][v15] )
+      {
+        v16 = 0;
+        if ( !v1->pActiveSkills[v15] )
+        {
+          v17 = pSkillNames[v15];
+          v14->uY = v32 + v34;
+          v18 = pFontArrus->CalcTextHeight(v17, &v28, 0, 0);
+          v19 = v14->uY;
+          v14->uHeight = v18;
+          v20 = v19 + v18 - 1;
+          v14->uW = v20;
+          v34 = v20;
+          v21 = v31;
+          if ( pDialogueWindow->pCurrentPosActiveItem != v33 )
+            v21 = v30;
+          v28.DrawTitleText(pFontArrus, 0, v19, v21, v17, 3u);
+          goto LABEL_34;
+        }
+      }
+      else
+      {
+        v16 = 0;
+      }
+      v14->uW = v16;
+      v14->uHeight = v16;
+      v14->uY = v16;
+LABEL_34:
+      v8 = v29;
+      ++v35;
+      ++v33;
+      result = v29->pNumPresenceButton + v29->pStartingPosActiveItem;
+    }
+    while ( v35 < result );
+  }
+  return result;
+}
+
+
+
+//----- (004B6943) --------------------------------------------------------
+void __cdecl TravelByTransport()
+{
+  GUIWindow *v0; // ebx@1
+  Player *v1; // esi@1
+  signed int v2; // edi@1
+  unsigned int v3; // eax@1
+  signed int v4; // ebx@1
+  char *v5; // esi@7
+  int v6; // eax@9
+  int v7; // eax@9
+  int v8; // eax@12
+  int v9; // edi@12
+  int v10; // edx@12
+  int v11; // ecx@12
+  signed int v12; // esi@13
+  signed int v13; // edi@14
+  DWORD v14; // eax@26
+  DWORD v15; // edi@26
+  GUIWindow *v16; // ebx@36
+  int v17; // esi@36
+  int v18; // eax@36
+  int v19; // ecx@36
+  int v20; // esi@36
+  int v21; // eax@36
+  void *v22; // eax@39
+  Player *v23; // esi@39
+  GUIButton *v24; // ebx@39
+  signed int v25; // eax@41
+  int v26; // esi@44
+  const char *v27; // eax@46
+  char *v28; // eax@62
+  int v29; // eax@62
+  unsigned int v30; // ecx@62
+  char *v31; // eax@63
+  char v32; // [sp-3Ch] [bp-2CCh]@62
+  int v33; // [sp-38h] [bp-2C8h]@62
+  int v34; // [sp-34h] [bp-2C4h]@62
+  int v35; // [sp-30h] [bp-2C0h]@62
+  int v36; // [sp-2Ch] [bp-2BCh]@62
+  int v37; // [sp-28h] [bp-2B8h]@62
+  int v38; // [sp-24h] [bp-2B4h]@62
+  int v39; // [sp-20h] [bp-2B0h]@62
+  int v40; // [sp-1Ch] [bp-2ACh]@62
+  int v41; // [sp-18h] [bp-2A8h]@62
+  int v42; // [sp-14h] [bp-2A4h]@62
+  char *v43; // [sp-10h] [bp-2A0h]@62
+  char *v44; // [sp-Ch] [bp-29Ch]@62
+  unsigned int v45; // [sp-8h] [bp-298h]@62
+  char *v46; // [sp-4h] [bp-294h]@62
+  const char *v47[5]; // [sp+0h] [bp-290h]@7
+  char v48; // [sp+14h] [bp-27Ch]@37
+  char v49; // [sp+78h] [bp-218h]@68
+  char v50; // [sp+DCh] [bp-1B4h]@68
+  char v51; // [sp+140h] [bp-150h]@68
+  char Dest; // [sp+1A4h] [bp-ECh]@36
+  GUIWindow v53; // [sp+208h] [bp-88h]@1
+  int v54; // [sp+25Ch] [bp-34h]@36
+  int v55; // [sp+260h] [bp-30h]@36
+  unsigned int v56; // [sp+264h] [bp-2Ch]@1
+  __int16 v57[2]; // [sp+268h] [bp-28h]@1
+  Player *v58; // [sp+26Ch] [bp-24h]@36
+  GUIWindow *v59; // [sp+270h] [bp-20h]@1
+  unsigned int v60; // [sp+274h] [bp-1Ch]@36
+  Player *v61; // [sp+278h] [bp-18h]@1
+  int v62; // [sp+27Ch] [bp-14h]@36
+  int v63; // [sp+280h] [bp-10h]@14
+  char *a1; // [sp+284h] [bp-Ch]@37
+  unsigned int s1; // [sp+288h] [bp-8h]@1
+  int v66; // [sp+28Ch] [bp-4h]@48
+
+  v0 = ptr_507BC0;
+  memcpy(&v53, ptr_507BC0, sizeof(v53));
+  v2 = 255;
+  v61 = pPlayers[uActiveCharacter];
+  v1 = v61;
+  v53.uFrameX = 483;
+  v53.uFrameWidth = 148;
+  v53.uFrameZ = 334;
+  *(int *)v57 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  v56 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  v3 = 52 * (unsigned int)v0->ptr_1C;
+  //v59 = (GUIWindow *)((((p2DEvents_minus1___00[v3 / 2] != 27) - 1) & 0xFFFFFFE7) + 50);
+  v59 = (GUIWindow *)((((p2DEvents[(unsigned int)v0->ptr_1C - 1].uType != 27) - 1) & 0xFFFFFFE7) + 50);
+  //v4 = (signed __int64)((double)(signed int)v59 * p2DEvents_minus1__20[v3 / 4]);
+  v4 = (signed __int64)((double)(signed int)v59 * p2DEvents[(unsigned int)v0->ptr_1C - 1].fPriceMultiplier);
+  s1 = v4 * (100 - v1->GetMerchant()) / 100;
+  if ( (signed int)s1 < v4 / 3 )
+    s1 = v4 / 3;
+  if ( dword_F8B19C == 1 )
+  {
+    if ( sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
+    {
+      v16 = pDialogueWindow;
+      v58 = (Player *)-1;
+      v62 = 0;
+      v17 = LOBYTE(pFontArrus->uFontHeight) - 3;
+      v59 = pDialogueWindow;
+      v54 = v17;
+      strcpy(&Dest, "");
+      sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[405], s1);
+      v18 = pFontArrus->CalcTextHeight(pTmpBuf2, &v53, 0, 0);
+      v19 = v16->pNumPresenceButton;
+      v20 = v18 + v17 + 146;
+      v21 = v16->pStartingPosActiveItem;
+      v63 = v20;
+      v55 = v20;
+      v60 = v21;
+      if ( v21 >= v21 + v19 )
+        goto LABEL_71;
+      s1 = 2;
+      a1 = &v48;
+      while ( 1 )
+      {
+        v47[1] = (const char *)v60;
+        v22 = ptr_507BC0->ptr_1C;
+        v23 = (Player *)(unsigned __int8)*(&_4F0D38_TravelInfo[4 * (signed int)v22] + v62);
+        v61 = (Player *)(unsigned __int8)*(&_4F0D38_TravelInfo[4 * (signed int)v22] + v62);
+        v24 = v16->GetControl(v60);
+        if ( v23 != v58
+          && ((signed int)s1 >= 6 ? (v25 = 1) : (v25 = (unsigned __int8)*(&byte_4F09B1[32 * (int)v23]
+                                                                        + pParty->uDaysPlayed % 7)),
+              v25
+           && ((v26 = 8 * (int)v23, !dword_4F09CC[v26])
+            || (unsigned __int16)_449B57_test_bit(pParty->_award_bits, LOWORD(dword_4F09CC[v26])))) )
+        {
+          v58 = v61;
+          v27 = (const char *)v56;
+          if ( pDialogueWindow->pCurrentPosActiveItem != s1 )
+            v27 = *(const char **)v57;
+          v47[1] = v27;
+          sprintf(a1, format_4E2DC8, v27);
+          v66 = (unsigned __int8)byte_4F09B8[v26 * 4];
+          if ( (signed int)ptr_507BC0->ptr_1C >= 63 )
+          {
+            if ( CheckHiredNPCSpeciality(8u) )
+              v66 -= 2;
+            if ( CheckHiredNPCSpeciality(9u) )
+              v66 -= 3;
+            v47[1] = (const char *)45;
+          }
+          else
+          {
+            v47[1] = (const char *)35;
+          }
+          if ( CheckHiredNPCSpeciality((unsigned int)v47[1]) )
+            v66 -= 2;
+          if ( CheckHiredNPCSpeciality(0x2Cu) )
+            --v66;
+          if ( v66 < 1 )
+            v66 = 1;
+          if ( v61 != (Player *)v2 )
+          {
+            memcpy(&v32, (char *)&pMapStats + 68 * (unsigned __int8)byte_4F09B0[v26 * 4], 0x44u);
+            sprintf(
+              pTmpBuf,
+              pGlobalTXT_LocalizationStrings[404],
+              v66,
+              *(int *)&v32,
+              v33,
+              v34,
+              v35,
+              v36,
+              v37,
+              v38,
+              v39,
+              v40,
+              v41,
+              v42,
+              v43,
+              v44,
+              v45,
+              v46,
+              *(_QWORD *)v47);
+            strcat(a1, pTmpBuf);
+            v28 = a1;
+            a1 += 100;
+            ++v62;
+            ++s1;
+            strcat(v28, "\n \n");
+            v24->uY = v63;
+            v29 = pFontArrus->CalcTextHeight(pTmpBuf, &v53, 0, 0);
+            v30 = v24->uY;
+            v24->uHeight = v29;
+            v2 = 255;
+            v24->uW = v30 + v29 - 1;
+            v63 += v54 + v29;
+          }
+        }
+        else
+        {
+          v31 = a1;
+          ++v62;
+          ++s1;
+          a1 += 100;
+          strcpy(v31, "");
+          if ( v24 )
+          {
+            v24->uW = 0;
+            v24->uHeight = 0;
+            v24->uY = 0;
+          }
+        }
+        ++v60;
+        if ( (signed int)v60 >= v59->pNumPresenceButton + v59->pStartingPosActiveItem )
+          break;
+        v16 = v59;
+      }
+      if ( v63 != v55 )
+      {
+        v47[1] = &Dest;
+        v47[0] = &v51;
+        v46 = &v50;
+        v45 = (unsigned int)&v49;
+        v44 = &v48;
+        v43 = pTmpBuf2;
+        sprintf(pTmpBuf, "%s\n \n%s%s%s%s%s", pTmpBuf2, &v48, &v49, &v50, &v51, &Dest);
+        v53.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf, 3u);
+      }
+      else
+      {
+LABEL_71:
+        v47[1] = (const char *)3;
+        v47[0] = pGlobalTXT_LocalizationStrings[561];
+        v46 = *(char **)v57;
+        v45 = (174 - pFontArrus->CalcTextHeight(pGlobalTXT_LocalizationStrings[561], &v53, 0, 0)) / 2 + 138;
+        v53.DrawTitleText(pFontArrus, 0, v45, (unsigned __int16)v46, v47[0], (unsigned int)v47[1]);
+        pAudioPlayer->StopChannels(-1, -1);
+      }
+    }
+  }
+  else
+  {
+    if ( dword_F8B19C > 104 && dword_F8B19C <= 108 )
+    {
+      if ( pParty->uNumGold < s1 )
+      {
+        ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
+        HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 3);
+        if ( (signed int)pMessageQueue_50CBD0->uNumMessages >= 40 )
+          return;
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
+        goto LABEL_33;
+      }
+      Party::TakeGold(s1);
+      v47[1] = (const char *)7;
+      v5 = &byte_4F09B0[32 * (unsigned __int8)*(&byte_4F0CCF[4 * (unsigned int)ptr_507BC0->ptr_1C] + dword_F8B19C)];
+      if ( v5[pParty->uDaysPlayed % 7 + 1] )
+      {
+        if ( _strcmpi(pCurrentMapName, pMapStats->pInfos[(unsigned __int8)*v5].pFilename) )
+        {
+          SaveGame(1, 0);
+          strcpy(pCurrentMapName, pMapStats->pInfos[(unsigned __int8)*v5].pFilename);
+          v8 = *((int *)v5 + 6);
+          v9 = *((int *)v5 + 5);
+          v10 = *((int *)v5 + 4);
+          dword_6BE364_game_settings_1 |= 1u;
+          _5B65B8_npcdata_hiword_house_or_other = 0;
+          dword_5B65BC = 0;
+          _5B65B4_npcdata_loword_house_or_other = v8;
+          v11 = *((int *)v5 + 3);
+          uGameState = 2;
+          _5B65A8_npcdata_uflags_or_other = v11;
+          _5B65AC_npcdata_fame_or_other = v10;
+          _5B65B0_npcdata_rep_or_other = v9;
+          dword_5B65C0 = v11 | v10 | v9 | v8;
+        }
+        else
+        {
+          v6 = *((int *)v5 + 3);
+          pParty->sRotationX = 0;
+          pParty->vPosition.x = v6;
+          v7 = *((int *)v5 + 4);
+          pIndoorCamera->sRotationY = 0;
+          pParty->uFlags |= 2u;
+          pParty->vPosition.y = v7;
+          pParty->vPosition.z = *((int *)v5 + 5);
+          pParty->uFallStartY = pParty->vPosition.z;
+          pParty->sRotationY = *((int *)v5 + 6);
+        }
+        HousePlaySomeSound((unsigned int)ptr_507BC0->ptr_1C, 2);
+        v12 = (unsigned __int8)v5[8];
+        if ( (signed int)ptr_507BC0->ptr_1C >= 63 )
+        {
+          v63 = 72;
+          v13 = 2500;
+          if ( CheckHiredNPCSpeciality(8u) )
+            v12 -= 2;
+          if ( CheckHiredNPCSpeciality(9u) )
+            v12 -= 3;
+          v47[1] = (const char *)45;
+        }
+        else
+        {
+          v63 = 71;
+          v13 = 1500;
+          v47[1] = (const char *)35;
+        }
+        if ( CheckHiredNPCSpeciality((unsigned int)v47[1]) )
+          v12 -= 2;
+        if ( CheckHiredNPCSpeciality(0x2Cu) )
+          --v12;
+        if ( v12 < 1 )
+          v12 = 1;
+        RestAndHeal(1440 * v12);
+        v61->PlaySound(v63, 0);
+        v14 = GetTickCount();
+        v15 = v14 + v13;
+        if ( v15 < v14 )
+          v15 = v14;
+        while ( GetTickCount() < v15 )
+          sqrt(3.1415926);
+        while ( sub_4BD8B5() )
+          ;
+        if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+        {
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+LABEL_33:
+          *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+          ++pMessageQueue_50CBD0->uNumMessages;
+          return;
+        }
+      }
+      else
+      {
+        dword_F8B19C = 1;
+        pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+      }
+    }
+  }
+}
+
+
+
+
+
+//----- (00405CFF) --------------------------------------------------------
+void stru262_TurnBased::End(bool bPlaySound)
+{
+  stru262_TurnBased *v2; // edi@1
+  int v3; // ebx@1
+  int v4; // esi@1
+  unsigned __int8 v5; // zf@1
+  unsigned __int8 v6; // sf@1
+  TurnBased_QueueElem *v7; // ecx@2
+  unsigned __int16 *pAttributes; // ecx@7
+  size_t v9; // edx@7
+  unsigned __int16 v10; // ax@8
+  TurnBased_QueueElem *v11; // ebx@12
+  ObjectType objType; // eax@13
+  int objID; // esi@13
+  int v14; // [sp+Ch] [bp-4h]@11
+
+  v2 = this;
+  v3 = 0;
+  v4 = 0;
+  v5 = this->uActorQueueSize == 0;
+  v6 = this->uActorQueueSize < 0;
+  this->field_4 = 0;
+  if ( !(v6 | v5) )
+  {
+    v7 = this->pQueue;
+    do
+    {
+      if ( (v7->uPackedID & 7) == OBJECT_Actor )
+        LOBYTE(pActors[v7->uPackedID >> 3].uAttributes) &= 0x7Fu;
+      ++v4;
+      ++v7;
+    }
+    while ( v4 < v2->uActorQueueSize );
+  }
+  if ( (signed int)uNumLayingItems > 0 )
+  {
+    pAttributes = &pLayingItems[0].uAttributes;
+    v9 = uNumLayingItems;
+    do
+    {
+      v10 = *pAttributes;
+      if ( *pAttributes & 4 )
+      {
+        LOBYTE(v10) = v10 & 0xFB;
+        *pAttributes = v10;
+      }
+      pAttributes += 56;
+      --v9;
+    }
+    while ( v9 );
+  }
+  v14 = 0;
+  if ( v2->uActorQueueSize > 0 )
+  {
+    v11 = v2->pQueue;
+    do
+    {
+      objType = (ObjectType)(v11->uPackedID & 7);
+      objID = v11->uPackedID >> 3;
+      if ( objType == OBJECT_Player )
+      {
+        pPlayers[objID + 1]->uTimeToRecovery = (signed __int64)((double)v11->field_4 * 2.133333333333333);
+      }
+      else
+      {
+        if ( objType == OBJECT_Actor )
+          pActors[objID].pMonsterInfo.uRecoveryTime = (signed __int64)((double)v11->field_4 * 2.133333333333333);
+      }
+      ++v14;
+      ++v11;
+    }
+    while ( v14 < v2->uActorQueueSize );
+    v3 = 0;
+  }
+  pAudioPlayer->StopChannels(-1, -1);
+  if ( bPlaySound != v3 )
+    pAudioPlayer->PlaySound((SoundID)(SOUND_GoldReceived|SOUND_EnteringAHouse), v3, v3, -1, v3, v3, v3, v3);
+  pTurnEngine->field_18 &= 0xFFFFFFFDu;
+  pEventTimer->StopGameTime();
+  dword_50C994 = v3;
+  dword_50C998_turnbased_icon_1A = v3;
+}
+// 50C994: using guessed type int dword_50C994;
+// 50C998: using guessed type int dword_50C998_turnbased_icon_1A;
+
+//----- (00405E14) --------------------------------------------------------
+void stru262_TurnBased::_405E14()
+{
+  stru262_TurnBased *v1; // esi@1
+  int v2; // ecx@1
+  SpellBuff *v3; // edi@2
+  Actor *v4; // ebx@3
+  signed int v5; // edx@20
+  AIDirection *v6; // esi@21
+  int v7; // eax@21
+  int v8; // eax@21
+  int v9; // eax@22
+  int v10; // eax@23
+  int v11; // eax@37
+  int v12; // eax@44
+  AIDirection a3; // [sp+4h] [bp-68h]@21
+  AIDirection v14; // [sp+20h] [bp-4Ch]@21
+  AIDirection v15; // [sp+3Ch] [bp-30h]@21
+  SpellBuff *v16; // [sp+58h] [bp-14h]@2
+  int v17; // [sp+5Ch] [bp-10h]@6
+  stru262_TurnBased *v18; // [sp+60h] [bp-Ch]@1
+  int v19; // [sp+64h] [bp-8h]@8
+  unsigned int v20; // [sp+68h] [bp-4h]@1
+
+  v1 = this;
+  v2 = 0;
+  v18 = v1;
+  v20 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v3 = pActors[0].pActorBuffs;
+    v16 = pActors[0].pActorBuffs;
+    do
+    {
+      v4 = (Actor *)((char *)&v3[-13] - 4);
+      if ( SHIDWORD(v3[3].uExpireTime) < v2 || SHIDWORD(v3[3].uExpireTime) <= v2 && LODWORD(v3[3].uExpireTime) <= v2 )
+        v17 = v2;
+      else
+        v17 = 1;
+      v19 = v2;
+      do
+      {
+        if ( v19 != 10 )
+        {
+          v3->_4585CA(pParty->uTimePlayed);
+          v2 = 0;
+        }
+        ++v19;
+        ++v3;
+      }
+      while ( v19 < 22 );
+      if ( v17 != v2
+        && SHIDWORD(v4->pActorBuffs[3].uExpireTime) <= v2
+        && (SHIDWORD(v4->pActorBuffs[3].uExpireTime) < v2 || LODWORD(v4->pActorBuffs[3].uExpireTime) <= v2) )
+        v4->uActorHeight = pMonsterList->pMonsters[v4->pMonsterInfo.uID - 1].uMonsterHeight;
+      if ( !(v4->uAttributes & 0x80) )
+      {
+        if ( !v4->pActorBuffs[5].uExpireTime )
+        {
+          if ( !v4->pActorBuffs[6].uExpireTime )
+          {
+            v5 = v4->uCurrentActionLength;
+            v4->uCurrentActionTime += pMiscTimer->uTimeElapsed;
+            if ( (signed int)v4->uCurrentActionTime >= v5 )
+            {
+              v17 = dword_4F6E08[v20];
+              v6 = Actor::GetDirectionInfo(8 * v20 | 3, v17, &a3, v2);
+              v7 = v4->uAIState;
+              memcpy(&v15, v6, sizeof(v15));
+              v8 = v7 - 4;
+              memcpy(&v14, &v15, sizeof(v14));
+              if ( v8 )
+              {
+                v9 = v8 - 1;
+                if ( v9 )
+                {
+                  v10 = v9 - 6;
+                  if ( v10 )
+                  {
+                    if ( v10 != 8 )
+                      Actor::_403F58(v20, v17, 32, &v14);
+                  }
+                }
+              }
+              else
+              {
+                v4->uCurrentActionTime = 0;
+                v4->uCurrentActionLength = 0;
+                v4->uAIState = Dead;
+                v4->UpdateAnimation();
+              }
+              v1 = v18;
+              v2 = 0;
+            }
+          }
+        }
+      }
+      ++v20;
+      v3 = (SpellBuff *)((char *)v16 + 836);
+      v16 = (SpellBuff *)((char *)v16 + 836);
+    }
+    while ( (signed int)v20 < (signed int)uNumActors );
+  }
+  if ( v1->field_4 == 1 )
+  {
+    v12 = v1->field_8;
+    if ( v12 == 64 )
+    {
+      v1->_406A63();
+    }
+    else
+    {
+      if ( v12 > v2 )
+      {
+        v1->_406B9F();
+      }
+      else
+      {
+        v1->_406AFE();
+        v1->field_10 = 100;
+      }
+    }
+    v1->field_8 -= pEventTimer->uTimeElapsed;
+    return;
+  }
+  if ( v1->field_4 == 2 )
+  {
+    if ( !(v1->field_18 & 1) )
+    {
+      v11 = v1->field_10;
+      if ( v11 == 100 )
+      {
+        v1->StartTurn();
+LABEL_39:
+        v1->_40652A();
+        return;
+      }
+      if ( v11 > v2 || v1->pQueue[0].field_4 <= v2 )
+      {
+        v1->_4065B0();
+        goto LABEL_39;
+      }
+    }
+    v1->NextTurn();
+    return;
+  }
+  if ( v1->field_4 == 3 )
+  {
+    if ( v1->uActionPointsLeft <= v2 || v1->field_18 & 8 )
+    {
+      v1->field_18 &= 0xFFFFFFF7u;
+      v1->field_4 = 1;
+      v1->field_8 = 64;
+    }
+    else
+    {
+      v1->_406FA8();
+    }
+  }
+}
+
+
+
+
+//----- (0043FDED) --------------------------------------------------------
+void PrepareActorRenderList_BLV()
+{
+  RenderBillboard *v0; // esi@0
+  unsigned __int16 v3; // ax@3
+  unsigned int v4; // eax@5
+  unsigned __int16 v5; // cx@5
+  int v6; // esi@5
+  unsigned int v7; // eax@7
+  int v8; // eax@10
+  SpriteFrame *v9; // eax@16
+  SpriteFrame *v10; // ebx@18
+  //int *v11; // eax@18
+  int v12; // ecx@28
+  //IndoorCameraD3D **v14; // eax@36
+  double v15; // st7@36
+  float v16; // eax@36
+  //double v17; // ST30_8@36
+  signed __int64 v18; // qtt@36
+  int v19; // ST5C_4@36
+  signed __int64 v20; // qtt@37
+  int v21; // ST5C_4@37
+  signed __int16 v22; // cx@39
+  int v23; // ST50_4@40
+  signed int v24; // ecx@40
+  int v25; // edx@44
+  __int16 v26; // ax@44
+  //MonsterDesc *v27; // edx@44
+  //int v28; // ecx@44
+  unsigned __int8 v29; // zf@44
+  unsigned __int8 v30; // sf@44
+  unsigned int v31; // [sp-8h] [bp-5Ch]@15
+  int v32; // [sp+1Ch] [bp-38h]@5
+  int a3; // [sp+20h] [bp-34h]@5
+  int a2; // [sp+24h] [bp-30h]@5
+  int a1a; // [sp+28h] [bp-2Ch]@5
+  __int16 a5; // [sp+2Ch] [bp-28h]@5
+  int a5a; // [sp+2Ch] [bp-28h]@36
+  int a5b; // [sp+2Ch] [bp-28h]@40
+  __int16 v41; // [sp+3Ch] [bp-18h]@18
+  int a6; // [sp+40h] [bp-14h]@34
+  int v43; // [sp+44h] [bp-10h]@34
+  int z; // [sp+48h] [bp-Ch]@32
+  signed int y; // [sp+4Ch] [bp-8h]@32
+  int x; // [sp+50h] [bp-4h]@32
+
+  for (uint i = 0; i < uNumActors; ++i)
+  {
+    auto p = pActors + i;
+
+    if (p->uAIState == Removed ||
+        p->uAIState == Disabled)
+      continue;
+
+    a5 = p->uSectorID;
+    a2 = p->vPosition.y;
+    a1a = p->vPosition.x;
+    a3 = p->vPosition.z;
+    v4 = stru_5C6E00->Atan2(a1a - pBLVRenderParams->vPartyPos.x, a2 - pBLVRenderParams->vPartyPos.y);
+    LOWORD(v0) = p->uYawAngle;
+    v5 = p->uCurrentActionAnimation;
+    v6 = ((signed int)((char *)v0 + ((signed int)stru_5C6E00->uIntegerPi >> 3) - v4 + stru_5C6E00->uIntegerPi) >> 8) & 7;
+    v32 = v6;
+    if ( pParty->bTurnBasedModeOn )
+    {
+      if ( v5 == 1 )
+      {
+        v7 = pMiscTimer->uTotalGameTimeElapsed;
+        goto LABEL_10;
+      }
+    }
+    else
+    {
+      if ( v5 == 1 )
+      {
+        v7 = pBLVRenderParams->field_0_timer_;
+LABEL_10:
+        v8 = i * 32 + v7;
+        goto LABEL_12;
+      }
+    }
+    v8 = p->uCurrentActionTime;
+LABEL_12:
+    if (p->pActorBuffs[5].uExpireTime > 0i64 || p->pActorBuffs[6].uExpireTime > 0i64 )
+      v8 = 0;
+    v31 = p->pSpriteIDs[v5];
+    if (p->uAIState == Resurrected)
+      v9 = pSpriteFrameTable->GetFrameBy_x(v31, v8);
+    else
+      v9 = pSpriteFrameTable->GetFrame(v31, v8);
+    v41 = 0;
+    v10 = v9;
+    //v11 = (int *)v9->uFlags;
+    if (v9->uFlags & 2)
+      v41 = 2;
+    if (v9->uFlags & 0x40000)
+      v41 |= 0x40u;
+    if (v9->uFlags & 0x20000)
+      LOBYTE(v41) = v41 | 0x80;
+    v0 = (RenderBillboard *)(256 << v6);
+    if ( (unsigned int)v0 & v9->uFlags)
+      v41 |= 4u;
+    if ( v10->uGlowRadius )
+    {
+      //LOBYTE(v11) = byte_4E94D3;
+      pMobileLightsStack->AddLight(
+        a1a,
+        a2,
+        a3,
+        a5,
+        v10->uGlowRadius,
+        0xFFu,
+        0xFFu,
+        0xFFu,
+        byte_4E94D3);
+    }
+    v12 = 0;
+    if ( pBspRenderer->uNumVisibleNotEmptySectors <= 0 )
+      continue;
+    while (pBspRenderer->pVisibleSectorIDs_toDrawDecorsActorsEtcFrom[v12] != p->uSectorID)
+    {
+      ++v12;
+      if ( v12 >= pBspRenderer->uNumVisibleNotEmptySectors )
+        goto _continue;
+    }
+    if ( !pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(a1a, a2, a3, &x, &y, &z, 1)
+      || (v0 = (RenderBillboard *)abs(x), (signed int)v0 < abs(y)) )
+      continue;
+    pGame->pIndoorCameraD3D->Project(x, y, z, &v43, &a6);
+
+    v0 = &pBillboardRenderList[uNumBillboardsToDraw];
+    if (uNumBillboardsToDraw >= 500)
+      break;
+    ++uNumBillboardsToDraw;
+    ++uNumSpritesDrawnThisFrame;
+    p->uAttributes |= 8u;
+    v29 = pRenderer->pRenderD3D == 0;
+    v0->uHwSpriteID = v10->pHwSpriteIDs[v32];
+    v0->uPalette = v10->uPaletteIndex;
+    v0->uIndoorSectorID = a5;
+    if ( v29 )
+    {
+      LODWORD(v20) = pBLVRenderParams->field_40 << 16;
+      HIDWORD(v20) = pBLVRenderParams->field_40 >> 16;
+      v21 = v20 / x;
+      v0->field_0 = (unsigned __int64)(v10->scale * v20 / x) >> 16;
+      a5a = (unsigned __int64)(v10->scale * (signed __int64)v21) >> 16;
+    }
+    else
+    {
+      //v14 = &pGame->pIndoorCameraD3D;
+      v0->fov_x = pGame->pIndoorCameraD3D->fov_x;
+      v15 = pGame->pIndoorCameraD3D->fov_y;
+      v16 = v0->fov_x;
+      v0->fov_y = v15;
+      //v17 = v16 + 6.7553994e15;
+      LODWORD(v18) = 0;
+      HIDWORD(v18) = floorf(v16 + 0.5f);
+      v19 = v18 / x;
+      v0->field_0 = (unsigned __int64)(v10->scale * v18 / x) >> 16;
+      a5a = (unsigned __int64)(v10->scale * (signed __int64)v19) >> 16;
+    }
+    v0->field_4 = a5a;
+    if ( (signed __int64)p->pActorBuffs[3].uExpireTime <= 0 )
+    {
+      if ( (signed __int64)p->pActorBuffs[10].uExpireTime > 0 )
+      {
+        a5b = (unsigned __int64)(pGame->pStru6Instance->_4A806F(p) * (signed __int64)v0->field_4) >> 16;
+        goto LABEL_43;
+      }
+    }
+    else
+    {
+      v22 = p->pActorBuffs[3].uPower;
+      if ( v22 )
+      {
+        v23 = (unsigned __int64)(65536 / (unsigned __int16)v22 * (signed __int64)v0->field_0) >> 16;
+        v24 = p->pActorBuffs[3].uPower;
+        v0->field_0 = v23;
+        a5b = (unsigned __int64)(65536 / v24 * (signed __int64)v0->field_4) >> 16;
+LABEL_43:
+        v0->field_4 = a5b;
+        goto LABEL_44;
+      }
+    }
+LABEL_44:
+    HIWORD(v25) = HIWORD(x);
+    v0->some_x = a1a;
+    v0->some_y = a2;
+    v0->some_z = a3;
+    v0->uScreenSpaceX = v43;
+    v0->uScreenSpaceY = a6;
+    LOWORD(v25) = 0;
+    LOBYTE(v26) = v41;
+    v0->sZValue = v25 + (8 * i | 3);
+    //v27 = pMonsterList->pMonsters;
+    //v28 = p->pMonsterInfo.uID;
+    v29 = HIDWORD(p->pActorBuffs[5].uExpireTime) == 0;
+    v30 = HIDWORD(p->pActorBuffs[5].uExpireTime) < 0;
+    v0->field_1E = v41;
+    v0->pSpriteFrame = v10;
+    v0->uTintColor = pMonsterList->pMonsters[p->pMonsterInfo.uID - 1].uTintColor;
+    if ( !v30 && (!(v30 | v29) || LODWORD(p->pActorBuffs[5].uExpireTime)) )
+    {
+      HIBYTE(v26) = HIBYTE(v41) | 1;
+      v0->field_1E = v26;
+    }
+    
+_continue:
+    ;
+  }
+}
+
+
+
+
+
+//----- (00444732) --------------------------------------------------------
+char *_444732_GetEventHintString(unsigned int uEventID)
+{
+  signed int v1; // edx@1
+  char *v2; // eax@2
+  int v3; // ebx@4
+  int v4; // esi@4
+  char *result; // eax@6
+  int v6; // eax@9
+  char *i; // esi@11
+  int v8; // edx@12
+
+  v1 = 0;
+  if ( (signed int)uLevelEVT_NumEvents <= 0 )
+  {
+LABEL_6:
+    result = 0;
+  }
+  else
+  {
+    v2 = (char *)&pLevelEVT_Events[0].uEventOffsetInEVT;
+    while ( 1 )
+    {
+      if ( *((int *)v2 - 2) == uEventID )
+      {
+        v3 = *(int *)v2;
+        v4 = *((int *)v2 + 3);
+        if ( pLevelEVT[*(int *)v2 + 4] == 4 )
+          break;
+      }
+      ++v1;
+      v2 += 12;
+      if ( v1 >= (signed int)uLevelEVT_NumEvents )
+        goto LABEL_6;
+    }
+    if ( pLevelEVT[v4 + 4] == 2 )
+    {
+      v6 = (unsigned __int8)pLevelEVT[v4 + 5]
+         + (((unsigned __int8)pLevelEVT[v4 + 6]
+           + (((unsigned __int8)pLevelEVT[v4 + 7] + ((unsigned __int8)pLevelEVT[v4 + 8] << 8)) << 8)) << 8);
+LABEL_10:
+      //result = (char *)p2DEvents_minus1_::04[13 * v6];
+      result = (char *)p2DEvents[v6 - 1].pName;
+    }
+    else
+    {
+      for ( i = (char *)pLevelEVT_Events + 4 * (3 * v1 + 3); *(int *)i == uEventID; i += 12 )
+      {
+        v8 = *((int *)i + 2);
+        if ( pLevelEVT[v8 + 4] == 2 )
+        {
+          v6 = (unsigned __int8)pLevelEVT[v8 + 5]
+             + (((unsigned __int8)pLevelEVT[v8 + 6]
+               + (((unsigned __int8)pLevelEVT[v8 + 7] + ((unsigned __int8)pLevelEVT[v8 + 8] << 8)) << 8)) << 8);
+          if ( (unsigned int)v6 < 0x258 )
+            goto LABEL_10;
+        }
+      }
+      result = &pLevelStr[pLevelStrOffsets[(unsigned __int8)pLevelEVT[v3 + 5]]];
+    }
+  }
+  return result;
+}
+
+
+
+
+//----- (00444839) --------------------------------------------------------
+unsigned int __fastcall sub_444839_move_map(unsigned int a1, int a2, int x, int y, int z, int directiony, int directionx, int a8, const char *pLocationName)
+{
+  unsigned int v9; // ebx@1
+  int v10; // edi@1
+  signed int v11; // eax@1
+  unsigned int v12; // eax@6
+  const char *v13; // ST0C_4@6
+  unsigned int v14; // eax@8
+  const char *v15; // eax@14
+  unsigned int v16; // eax@16
+  unsigned int result; // eax@26
+  const char *v18; // [sp-8h] [bp-40h]@9
+  const char *v19; // [sp-4h] [bp-3Ch]@2
+  char *v20; // [sp-4h] [bp-3Ch]@9
+  const char *v21; // [sp-4h] [bp-3Ch]@11
+  char pContainer[40]; // [sp+Ch] [bp-2Ch]@1
+  unsigned int v23; // [sp+34h] [bp-4h]@1
+
+  v9 = a1;
+  v10 = a2;
+  v23 = IndoorLocation::GetLocationIndex(pLocationName);
+  dword_59117C_teleportx = x;
+  dword_591178_teleporty = y;
+  dword_591174_teleportz = z;
+  dword_591170_teleport_directiony = directiony;
+  dword_59116C_teleport_directionx = directionx;
+  dword_591168_teleport_speedz = a8;
+  dword_591164_teleport_map_name = (char *)pLocationName;
+  uCurrentHouse_Animation = v9;
+  pEventTimer->Pause();
+  pAudioPlayer->StopChannels(-1, -1);
+  v11 = const_2();
+  sprintf(pContainer, "evt%02d", v11);
+  if ( pParty->uAlignment )
+  {
+    if ( pParty->uAlignment != 2 )
+      goto LABEL_6;
+    v19 = "-c";
+  }
+  else
+  {
+    v19 = "-b";
+  }
+  strcat(pContainer, v19);
+LABEL_6:
+  v12 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+  v13 = pHouse_ExitPictures[v10];
+  pTexture_Dialogue_Background = &pIcons_LOD->pTextures[v12];
+  pTexture_outside = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v13, TEXTURE_16BIT_PALETTE)];
+  if ( v9 )
+  {
+    if ( !v23 )
+      //pVideoPlayer->_4BF28F(pAnimatedRooms[p2DEvents_minus1___02[26 * v9]].field_0, 1u);
+      pVideoPlayer->_4BF28F(pAnimatedRooms[p2DEvents[v9 - 1].uAnimationID].field_0, 1u);
+  }
+  else
+  {
+    if ( !v23 )
+    {
+      v14 = pMapStats->GetMapInfo(pCurrentMapName);
+      if ( v14 )
+      {
+        v20 = pMapStats->pInfos[v14].pName;
+        v18 = pGlobalTXT_LocalizationStrings[410];
+LABEL_10:
+        sprintf(byte_591098, v18, v20);
+        goto LABEL_20;
+      }
+      v21 = pGlobalTXT_LocalizationStrings[79];
+      goto LABEL_19;
+    }
+  }
+  v15 = pLocationName;
+  if ( *pLocationName == 48 )
+    v15 = pCurrentMapName;
+  v16 = pMapStats->GetMapInfo(v15);
+  if ( v16 )
+  {
+    v20 = pMapStats->pInfos[v16].pName;
+    v18 = pGlobalTXT_LocalizationStrings[411];
+    goto LABEL_10;
+  }
+  v21 = pGlobalTXT_LocalizationStrings[73];
+LABEL_19:
+  strcpy(byte_591098, v21);
+LABEL_20:
+  pDialogueWindow = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)26, 0, (int)byte_591098);
+  //if ( BYTE1(pAnimatedRooms[p2DEvents_minus1___02[26 * v9]].field_C) )
+  if ( BYTE1(pAnimatedRooms[p2DEvents[v9 - 1].uAnimationID].field_C) )
+    HousePlaySomeSound(v9, 1);
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor && uActiveCharacter && pParty->uFlags & 0x30 )
+    pPlayers[uActiveCharacter]->PlaySound(47, 0);
+  result = v23;
+  if ( v23 )
+    uCurrentHouse_Animation = v23;
+  return result;
+}
+
+
+//----- (0044606A) --------------------------------------------------------
+int __fastcall PrepareHouse(unsigned int uHouseID)
+{
+  unsigned int v1; // ebx@1
+  signed int v2; // esi@1
+  int uExitPic; // edi@1
+  __int16 uExitMapID; // ax@2
+  int result; // eax@5
+  unsigned int *v6; // ecx@8
+  int v7; // ebx@11
+  int v8; // esi@16
+  unsigned int v9; // eax@16
+  unsigned int v10; // eax@19
+  int v11; // ecx@19
+  char pContainer[36]; // [sp+Ch] [bp-54h]@16
+  int v13; // [sp+30h] [bp-30h]@11
+  int Dst[6]; // [sp+34h] [bp-2Ch]@1
+  unsigned int v15; // [sp+4Ch] [bp-14h]@1
+  int uAnimationID; // [sp+50h] [bp-10h]@1
+  unsigned int *v17; // [sp+54h] [bp-Ch]@3
+  unsigned int v18; // [sp+58h] [bp-8h]@1
+  int v19; // [sp+5Ch] [bp-4h]@7
+
+  v15 = uHouseID;
+  v1 = 52 * uHouseID;
+  //uAnimationID = p2DEvents_minus1___02[26 * uHouseID];
+  uAnimationID = p2DEvents[uHouseID - 1].uAnimationID;
+  v2 = 0;
+  v18 = 52 * uHouseID;
+  memset(Dst, 0, 0x18u);
+  //uExitPic = *(__int16 *)((char *)p2DEvents_minus1_::2C + v1);
+  uExitPic = p2DEvents[uHouseID - 1].uExitPicID;
+  uNumDialogueNPCPortraits = 0;
+  uHouse_ExitPic = uExitPic;
+  if ( uExitPic )
+  {
+    //uExitMapID = *(__int16 *)((char *)p2DEvents_minus1_::30 + v1);
+    uExitMapID = p2DEvents[uHouseID - 1]._quest_related;
+    if ( uExitMapID > 0 )
+    {
+      v17 = (unsigned int *)(uExitMapID - 1);
+      if ( !((unsigned __int8)(0x80u >> (signed int)v17 % 8) & pParty->_award_bits[(uExitMapID - 1) >> 3]) )
+      {
+        uExitPic = 0;
+        uHouse_ExitPic = 0;
+      }
+    }
+  }
+  dword_591080 = pAnimatedRooms[uAnimationID].field_8;
+  result = dword_591080;
+  if ( dword_591080 )
+  {
+    v2 = 1;
+    Dst[0] = dword_591080;
+    uNumDialogueNPCPortraits = 1;
+  }
+  v19 = 1;
+  if ( (signed int)pNPCStats->uNumNewNPCs > 1 )
+  {
+    v6 = &pNPCStats->pNewNPCData[1].uFlags;
+    v17 = &pNPCStats->pNewNPCData[1].uFlags;
+    do
+    {
+      if ( v6[3] == v15 )
+      {
+        if ( !(*(char *)v6 & 0x80) )
+        {
+          v7 = v2++ - (result != 0);
+          array_5913D8[v7] = (NPCData *)(v6 - 2);
+          v6 = v17;
+          *(&v13 + v2) = *(v17 - 1);
+          v1 = v18;
+          if ( (*v6 & 3) != 2 )
+            ++*v6;
+        }
+      }
+      ++v19;
+      v6 += 19;
+      v17 = v6;
+    }
+    while ( v19 < (signed int)pNPCStats->uNumNewNPCs );
+    uNumDialogueNPCPortraits = v2;
+  }
+  v19 = 0;
+  if ( v2 > 0 )
+  {
+    do
+    {
+      v8 = v19;
+      sprintf(pContainer, "npc%03u", Dst[v19]);
+      v9 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      ++v19;
+      pDialogueNPCPortraits[v8] = &pIcons_LOD->pTextures[v9];
+      result = v19;
+    }
+    while ( v19 < uNumDialogueNPCPortraits );
+    uExitPic = uHouse_ExitPic;
+  }
+  if ( uExitPic )
+  {
+    v10 = pIcons_LOD->LoadTexture(pHouse_ExitPictures[uExitPic], TEXTURE_16BIT_PALETTE);
+    v11 = uNumDialogueNPCPortraits++;
+    pDialogueNPCPortraits[v11] = &pIcons_LOD->pTextures[v10];
+    //result = *(__int16 *)((char *)p2DEvents_minus1_::2E + v1);
+    result = p2DEvents[uHouseID - 1].uExitMapID;
+    uHouse_ExitPic = result;
+  }
+  return result;
+}
+
+
+
+
+
+//----- (0044622E) --------------------------------------------------------
+bool __fastcall EnterHouse(enum HOUSE_TYPE uHouseID)
+{
+  enum HOUSE_TYPE v1; // edi@1
+  int v2; // edi@5
+  unsigned int uOpenTime; // eax@5
+  int uCloseTime; // esi@5
+  unsigned int v5; // esi@5
+  int v6; // edx@5
+  signed int v7; // ecx@10
+  signed int v8; // eax@10
+  int v9; // esi@10
+  unsigned int v10; // esi@16
+  int v11; // ecx@17
+  unsigned int v12; // kr00_4@25
+  void *v13; // esi@25
+  int v14; // eax@25
+  Player *v15; // esi@27
+  signed int v16; // eax@32
+  unsigned int v17; // eax@37
+  signed int v18; // edi@37
+  signed int v19; // edi@41
+  unsigned int v20; // ecx@41
+  const char *v22; // [sp-4h] [bp-40h]@33
+  char pContainer[40]; // [sp+Ch] [bp-30h]@32
+  unsigned int v24; // [sp+34h] [bp-8h]@5
+  enum HOUSE_TYPE v25; // [sp+38h] [bp-4h]@1
+
+  v1 = uHouseID;
+  v25 = uHouseID;
+  GameUI_StatusBar_TimedString[0] = 0;
+  pStatusBarString[0] = 0;
+  ShowStatusBarString("", 2u);
+  if ( pMessageQueue_50CBD0->uNumMessages )
+    pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+  viewparams->bRedrawGameUI = 1;
+  uDialogueType = 0;
+  pKeyActionMap->_459ED1(3);
+  pKeyActionMap->ResetKeys();
+  if ( v1 == 600 || v1 == 601 )
+  {
+    GameOverMenu(0);
+    return 0;
+  }
+  v2 = 26 * v1;
+  //uOpenTime = p2DEvents_minus1_::uOpenTime[v2];
+  uOpenTime = p2DEvents[v1 - 1].uOpenTime;
+  //uCloseTime = p2DEvents_minus1_::uCloseTime[v2];
+  uCloseTime = p2DEvents[v1 - 1].uCloseTime;
+  ptr_F8B1E8 = 0;
+  v24 = uOpenTime;
+  v5 = uCloseTime - 1;
+  dword_F8B1E4 = 0;
+  dword_F8B1F4 = 0;
+  memset(byte_F8B1F0, 0, 4u);
+  memset(byte_F8B148, 0, 0x10u);
+  pRenderer->ClearZBuffer(0, 479);
+  v6 = v24;
+  if ( (signed int)v5 <= (signed int)v24 )
+  {
+    if ( pParty->uCurrentHour >= v24 )
+      goto LABEL_16;
+  }
+  else
+  {
+    if ( pParty->uCurrentHour < v24 )
+    {
+LABEL_10:
+      v7 = 0;
+      v8 = 0;
+      v9 = v5 + 1;
+      if ( (signed int)v24 > 12 )
+      {
+        v6 = v24 - 12;
+        v7 = 1;
+      }
+      if ( v9 > 12 )
+      {
+        v9 -= 12;
+        v8 = 1;
+      }
+      sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[414], v6, aAMPMNames[v7], v9, aAMPMNames[v8]);
+      ShowStatusBarString(pTmpBuf, 2u);
+      if ( uActiveCharacter )
+        pPlayers[uActiveCharacter]->PlaySound(3, 0);
+      return 0;
+    }
+  }
+  if ( pParty->uCurrentHour > v5 )
+    goto LABEL_10;
+LABEL_16:
+  v10 = v25;
+  if ( (signed int)v25 >= 53 )
+    goto LABEL_21;
+  v11 = pParty->field_3C._shop_ban_times[2 * v25 + 1];
+  if ( !(v11 | pParty->field_3C._shop_ban_times[2 * v25])
+    || (signed __int64)__PAIR__(v11, pParty->field_3C._shop_ban_times[2 * v25]) <= (signed __int64)pParty->uTimePlayed )
+  {
+    pParty->field_3C._shop_ban_times[2 * v25] = 0;
+    pParty->field_3C._shop_ban_times[2 * v10 + 1] = 0;
+LABEL_21:
+    if ( !dword_597F18 )
+      pAudioPlayer->StopChannels(-1, -1);
+    //uCurrentHouse_Animation = p2DEvents_minus1___02[v2];
+    uCurrentHouse_Animation = p2DEvents[v2 / sizeof(_2devent) - 1].uAnimationID;
+    dword_F8B198 = LOBYTE(pAnimatedRooms[uCurrentHouse_Animation].field_C);
+    if ( dword_F8B198 == 20 && pParty->uFine )
+    {
+      uCurrentHouse_Animation = (signed __int16)p2DEvents[186].uAnimationID;
+      v25 = (HOUSE_TYPE)187;
+      v12 = LODWORD(pParty->uTimePlayed);
+      LODWORD(pParty->uTimePlayed) += 0x7620000u;
+      v13 = &pParty->pPlayers[0].uNumDivineInterventionCastsThisDay;
+      v14 = LOBYTE(pAnimatedRooms[(signed __int16)p2DEvents[186].uAnimationID].field_C);
+      pParty->uTimePlayed = __PAIR__(HIDWORD(pParty->uTimePlayed), v12) + 0x7620000;
+      dword_F8B198 = v14;
+      do
+      {
+        *((short *)v13 - 258) = 0;
+        memset(v13, 0, 4u);
+        v13 = (char *)v13 + 6972;
+      }
+      while ( (signed int)v13 < (signed int)&pParty->field_871C[694] );
+      ++pParty->uNumPrisonTerms;
+      pParty->uFine = 0;
+      v15 = pParty->pPlayers;
+      do
+      {
+        v15->SetVariable(VAR_Award, 87);
+        ++v15;
+      }
+      while ( (signed int)v15 < (signed int)pParty->pHirelings );
+      v10 = v25;
+    }
+    ++pIcons_LOD->uTexturePacksCount;
+    if ( !pIcons_LOD->uNumPrevLoadedFiles )
+      pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+    v16 = const_2();
+    sprintf(pContainer, "evt%02d", v16);
+    if ( pParty->uAlignment )
+    {
+      if ( pParty->uAlignment != 2 )
+        goto LABEL_37;
+      v22 = "-c";
+    }
+    else
+    {
+      v22 = "-b";
+    }
+    strcat(pContainer, v22);
+LABEL_37:
+    v17 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    array_5913D8[6] = 0;
+    pTexture_Dialogue_Background = &pIcons_LOD->pTextures[v17];
+    uTextureID_507B04 = uTextureID_right_panel;
+    PrepareHouse(v10);
+    v18 = 1;
+    uTextureID_507B04 = uTextureID_right_panel;
+    if ( uNumDialogueNPCPortraits == 1 )
+      array_5913D8[6] = (NPCData *)1;
+    pVideoPlayer->_4BF28F(pAnimatedRooms[uCurrentHouse_Animation].field_0, 1u);
+    if ( (signed int)v10 < 139 || (signed int)v10 > 172 )
+    {
+      if ( (signed int)v10 >= 54 && (signed int)v10 <= 73 && !sub_4B68EA(v10 - 54) )
+        goto LABEL_49;
+      v20 = v10;
+    }
+    else
+    {
+      v19 = word_4F0704[2 * v10] - 1;
+      v20 = v10;
+      if ( !((unsigned __int8)(0x80u >> v19 % 8) & pPlayers[uActiveCharacter]->field_152[v19 >> 3]) )
+      {
+        HousePlaySomeSound(v10, 3);
+        v18 = 1;
+LABEL_49:
+        dword_5C35D4 = v18;
+        return v18;
+      }
+      v18 = 1;
+    }
+    HousePlaySomeSound(v20, v18);
+    goto LABEL_49;
+  }
+  ShowStatusBarString(pGlobalTXT_LocalizationStrings[191], 2u);// "You've been banned from this shop!"
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mm7_5.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,17304 @@
+#include "mm7.h"
+
+#include "MapInfo.h"
+#include "Game.h"
+#include "GUIWindow.h"
+#include "GUIFont.h"
+#include "GUIButton.h"
+#include "GUIProgressBar.h"
+#include "Party.h"
+#include "AudioPlayer.h"
+#include "Outdoor.h"
+#include "IndoorCamera.h"
+#include "Overlays.h"
+#include "Monsters.h"
+#include "Arcomage.h"
+#include "LOD.h"
+#include "Actor.h"
+#include "Allocator.h"
+#include "Events.h"
+#include "Viewport.h"
+#include "FrameTableInc.h"
+#include "Math.h"
+#include "LayingItem.h"
+#include "ObjectList.h"
+#include "Chest.h"
+#include "PaletteManager.h"
+#include "DecorationList.h"
+#include "SaveLoad.h"
+#include "stru123.h"
+#include "Time.h"
+#include "IconFrameTable.h"
+#include "stru179.h"
+#include "Awards.h"
+#include "Autonotes.h"
+#include "stru160.h"
+#include "stru279.h"
+#include "TurnEngine.h"
+#include "stru277.h"
+#include "Weather.h"
+#include "stru272.h"
+#include "stru298.h"
+#include "StorylineTextTable.h"
+#include "Events2D.h"
+#include "Log.h"
+
+#include "mm7_data.h"
+
+
+
+
+
+
+
+
+
+
+
+
+static char static_sub_417BB5_out_string[1200]; // static to a file, not sub actually
+
+
+
+//----- (004304E7) --------------------------------------------------------
+void __cdecl GameUI_MsgProc()
+{
+  signed int v0; // edi@6
+  char *v1; // esi@6
+  unsigned int v2; // edx@7
+  Actor *pActor; // ecx@13
+  int v4; // ecx@18
+  NPCData *pNPCData; // eax@18
+  int v6; // edx@20
+  int v7; // ecx@29
+  unsigned int v8; // edx@59
+  unsigned int v9; // ecx@60
+  unsigned int v10; // ecx@73
+  unsigned int v11; // eax@75
+  unsigned __int8 v12; // sf@75
+  unsigned __int8 v13; // of@75
+  int v14; // eax@98
+  unsigned int v15; // eax@102
+  unsigned __int8 v16; // al@104
+  unsigned __int8 v17; // al@105
+  int v18; // eax@106
+  float v19; // ST64_4@121
+  unsigned int v20; // ecx@121
+  float v21; // ST64_4@126
+  float v22; // ST64_4@127
+  unsigned int v23; // ecx@135
+  unsigned int v24; // ecx@149
+  unsigned int v25; // ecx@165
+  GUIWindow *pWindow; // eax@204
+  unsigned int v27; // edx@204
+  unsigned int v28; // ecx@204
+  GUIWindow *pWindow2; // ecx@248
+  int v30; // edx@258
+  const char *v31; // ecx@262
+  signed int v32; // eax@269
+  unsigned int v33; // eax@277
+  unsigned __int8 v34; // al@279
+  unsigned __int8 v35; // al@280
+  GUIWindow *pWindow3; // ecx@332
+  int v37; // eax@341
+  int v38; // eax@358
+  SHORT v39; // ax@365
+  signed int v40; // eax@365
+  char *v41; // eax@380
+  int v42; // eax@396
+  POINT *pPoint; // eax@397
+  signed int v44; // eax@398
+  int v45; // edx@398
+  signed int v46; // ecx@398
+  char v47; // zf@399
+  char v48; // zf@405
+  BLVFace *pBLVFace; // ecx@410
+  ODMFace *pODMFace; // ecx@412
+  void *v51; // ecx@415
+  void *v52; // eax@424
+  __int16 v53; // ax@431
+  int v54; // eax@432
+  int v55; // ecx@432
+  int v56; // edx@432
+  int v57; // eax@432
+  Player *pPlayer; // edx@442
+  unsigned int v59; // eax@445
+  signed int v60; // ST64_4@459
+  NPCData *pNPCData2; // eax@467
+  unsigned __int64 v62; // kr00_8@467
+  __int16 v63; // dx@479
+  unsigned int v64; // eax@486
+  int v65; // ecx@486
+  int v66; // eax@488
+  char *v67; // eax@489
+  __int16 v68; // dx@498
+  char *v69; // eax@512
+  int v70; // eax@525
+  int v71; // edi@527
+  NPCData *pNPCData3; // esi@527
+  char *v73; // ecx@533
+  signed int v74; // edi@535
+  int v75; // eax@535
+  int v76; // esi@535
+  int v77; // eax@537
+  Player *pPlayer2; // ecx@549
+  int v79; // ecx@550
+  unsigned int v80; // edx@550
+  signed int v81; // eax@552
+  POINT *pPoint2; // eax@553
+  signed int v83; // ecx@554
+  signed int v84; // ecx@554
+  GUIButton *pButton; // eax@578
+  unsigned int v86; // eax@583
+  const char *v87; // ecx@595
+  const char *v88; // ecx@596
+  unsigned int v89; // eax@598
+  unsigned int v90; // eax@602
+  int v91; // edx@605
+  int v92; // eax@605
+  int v93; // edx@605
+  int pPlayerNum; // edx@611
+  int v95; // eax@611
+  const char *v96; // ecx@621
+  unsigned int v97; // eax@624
+  int v98; // eax@636
+  unsigned __int8 v99; // al@643
+  Player *pPlayer3; // eax@648
+  int v101; // ecx@648
+  int v102; // edx@652
+  int v103; // eax@671
+  Player *pPlayer4; // ecx@718
+  int v105; // eax@718
+  Player *pPlayer5; // ST78_4@758
+  unsigned int v107; // eax@758
+  unsigned int v108; // eax@758
+  char *v109; // ST64_4@759
+  Player *v110; // ST78_4@759
+  int v111; // ST60_4@759
+  int v112; // ST5C_4@759
+  char *v113; // ST58_4@759
+  signed int v114; // eax@759
+  unsigned int v115; // eax@764
+  int v116; // eax@776
+  POINT *pPoint3; // eax@777
+  unsigned int v118; // eax@785
+  unsigned int v119; // ecx@786
+  unsigned int v120; // [sp-28h] [bp-624h]@86
+  unsigned int v121; // [sp-28h] [bp-624h]@711
+  unsigned int v122; // [sp-24h] [bp-620h]@86
+  unsigned int v123; // [sp-24h] [bp-620h]@711
+  unsigned int v124; // [sp-20h] [bp-61Ch]@86
+  unsigned int v125; // [sp-20h] [bp-61Ch]@711
+  unsigned int v126; // [sp-1Ch] [bp-618h]@86
+  int v127; // [sp-1Ch] [bp-618h]@107
+  unsigned int v128; // [sp-1Ch] [bp-618h]@711
+  int v129; // [sp-18h] [bp-614h]@86
+  signed int v130; // [sp-18h] [bp-614h]@107
+  int v131; // [sp-14h] [bp-610h]@86
+  unsigned int v132; // [sp-14h] [bp-610h]@107
+  unsigned int v133; // [sp-10h] [bp-60Ch]@60
+  unsigned int v134; // [sp-10h] [bp-60Ch]@86
+  signed int v135; // [sp-10h] [bp-60Ch]@107
+  unsigned int v136; // [sp-10h] [bp-60Ch]@121
+  unsigned int v137; // [sp-Ch] [bp-608h]@60
+  unsigned int v138; // [sp-Ch] [bp-608h]@86
+  signed int v139; // [sp-Ch] [bp-608h]@107
+  unsigned int v140; // [sp-Ch] [bp-608h]@121
+  enum WindowType pWindowType; // [sp-8h] [bp-604h]@56
+  enum WindowType pWindowType1; // [sp-8h] [bp-604h]@60
+  unsigned __int8 v143; // [sp-8h] [bp-604h]@86
+  int v144; // [sp-8h] [bp-604h]@107
+  enum WindowType pWindowType2; // [sp-8h] [bp-604h]@121
+  const char *v146; // [sp-8h] [bp-604h]@449
+  unsigned int v147; // [sp-8h] [bp-604h]@550
+  int v148; // [sp-4h] [bp-600h]@56
+  GUIButton *pButton2; // [sp-4h] [bp-600h]@59
+  const char *v150; // [sp-4h] [bp-600h]@86
+  unsigned int v151; // [sp-4h] [bp-600h]@107
+  int v152; // [sp-4h] [bp-600h]@121
+  int v153; // [sp-4h] [bp-600h]@135
+  int v154; // [sp-4h] [bp-600h]@149
+  int v155; // [sp-4h] [bp-600h]@165
+  int v156; // [sp-4h] [bp-600h]@204
+  const char *v157; // [sp-4h] [bp-600h]@444
+  unsigned int v158; // [sp-4h] [bp-600h]@449
+  __int16 v159; // [sp-4h] [bp-600h]@550
+  int v160; // [sp-4h] [bp-600h]@599
+  const char *v161; // [sp-4h] [bp-600h]@637
+  int v162; // [sp+0h] [bp-5FCh]@56
+  int v163; // [sp+0h] [bp-5FCh]@59
+  Texture *pTexture; // [sp+0h] [bp-5FCh]@86
+  int v165; // [sp+0h] [bp-5FCh]@107
+  int v166; // [sp+0h] [bp-5FCh]@121
+  int v167; // [sp+0h] [bp-5FCh]@135
+  int v168; // [sp+0h] [bp-5FCh]@149
+  int v169; // [sp+0h] [bp-5FCh]@165
+  int v170; // [sp+0h] [bp-5FCh]@204
+  signed int v171; // [sp+0h] [bp-5FCh]@259
+  KeyToggleType pKeyToggleType; // [sp+0h] [bp-5FCh]@287
+  char *v173; // [sp+0h] [bp-5FCh]@444
+  char *v174; // [sp+0h] [bp-5FCh]@449
+  int v175; // [sp+0h] [bp-5FCh]@550
+  int v176; // [sp+0h] [bp-5FCh]@599
+  const char *v177; // [sp+0h] [bp-5FCh]@629
+  char *v178; // [sp+0h] [bp-5FCh]@637
+  int v179; // [sp+4h] [bp-5F8h]@0
+  signed int _this; // [sp+14h] [bp-5E8h]@22
+  signed int thisa; // [sp+14h] [bp-5E8h]@251
+  signed int thisb; // [sp+14h] [bp-5E8h]@272
+  Player *pPlayer7; // [sp+14h] [bp-5E8h]@373
+  Player *pPlayer8; // [sp+14h] [bp-5E8h]@377
+  char *thise; // [sp+14h] [bp-5E8h]@445
+  Player *pPlayer9; // [sp+14h] [bp-5E8h]@455
+  int thisg; // [sp+14h] [bp-5E8h]@467
+  int thish; // [sp+14h] [bp-5E8h]@528
+  signed int thisi; // [sp+14h] [bp-5E8h]@535
+  MapInfo *pMapInfo; // [sp+14h] [bp-5E8h]@604
+  Player *pPlayer10; // [sp+14h] [bp-5E8h]@641
+  int thisl; // [sp+14h] [bp-5E8h]@648
+  int uMessageParam; // [sp+18h] [bp-5E4h]@7
+  int uAction; // [sp+1Ch] [bp-5E0h]@18
+  NPCData *pNPCData4; // [sp+20h] [bp-5DCh]@23
+  unsigned int uNumSeconds; // [sp+24h] [bp-5D8h]@18
+  char v197; // [sp+2Bh] [bp-5D1h]@101
+  enum UIMessageType uMessage; // [sp+2Ch] [bp-5D0h]@7
+  unsigned int v199; // [sp+30h] [bp-5CCh]@7
+  char *v200; // [sp+34h] [bp-5C8h]@518
+  POINT v201; // [sp+38h] [bp-5C4h]@553
+  POINT v202; // [sp+40h] [bp-5BCh]@141
+  POINT a2; // [sp+48h] [bp-5B4h]@127
+  POINT v204; // [sp+50h] [bp-5ACh]@777
+  POINT v205; // [sp+58h] [bp-5A4h]@171
+  POINT v206; // [sp+60h] [bp-59Ch]@553
+  POINT v207; // [sp+68h] [bp-594h]@155
+  POINT v208; // [sp+70h] [bp-58Ch]@397
+  POINT v209; // [sp+78h] [bp-584h]@777
+  POINT v210; // [sp+80h] [bp-57Ch]@397
+  POINT v211; // [sp+88h] [bp-574h]@704
+  __int64 v212; // [sp+90h] [bp-56Ch]@467
+  char v213; // [sp+98h] [bp-564h]@385
+  char pLevelName; // [sp+9Ch] [bp-560h]@380
+  char pOut; // [sp+BCh] [bp-540h]@370
+  FrameTableTxtLine v216; // [sp+DCh] [bp-520h]@524
+  int v217[9]; // [sp+158h] [bp-4A4h]@652
+  FrameTableTxtLine v218; // [sp+17Ch] [bp-480h]@524
+  char a1[64]; // [sp+1F8h] [bp-404h]@467
+  char Str2[128]; // [sp+238h] [bp-3C4h]@527
+  Actor actor; // [sp+2B8h] [bp-344h]@4
+
+  dword_50CDC8 = 0;
+  if ( !pEventTimer->bPaused )
+  {
+    pParty->sEyelevel = pParty->uDefaultEyelevel;
+    pParty->uPartyHeight = pParty->uDefaultPartyHeight;
+  }
+  if ( bDialogueUI_InitializeActor_NPC_ID )
+  {
+    //Actor::Actor(&actor);
+    memset(&actor, 0, 0x344u);
+    dword_5B65D0_dialogue_actor_npc_id = bDialogueUI_InitializeActor_NPC_ID;
+    actor.uNPC_ID = bDialogueUI_InitializeActor_NPC_ID;
+    actor.InitializeDialogue(0);
+    bDialogueUI_InitializeActor_NPC_ID = 0;
+  }
+  if ( pMessageQueue_50CBD0->uNumMessages )
+  {
+    v0 = 1;
+    v1 = "";
+    while ( 2 )
+    {
+      if ( !pMessageQueue_50CBD0->uNumMessages )
+        break;
+
+      pMessageQueue_50CBD0->PopMessage(&uMessage, &uMessageParam, (int *)&v199);
+      switch ( uMessage )
+      {
+        case UIMSG_ChangeGameState:
+          uGameState = v0;
+          goto _continue;
+        case UIMSG_PlayArcomage:
+          pVideoPlayer->_4BF5B2();
+          pArcomageGame->bGameInProgress = 1;
+          PrepareArcomage();
+          goto _continue;
+        case UIMSG_StartNPCDialogue:
+          if ( !uActiveCharacter )
+            goto _continue;
+          viewparams->field_48 = v0;
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          dword_5B65D0_dialogue_actor_npc_id = pActors[uMessageParam].uNPC_ID;
+          pActor = &pActors[uMessageParam];
+          goto _actor_init_dlg;
+        case UIMSG_Quit|0x2:
+        case 0x87:
+          if ( bNoNPCHiring != 1 && !pCurrentScreen )
+          {
+            if ( pMessageQueue_50CBD0->uNumMessages )
+              pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+            uAction = 0;
+            uNumSeconds = uMessage - 134;
+            v4 = 0;
+            pNPCData = pParty->pHirelings;
+            do
+            {
+              if ( pNPCData->pName )
+              {
+                v6 = uAction++;
+                pTmpBuf[v6] = v4;
+              }
+              ++pNPCData;
+              ++v4;
+            }
+            while ( (signed int)pNPCData < (signed int)&pParty->pPickedItem );
+            _this = 0;
+            if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+            {
+              pNPCData4 = pNPCStats->pNewNPCData;
+              do
+              {
+                if ( pNPCData4->uFlags & 0x80
+                  && (!pParty->pHirelings[0].pName || strcmp(pNPCData4->pName, pParty->pHirelings[0].pName))
+                  && (!pParty->pHirelings[1].pName || strcmp(pNPCData4->pName, pParty->pHirelings[1].pName)) )
+                {
+                  v7 = uAction++;
+                  pTmpBuf[v7] = _this + 2;
+                }
+                ++_this;
+                ++pNPCData4;
+              }
+              while ( _this < (signed int)pNPCStats->uNumNewNPCs );
+            }
+            if ( (signed int)(uNumSeconds + (unsigned __int8)pParty->field_709) < uAction )
+            {
+              //Actor::Actor(&actor);
+              memset(&actor, 0, 0x344u);
+              actor.uNPC_ID += -1 - (unsigned __int8)pParty->field_709 - uNumSeconds;
+              pActor = &actor;
+_actor_init_dlg:
+              pActor->InitializeDialogue(v0);
+            }
+          }
+          goto _continue;
+        case 0x51:
+          sub_4BDB56_buy_skill____();
+          goto _continue;
+        case UIMSG_AF:
+          sub_4B2001(uMessageParam);
+          goto _continue;
+        case 0x195:
+          sub_4BCACC_bounties(uMessageParam);
+          goto _continue;
+        case 0x88:
+          sub_4BC49B(uMessageParam);
+          goto _continue;
+        case 0x19A:
+          _4B4224_UpdateNPCTopics(uMessageParam);
+          goto _continue;
+        case UIMSG_StartNewGame:
+          if ( dword_6BE138 == 124 || uMessageParam )
+          {
+            pIcons_LOD->_40F9C5();
+            pIcons_LOD->_4114F2();
+            if ( pMessageQueue_50CBD0->uNumMessages )
+              pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+            pGUIWindow_CurrentMenu->Release();
+            uGameState = 4;
+LABEL_188:
+            pCurrentScreen = 0;
+            viewparams->bRedrawGameUI = v0;
+          }
+          else
+          {
+            ShowStatusBarString(pGlobalTXT_LocalizationStrings[201], 2u);// "Are you sure?  Click again to start a New Game"
+            pAudioPlayer->PlaySound(SOUND_20001, 0, 0, -1, 0, 0, 0, 0);
+            dword_6BE138 = 124;
+          }
+_release_tex_and_continue:
+          stru_506E40.Release();
+          goto _continue;
+        case UIMSG_Game_OpenLoadGameDialog:
+          pIcons_LOD->_40F9C5();
+          pIcons_LOD->_4114F2();
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          pGUIWindow_CurrentMenu->Release();
+          pCurrentScreen = 12;
+          GameUI_DrawLoadMenu(v0);
+          goto _continue;
+        case UIMSG_Quit:
+          if ( dword_6BE138 == 132 || uMessageParam )
+          {
+            pIcons_LOD->_40F9C5();
+            pIcons_LOD->_4114F2();
+            if ( pMessageQueue_50CBD0->uNumMessages )
+              pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+            pGUIWindow_CurrentMenu->Release();
+            pCurrentScreen = 0;
+            viewparams->bRedrawGameUI = v0;
+            if ( !uMessageParam )
+              pAudioPlayer->PlaySound((SoundID)(SOUND_EnteringAHouse|0x1), 0, 0, -1, 0, 0, 0, 0);
+            uGameState = 7;
+          }
+          else
+          {
+            ShowStatusBarString(pGlobalTXT_LocalizationStrings[82], 2u);// "Are you sure?  Click again to quit"
+            pAudioPlayer->PlaySound(SOUND_20001, 0, 0, -1, 0, 0, 0, 0);
+            dword_6BE138 = 132;
+          }
+          goto _release_tex_and_continue;
+        case 0x80:
+          pIcons_LOD->_40F9C5();
+          pIcons_LOD->_4114F2();
+          pGUIWindow_CurrentMenu->Release();
+          pCurrentScreen = 2;
+          v162 = 0;
+          v148 = 0;
+          pWindowType = (WindowType)8;
+          goto LABEL_439;
+        case UIMSG_A2:
+          --dword_6A0C9C;
+          if ( dword_6A0C9C < 0 )
+            dword_6A0C9C = 0;
+          v163 = 0;
+          v8 = 199;
+          pButton2 = ptr_69BD5C;
+          //goto LABEL_60;
+		  pWindowType1 = (WindowType)90;
+          v137 = 17;
+          v133 = 17;
+          v9 = 215;
+          goto LABEL_733;
+        case UIMSG_A3:
+          ++dword_6A0C9C;
+          if ( dword_6A0C9C >= uMessageParam )
+            dword_6A0C9C = uMessageParam - 1;
+          v163 = 0;
+          v8 = 323;
+          pButton2 = ptr_69BD58;
+//LABEL_60:
+          pWindowType1 = (WindowType)90;
+          v137 = 17;
+          v133 = 17;
+          v9 = 215;
+          goto LABEL_733;
+        case UIMSG_A6:
+          v163 = 0;
+          v8 = 302;
+          pButton2 = ptr_69BD60;
+          v9 = 350;
+          pWindowType1 = (WindowType)96;
+          v137 = 42;
+          v133 = 106;
+          goto LABEL_733;
+        case UIMSG_A4:
+          v163 = 0;
+          v8 = 302;
+          pButton2 = ptr_69BD64;
+          v9 = 241;
+          pWindowType1 = (WindowType)94;
+          v137 = 42;
+          v133 = 106;
+          goto LABEL_733;
+        case UIMSG_A5:
+          if ( pGUIWindow_CurrentMenu->field_40 == v0 )
+            pKeyActionMap->_459ED1(0);
+          if ( pCurrentScreen != 11 || uLoadGameUI_SelectedSlot != dword_6A0C9C + uMessageParam )
+          {
+            v10 = dword_6A0C9C + uMessageParam;
+            if ( dword_6BE138 == dword_6A0C9C + uMessageParam )
+            {
+              if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+              {
+                pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)164;
+                pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+                *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+                v11 = pMessageQueue_50CBD0->uNumMessages + 1;
+                v13 = __OFSUB__(pMessageQueue_50CBD0->uNumMessages + 1, 40);
+                v12 = (signed int)pMessageQueue_50CBD0->uNumMessages - 39 < 0;
+                ++pMessageQueue_50CBD0->uNumMessages;
+                if ( v12 ^ v13 )
+                {
+                  pMessageQueue_50CBD0->pMessages[v11].eType = (UIMessageType)82;
+                  pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+                  *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+                  ++pMessageQueue_50CBD0->uNumMessages;
+                }
+              }
+            }
+            uLoadGameUI_SelectedSlot = v10;
+            dword_6BE138 = v10;
+          }
+          else
+          {
+            pKeyActionMap->_459E5A(0, 19, pGUIWindow_CurrentMenu);
+            if ( strcmp((const char *)&pSavegameHeader + 100 * uLoadGameUI_SelectedSlot, pGlobalTXT_LocalizationStrings[72]) )// "Empty"
+              strcpy((char *)pKeyActionMap->pPressedKeysBuffer, (const char *)&pSavegameHeader + 100 * uLoadGameUI_SelectedSlot);
+            pKeyActionMap->uNumKeysPressed = strlen((const char *)pKeyActionMap->pPressedKeysBuffer);
+          }
+          goto _continue;
+        case UIMSG_LoadGame:
+          if ( pSavegameUsedSlots[uLoadGameUI_SelectedSlot] )
+          {
+            LoadGame(uLoadGameUI_SelectedSlot);
+            uGameState = 3;
+          }
+          goto _release_tex_and_continue;
+        case UIMSG_SaveGame:
+          if ( pGUIWindow_CurrentMenu->field_40 == v0 )
+          {
+            pKeyActionMap->_459ED1(0);
+            strcpy(
+              (char *)&pSavegameHeader + 100 * uLoadGameUI_SelectedSlot,
+              (const char *)pKeyActionMap->pPressedKeysBuffer);
+          }
+          DoSavegame(uLoadGameUI_SelectedSlot);
+          goto _release_tex_and_continue;
+        case UIMSG_StartNewGame|0x2:
+          pGUIWindow_CurrentMenu->Release();
+          pCurrentScreen = 11;
+          GameUI_DrawSaveMenu();
+          goto _continue;
+        case UIMSG_Game_OpenOptionsDialog:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          pGUIWindow_CurrentMenu->Release();
+          viewparams->field_48 = v0;
+          pCurrentScreen = 2;
+          uTextureID_507C60 = pIcons_LOD->LoadTexture("ControlBG", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C6C = pIcons_LOD->LoadTexture("con_16x", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C68 = pIcons_LOD->LoadTexture("con_32x", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C70 = pIcons_LOD->LoadTexture("con_ArrL", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C74 = pIcons_LOD->LoadTexture("con_ArrR", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C64[0] = pIcons_LOD->LoadTexture("con_Smoo", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[9] = pIcons_LOD->LoadTexture("convol00", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[0] = pIcons_LOD->LoadTexture("convol10", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[1] = pIcons_LOD->LoadTexture("convol20", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[2] = pIcons_LOD->LoadTexture("convol30", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[3] = pIcons_LOD->LoadTexture("convol40", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[4] = pIcons_LOD->LoadTexture("convol50", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[5] = pIcons_LOD->LoadTexture("convol60", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[6] = pIcons_LOD->LoadTexture("convol70", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[7] = pIcons_LOD->LoadTexture("convol80", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_SoundLevels[8] = pIcons_LOD->LoadTexture("convol90", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C84 = pIcons_LOD->LoadTexture("option04", TEXTURE_16BIT_PALETTE);
+          uTextureID_507CB0 = pIcons_LOD->LoadTexture("option03", TEXTURE_16BIT_PALETTE);
+          uTextureID_507CB8 = pIcons_LOD->LoadTexture("option02", TEXTURE_16BIT_PALETTE);
+          uTextureID_507CB4 = pIcons_LOD->LoadTexture("option01", TEXTURE_16BIT_PALETTE);
+          pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, WINDOW_Options, 0, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x16u, 0x10Eu,
+            (uTextureID_507C6C != -1 ? pIcons_LOD->pTextures[uTextureID_507C6C].uTextureWidth : 24),
+            (uTextureID_507C6C != -1 ? pIcons_LOD->pTextures[uTextureID_507C6C].uTextureHeight : 26),
+            v0, 0, 0xB8u, 0x80u, 0, v1, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x5Du, 0x10Eu,
+            (uTextureID_507C68 != -1 ? pIcons_LOD->pTextures[uTextureID_507C68].uTextureWidth : 24),
+            (uTextureID_507C68 != -1 ? pIcons_LOD->pTextures[uTextureID_507C68].uTextureHeight : 26),
+            v0, 0, 0xB8u, 0x40u, 0, v1, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0xA4u, 0x10Eu,
+            (uTextureID_507C64[0] != -1 ? pIcons_LOD->pTextures[uTextureID_507C64[0]].uTextureWidth : 24),
+            (uTextureID_507C64[0] != -1 ? pIcons_LOD->pTextures[uTextureID_507C64[0]].uTextureHeight : 26),
+            v0, 0, 0xB8u, 0, 0, v1, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x14u, 0x12Fu,
+            (uTextureID_507CB4 != -1 ? pIcons_LOD->pTextures[uTextureID_507CB4].uTextureWidth : 24),
+            (uTextureID_507CB4 != -1 ? pIcons_LOD->pTextures[uTextureID_507CB4].uTextureHeight : 26),
+            v0, 0, 0xB9u, 0, 0, v1, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x80u, 0x12Fu,
+            (uTextureID_507CB8 != -1 ? pIcons_LOD->pTextures[uTextureID_507CB8].uTextureWidth : 24),
+            (uTextureID_507CB8 != -1 ? pIcons_LOD->pTextures[uTextureID_507CB8].uTextureHeight : 26),
+            v0, 0, 0xBBu, 0, 0, v1, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x14u, 0x145u,
+            (uTextureID_507CB0 != -1 ? pIcons_LOD->pTextures[uTextureID_507CB0].uTextureWidth : 24),
+            (uTextureID_507CB0 != -1 ? pIcons_LOD->pTextures[uTextureID_507CB0].uTextureHeight : 26),
+            v0, 0, 0xE1u, 0, 0, v1, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x80u, 0x145u,
+            (uTextureID_507C84 != -1 ? pIcons_LOD->pTextures[uTextureID_507C84].uTextureWidth : 24),
+            (uTextureID_507C84 != -1 ? pIcons_LOD->pTextures[uTextureID_507C84].uTextureHeight : 26),
+            v0, 0, 0xE2u, 0, 0, v1, 0);
+          pBtn_SliderLeft = pGUIWindow_CurrentMenu->CreateButton(243, 162, 16, 16, v0, 0, 111, 4, 0, v1,
+                         &pIcons_LOD->pTextures[uTextureID_507C70], 0);
+          pBtn_SliderRight = pGUIWindow_CurrentMenu->CreateButton(0x1B3u, 0xA2u, 0x10u, 0x10u, v0, 0, 0x6Fu, 5, 0, v1,
+                         &pIcons_LOD->pTextures[uTextureID_507C74], 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x107u, 0xA2u, 0xACu, 0x11u, v0, 0, 0x6Fu, 0, 0, v1, 0);
+          pBtn_SliderLeft = pGUIWindow_CurrentMenu->CreateButton(0xF3u, 0xD8u, 0x10u, 0x10u, v0, 0, 0x70u, 4, 0, v1,
+                         &pIcons_LOD->pTextures[uTextureID_507C70], 0);
+          pBtn_SliderRight = pGUIWindow_CurrentMenu->CreateButton(0x1B3u, 0xD8u, 0x10u, 0x10u, v0, 0, 0x70u, 5, 0, v1,
+                         &pIcons_LOD->pTextures[uTextureID_507C74], 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x107u, 0xD8u, 0xACu, 0x11u, v0, 0, 0x70u, 0, 0, v1, 0);
+          pBtn_SliderLeft = pGUIWindow_CurrentMenu->CreateButton(0xF3u, 0x10Eu, 0x10u, 0x10u, v0, 0, 0xBAu, 4, 0, v1,
+                         &pIcons_LOD->pTextures[uTextureID_507C70], 0);
+          pBtn_SliderRight = pGUIWindow_CurrentMenu->CreateButton(0x1B3u, 0x10Eu, 0x10u, 0x10u, v0, 0, 0xBAu, 5u, 0, v1,
+                         &pIcons_LOD->pTextures[uTextureID_507C74], 0);
+          pGUIWindow_CurrentMenu->CreateButton(0x107u, 0x10Eu, 0xACu, 0x11u, v0, 0, 0xBAu, 0, 0, v1, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0xF1u, 0x12Eu, 0xD6u, 0x28u, v0, 0, 0x71u, 0, 0,
+            pGlobalTXT_LocalizationStrings[619],// "Return to Game"
+            0);
+          pGUIWindow_CurrentMenu->CreateButton(0x13u, 0x8Cu, 0xD6u, 0x28u, v0, 0, 0x19Fu, 0, 0x4Bu, v1, 0);
+          pTexture = 0;
+          v150 = v1;
+          v143 = 86;
+          v138 = 0;
+          v134 = 421;
+          v131 = 0;
+          v129 = v0;
+          v126 = 40;
+          v124 = 214;
+          v122 = 194;
+          v120 = 19;
+          goto LABEL_117;
+        case UIMSG_OpenKeyMappingOptions:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          pGUIWindow_CurrentMenu->Release();
+          viewparams->field_48 = 1;
+          pCurrentScreen = 26;
+          uTextureID_507BF4 = pIcons_LOD->LoadTexture("optkb", TEXTURE_16BIT_PALETTE);
+          uTextureID_507BF8 = pIcons_LOD->LoadTexture("optkb_h", TEXTURE_16BIT_PALETTE);
+          uTextureID_507BFC = pIcons_LOD->LoadTexture("resume1", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C00 = pIcons_LOD->LoadTexture("optkb_1", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C04 = pIcons_LOD->LoadTexture("optkb_2", TEXTURE_16BIT_PALETTE);
+          pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, WINDOW_KeyMappingOptions, 0, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0xF1u, 0x12Eu, 0xD6u, 0x28u, 1, 0, 0x71u, 0, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(19u, 0x12Eu, 0x6Cu, 0x14u, 1, 0, 0x1A0u, 0, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(127u, 0x12Eu, 0x6Cu, 0x14u, 1, 0, 0x1A1u, 0, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(127u, 0x144u, 0x6Cu, 0x14u, 1, 0, 0x1A2u, 0, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(19u, 0x144u, 0x6Cu, 0x14u, 1, 0, 0x7Fu, 0, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(129u, 0x94u, 0x46u, 0x13u, 1, 0, 0x1A3u, 0, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(129u, 0xA7u, 0x46u, 0x13u, 1, 0, 0x1A3u, 1u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(129u, 0xBAu, 0x46u, 0x13u, 1, 0, 0x1A3u, 2u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(129u, 0xCDu, 0x46u, 0x13u, 1, 0, 0x1A3u, 3u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(129u, 224u, 70u, 19u, 1, 0, 0x1A3u, 4u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(129u, 243u, 70u, 0x13u, 1, 0, 0x1A3u, 5u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(129u, 262u, 70u, 0x13u, 1, 0, 0x1A3u, 6u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(350u, 148u, 70u, 0x13u, 1, 0, 0x1A3u, 7u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(350u, 167u, 70u, 0x13u, 1, 0, 0x1A3u, 8u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(350u, 186u, 70u, 0x13u, 1, 0, 0x1A3u, 9u, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(350u, 205u, 70u, 0x13u, 1, 0, 0x1A3u, 0xAu, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(350u, 224u, 70u, 0x13u, 1, 0, 0x1A3u, 0xBu, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(350u, 243u, 70u, 0x13u, 1, 0, 0x1A3u, 0xCu, 0, "", 0);
+          pGUIWindow_CurrentMenu->CreateButton(350u, 262u, 70u, 0x13u, 1, 0, 0x1A3u, 0xDu, 0, "", 0);
+          dword_506E68 = -1;
+          dword_506F08 = 1;
+          memset(word_506E6C, 0, 0x1Cu);
+          word_506E6C[14] = 0;
+          memcpy(pPrevVirtualCidesMapping, pKeyActionMap->pVirtualKeyCodesMapping, 0x78u);
+          goto LABEL_90;
+        default:
+          goto _continue;
+        case UIMSG_ResetKeyMapping|0x1:
+          if ( dword_506E68 != -1 )
+            goto LABEL_623;
+          v14 = uMessageParam;
+          if ( dword_506F08 != v0 )
+            v14 = uMessageParam + 14;
+          dword_506E68 = v14;
+          pKeyActionMap->_459E5A(0, v0, pGUIWindow_CurrentMenu);
+          goto _continue;
+        case UIMSG_ResetKeyMapping:
+          v197 = 1;
+          pKeyActionMap->SetDefaultMapping();
+          uAction = 0;
+          do
+          {
+            v15 = pKeyActionMap->GetActionVKey((enum InputAction)uAction);
+            if ( v15 != pPrevVirtualCidesMapping[uAction] )
+            {
+              if ( v197 )
+              {
+                v16 = pKeyActionMap->GetActionVKey((enum InputAction)uAction);
+                GUI_ReplaceHotkey(LOBYTE(pPrevVirtualCidesMapping[uAction]), v16, v0);
+                v197 = 0;
+              }
+              else
+              {
+                v17 = pKeyActionMap->GetActionVKey((enum InputAction)uAction);
+                GUI_ReplaceHotkey(LOBYTE(pPrevVirtualCidesMapping[uAction]), v17, 0);
+              }
+            }
+            pPrevVirtualCidesMapping[uAction] = pKeyActionMap->GetActionVKey((enum InputAction)uAction);
+            v18 = uAction++;
+            v13 = __OFSUB__(uAction, 28);
+            v12 = uAction - 28 < 0;
+            *((char *)word_506E6C + v18) = 0;
+          }
+          while ( v12 ^ v13 );
+          v165 = 0;
+          v151 = 0;
+          v144 = 0;
+          v139 = 0;
+          v135 = -1;
+          v132 = 0;
+          v130 = 0;
+          v127 = 219;
+          goto _play_sound_and_continue;
+        case 0x1A0:
+          dword_506F08 = v0;
+          goto _continue;
+        case UIMSG_StartNPCDialogue|0x100:
+          dword_506F08 = 2;
+          goto _continue;
+        case UIMSG_OpenVideoOptions:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          pGUIWindow_CurrentMenu->Release();
+          viewparams->field_48 = v0;
+          pCurrentScreen = 28;
+          uTextureID_507C10 = pIcons_LOD->LoadTexture("optvid", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C14 = pIcons_LOD->LoadTexture("opvdH-bs", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C18 = pIcons_LOD->LoadTexture("opvdH-cl", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C1C = pIcons_LOD->LoadTexture("opvdH-tn", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C20 = pIcons_LOD->LoadTexture("con_ArrL", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C24 = pIcons_LOD->LoadTexture("con_ArrR", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[0] = pIcons_LOD->LoadTexture("convol10", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[1] = pIcons_LOD->LoadTexture("convol20", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[2] = pIcons_LOD->LoadTexture("convol30", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[3] = pIcons_LOD->LoadTexture("convol40", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[4] = pIcons_LOD->LoadTexture("convol50", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[5] = pIcons_LOD->LoadTexture("convol60", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[6] = pIcons_LOD->LoadTexture("convol70", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[7] = pIcons_LOD->LoadTexture("convol80", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[8] = pIcons_LOD->LoadTexture("convol90", TEXTURE_16BIT_PALETTE);
+          pTextureIDs_GammaPositions[9] = pIcons_LOD->LoadTexture("convol00", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C50 = pIcons_LOD->LoadTexture("opvdG-bs", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C54 = pIcons_LOD->LoadTexture("opvdG-cl", TEXTURE_16BIT_PALETTE);
+          uTextureID_507C58 = pIcons_LOD->LoadTexture("opvdG-tn", TEXTURE_16BIT_PALETTE);
+          pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, WINDOW_VideoOptions, 0, 0);
+          pGUIWindow_CurrentMenu->CreateButton(0xF1u, 0x12Eu, 0xD6u, 0x28u, v0, 0, 0x71u, 0, 0, v1, 0);
+          if ( pRenderer->pRenderD3D )
+          {
+            pGUIWindow_CurrentMenu->CreateButton(0x13u, 0x118u, 0xD6u, 0x12u, v0, 0, 0x1A6u, 0, 0, v1, 0);
+            pGUIWindow_CurrentMenu->CreateButton(0x13u, 0x12Eu, 0xD6u, 0x12u, v0, 0, 0x1A7u, 0, 0, v1, 0);
+            pGUIWindow_CurrentMenu->CreateButton(0x13u, 0x144u, 0xD6u, 0x12u, v0, 0, 0x1A8u, 0, 0, v1, 0);
+          }
+          if ( !pRenderer->bWindowMode )
+          {
+            v0 = 1;
+            if ( GammaController::IsGammaSupported() )
+            {
+              pBtn_SliderLeft = pGUIWindow_CurrentMenu->CreateButton(0x15u, 0xA1u, 0x10u, 0x10u, 1, 0, 0x1A9u, 4u, 0, v1,
+                             &pIcons_LOD->pTextures[uTextureID_507C20], 0);
+              pBtn_SliderRight = pGUIWindow_CurrentMenu->CreateButton(0xD5u, 0xA1u, 0x10u, 0x10u, 1, 0, 0x1A9u, 5u, 0, v1,
+                             &pIcons_LOD->pTextures[uTextureID_507C24], 0);
+              pTexture = 0;
+              v150 = v1;
+              v143 = 0;
+              v138 = 0;
+              v134 = 425;
+              v131 = 0;
+              v129 = 1;
+              v126 = 18;
+              v124 = 170;
+              v122 = 162;
+              v120 = 42;
+LABEL_117:
+              pGUIWindow_CurrentMenu->CreateButton(v120, v122, v124, v126, v129, v131, v134, v138, v143, v150, pTexture);
+            }
+          }
+          goto _continue;
+        case UIMSG_ToggleTint|0x1:
+          if ( uMessageParam == 4 )
+          {
+            --uGammaPos;
+            if ( (uGammaPos & 0x80000000u) != 0 )
+            {
+              uGammaPos = 0;
+              goto LABEL_128;
+            }
+            v19 = (double)(signed int)uGammaPos * 0.1 + 0.6;
+            pGame->pGammaController->Initialize(v19);
+            v166 = v0;
+            v152 = (int)pBtn_SliderLeft;
+            pWindowType2 = (WindowType)90;
+            v140 = 0;
+            v136 = 0;
+            v20 = 21;
+            goto LABEL_122;
+          }
+          if ( uMessageParam == 5 )
+          {
+            ++uGammaPos;
+            if ( (signed int)uGammaPos <= 9 )
+            {
+              v21 = (double)(signed int)uGammaPos * 0.1 + 0.6;
+              pGame->pGammaController->Initialize(v21);
+              v20 = 213;
+              v166 = v0;
+              v152 = (int)pBtn_SliderRight;
+              pWindowType2 = (WindowType)90;
+              v140 = 0;
+              v136 = 0;
+LABEL_122:
+              GUIWindow::Create(v20, 0xA1u, v136, v140, pWindowType2, v152, v166);
+              goto LABEL_128;
+            }
+            uGammaPos = 9;
+          }
+          else
+          {
+            uGammaPos = (pMouse->GetCursorPos(&a2)->x - 42) / 17;
+            v22 = (double)(signed int)uGammaPos * 0.1 + 0.6;
+            pGame->pGammaController->Initialize(v22);
+          }
+LABEL_128:
+          v165 = 0;
+          v151 = 0;
+          v144 = 0;
+          v139 = 0;
+          v135 = -1;
+          v132 = 0;
+          v130 = 0;
+          v127 = 21;
+          goto _play_sound_and_continue;
+        case UIMSG_ToggleBloodsplats:
+          pGame->ToggleFlags2(0x20u);
+          goto _continue;
+        case UIMSG_ToggleColoredLights:
+          pRenderer->bUseColoredLights = pRenderer->bUseColoredLights == 0;
+          goto _continue;
+        case UIMSG_ToggleTint:
+          pRenderer->bTinting = pRenderer->bTinting == 0;
+          goto _continue;
+        case UIMSG_ChangeMusicVolume:
+          if ( uMessageParam == 4 )
+          {
+            --uMusicVolimeMultiplier;
+            if ( (char)uMusicVolimeMultiplier < 1 )
+              uMusicVolimeMultiplier = 0;
+            v167 = v0;
+            v23 = 243;
+            v153 = (int)pBtn_SliderLeft;
+LABEL_136:
+            GUIWindow::Create(v23, 0xD8u, 0, 0, (enum WindowType)90, v153, v167);
+            goto LABEL_143;
+          }
+          if ( uMessageParam == 5 )
+          {
+            ++uMusicVolimeMultiplier;
+            if ( (char)uMusicVolimeMultiplier > 9 )
+              uMusicVolimeMultiplier = 9;
+            v167 = v0;
+            v23 = 435;
+            v153 = (int)pBtn_SliderRight;
+            goto LABEL_136;
+          }
+          uMusicVolimeMultiplier = (pMouse->GetCursorPos(&v202)->x - 263) / 17;
+          if ( (char)uMusicVolimeMultiplier > 9 )
+            uMusicVolimeMultiplier = 9;
+LABEL_143:
+          if ( uMusicVolimeMultiplier )
+            pAudioPlayer->PlaySound(SOUND_Bell, -1, 0, -1, 0, 0,
+              (signed __int64)(pSoundVolumeLevels[(char)uMusicVolimeMultiplier] * 64.0), 0);
+          pAudioPlayer->SetMusicVolume((signed __int64)(pSoundVolumeLevels[(char)uMusicVolimeMultiplier] * 64.0));
+          goto _continue;
+        case UIMSG_ChangeSoundVolume:
+          if ( uMessageParam == 4 )
+          {
+            --uSoundVolumeMultiplier;
+            if ( (char)uSoundVolumeMultiplier < 1 )
+              uSoundVolumeMultiplier = 0;
+            v168 = v0;
+            v24 = 243;
+            v154 = (int)pBtn_SliderLeft;
+LABEL_150:
+            GUIWindow::Create(v24, 0xA2u, 0, 0, (enum WindowType)90, v154, v168);
+            goto LABEL_157;
+          }
+          if ( uMessageParam == 5 )
+          {
+            ++uSoundVolumeMultiplier;
+            if ( (char)uSoundVolumeMultiplier > 8 )
+              uSoundVolumeMultiplier = 9;
+            v168 = v0;
+            v24 = 435;
+            v154 = (int)pBtn_SliderRight;
+            goto LABEL_150;
+          }
+          uSoundVolumeMultiplier = (pMouse->GetCursorPos(&v207)->x - 263) / 17;
+          if ( (char)uSoundVolumeMultiplier > 8 )
+            uSoundVolumeMultiplier = 9;
+LABEL_157:
+          pAudioPlayer->SetMasterVolume((signed __int64)(pSoundVolumeLevels[(char)uSoundVolumeMultiplier] * 128.0));
+          v165 = 0;
+          v151 = 0;
+          v144 = 0;
+          v139 = 0;
+          v135 = -1;
+          v132 = 0;
+          v130 = -1;
+          v127 = 218;
+          goto _play_sound_and_continue;
+        case UIMSG_ToggleFlipOnExit:
+          bFlipOnExit = bFlipOnExit == 0;
+          goto _continue;
+        case UIMSG_ToggleAlwaysRun:
+          bAlwaysRun = bAlwaysRun == 0;
+          goto _continue;
+        case UIMSG_ToggleWalkSound:
+          bWalkSound = bWalkSound == 0;
+          goto _continue;
+        case UIMSG_ToggleShowDamage:
+          bShowDamage = bShowDamage == 0;
+          goto _continue;
+        case UIMSG_ChangeVoiceVolume:
+          if ( uMessageParam == 4 )
+          {
+            --uVoicesVolumeMultiplier;
+            if ( (char)uVoicesVolumeMultiplier < 1 )
+              uVoicesVolumeMultiplier = 0;
+            v169 = v0;
+            v25 = 243;
+            v155 = (int)pBtn_SliderLeft;
+LABEL_166:
+            GUIWindow::Create(v25, 0x10Eu, 0, 0, (enum WindowType)90, v155, v169);
+            goto LABEL_173;
+          }
+          if ( uMessageParam == 5 )
+          {
+            ++uVoicesVolumeMultiplier;
+            if ( (char)uVoicesVolumeMultiplier > 8 )
+              uVoicesVolumeMultiplier = 9;
+            v169 = v0;
+            v25 = 435;
+            v155 = (int)pBtn_SliderRight;
+            goto LABEL_166;
+          }
+          uVoicesVolumeMultiplier = (pMouse->GetCursorPos(&v205)->x - 263) / 17;
+          if ( (char)uVoicesVolumeMultiplier > 8 )
+            uVoicesVolumeMultiplier = 9;
+LABEL_173:
+          if ( !uVoicesVolumeMultiplier )
+            goto _continue;
+          v165 = 0;
+          v151 = (signed __int64)(pSoundVolumeLevels[(char)uVoicesVolumeMultiplier] * 128.0);
+          v144 = 0;
+          v139 = 0;
+          v135 = -1;
+          v132 = 0;
+          v130 = -1;
+          v127 = 5788;
+          goto _play_sound_and_continue;
+        case UIMSG_SetTurnSpeed:
+          if ( uMessageParam )
+            pParty->sRotationY = uMessageParam * pParty->sRotationY / uMessageParam;
+          uTurnSpeed = uMessageParam;
+          goto _continue;
+        case UIMSG_SetGraphicsMode:
+          if ( !bUseLoResSprites )
+          {
+            byte_6BE388_graphicsmode = uMessageParam;
+LABEL_184:
+            MM7Initialization();
+            goto _continue;
+          }
+          if ( uMessageParam )
+          {
+            if ( uMessageParam == 1 )
+            {
+              byte_6BE388_graphicsmode = 0;
+            }
+            else
+            {
+              if ( uMessageParam != 2 )
+                goto _continue;
+              byte_6BE388_graphicsmode = 1;
+            }
+            goto LABEL_184;
+          }
+          ModalWindow(pNPCTopics[453].pText, 0);
+          goto _continue;
+        case UIMSG_SkillUp|0x2:
+          pGUIWindow_CurrentMenu->Release();
+          pEventTimer->Resume();
+          goto LABEL_188;
+        case UIMSG_OpenQuestBook:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( pCurrentScreen )
+            pGUIWindow_CurrentMenu->Release();
+          pEventTimer->Pause();
+          pAudioPlayer->StopChannels(-1, -1);
+          pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640u, 480u, WINDOW_Book, uMessage, 0);
+          pBooksWindow = GUIWindow::Create(493u, 355u, 0, 0, (enum WindowType)99, (int)pBtn_Quests, 0);
+          bFlashQuestBook = 0;
+          goto _continue;
+        case UIMSG_OpenAutonotes:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( pCurrentScreen )
+            pGUIWindow_CurrentMenu->Release();
+          pEventTimer->Pause();
+          pAudioPlayer->StopChannels(-1, -1);
+          pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640u, 480u, WINDOW_Book, uMessage, 0);
+          pBooksWindow = GUIWindow::Create(527u, 353u, 0, 0, (enum WindowType)99, (int)pBtn_Autonotes, 0);
+          bFlashAutonotesBook = 0;
+          goto _continue;
+        case UIMSG_OpenMapBook:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( pCurrentScreen )
+            pGUIWindow_CurrentMenu->Release();
+          pEventTimer->Pause();
+          viewparams->sPartyPosX = pParty->vPosition.x;
+          viewparams->sPartyPosZ = pParty->vPosition.y;
+          pAudioPlayer->StopChannels(-1, -1);
+          pWindow = GUIWindow::Create(0, 0, 640u, 480u, WINDOW_Book, uMessage, 0);
+          v27 = 353;
+          v28 = 546;
+          v170 = 0;
+          v156 = (int)pBtn_Maps;
+          goto LABEL_210;
+        case UIMSG_OpenCalendar:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( pCurrentScreen )
+            pGUIWindow_CurrentMenu->Release();
+          pEventTimer->Pause();
+          pAudioPlayer->StopChannels(-1, -1);
+          pWindow = GUIWindow::Create(0, 0, 640, 480, WINDOW_Book, uMessage, 0);
+          v27 = 354;
+          v28 = 570;
+          v170 = 0;
+          v156 = (int)pBtn_Calendar;
+LABEL_210:
+          pGUIWindow_CurrentMenu = pWindow;
+          pBooksWindow = GUIWindow::Create(v28, v27, 0, 0, (enum WindowType)99, v156, v170);
+          goto _continue;
+        case UIMSG_OpenHistoryBook:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( pCurrentScreen )
+            pGUIWindow_CurrentMenu->Release();
+          pEventTimer->Pause();
+          pAudioPlayer->StopChannels(-1, -1);
+          pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, WINDOW_Book, uMessage, 0);
+          pBooksWindow = GUIWindow::Create(0x258u, 0x169u, 0, 0, (enum WindowType)99, (int)pBtn_History, 0);
+          bFlashHistoryBook = 0;
+          goto _continue;
+        case UIMSG_CloseBook:
+          back_to_game();
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( pCurrentScreen > 15 )
+          {
+            if ( pCurrentScreen >= 17 && (pCurrentScreen <= 18 || pCurrentScreen == 104) )
+            {
+LABEL_229:
+              if ( dword_50CDC8 )
+                goto LABEL_232;
+              sub_42FC15();
+              goto LABEL_231;
+            }
+          }
+          else
+          {
+            if ( pCurrentScreen >= 14 || pCurrentScreen == 4 || pCurrentScreen == 10 )
+              goto LABEL_229;
+            if ( pCurrentScreen == 13 && !dword_50CDC8 && !dword_5C35C8 )
+            {
+              sub_42FC15();
+              dword_5C35C8 = 0;
+LABEL_231:
+              uMessageParam = v0;
+              goto LABEL_232;
+            }
+          }
+LABEL_232:
+          if ( !ptr_507BDC )
+          {
+            pRenderer->ClearZBuffer(0, 479);
+            viewparams->bRedrawGameUI = v0;
+            viewparams->field_48 = v0;
+            if ( pCurrentScreen )
+            {
+              if ( pCurrentScreen > 103 )
+              {
+                if ( pCurrentScreen == 104 )
+                  goto LABEL_321;
+              }
+              else
+              {
+                if ( pCurrentScreen < 100 )
+                {
+                  switch ( pCurrentScreen )
+                  {
+                    case 23:
+                      pIcons_LOD->_4114F2();
+                      if ( some_active_character )
+                      {
+                        uActiveCharacter = some_active_character;
+                        uActiveCharacter = pParty->GetNextActiveCharacter();
+                        some_active_character = 0;
+                        if ( pParty->bTurnBasedModeOn )
+                          pTurnEngine->_40471C();
+                        dword_50C9D0 = 0;
+                        dword_50C9D4 = 0;
+                        dword_50C9D8 = 0;
+                      }
+                      if ( ptr_50C9A4 && ptr_50C9A4->uItemID )
+                      {
+                        LOBYTE(ptr_50C9A4->uAttributes) &= 0xFu;
+                        dword_50C9A8 = 0;
+                        ptr_50C9A4 = 0;
+                      }
+                      goto LABEL_322;
+                    case 3:
+                      pBooksWindow->Release();
+                      //crt_deconstruct_ptr_6A0118();
+                      pBooksWindow = 0;
+                      pEventTimer->Resume();
+                      goto LABEL_322;
+                    case 11:
+                    case 12:
+                      pIcons_LOD->_4114F2();
+                      //crt_deconstruct_ptr_6A0118();
+                      goto LABEL_291;
+                    case 15:
+                      pCurrentScreen = 10;
+                      goto _continue;
+                    case 10:
+                      pWindow2 = pChestWindow;
+                      goto LABEL_249;
+                    case 25:
+                      pWindow2 = ptr_507BC8;
+LABEL_249:
+                      pWindow2->Release();
+                      pIcons_LOD->_4114F2();
+                      pCurrentScreen = 0;
+                      viewparams->bRedrawGameUI = v0;
+                      pEventTimer->Resume();
+                      goto _continue;
+                    case 2:
+                      thisa = (signed int)&uTextureID_507C60;
+                      do
+                      {
+                        if ( *(int *)thisa )
+                          pIcons_LOD->pTextures[*(int *)thisa].Release();
+                        thisa += 4;
+                      }
+                      while ( thisa < (signed int)&dword_507CBC );
+                      memset(&uTextureID_507C60, 0, 0x5Cu);
+                      pIcons_LOD->_40F9C5();
+                      WriteWindowsRegistryInt("soundflag", (char)uSoundVolumeMultiplier);
+                      WriteWindowsRegistryInt("musicflag", (char)uMusicVolimeMultiplier);
+                      WriteWindowsRegistryInt("CharVoices", (char)uVoicesVolumeMultiplier);
+                      WriteWindowsRegistryInt("WalkSound", bWalkSound);
+                      WriteWindowsRegistryInt("ShowDamage", bShowDamage);
+                      WriteWindowsRegistryInt("graphicsmode", (unsigned __int8)byte_6BE388_graphicsmode);
+                      WriteWindowsRegistryInt("valAlwaysRun", bAlwaysRun);
+                      WriteWindowsRegistryInt("FlipOnExit", bFlipOnExit);
+                      if ( !uTurnSpeed )
+                      {
+                        v171 = 3;
+                        goto LABEL_261;
+                      }
+                      if ( uTurnSpeed == 64 )
+                      {
+                        v171 = 2;
+LABEL_261:
+                        v30 = v171;
+                        goto LABEL_262;
+                      }
+                      if ( uTurnSpeed != 128 )
+                        goto LABEL_291;
+                      v30 = v0;
+LABEL_262:
+                      v31 = "TurnDelta";
+LABEL_263:
+                      WriteWindowsRegistryInt(v31, v30);
+LABEL_291:
+                      stru_506E40.Release();
+                      break;
+                    case 1:
+                      pIcons_LOD->_40F9C5();
+                      pIcons_LOD->_4114F2();
+                      pIcons_LOD->_40F9C5();
+                      pIcons_LOD->_4114F2();
+                      goto LABEL_291;
+                    case 28:
+                      if ( pRenderer->pRenderD3D )
+                      {
+                        WriteWindowsRegistryInt("Colored Lights", pRenderer->bUseColoredLights);
+                        WriteWindowsRegistryInt("Tinting", pRenderer->bTinting);
+                        WriteWindowsRegistryInt("Bloodsplats", (LOBYTE(pGame->uFlags2) >> 5) & 1);
+                      }
+                      if ( pRenderer->bWindowMode )
+                        goto LABEL_291;
+                      v30 = uGammaPos;
+                      v31 = "GammaPos";
+                      goto LABEL_263;
+                    case 26:
+                      v197 = 1;
+                      v32 = 0;
+                      while ( *((char *)word_506E6C + v32) != 1 )
+                      {
+                        ++v32;
+                        if ( v32 >= 28 )
+                        {
+                          thisb = (signed int)&uTextureID_507BF4;
+                          do
+                          {
+                            if ( *(int *)thisb )
+                              pIcons_LOD->pTextures[*(int *)thisb].Release();
+                            thisb += 4;
+                          }
+                          while ( thisb < (signed int)&dword_507C08 );
+                          memset(&uTextureID_507BF4, 0, 0x14u);
+                          pIcons_LOD->_40F9C5();
+                          uAction = 0;
+                          do
+                          {
+                            v33 = pKeyActionMap->GetActionVKey((enum InputAction)uAction);
+                            if ( v33 != pPrevVirtualCidesMapping[uAction] )
+                            {
+                              if ( v197 )
+                              {
+                                v34 = pKeyActionMap->GetActionVKey((enum InputAction)uAction);
+                                GUI_ReplaceHotkey(v34, LOBYTE(pPrevVirtualCidesMapping[uAction]), v0);
+                                v197 = 0;
+                              }
+                              else
+                              {
+                                v35 = pKeyActionMap->GetActionVKey((enum InputAction)uAction);
+                                GUI_ReplaceHotkey(v35, LOBYTE(pPrevVirtualCidesMapping[uAction]), 0);
+                              }
+                            }
+                            if ( uAction && uAction != 2 && uAction != 3 && uAction != v0 && uAction != 25 && uAction != 26 )
+                              pKeyToggleType = (KeyToggleType)v0;
+                            else
+                              pKeyToggleType = (KeyToggleType)0;
+                            pKeyActionMap->SetKeyMapping(uAction, pPrevVirtualCidesMapping[uAction], pKeyToggleType);
+                            ++uAction;
+                          }
+                          while ( uAction < 28 );
+                          pKeyActionMap->StoreMappings();
+                          goto LABEL_291;
+                        }
+                      }
+                      goto LABEL_623;
+                    case 5:
+                      if ( dword_506F14 )
+                      {
+                        Rest(_506F18_num_hours_to_sleep);
+                        pParty->pPlayers[3].pConditions[2] = 0i64;
+                        pParty->pPlayers[2].pConditions[2] = 0i64;
+                        pParty->pPlayers[1].pConditions[2] = 0i64;
+                        pParty->pPlayers[0].pConditions[2] = 0i64;
+                      }
+                      pTexture_RestUI_CurrentSkyFrame->Release();
+                      pTexture_RestUI_CurrentHourglassFrame->Release();
+                      pTexture_RestUI_CurrentHourglassFrame = 0;
+                      pTexture_RestUI_CurrentSkyFrame = 0;
+                      pIcons_LOD->_40F9C5();
+                      pIcons_LOD->_4114F2();
+                      _506F18_num_hours_to_sleep = 0;
+                      dword_506F14 = 0;
+                      dword_507B94 = v0;
+                      goto LABEL_322;
+                    case 14:
+                      pGUIWindow_CurrentMenu->Release();
+                      pCurrentScreen = 13;
+                      pIcons_LOD->_4114F2();
+                      goto _continue;
+                    case 13:
+                      if ( uDialogueType )
+                        uDialogueType = 0;
+                      if ( uGameState == 2 )
+                      {
+                        while ( sub_4BD8B5() )
+                          ;
+                      }
+                      else
+                      {
+                        if ( sub_4BD8B5() )
+                          goto _continue;
+                      }
+                      sub_4B1D27();
+                      pAudioPlayer->PlaySound((SoundID)(SOUND_EnteringAHouse|0x1), 814, 0, -1, 0, 0, 0, 0);
+                      pVideoPlayer->Unload();
+                      pGUIWindow_CurrentMenu = ptr_507BC0;
+                      goto LABEL_322;
+                    case 18:
+                      if ( uCurrentHouse_Animation == 153 )
+                        HousePlaySomeSound(0x99u, 3);
+                      pVideoPlayer->Unload();
+                      goto LABEL_306;
+                    case 4:
+LABEL_306:
+                      if ( dword_5B65CC )
+                      {
+                        pParty->field_709 = 0;
+                        LOBYTE(pNPCStats->pNewNPCData[dword_5B65CC].uFlags) &= 0x7Fu;
+                        sub_44A56A();
+                        viewparams->bRedrawGameUI = v0;
+                        dword_5B65CC = 0;
+                      }
+                      goto LABEL_317;
+                    case 19:
+                      memset(GameUI_StatusBar_TimedString, 0, 0xC8u);
+                      sub_4452BB();
+                      goto LABEL_317;
+                    case 17:
+                      if ( pParty->vPosition.x < -22528 )
+                        pParty->vPosition.x = -22528;
+                      if ( pParty->vPosition.x > 22528 )
+                        pParty->vPosition.x = 22528;
+                      if ( pParty->vPosition.y < -22528 )
+                        pParty->vPosition.y = -22528;
+                      if ( pParty->vPosition.y > 22528 )
+                        pParty->vPosition.y = 22528;
+                      goto LABEL_317;
+                    case 16:
+                      pVideoPlayer->Unload();
+                      goto _continue;
+                    case 7:
+                      goto LABEL_319;
+                    default:
+                      goto LABEL_322;
+                  }
+                  goto LABEL_322;
+                }
+LABEL_319:
+                sub_4196A0();
+                sub_419379();
+LABEL_321:
+                pIcons_LOD->_4114F2();
+              }
+LABEL_322:
+              if ( pGUIWindow_Settings )
+              {
+                if ( pCurrentScreen == 7 )
+                {
+                  pMouse->SetCursorBitmap("MICON2");
+                }
+                else
+                {
+                  pGUIWindow_Settings->Release();
+                  pGUIWindow_Settings = 0;
+                  pMouse->SetCursorBitmap("MICON1");
+                  GameUI_StatusBar_TimedStringTimeLeft = 0;
+                  unk_50C9A0 = 0;
+                  back_to_game();
+                }
+              }
+              if ( (signed int)uActiveCharacter < v0 || (signed int)uActiveCharacter > 4 )
+                uActiveCharacter = pParty->GetNextActiveCharacter();
+              pGUIWindow_CurrentMenu->Release();
+              if ( pGUIWindow_CurrentMenu == ptr_507BC0 )
+                ptr_507BC0 = 0;
+              pGUIWindow_CurrentMenu = 0;
+              pEventTimer->Resume();
+              pCurrentScreen = 0;
+              viewparams->bRedrawGameUI = v0;
+              pIcons_LOD->_4355F7();
+              goto _continue;
+            }
+            pWindow3 = pGUIWindow_Settings;
+            if ( !pGUIWindow_Settings )//Draw Menu
+            {
+              dword_6BE138 = -1;
+              GUIWindow::Create(0x25Au, 0x1C2u, 0, 0, (enum WindowType)90, (int)pBtn_GameSettings, v0);
+              pEventTimer->Pause();
+              pAudioPlayer->StopChannels(-1, -1);
+              ++pIcons_LOD->uTexturePacksCount;
+              pCurrentScreen = v0;
+              if ( !pIcons_LOD->uNumPrevLoadedFiles )
+                pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+              pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)3, 0, 0);
+              uTextureID_507944 = pIcons_LOD->LoadTexture("options", TEXTURE_16BIT_PALETTE);
+              uTextureID_507940 = pIcons_LOD->LoadTexture("new1", TEXTURE_16BIT_PALETTE);
+              uTextureID_50793C = pIcons_LOD->LoadTexture("load1", TEXTURE_16BIT_PALETTE);
+              uTextureID_507938 = pIcons_LOD->LoadTexture("save1", TEXTURE_16BIT_PALETTE);
+              uTextureID_507934 = pIcons_LOD->LoadTexture("controls1", TEXTURE_16BIT_PALETTE);
+              uTextureID_507930 = pIcons_LOD->LoadTexture("resume1", TEXTURE_16BIT_PALETTE);
+              uTextureID_50792C = pIcons_LOD->LoadTexture("quit1", TEXTURE_16BIT_PALETTE);
+              pBtn_NewGame = pGUIWindow_CurrentMenu->CreateButton(0x13u, 0x9Bu, 0xD6u, 0x28u, v0, 0, 0x7Cu, 0, 0x4Eu,
+                             pGlobalTXT_LocalizationStrings[614],// "New Game"
+                             (Texture *)(uTextureID_507940 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507940] : 0), 0);
+              pBtn_SaveGame = pGUIWindow_CurrentMenu->CreateButton(0x13u, 0xD1u, 0xD6u, 0x28u, v0, 0, 0x7Eu, 0, 0x53u,
+                             pGlobalTXT_LocalizationStrings[615],// "Save Game"
+                             (Texture *)(uTextureID_507938 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507938] : 0), 0);
+              pBtn_LoadGame = pGUIWindow_CurrentMenu->CreateButton(19, 263, 0xD6u, 0x28u, v0, 0, 0x7Du, 0, 0x4Cu,
+                             pGlobalTXT_LocalizationStrings[616],// "Load Game"
+                             (Texture *)(uTextureID_50793C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50793C] : 0), 0);
+              pBtn_GameControls = pGUIWindow_CurrentMenu->CreateButton(241, 155, 214, 40, v0, 0, 0x7Fu, 0, 0x43u,
+                             pGlobalTXT_LocalizationStrings[617],// ""Sound, Keyboard, Game Options:""
+                             (Texture *)(uTextureID_507934 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507934] : 0), 0);
+              pBtn_QuitGame = pGUIWindow_CurrentMenu->CreateButton(241, 209, 214, 40, v0, 0, 0x84u, 0, 0x51u,
+                             pGlobalTXT_LocalizationStrings[618],// "Quit"
+                             (Texture *)(uTextureID_50792C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50792C] : 0), 0);
+              pBtn_Resume = pGUIWindow_CurrentMenu->CreateButton(241, 263, 214, 40, v0, 0, 0x7Bu, 0, 0x52u,
+                             pGlobalTXT_LocalizationStrings[619],// "Return to Game"
+                             (Texture *)(uTextureID_507930 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507930] : 0), 0);
+              pGUIWindow_CurrentMenu->_41D08F(6, v0, 0, 0);
+              viewparams->field_48 = v0;
+              stru_506E40.Release();
+              uNumSeconds = (unsigned int)MakeScreenshot(155, 117);
+              pRenderer->SavePCXImage("gamma.pcx", (char *)uNumSeconds, 155, 117);
+              free((void *)uNumSeconds);
+              stru_506E40._40E55E("gamma.pcx", 0);
+              goto _continue;
+            }
+            goto LABEL_333;
+          }
+          sub_41426F();
+_continue:
+          continue;
+        case UIMSG_BC:
+          if ( uMessageParam )
+          {
+            GUIWindow::Create(0x272u, 0xB3u, 0, 0, (enum WindowType)90, (int)pBtn_NPCRight, 0);
+            v37 = (pParty->pHirelings[0].pName != 0) + (pParty->pHirelings[1].pName != 0) + (unsigned __int8)pParty->field_70A - 2;
+            if ( (unsigned __int8)pParty->field_709 < v37 )
+            {
+              ++pParty->field_709;
+              if ( (unsigned __int8)pParty->field_709 >= v37 )
+                pParty->field_709 = (pParty->pHirelings[0].pName != 0) + (pParty->pHirelings[1].pName != 0) + pParty->field_70A - 2;
+            }
+          }
+          else
+          {
+            GUIWindow::Create(0x1D5u, 0xB3u, 0, 0, (enum WindowType)90, (int)pBtn_NPCLeft, 0);
+            if ( pParty->field_709 )
+            {
+              --pParty->field_709;
+              if ( pParty->field_709 < 1 )
+                pParty->field_709 = 0;
+            }
+          }
+          DrawHiredNPCs();
+          goto _continue;
+        case UIMSG_OpenRestUI|0x2:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          dword_50CDC8 = v0;
+          sub_42FBDD();
+          HousePlaySomeSound(uCurrentHouse_Animation, 2);
+          pVideoPlayer->Unload();
+          sub_44603D();
+          viewparams->bRedrawGameUI = v0;
+          if ( dword_59117C_teleportx | dword_591178_teleporty | dword_591174_teleportz | dword_591170_teleport_directiony | dword_59116C_teleport_directionx | dword_591168_teleport_speedz )
+          {
+            if ( dword_59117C_teleportx )
+            {
+              pParty->vPosition.x = dword_59117C_teleportx;
+              _5B65A8_npcdata_uflags_or_other = dword_59117C_teleportx;
+            }
+            if ( dword_591178_teleporty )
+            {
+              pParty->vPosition.y = dword_591178_teleporty;
+              _5B65AC_npcdata_fame_or_other = dword_591178_teleporty;
+            }
+            if ( dword_591174_teleportz )
+            {
+              pParty->vPosition.z = dword_591174_teleportz;
+              _5B65B0_npcdata_rep_or_other = dword_591174_teleportz;
+              pParty->uFallStartY = dword_591174_teleportz;
+            }
+            if ( dword_591170_teleport_directiony )
+            {
+              pParty->sRotationY = dword_591170_teleport_directiony;
+              _5B65B4_npcdata_loword_house_or_other = dword_591170_teleport_directiony;
+            }
+            if ( dword_59116C_teleport_directionx )
+            {
+              pParty->sRotationX = dword_59116C_teleport_directionx;
+              _5B65B8_npcdata_hiword_house_or_other = dword_59116C_teleport_directionx;
+              v38 = dword_591168_teleport_speedz;
+              pParty->uFallSpeed = dword_591168_teleport_speedz;
+              dword_5B65BC = dword_591168_teleport_speedz;
+            }
+            else
+            {
+              v38 = dword_5B65BC;
+            }
+            if ( *dword_591164_teleport_map_name != 48 )
+            {
+              pGameLoadingUI_ProgressBar->uType = (GUIProgressBar::Type)2;
+              dword_5B65C0 = _5B65A8_npcdata_uflags_or_other | _5B65AC_npcdata_fame_or_other | _5B65B0_npcdata_rep_or_other | _5B65B4_npcdata_loword_house_or_other | _5B65B8_npcdata_hiword_house_or_other | v38;
+              OnMapLeave();
+              sub_44987B(dword_591164_teleport_map_name, 0);
+            }
+          }
+          else
+          {
+            dword_597F18 = dword_5C341C;
+            EventProcessor(dword_5C3418, 0, v0);
+          }
+          dword_597F18 = 0;
+          if ( !_strcmpi(byte_6BE3B0, "d05.blv") )
+            pParty->uTimePlayed += 1474560i64;
+          goto _continue;
+        case 0x19C:
+          sub_42FC15();
+          pVideoPlayer->Unload();
+          sub_44603D();
+          dword_597F18 = 0;
+          goto LABEL_422;
+        case UIMSG_CycleCharacters:
+          v39 = GetAsyncKeyState(VK_SHIFT);
+          v40 = CycleCharacter(v39);
+          goto LABEL_421;
+        case UIMSG_LoadGame|0x8:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          dword_50CDC8 = v0;
+          sub_42FBDD();
+          pNPCData4 = (NPCData *)GetTravelTime();
+          strcpy(pOutdoor->pLevelFilename, pCurrentMapName);
+          if ( bUnderwater != 1 && pParty->bFlying
+            || pOutdoor->GetTravelDestination(pParty->vPosition.x, pParty->vPosition.y, &pOut, 20) != v0 )
+          {
+            viewparams->bRedrawGameUI = v0;
+LABEL_387:
+            sub_42FC15();
+            if ( pParty->vPosition.x < -22528 )
+              pParty->vPosition.x = -22528;
+            if ( pParty->vPosition.x > 22528 )
+              pParty->vPosition.x = 22528;
+            if ( pParty->vPosition.y < -22528 )
+              pParty->vPosition.y = -22528;
+            if ( pParty->vPosition.y > 22528 )
+              pParty->vPosition.y = 22528;
+LABEL_317:
+            sub_44603D();
+            pCurrentScreen = 0;
+          }
+          else
+          {
+            pParty->field_6E4 = 0;
+            pParty->field_6E0 = 0;
+            pStru277->_427D48(v0);
+            sub_44603D();
+            pEventTimer->Pause();
+            pGameLoadingUI_ProgressBar->_443484((GUIProgressBar::Type)2);
+            ++pGameLoadingUI_ProgressBar->uProgressMax;
+            SaveGame(v0, 0);
+            pGameLoadingUI_ProgressBar->Progress();
+            RestAndHeal(1440 * (signed int)pNPCData4);
+            if ( pParty->uNumFoodRations )
+            {
+              pParty->RestAndHeal();
+              if ( ((pParty->uNumFoodRations - (signed int)pNPCData4) & 0x80000000u) != 0 )
+              {
+                pPlayer7 = pParty->pPlayers;
+                do
+                {
+                  pPlayer7->SetCondition(v0, 0);
+                  ++pPlayer7;
+                }
+                while ( (signed int)pPlayer7 < (signed int)pParty->pHirelings );
+                ++pParty->field_764;
+              }
+              Party::TakeFood((unsigned int)pNPCData4);
+            }
+            else
+            {
+              pPlayer8 = pParty->pPlayers;
+              do
+              {
+                pPlayer8->SetCondition(v0, 0);
+                ++pPlayer8;
+              }
+              while ( (signed int)pPlayer8 < (signed int)pParty->pHirelings );
+              ++pParty->field_764;
+            }
+            pPaletteManager->ResetNonLocked();
+            pSpriteFrameTable->ResetSomeSpriteFlags();
+            strcpy(pCurrentMapName, &pOut);
+            strcpy(&pLevelName, pCurrentMapName);
+            v41 = strtok(&pLevelName, ".");
+            strcpy(&pLevelName, v41);
+            Level_LoadEvtAndStr(&pLevelName);
+            pDecalBuilder->Reset( 0);
+            LoadLevel_InitializeLevelEvt();
+            uLevelMapStatsID = pMapStats->GetMapInfo(pCurrentMapName);
+            bUnderwater = 0;
+            bNoNPCHiring = 0;
+            pGame->uFlags2 &= 0xFFFFFFF7u;
+            if ( Is_out15odm_underwater() )
+            {
+              bUnderwater = 1;
+              pGame->uFlags2 |= 8u;
+            }
+            if ( !_strcmpi(pCurrentMapName, "out15.odm") || !_strcmpi(pCurrentMapName, "d47.blv") )
+              bNoNPCHiring = 1;
+            v0 = 1;
+            PrepareToLoadODM(1u, (OutdoorCamera *)1);
+            pAudioPlayer->SetMapEAX();
+            bDialogueUI_InitializeActor_NPC_ID = 0;
+            OnMapLoad();
+            pOutdoor->SetFog();
+            TeleportToStartingPoint(uLevel_StartingPointType);
+            pParty->vPosition.z = GetTerrainHeightsAroundParty2(pParty->vPosition.x, pParty->vPosition.y, (int *)&v213, 0);
+            pParty->uFallStartY = pParty->vPosition.z;
+            sub_461103();
+            pEventTimer->Resume();
+            viewparams->bRedrawGameUI = 1;
+            pCurrentScreen = 0;
+            pGameLoadingUI_ProgressBar->Release();
+          }
+          goto LABEL_422;
+        case UIMSG_SaveGame|0x8:
+          goto LABEL_387;
+        case UIMSG_BE:
+          if ( pRenderer->pRenderD3D )
+          {
+            LOWORD(v42) = pGame->pVisInstance->get_picked_object_zbuf_val();
+          }
+          else
+          {
+            uNumSeconds = (unsigned int)pMouse->GetCursorPos(&v210);
+            pPoint = pMouse->GetCursorPos(&v208);
+            v42 = pRenderer->pActiveZBuffer[*(int *)uNumSeconds + pSRZBufferLineOffsets[pPoint->y]];
+          }
+          v44 = (unsigned __int16)v42;
+          v45 = v44 & 7;
+          uNumSeconds = v44;
+          v46 = v44 >> 3;
+          if ( v45 == 3 )
+          {
+            v47 = pActors[v46].uAIState == Dead;
+            goto LABEL_400;
+          }
+          if ( v45 == 2 )
+          {
+            v47 = (pObjectList->pObjects[pLayingItems[v46].uObjectDescID].uFlags & 0x10) == 0;
+LABEL_400:
+            if ( !v47 )
+              goto _continue;
+            goto LABEL_415;
+          }
+          if ( v45 == 5 )
+          {
+            v48 = pLevelDecorations[v46].field_16_event_id == 0;
+          }
+          else
+          {
+            if ( v45 != 6 )
+              goto _continue;
+            if ( uCurrentlyLoadedLevelType != v0 )
+            {
+              pODMFace = &pOutdoor->pBModels[v44 >> 9].pFaces[v46 & 0x3F];
+              if ( !(pODMFace->uAttributes & 0x02000000) || !pODMFace->sCogTriggeredID )
+                goto _continue;
+              v44 = uNumSeconds;
+              goto LABEL_415;
+            }
+            pBLVFace = &pIndoor->pFaces[v46];
+            if ( !(BYTE3(pBLVFace->uAttributes) & 2) )
+              goto _continue;
+            v48 = pIndoor->pFaceExtras[pBLVFace->uFaceExtraID].uEventID == 0;
+          }
+          if ( v48 )
+            goto _continue;
+LABEL_415:
+          v51 = pGUIWindow_Settings->ptr_1C;
+          *((char *)v51 + 8) &= 0xBFu;
+LABEL_416:
+          *((short *)v51 + 2) = uMessageParam;
+          *((int *)v51 + 3) = v44;
+          pParty->pPlayers[*((short *)v51 + 1)].SetRecoveryTime(300);
+          pWindow3 = pGUIWindow_Settings;
+LABEL_333:
+          pWindow3->Release();
+          pGUIWindow_Settings = 0;
+          pMouse->SetCursorBitmap("MICON1");
+          GameUI_StatusBar_TimedStringTimeLeft = 0;
+          unk_50C9A0 = 0;
+          back_to_game();
+          goto _continue;
+        case UIMSG_ChangeGameState|0x40:
+        case 0x8D:
+        case 0x8F:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( unk_50C9A0 )
+          {
+            v40 = uMessageParam;
+LABEL_421:
+            uActiveCharacter = v40;
+LABEL_422:
+            viewparams->bRedrawGameUI = v0;
+          }
+          else
+          {
+            if ( pGUIWindow_Settings )
+            {
+              v52 = pGUIWindow_Settings->ptr_1C;
+              switch ( uMessage )
+              {
+                case 69:
+                  *((char *)v52 + 8) &= 0xFDu;
+                  break;
+                case 141:
+                  *((char *)v52 + 9) &= 0xFEu;
+                  break;
+                case 143:
+                  *((char *)v52 + 9) &= 0xFDu;
+                  break;
+              }
+              *((short *)v52 + 2) = uMessageParam;
+              pParty->pPlayers[*((short *)v52 + 1)].SetRecoveryTime(300);
+              pGUIWindow_Settings->Release();
+              pGUIWindow_Settings = 0;
+              pEventTimer->Resume();
+              pMouse->SetCursorBitmap("MICON1");
+              GameUI_StatusBar_TimedStringTimeLeft = 0;
+              unk_50C9A0 = 0;
+            }
+          }
+          goto _continue;
+        case UIMSG_BF:
+          dword_50CDC8 = v0;
+          sub_42FBDD();
+          SaveGame(v0, 0);
+          strcpy(pCurrentMapName, pMapStats->pInfos[uHouse_ExitPic].pFilename);
+          dword_6BE364_game_settings_1 |= v0;
+          uGameState = 2;
+		  //v53 = p2DEvents_minus1_::30[26 * (unsigned int)ptr_507BC0->ptr_1C];
+          v53 = p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1]._quest_related;
+		  if ( v53 < 0 )
+          {
+            v54 = abs(v53) - 1;
+            _5B65B8_npcdata_hiword_house_or_other = 0;
+            dword_5B65BC = 0;
+            v55 = dword_4E4560[v54];
+            _5B65AC_npcdata_fame_or_other = dword_4E4578[v54];
+            v56 = dword_4E4590[v54];
+            v57 = dword_4E45A8[v54];
+            _5B65A8_npcdata_uflags_or_other = v55;
+            _5B65B4_npcdata_loword_house_or_other = v57;
+            _5B65B0_npcdata_rep_or_other = v56;
+            dword_5B65C0 = v55 | _5B65AC_npcdata_fame_or_other | v56 | v57;
+          }
+          sub_4BD8B5();
+          goto LABEL_434;
+        case UIMSG_C3:
+          pAudioPlayer->StopChannels(-1, -1);
+          v162 = uMessageParam;
+          v148 = 195;
+          goto LABEL_438;
+        case UIMSG_B1:
+          pAudioPlayer->StopChannels(-1, -1);
+          v162 = 0;
+          v148 = 177;
+LABEL_438:
+          pWindowType = (WindowType)9;
+LABEL_439:
+          pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, pWindowType, v148, v162);
+          goto _continue;
+        case UIMSG_B2:
+          v165 = 0;
+          v151 = 0;
+          v144 = 0;
+          v139 = 0;
+          bRecallingBeacon = uMessageParam;
+          v135 = -1;
+          v132 = 0;
+          v130 = 0;
+          v127 = uMessageParam + 204;
+          goto _play_sound_and_continue;
+        case UIMSG_B4:
+          if ( !pGUIWindow_CurrentMenu )
+            goto _continue;
+          pPlayer = pPlayers[_506348_current_lloyd_playerid + 1];
+          uNumSeconds = (unsigned int)&pPlayer->pInstalledBeacons[uMessageParam];
+          if ( bRecallingBeacon )
+          {
+            if ( !*((int *)&pSavegameThumbnails->pPixels + 10 * uMessageParam) )
+              goto _continue;
+            v173 = pMapStats->pInfos[sub_410D99_get_map_index(HIWORD(pPlayer->pInstalledBeacons[uMessageParam].field_18))].pName;
+            v157 = pGlobalTXT_LocalizationStrings[474];// "Recall to %s"
+            goto _sprintex_2args_draw_status_and_continue;
+          }
+          v59 = pMapStats->GetMapInfo(pCurrentMapName);
+          thise = "Not in Map Stats";
+          if ( v59 )
+            thise = pMapStats->pInfos[v59].pName;
+          if ( !*((int *)&pSavegameThumbnails->pPixels + 10 * uMessageParam) || !v59 )
+          {
+            v173 = thise;
+            v157 = pGlobalTXT_LocalizationStrings[476];// "Set to %s"
+            goto _sprintex_2args_draw_status_and_continue;
+          }
+          v174 = pMapStats->pInfos[sub_410D99_get_map_index(*(short *)(uNumSeconds + 26))].pName;
+          v158 = (unsigned int)thise;
+          v146 = pGlobalTXT_LocalizationStrings[475];// "Set %s over %s"
+_sprintex_draw_status_and_continue:
+          sprintf(pTmpBuf, v146, v158, v174);
+          goto _set_status_string_pTmpBuf_and_continue;
+        case UIMSG_B5:
+          dword_50CDC8 = v0;
+          goto LABEL_453;
+        case UIMSG_B3:
+          pPlayer9 = pPlayers[_506348_current_lloyd_playerid + 1];
+          pNPCData4 = (NPCData *)&pPlayer9->pInstalledBeacons[uMessageParam];
+          if ( !*(_QWORD *)&pNPCData4->pName && bRecallingBeacon )
+            goto _continue;
+          byte_506360 = 1;
+          pPlayer9->CanCastSpell(uRequiredMana);
+          if ( pParty->bTurnBasedModeOn )
+          {
+            v60 = sRecoveryTime;
+            pParty->pTurnBasedPlayerRecoveryTimes[_506348_current_lloyd_playerid] = sRecoveryTime;
+            pPlayer9->SetRecoveryTime(v60);
+            pTurnEngine->_40471C();
+          }
+          else
+          {
+            pPlayer9->SetRecoveryTime((signed __int64)(flt_6BE3A4_debug_recmod1 * (double)sRecoveryTime * 2.133333333333333));
+          }
+          pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[dword_506338], 0, 0, -1, 0, dword_50633C, 0, 0);
+          if ( bRecallingBeacon )
+          {
+            if ( _strcmpi(pCurrentMapName, (const char *)&pGames_LOD->pSubIndices[HIWORD(pNPCData4->uProfession)]) )
+            {
+              SaveGame(v0, 0);
+              OnMapLeave();
+              strcpy(pCurrentMapName, (const char *)&pGames_LOD->pSubIndices[HIWORD(pNPCData4->uProfession)]);
+              dword_6BE364_game_settings_1 |= v0;
+              uGameState = 2;
+              _5B65A8_npcdata_uflags_or_other = pNPCData4->uFlags;
+              _5B65AC_npcdata_fame_or_other = pNPCData4->fame;
+              _5B65B0_npcdata_rep_or_other = pNPCData4->rep;
+              _5B65B4_npcdata_loword_house_or_other = LOWORD(pNPCData4->house);
+              _5B65B8_npcdata_hiword_house_or_other = HIWORD(pNPCData4->house);
+              dword_5B65C0 = v0;
+            }
+            else
+            {
+              pParty->vPosition.x = pNPCData4->uFlags;
+              pParty->vPosition.y = pNPCData4->fame;
+              pParty->vPosition.z = pNPCData4->rep;
+              pParty->uFallStartY = pParty->vPosition.z;
+              pParty->sRotationY = LOWORD(pNPCData4->house);
+              pParty->sRotationX = HIWORD(pNPCData4->house);
+            }
+            if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+            {
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v0;
+              *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+              ++pMessageQueue_50CBD0->uNumMessages;
+            }
+            //crt_deconstruct_ptr_6A0118();
+            pBooksWindow->Release();
+            pGUIWindow_CurrentMenu->Release();
+            pBooksWindow = 0;
+            pGUIWindow_CurrentMenu = 0;
+          }
+          else
+          {
+            sprintf(a1, "data\\lloyd%d%d.pcx", _506348_current_lloyd_playerid + 1, uMessageParam + 1);
+            SaveScreenshot(a1);
+            LoadThumbnailLloydTexture(uMessageParam, _506348_current_lloyd_playerid + 1);
+            v212 = qword_506350 << 7;
+            pNPCData2 = pNPCData4;
+            thisg = 0;
+            v62 = pParty->uTimePlayed + (signed __int64)((double)(qword_506350 << 7) * 0.033333335);
+            pNPCData4->pName = (char *)v62;
+            pNPCData2->uPortraitID = HIDWORD(v62);
+            pNPCData2->uFlags = pParty->vPosition.x;
+            pNPCData2->fame = pParty->vPosition.y;
+            pNPCData2->rep = pParty->vPosition.z;
+            LOWORD(pNPCData2->house) = LOWORD(pParty->sRotationY);
+            HIWORD(pNPCData2->house) = LOWORD(pParty->sRotationX);
+            if ( (signed int)pGames_LOD->uNumSubIndices / 2 <= 0 )
+              goto _continue;
+            uAction = 0;
+            while ( _strcmpi((const char *)pGames_LOD->pSubIndices + uAction, pCurrentMapName) )
+            {
+              ++thisg;
+              uAction += 32;
+              if ( thisg >= (signed int)pGames_LOD->uNumSubIndices / 2 )
+                goto _continue;
+            }
+            HIWORD(pNPCData4->uProfession) = thisg;
+          }
+          goto _continue;
+        case UIMSG_B7:
+          if ( uMessageParam )
+          {
+            switch ( uMessageParam )
+            {
+              case 1:
+                v63 = 208;
+                break;
+              case 2:
+                v63 = 207;
+                break;
+              case 3:
+                v63 = 211;
+                break;
+              case 4:
+                v63 = 209;
+                break;
+              default:
+                if ( uMessageParam != 5 )
+                {
+LABEL_486:
+                  SaveGame(v0, 0);
+                  v64 = pMapStats->GetMapInfo(pCurrentMapName);
+                  v65 = uMessageParam;
+                  if ( v64 == stru_4ECBB8[uMessageParam].uMapInfoID )
+                  {
+                    pParty->vPosition.x = stru_4ECBB8[v65].pos.x;
+                    pParty->vPosition.y = stru_4ECBB8[v65].pos.y;
+                    pParty->vPosition.z = stru_4ECBB8[v65].pos.z;
+                    pParty->uFallStartY = pParty->vPosition.z;
+                    pParty->sRotationY = stru_4ECBB8[v65].rot_y;
+                    pParty->sRotationX = stru_4ECBB8[v65].rot_x;
+                  }
+                  else
+                  {
+                    SaveGame(v0, 0);
+                    OnMapLeave();
+                    dword_6BE364_game_settings_1 |= v0;
+                    uGameState = 2;
+                    strcpy(pCurrentMapName, pMapStats->pInfos[stru_4ECBB8[uMessageParam].uMapInfoID].pFilename);
+                    dword_5B65C0 = v0;
+                    _5B65A8_npcdata_uflags_or_other = stru_4ECBB8[uMessageParam].pos.x;
+                    _5B65AC_npcdata_fame_or_other = stru_4ECBB8[uMessageParam].pos.y;
+                    _5B65B0_npcdata_rep_or_other = stru_4ECBB8[uMessageParam].pos.z;
+                    v66 = stru_4ECBB8[uMessageParam].rot_x;
+                    _5B65B4_npcdata_loword_house_or_other = stru_4ECBB8[uMessageParam].rot_y;
+                    _5B65B8_npcdata_hiword_house_or_other = v66;
+                    InitializeActors();
+                  }
+                  v67 = pGUIWindow_CurrentMenu->Hint;
+                  if ( v67 )
+                    *((int *)v67 + 17) = v0;
+                  else
+                    pParty->pPlayers[(unsigned __int8)byte_50C0C0].CanCastSpell(0x14u);
+LABEL_434:
+                  if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+                  {
+                    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+                    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v0;
+LABEL_771:
+                    *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+                    ++pMessageQueue_50CBD0->uNumMessages;
+                  }
+                  goto _continue;
+                }
+                v63 = 210;
+                break;
+            }
+          }
+          else
+          {
+            v63 = 206;
+          }
+          if ( !(unsigned __int16)_449B57_test_bit(pParty->_award_bits, v63) )
+            return;
+          goto LABEL_486;
+        case UIMSG_B6:
+          if ( uMessageParam )
+          {
+            switch ( uMessageParam )
+            {
+              case 1:
+                v68 = 208;
+                break;
+              case 2:
+                v68 = 207;
+                break;
+              case 3:
+                v68 = 211;
+                break;
+              case 4:
+                v68 = 209;
+                break;
+              default:
+                if ( uMessageParam != 5 )
+                  goto LABEL_506;
+                v68 = 210;
+                break;
+            }
+          }
+          else
+          {
+            v68 = 206;
+          }
+          if ( !(unsigned __int16)_449B57_test_bit(pParty->_award_bits, v68) )
+          {
+            pRenderer->DrawTextureRGB(0, 0x160u, pTexture_StatusBar);
+            goto _continue;
+          }
+LABEL_506:
+          if ( uMessageParam )
+          {
+            switch ( uMessageParam )
+            {
+              case 1:
+                v69 = pMapStats->pInfos[4].pName;
+                break;
+              case 2:
+                v69 = pMapStats->pInfos[3].pName;
+                break;
+              case 3:
+                v69 = pMapStats->pInfos[10].pName;
+                break;
+              case 4:
+                v69 = pMapStats->pInfos[7].pName;
+                break;
+              default:
+                if ( uMessageParam != 5 )
+                  //goto LABEL_519;
+				  {
+				   v173 = v200;
+                   v157 = pGlobalTXT_LocalizationStrings[35];
+                   goto _sprintex_2args_draw_status_and_continue;
+			      }
+                v69 = pMapStats->pInfos[8].pName;
+                break;
+            }
+          }
+          else
+          {
+            v69 = pMapStats->pInfos[21].pName;
+          }
+          v200 = v69;
+//LABEL_519:
+          v173 = v200;
+          v157 = pGlobalTXT_LocalizationStrings[35];
+          goto _sprintex_2args_draw_status_and_continue;
+        case UIMSG_ShowFinalWindow:
+          sprintf(pFinalMessage, "%s\n \n%s\n \n%s", pGlobalTXT_LocalizationStrings[151],// "Congratulations Adventurer."
+            pGlobalTXT_LocalizationStrings[118],// "We hope that you've enjoyed playing Might and Magic VII as much as we did making it. We have saved this screen as MM7_WIN.PCX in your MM7 directory. You can print it out as proof of your accomplishment."
+            pGlobalTXT_LocalizationStrings[167]);// "- The Might and Magic VII Development Team."   
+          ModalWindow(pFinalMessage, 196);
+          uGameState = GAME_STATE_FINAL_WINDOW;
+          goto _continue;
+        case UIMSG_C4:
+          uGameState = 0;
+          strcpy((char *)pKeyActionMap->pPressedKeysBuffer, "2");
+          goto LABEL_524;
+        case UIMSG_D5|0x8:
+LABEL_524:
+          sprintf(pTmpBuf, "%s", pKeyActionMap->pPressedKeysBuffer);
+          memcpy(&v216, texture_frame_table_txt_parser((const char *)pKeyActionMap->pPressedKeysBuffer, &v218), sizeof(v216));
+          if ( v216.field_0 == 1 )
+          {
+            pNPCData4 = (NPCData *)((signed int)pGames_LOD->uNumSubIndices / 2);
+            v70 = atoi(v216.pProperties[0]);
+            if ( v70 <= 0 || v70 >= 77 )
+            {
+LABEL_90:
+              v1 = "";
+LABEL_91:
+              v0 = 1;
+              goto _continue;
+            }
+            v71 = v70;
+            strcpy(Str2, pMapStats->pInfos[v70].pFilename);
+            pNPCData3 = 0;
+            if ( (signed int)pNPCData4 > 0 )
+            {
+              thish = 0;
+              do
+              {
+                if ( !_strcmpi((const char *)&pGames_LOD->pSubIndices[thish], Str2) )
+                  break;
+                ++thish;
+                pNPCData3 = (NPCData *)((char *)pNPCData3 + 1);
+              }
+              while ( (signed int)pNPCData3 < (signed int)pNPCData4 );
+              if ( (signed int)pNPCData3 < (signed int)pNPCData4 )
+              {
+                strcpy(pCurrentMapName, (const char *)&pGames_LOD->pSubIndices[(int)pNPCData3]);
+                dword_6BE364_game_settings_1 |= 1u;
+                uGameState = 2;
+                OnMapLeave();
+                //goto LABEL_90;
+				v1 = "";
+                v0 = 1;
+                goto _continue;
+              }
+            }
+            sprintf(Str2, "No map found for %s", pMapStats->pInfos[v71].pName);
+            v73 = Str2;
+          }
+          else
+          {
+            if ( v216.field_0 != 3 )
+              goto LABEL_90;
+            v74 = atoi(v216.pProperties[0]);
+            thisi = atoi(v216.pProperties[1]);
+            v75 = atoi(v216.pProperties[2]);
+            v76 = v75;
+            if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+            {
+              if ( pIndoor->GetSector(v74, thisi, v75) )
+              {
+                v77 = thisi;
+LABEL_544:
+                pParty->vPosition.x = v74;
+                pParty->vPosition.y = v77;
+                pParty->vPosition.z = v76;
+                pParty->uFallStartY = v76;
+                goto LABEL_90;
+              }
+            }
+            else
+            {
+              if ( v74 > -32768 )
+              {
+                if ( v74 < 32768 )
+                {
+                  v77 = thisi;
+                  if ( thisi > -32768 )
+                  {
+                    if ( thisi < 32768 && v76 >= 0 && v76 < 10000 )
+                      goto LABEL_544;
+                  }
+                }
+              }
+            }
+            pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+            v73 = "Can't jump to that location!";
+          }
+          ShowStatusBarString(v73, 6u);
+          //goto LABEL_90;
+		  v1 = "";
+          v0 = 1;
+          goto _continue;
+        case 0x19:
+          if ( bUnderwater == 1 )
+            goto LABEL_682;
+          if ( !uActiveCharacter || (pPlayer2 = pPlayers[uActiveCharacter], pPlayer2->uTimeToRecovery) )
+            goto LABEL_90;
+          v79 = pPlayer2->uQuickSpell;
+          v175 = uActiveCharacter;
+          v159 = 0;
+          v147 = 0;
+          v80 = uActiveCharacter - 1;
+          goto LABEL_679;
+        case 0x46:
+        case UIMSG_Quit|0x8:
+          if ( pRenderer->pRenderD3D )
+          {
+            v81 = pGame->pVisInstance->get_picked_object_zbuf_val();
+          }
+          else
+          {
+            uNumSeconds = (unsigned int)pMouse->GetCursorPos(&v206);
+            pPoint2 = pMouse->GetCursorPos(&v201);
+            v81 = pRenderer->pActiveZBuffer[*(int *)uNumSeconds + pSRZBufferLineOffsets[pPoint2->y]];
+          }
+          v83 = v81;
+          v44 = (unsigned __int16)v81;
+          v84 = v83 >> 16;
+          if ( (v44 & 7) != 3 || v84 >= 5120 )
+            //goto LABEL_90;
+		  {
+			v1 = "";
+            v0 = 1;
+            goto _continue;
+		  }
+          v51 = pGUIWindow_Settings->ptr_1C;
+          if ( uMessage == 70 )
+          {
+            *((char *)v51 + 8) &= 0xF7u;
+          }
+          else
+          {
+            if ( uMessage == 140 )
+              *((char *)v51 + 9) &= 0xFEu;
+            else
+              *((char *)v51 + 9) &= 0xFDu;
+          }
+          goto LABEL_416;
+        case 0x1C:
+          if ( !uActiveCharacter || pCurrentScreen )
+            //goto LABEL_90;
+		  {
+			v1 = "";
+            v0 = 1;
+            goto _continue;
+		  }
+          ptr_507BC8 = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)104, uMessageParam, 0);
+          pCurrentScreen = 25;
+          pEventTimer->Pause();
+          goto _continue;
+        case 0x1B:
+          if ( !uActiveCharacter )
+            //goto LABEL_90;
+		  {
+			v1 = "";
+            v0 = 1;
+            goto _continue;
+		  }
+          if ( pParty->bTurnBasedModeOn != v0 )
+            goto LABEL_569;
+          if ( pTurnEngine->field_4 == v0 || pTurnEngine->field_4 == 3 )
+            //goto LABEL_90;
+		  {
+			v1 = "";
+            v0 = 1;
+            goto _continue;
+		  }
+          if ( !(pTurnEngine->field_18 & 2) )
+          {
+LABEL_569:
+            if ( pActors[uMessageParam].uAIState == 5 )
+              stru_50C198.LootActor(&pActors[uMessageParam]);
+            else
+              Actor::StealFrom(uMessageParam);
+          }
+          goto _continue;
+        case 0x17:
+          if ( !uActiveCharacter )
+            //goto LABEL_90;
+		  {
+			v1 = "";
+            v0 = 1;
+            goto _continue;
+		  }
+          if ( pParty->bTurnBasedModeOn != v0 )
+            goto LABEL_577;
+          if ( pTurnEngine->field_4 == v0 || pTurnEngine->field_4 == 3 )
+            //goto LABEL_90;
+		  {
+			v1 = "";
+            v0 = 1;
+            goto _continue;
+		  }
+          if ( !(pTurnEngine->field_18 & 2) )
+LABEL_577:
+            _42ECB5_PlayerAttacksActor();
+          goto _continue;
+        case UIMSG_A7:
+          v163 = (int)pGlobalTXT_LocalizationStrings[81];// "Exit Rest"
+          pButton = pButton_RestUI_Exit;
+          pButton2 = pButton_RestUI_Exit;
+          pWindowType1 = (WindowType)96;
+          goto LABEL_731;
+        case UIMSG_ShowStatus_Player|0x1:
+          if ( dword_506F14 == 2 )
+            goto LABEL_621;
+          GUIWindow::Create(pButton_RestUI_Wait5Minutes->uX, pButton_RestUI_Wait5Minutes->uY, 0, 0, (enum WindowType)90,
+            (int)pButton_RestUI_Wait5Minutes, (int)pGlobalTXT_LocalizationStrings[238]);// "Wait 5 Minutes"
+          dword_506F14 = v0;
+          _506F18_num_hours_to_sleep = 5;
+          goto _continue;
+        case 0x60:
+          if ( dword_506F14 == 2 )
+            goto LABEL_621;
+          GUIWindow::Create(pButton_RestUI_Wait1Hour->uX, pButton_RestUI_Wait1Hour->uY, 0, 0, (enum WindowType)90,
+            (int)pButton_RestUI_Wait1Hour, (int)pGlobalTXT_LocalizationStrings[239]);// "Wait 1 Hour"
+          dword_506F14 = v0;
+          _506F18_num_hours_to_sleep = 60;
+          goto _continue;
+        case UIMSG_OpenRestUI:
+          dword_506F14 = 2;
+          RestUI_Initialize();
+          v86 = 60 * (sub_494820(pParty->uCurrentHour) + 1) - pParty->uCurrentMinute;
+          _506F18_num_hours_to_sleep = v86;
+          if ( uMessageParam == 111 || uMessageParam == 114 || uMessageParam == 116 )
+            _506F18_num_hours_to_sleep = v86 + 720;
+          goto LABEL_615;
+        case 0x68:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( pCurrentScreen )
+            goto _continue;
+          if ( sub_42F4DA() )
+            goto LABEL_594;
+          if ( pParty->bTurnBasedModeOn == v0 )
+            goto LABEL_595;
+          if ( !(pParty->uFlags & 0x88) )
+          {
+            RestUI_Initialize();
+            goto _continue;
+          }
+LABEL_594:
+          if ( pParty->bTurnBasedModeOn == v0 )
+          {
+LABEL_595:
+            v87 = pGlobalTXT_LocalizationStrings[478];// "You can't rest in turn-based mode!"
+            goto _draw_status_string_and_continue;
+          }
+          v88 = pGlobalTXT_LocalizationStrings[480];// "There are hostile enemies near!"
+          if ( pParty->uFlags & 0x88 )
+            v88 = pGlobalTXT_LocalizationStrings[479];// "You can't rest here!"
+          ShowStatusBarString(v88, 2u);
+          v89 = uActiveCharacter;
+          if ( !uActiveCharacter )
+            //goto LABEL_90;
+		  {
+			v1 = "";
+            v0 = 1;
+            goto _continue;
+		  }
+          v176 = 0;
+          v160 = 13;
+          goto LABEL_619;
+        case 0x61:
+          if ( dword_506F14 )
+            goto LABEL_621;
+          if ( pParty->uNumFoodRations < uRestUI_FoodRequiredToRest )
+          {
+            ShowStatusBarString(pGlobalTXT_LocalizationStrings[482], 2u);// "You don't have enough food to rest"
+            if ( uActiveCharacter && pPlayers[uActiveCharacter]->CanAct() )
+            {
+              v89 = uActiveCharacter;
+              v176 = 0;
+              v160 = 108;
+LABEL_619:
+              pPlayers[v89]->PlaySound(v160, v176);
+            }
+          }
+          else
+          {
+            pParty->pPlayers[3].pConditions[2] = pParty->uTimePlayed;
+            pParty->pPlayers[2].pConditions[2] = pParty->uTimePlayed;
+            pParty->pPlayers[1].pConditions[2] = pParty->uTimePlayed;
+            pParty->pPlayers[0].pConditions[2] = pParty->uTimePlayed;
+            v90 = pMapStats->GetMapInfo(pCurrentMapName);
+            if ( !v90 )
+              v90 = rand() % (signed int)pMapStats->uNumMaps + 1;
+            pMapInfo = &pMapStats->pInfos[v90];
+            if ( rand() % 100 + 1 <= pMapInfo->field_30 )
+            {
+              v91 = rand() % 100;
+              v92 = pMapInfo->field_31;
+              v93 = v91 + 1;
+              if ( v93 > v92 )
+                pNPCData4 = (NPCData *)((v93 > v92 + pMapInfo->field_32) + 2);
+              else
+                pNPCData4 = (NPCData *)v0;
+              if ( !sub_45063B(pMapInfo, (int)pNPCData4) )
+                pNPCData4 = 0;
+              if ( pNPCData4 )
+              {
+                pPlayerNum = rand() % 4;
+                LODWORD(pParty->pPlayers[pPlayerNum].pConditions[2]) = 0;
+                HIDWORD(pParty->pPlayers[pPlayerNum].pConditions[2]) = 0;
+                v95 = rand();
+                Rest(v95 % 6 + 60);
+                _506F18_num_hours_to_sleep = 0;
+                dword_506F14 = 0;
+                if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+                {
+                  pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+                  pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+                  *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+                  ++pMessageQueue_50CBD0->uNumMessages;
+                }
+                ShowStatusBarString(pGlobalTXT_LocalizationStrings[481], 2u);// "Encounter!"
+                v165 = 0;
+                v151 = 0;
+                v144 = 0;
+                v139 = 0;
+                v135 = -1;
+                v132 = 0;
+                v130 = 0;
+                v127 = 227;
+                goto _play_sound_and_continue;
+              }
+            }
+            Party::TakeFood(uRestUI_FoodRequiredToRest);
+            _506F18_num_hours_to_sleep = 480;
+LABEL_615:
+            dword_506F14 = 2;
+            pParty->RestAndHeal();
+            pParty->field_764 = 0;
+            pParty->pPlayers[3].pConditions[2] = pParty->uTimePlayed;
+            pParty->pPlayers[2].pConditions[2] = pParty->uTimePlayed;
+            pParty->pPlayers[1].pConditions[2] = pParty->uTimePlayed;
+            pParty->pPlayers[0].pConditions[2] = pParty->uTimePlayed;
+          }
+          goto _continue;
+        case UIMSG_ShowStatus_Funds|0x8:
+          if ( dword_506F14 == 2 )
+          {
+LABEL_621:
+            v96 = pGlobalTXT_LocalizationStrings[477];// "You are already resting!"
+            goto LABEL_622;
+          }
+          GUIWindow::Create(pButton_RestUI_WaitUntilDawn->uX, pButton_RestUI_WaitUntilDawn->uY, 0, 0, (enum WindowType)90,
+            (int)pButton_RestUI_WaitUntilDawn, (int)pGlobalTXT_LocalizationStrings[237]);// "Wait until Dawn"
+          v97 = sub_494820(pParty->uCurrentHour);
+          dword_506F14 = v0;
+          _506F18_num_hours_to_sleep = 60 * v97 - pParty->uCurrentMinute;
+          goto _continue;
+        case 0x4E:
+          if ( dword_50654C && byte_506550 )
+          {
+            v173 = pSpellStats->pInfos[dword_50654C + 11 * pPlayers[uActiveCharacter]->pNumSpellBookPage].pName;
+            v157 = pGlobalTXT_LocalizationStrings[483];
+_sprintex_2args_draw_status_and_continue:
+            sprintf(pTmpBuf, v157, v173);
+          }
+          else
+          {
+            if ( pPlayers[uActiveCharacter]->uQuickSpell )
+              v177 = pGlobalTXT_LocalizationStrings[584];// "Click here to remove your Quick Spell"
+            else
+              v177 = pGlobalTXT_LocalizationStrings[484];// "Select a spell then click here to set a QuickSpell"
+            strcpy(pTmpBuf, v177);
+          }
+_set_status_string_pTmpBuf_and_continue:
+          sub_41C0B8_set_status_string(pTmpBuf);
+          goto _continue;
+        case 0x4F:
+          if ( !uActiveCharacter
+            || (uNumSeconds = (unsigned int)pPlayers[uActiveCharacter],
+                !*(char *)(uNumSeconds + 11 * *(char *)(uNumSeconds + 6734) + uMessageParam + 402)) )
+            goto _continue;
+          if ( sub_4637E0_is_there_popup_onscreen() )
+            dword_507B00_spell_info_to_draw_in_popup = uMessageParam + 1;
+          v98 = *(char *)(uNumSeconds + 6734);
+          if ( dword_50654C - 1 == uMessageParam )
+          {
+            v178 = pSpellStats->pInfos[uMessageParam + 11 * v98 + 1].pName;
+            v161 = pGlobalTXT_LocalizationStrings[485];
+          }
+          else
+          {
+            v178 = pSpellStats->pInfos[uMessageParam + 11 * v98 + 1].pName;
+            v161 = pGlobalTXT_LocalizationStrings[486];
+          }
+          sprintf(pTmpBuf, v161, v178);
+          sub_41C0B8_set_status_string(pTmpBuf);
+          goto LABEL_91;
+        case 0x58:
+          GUIWindow::Create(pBtn_InstallRemoveSpell->uX, pBtn_InstallRemoveSpell->uY, 0, 0, (enum WindowType)90, (int)pBtn_InstallRemoveSpell, 0);
+          if ( !uActiveCharacter )
+            goto _continue;
+          pPlayer10 = pPlayers[uActiveCharacter];
+          if ( !byte_506550 || !dword_50654C )
+          {
+            v165 = 0;
+            v151 = 0;
+            v144 = 0;
+            v139 = 0;
+            v135 = -1;
+            v132 = 0;
+            pPlayer10->uQuickSpell = 0;
+            v130 = 0;
+            dword_50654C = 0;
+            v127 = 203;
+            goto _play_sound_and_continue;
+          }
+          v99 = dword_50654C + 11 * pPlayers[uActiveCharacter]->pNumSpellBookPage;
+          pPlayers[uActiveCharacter]->uQuickSpell = v99;
+          stru_A750F8[uActiveCharacter + 3]._494836(v99, uActiveCharacter);
+          if ( uActiveCharacter )
+            pPlayer10->PlaySound(12, 0);
+          byte_506550 = 0;
+          goto _continue;
+        case 0x33:
+          if ( !uActiveCharacter )
+            goto _continue;
+          pPlayer3 = pPlayers[uActiveCharacter];
+          pNPCData4 = 0;
+          uAction = 0;
+          v101 = 0;
+          thisl = (int)&pPlayer3->pActiveSkills[12];
+          do
+          {
+            if ( *(short *)thisl )
+            {
+              if ( pPlayer3->pNumSpellBookPage == v101 )
+                uAction = (int)pNPCData4;
+              v102 = (int)pNPCData4;
+              pNPCData4 = (NPCData *)((char *)pNPCData4 + 1);
+              v217[v102] = v101;
+            }
+            thisl += 2;
+            ++v101;
+          }
+          while ( v101 < 9 );
+          if ( !pNPCData4 )
+            goto LABEL_662;
+          if ( GetAsyncKeyState(16) )
+          {
+            --uAction;
+            if ( uAction < 0 )
+              uAction = (int)((char *)pNPCData4 - 1);
+          }
+          else
+          {
+            ++uAction;
+            if ( uAction >= (signed int)pNPCData4 )
+              uAction = 0;
+          }
+          sub_41140B();
+          pPlayers[uActiveCharacter]->pNumSpellBookPage = LOBYTE(v217[uAction]);
+          goto LABEL_661;
+        case UIMSG_SaveGame|0x4:
+          if ( pTurnEngine->field_4 == 3 || !uActiveCharacter || uMessageParam == pPlayers[uActiveCharacter]->pNumSpellBookPage )
+            goto _continue;
+          sub_41140B();
+          pPlayers[uActiveCharacter]->pNumSpellBookPage = uMessageParam;
+LABEL_661:
+          pGUIWindow_CurrentMenu->_411621();
+LABEL_662:
+          v165 = 0;
+          v151 = 0;
+          v144 = 0;
+          v139 = 0;
+          v135 = -1;
+          v132 = 0;
+          v130 = 0;
+          v127 = rand() % 2 + 204;
+          goto _play_sound_and_continue;
+        case UIMSG_LoadGame|0x4:
+          if ( pTurnEngine->field_4 != 3 )
+          {
+            if ( uActiveCharacter )
+            {
+              uNumSeconds = (unsigned int)pPlayers[uActiveCharacter];
+              if ( *(char *)(uNumSeconds + 11 * *(char *)(uNumSeconds + 6734) + uMessageParam + 402) )
+              {
+                if ( dword_50654C - 1 == uMessageParam )
+                {
+                  pGUIWindow_CurrentMenu->Release();
+                  pEventTimer->Resume();
+                  viewparams->bRedrawGameUI = v0;
+                  pCurrentScreen = 0;
+                  pIcons_LOD->_4114F2();
+                  v103 = dword_50654C + 11 * *(char *)(uNumSeconds + 6734);
+                  if ( dword_50C9E8 < 40 )
+                  {
+                    dword_50C9EC[3 * dword_50C9E8] = 142;
+                    dword_50C9F0[3 * dword_50C9E8] = v103;
+                    *(&dword_50C9E8 + 3 * dword_50C9E8 + 3) = uActiveCharacter - 1;
+                    ++dword_50C9E8;
+                  }
+                }
+                else
+                {
+                  byte_506550 = 1;
+                  dword_50654C = uMessageParam + 1;
+                }
+              }
+            }
+          }
+          goto _continue;
+        case 0x8E:
+          if ( pTurnEngine->field_4 == 3 )
+            goto _continue;
+          v175 = 0;
+          v159 = 0;
+          v147 = 0;
+          goto LABEL_678;
+        case 0x92:
+          if ( pTurnEngine->field_4 != 3 )
+          {
+            v175 = 0;
+            v159 = v0;
+            v147 = 133;
+LABEL_678:
+            v80 = v199;
+            v79 = uMessageParam;
+LABEL_679:
+            _42777D_CastSpell_UseWand_ShootArrow(v79, v80, v147, v159, v175);
+          }
+          goto _continue;
+        case 0x69:
+          if ( pTurnEngine->field_4 == 3 )
+            goto _continue;
+          if ( bUnderwater == 1 )
+          {
+LABEL_682:
+            v96 = pGlobalTXT_LocalizationStrings[652];// "You can not do that while you are underwater!"
+LABEL_622:
+            ShowStatusBarString(v96, 2u);
+LABEL_623:
+            v165 = 0;
+            v151 = 0;
+            v144 = 0;
+            v139 = 0;
+            v135 = -1;
+            v132 = 0;
+            v130 = 0;
+            v127 = 27;
+_play_sound_and_continue:
+            pAudioPlayer->PlaySound((SoundID)v127, v130, v132, v135, v139, v144, v151, v165);
+          }
+          else
+          {
+            if ( pMessageQueue_50CBD0->uNumMessages )
+              pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+            if ( uActiveCharacter && !pPlayers[uActiveCharacter]->uTimeToRecovery )
+            {
+              if ( !pCurrentScreen )
+                goto LABEL_693;
+              if ( pCurrentScreen != 5
+                && pCurrentScreen != 7
+                && (pCurrentScreen <= 99
+                 || pCurrentScreen > 103) )
+              {
+                pGUIWindow_CurrentMenu->Release();
+LABEL_693:
+                GUIWindow::Create(0x1DCu, 0x1C2u, 0, 0, (enum WindowType)90, (int)pBtn_CastSpell, 0);
+                pCurrentScreen = 8;
+                pEventTimer->Pause();
+                pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)18, 0, 0);
+                pAudioPlayer->PlaySound((SoundID)48, 0, 0, -1, 0, 0, 0, 0);
+                viewparams->field_48 = v0;
+                goto _continue;
+              }
+            }
+          }
+          goto _continue;
+        case 0x6A:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          if ( pCurrentScreen )
+            pGUIWindow_CurrentMenu->Release();
+          ++pIcons_LOD->uTexturePacksCount;
+          if ( !pIcons_LOD->uNumPrevLoadedFiles )
+            pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+          GUIWindow::Create(0x230u, 0x1C2u, 0, 0, (enum WindowType)90, (int)pBtn_QuickReference, 0);
+          viewparams->bRedrawGameUI = v0;
+          pEventTimer->Pause();
+          pAudioPlayer->StopChannels(-1, -1);
+          pCurrentScreen = 104;
+          pGUIWindow_CurrentMenu = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)12, 5, 0);
+          papredoll_dbrds[2] = pIcons_LOD->LoadTexture("BUTTEXI1", TEXTURE_16BIT_PALETTE);
+          pBtn_ExitCancel = pGUIWindow_CurrentMenu->CreateButton(0x187u, 0x13Cu, 0x4Bu, 0x21u, v0, 0, 0x71u, 0, 0,
+                         pGlobalTXT_LocalizationStrings[79],// "Exit"
+                         (Texture *)(uTextureID_BUTTDESC2 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BUTTDESC2] : 0), 0, v179);
+          goto _continue;
+        case 0x6B:
+          if ( pCurrentScreen )
+          {
+            pGUIWindow_CurrentMenu->Release();
+            pEventTimer->Resume();
+            pCurrentScreen = 0;
+            viewparams->bRedrawGameUI = v0;
+          }
+          stru_506E40.Release();
+          uNumSeconds = (unsigned int)MakeScreenshot(155, 117);
+          pRenderer->SavePCXImage("gamma.pcx", (char *)uNumSeconds, 155, 117);
+          free((void *)uNumSeconds);
+          stru_506E40._40E55E("gamma.pcx", 0);
+          GUIWindow::Create(0x25Au, 0x1C2u, 0, 0, (enum WindowType)92, (int)pBtn_GameSettings, 0);
+LABEL_453:
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages >= 40 )
+            goto _continue;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+          goto LABEL_770;
+        case UIMSG_C0:
+          dword_50651C = v0;
+          if ( pMouse->GetCursorPos(&v211)->y > 178 )
+            dword_50651C = -1;
+          goto _continue;
+        case UIMSG_A9:
+          GUIWindow::Create(pBtn_Up->uX, pBtn_Up->uY, 0, 0, (WindowType)(WINDOW_HouseInterior|0x42), (int)pBtn_Up, 0);
+LABEL_707:
+          dword_506548 = v0;
+          goto _continue;
+        case UIMSG_AA:
+          GUIWindow::Create(pBtn_Down->uX, pBtn_Down->uY, 0, 0, (WindowType)(WINDOW_HouseInterior|0x42), (int)pBtn_Down, 0);
+LABEL_709:
+          dword_506544 = v0;
+          goto _continue;
+        case 0x55:
+          bRingsShownInCharScreen ^= v0;
+          GUIButton::_41D0D8(pCharacterScreen_DetalizBtn);
+          GUIButton::_41D0D8(pCharacterScreen_DollBtn);
+          if ( bRingsShownInCharScreen )
+          {
+            v128 = (uTextureID_5118C8 != -1 ? pIcons_LOD->pTextures[uTextureID_5118C8].uTextureHeight : 26);
+            v125 = (uTextureID_5118C8 != -1 ? pIcons_LOD->pTextures[uTextureID_5118C8].uTextureWidth : 24);
+            v123 = 445;
+            v121 = 470;
+          }
+          else
+          {
+            v128 = 30;
+            v125 = 30;
+            v123 = 300;
+            v121 = 600;
+          }
+          pCharacterScreen_DetalizBtn = pGUIWindow_CurrentMenu->CreateButton(v121, v123, v125, v128, v0, 0, 0x55u, 0, 0,
+                         pGlobalTXT_LocalizationStrings[64],// "Detail Toggle"
+                         0);
+          pCharacterScreen_DollBtn = pGUIWindow_CurrentMenu->CreateButton(0x1DCu, 0, 0xA4u, 0x159u, v0, 0, 0x85u, 0, 0, v1, 0);
+          goto LABEL_422;
+        case UIMSG_Quit|0x1:
+          OnPaperdollLeftClick();
+          goto _continue;
+        case UIMSG_CloseBook|0x2:
+          pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 100;
+          sub_4196A0();
+          sub_419379();
+          pButton = pCharacterScreen_StatsBtn;
+          goto LABEL_716;
+        case UIMSG_ChangeMusicVolume|0x2:
+          pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 101;
+          sub_4196A0();
+          sub_419379();
+          sub_419401();
+          pButton = pCharacterScreen_SkillsBtn;
+          goto LABEL_716;
+        case UIMSG_SkillUp:
+          pPlayer4 = pPlayers[uActiveCharacter];
+          v105 = (int)&pPlayer4->pActiveSkills[uMessageParam];
+          LOWORD(v2) = *(short *)v105;
+          uNumSeconds = v2;
+          if ( pPlayer4->uSkillPoints < (v2 & 0x3F) + 1 )
+          {
+            v87 = pGlobalTXT_LocalizationStrings[488];// "You don't have enough skill points!"
+          }
+          else
+          {
+            if ( (uNumSeconds & 0x3F) < 0x3C )
+            {
+              *(short *)v105 = uNumSeconds + 1;
+              pPlayer4->uSkillPoints -= pPlayer4->pActiveSkills[uMessageParam] & 0x3F;
+              pPlayer4->PlaySound(14, 0);
+              v165 = 0;
+              v151 = 0;
+              v144 = 0;
+              v139 = 0;
+              v135 = -1;
+              v132 = 0;
+              v130 = 0;
+              v127 = 20001;
+              goto _play_sound_and_continue;
+            }
+            v87 = pGlobalTXT_LocalizationStrings[487];// "You have already mastered this skill!"
+          }
+_draw_status_string_and_continue:
+          ShowStatusBarString(v87, 2u);
+          goto _continue;
+        case UIMSG_ChangeMusicVolume|0x4:
+          pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
+          sub_419379();
+          sub_4196A0();
+          pButton = pCharacterScreen_InventoryBtn;
+LABEL_716:
+          v163 = 0;
+          pButton2 = pButton;
+          pWindowType1 = (WindowType)91;
+          goto LABEL_731;
+        case UIMSG_A8:
+          pButton = pCharacterScreen_ExitBtn;
+          v163 = 0;
+          pButton2 = pCharacterScreen_ExitBtn;
+          pWindowType1 = (WindowType)97;
+          goto LABEL_731;
+        case UIMSG_CloseBook|0x4:
+          sub_419379();
+          sub_4196A0();
+          sub_419220();
+          pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 102;
+          GUIWindow::Create(pCharacterScreen_AwardsBtn->uX, pCharacterScreen_AwardsBtn->uY, 0, 0, (WindowType)(WINDOW_HouseInterior|0x42),
+            (int)pCharacterScreen_AwardsBtn, 0);
+          sub_419100();
+          goto _continue;
+		case 71://0x47:
+          switch ( uMessageParam )
+          {
+            default:
+              goto _continue;
+            case 11:
+              goto LABEL_707;
+            case 10:
+              goto LABEL_709;
+            case 0:
+              pButton = pBtn_Book_1;
+              dword_506544 = v0;
+              break;
+            case 1:
+              pButton = pBtn_Book_2;
+              dword_506548 = v0;
+              break;
+            case 2:
+              dword_506540 = v0;
+              if ( dword_506364 )
+                goto _continue;
+              pButton = pBtn_Book_3;
+              break;
+            case 3:
+              dword_50653C = v0;
+              if ( dword_506364 )
+                goto _continue;
+              pButton = pBtn_Book_4;
+              break;
+            case 4:
+              dword_506538 = v0;
+              if ( dword_506364 )
+                goto _continue;
+              pButton = pBtn_Book_5;
+              break;
+            case 5:
+              dword_506534 = v0;
+              if ( dword_506364 )
+                goto _continue;
+              pButton = pBtn_Book_6;
+              break;
+            case 6:
+              pButton = pBtn_Autonotes_Misc;
+              dword_506530 = v0;
+              break;
+            case 7:
+              pButton = pBtn_Autonotes_Instructors;
+              dword_50652C = v0;
+              break;
+          }
+          v163 = v0;
+          pButton2 = pButton;
+          pWindowType1 = (WindowType)92;
+LABEL_731:
+          v8 = pButton->uY;
+          v9 = pButton->uX;
+          goto LABEL_732;
+        case UIMSG_SelectCharacter:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          GameUI_OnPlayerPortraitLeftClick(uMessageParam);
+          goto _continue;
+        case UIMSG_ShowStatus_Funds:
+          v174 = (char *)pParty->uNumGoldInBank;
+          v158 = pParty->uNumGold + pParty->uNumGoldInBank;
+          v146 = pGlobalTXT_LocalizationStrings[489];// "You have %d total gold, %d in the Bank""
+          goto _sprintex_draw_status_and_continue;
+        case UIMSG_ShowStatus_DateTime:
+          pNPCData4 = (NPCData *)pParty->uCurrentHour;
+          if ( (signed int)pParty->uCurrentHour <= 12 )
+          {
+            if ( !pNPCData4 )
+              pNPCData4 = (NPCData *)12;
+          }
+          else
+          {
+            pNPCData4 = (NPCData *)((char *)pNPCData4 - 12);
+          }
+          if ( pParty->uCurrentHour < 0xC || (uNumSeconds = v0, pParty->uCurrentHour >= 0x18) )
+            uNumSeconds = 0;
+          sprintf(pTmpBuf, "%d:%02d%s %s %d %s %d", pNPCData4, pParty->uCurrentMinute, aAMPMNames[uNumSeconds], aDayNames[pParty->uDaysPlayed % 7],
+            7 * pParty->uCurrentMonthWeek + pParty->uDaysPlayed % 7 + 1, aMonthNames[pParty->uCurrentMonth], pParty->uCurrentYear);
+          goto _set_status_string_pTmpBuf_and_continue;
+        case UIMSG_ShowStatus_Food:
+          v173 = (char *)pParty->uNumFoodRations;
+          v157 = pGlobalTXT_LocalizationStrings[501];// You have %lu food"
+          goto _sprintex_2args_draw_status_and_continue;
+        case UIMSG_ShowStatus_Player:
+          pPlayer5 = pPlayers[uMessageParam];
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[429], pPlayer5->pName, pClassNames[pPlayer5->uClass]);// "%s the %s"
+          strcat(pTmpBuf, ": ");
+          v107 = pPlayer5->GetMajorConditionIdx();
+          strcat(pTmpBuf, aCharacterConditionNames[v107]);
+          sub_41C0B8_set_status_string(pTmpBuf);
+          v108 = 8 * uMessageParam - 8;
+          LOBYTE(v108) = v108 | 4;
+          pMouse->uPointingObjectID = v108;
+          goto _continue;
+        case UIMSG_ShowStatus_ManaHP:
+          v109 = pGlobalTXT_LocalizationStrings[212];// "Spell Points"
+          v110 = pPlayers[uMessageParam];
+          v111 = v110->GetMaxMana();
+          v112 = v110->sMana;
+          v113 = pGlobalTXT_LocalizationStrings[108];// "Hit Points"
+          v114 = v110->GetMaxHealth();
+          sprintf(pTmpBuf, "%d / %d %s    %d / %d %s", v110->sHealth, v114, v113, v112, v111, v109);
+          goto _set_status_string_pTmpBuf_and_continue;
+        case 0xC:
+          if ( pCurrentScreen == 15 )
+            goto LABEL_762;
+          sub_420E01();
+          goto _continue;
+        case UIMSG_ChangeMusicVolume|0x8:
+LABEL_762:
+          sub_421EA6_OnInventoryLeftClick();
+          goto _continue;
+        case 0xA:
+          if ( !pRenderer->pRenderD3D )
+            goto LABEL_772;
+          v115 = pMessageQueue_50CBD0->uNumMessages;
+          if ( !pMessageQueue_50CBD0->uNumMessages )
+            goto LABEL_768;
+          if ( pMessageQueue_50CBD0->pMessages[0].field_8 )
+          {
+            v115 = v0;
+            pMessageQueue_50CBD0->uNumMessages = v0;
+LABEL_769:
+            pMessageQueue_50CBD0->pMessages[v115].eType = (UIMessageType)14;
+LABEL_770:
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+            goto LABEL_771;
+          }
+          v115 = 0;
+          pMessageQueue_50CBD0->uNumMessages = 0;
+LABEL_768:
+          if ( (signed int)v115 < 40 )
+            goto LABEL_769;
+          goto _continue;
+        case 0xE:
+LABEL_772:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          OnGameViewportClick();
+          goto _continue;
+        case 0xF:
+          if ( pRenderer->pRenderD3D )
+          {
+            LOWORD(v116) = pGame->pVisInstance->get_picked_object_zbuf_val();
+          }
+          else
+          {
+            uNumSeconds = (unsigned int)pMouse->GetCursorPos(&v209);
+            pPoint3 = pMouse->GetCursorPos(&v204);
+            v116 = pRenderer->pActiveZBuffer[*(int *)uNumSeconds + pSRZBufferLineOffsets[pPoint3->y]];
+          }
+          v163 = 0;
+          pButton2 = (GUIButton *)(unsigned __int16)v116;
+          pWindowType1 = (WindowType)15;
+          goto LABEL_779;
+        case 0x54:
+          v163 = 0;
+          pButton2 = (GUIButton *)uMessageParam;
+          pWindowType1 = (WindowType)22;
+LABEL_779:
+          v8 = 0;
+          v9 = 0;
+LABEL_732:
+          v137 = 0;
+          v133 = 0;
+LABEL_733:
+          GUIWindow::Create(v9, v8, v133, v137, pWindowType1, (int)pButton2, v163);
+          goto _continue;
+        case 0x194:
+          if ( pMessageQueue_50CBD0->uNumMessages )
+            pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+          OnPressSpace();
+          goto _continue;
+        case UIMSG_ChangeSoundVolume|0x100:
+          if ( pCurrentScreen )
+            goto _continue;
+          pParty->uFlags |= 2u;
+          GUIWindow::Create(0x207u, 0x88u, 0, 0, (enum WindowType)90, (int)dword_507A14, 0);
+          uNumSeconds = 131072;
+          v118 = 2 * viewparams->uMinimapZoom;
+          ++viewparams->field_28;
+          viewparams->uMinimapZoom *= 2;
+          if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor)
+          {
+            if ( (signed int)v118 > 4096 )
+            {
+              viewparams->uMinimapZoom = 4096;
+              viewparams->field_28 = 12;
+            }
+            goto _continue;
+          }
+          v119 = 2048;
+          if ( (signed int)v118 <= 2048 )
+            goto LABEL_789;
+          viewparams->field_28 = 11;
+          goto LABEL_788;
+        case UIMSG_ChangeMusicVolume|0x100:
+          if ( pCurrentScreen )
+            goto _continue;
+          pParty->uFlags |= 2u;
+          GUIWindow::Create(0x23Eu, 0x88u, 0, 0, (enum WindowType)90, (int)dword_507A18, 0);
+          uNumSeconds = 32768;
+          v118 = (unsigned __int64)((signed __int64)(signed int)viewparams->uMinimapZoom << 15) >> 16;
+          --viewparams->field_28;
+          viewparams->uMinimapZoom = (unsigned __int64)((signed __int64)(signed int)viewparams->uMinimapZoom << 15) >> 16;
+          if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+          {
+            v119 = 512;
+            if ( (signed int)v118 < 512 )
+            {
+              viewparams->field_28 = 9;
+LABEL_788:
+              v118 = v119;
+              viewparams->uMinimapZoom = v119;
+            }
+LABEL_789:
+            dword_576E2C = v118;
+            dword_576E28 = viewparams->field_28;
+          }
+          else
+          {
+            if ( (signed int)v118 < 256 )
+            {
+              viewparams->uMinimapZoom = 256;
+              viewparams->field_28 = 8;
+            }
+          }
+          goto _continue;
+      }
+    }
+  }
+  pMessageQueue_50CBD0->uNumMessages = dword_50C9E8;
+  memcpy(pMessageQueue_50CBD0->pMessages, dword_50C9EC, 12 * dword_50C9E8);
+  dword_50C9E8 = 0;
+  if ( dword_50C9DC )
+  {
+    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)dword_50C9DC;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = (int)ptr_50C9E0;
+      *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+    dword_50C9DC = 0;
+  }
+  else
+  {
+    if ( dword_50C9D0 > 0 )
+    {
+      dword_50C9D8 -= pEventTimer->uTimeElapsed;
+      if ( dword_50C9D8 <= 0 )
+      {
+        if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+        {
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)dword_50C9D0;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = dword_50C9D4;
+          *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+          ++pMessageQueue_50CBD0->uNumMessages;
+        }
+        dword_50C9D0 = 0;
+        dword_50C9D4 = 0;
+        dword_50C9D8 = 0;
+      }
+    }
+  }
+  pStru277->_427E01_cast_spell();
+}
+
+
+//----- (004356FF) --------------------------------------------------------
+void __cdecl back_to_game()
+{
+  dword_507BF0_is_there_popup_onscreen = 0;
+  dword_4E455C = 1;
+  dword_50CDCC = 0;
+  if ( pGUIWindow_ScrollWindow )
+    free_book_subwindow();
+  if ( !pCurrentScreen && !pGUIWindow_Settings )
+    pEventTimer->Resume();
+  viewparams->bRedrawGameUI = 1;
+}
+//----- (00435748) --------------------------------------------------------
+void __cdecl GUI_MainMenuMessageProc()
+{
+  //AudioPlayer *v0; // ebp@2
+  char *v1; // ebx@2
+  unsigned int v2; // ecx@18
+  void *v3; // edi@21
+  signed int v4; // eax@29
+  int v5; // ecx@29
+  enum PLAYER_SKILL_TYPE v6; // edi@37
+  GUIWindow *pWindow; // eax@56
+  unsigned int v8; // edx@56
+  Player *pCurrentPlayer; // edi@57
+  signed int v10; // eax@58
+  GUIButton *pButton; // eax@59
+  unsigned __int8 v12; // sf@62
+  signed int v13; // eax@64
+  unsigned int v14; // eax@66
+  int v15; // edi@70
+  char v16; // zf@73
+  int v17; // eax@73
+  int v19; // edi@116
+  char v20; // dl@116
+  unsigned int v21; // eax@116
+  Player *v22; // ecx@116
+  char *v23; // ebx@118
+  int v24; // eax@118
+  unsigned int v25; // eax@120
+  unsigned int v26; // ecx@127
+  unsigned int v27; // eax@129
+  unsigned __int8 v28; // of@129
+  SoundID pSoundID; // [sp-2Ch] [bp-3Ch]@36
+  signed int v30; // [sp-28h] [bp-38h]@36
+  unsigned int v31; // [sp-24h] [bp-34h]@36
+  signed int v32; // [sp-20h] [bp-30h]@36
+  signed int v34; // [sp-1Ch] [bp-2Ch]@36
+  int v36; // [sp-18h] [bp-28h]@36
+  unsigned int v38; // [sp-14h] [bp-24h]@36
+  int v39; // [sp-14h] [bp-24h]@56
+  signed int v40; // [sp-10h] [bp-20h]@15
+  signed int v41; // [sp-10h] [bp-20h]@29
+  int v42; // [sp-10h] [bp-20h]@36
+  int v43; // [sp-10h] [bp-20h]@56
+  int uNum; // [sp+4h] [bp-Ch]@3
+  UIMessageType pUIMessageType; // [sp+8h] [bp-8h]@3
+  int pSex; // [sp+Ch] [bp-4h]@3
+  Player *pPlayer;
+
+  if ( pMessageQueue_50CBD0->uNumMessages )
+  {
+    //v0 = pAudioPlayer;
+    v1 = (char *)pParty->pPlayers;
+	pPlayer = pParty->pPlayers;
+    do
+    {
+      pMessageQueue_50CBD0->PopMessage(&pUIMessageType, &uNum, &pSex);
+      switch (pUIMessageType)
+      {
+        case UIMSG_MainMenu_ShowPartyCreationWnd:
+        {
+          GUIWindow::Create(495, 172, 0, 0, WINDOW_5A, (int)pMainMenu_BtnNew, 0);
+          SetCurrentMenuID(MENU_NEWGAME);
+        }
+        continue;
+        case UIMSG_MainMenu_ShowLoadWindow:
+        {
+          GUIWindow::Create(495, 227, 0, 0, WINDOW_5A, (int)pMainMenu_BtnLoad, 0);
+          SetCurrentMenuID(MENU_SAVELOAD);
+        }
+        continue;
+        case UIMSG_ShowCredits:
+        {
+          GUIWindow::Create(495, 282, 0, 0, WINDOW_5A, (int)pMainMenu_BtnCredits, 0);
+          SetCurrentMenuID(MENU_CREDITS);
+        }
+        continue;
+        case UIMSG_ExitToWindows:
+        {
+          GUIWindow::Create(495, 337, 0, 0, WINDOW_5A, (int)pMainMenu_BtnExit, 0);
+          SetCurrentMenuID(MENU_FINISHED);
+        }
+        continue;
+        case UIMSG_LoadGame:
+        {
+          if (!pSavegameUsedSlots[uLoadGameUI_SelectedSlot])
+            continue;
+          SetCurrentMenuID(MENU_LOAD);
+        }
+        continue;
+      }
+      switch (pUIMessageType)
+      {
+        case UIMSG_A5:   // WINDOW_5A
+        {
+            //main menu save/load wnd   clicking on savegame lines
+          if (pGUIWindow_CurrentMenu->field_40 == 1)
+            pKeyActionMap->_459ED1(0);
+          if ( pCurrentScreen != 11 || uLoadGameUI_SelectedSlot != uNum + dword_6A0C9C )
+          {
+            //load clicked line
+              v26 = uNum + dword_6A0C9C;
+              if ( dword_6BE138 == uNum + dword_6A0C9C )
+              {
+                pMessageQueue_50CBD0->SendMessage(UIMSG_A4, 0, 0);
+                pMessageQueue_50CBD0->SendMessage(UIMSG_LoadGame, 0, 0);
+              }
+              uLoadGameUI_SelectedSlot = v26;
+              dword_6BE138 = v26;
+          }
+          else
+          {
+            //typing in the line
+              pKeyActionMap->_459E5A(0, 19, pGUIWindow_CurrentMenu);
+              strcpy((char *)pKeyActionMap->pPressedKeysBuffer, pSavegameHeader[uLoadGameUI_SelectedSlot].pName);
+              pKeyActionMap->uNumKeysPressed = strlen((const char *)pKeyActionMap->pPressedKeysBuffer);
+          }
+        }
+        continue;
+        case UIMSG_A4:
+        {
+          GUIWindow::Create(pGUIWindow_CurrentMenu->uFrameX + 241, pGUIWindow_CurrentMenu->uFrameY + 302, 61, 28, WINDOW_5E, (int)ptr_69BD64, 0);
+        }
+        continue;
+      }
+      if ( (signed int)pUIMessageType > UIMSG_PlayerCreationRemoveDownSkill )
+      {
+        if ( pUIMessageType > UIMSG_A3 )
+        {
+          if ( pUIMessageType == UIMSG_A6 )
+          {
+            GUIWindow::Create(pGUIWindow_CurrentMenu->uFrameX + 350, pGUIWindow_CurrentMenu->uFrameY + 302, 61, 28, (WindowType)95, (int)ptr_69BD60, 0);
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_SelectFacePlayerBack )
+          {
+            pPlayer = &pParty->pPlayers[uNum];
+            v12 = (char)((int)pPlayer->uFace - 1) < 0;
+            --pPlayer->uFace;
+            if ( v12 )
+              pPlayer->uFace = 19;
+            pPlayer->uVoiceID = pPlayer->uFace;
+            pPlayer->SetInitialStats();
+            pPlayer->SetSexByVoice();
+            pPlayer->RandomizeName();
+            v25 = uNum;
+            pGUIWindow_CurrentMenu->pCurrentPosActiveItem = (pGUIWindow_CurrentMenu->pCurrentPosActiveItem - pGUIWindow_CurrentMenu->pStartingPosActiveItem)
+                                                      % 7 + pGUIWindow_CurrentMenu->pStartingPosActiveItem + 7 * uNum;
+            uPlayerCreationUI_SelectedCharacter = v25;
+            GUIWindow::Create(pCreationUI_BtnPressLeft[v25]->uX, pCreationUI_BtnPressLeft[v25]->uY, 0, 0,
+              (enum WindowType)92, (int)pCreationUI_BtnPressLeft[v25], 1);
+            //v0 = pAudioPlayer;
+            pAudioPlayer->PlaySound((SoundID)66, 0, 0, -1, 0, 0, 0.0, 0);
+            v22 = pPlayer;
+            v22->PlaySound(102, 0);
+            v1 = (char *)pParty->pPlayers;
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_SelectFacePlayerForward )
+          {
+            pPlayer = &pParty->pPlayers[uNum];
+			v20 = (char)((int)pPlayer->uFace + 1) % 20;
+            pPlayer->uFace = v20;
+            pPlayer->uVoiceID = v20;
+            pPlayer->SetInitialStats();
+            pPlayer->SetSexByVoice();
+            pPlayer->RandomizeName();
+            v21 = uNum;
+            pGUIWindow_CurrentMenu->pCurrentPosActiveItem = (pGUIWindow_CurrentMenu->pCurrentPosActiveItem - pGUIWindow_CurrentMenu->pStartingPosActiveItem)
+                                                      % 7 + pGUIWindow_CurrentMenu->pStartingPosActiveItem + 7 * uNum;
+            uPlayerCreationUI_SelectedCharacter = v21;
+            GUIWindow::Create(pCreationUI_BtnPressRight[v21]->uX, pCreationUI_BtnPressRight[v21]->uY, 0, 0, (enum WindowType)92,
+			  (int)pCreationUI_BtnPressRight[v21], 1);
+            //v0 = pAudioPlayer;
+            pAudioPlayer->PlaySound((SoundID)66, 0, 0, -1, 0, 0, 0, 0);
+            v22 = pPlayer;
+            v22->PlaySound(102, 0);
+            v1 = (char *)pParty->pPlayers;
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_AD )
+          {
+            GUIWindow::Create(pMainMenu_BtnNew->uX, pMainMenu_BtnNew->uY, 0, 0, (enum WindowType)90, (int)pMainMenu_BtnNew, 0);
+          SetCurrentMenuID(MENU_LOAD);
+          continue;
+          }
+          if ( pUIMessageType != UIMSG_AE )
+            continue;
+          GUIWindow::Create(pMainMenu_BtnExit->uX, pMainMenu_BtnExit->uY, 0, 0, (enum WindowType)90, (int)pMainMenu_BtnExit, 0);
+LABEL_114:
+          v40 = 10;
+LABEL_89:
+          v2 = v40;
+          SetCurrentMenuID((MENU_STATE)v2);
+          continue;
+        }
+        if ( pUIMessageType == UIMSG_A3 )
+        {
+          ++dword_6A0C9C;
+          if ( dword_6A0C9C >= uNum )
+            dword_6A0C9C = uNum - 1;
+          if ( dword_6A0C9C < 1 )
+            dword_6A0C9C = 0;
+          pWindow = pGUIWindow_CurrentMenu;
+          v43 = 0;
+          v39 = (int)ptr_69BD58;
+          v8 = pGUIWindow_CurrentMenu->uFrameY + 323;
+          goto LABEL_105;
+        }
+        if ( pUIMessageType == UIMSG_6B )
+        {
+          if ( pCurrentScreen )
+          {
+            pGUIWindow_CurrentMenu->Release();
+            pEventTimer->Resume();
+            pCurrentScreen = 0;
+            viewparams->bRedrawGameUI = 1;
+          }
+          GUIWindow::Create(602, 450, 0, 0, (enum WindowType)92, (int)pBtn_GameSettings, 0);
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages >= 40 )
+            continue;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = UIMSG_CloseBook;
+          goto LABEL_93;
+        }
+        if ( pUIMessageType == UIMSG_CloseBook )
+        {
+          if ( ptr_507BDC )
+          {
+            sub_41426F();
+            continue;
+          }
+          if ( !(BYTE1(dword_6BE364_game_settings_1) & 0x40) )
+            continue;
+          v15 = 1;
+          pVideoPlayer->bStopBeforeSchedule = 1;
+          viewparams->bRedrawGameUI = 1;
+          viewparams->field_48 = 1;
+          if ( !GetCurrentMenuID() || GetCurrentMenuID() == 6 || GetCurrentMenuID() == 7 )
+          {
+            v17 = pCurrentScreen;
+LABEL_83:
+            if ( v17 == 16 )
+              pVideoPlayer->FastForwardToFrame(pVideoPlayer->field_40);
+            if (GetCurrentMenuID() == MENU_7)
+            {
+              v40 = 6;
+              goto LABEL_89;
+            }
+            if (GetCurrentMenuID() == MENU_Credits)
+            {
+              v40 = 11;
+              goto LABEL_89;
+            }
+            if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+            {
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)5;
+LABEL_93:
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+              *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+              ++pMessageQueue_50CBD0->uNumMessages;
+              continue;
+            }
+            continue;
+          }
+          v16 = GetCurrentMenuID() == 8;
+          v17 = pCurrentScreen;
+          if ( v16 && !pCurrentScreen )
+            goto LABEL_83;
+          if ( pCurrentScreen == 12 )
+          {
+            pIcons_LOD->_4114F2();
+            //crt_deconstruct_ptr_6A0118();
+            pTexture_PCX.Release();
+            pTexture_PCX.Load("title.pcx", 0);
+            SetCurrentMenuID(MENU_MAIN);
+            v15 = 1;
+LABEL_81:
+            pGUIWindow_CurrentMenu->Release();
+            pGUIWindow2->Release();
+            pGUIWindow2 = 0;
+            pEventTimer->Resume();
+            pCurrentScreen = 0;
+            viewparams->bRedrawGameUI = v15;
+            continue;
+          }
+          if ( pCurrentScreen == 16 )
+          {
+            pVideoPlayer->Unload();
+          }
+          else
+          {
+            if ( pCurrentScreen != 27 )
+              goto LABEL_81;
+            //VideoPlayer::dtor();
+          }
+        }
+        else
+        {
+          if ( pUIMessageType == UIMSG_PlayerCreationSelectQuality )
+          {
+            pGUIWindow_CurrentMenu->pCurrentPosActiveItem = (pGUIWindow_CurrentMenu->pCurrentPosActiveItem - pGUIWindow_CurrentMenu->pStartingPosActiveItem)
+                                                      % 7 + pGUIWindow_CurrentMenu->pStartingPosActiveItem + 7 * uNum;
+            uPlayerCreationUI_SelectedCharacter = uNum;
+            pAudioPlayer->PlaySound((SoundID)66, 0, 0, -1, 0, 0, 0, 0);
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_PlayerCreationVoiceBack )
+          {
+            pCurrentPlayer = &pPlayer[uNum];
+            pSex = pCurrentPlayer->GetSexByVoice();
+            do
+            {
+              v12 = (/*(*/pCurrentPlayer->uVoiceID-- - 1/*) & 0x80000000u */) != 0;
+              if ( v12 )
+                pCurrentPlayer->uVoiceID = 19;
+              v13 = pCurrentPlayer->GetSexByVoice();
+            }
+            while ( v13 != pSex );
+            pButton = pCreationUI_BtnPressLeft2[uNum];
+            GUIWindow::Create(pButton->uX, pButton->uY, 0, 0, (enum WindowType)92, (int)pButton, 1);
+            pAudioPlayer->PlaySound((SoundID)66, 0, 0, -1, 0, 0, 0, 0);
+            pCurrentPlayer->PlaySound(102, 0);
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_PlayerCreationVoiceForward )
+          {
+            pCurrentPlayer = &pPlayer[uNum];
+            pSex = pCurrentPlayer->GetSexByVoice();
+            do
+            {
+              pCurrentPlayer->uVoiceID = (signed int)(pCurrentPlayer->uVoiceID + 1) % 20;
+              v10 = pCurrentPlayer->GetSexByVoice();
+            }
+            while ( v10 != pSex );
+            pButton = pCreationUI_BtnPressRight2[uNum];
+            GUIWindow::Create(pButton->uX, pButton->uY, 0, 0, (enum WindowType)92, (int)pButton, 1);
+            pAudioPlayer->PlaySound((SoundID)66, 0, 0, -1, 0, 0, 0, 0);
+            pCurrentPlayer->PlaySound(102, 0);
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_A2 )
+          {
+            --dword_6A0C9C;
+            if ( dword_6A0C9C < 0 )
+              dword_6A0C9C = 0;
+            pWindow = pGUIWindow_CurrentMenu;
+            v43 = 0;
+            v39 = (int)ptr_69BD5C;
+            v8 = pGUIWindow_CurrentMenu->uFrameY + 197;
+LABEL_105:
+            GUIWindow::Create(pWindow->uFrameX + 215, v8, 0, 0, (WindowType)90, v39, v43);
+            continue;
+          }
+        }
+      }
+      else
+      {
+        if ( pUIMessageType == UIMSG_PlayerCreationRemoveDownSkill )
+        {
+          uPlayerCreationUI_SelectedCharacter = uNum;
+          v41 = 3;
+          v1 = (char *)pParty->pPlayers;
+          v5 = (pGUIWindow_CurrentMenu->pCurrentPosActiveItem - pGUIWindow_CurrentMenu->pStartingPosActiveItem) % 7
+             + pGUIWindow_CurrentMenu->pStartingPosActiveItem + 7 * uNum;
+          pGUIWindow_CurrentMenu->pCurrentPosActiveItem = v5;
+          pParty->pPlayers[0].pActiveSkills[(&pPlayer[uPlayerCreationUI_SelectedCharacter])->GetSkillIdxByOrder(v41)
+                                             + 3486 * uPlayerCreationUI_SelectedCharacter] = 0;
+          continue;
+        }
+        if ( (signed int)pUIMessageType > UIMSG_3C )
+        {
+          if ( pUIMessageType == UIMSG_PlayerCreationClickPlus )
+          {
+            GUIWindow::Create(613, 393, 0, 0, (enum WindowType)90, (int)pPlayerCreationUI_BtnPlus, 1);
+            (&pPlayer[uPlayerCreationUI_SelectedCharacter])->IncreaseAttribute(
+              (pGUIWindow_CurrentMenu->pCurrentPosActiveItem - pGUIWindow_CurrentMenu->pStartingPosActiveItem) % 7);
+            pAudioPlayer->PlaySound((SoundID)20, 0, 0, -1, 0, 0, 0, 0);
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_PlayerCreationClickMinus )
+          {
+            GUIWindow::Create(523, 393, 0, 0, (enum WindowType)90, (int)pPlayerCreationUI_BtnMinus, 1);
+            (&pPlayer[uPlayerCreationUI_SelectedCharacter])->DecreaseAttribute(
+              (pGUIWindow_CurrentMenu->pCurrentPosActiveItem - pGUIWindow_CurrentMenu->pStartingPosActiveItem) % 7);
+            pAudioPlayer->PlaySound((SoundID)23, 0, 0, -1, 0, 0, 0, 0);
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_PlayerCreationSelectActiveSkill )
+          {
+            auto _t = &pPlayer[uPlayerCreationUI_SelectedCharacter];
+            v6 = _t->GetSkillIdxByOrder(uNum + 4);
+            if ( _t->GetSkillIdxByOrder(3) == 37 )
+              pParty->pPlayers[0].pActiveSkills[v6 + 3486 * uPlayerCreationUI_SelectedCharacter] = 1;
+            pAudioPlayer->PlaySound((SoundID)24, 0, 0, -1, 0, 0, 0, 0);
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_PlayerCreationSelectClass )
+          {
+            (&pPlayer[uPlayerCreationUI_SelectedCharacter])->Reset(uNum);
+            pAudioPlayer->PlaySound((SoundID)66, 0, 0, -1, 0, 0, 0, 0);
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_PlayerCreationClickOK )
+          {
+            GUIWindow::Create(580, 431, 0, 0, (enum WindowType)90, (int)pPlayerCreationUI_BtnOK, 0);
+            if ( PlayerCreation_ComputeAttributeBonus() || !sub_4908DE() )
+              GameUI_StatusBar_TimedStringTimeLeft = GetTickCount() + 4000;
+            else
+              uGameState = 6;
+            continue;
+          }
+          if ( pUIMessageType == UIMSG_PlayerCreationClickReset ) 
+          {
+            GUIWindow::Create(527, 431, 0, 0, (enum WindowType)90, (int)pPlayerCreationUI_BtnReset, 0);
+            pParty->Reset();
+          }
+          else
+          {
+            if ( pUIMessageType == UIMSG_PlayerCreationRemoveUpSkill )
+            {
+              uPlayerCreationUI_SelectedCharacter = uNum;
+              v4 = pGUIWindow_CurrentMenu->pCurrentPosActiveItem - pGUIWindow_CurrentMenu->pStartingPosActiveItem;
+              pSex = pGUIWindow_CurrentMenu->pStartingPosActiveItem;
+              v41 = 2;
+              v5 = v4 % 7 + pSex + 7 * uNum;
+              pGUIWindow_CurrentMenu->pCurrentPosActiveItem = v5;
+              pParty->pPlayers[0].pActiveSkills[(&pPlayer[uPlayerCreationUI_SelectedCharacter])->GetSkillIdxByOrder(v41)
+                                             + 3486 * uPlayerCreationUI_SelectedCharacter] = 0;
+              continue;
+            }
+          }
+        }
+        else
+        {
+          switch ( pUIMessageType )
+          {
+            case 60:
+              pAudioPlayer->PlaySound((SoundID)24, 0, 0, -1, 0, 0, 0, 0);
+              v3 = (void *)uNum;
+              uPlayerCreationUI_SelectedCharacter = uNum;
+              pKeyActionMap->_459E5A(0, 15, pGUIWindow_CurrentMenu);
+              pGUIWindow_CurrentMenu->ptr_1C = v3;
+              break;
+            case 5:
+              uGameState = 1;
+              break;
+            case 17:
+              pMouse->SetCursorBitmap("MICON2");
+              break;
+            default:
+              if ( pUIMessageType == 58 )
+                goto LABEL_114;
+              break;
+          }
+        }
+      }
+    }
+    while ( pMessageQueue_50CBD0->uNumMessages );
+  }
+}
+
+//----- (00436427) --------------------------------------------------------
+double __cdecl get_shading_dist_mist()
+{
+  double result; // st7@2
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    result = (double)pOutdoorCamera->shading_dist_mist;
+  else
+    result = 16192.0;
+  return result;
+}
+
+//----- (0043643E) --------------------------------------------------------
+double __cdecl GetPickDepth()
+{
+  double result; // st7@2
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    result = (double)pOutdoorCamera->uPickDepth;
+  else
+    result = 16192.0;
+  return result;
+}
+
+//----- (0043648F) --------------------------------------------------------
+void Vec3_short__to_RenderVertexSoft(RenderVertexSoft *_this, Vec3_short_ *a2)
+{
+  _this->flt_2C = 0.0;
+
+  _this->vWorldPosition.x = a2->x;
+  _this->vWorldPosition.y = a2->y;
+  _this->vWorldPosition.z = a2->z;
+}
+
+//----- (004369DB) --------------------------------------------------------
+void Vec3_float_::Normalize()
+{
+  Vec3_float_ *v1; // esi@1
+  double v2; // st7@1
+
+  auto a1 = this;
+  v1 = a1;
+  v2 = 1.0 / sqrt(a1->x * a1->x + a1->y * a1->y + a1->z * a1->z);
+  v1->x = v2 * v1->x;
+  v1->y = v2 * v1->y;
+  v1->z = v2 * v1->z;
+}
+
+
+
+
+
+
+
+//----- (004382BC) --------------------------------------------------------
+__int16 __thiscall sub_4382BC(int _this)
+{
+  LOG_DECOMPILATION_WARNING();
+  return 0;
+  /*__int16 result; // ax@4
+  __int16 v14; // sp@11
+  int v15; // [sp-4h] [bp-Ch]@0
+  signed __int16 v16; // [sp+4h] [bp-4h]@1
+  __int16 v17; // [sp+4h] [bp-4h]@8
+  __int16 v18; // [sp+4h] [bp-4h]@11
+
+  v16 = 1;
+  __asm { pushf }
+  if ( v15 == (v15 ^ 0x200000) )
+    v16 = 0;
+  if ( v16 )
+  {
+    result = sub_43847A();
+  }
+  else
+  {
+    //UNDEF(_ZF);
+    //UNDEF(_SF);
+    //UNDEF(_OF);
+    _CF = 0;
+    if ( !_ZF )
+      _CF = 1;
+    __asm { pushfw }
+    bProcessorIsNotIntel = (BYTE2(v15) & 1 ^ 1) & 1;
+    _CF = 0;
+    _OF = 0;
+    _ZF = 0;
+    _SF = 1;
+    __asm { pushfw }
+    v17 = 2;
+    if ( (HIWORD(v15) | 0xF000) & 0xF000 )
+      v17 = -1;
+    __asm { popfw }
+    result = v17;
+    if ( v17 != 2 )
+    {
+      _CF = 0;
+      _OF = 0;
+      _ZF = v14 == 0;
+      _SF = v14 < 0;
+      __asm { pushf }
+      v18 = 3;
+      if ( v15 != (v15 ^ 0x40000) )
+        v18 = -1;
+      __asm { popf }
+      result = v18;
+      if ( v18 != 3 )
+        result = 4;
+    }
+  }
+  if ( bProcessorIsNotIntel )
+    HIBYTE(result) |= 0x80u;
+  return result;*/
+}
+
+//----- (004383ED) --------------------------------------------------------
+int __cdecl sub_4383ED()
+{
+  LOG_DECOMPILATION_WARNING();
+  return 0;
+  /*signed int v9; // eax@4
+  int v16; // [sp-4h] [bp-38h]@0
+  int v17[3]; // [sp+Ch] [bp-28h]@1
+  char v18; // [sp+18h] [bp-1Ch]@1
+  char v19; // [sp+19h] [bp-1Bh]@1
+  int v20[4]; // [sp+1Ch] [bp-18h]@1
+  int v21; // [sp+2Ch] [bp-8h]@1
+  int v22; // [sp+30h] [bp-4h]@1
+
+  v17[0] = *(int *)"------------";
+  v17[1] = *(int *)"--------";
+  v17[2] = *(int *)"----";
+  v18 = asc_4E4938[12];
+  v19 = 0;
+  v22 = 0;
+  v20[0] = *(int *)"GenuineIntel";
+  v20[1] = *(int *)"ineIntel";
+  v20[2] = *(int *)"ntel";
+  LOBYTE(v20[3]) = aGenuineintel[12];
+  _CF = 0;
+  _OF = 0;
+  _ZF = 0;
+  _SF = 0;
+  v21 = 1;
+  __asm { pushf }
+  if ( v16 == (v16 ^ 0x200000) )
+    v21 = 0;
+  if ( (short)v21 )
+  {
+    _EAX = 0;
+    __asm { cpuid }
+    v17[0] = _EBX;
+    v17[1] = _EDX;
+    v17[2] = _ECX;
+    v9 = 0;
+    do
+    {
+      if ( *((char *)v17 + v9) != *((char *)v20 + v9) )
+        bProcessorIsNotIntel = 1;
+      ++v9;
+    }
+    while ( v9 < 12 );
+    if ( v9 >= 1 )
+    {
+      _EAX = 1;
+      __asm { cpuid }
+      v22 = _EDX;
+    }
+  }
+  return v22;*/
+}
+
+//----- (0043847A) --------------------------------------------------------
+__int16 __cdecl sub_43847A()
+{
+  __debugbreak();
+  return 0;
+  /*signed int v5; // eax@1
+  char v12[12]; // [sp+Ch] [bp-28h]@1
+  char v13; // [sp+18h] [bp-1Ch]@1
+  char v14; // [sp+19h] [bp-1Bh]@1
+  int v15[4]; // [sp+1Ch] [bp-18h]@1
+  int v16; // [sp+2Eh] [bp-6h]@1
+  char v17; // [sp+32h] [bp-2h]@6
+  char v18; // [sp+33h] [bp-1h]@1
+
+  *(int *)v12 = *(int *)"------------";
+  *(int *)&v12[4] = *(int *)"--------";
+  *(int *)&v12[8] = *(int *)"----";
+  v13 = asc_4E4938[12];
+  v14 = 0;
+  v18 = 0;
+  v15[0] = *(int *)"GenuineIntel";
+  v15[1] = *(int *)"ineIntel";
+  v15[2] = *(int *)"ntel";
+  v16 = 65535;
+  LOBYTE(v15[3]) = aGenuineintel[12];
+  _EAX = 0;
+  __asm { cpuid }
+  *(int *)v12 = _EBX;
+  *(int *)&v12[4] = _EDX;
+  *(int *)&v12[8] = _ECX;
+  v5 = 0;
+  do
+  {
+    if ( v12[v5] != *((char *)v15 + v5) )
+      bProcessorIsNotIntel = 1;
+    ++v5;
+  }
+  while ( v5 < 12 );
+  if ( v5 >= 1 )
+  {
+    _EAX = 1;
+    __asm { cpuid }
+    v18 = _EAX & 0xF;
+    LOBYTE(_EAX) = (unsigned __int8)(_EAX & 0xF0) >> 4;
+    v17 = _EAX;
+    LOWORD(v16) = ((_EAX & 0xF00u) >> 8) & 0xF;
+  }
+  return v16;*/
+}
+
+
+
+//----- (004385B5) --------------------------------------------------------
+void stru11::CheckCPU()
+{
+  LOG_DECOMPILATION_WARNING();
+  /*
+  int v5; // [sp-4h] [bp-10h]@0
+  signed int v6; // [sp+4h] [bp-8h]@1
+  signed int v7; // [sp+8h] [bp-4h]@1
+
+  _CF = 0;
+  _OF = 0;
+  _ZF = 1;
+  _SF = 0;
+  v7 = 0;
+  __asm { pushf }
+  v6 = 3;
+  if ( v5 != (v5 ^ 0x40000) )
+  {
+    __asm { popf }
+    v6 = 4;
+    __asm { pushf }
+    if ( v5 != (v5 ^ 0x200000) )
+    {
+      v7 = 1;
+      v6 = 0;
+    }
+  }
+  if ( v6 == 3 )
+  {
+    this->field_AC = 1;
+  }
+  else
+  {
+    if ( v6 == 4 )
+    {
+      this->field_AC = 2;
+    }
+    else
+    {
+      if ( v7 )
+      {
+        this->field_AC = 2;
+        RunCPUID();
+      }
+      else
+      {
+        this->field_AC = 0;
+      }
+    }
+  }*/
+}
+
+//----- (00438659) --------------------------------------------------------
+void stru11::RunCPUID()
+{
+  __debugbreak();
+  /*stru11 *v6; // esi@1
+  unsigned int uNumOps; // edi@1
+  int uNumExtOps; // edi@16
+  char pCyrixString[16]; // [sp+Ch] [bp-60h]@1
+  char pCentaurString[16]; // [sp+1Ch] [bp-50h]@1
+  char pAMDString[16]; // [sp+2Ch] [bp-40h]@1
+  char pIntelString[16]; // [sp+3Ch] [bp-30h]@1
+  char pCPUString[16]; // [sp+4Ch] [bp-20h]@1
+  stru11 *thisa; // [sp+5Ch] [bp-10h]@1
+  char *v35; // [sp+60h] [bp-Ch]@1
+  int v36; // [sp+64h] [bp-8h]@1
+  int v37; // [sp+68h] [bp-4h]@1
+
+  thisa = this;
+  *(int *)pIntelString = *(int *)"GenuineIntel";
+  *(int *)&pIntelString[4] = *(int *)"ineIntel";
+  *(int *)&pIntelString[8] = *(int *)"ntel";
+  pIntelString[12] = aGenuineintel[12];
+  *(int *)pAMDString = *(int *)"AuthenticAMD";
+  *(int *)&pAMDString[4] = *(int *)"enticAMD";
+  *(int *)&pAMDString[8] = *(int *)"cAMD";
+  pAMDString[12] = aAuthenticamd[12];
+  *(int *)pCyrixString = *(int *)"CyrixInstead";
+  *(int *)&pCyrixString[4] = *(int *)"xInstead";
+  *(int *)&pCyrixString[8] = *(int *)"tead";
+  pCyrixString[12] = aCyrixinstead[12];
+  *(int *)pCentaurString = *(int *)"CentaurHauls";
+  *(int *)&pCentaurString[4] = *(int *)"aurHauls";
+  *(int *)&pCentaurString[8] = *(int *)"auls";
+  v37 = 0;
+  v36 = 0;
+  pCentaurString[12] = aCentaurhauls[12];
+  v35 = pCPUString;
+  pCPUString[12] = 0;
+  _EAX = 0;
+  __asm { cpuid }
+  v37 = _EAX;
+  *(int *)pCPUString = _EBX;
+  *(int *)&pCPUString[4] = _EDX;
+  *(int *)&pCPUString[8] = _ECX;
+  v6 = thisa;
+  uNumOps = _EAX;
+  thisa->cpuid_00000000_ebx_vendorstr1 = _EBX;
+  v6->cpuid_00000000_edx_vendorstr2 = *(int *)&pCPUString[4];
+  v6->cpuid_00000000_ecx_vendorstr3 = *(int *)&pCPUString[8];
+  v6->cpuid_00000000_eax_numops = _EAX;
+  strcpy(v6->pCPUString, pCPUString);
+  if ( strcmp(pIntelString, pCPUString) )
+  {
+    if ( strcmp(pAMDString, pCPUString) )
+    {
+      if ( strcmp(pCyrixString, pCPUString) )
+      {
+        if ( strcmp(pCentaurString, pCPUString) )
+          v6->uProcessorManufacturer = 0;
+        else
+          v6->uProcessorManufacturer = 4;
+      }
+      else
+      {
+        v6->uProcessorManufacturer = 3;
+      }
+    }
+    else
+    {
+      v6->uProcessorManufacturer = 2;
+    }
+  }
+  else
+  {
+    v6->uProcessorManufacturer = 1;
+  }
+  if ( uNumOps >= 1 )
+    RunCPUID_op1();
+  if ( uNumOps >= 2 )
+    RunCPUID_op2();
+  _EAX = 0x80000000u;
+  __asm { cpuid }
+  if ( !(_EAX & 0x80000000) )
+    _EAX = 0x80000000u;
+  v36 = _EAX;
+  v6->cpuid_80000000_edx = _EAX;
+  uNumExtOps = _EAX ^ 0x80000000;
+  if ( (_EAX ^ 0x80000000u) >= 1 )
+  {
+    _EAX = 0x80000001u;
+    __asm { cpuid }
+    thisa = (stru11 *)_EAX;
+    v35 = (char *)_EDX;
+    v6->cpuid_80000001_eax = _EAX;
+    v6->cpuid_80000001_edx = (int)v35;
+  }
+  if ( (unsigned int)uNumExtOps >= 4 )
+    RunCPUID_ext2_3_4();
+  if ( (unsigned int)uNumExtOps >= 5 )
+  {
+    _EAX = 0x80000005u;
+    __asm { cpuid }
+    thisa = (stru11 *)_EBX;
+    v35 = (char *)_ECX;
+    v36 = _EDX;
+    v6->cpuid_80000005_ebx = _EBX;
+    v6->cpuid_80000005_ecx = (int)v35;
+    v6->cpuid_80000005_edx = v36;
+  }
+  if ( (unsigned int)uNumExtOps >= 6 )
+  {
+    _EAX = 0x80000006u;
+    __asm { cpuid }
+    v6->cpuid_80000006_ecx = _ECX;
+  }*/
+}
+
+//----- (00438821) --------------------------------------------------------
+void stru11::RunCPUID_op1()
+{
+  __debugbreak();
+  /*stru11 *v1; // esi@1
+  unsigned int v7; // ecx@1
+  int v8; // eax@3
+  int v9; // eax@10
+  signed int v10; // eax@11
+  int v11; // ecx@11
+  int v12; // eax@15
+  signed int v13; // eax@19
+  int v14; // ecx@19
+  signed int v15; // eax@25
+  int v16; // ecx@25
+  signed int v17; // eax@34
+  int v18; // ecx@34
+
+  v1 = this;
+  _EAX = 1;
+  __asm { cpuid }
+  v7 = _EAX;
+  v1->cpuid_00000001_edx = _EDX;
+  v1->cpuid_00000001_eax = _EAX;
+  if ( (_EAX & 0x3000) == 8192 )
+  {
+    LOBYTE(v1->cpuid_80000002_registers2[0]) = 1;
+    v7 = 0;
+  }
+  v8 = (v7 >> 8) & 0xF;
+  switch ( v8 )
+  {
+    case 4:
+      v1->field_AC = 2;
+      break;
+    case 5:
+      v1->field_AC = 15;
+      break;
+    case 6:
+      v1->field_AC = 36;
+      break;
+    default:
+      v1->field_AC = 49;
+      break;
+  }
+  v9 = v1->uProcessorManufacturer;
+  if ( v9 == 1 )
+  {
+    v10 = 0;
+    v11 = v7 & 0x3FF0;
+    while ( v11 != dword_4E4948[2 * v10] )
+    {
+      ++v10;
+      if ( v10 >= 17 )
+        return;
+    }
+    v12 = dword_4E494C[2 * v10];
+    goto LABEL_39;
+  }
+  if ( v9 == 2 )
+  {
+    if ( (v7 & 0xF00) == dword_4E49D0[0] )
+    {
+      v12 = dword_4E49D4[0];
+    }
+    else
+    {
+      v13 = 1;
+      v14 = v7 & 0x3FF0;
+      while ( v14 != dword_4E49D0[2 * v13] )
+      {
+        ++v13;
+        if ( v13 >= 9 )
+          return;
+      }
+      v12 = dword_4E49D4[2 * v13];
+    }
+    goto LABEL_39;
+  }
+  if ( v9 != 3 )
+  {
+    if ( v9 != 4 )
+      return;
+    v17 = 0;
+    v18 = v7 & 0x3FF0;
+    while ( v18 != dword_4E4A40[2 * v17] )
+    {
+      ++v17;
+      if ( v17 >= 2 )
+        return;
+    }
+    v12 = dword_4E4A44[2 * v17];
+    goto LABEL_39;
+  }
+  v15 = 1;
+  v16 = v7 & 0x3FF0;
+  while ( v16 != dword_4E4A18[2 * v15] )
+  {
+    ++v15;
+    if ( v15 >= 5 )
+      goto LABEL_30;
+  }
+  v1->field_AC = dword_4E4A1C[2 * v15];
+LABEL_30:
+  v12 = 24;
+  if ( v1->field_AC == 24 )
+  {
+    if ( _EDX != 1 )
+      v12 = (((_EDX != 261) - 1) & 0xA) + 15;
+LABEL_39:
+    v1->field_AC = v12;
+  }*/
+}
+
+//----- (00438992) --------------------------------------------------------
+void stru11::RunCPUID_op2()
+{
+  __debugbreak();
+  /*
+  stru11 *v1; // edi@1
+  int v7; // eax@1
+  signed int v8; // ecx@2
+  unsigned __int8 v9; // al@3
+  signed int v10; // ecx@14
+  unsigned __int8 v11; // al@15
+  int v12; // [sp+Ch] [bp-14h]@1
+  int v13; // [sp+10h] [bp-10h]@1
+  int v14; // [sp+14h] [bp-Ch]@1
+  int v15; // [sp+18h] [bp-8h]@1
+  int *v16; // [sp+1Ch] [bp-4h]@1
+
+  v1 = this;
+  v16 = &v12;
+  _EAX = 2;
+  __asm { cpuid }
+  v12 = _EAX;
+  v13 = _EBX;
+  v14 = _ECX;
+  v15 = _EDX;
+  v1->cpuid_00000002_eax = _EAX;
+  v1->cpuid_00000002_ebx = v13;
+  v1->cpuid_00000002_ecx = v14;
+  v1->cpuid_00000002_edx = v15;
+  v7 = v1->field_AC;
+  if ( v7 == 40 )
+  {
+    v8 = 0;
+    while ( 1 )
+    {
+      v9 = *((char *)&v12 + v8);
+      if ( v9 == 64 )
+      {
+        v1->field_AC = 43;
+        return;
+      }
+      if ( v9 >= 0x41u && v9 <= 0x43u )
+      {
+        v1->field_AC = 41;
+        return;
+      }
+      if ( v9 >= 0x44u && v9 <= 0x45u )
+        break;
+      ++v8;
+      if ( v8 >= 16 )
+        return;
+    }
+    v1->field_AC = 42;
+  }
+  else
+  {
+    if ( v7 == 45 )
+    {
+      v10 = 0;
+      while ( 1 )
+      {
+        v11 = *((char *)&v12 + v10);
+        if ( v11 >= 0x40u && v11 <= 0x43u )
+        {
+          v1->field_AC = 46;
+          return;
+        }
+        if ( v11 >= 0x44u && v11 <= 0x45u )
+          break;
+        ++v10;
+        if ( v10 >= 16 )
+          return;
+      }
+      v1->field_AC = 47;
+    }
+  }*/
+}
+
+//----- (00438A67) --------------------------------------------------------
+void stru11::RunCPUID_ext2_3_4()
+{
+  __debugbreak();
+  /*stru11 *v1; // edi@1
+  stru11 *v17; // eax@1
+  int v18[3][4]; // [sp+Ch] [bp-38h]@1
+  stru11 *v19; // [sp+3Ch] [bp-8h]@1
+
+  v1 = this;
+  v19 = this;
+  _EAX = 0x80000002u;
+  __asm { cpuid }
+  v18[0][0] = _EAX;
+  *(_QWORD *)&v18[0][1] = __PAIR__(_ECX, _EBX);
+  v18[0][3] = _EDX;
+  _EAX = 0x80000003u;
+  __asm { cpuid }
+  v18[1][0] = _EAX;
+  *(_QWORD *)&v18[1][1] = __PAIR__(_ECX, _EBX);
+  v18[1][3] = _EDX;
+  _EAX = 0x80000004u;
+  __asm { cpuid }
+  v18[2][0] = _EAX;
+  *(_QWORD *)&v18[2][1] = __PAIR__(_ECX, _EBX);
+  v18[2][3] = _EDX;
+  v17 = v19;
+  memcpy(v1->cpuid_80000002_registers, v18, 0x30u);
+  memcpy((char *)&v17->cpuid_80000002_registers2[0] + 1, v18, 0x30u);*/
+}
+
+
+
+//----- (00438BDF) --------------------------------------------------------
+bool MonsterStats::BelongsToSupertype(unsigned int uMonsterInfoID, enum MONSTER_SUPERTYPE eSupertype)
+{
+  unsigned __int8 v2; // zf@15
+  char v3; // sf@15
+  unsigned __int8 v4; // of@15
+  bool result; // eax@33
+
+  switch ( eSupertype )
+  {
+    case MONSTER_SUPERTYPE_UNDEAD:
+      if ( (signed int)uMonsterInfoID >= MONSTER_GHOST_1 && (signed int)uMonsterInfoID <= MONSTER_GHOST_3
+        || (signed int)uMonsterInfoID >= MONSTER_LICH_1 && (signed int)uMonsterInfoID <= MONSTER_LICH_3
+        || (signed int)uMonsterInfoID >= MONSTER_SKELETON_1 && (signed int)uMonsterInfoID <= MONSTER_SKELETON_3
+        || (signed int)uMonsterInfoID >= MONSTER_VAMPIRE_1 && (signed int)uMonsterInfoID <= MONSTER_VAMPIRE_3
+        || (signed int)uMonsterInfoID >= MONSTER_WIGHT_1 && (signed int)uMonsterInfoID <= MONSTER_WIGHT_3
+        || (signed int)uMonsterInfoID >= MONSTER_ZOMBIE_1 && (signed int)uMonsterInfoID <= MONSTER_ZOMBIE_3 )
+        goto ret_true;
+      if ( (signed int)uMonsterInfoID < MONSTER_GHOUL_1 )
+        goto ret_false;
+      v4 = __OFSUB__(uMonsterInfoID, (int)MONSTER_GHOUL_3);
+      v2 = uMonsterInfoID == MONSTER_GHOUL_3;
+      v3 = ((uMonsterInfoID - MONSTER_GHOUL_3) & 0x80000000u) != 0;
+      goto false_if_outside;
+    case MONSTER_SUPERTYPE_KREEGAN:
+      if ( (signed int)uMonsterInfoID < MONSTER_DEVIL_1 )
+        goto ret_false;
+      v4 = __OFSUB__(uMonsterInfoID, (int)MONSTER_DEVIL_3);
+      v2 = uMonsterInfoID == MONSTER_DEVIL_3;
+      v3 = ((uMonsterInfoID - MONSTER_DEVIL_3) & 0x80000000u) != 0;
+      goto false_if_outside;
+    case MONSTER_SUPERTYPE_ELF:
+      if ( (signed int)uMonsterInfoID >= MONSTER_PEASANT_ELF_FEMALE_1_1
+        && (signed int)uMonsterInfoID <= MONSTER_PEASANT_ELF_MALE_3_3
+        || (signed int)uMonsterInfoID >= MONSTER_ELF_ARCHER_1 && (signed int)uMonsterInfoID <= MONSTER_ELF_ARCHER_3 )
+        goto ret_true;
+      if ( (signed int)uMonsterInfoID < MONSTER_ELF_SPEARMAN_1 )
+        goto ret_false;
+      v4 = __OFSUB__(uMonsterInfoID, (int)MONSTER_ELF_SPEARMAN_3);
+      v2 = uMonsterInfoID == MONSTER_ELF_SPEARMAN_3;
+      v3 = ((uMonsterInfoID - MONSTER_ELF_SPEARMAN_3) & 0x80000000u) != 0;
+      goto false_if_outside;
+    case MONSTER_SUPERTYPE_DRAGON:
+      if ( (signed int)uMonsterInfoID < MONSTER_DRAGON_1 )
+        goto ret_false;
+      v4 = __OFSUB__(uMonsterInfoID, (int)MONSTER_DRAGON_3);
+      v2 = uMonsterInfoID == MONSTER_DRAGON_3;
+      v3 = ((uMonsterInfoID - MONSTER_DRAGON_3) & 0x80000000u) != 0;
+      goto false_if_outside;
+    case MONSTER_SUPERTYPE_WATER_ELEMENTAL:
+      if ( (signed int)uMonsterInfoID < MONSTER_ELEMENTAL_WATER_1 )
+        goto ret_false;
+      v4 = __OFSUB__(uMonsterInfoID, (int)MONSTER_ELEMENTAL_WATER_3);
+      v2 = uMonsterInfoID == MONSTER_ELEMENTAL_WATER_3;
+      v3 = ((uMonsterInfoID - MONSTER_ELEMENTAL_WATER_3) & 0x80000000u) != 0;
+      goto false_if_outside;
+    case MONSTER_SUPERTYPE_TREANT:
+      if ( (signed int)uMonsterInfoID < MONSTER_TREANT_1 )
+        goto ret_false;
+      v4 = __OFSUB__(uMonsterInfoID, (int)MONSTER_TREANT_3);
+      v2 = uMonsterInfoID == MONSTER_TREANT_3;
+      v3 = ((uMonsterInfoID - MONSTER_TREANT_3) & 0x80000000u) != 0;
+      goto false_if_outside;
+    case MONSTER_SUPERTYPE_TITAN:
+      if ( (signed int)uMonsterInfoID < MONSTER_TITAN_1 )
+        goto ret_false;
+      v4 = __OFSUB__(uMonsterInfoID, (int)MONSTER_TITAN_3);
+      v2 = uMonsterInfoID == MONSTER_TITAN_3;
+      v3 = ((uMonsterInfoID - MONSTER_TITAN_3) & 0x80000000u) != 0;
+false_if_outside:
+      if ( !((unsigned __int8)(v3 ^ v4) | v2) )
+        goto ret_false;
+ret_true:
+      result = 1;
+      break;
+    default:
+ret_false:
+      result = 0;
+      break;
+  }
+  return result;
+}
+
+
+//----- (00438F8F) --------------------------------------------------------
+void __cdecl _438F8F_area_of_effect__damage_evaluate()
+{
+  int v0; // edx@1
+  char *v1; // esi@2
+  int v2; // ecx@3
+  signed int v3; // eax@3
+  LayingItem *v4; // eax@4
+  signed int v5; // eax@4
+  signed int v6; // eax@6
+  unsigned int v7; // edi@6
+  int v8; // eax@6
+  __int16 v9; // bx@8
+  int v10; // edi@8
+  Vec3_int_ v11; // ST04_12@9
+  int v12; // ST0C_4@10
+  Actor *v13; // edi@11
+  int v14; // edx@15
+  int v15; // edx@15
+  int v16; // ebx@15
+  signed int v17; // eax@15
+  int v18; // edi@15
+  int v19; // edi@15
+  Vec3_int_ v20; // ST04_12@16
+  Vec3_int_ *v21; // eax@17
+  unsigned int v22; // edx@17
+  int v23; // edx@18
+  int v24; // eax@18
+  Vec3_int_ v25; // ST04_12@19
+  unsigned int v26; // ebx@20
+  char *v27; // edi@20
+  char *v28; // edi@27
+  int v29; // ebx@29
+  int v30; // eax@29
+  int v31; // edx@29
+  int v32; // eax@29
+  int v33; // ST24_4@29
+  Vec3_int_ v34; // ST04_12@30
+  Vec3_int_ *v35; // eax@31
+  LayingItem *v36; // [sp+0h] [bp-28h]@0
+  signed int v37; // [sp+4h] [bp-24h]@5
+  int v38; // [sp+4h] [bp-24h]@15
+  signed int v39; // [sp+8h] [bp-20h]@3
+  int v40; // [sp+8h] [bp-20h]@15
+  int v41; // [sp+Ch] [bp-1Ch]@5
+  int v42; // [sp+Ch] [bp-1Ch]@15
+  int v43; // [sp+10h] [bp-18h]@1
+  int v44; // [sp+14h] [bp-14h]@15
+  unsigned int uActorID; // [sp+18h] [bp-10h]@6
+  Vec3_int_ *pVelocity; // [sp+1Ch] [bp-Ch]@2
+  int a1; // [sp+20h] [bp-8h]@8
+  int v48; // [sp+24h] [bp-4h]@8
+
+  v0 = 0;
+  v43 = 0;
+  if ( stru_50FE08.count > 0 )
+  {
+    pVelocity = &stru_50FE08.vec_4B4;
+    v1 = (char *)stru_50FE08.pZs;
+    do
+    {
+      v2 = *((short *)v1 - 300) & 7;
+      v3 = (signed int)*((short *)v1 - 300) >> 3;
+      v39 = (signed int)*((short *)v1 - 300) >> 3;
+      if ( v2 == 2 )
+      {
+        v4 = &pLayingItems[v3];
+        v36 = v4;
+        v5 = v4->field_58;
+        v2 = v5 & 7;
+        v3 = v5 >> 3;
+      }
+      v41 = v2;
+      v37 = v3;
+      if ( stru_50FE08.field_3EC[v0] & 1 )
+      {
+        v6 = dword_4F6E08[v3];
+        v7 = v6 >> 3;
+        v8 = (v6 & 7) - 3;
+        uActorID = v7;
+        if ( v8 )
+        {
+          if ( v8 == 1 )
+          {
+            v9 = *(short *)v1;
+            v10 = pParty->vPosition.y - *((short *)v1 - 100);
+            a1 = pParty->vPosition.x - *((short *)v1 - 200);
+            v48 = v10;
+            if ( a1 * a1
+               + v10 * v10
+               + ((signed int)(pParty->vPosition.z + pParty->uPartyHeight) >> (1 - v9))
+               * ((signed int)(pParty->vPosition.z + pParty->uPartyHeight) >> (1 - v9)) < (unsigned int)((*((short *)v1 + 100) + 32) * (*((short *)v1 + 100) + 32)) )
+            {
+              v11.z = *(short *)v1;
+              v11.y = *((short *)v1 - 100);
+              v11.x = *((short *)v1 - 200);
+              if ( sub_407A1C(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z + pParty->sEyelevel, v11) )
+              {
+                v12 = stru_50C198.which_player_would_attack(&pActors[v39]);
+                DamagePlayerFromMonster(*((short *)v1 - 300), stru_50FE08.field_450[v43], pVelocity, v12);
+              }
+            }
+          }
+        }
+        else
+        {
+          v13 = &pActors[v7];
+          if ( SHIDWORD(v13->pActorBuffs[6].uExpireTime) > 0
+            || SHIDWORD(v13->pActorBuffs[6].uExpireTime) >= 0 && LODWORD(v13->pActorBuffs[6].uExpireTime)
+            || v13->CanAct() )
+          {
+            v14 = v13->vPosition.y;
+            v40 = v13->vPosition.x;
+            v38 = v14;
+            v15 = v14 - *((short *)v1 - 100);
+            v16 = *(short *)v1;
+            v42 = v13->vPosition.z;
+            a1 = v40 - *((short *)v1 - 200);
+            v17 = v13->uActorHeight;
+            v18 = v13->uActorRadius;
+            v44 = v42;
+            v19 = *((short *)v1 + 100) + v18;
+            v48 = v15;
+            if ( a1 * a1 + v15 * v15 + (v42 + (v17 >> 1) - v16) * (v42 + (v17 >> 1) - v16) < (unsigned int)(v19 * v19) )
+            {
+              v20.z = *(short *)v1;
+              v20.y = *((short *)v1 - 100);
+              v20.x = *((short *)v1 - 200);
+              if ( sub_407A1C(v40, v38, v42 + 50, v20) )
+              {
+                Vec3_int_::Normalize(&a1, &v48, &v44);
+                v21 = pVelocity;
+                v22 = uActorID;
+                pVelocity->x = a1;
+                v21->y = v48;
+                v21->z = v44;
+                sub_43B1B0(*((short *)v1 - 300), v22, v21, stru_50FE08.field_450[v43]);
+              }
+            }
+          }
+        }
+      }
+      else
+      {
+        v23 = pParty->vPosition.y - *((short *)v1 - 100);
+        v24 = ((signed int)pParty->uPartyHeight >> 1) - *(short *)v1;
+        a1 = pParty->vPosition.x - *((short *)v1 - 200);
+        v48 = v23;
+        if ( a1 * a1 + v23 * v23 + (pParty->vPosition.z + v24) * (pParty->vPosition.z + v24) < (unsigned int)((*((short *)v1 + 100) + 32) * (*((short *)v1 + 100) + 32)) )
+        {
+          v25.z = *(short *)v1;
+          v25.y = *((short *)v1 - 100);
+          v25.x = *((short *)v1 - 200);
+          if ( sub_407A1C(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z + pParty->sEyelevel, v25) )
+          {
+            v26 = 0;
+            v27 = (char *)&pParty->pPlayers[0].pConditions[15];
+            do
+            {
+              if ( !(*((int *)v27 - 1) | *((int *)v27 - 2)) && !*(_QWORD *)v27 && !*((_QWORD *)v27 + 1) )
+                DamagePlayerFromMonster(*((short *)v1 - 300), stru_50FE08.field_450[v43], pVelocity, v26);
+              v27 += 6972;
+              ++v26;
+            }
+            while ( (signed int)v27 < (signed int)&pParty->pHirelings[1].evtb );
+          }
+        }
+        uActorID = 0;
+        if ( (signed int)uNumActors > 0 )
+        {
+          v28 = (char *)&pActors[0].vPosition.z;
+          do
+          {
+            if ( ((Actor *)(v28 - 146))->CanAct() )
+            {
+              v29 = *(short *)v1;
+              v30 = *((short *)v28 - 1) - *((short *)v1 - 100);
+              a1 = *((short *)v28 - 2) - *((short *)v1 - 200);
+              v31 = *(short *)v28;
+              v48 = v30;
+              v44 = v31;
+              v32 = ((signed int)*((short *)v28 - 4) >> 1) - v29;
+              v33 = *((short *)v28 - 5) + *((short *)v1 + 100);
+              if ( a1 * a1 + v48 * v48 + (v31 + v32) * (v31 + v32) < (unsigned int)(v33 * v33) )
+              {
+                v34.z = *(short *)v1;
+                v34.y = *((short *)v1 - 100);
+                v34.x = *((short *)v1 - 200);
+                if ( sub_407A1C(*((short *)v28 - 2), *((short *)v28 - 1), *(short *)v28 + 50, v34) )
+                {
+                  Vec3_int_::Normalize(&a1, &v48, &v44);
+                  v35 = pVelocity;
+                  pVelocity->x = a1;
+                  v35->y = v48;
+                  v35->z = v44;
+                  switch ( v41 )
+                  {
+                    case 4:
+                      DamageMonsterFromParty(*((short *)v1 - 300), uActorID, v35);
+                      break;
+                    case 3:
+                      if ( v36 && pActors[v37].GetActorsRelation((Actor *)(v28 - 146)) )
+                        sub_43B1B0(*((short *)v1 - 300), uActorID, pVelocity, v36->field_61);
+                      break;
+                    case 2:
+                      sub_43B057(*((short *)v1 - 300), uActorID, v35);
+                      break;
+                  }
+                }
+              }
+            }
+            ++uActorID;
+            v28 += 836;
+          }
+          while ( (signed int)uActorID < (signed int)uNumActors );
+        }
+      }
+      ++pVelocity;
+      v0 = v43 + 1;
+      v1 += 2;
+      ++v43;
+    }
+    while ( v43 < stru_50FE08.count );
+  }
+  stru_50FE08.count = 0;
+}
+// 50FE08: using guessed type stru298 stru_50FE08;
+
+//----- (00439474) --------------------------------------------------------
+bool __fastcall DamageMonsterFromParty(signed int a1, unsigned int uActorID_Monster, Vec3_int_ *pVelocity)
+{
+  signed int v3; // eax@1
+  LayingItem *v4; // ebx@1
+  int v5; // edx@3
+  bool uPlayerID; // eax@3
+  Player *pPlayer; // edi@4
+  Actor *pMonster; // esi@7
+  LayingItem *v9; // ebx@12
+  int v10; // eax@12
+  int v11; // ebx@12
+  unsigned int v12; // ecx@12
+  int v13; // edx@15
+  int v14; // edx@17
+  int v15; // eax@24
+  unsigned __int16 v16; // cx@25
+  int v17; // eax@29
+  int v18; // eax@38
+  unsigned __int8 v19; // zf@38
+  unsigned __int8 v20; // sf@38
+  int v21; // edx@44
+  int v22; // eax@44
+  unsigned __int8 v23; // zf@44
+  unsigned __int8 v24; // sf@44
+  int v25; // edx@51
+  int v26; // ecx@51
+  signed int v27; // eax@51
+  int v28; // eax@53
+  signed int v29; // eax@76
+  signed int v30; // eax@84
+  signed int v31; // eax@92
+  int v32; // eax@94
+  int v33; // eax@100
+  int v34; // eax@104
+  signed int v35; // eax@104
+  double v36; // st7@104
+  float v37; // ST08_4@104
+  float v38; // ST04_4@104
+  float v39; // ST00_4@104
+  int v40; // ebx@107
+  unsigned int v41; // ebx@109
+  signed __int64 v42; // qax@125
+  unsigned __int16 v43; // ax@132
+  char v44; // bl@132
+  unsigned __int16 v45; // ax@132
+  unsigned __int64 v46; // [sp+Ch] [bp-60h]@6
+  const char *v47; // [sp+14h] [bp-58h]@104
+  char *pPlayerName; // [sp+18h] [bp-54h]@12
+  char *pMonsterName; // [sp+1Ch] [bp-50h]@6
+  int v50; // [sp+20h] [bp-4Ch]@6
+  unsigned __int64 *v51; // [sp+30h] [bp-3Ch]@6
+  int v52; // [sp+34h] [bp-38h]@12
+  int v53; // [sp+38h] [bp-34h]@10
+  int v54; // [sp+3Ch] [bp-30h]@1
+  int v55; // [sp+40h] [bp-2Ch]@12
+  signed int a4; // [sp+44h] [bp-28h]@1
+  PlayerEquipment *v57; // [sp+48h] [bp-24h]@10
+  int v58; // [sp+4Ch] [bp-20h]@10
+  int v59; // [sp+50h] [bp-1Ch]@1
+  unsigned int uActorID_Monster_; // [sp+54h] [bp-18h]@1
+  int v61; // [sp+58h] [bp-14h]@1
+  int v62; // [sp+5Ch] [bp-10h]@1
+  int uDamageAmount; // [sp+60h] [bp-Ch]@1
+  int a2; // [sp+64h] [bp-8h]@27
+  int a3; // [sp+6Bh] [bp-1h]@6
+
+  v3 = a1;
+  v4 = 0;
+  uActorID_Monster_ = uActorID_Monster;
+  v54 = a1;
+  uDamageAmount = 0;
+  a4 = 0;
+  v61 = 0;
+  v59 = 0;
+  v62 = 0;
+  if ( (a1 & 7) == 2 )
+  {
+    v4 = &pLayingItems[a1 >> 3];
+    uDamageAmount = (int)v4;
+    v61 = v4->field_60_distance_related_prolly_lod;
+    v3 = v4->field_58;
+    v54 = v4->field_58;
+  }
+  v5 = v3 & 7;
+  uPlayerID = v3 >> 3;
+  if ( v5 != 4 )
+    return uPlayerID;
+  pPlayer = &pParty->pPlayers[uPlayerID];
+  if ( uPlayerID < 0 && uPlayerID > 3 )
+  {
+    MessageBoxW(nullptr, L"Invalid player in damageMonsterFromParty!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Damage.cpp:457", 0);
+  }
+  pMonster = &pActors[uActorID_Monster_];
+  uPlayerID = pMonster->IsAlive();
+  if ( uPlayerID )
+    return uPlayerID;
+  BYTE1(pMonster->uAttributes) |= 0xC0u;
+  if ( pMonster->uAIState == Fleeing )
+    pMonster->uAttributes |= 0x20000u;
+  v58 = 0;
+  v53 = 0;
+  v57 = 0;
+  if ( !v4 )
+  {
+    v51 = (unsigned __int64 *)pPlayer->pEquipment.uMainHand;
+    v59 = 1;
+    if ( pPlayer->HasItemEquipped(EQUIP_TWO_HANDED) )
+    {
+      v55 = pItemsTable->pItems[*(int *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)v51 + 5]].uSkillType;
+      v28 = SkillToMastery(pPlayer->pActiveSkills[v55]);
+      uDamageAmount = v28;
+      if ( v55 )
+      {
+        if ( v55 == 6 )
+        {
+          if ( v28 >= 3 )
+          {
+            LOBYTE(v51) = pPlayer->GetActualSkillLevel(PLAYER_SKILL_MACE) & 0x3F;
+            v51 = (unsigned __int64 *)(unsigned __int8)v51;
+            if ( rand() % 100 < (unsigned __int8)v51 )
+              v58 = 1;
+          }
+          if ( uDamageAmount >= 4 )
+          {
+            LOBYTE(v51) = pPlayer->GetActualSkillLevel(PLAYER_SKILL_MACE) & 0x3F;
+            v51 = (unsigned __int64 *)(unsigned __int8)v51;
+            if ( rand() % 100 < (unsigned __int8)v51 )
+              v53 = 1;
+          }
+        }
+      }
+      else
+      {
+        if ( uDamageAmount >= 3 )
+        {
+          LOBYTE(v51) = pPlayer->GetActualSkillLevel((PLAYER_SKILL_TYPE)0) & 0x3F;
+          v51 = (unsigned __int64 *)(unsigned __int8)v51;
+          if ( rand() % 100 < (unsigned __int8)v51 )
+            v58 = 1;
+        }
+      }
+    }
+    v50 = pMonster->pMonsterInfo.uID;
+    a2 = 4;
+    v27 = pPlayer->CalculateMeleeDamageTo(0, 0, v50);
+    goto LABEL_65;
+  }
+  v19 = v4->field_48 == 99;
+  v61 = v4->field_60_distance_related_prolly_lod;
+  if ( !v19 )
+  {
+    v9 = (LayingItem *)uDamageAmount;
+    v50 = pParty->vPosition.x - *(int *)(uDamageAmount + 4);
+    v55 = abs(v50);
+    pMonsterName = (char *)(pParty->vPosition.y - v9->vPosition.y);
+    v51 = (unsigned __int64 *)abs((int)pMonsterName);
+    pPlayerName = (char *)(pParty->vPosition.z - v9->vPosition.z);
+    v52 = abs((int)pPlayerName);
+    v61 = v55;
+    v10 = v55;
+    v11 = (int)v51;
+    v12 = v52;
+    if ( v55 < (signed int)v51 )
+    {
+      v10 = (int)v51;
+      v11 = v55;
+    }
+    if ( v10 < v52 )
+    {
+      v13 = v10;
+      v10 = v52;
+      v12 = v13;
+    }
+    if ( v11 < (signed int)v12 )
+    {
+      v14 = v12;
+      v12 = v11;
+      v11 = v14;
+    }
+    uPlayerID = ((unsigned int)(11 * v11) >> 5) + (v12 >> 2) + v10;
+    v61 = uPlayerID;
+    if ( uPlayerID >= 2560 )
+    {
+      if ( v61 >= 5120 && !(BYTE1(pMonster->uAttributes) & 4) )
+        return uPlayerID;
+      v61 = 2;
+    }
+    else
+    {
+      v61 = 1;
+    }
+    v4 = (LayingItem *)uDamageAmount;
+  }
+  v15 = v4->field_48;
+  if ( v15 == 102 )
+  {
+    v16 = pPlayer->pActiveSkills[7];
+    v61 = 1;
+    if ( (signed int)SkillToMastery(v16) >= 3 )
+      a4 = pPlayer->pActiveSkills[7] & 0x3F;
+    a2 = 4;
+    uDamageAmount = pPlayer->CalculateMeleeDamageTo(1, 1, 0);
+    goto LABEL_67;
+  }
+  if ( v15 != 100 )
+  {
+    if ( v15 == 101 )
+    {
+      a2 = 0;
+      v18 = pPlayer->CalculateRangedDamageTo(0);
+      v19 = HIDWORD(pMonster->pActorBuffs[15].uExpireTime) == 0;
+      v20 = SHIDWORD(pMonster->pActorBuffs[15].uExpireTime) < 0;
+      uDamageAmount = v18;
+      if ( !v20 && (!(v20 | v19) || LODWORD(pMonster->pActorBuffs[15].uExpireTime)) )
+        uDamageAmount >>= 1;
+      v59 = 1;
+      goto LABEL_67;
+    }
+    if ( v15 == 39 )
+    {
+      a4 = 5 * v4->field_4C;
+      a2 = pPlayer->GetSpellSchool(0x27u);
+      v21 = v4->field_4C;
+      v50 = pMonster->sCurrentHP;
+      pMonsterName = (char *)v4->field_50;
+      v22 = _43AFE3_calc_spell_damage(39, v21, (signed int)pMonsterName, v50);
+      v23 = HIDWORD(pMonster->pActorBuffs[15].uExpireTime) == 0;
+      v24 = SHIDWORD(pMonster->pActorBuffs[15].uExpireTime) < 0;
+      uDamageAmount = v22;
+      if ( !v24 && (!(v24 | v23) || LODWORD(pMonster->pActorBuffs[15].uExpireTime)) )
+        uDamageAmount >>= 1;
+      v59 = 0;
+LABEL_67:
+      if ( !stru_50C198.PlayerHitOrMiss(pPlayer, pMonster, v61, a4) )
+      {
+LABEL_68:
+        LOWORD(uPlayerID) = pPlayer->PlaySound(52, 0);
+        return uPlayerID;
+      }
+      goto LABEL_69;
+    }
+    if ( v15 == 34 )
+    {
+      uDamageAmount = 0;
+      a2 = 4;
+      v58 = 1;
+      goto LABEL_67;
+    }
+    v50 = v4->field_48;
+    a2 = pPlayer->GetSpellSchool(v50);
+    v25 = v4->field_4C;
+    v26 = v4->field_48;
+    v50 = pMonster->sCurrentHP;
+    pMonsterName = (char *)v4->field_50;
+    v27 = _43AFE3_calc_spell_damage(v26, v25, (signed int)pMonsterName, v50);
+    v59 = 0;
+    v57 = (PlayerEquipment *)1;
+LABEL_65:
+    uDamageAmount = v27;
+    goto LABEL_66;
+  }
+  v50 = pMonster->word_000086_some_monster_id;
+  a2 = 4;
+  v17 = pPlayer->CalculateRangedDamageTo(v50);
+  v19 = v4->stru_24.uItemID == 0;
+  uDamageAmount = v17;
+  if ( !v19 && v4->stru_24.uAdditionalValue == 3 )
+  {
+    a2 = 0;
+    v57 = (PlayerEquipment *)1;
+  }
+  if ( SHIDWORD(pMonster->pActorBuffs[15].uExpireTime) >= 0
+    && (SHIDWORD(pMonster->pActorBuffs[15].uExpireTime) > 0 || LODWORD(pMonster->pActorBuffs[15].uExpireTime)) )
+    uDamageAmount >>= 1;
+  v59 = 1;
+LABEL_66:
+  if ( !v57 )
+    goto LABEL_67;
+LABEL_69:
+  if ( pPlayer->pConditions[1] )
+    uDamageAmount >>= 1;
+  if ( (signed __int64)pMonster->pActorBuffs[5].uExpireTime > 0 )
+    uDamageAmount = 0;
+  v61 = stru_50C198.CalcMagicalDamageToActor(pMonster, a2, uDamageAmount);
+  if ( !v4 && pPlayer->IsUnarmed() && (signed __int64)pPlayer->pPlayerBuffs[6].uExpireTime > 0 )
+  {
+    v50 = pPlayer->pPlayerBuffs[6].uPower;
+    v29 = stru_50C198.CalcMagicalDamageToActor(pMonster, 8, v50);
+    v61 += v29;
+  }
+  uDamageAmount = v61;
+  if ( v59 )
+  {
+    if ( v4 )
+    {
+      a4 = v4->stru_24._439DF3_get_additional_damage(&a2, &v62);
+      if ( v62 && pMonster->sCurrentHP > 0 )
+      {
+        pPlayer->sHealth += v61 / 5;
+        if ( pPlayer->sHealth > pPlayer->GetMaxHealth() )
+          pPlayer->sHealth = pPlayer->GetMaxHealth();
+        v62 = 0;
+      }
+      v30 = stru_50C198.CalcMagicalDamageToActor(pMonster, a2, a4);
+      uDamageAmount = v61 + v30;
+    }
+    else
+    {
+      v59 = 0;
+      v57 = &pPlayer->pEquipment;
+      do
+      {
+        if ( pPlayer->HasItemEquipped((ITEM_EQUIP_TYPE)v59) )
+        {
+          auto _s = (ItemGen *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v57->uOffHand + 5];
+          a4 = _s->_439DF3_get_additional_damage(&a2, &v62);
+          if ( v62 && pMonster->sCurrentHP > 0 )
+          {
+            pPlayer->sHealth += v61 / 5;
+            if ( pPlayer->sHealth > pPlayer->GetMaxHealth() )
+              pPlayer->sHealth = pPlayer->GetMaxHealth();
+            v62 = 0;
+          }
+          v31 = stru_50C198.CalcMagicalDamageToActor(pMonster, a2, a4);
+          uDamageAmount += v31;
+        }
+        ++v59;
+        v57 = (PlayerEquipment *)((char *)v57 + 4);
+      }
+      while ( v59 <= 1 );
+    }
+  }
+  v32 = uDamageAmount;
+  pMonster->sCurrentHP -= uDamageAmount;
+  if ( !v32 && !v58 )
+    goto LABEL_68;
+  if ( pMonster->sCurrentHP > 0 )
+  {
+    Actor::_4030AD(uActorID_Monster_, v54, 0);
+    Actor::_43AC45(uActorID_Monster_, 1);
+    if ( bShowDamage )
+    {
+      v50 = uDamageAmount;
+      pMonsterName = (char *)pMonster;
+      pPlayerName = pPlayer->pName;
+      if ( v4 )
+        v47 = pGlobalTXT_LocalizationStrings[189];// "%s shoots %s for %lu points"
+      else
+        v47 = pGlobalTXT_LocalizationStrings[164];// "%s hits %s for %lu damage"
+      sprintf(pTmpBuf, v47, pPlayerName, pMonsterName, v50);
+      ShowStatusBarString(pTmpBuf, 2u);
+    }
+    v41 = 0;
+  }
+  else
+  {
+    if ( pMonsterStats->pInfos[pMonster->pMonsterInfo.uID].bQuestMonster & 1 )
+    {
+      v33 = byte_4D864C && BYTE2(pGame->uFlags) & 8 ? 10 * pMonster->uActorRadius : pMonster->uActorRadius;
+      v55 = v33;
+      if ( pRenderer->pRenderD3D )
+      {
+        if ( pGame->uFlags2 & 0x20 )
+        {
+          v50 = 0;
+          pMonsterName = 0;
+          v34 = pMonster->vPosition.z;
+          *(float *)&pPlayerName = (double)v55;
+          v51 = (unsigned __int64 *)v34;
+          *(float *)&v47 = 0.0;
+          v35 = pMonster->vPosition.y;
+          *((float *)&v46 + 1) = 0.0;
+          *(float *)&v46 = 1.0;
+          v36 = (double)(signed int)v51;
+          v51 = (unsigned __int64 *)v35;
+          v37 = v36;
+          v51 = (unsigned __int64 *)pMonster->vPosition.x;
+          v38 = (double)v35;
+          v39 = (double)(signed int)v51;
+          pDecalBuilder->AddBloodsplat(v39, v38, v37, 1.0, 0.0, 0.0, *(float *)&pPlayerName, 0, 0);
+        }
+      }
+    }
+    Actor::Die(uActorID_Monster_);
+    Actor::_438CF3(uActorID_Monster_);
+    Actor::_43AC45(uActorID_Monster_, 1);
+    if ( pMonster->pMonsterInfo.uExp )
+      sub_4269A2_GivePartyExp(pMonsterStats->pInfos[pMonster->pMonsterInfo.uID].uExp);
+    v40 = 51;
+    if ( rand() % 100 < 20 )
+      v40 = ((signed int)pMonster->pMonsterInfo.uHP >= 100) + 1;
+    pPlayer->PlaySound(v40, 0);
+    v41 = 0;
+    if ( bShowDamage )
+    {
+      v50 = (int)pMonster;
+      pMonsterName = (char *)uDamageAmount;
+      pPlayerName = pPlayer->pName;             // "%s inflicts %lu points killing %s"
+      sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[175], pPlayer->pName, uDamageAmount, pMonster);
+      ShowStatusBarString(pTmpBuf, 2u);
+    }
+  }
+  if ( SHIDWORD(pMonster->pActorBuffs[20].uExpireTime) >= (signed int)v41
+    && (SHIDWORD(pMonster->pActorBuffs[20].uExpireTime) > (signed int)v41
+     || LODWORD(pMonster->pActorBuffs[20].uExpireTime) > v41)
+    && uDamageAmount != v41 )
+    pPlayer->ReceiveDamage(uDamageAmount, a2);
+  v50 = 24;
+  v59 = 20 * v61 / (signed int)pMonster->pMonsterInfo.uHP;
+  if ( (pPlayer->_48EA46_calc_special_bonus_by_items(24) || v58 != v41)
+    && stru_50C198.GetMagicalResistance(pMonster, 3u) )
+  {
+    LODWORD(v42) = 20;
+    v59 = 10;
+    if ( pParty->bTurnBasedModeOn == v41 )
+      v42 = (signed __int64)(flt_6BE3A8_debug_recmod2 * 42.66666666666666);
+    pMonster->pMonsterInfo.uRecoveryTime += v42;
+    if ( bShowDamage != v41 )
+    {
+      v50 = (int)pMonster;
+      pMonsterName = pPlayer->pName;            // "%s stuns %s"
+      sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[635], pPlayer->pName, pMonster);
+      ShowStatusBarString(pTmpBuf, 2u);
+    }
+  }
+  if ( v53 != v41 )
+  {
+    if ( pMonster->CanAct() )
+    {
+      if ( stru_50C198.GetMagicalResistance(pMonster, 3u) )
+      {
+        LOBYTE(v43) = pPlayer->GetActualSkillLevel(PLAYER_SKILL_MACE);
+        v44 = v43;
+        v45 = SkillToMastery(v43);
+        v51 = (unsigned __int64 *)(7680 * (v44 & 0x3F));
+        v46 = pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)v51 * 0.033333335);
+        pMonster->pActorBuffs[6].Apply(v46, v45, 0, 0, 0);
+        if ( bShowDamage )
+        {
+          v50 = (int)pMonster;
+          pMonsterName = pPlayer->pName;        // "%s paralyzes %s"
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[636], pPlayer->pName, pMonster);
+          ShowStatusBarString(pTmpBuf, 2u);
+        }
+      }
+    }
+  }
+  if ( v59 > 10 )
+    v59 = 10;
+  if ( !MonsterStats::BelongsToSupertype(pMonster->pMonsterInfo.uID, MONSTER_SUPERTYPE_TREANT) )
+  {
+    pVelocity->x = (unsigned __int64)(v59 * (signed __int64)pVelocity->x) >> 16;
+    pVelocity->y = (unsigned __int64)(v59 * (signed __int64)pVelocity->y) >> 16;
+    pVelocity->z = (unsigned __int64)(v59 * (signed __int64)pVelocity->z) >> 16;
+    pMonster->vVelocity.x = 50 * LOWORD(pVelocity->x);
+    pMonster->vVelocity.y = 50 * LOWORD(pVelocity->y);
+    pMonster->vVelocity.z = 50 * LOWORD(pVelocity->z);
+  }
+  return Actor::AddBloodsplatOnDamageOverlay(uActorID_Monster_, 1, v61);
+}
+// 4D864C: using guessed type char byte_4D864C;
+
+
+//----- (00439FCB) --------------------------------------------------------
+void __fastcall DamagePlayerFromMonster(unsigned int uObjID, int a2, Vec3_int_ *pPos, unsigned int a4)
+{
+  signed int v4; // esi@1
+  unsigned int v5; // ecx@1
+  Player *v6; // ebx@3
+  Actor *v7; // esi@3
+  unsigned int v8; // eax@4
+  char *v9; // eax@5
+  signed int v10; // eax@6
+  int v11; // edx@8
+  int v12; // edx@9
+  int v13; // edx@10
+  int v14; // edx@16
+  int v15; // edx@17
+  int v16; // edx@18
+  enum SoundID v17; // eax@24
+  int v18; // eax@26
+  unsigned __int8 v19; // zf@26
+  unsigned __int8 v20; // sf@26
+  unsigned __int16 v21; // ax@29
+  signed int v22; // edi@36
+  int v23; // eax@38
+  signed int v24; // eax@44
+  unsigned __int16 v25; // cx@47
+  signed int v26; // eax@49
+  int v27; // eax@54
+  float v28; // ST18_4@58
+  double v29; // st7@58
+  float v30; // ST08_4@58
+  double v31; // st7@58
+  float v32; // ST04_4@58
+  float v33; // ST00_4@58
+  int v34; // edi@61
+  int v35; // eax@70
+  double v36; // st7@70
+  LayingItem *v37; // ebx@77
+  int v38; // edi@77
+  int v39; // esi@77
+  int v40; // eax@77
+  int v41; // eax@77
+  int v42; // eax@78
+  char *v43; // eax@81
+  Actor *v44; // esi@82
+  char *v45; // edi@84
+  unsigned __int16 v46; // ax@84
+  int v47; // ebx@105
+  int v48; // eax@107
+  unsigned __int16 v49; // ax@116
+  int v50; // ebx@123
+  unsigned __int16 v51; // ax@124
+  char v52; // bl@124
+  int v53; // eax@128
+  signed int v54; // eax@134
+  unsigned __int16 v55; // cx@137
+  signed int v56; // eax@139
+  int v57; // eax@144
+  float v58; // ST18_4@148
+  double v59; // st7@148
+  float v60; // ST08_4@148
+  double v61; // st7@148
+  float v62; // ST04_4@148
+  float v63; // ST00_4@148
+  int v64; // ebx@151
+  int v65; // eax@161
+  double v66; // st7@161
+  signed int v67; // ecx@164
+  signed int v68; // eax@170
+  int v69; // ecx@170
+  int v70; // eax@171
+  enum SoundID v71; // [sp+20h] [bp-34h]@12
+  int v72; // [sp+30h] [bp-24h]@164
+  double v73; // [sp+40h] [bp-14h]@72
+  signed int v74; // [sp+44h] [bp-10h]@1
+  unsigned int v75; // [sp+48h] [bp-Ch]@3
+  unsigned int uActorID; // [sp+4Ch] [bp-8h]@1
+  int v77; // [sp+50h] [bp-4h]@26
+  signed int a4a; // [sp+60h] [bp+Ch]@162
+  Player *a4b; // [sp+60h] [bp+Ch]@168
+
+  v4 = (signed int)uObjID >> 3;
+  v5 = (uObjID & 7) - 2;
+  v74 = a2;
+  uActorID = v4;
+  if ( v5 )
+  {
+    if ( v5 != 1
+      || (v6 = &pParty->pPlayers[a4], v7 = &pActors[v4],
+                                     v75 = v6->sHealth,
+                                     !stru_50C198.ActorHitOrMiss(v7, v6)) )
+      return;
+    v8 = v6->pEquipment.uBody;
+    if ( !v8
+      || (v9 = (char *)v6 + 36 * v8, v9[516] & 2)
+      || (v10 = pItemsTable->pItems[*((int *)v9 + 124)].uSkillType, v10 < 10)
+      || v10 > 11 )
+    {
+      v14 = rand() % 4;
+      if ( !v14 )
+      {
+        v71 = (SoundID)108;
+        goto LABEL_24;
+      }
+      v15 = v14 - 1;
+      if ( !v15 )
+      {
+        v71 = (SoundID)109;
+        goto LABEL_24;
+      }
+      v16 = v15 - 1;
+      if ( !v16 )
+      {
+        v71 = (SoundID)110;
+        goto LABEL_24;
+      }
+      if ( v16 == 1 )
+      {
+        v71 = (SoundID)44;
+        goto LABEL_24;
+      }
+    }
+    else
+    {
+      v11 = rand() % 4;
+      if ( !v11 )
+      {
+        v71 = (SoundID)105;
+        goto LABEL_24;
+      }
+      v12 = v11 - 1;
+      if ( !v12 )
+      {
+        v71 = (SoundID)106;
+        goto LABEL_24;
+      }
+      v13 = v12 - 1;
+      if ( !v13 )
+      {
+        v71 = (SoundID)107;
+        goto LABEL_24;
+      }
+      if ( v13 == 1 )
+      {
+        v71 = (SoundID)45;
+LABEL_24:
+        v17 = v71;
+        goto LABEL_26;
+      }
+    }
+    v17 = (SoundID)a4;
+LABEL_26:
+    pAudioPlayer->PlaySound(v17, (8 * a4 + 80) | 4, 0, -1, 0, 0, 0, 0);
+    v18 = Actor::_43B3E0_CalcDamage(v7, v74);
+    v19 = HIDWORD(v7->pActorBuffs[3].uExpireTime) == 0;
+    v20 = SHIDWORD(v7->pActorBuffs[3].uExpireTime) < 0;
+    v77 = v18;
+    if ( !v20 && (!(v20 | v19) || LODWORD(v7->pActorBuffs[3].uExpireTime) > 0) )
+    {
+      v21 = v7->pActorBuffs[3].uPower;
+      if ( v21 )
+        v77 /= (signed int)v21;
+    }
+    if ( v74 )
+    {
+      if ( v74 == 1 )
+      {
+        v22 = v7->pMonsterInfo.uAttack2Type;
+      }
+      else
+      {
+        if ( v74 == 2 )
+        {
+          v23 = v7->pMonsterInfo.uSpell1ID;
+        }
+        else
+        {
+          if ( v74 != 3 )
+          {
+            if ( v74 == 4 )
+              v22 = v7->pMonsterInfo.field_3C_some_special_attack;
+            else
+              v22 = 4;
+            goto LABEL_43;
+          }
+          v23 = v7->pMonsterInfo.uSpell2ID;
+        }
+        v22 = LOBYTE(pSpellStats->pInfos[v23].uSchool);
+      }
+    }
+    else
+    {
+      v22 = v7->pMonsterInfo.uAttack1Type;
+    }
+LABEL_43:
+    if ( !(dword_6BE368_debug_settings_2 & 0x10) )
+    {
+      v24 = v6->ReceiveDamage(v77, v22);
+      if ( SHIDWORD(v6->pPlayerBuffs[10].uExpireTime) >= 0
+        && (SHIDWORD(v6->pPlayerBuffs[10].uExpireTime) > 0 || LODWORD(v6->pPlayerBuffs[10].uExpireTime)) )
+      {
+        v25 = v7->uAIState;
+        if ( v25 != 5 )
+        {
+          if ( v25 != 4 )
+          {
+            v26 = stru_50C198.CalcMagicalDamageToActor(v7, v22, v24);
+            v7->sCurrentHP -= v26;
+            if ( v26 )
+            {
+              if ( v7->sCurrentHP >= 1 )
+              {
+                Actor::_4030AD(uActorID, 8 * a4 | 4, 0);
+                Actor::_43AC45(uActorID, 1);
+              }
+              else
+              {
+                if ( pMonsterStats->pInfos[v7->pMonsterInfo.uID].bQuestMonster & 1 )
+                {
+                  v27 = byte_4D864C && BYTE2(pGame->uFlags) & 8 ? 10 * v7->uActorRadius : v7->uActorRadius;
+                  v74 = v27;
+                  if ( pRenderer->pRenderD3D )
+                  {
+                    if ( pGame->uFlags2 & 0x20 )
+                    {
+                      v28 = (double)v74;
+                      v74 = v7->vPosition.z;
+                      v29 = (double)v74;
+                      v74 = v7->vPosition.y;
+                      v30 = v29;
+                      v31 = (double)v74;
+                      v74 = v7->vPosition.x;
+                      v32 = v31;
+                      v33 = (double)v74;
+                      pDecalBuilder->AddBloodsplat(v33, v32, v30, 1.0, 0.0, 0.0, v28, 0, 0);
+                    }
+                  }
+                }
+                Actor::Die(uActorID);
+                Actor::_438CF3(uActorID);
+                Actor::_43AC45(uActorID, 1);
+                if ( v7->pMonsterInfo.uExp )
+                  sub_4269A2_GivePartyExp(pMonsterStats->pInfos[v7->pMonsterInfo.uID].uExp);
+                v34 = 51;
+                if ( rand() % 100 < 20 )
+                  v34 = ((signed int)v7->pMonsterInfo.uHP >= 100) + 1;
+                v6->PlaySound(v34, 0);
+              }
+            }
+          }
+        }
+      }
+      if ( !(dword_6BE368_debug_settings_2 & 0x10)
+        && v7->pMonsterInfo.uSpecialAttack
+        && rand() % 100 < v7->pMonsterInfo.uLevel * v7->pMonsterInfo.uSpecialAttackType )
+        v6->_48DCF6(v7->pMonsterInfo.uSpecialAttack, v7);
+    }
+    if ( !pParty->bTurnBasedModeOn )
+    {
+      v35 = v6->GetActualEndurance();
+      v36 = (double)(20 - v6->_48EA1B_get_static_effect(v35)) * flt_6BE3A4_debug_recmod1 * 2.133333333333333;
+      v6->SetRecoveryTime((signed __int64)v36);
+    }
+    if ( v77 )
+    {
+      v73 = (double)(signed int)v75;
+      if ( (double)v6->GetMaxHealth() * 0.25 < v73 )
+      {
+        if ( v6->sHealth > 0 )
+        {
+          if ( (double)v6->GetMaxHealth() * 0.25 >= (double)v6->sHealth )
+            v6->PlaySound(48, 0);
+        }
+      }
+    }
+    viewparams->bRedrawGameUI = 1;
+    return;
+  }
+  v37 = &pLayingItems[uActorID];
+  v38 = v37->field_58 & 7;
+  v39 = v37->field_58 >> 3;
+  v40 = v37->field_58 & 7;
+  uActorID = v37->field_58 >> 3;
+  v41 = v40 - 2;
+  if ( !v41 )
+    goto LABEL_80;
+  v42 = v41 - 1;
+  if ( !v42 )
+  {
+    v44 = &pActors[v39];
+    if ( a4 == -1 )
+      a4 = stru_50C198.which_player_would_attack(v44);
+    v45 = (char *)&pParty->pPlayers[a4];
+    v77 = Actor::_43B3E0_CalcDamage(v44, v74);
+    v46 = v37->uItemType;
+    if ( v37->uItemType == 545 )
+    {
+      LOBYTE(v51) = ((Player *)v45)->GetActualSkillLevel(PLAYER_SKILL_UNARMED);
+      v52 = v51;
+      if ( (signed int)SkillToMastery(v51) >= 4 && rand() % 100 < (v52 & 0x3F) )
+      {
+        sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[637], v45 + 168);
+        ShowStatusBarString(pTmpBuf, 2u);
+        ((Player *)v45)->PlaySound(6, 0);
+        return;
+      }
+    }
+    else
+    {
+      if ( v46 != 555
+        && v46 != 510
+        && v46 != 500
+        && v46 != 515
+        && v46 != 505
+        && v46 != 530
+        && v46 != 525
+        && v46 != 520
+        && v46 != 535
+        && v46 != 540 )
+        goto LABEL_115;
+    }
+    if ( !stru_50C198.ActorHitOrMiss(v44, (Player *)v45) )
+      return;
+    if ( *((_QWORD *)v45 + 782) > 0i64 )
+      v77 >>= 1;
+    if ( ((Player *)v45)->HasEnchantedItemEquipped(36) )
+      v77 >>= 1;
+    if ( ((Player *)v45)->HasEnchantedItemEquipped(69) )
+      v77 >>= 1;
+    if ( ((Player *)v45)->HasItemEquipped(EQUIP_ARMOUR)
+      && *(int *)&v45[36 * *((int *)v45 + 1621) + 496] == 504 )
+      v77 >>= 1;
+    v75 = 0;
+    v47 = (int)(v45 + 6472);
+    do
+    {
+      if ( ((Player *)v45)->HasItemEquipped((ITEM_EQUIP_TYPE)v75) )
+      {
+        v48 = *(int *)&v45[36 * *(int *)v47 + 496];
+        if ( v48 == 520 )
+          v77 >>= 1;
+        if ( v48 == 531 )
+          v77 >>= 1;
+        if ( ((Player *)v45)->GetEquippedItemEquipType(v75) == 4 && SkillToMastery(*((short *)v45 + 140)) == 4 )
+          v77 >>= 1;
+      }
+      ++v75;
+      v47 += 4;
+    }
+    while ( (signed int)v75 <= 1 );
+LABEL_115:
+    if ( (signed __int64)v44->pActorBuffs[3].uExpireTime > 0 )
+    {
+      v49 = v44->pActorBuffs[3].uPower;
+      if ( v49 )
+        v77 /= (signed int)v49;
+    }
+    if ( !v74 )
+    {
+      v50 = v44->pMonsterInfo.uAttack1Type;
+      goto LABEL_133;
+    }
+    if ( v74 == 1 )
+    {
+      v50 = v44->pMonsterInfo.uAttack2Type;
+      goto LABEL_133;
+    }
+    if ( v74 == 2 )
+    {
+      v53 = v44->pMonsterInfo.uSpell1ID;
+    }
+    else
+    {
+      if ( v74 != 3 )
+      {
+        if ( v74 == 4 )
+          v50 = v44->pMonsterInfo.field_3C_some_special_attack;
+        else
+          v50 = 4;
+LABEL_133:
+        if ( !(dword_6BE368_debug_settings_2 & 0x10) )
+        {
+          v54 = ((Player *)v45)->ReceiveDamage(v77, v50);
+          if ( *((int *)v45 + 1553) >= 0 )
+          {
+            if ( *((int *)v45 + 1553) > 0 || *((int *)v45 + 1552) )
+            {
+              v55 = v44->uAIState;
+              if ( v55 != 5 )
+              {
+                if ( v55 != 4 )
+                {
+                  v56 = stru_50C198.CalcMagicalDamageToActor(v44, v50, v54);
+                  v44->sCurrentHP -= v56;
+                  if ( v56 )
+                  {
+                    if ( v44->sCurrentHP >= 1 )
+                    {
+                      Actor::_4030AD(uActorID, 8 * a4 | 4, 0);
+                      Actor::_43AC45(uActorID, 1);
+                    }
+                    else
+                    {
+                      if ( pMonsterStats->pInfos[v44->pMonsterInfo.uID].bQuestMonster & 1 )
+                      {
+                        v57 = byte_4D864C && BYTE2(pGame->uFlags) & 8 ? 10 * v44->uActorRadius : v44->uActorRadius;
+                        v75 = v57;
+                        if ( pRenderer->pRenderD3D )
+                        {
+                          if ( pGame->uFlags2 & 0x20 )
+                          {
+                            v58 = (double)(signed int)v75;
+                            v75 = v44->vPosition.z;
+                            v59 = (double)(signed int)v75;
+                            v75 = v44->vPosition.y;
+                            v60 = v59;
+                            v61 = (double)(signed int)v75;
+                            v75 = v44->vPosition.x;
+                            v62 = v61;
+                            v63 = (double)(signed int)v75;
+                            pDecalBuilder->AddBloodsplat(v63, v62, v60, 1.0, 0.0, 0.0, v58, 0, 0);
+                          }
+                        }
+                      }
+                      Actor::Die(uActorID);
+                      Actor::_438CF3(uActorID);
+                      Actor::_43AC45(uActorID, 1);
+                      if ( v44->pMonsterInfo.uExp )
+                        sub_4269A2_GivePartyExp(pMonsterStats->pInfos[v44->pMonsterInfo.uID].uExp);
+                      v64 = 51;
+                      if ( rand() % 100 < 20 )
+                        v64 = ((signed int)v44->pMonsterInfo.uHP >= 100) + 1;
+                      ((Player *)v45)->PlaySound(v64, 0);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        if ( !v74
+          && !(dword_6BE368_debug_settings_2 & 0x10)
+          && v44->pMonsterInfo.uSpecialAttack
+          && rand() % 100 < v44->pMonsterInfo.uLevel * v44->pMonsterInfo.uSpecialAttackType )
+          ((Player *)v45)->_48DCF6(v44->pMonsterInfo.uSpecialAttack, v44);
+        if ( !pParty->bTurnBasedModeOn )
+        {
+          v65 = ((Player *)v45)->GetActualEndurance();
+          v66 = (double)(20 - ((Player *)v45)->_48EA1B_get_static_effect(v65))
+              * flt_6BE3A4_debug_recmod1
+              * 2.133333333333333;
+          ((Player *)v45)->SetRecoveryTime((signed __int64)v66);
+        }
+        return;
+      }
+      v53 = v44->pMonsterInfo.uSpell2ID;
+    }
+    v50 = LOBYTE(pSpellStats->pInfos[v53].uSchool);
+    goto LABEL_133;
+  }
+  if ( v42 != 1 )
+    return;
+LABEL_80:
+  if ( a4 != -1 )
+  {
+    v43 = (char *)&pParty->pPlayers[a4];
+LABEL_168:
+    a4b = (Player *)v43;
+    if ( v38 != 4 || v37->field_48 != 100 )
+    {
+      v70 = ((Player *)v43)->GetMaxHealth();
+      v68 = _43AFE3_calc_spell_damage(v37->field_48, v37->field_4C, v37->field_50, v70);
+      v69 = LOBYTE(pSpellStats->pInfos[v37->field_48].uSchool);
+    }
+    else
+    {
+      v68 = pParty->pPlayers[uActorID].CalculateRangedDamageTo(0);
+      v69 = 0;
+    }
+    a4b->ReceiveDamage(v68, v69);
+    if ( v38 == 4 && !qword_A750D8 )
+    {
+      qword_A750D8 = 256i64;
+      word_A750E0 = 44;
+      word_A750E2 = uActorID + 1;
+    }
+    return;
+  }
+  v74 = 0;
+  a4a = 1;
+  do
+  {
+    if ( pPlayers[a4a]->CanAct() )
+    {
+      v67 = v74++;
+      *(&v72 + v67) = a4a;
+    }
+    ++a4a;
+  }
+  while ( a4a <= 4 );
+  if ( v74 )
+  {
+    v43 = &stru_AA1058[3].pSounds[6972 * *(&v72 + rand() % v74) + 40552];
+    goto LABEL_168;
+  }
+}
+
+
+//----- (0043A97E) --------------------------------------------------------
+void __fastcall sub_43A97E(unsigned int uLayingItemID, signed int a2)
+{
+  unsigned int v2; // esi@1
+  unsigned int v3; // ebx@1
+  int v4; // edi@1
+  int v5; // edx@1
+  unsigned int v6; // [sp+10h] [bp-4h]@1
+
+  v6 = uLayingItemID;
+  v2 = uLayingItemID;
+  v3 = a2 >> 3;
+  v4 = pLayingItems[uLayingItemID].field_58 & 7;
+  v5 = (a2 & 7) - 3;
+  if ( v5 )
+  {
+    if ( v5 == 1 )
+    {
+      layingitem_vel_50FDFC.x = pLayingItems[v2].vVelocity.x;
+      layingitem_vel_50FDFC.y = pLayingItems[v2].vVelocity.y;
+      layingitem_vel_50FDFC.z = pLayingItems[v2].vVelocity.z;
+      Vec3_int_::Normalize(&layingitem_vel_50FDFC.x, &layingitem_vel_50FDFC.y, &layingitem_vel_50FDFC.z);
+      DamagePlayerFromMonster(8 * v6 | 2, pLayingItems[v2].field_61, &layingitem_vel_50FDFC, 0xFFFFFFFFu);
+    }
+  }
+  else
+  {
+    layingitem_vel_50FDFC.x = pLayingItems[v2].vVelocity.x;
+    layingitem_vel_50FDFC.y = pLayingItems[v2].vVelocity.y;
+    layingitem_vel_50FDFC.z = pLayingItems[v2].vVelocity.z;
+    Vec3_int_::Normalize(&layingitem_vel_50FDFC.x, &layingitem_vel_50FDFC.y, &layingitem_vel_50FDFC.z);
+    switch ( v4 )
+    {
+      case OBJECT_Actor:
+        sub_43B1B0(8 * v6 | AI_OBJECT_LAYING_ITEM, v3, &layingitem_vel_50FDFC, pLayingItems[v2].field_61);
+        break;
+      case OBJECT_Player:
+        DamageMonsterFromParty(8 * v6 | AI_OBJECT_LAYING_ITEM, v3, &layingitem_vel_50FDFC);
+        break;
+      case OBJECT_Item:
+        sub_43B057(8 * v6 | AI_OBJECT_LAYING_ITEM, v3, &layingitem_vel_50FDFC);
+        break;
+    }
+  }
+}
+
+//----- (0043AA99) --------------------------------------------------------
+void __fastcall Vec3_int_::Rotate(int sDepth, int sRotY, int sRotX, Vec3_int_ v, int *outx, int *outy, int *outz)
+{
+  int v7; // ebx@1
+  int v8; // ST14_4@1
+  int v9; // edi@1
+  int anglea; // [sp+20h] [bp+8h]@1
+
+  v7 = sRotX;
+  v8 = sDepth;
+  v9 = sRotY;
+  anglea = (unsigned __int64)(stru_5C6E00->SinCos(sRotX) * (signed __int64)sDepth) >> 16;
+  *outx = v.x + ((unsigned __int64)(stru_5C6E00->SinCos(v9) * (signed __int64)anglea) >> 16);
+  *outy = v.y
+        + ((unsigned __int64)(stru_5C6E00->SinCos(v9 - stru_5C6E00->uIntegerHalfPi)
+                            * (signed __int64)anglea) >> 16);
+  *outz = v.z
+        + ((unsigned __int64)(stru_5C6E00->SinCos(v7 - stru_5C6E00->uIntegerHalfPi) * (signed __int64)v8) >> 16);
+}
+
+//----- (0043AB61) --------------------------------------------------------
+void Vec3_int_::Normalize(int *x, int *y, int *z)
+{
+  int *v3; // edi@1
+  int *v4; // esi@1
+  signed int v5; // eax@1
+
+  v3 = x;
+  v4 = y;
+  v5 = sub_452A9E(*y * *y + *z * *z + *x * *x);
+  *v3 *= 65536 / (v5 | 1);
+  *v4 *= 65536 / (v5 | 1);
+  *z *= 65536 / (v5 | 1);
+}
+
+
+
+
+//----- (0043AE12) --------------------------------------------------------
+double __fastcall sub_43AE12(signed int a1)
+{
+  signed int v1; // ST00_4@1
+  signed int v2; // ecx@1
+  double v3; // st7@1
+  double result; // st7@6
+
+  v1 = a1;
+  v2 = 0;
+  v3 = (double)v1;
+  do
+  {
+    if ( v3 < flt_4E4A80[v2 + 5] )
+      break;
+    ++v2;
+  }
+  while ( v2 < 5 );
+  if ( v2 <= 0 || v2 >= 5 )
+  {
+    if ( v2 )
+      result = flt_4E4A80[4];
+    else
+      result = flt_4E4A80[0];
+  }
+  else
+  {
+    result = (flt_4E4A80[v2] - *(float *)&aAuthenticamd[4 * v2 + 12])
+           * (v3 - flt_4E4A80[v2 + 4])
+           / (flt_4E4A80[v2 + 5] - flt_4E4A80[v2 + 4])
+           + flt_4E4A80[v2];
+  }
+  return result;
+}
+
+//----- (0043AFE3) --------------------------------------------------------
+int __fastcall _43AFE3_calc_spell_damage(int a1, int a2, signed int a3, int a4)
+{
+  int result; // eax@1
+  unsigned int v5; // [sp-4h] [bp-8h]@9
+
+  result = 0;
+  if ( a1 == 7 )
+  {
+    if ( a3 <= 0 )
+      return result;
+    if ( a3 <= 2 )
+    {
+      v5 = 6;
+    }
+    else
+    {
+      if ( a3 == 3 )
+      {
+        v5 = 8;
+      }
+      else
+      {
+        if ( a3 != 4 )
+          return result;
+        v5 = 10;
+      }
+    }
+    result = GetDiceResult(a2, v5);
+  }
+  else
+  {
+    if ( a1 == 44 )
+      result = a4 * (LOBYTE(pSpellDatas[40].field_10) + 2 * a2) / 100;
+    else
+      result = *((char *)&pSpellDatas[0].field_10 + 20 * a1)
+             + GetDiceResult(a2, *((char *)&pSpellDatas[0].field_10 + 20 * a1 + 1));
+  }
+  return result;
+}
+
+//----- (0043B057) --------------------------------------------------------
+void __fastcall sub_43B057(unsigned int uObjID, unsigned int uActorID, Vec3_int_ *pVelocity)
+{
+  Actor *pActor; // esi@1
+  LayingItem *v4; // eax@3
+  int v5; // ecx@3
+  int v6; // eax@4
+  int v7; // edi@4
+  unsigned int uActorIDa; // [sp+8h] [bp-8h]@1
+  unsigned int a2; // [sp+Ch] [bp-4h]@1
+  int a2a; // [sp+Ch] [bp-4h]@8
+
+  uActorIDa = uActorID;
+  pActor = &pActors[uActorID];
+  a2 = uObjID;
+  if ( !pActors[uActorID].IsAlive() )
+  {
+    if ( (a2 & 7) == 2 )
+    {
+      v4 = &pLayingItems[(signed int)a2 >> 3];
+      v5 = v4->field_48;
+      if ( v5 )
+      {
+        v6 = _43AFE3_calc_spell_damage(v5, v4->field_4C, v4->field_50, pActor->sCurrentHP);
+        v7 = stru_50C198.CalcMagicalDamageToActor(pActor, 0, v6);
+        pActor->sCurrentHP -= v7;
+        if ( v7 )
+        {
+          if ( pActor->sCurrentHP > 0 )
+            Actor::_4030AD(uActorIDa, a2, 0);
+          else
+            Actor::Die(uActorIDa);
+          a2a = 20 * v7 / (signed int)pActor->pMonsterInfo.uHP;
+          if ( 20 * v7 / (signed int)pActor->pMonsterInfo.uHP > 10 )
+            a2a = 10;
+          if ( !MonsterStats::BelongsToSupertype(pActor->pMonsterInfo.uID, MONSTER_SUPERTYPE_TREANT) )
+          {
+            pVelocity->x = (unsigned __int64)(a2a * (signed __int64)pVelocity->x) >> 16;
+            pVelocity->y = (unsigned __int64)(a2a * (signed __int64)pVelocity->y) >> 16;
+            pVelocity->z = (unsigned __int64)(a2a * (signed __int64)pVelocity->z) >> 16;
+            pActor->vVelocity.x = 50 * LOWORD(pVelocity->x);
+            pActor->vVelocity.y = 50 * LOWORD(pVelocity->y);
+            pActor->vVelocity.z = 50 * LOWORD(pVelocity->z);
+          }
+          Actor::AddBloodsplatOnDamageOverlay(uActorIDa, 1, v7);
+        }
+        else
+        {
+          Actor::_4030AD(uActorIDa, a2, 0);
+        }
+      }
+    }
+  }
+}
+
+//----- (0043B1B0) --------------------------------------------------------
+__int16 __fastcall sub_43B1B0(signed int a1, unsigned int a2, Vec3_int_ *pVelocity, signed int a4)
+{
+  int v4; // ebx@1
+  LayingItem *v5; // eax@2
+  bool v6; // eax@3
+  Actor *v7; // esi@4
+  Actor *v8; // edi@4
+  char v9; // zf@5
+  __int64 v10; // qax@8
+  signed __int16 v11; // cx@9
+  signed int v12; // ecx@20
+  int v13; // ecx@22
+  int v14; // edi@30
+  unsigned int uActorID; // [sp+Ch] [bp-8h]@1
+  signed int v17; // [sp+10h] [bp-4h]@1
+  int v18; // [sp+20h] [bp+Ch]@34
+
+  v4 = 0;
+  uActorID = a2;
+  v17 = a1;
+  if ( (a1 & 7) == 2 )
+  {
+    v5 = &pLayingItems[a1 >> 3];
+    v4 = v5->field_60_distance_related_prolly_lod;
+    v17 = v5->field_58;
+  }
+  LOWORD(v6) = v17 & 7;
+  if ( v6 == 3 )
+  {
+    v7 = &pActors[a2];
+    v8 = &pActors[v17 >> 3];
+    v6 = pActors[a2].IsAlive();
+    if ( !v6 )
+    {
+      v9 = v7->uAIState == 7;
+      v7->uLastCharacterIDToHit = v17;
+      if ( v9 )
+        BYTE2(v7->uAttributes) |= 2u;
+      v6 = stru_50C198._4273BB(v8, v7, v4, 0);
+      if ( v6 )
+      {
+        v10 = (unsigned int)Actor::_43B3E0_CalcDamage(v8, a4);
+        if ( (signed __int64)v8->pActorBuffs[3].uExpireTime > 0 )
+        {
+          v11 = v8->pActorBuffs[3].uPower;
+          if ( v11 )
+            v10 = (signed int)v10 / (unsigned __int16)v11;
+        }
+        if ( SHIDWORD(v7->pActorBuffs[5].uExpireTime) >= SHIDWORD(v10)
+          && (SHIDWORD(v7->pActorBuffs[5].uExpireTime) > SHIDWORD(v10)
+           || LODWORD(v7->pActorBuffs[5].uExpireTime) > HIDWORD(v10)) )
+          LODWORD(v10) = 0;
+        if ( a4 != HIDWORD(v10) )
+        {
+          if ( a4 - HIDWORD(v10) == 1 )
+          {
+            v12 = v8->pMonsterInfo.uAttack2Type;
+            if ( SHIDWORD(v7->pActorBuffs[15].uExpireTime) >= SHIDWORD(v10)
+              && (SHIDWORD(v7->pActorBuffs[15].uExpireTime) > SHIDWORD(v10)
+               || LODWORD(v7->pActorBuffs[15].uExpireTime) > HIDWORD(v10)) )
+              LODWORD(v10) = (signed int)v10 >> 1;
+            goto LABEL_30;
+          }
+          if ( a4 - HIDWORD(v10) == 2 )
+          {
+            v13 = v7->pMonsterInfo.uSpell1ID;
+          }
+          else
+          {
+            if ( a4 - HIDWORD(v10) != 3 )
+            {
+              if ( a4 - HIDWORD(v10) == 4 )
+                v12 = v8->pMonsterInfo.field_3C_some_special_attack;
+              else
+                v12 = 4;
+LABEL_30:
+              v14 = stru_50C198.CalcMagicalDamageToActor(v7, v12, v10);
+              v7->sCurrentHP -= v14;
+              if ( v14 )
+              {
+                if ( v7->sCurrentHP > 0 )
+                  Actor::_4030AD(uActorID, v17, 0);
+                else
+                  Actor::Die(uActorID);
+                Actor::_43AC45(uActorID, 0);
+                v18 = 20 * v14 / (signed int)v7->pMonsterInfo.uHP;
+                if ( 20 * v14 / (signed int)v7->pMonsterInfo.uHP > 10 )
+                  v18 = 10;
+                if ( !MonsterStats::BelongsToSupertype(v7->pMonsterInfo.uID, MONSTER_SUPERTYPE_TREANT) )
+                {
+                  pVelocity->x = (unsigned __int64)(v18 * (signed __int64)pVelocity->x) >> 16;
+                  pVelocity->y = (unsigned __int64)(v18 * (signed __int64)pVelocity->y) >> 16;
+                  pVelocity->z = (unsigned __int64)(v18 * (signed __int64)pVelocity->z) >> 16;
+                  v7->vVelocity.x = 50 * LOWORD(pVelocity->x);
+                  v7->vVelocity.y = 50 * LOWORD(pVelocity->y);
+                  v7->vVelocity.z = 50 * LOWORD(pVelocity->z);
+                }
+                LOWORD(v6) = Actor::AddBloodsplatOnDamageOverlay(uActorID, 1, v14);
+              }
+              else
+              {
+                LOWORD(v6) = Actor::_4030AD(uActorID, v17, 0);
+              }
+              return v6;
+            }
+            v13 = v7->pMonsterInfo.uSpell2ID;
+          }
+          v12 = LOBYTE(pSpellStats->pInfos[v13].uSchool);
+          goto LABEL_30;
+        }
+        v12 = v8->pMonsterInfo.uAttack1Type;
+        goto LABEL_30;
+      }
+    }
+  }
+  return v6;
+}
+
+
+//----- (0043BCA7) --------------------------------------------------------
+int __cdecl CharacterUI_LoadPaperdollTextures()
+{
+  int v0; // edi@7
+  enum CHARACTER_RACE v1; // ebx@7
+  signed int v2; // eax@7
+  int v3; // ebx@10
+  Player *v4; // edi@12
+  unsigned __int8 v5; // cl@12
+  int v6; // edi@16
+  unsigned int v7; // eax@16
+  Player *v8; // ebx@16
+  char *v9; // ebx@16
+  char v10; // al@16
+  signed int v11; // edi@21
+  Player *v12; // ebx@23
+  Player *v13; // edi@29
+  int v14; // ebp@29
+  stru331 *v15; // edi@65
+  signed int v16; // ebx@66
+  unsigned int v17; // eax@67
+  unsigned int *v18; // ecx@67
+  unsigned int *v19; // ebx@68
+  int v20; // edi@73
+  int v21; // ebp@73
+  unsigned int v22; // eax@76
+  int v23; // ecx@76
+  unsigned int v24; // eax@78
+  int v25; // ecx@78
+  int v26; // ebx@79
+  unsigned int v27; // eax@80
+  int v28; // ecx@80
+  int result; // eax@83
+  int v30; // [sp+10h] [bp-28h]@5
+  signed int v31; // [sp+10h] [bp-28h]@68
+  signed int v32; // [sp+10h] [bp-28h]@75
+  signed int v33; // [sp+10h] [bp-28h]@77
+  int v34; // [sp+10h] [bp-28h]@79
+  char *v35; // [sp+14h] [bp-24h]@65
+  int v36; // [sp+14h] [bp-24h]@75
+  int v37; // [sp+14h] [bp-24h]@77
+  signed int v38; // [sp+14h] [bp-24h]@79
+  unsigned int *v39; // [sp+18h] [bp-20h]@66
+  int *v40; // [sp+18h] [bp-20h]@73
+  unsigned int *v41; // [sp+1Ch] [bp-1Ch]@73
+  int v42; // [sp+20h] [bp-18h]@6
+  int v43; // [sp+20h] [bp-18h]@73
+  char pContainer[128]; // [sp+24h] [bp-14h]@12
+
+  uTextureID_MAGNIF_B = pIcons_LOD->LoadTexture("MAGNIF-B", TEXTURE_16BIT_PALETTE);
+  if ( !pParty->uAlignment || pParty->uAlignment == 1 || pParty->uAlignment == 2 )
+    uTextureID_BACKDOLL = pIcons_LOD->LoadTexture("BACKDOLL", TEXTURE_16BIT_PALETTE);
+  uTextureID_507B04 = uTextureID_right_panel;
+  v30 = 0;
+  uTextureID_BACKHAND = pIcons_LOD->LoadTexture("BACKHAND", TEXTURE_16BIT_PALETTE);
+  uTextureID_5118C8 = uTextureID_506438;
+  do
+  {
+    v42 = v30 + 1;
+    if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(v30 + 1) )
+    {
+      v0 = v30;
+      v1 = pPlayers[v30 + 1]->GetRace();
+      v2 = pPlayers[v30 + 1]->GetSexByVoice();
+      if ( v1 && v1 != 1 && v1 != 2 )
+        v3 = (v2 != 0) + 3;
+      else
+        v3 = (v2 != 0) + 1;
+      wsprintfA(pContainer, "pc23v%dBod", v3);
+      papredoll_dbods[v0] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      wsprintfA(pContainer, "pc23v%dlad", v3);
+      papredoll_dlads[v0] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      wsprintfA(pContainer, "pc23v%dlau", v3);
+      papredoll_dlaus[v0] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      wsprintfA(pContainer, "pc23v%drh", v3);
+      papredoll_drhs[v0] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      wsprintfA(pContainer, "pc23v%dlh", v3);
+      papredoll_dlhs[v0] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      wsprintfA(pContainer, "pc23v%dlhu", v3);
+      papredoll_dlhus[v0] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      v4 = pPlayers[v0 + 1];
+      v5 = v4->uFace;
+      if ( v5 == 12 || v5 == 13 )
+        papredoll_dbrds[(char)v5] = 0;
+      papredoll_flying_feet[v4->uFace] = 0;
+      IsPlayerWearingWatersuit[v30 + 1] = 1;
+    }
+    else
+    {
+      v6 = v30;
+      papredoll_dbods[v30] = pIcons_LOD->LoadTexture(
+                               dbod_texnames_by_face[pPlayers[v30 + 1]->uFace],
+                               TEXTURE_16BIT_PALETTE);
+      papredoll_dlads[v30] = pIcons_LOD->LoadTexture(
+                               dlad_texnames_by_face[pPlayers[v30 + 1]->uFace],
+                               TEXTURE_16BIT_PALETTE);
+      papredoll_dlaus[v30] = pIcons_LOD->LoadTexture(
+                               dlau_texnames_by_face[pPlayers[v30 + 1]->uFace],
+                               TEXTURE_16BIT_PALETTE);
+      papredoll_drhs[v30] = pIcons_LOD->LoadTexture(
+                              drh_texnames_by_face[pPlayers[v30 + 1]->uFace],
+                              TEXTURE_16BIT_PALETTE);
+      papredoll_dlhs[v30] = pIcons_LOD->LoadTexture(
+                              dlh_texnames_by_face[pPlayers[v30 + 1]->uFace],
+                              TEXTURE_16BIT_PALETTE);
+      v7 = pIcons_LOD->LoadTexture(
+             dlhu_texnames_by_face[pPlayers[v30 + 1]->uFace],
+             TEXTURE_16BIT_PALETTE);
+      v8 = pPlayers[v30 + 1];
+      papredoll_dlhus[v30] = v7;
+      v9 = (char *)&v8->uFace;
+      v10 = *v9;
+      if ( *v9 == 12 || v10 == 13 )
+      {
+        wsprintfA(pContainer, "pc%02dbrd", v10 + 1);
+        v9 = (char *)&pPlayers[v6 + 1]->uFace;
+        papredoll_dbrds[*v9] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      }
+      wsprintfA(pContainer, "item281pc%02d", *v9 + 1);
+      papredoll_flying_feet[pPlayers[v6 + 1]->uFace] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      IsPlayerWearingWatersuit[v30 + 1] = 0;
+    }
+    ++v30;
+  }
+  while ( v42 < 4 );
+  uTextureID_ar_up_up = pIcons_LOD->LoadTexture("ar_up_up", TEXTURE_16BIT_PALETTE);
+  uTextureID_ar_up_dn = pIcons_LOD->LoadTexture("ar_up_dn", TEXTURE_16BIT_PALETTE);
+  uTextureID_ar_dn_up = pIcons_LOD->LoadTexture("ar_dn_up", TEXTURE_16BIT_PALETTE);
+  uTextureID_ar_dn_dn = pIcons_LOD->LoadTexture("ar_dn_dn", TEXTURE_16BIT_PALETTE);
+  papredoll_dbrds[9] = pIcons_LOD->LoadTexture("ib-cd1-d", TEXTURE_16BIT_PALETTE);
+  papredoll_dbrds[7] = pIcons_LOD->LoadTexture("ib-cd2-d", TEXTURE_16BIT_PALETTE);
+  papredoll_dbrds[5] = pIcons_LOD->LoadTexture("ib-cd3-d", TEXTURE_16BIT_PALETTE);
+  papredoll_dbrds[3] = pIcons_LOD->LoadTexture("ib-cd4-d", TEXTURE_16BIT_PALETTE);
+  papredoll_dbrds[1] = pIcons_LOD->LoadTexture("ib-cd5-d", TEXTURE_16BIT_PALETTE);
+  v11 = 0;
+  do
+  {
+    byte_5111C0[v11] = 0;
+    if ( pParty->pPickedItem.uItemID != v11 + 66 )
+    {
+      v12 = pParty->pPlayers;
+      while ( !sub_43EE15_player_has_item(v11 + 66, v12, 0) )
+      {
+        ++v12;
+        if ( (signed int)v12 >= (signed int)pParty->pHirelings )
+          goto LABEL_28;
+      }
+    }
+    byte_5111C0[v11] = 1;
+LABEL_28:
+    ++v11;
+  }
+  while ( v11 < 54 );
+  *(int *)byte_5111F6 = 0;
+  *(int *)&byte_5111F6[4] = 0;
+  *(int *)&byte_5111F6[8] = 0;
+  *(int *)&byte_5111F6[12] = 0;
+  *(int *)&byte_5111F6[16] = 0;
+  v13 = pParty->pPlayers;
+  v14 = 1;
+  do
+  {
+    if ( sub_43EE15_player_has_item(0x204u, v13, 1) )
+      byte_5111F6[2] = 1;
+    if ( sub_43EE15_player_has_item(0x1F8u, v13, 1) )
+      byte_5111F6[0] = 1;
+    if ( sub_43EE15_player_has_item(0x1F9u, v13, 1) )
+      byte_5111F6[1] = 1;
+    if ( sub_43EE15_player_has_item(0x215u, v13, 1) )
+      byte_5111F6[16] = 1;
+    if ( sub_43EE15_player_has_item(0x200u, v13, 1) )
+      byte_5111F6[3] = 1;
+    if ( sub_43EE15_player_has_item(0x209u, v13, 1) )
+      byte_5111F6[4] = 1;
+    if ( sub_43EE15_player_has_item(0x20Au, v13, 1) )
+      byte_5111F6[5] = 1;
+    if ( sub_43EE15_player_has_item(0x20Bu, v13, 1) )
+      byte_5111F6[6] = 1;
+    if ( sub_43EE15_player_has_item(0x214u, v13, 1) )
+      byte_5111F6[7] = 1;
+    if ( sub_43EE15_player_has_item(0x220u, v13, 1) )
+      byte_5111F6[8] = 1;
+    if ( sub_43EE15_player_has_item(0x20Cu, v13, 1) )
+      byte_5111F6[9] = 1;
+    if ( sub_43EE15_player_has_item(0x217u, v13, 1) )
+      byte_5111F6[10] = 1;
+    if ( sub_43EE15_player_has_item(0x20Du, v13, 1) )
+      byte_5111F6[11] = 1;
+    if ( sub_43EE15_player_has_item(0x212u, v13, 1) )
+      byte_5111F6[12] = 1;
+    if ( sub_43EE15_player_has_item(0x223u, v13, 1) )
+      byte_5111F6[13] = 1;
+    if ( sub_43EE15_player_has_item(0x224u, v13, 1) )
+      byte_5111F6[14] = 1;
+    if ( sub_43EE15_player_has_item(0x226u, v13, 1) )
+      byte_5111F6[15] = 1;
+    ++v13;
+  }
+  while ( (signed int)v13 < (signed int)pParty->pHirelings );
+  v15 = &stru_511698.field_2C;
+  v35 = (char *)&stru_511718.field_18;
+  do
+  {
+    v16 = 0;
+    v39 = (unsigned int *)(v35 - 24);
+    do
+    {
+      _43C91D_FormItemTextureFilename(pContainer, v16 + 100, v14, 0);
+      v17 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      ++v16;
+      v18 = v39;
+      ++v39;
+      *v18 = v17;
+    }
+    while ( v16 < 5 );
+    _43C91D_FormItemTextureFilename(pContainer, 535, v14, 0);
+    v31 = 0;
+    v19 = (unsigned int *)((char *)v15 - 44);
+    *(int *)v35 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    do
+    {
+      _43C91D_FormItemTextureFilename(pContainer, v31++ + 89, v14, 0);
+      *v19 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      ++v19;
+    }
+    while ( v31 < 11 );
+    _43C91D_FormItemTextureFilename(pContainer, 521, v14, 0);
+    v15->field_0 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    _43C91D_FormItemTextureFilename(pContainer, 522, v14, 0);
+    v15->field_4 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    _43C91D_FormItemTextureFilename(pContainer, 523, v14, 0);
+    v15->field_8 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    _43C91D_FormItemTextureFilename(pContainer, 532, v14, 0);
+    v15->field_C = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    _43C91D_FormItemTextureFilename(pContainer, 544, v14, 0);
+    v15->field_10 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    if ( _43ED6F_check_party_races(true) )
+      papredoll_dbrds[11] = pIcons_LOD->LoadTexture("item092v3", TEXTURE_16BIT_PALETTE);
+    v35 += 28;
+    ++v14;
+    ++v15;
+  }
+  while ( v14 - 1 < 2 );
+  v43 = 0;
+  v20 = 1;
+  v40 = &dword_511638[0][5];
+  v21 = (int)paperdoll_array_511290[0][13];
+  v41 = (unsigned int *)&stru_511718.texid1;
+  do
+  {
+    if ( sub_43EDB9_get_some_race_sex_relation_2(v20 - 1) )
+    {
+      _43C91D_FormItemTextureFilename(pContainer, 524, v20, 0);
+      v32 = 66;
+      *v41 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      v36 = v21 - 152;
+      do
+      {
+        _43C91D_FormItemTextureFilename(pContainer, v32, v20, 0);
+        *(int *)(v36 - 4) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+        _43C91D_FormItemTextureFilename(pContainer, v32, v20, 1);
+        *(int *)v36 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+        _43C91D_FormItemTextureFilename(pContainer, v32, v20, 2);
+        v22 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+        v23 = v36;
+        v36 += 12;
+        ++v32;
+        *(int *)(v23 + 4) = v22;
+      }
+      while ( v32 - 66 < 13 );
+      _43C91D_FormItemTextureFilename(pContainer, 516, v20, 0);
+      *(int *)v21 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 516, v20, 1);
+      *(int *)(v21 + 4) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 516, v20, 2);
+      *(int *)(v21 + 8) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 505, v20, 0);
+      *(int *)(v21 + 12) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 505, v20, 1);
+      *(int *)(v21 + 16) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 505, v20, 2);
+      *(int *)(v21 + 20) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 504, v20, 0);
+      *(int *)(v21 + 24) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 504, v20, 1);
+      *(int *)(v21 + 28) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 504, v20, 2);
+      *(int *)(v21 + 32) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 533, v20, 0);
+      *(int *)(v21 + 36) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 533, v20, 1);
+      *(int *)(v21 + 40) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 533, v20, 2);
+      *(int *)(v21 + 44) = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      v33 = 0;
+      v37 = (int)(v40 - 5);
+      do
+      {
+        _43C91D_FormItemTextureFilename(pContainer, v33 + 115, v20, 0);
+        v24 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+        ++v33;
+        v25 = v37;
+        v37 += 4;
+        *(int *)v25 = v24;
+      }
+      while ( v33 < 5 );
+      _43C91D_FormItemTextureFilename(pContainer, 512, v20, 0);
+      v26 = v43;
+      v38 = 105;
+      v34 = v43;
+      *v40 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      do
+      {
+        _43C91D_FormItemTextureFilename(pContainer, v38, v20, 0);
+        *(int *)((char *)paperdoll_array_511828 + v34) = pIcons_LOD->LoadTexture(
+                                                           pContainer,
+                                                           TEXTURE_16BIT_PALETTE);
+        _43C91D_FormItemTextureFilename(pContainer, v38, v20, 1);
+        v27 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+        v28 = v34;
+        v34 += 4;
+        ++v38;
+        *(int *)((char *)dword_511788 + v28) = v27;
+      }
+      while ( v38 - 105 < 5 );
+      _43C91D_FormItemTextureFilename(pContainer, 525, v20, 0);
+      *(int *)((char *)&paperdoll_array_511828[0][5] + v43) = pIcons_LOD->LoadTexture(
+                                                                pContainer,
+                                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 530, v20, 0);
+      *(int *)((char *)&paperdoll_array_511828[0][6] + v43) = pIcons_LOD->LoadTexture(
+                                                                pContainer,
+                                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 547, v20, 0);
+      *(int *)((char *)&paperdoll_array_511828[0][7] + v43) = pIcons_LOD->LoadTexture(
+                                                                pContainer,
+                                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 548, v20, 0);
+      *(int *)((char *)&paperdoll_array_511828[0][8] + v43) = pIcons_LOD->LoadTexture(
+                                                                pContainer,
+                                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 550, v20, 0);
+      *(int *)((char *)&paperdoll_array_511828[0][9] + v43) = pIcons_LOD->LoadTexture(
+                                                                pContainer,
+                                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 525, v20, 1);
+      *(int *)((char *)&dword_51179C + v43) = pIcons_LOD->LoadTexture(
+                                                pContainer,
+                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 530, v20, 1);
+      *(int *)((char *)&dword_5117A0 + v43) = pIcons_LOD->LoadTexture(
+                                                pContainer,
+                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 547, v20, 1);
+      *(int *)((char *)&dword_5117A4 + v43) = pIcons_LOD->LoadTexture(
+                                                pContainer,
+                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 548, v20, 1);
+      *(int *)((char *)&dword_5117A8 + v43) = pIcons_LOD->LoadTexture(
+                                                pContainer,
+                                                TEXTURE_16BIT_PALETTE);
+      _43C91D_FormItemTextureFilename(pContainer, 550, v20, 1);
+      *(int *)((char *)&dword_5117AC + v43) = pIcons_LOD->LoadTexture(
+                                                pContainer,
+                                                TEXTURE_16BIT_PALETTE);
+    }
+    else
+    {
+      v26 = v43;
+    }
+    v41 += 7;
+    v40 += 6;
+    v21 += 204;
+    ++v20;
+    result = v20 - 1;
+    v43 = v26 + 40;
+  }
+  while ( v20 - 1 < 4 );
+  return result;
+}
+
+
+
+//----- (0043C91D) --------------------------------------------------------
+int __fastcall _43C91D_FormItemTextureFilename(char *a1, signed int a2, int a3, int a4)
+{
+  int result; // eax@2
+  char v5; // zf@3
+  const char *v6; // [sp-Ch] [bp-18h]@88
+  signed int v7; // [sp-8h] [bp-14h]@61
+  int v8; // [sp-4h] [bp-10h]@61
+  signed int v9; // [sp-4h] [bp-10h]@69
+
+  result = 0; //BUG   fn is void
+  if ( a2 <= 500 )
+  {
+    //v5 = *((char *)&pBloodsplatContainer->std__vector_pBloodsplats[62].field_20 + a2 + 2) == 0;
+    v5 = byte_5111C0[(a2 - 100) + 32 + 2] == 0;
+LABEL_21:
+    if ( v5 )
+      return result;
+    result = 516;
+    if ( a2 < 66 || a2 > 78 )
+    {
+      if ( a2 == 516 )
+        goto LABEL_79;
+      if ( a2 != 504 && a2 != 505 && a2 != 533 )
+      {
+        if ( (a2 < 100 || a2 > 104) && a2 != 524 && a2 != 535 )
+        {
+          if ( a2 >= 115 && a2 <= 119 || a2 == 512 )
+          {
+            if ( a2 == 512 )
+              a2 = 312;
+            goto LABEL_87;
+          }
+          if ( (a2 < 89 || a2 > 99) && a2 != 521 && a2 != 522 && a2 != 523 && a2 != 532 && a2 != 544 )
+          {
+            result = 525;
+            if ( (a2 < 105 || a2 > 109) && a2 != 525 && a2 != 530 && a2 != 547 && a2 != 548 && a2 != 550 )
+              return result;
+            switch ( a2 )
+            {
+              case 525:
+                a2 = 325;
+                break;
+              case 530:
+                a2 = 330;
+                break;
+              case 547:
+                a2 = 347;
+                break;
+              case 548:
+                a2 = 348;
+                break;
+              case 550:
+                a2 = 350;
+                break;
+            }
+            v8 = a3;
+            v7 = a2;
+            if ( !a4 )
+              goto LABEL_88;
+LABEL_91:
+            v6 = "item%3.3dv%da1";
+            return sprintf(a1, v6, v7, v8);
+          }
+          if ( a2 == 521 )
+          {
+            a2 = 239;
+            goto LABEL_87;
+          }
+          if ( a2 == 522 )
+          {
+            a2 = 240;
+            goto LABEL_87;
+          }
+          if ( a2 == 523 )
+          {
+            a2 = 241;
+            goto LABEL_87;
+          }
+          if ( a2 != 532 )
+          {
+            if ( a2 == 544 )
+              a2 = 344;
+            goto LABEL_87;
+          }
+          v9 = 93;
+          goto LABEL_70;
+        }
+        if ( a2 == 524 )
+        {
+          a2 = 324;
+          goto LABEL_87;
+        }
+        if ( a2 == 535 )
+        {
+          v9 = 104;
+LABEL_70:
+          a2 = v9;
+        }
+LABEL_87:
+        v8 = a3;
+        v7 = a2;
+LABEL_88:
+        v6 = "item%3.3dv%d";
+        return sprintf(a1, v6, v7, v8);
+      }
+    }
+    if ( a2 != 516 )
+    {
+      switch ( a2 )
+      {
+        case 504:
+          a2 = 235;
+          break;
+        case 505:
+          a2 = 236;
+          break;
+        case 533:
+          a2 = 73;
+          break;
+      }
+LABEL_86:
+      if ( a4 )
+      {
+        if ( a4 != 1 )
+        {
+          if ( a4 != 2 )
+            return result;
+          v8 = a3;
+          v7 = a2;
+          v6 = "item%3.3dv%da2";
+          return sprintf(a1, v6, v7, v8);
+        }
+        v8 = a3;
+        v7 = a2;
+        goto LABEL_91;
+      }
+      goto LABEL_87;
+    }
+LABEL_79:
+    a2 = 234;
+    goto LABEL_86;
+  }
+  result = a2 - 504;
+  switch ( a2 )
+  {
+    case 516:
+      v5 = byte_5111F6[2] == 0;
+      goto LABEL_21;
+    case 505:
+      v5 = byte_5111F6[1] == 0;
+      goto LABEL_21;
+    case 504:
+      v5 = byte_5111F6[0] == 0;
+      goto LABEL_21;
+    case 533:
+      v5 = byte_5111F6[16] == 0;
+      goto LABEL_21;
+    case 512:
+      v5 = byte_5111F6[3] == 0;
+      goto LABEL_21;
+    case 521:
+      v5 = byte_5111F6[4] == 0;
+      goto LABEL_21;
+    case 522:
+      v5 = byte_5111F6[5] == 0;
+      goto LABEL_21;
+    case 523:
+      v5 = byte_5111F6[6] == 0;
+      goto LABEL_21;
+    case 532:
+      v5 = byte_5111F6[7] == 0;
+      goto LABEL_21;
+    case 544:
+      v5 = byte_5111F6[8] == 0;
+      goto LABEL_21;
+    case 524:
+      v5 = byte_5111F6[9] == 0;
+      goto LABEL_21;
+    case 535:
+      v5 = byte_5111F6[10] == 0;
+      goto LABEL_21;
+    case 525:
+      v5 = byte_5111F6[11] == 0;
+      goto LABEL_21;
+    case 530:
+      v5 = byte_5111F6[12] == 0;
+      goto LABEL_21;
+    case 547:
+      v5 = byte_5111F6[13] == 0;
+      goto LABEL_21;
+    case 548:
+      v5 = byte_5111F6[14] == 0;
+      goto LABEL_21;
+    case 550:
+      v5 = byte_5111F6[15] == 0;
+      goto LABEL_21;
+    default:
+      return result;
+  }
+  return result;
+}
+
+//----- (0043CC7C) --------------------------------------------------------
+void __fastcall CharacterUI_DrawPaperdoll(unsigned int uPlayerID)
+{
+  Player **ppPlayer; // esi@1
+  Player *pPlayer; // ebx@1
+  enum CHARACTER_RACE v3; // edi@1
+  signed int v4; // eax@1
+  int v5; // edi@4
+  unsigned int v6; // ecx@9
+  int v7; // ecx@10
+  unsigned int v8; // eax@14
+  int v9; // eax@15
+  int v10; // edx@15
+  int v11; // ecx@15
+  int v12; // eax@15
+  unsigned int v13; // edi@15
+  unsigned int v14; // ebx@18
+  int v15; // ecx@18
+  Texture *v16; // ebp@27
+  double v17; // st7@29
+  int v18; // edi@30
+  char *v19; // eax@30
+  Texture *v20; // edi@31
+  unsigned int v21; // eax@37
+  int v22; // edi@38
+  int v23; // eax@38
+  int v24; // ebx@38
+  int v25; // eax@38
+  LODFile_IconsBitmaps *v26; // ecx@42
+  Texture *v27; // edi@51
+  double v28; // st7@51
+  char v29; // zf@54
+  char *v30; // eax@54
+  unsigned int v31; // eax@59
+  int v32; // edx@60
+  int v33; // eax@65
+  int v34; // eax@74
+  int v35; // ebx@74
+  unsigned int v36; // ecx@74
+  int v37; // eax@74
+  LODFile_IconsBitmaps *v38; // ecx@78
+  Texture *v39; // edi@85
+  double v40; // st7@87
+  int v41; // edi@88
+  Texture *v42; // edi@89
+  unsigned int v43; // eax@93
+  int v44; // edx@94
+  int v45; // eax@98
+  int v46; // eax@106
+  int v47; // ecx@106
+  int v48; // ebx@106
+  int v49; // eax@106
+  LODFile_IconsBitmaps *v50; // ecx@110
+  Texture *v51; // edi@117
+  double v52; // st7@119
+  int v53; // edi@120
+  Texture *v54; // edi@121
+  char *v55; // eax@122
+  unsigned int v56; // eax@127
+  int v57; // edi@128
+  int v58; // ecx@128
+  int v59; // ebx@129
+  int v60; // ecx@132
+  int v61; // eax@134
+  int v62; // ecx@136
+  Texture *v63; // edi@145
+  double v64; // st7@147
+  int v65; // edi@148
+  char *v66; // eax@148
+  Texture *v67; // edi@149
+  Player *v68; // ebx@155
+  unsigned int v69; // edx@155
+  int v70; // edx@156
+  unsigned int v71; // eax@160
+  int v72; // edi@161
+  int v73; // edx@163
+  int v74; // ecx@168
+  unsigned int v75; // ebx@170
+  int v76; // ecx@172
+  Texture *v77; // edi@181
+  double v78; // st7@183
+  int v79; // edi@184
+  char *v80; // eax@184
+  Texture *v81; // edi@185
+  unsigned int v82; // eax@192
+  int v83; // eax@193
+  int v84; // eax@197
+  int v85; // eax@197
+  int v86; // ecx@197
+  int v87; // eax@197
+  int v88; // eax@198
+  int v89; // eax@199
+  int v90; // edi@201
+  int v91; // edi@213
+  int v92; // ebx@213
+  int v93; // edi@214
+  int v94; // ebx@214
+  int v95; // eax@214
+  char *v96; // edi@226
+  double v97; // st7@228
+  int v98; // edi@229
+  char *v99; // eax@229
+  Render *v100; // ecx@229
+  Texture *v101; // edi@230
+  int v102; // edi@236
+  int v103; // eax@237
+  int v104; // ecx@237
+  int v105; // edx@237
+  int v106; // edx@238
+  int v107; // edx@239
+  int v108; // edx@240
+  int v109; // edi@250
+  char *v110; // edx@250
+  unsigned int v111; // eax@259
+  int v112; // eax@260
+  int v113; // eax@260
+  int v114; // eax@265
+  int v115; // eax@274
+  int v116; // ebx@274
+  unsigned int v117; // edi@274
+  double v118; // st7@286
+  int v119; // edi@287
+  char *v120; // eax@287
+  Texture *v121; // edi@288
+  unsigned int v122; // edi@295
+  int v123; // ebx@297
+  int v124; // edi@298
+  int v125; // ecx@303
+  int v126; // eax@312
+  unsigned int v127; // ebx@314
+  int v128; // ecx@316
+  Texture *v129; // edi@325
+  double v130; // st7@327
+  int v131; // edi@328
+  char *v132; // eax@328
+  Texture *v133; // edi@329
+  unsigned int v134; // eax@335
+  int v135; // eax@336
+  int v136; // edx@336
+  int v137; // eax@336
+  unsigned int v138; // ebx@339
+  int v139; // ecx@339
+  Texture *v140; // edi@348
+  double v141; // st7@350
+  int v142; // edi@351
+  char *v143; // eax@351
+  Texture *v144; // edi@352
+  unsigned int v145; // eax@358
+  int v146; // eax@359
+  int v147; // ecx@359
+  int v148; // eax@359
+  int v149; // edx@359
+  int v150; // ebx@362
+  int v151; // ecx@363
+  int v152; // ecx@364
+  unsigned int v153; // eax@370
+  unsigned int v154; // edi@370
+  int v155; // eax@370
+  LODFile_IconsBitmaps *v156; // ecx@374
+  Texture *v157; // ebp@381
+  double v158; // st7@383
+  Texture *v159; // edi@385
+  char *v160; // eax@386
+  unsigned int v161; // eax@393
+  int v162; // eax@394
+  unsigned int v163; // [sp-Ch] [bp-58h]@230
+  unsigned int v164; // [sp-Ch] [bp-58h]@233
+  signed int v165; // [sp-Ch] [bp-58h]@235
+  char *v166; // [sp-8h] [bp-54h]@16
+  const char *v167; // [sp-8h] [bp-54h]@23
+  const char *v168; // [sp-8h] [bp-54h]@43
+  const char *v169; // [sp-8h] [bp-54h]@79
+  const char *v170; // [sp-8h] [bp-54h]@111
+  const char *v171; // [sp-8h] [bp-54h]@141
+  const char *v172; // [sp-8h] [bp-54h]@177
+  const char *v173; // [sp-8h] [bp-54h]@222
+  int v174; // [sp-8h] [bp-54h]@228
+  unsigned int v175; // [sp-8h] [bp-54h]@230
+  unsigned int v176; // [sp-8h] [bp-54h]@233
+  signed int v177; // [sp-8h] [bp-54h]@235
+  const char *v178; // [sp-8h] [bp-54h]@242
+  const char *v179; // [sp-8h] [bp-54h]@280
+  const char *v180; // [sp-8h] [bp-54h]@321
+  char *v181; // [sp-8h] [bp-54h]@337
+  const char *v182; // [sp-8h] [bp-54h]@344
+  const char *v183; // [sp-8h] [bp-54h]@375
+  signed int v184; // [sp-4h] [bp-50h]@66
+  signed int v185; // [sp-4h] [bp-50h]@99
+  signed int v186; // [sp-4h] [bp-50h]@202
+  int v187; // [sp-4h] [bp-50h]@228
+  Texture *v188; // [sp-4h] [bp-50h]@230
+  Texture *v189; // [sp-4h] [bp-50h]@233
+  Texture *v190; // [sp-4h] [bp-50h]@235
+  signed int v191; // [sp-4h] [bp-50h]@266
+  signed int v192; // [sp-4h] [bp-50h]@304
+  unsigned int a3; // [sp+10h] [bp-3Ch]@7
+  int a3a; // [sp+10h] [bp-3Ch]@15
+  int a3b; // [sp+10h] [bp-3Ch]@38
+  unsigned int a3c; // [sp+10h] [bp-3Ch]@74
+  unsigned int a3d; // [sp+10h] [bp-3Ch]@106
+  int a3e; // [sp+10h] [bp-3Ch]@129
+  int a3f; // [sp+10h] [bp-3Ch]@168
+  unsigned int a3g; // [sp+10h] [bp-3Ch]@216
+  unsigned int a3h; // [sp+10h] [bp-3Ch]@274
+  int a3i; // [sp+10h] [bp-3Ch]@312
+  int a3j; // [sp+10h] [bp-3Ch]@336
+  int a3k; // [sp+10h] [bp-3Ch]@362
+  signed int a2; // [sp+14h] [bp-38h]@7
+  unsigned int a2a; // [sp+14h] [bp-38h]@15
+  Texture *a2b; // [sp+14h] [bp-38h]@49
+  int a2c; // [sp+14h] [bp-38h]@74
+  int a2d; // [sp+14h] [bp-38h]@106
+  int a2e; // [sp+14h] [bp-38h]@129
+  int a2f; // [sp+14h] [bp-38h]@168
+  int a2g; // [sp+14h] [bp-38h]@214
+  int a2h; // [sp+14h] [bp-38h]@274
+  Texture *a2i; // [sp+14h] [bp-38h]@284
+  int a2j; // [sp+14h] [bp-38h]@312
+  int a2k; // [sp+14h] [bp-38h]@336
+  Player *v217; // [sp+18h] [bp-34h]@1
+  int v218; // [sp+1Ch] [bp-30h]@15
+  int v219; // [sp+1Ch] [bp-30h]@60
+  int v220; // [sp+1Ch] [bp-30h]@94
+  int v221; // [sp+1Ch] [bp-30h]@128
+  int v222; // [sp+1Ch] [bp-30h]@161
+  int v223; // [sp+1Ch] [bp-30h]@213
+  char v224; // [sp+1Ch] [bp-30h]@237
+  int v225; // [sp+1Ch] [bp-30h]@260
+  int v226; // [sp+1Ch] [bp-30h]@298
+  int v227; // [sp+1Ch] [bp-30h]@336
+  int v228; // [sp+1Ch] [bp-30h]@359
+  int v229; // [sp+20h] [bp-2Ch]@15
+  int v230; // [sp+20h] [bp-2Ch]@38
+  int v231; // [sp+20h] [bp-2Ch]@60
+  int v232; // [sp+20h] [bp-2Ch]@94
+  int v233; // [sp+20h] [bp-2Ch]@128
+  int v234; // [sp+20h] [bp-2Ch]@161
+  int v235; // [sp+20h] [bp-2Ch]@197
+  int v236; // [sp+20h] [bp-2Ch]@260
+  int v237; // [sp+20h] [bp-2Ch]@298
+  int v238; // [sp+20h] [bp-2Ch]@336
+  int v239; // [sp+24h] [bp-28h]@6
+  int v240; // [sp+28h] [bp-24h]@7
+  unsigned int v241; // [sp+2Ch] [bp-20h]@38
+  int v242; // [sp+2Ch] [bp-20h]@197
+  unsigned int v243; // [sp+2Ch] [bp-20h]@370
+  int v244; // [sp+34h] [bp-18h]@6
+  signed int v245; // [sp+34h] [bp-18h]@361
+  unsigned int uPlayerID_; // [sp+38h] [bp-14h]@1
+  int uPlayerID_a; // [sp+38h] [bp-14h]@9
+  signed int v248; // [sp+40h] [bp-Ch]@4
+  int v249; // [sp+40h] [bp-Ch]@358
+  signed int v250; // [sp+44h] [bp-8h]@1
+
+  ppPlayer = &pPlayers[uPlayerID];
+  pPlayer = *ppPlayer;
+  uPlayerID_ = uPlayerID;
+  v217 = *ppPlayer;
+  pIcons_LOD->LoadTexture("sptext01", TEXTURE_16BIT_PALETTE);
+  v3 = pPlayer->GetRace();
+  v4 = pPlayer->GetSexByVoice();
+  v250 = v4;
+  if ( v3 && v3 != 1 && v3 != 2 )
+  {
+    v248 = 1;
+    v5 = (v4 != 0) + 2;
+  }
+  else
+  {
+    v248 = 0;
+    v5 = v4 != 0;
+  }
+  v239 = v5;
+  v244 = (*ppPlayer)->uFace;
+  pRenderer->ResetClip();
+  pRenderer->DrawTextureIndexed(
+    0x1D3u,
+    0,
+    (Texture *)(uTextureID_BACKDOLL != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_BACKDOLL] : 0));
+  if ( !IsPlayerWearingWatersuit[uPlayerID_] )
+  {
+    v21 = pPlayer->pEquipment.uBow;
+    if ( !v21 )
+      goto LABEL_59;
+    v230 = pPlayer->pEquipment.uBow;
+    v22 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v21 + 5];
+    v23 = *(int *)v22;
+    v24 = papredoll_4E4C28 + array_4E4C30[v239].equip_x - pItemsTable->pItems[v23].uEquipX;
+    a3b = paperdoll_4E4C2C + array_4E4C30[v239].equip_y - pItemsTable->pItems[v23].uEquipY;
+    v241 = pIcons_LOD->LoadTexture(pItemsTable->pItems[v23].pIconName, TEXTURE_16BIT_PALETTE);
+    v25 = *(int *)(v22 + 20);
+    if ( !(*(int *)(v22 + 20) & 0xF0) )
+    {
+      if ( v25 & 2 )
+      {
+        v27 = (Texture *)(v241 != -1 ? (int)&pIcons_LOD->pTextures[v241] : 0);
+        pRenderer->_4A6776(v24, a3b, v27);
+      }
+      else
+      {
+        v29 = (v25 & 1) == 0;
+        v30 = (char *)&pIcons_LOD->pTextures[v241];
+        if ( v29 )
+        {
+          v27 = (Texture *)(v241 != -1 ? (int)v30 : 0);
+          pRenderer->DrawTransparentGreenShade(v24, a3b, (Texture *)(v241 != -1 ? (int)v30 : 0));
+        }
+        else
+        {
+          v27 = (Texture *)(v241 != -1 ? (int)v30 : 0);
+          pRenderer->DrawTextureTransparent(v24, a3b, (Texture *)(v241 != -1 ? (int)v30 : 0));
+        }
+      }
+LABEL_57:
+      if ( !bRingsShownInCharScreen )
+        pRenderer->_4A612A(v24, a3b, v27, v230);
+LABEL_59:
+      v31 = v217->pEquipment.uCloak;
+      if ( !v31 )
+        goto LABEL_93;
+      v231 = v217->pEquipment.uCloak;
+      v32 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v31 + 5];
+      v219 = v32;
+      if ( *(int *)v32 != 525 )
+      {
+        switch ( *(int *)v32 )
+        {
+          case 0x212:
+            v184 = 6;
+            break;
+          case 0x223:
+            v184 = 7;
+            break;
+          case 0x224:
+            v184 = 8;
+            break;
+          default:
+            if ( *(int *)v32 != 550 )
+            {
+              v33 = *(int *)v32 - 105;
+LABEL_72:
+              if ( v33 < 0 || v33 >= 10 )
+                goto LABEL_93;
+LABEL_74:
+              v34 = v33 + 10 * v239;
+              v35 = paperdoll_array_511828[0][v34];
+              a2c = papredoll_4E4C28 + paperdoll_array_4E5570[0][v34][0];// TODO indexing
+              v36 = paperdoll_4E4C2C + paperdoll_array_4E5570[0][v34][1];
+              v37 = *(int *)(v32 + 20);
+              a3c = v36;
+              if ( !(v37 & 0xF0) )
+              {
+                v41 = v35 + 1;
+                if ( v37 & 2 )
+                {
+                  v42 = (Texture *)(v41 != 0 ? (int)&pIcons_LOD->pTextures[v35] : 0);
+                  pRenderer->_4A6776(a2c, v36, v42);
+                }
+                else
+                {
+                  v42 = (Texture *)(v41 != 0 ? (int)&pIcons_LOD->pTextures[v35] : 0);
+                  pRenderer->DrawTextureTransparent(a2c, v36, v42);
+                }
+                if ( !bRingsShownInCharScreen )
+                  pRenderer->_4A612A(a2c, a3c, v42, v231);
+LABEL_93:
+                v240 = 4 * uPlayerID_ - 4;
+                pRenderer->DrawTextureTransparent(
+                  papredoll_4E4C28,
+                  paperdoll_4E4C2C,
+                  (Texture *)(*(unsigned int *)((char *)papredoll_dbods + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_dbods + v240)] : 0));
+                v43 = v217->pEquipment.uBody;
+                if ( !v43 )
+                  goto LABEL_127;
+                v232 = v217->pEquipment.uBody;
+                v44 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v43 + 5];
+                v220 = v44;
+                if ( *(int *)v44 != 504 )
+                {
+                  if ( *(int *)v44 == 505 )
+                  {
+                    v185 = 14;
+                  }
+                  else
+                  {
+                    if ( *(int *)v44 == 516 )
+                    {
+                      v185 = 13;
+                    }
+                    else
+                    {
+                      if ( *(int *)v44 != 533 )
+                      {
+                        v45 = *(int *)v44 - 66;
+LABEL_104:
+                        if ( v45 < 0 || v45 >= 17 )
+                          goto LABEL_127;
+LABEL_106:
+                        v46 = 17 * v239 + v45;
+                        a2d = papredoll_4E4C28 + paperdoll_array_4E4E30[0][v46][0];// TODO indexing
+                        v47 = paperdoll_4E4C2C + paperdoll_array_4E4E30[0][v46][1];
+                        v48 = paperdoll_array_511290[0][v46][0];
+                        v49 = *(int *)(v44 + 20);
+                        a3d = v47;
+                        if ( !(v49 & 0xF0) )
+                        {
+                          v53 = v48 + 1;
+                          if ( v49 & 2 )
+                          {
+                            v54 = (Texture *)(v53 != 0 ? (int)&pIcons_LOD->pTextures[v48] : 0);
+                            pRenderer->_4A6776(a2d, v47, v54);
+                          }
+                          else
+                          {
+                            v29 = (v49 & 1) == 0;
+                            v55 = (char *)&pIcons_LOD->pTextures[v48];
+                            if ( v29 )
+                            {
+                              v54 = (Texture *)(v53 != 0 ? (int)v55 : 0);
+                              pRenderer->DrawTransparentGreenShade(a2d, v47, v54);
+                            }
+                            else
+                            {
+                              v54 = (Texture *)(v53 != 0 ? (int)v55 : 0);
+                              pRenderer->DrawTextureTransparent(a2d, v47, v54);
+                            }
+                          }
+                          if ( !bRingsShownInCharScreen )
+                            pRenderer->_4A612A(a2d, a3d, v54, v232);
+LABEL_127:
+                          v56 = v217->pEquipment.field_20;
+                          if ( !v56 )
+                            goto LABEL_155;
+                          v233 = v217->pEquipment.field_20;
+                          v57 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v56 + 5];
+                          v221 = v57;
+                          v58 = *(int *)v57;
+                          if ( *(int *)v57 == 529 )
+                          {
+                            a3e = paperdoll_4E4C2C + paredoll_array_4E54B8[v239][1];
+                            a2e = papredoll_4E4C28 + paredoll_array_4E54B8[v239][0];
+                            v59 = papredoll_flying_feet[v244];
+                          }
+                          else
+                          {
+                            if ( v58 == 512 )
+                            {
+                              a3e = paperdoll_4E4C2C + paredoll_array_4E54B8[v239][3];
+                              a2e = papredoll_4E4C28 + paredoll_array_4E54B8[v239][2];
+                              v59 = dword_511638[v239][5];
+                            }
+                            else
+                            {
+                              v60 = v58 - 115;
+                              if ( v60 < 0 || v60 >= 5 )
+                              {
+                                a2e = 0;
+                                a3e = 0;
+                                v59 = dword_511638[v239][0];
+                              }
+                              else
+                              {
+                                v61 = v60 + 7 * v239;
+                                a3e = paperdoll_4E4C2C + dword_4E5490[0][v61][1];
+                                a2e = papredoll_4E4C28 + dword_4E5490[0][v61][0];
+                                v59 = dword_511638[0][v60 + 6 * v239];
+                              }
+                            }
+                          }
+                          v62 = *(int *)(v57 + 20);
+                          if ( !(*(int *)(v57 + 20) & 0xF0) )
+                          {
+                            v65 = v59 + 1;
+                            v66 = (char *)&pIcons_LOD->pTextures[v59];
+                            if ( v62 & 2 )
+                            {
+                              v67 = (Texture *)(v65 != 0 ? (int)v66 : 0);
+                              pRenderer->_4A6776(a2e, a3e, v67);
+                            }
+                            else
+                            {
+                              if ( v62 & 1 )
+                              {
+                                v67 = (Texture *)(v65 != 0 ? (int)v66 : 0);
+                                pRenderer->DrawTextureTransparent(a2e, a3e, v67);
+                              }
+                              else
+                              {
+                                v67 = (Texture *)(v65 != 0 ? (int)v66 : 0);
+                                pRenderer->DrawTransparentGreenShade(a2e, a3e, v67);
+                              }
+                            }
+                            if ( !bRingsShownInCharScreen )
+                              pRenderer->_4A612A(a2e, a3e, v67, v233);
+LABEL_155:
+                            v68 = v217;
+                            v69 = v217->pEquipment.uMainHand;
+                            uPlayerID_a = 2 * v239;
+                            if ( !v69
+                              || (v70 = *(int *)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v69 + 5],
+                                  pItemsTable->pItems[v70].uEquipType != 1)
+                              && (pItemsTable->pItems[v70].uSkillType != 4 || v217->pEquipment.uOffHand) )
+                              pRenderer->DrawTextureTransparent(
+                                papredoll_4E4C28 + dword_4E5AE0[2 * v239],
+                                paperdoll_4E4C2C + dword_4E5AE0[2 * v239 + 1],
+                                (Texture *)(*(unsigned int *)((char *)papredoll_dlads + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_dlads + v240)] : 0));
+                            v71 = v217->pEquipment.uBelt;
+                            if ( v71 )
+                            {
+                              v234 = v217->pEquipment.uBelt;
+                              v72 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v71 + 5];
+                              v222 = v72;
+                              if ( *(int *)v72 == 524 )
+                              {
+                                v73 = 5;
+                              }
+                              else
+                              {
+                                if ( *(int *)v72 == 535 )
+                                {
+                                  v73 = 6;
+                                  goto LABEL_168;
+                                }
+                                v73 = *(int *)v72 - 100;
+                              }
+                              if ( v73 >= 0 && v73 < 7 )
+                              {
+LABEL_168:
+                                v74 = 7 * v239 + v73;
+                                a2f = papredoll_4E4C28 + dword_4E57F0[0][v74][0];
+                                a3f = paperdoll_4E4C2C + dword_4E57F0[0][v74][1];
+                                if ( v248 != 1 || v73 == 5 )
+                                  v75 = stru_511718.texids[v74];
+                                else
+                                  v75 = stru_511718.texids[v73 + 7 * (v239 - 2)];
+                                v76 = *(int *)&v217->field_1F5[36 * v71 + 15];
+                                if ( !(*(int *)&v217->field_1F5[36 * v71 + 15] & 0xF0) )
+                                {
+                                  v79 = v75 + 1;
+                                  v80 = (char *)&pIcons_LOD->pTextures[v75];
+                                  if ( v76 & 2 )
+                                  {
+                                    v81 = (Texture *)(v79 != 0 ? (int)v80 : 0);
+                                    pRenderer->_4A6776(a2f, a3f, v81);
+                                  }
+                                  else
+                                  {
+                                    if ( v76 & 1 )
+                                    {
+                                      v81 = (Texture *)(v79 != 0 ? (int)v80 : 0);
+                                      pRenderer->DrawTextureTransparent(a2f, a3f, v81);
+                                    }
+                                    else
+                                    {
+                                      v81 = (Texture *)(v79 != 0 ? (int)v80 : 0);
+                                      pRenderer->DrawTransparentGreenShade(a2f, a3f, v81);
+                                    }
+                                  }
+                                  if ( !bRingsShownInCharScreen )
+                                    pRenderer->_4A612A(a2f, a3f, v81, v234);
+                                  goto LABEL_191;
+                                }
+                                if ( (*(int *)&v217->field_1F5[36 * v71 + 15] & 0xF0) != 16 )
+                                {
+                                  if ( (*(int *)&v217->field_1F5[36 * v71 + 15] & 0xF0) == 32 )
+                                  {
+                                    v172 = "sp28a";
+                                    goto LABEL_181;
+                                  }
+                                  if ( (*(int *)&v217->field_1F5[36 * v71 + 15] & 0xF0) == 64 )
+                                  {
+                                    v172 = "sp30a";
+                                    goto LABEL_181;
+                                  }
+                                  if ( (*(int *)&v217->field_1F5[36 * v71 + 15] & 0xF0) == 128 )
+                                  {
+                                    v172 = "sp91a";
+LABEL_181:
+                                    v77 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v172, TEXTURE_16BIT_PALETTE)];
+                                    dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                                    if ( dword_50C9A8 <= 0 )
+                                    {
+                                      dword_50C9A8 = 0;
+                                      *(char *)(v222 + 20) &= 0xFu;
+                                      ptr_50C9A4 = 0;
+                                    }
+                                    v78 = (double)GetTickCount() * 0.1;
+                                    pRenderer->_4A63E6(
+                                      a2f,
+                                      a3f,
+                                      (Texture *)(v75 != -1 ? (int)&pIcons_LOD->pTextures[v75] : 0),
+                                      v77,
+                                      (signed __int64)v78,
+                                      0,
+                                      255);
+LABEL_191:
+                                    v68 = v217;
+                                    goto LABEL_192;
+                                  }
+                                }
+                                v172 = "sptext01";
+                                goto LABEL_181;
+                              }
+                            }
+LABEL_192:
+                            v82 = v68->pEquipment.uMainHand;
+                            if ( v82 )
+                            {
+                              v83 = *(int *)&v68->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v82 + 5];
+                              if ( pItemsTable->pItems[v83].uEquipType == 1
+                                || pItemsTable->pItems[v83].uSkillType == 4 && !v68->pEquipment.uOffHand )
+                                pRenderer->DrawTextureTransparent(
+                                  papredoll_4E4C28 + pPaperdollLeftHand[uPlayerID_a],
+                                  paperdoll_4E4C2C + pPaperdollLeftHand[uPlayerID_a + 1],
+                                  (Texture *)(*(unsigned int *)((char *)papredoll_dlaus + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_dlaus + v240)] : 0));
+                            }
+                            v84 = v68->pEquipment.uBody;
+                            v235 = v84;
+                            v85 = (int)((char *)v68 + 36 * v84);
+                            v242 = v85;
+                            v86 = *(int *)(v85 + 496);
+                            v87 = *(int *)(v85 + 496) - 504;
+                            if ( v87 )
+                            {
+                              v88 = v87 - 1;
+                              if ( v88 )
+                              {
+                                v89 = v88 - 11;
+                                if ( v89 )
+                                {
+                                  if ( v89 != 17 )
+                                  {
+                                    v90 = v86 - 66;
+LABEL_207:
+                                    if ( v90 < 0 || v90 > 17 )
+                                    {
+LABEL_259:
+                                      v111 = v68->pEquipment.uCloak;
+                                      if ( !v111 )
+                                        goto LABEL_293;
+                                      v236 = v68->pEquipment.uCloak;
+                                      v112 = (int)&v68->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v111 + 5];
+                                      v225 = v112;
+                                      v113 = *(int *)v112;
+                                      if ( v113 != 525 )
+                                      {
+                                        switch ( v113 )
+                                        {
+                                          case 530:
+                                            v191 = 6;
+                                            break;
+                                          case 547:
+                                            v191 = 7;
+                                            break;
+                                          case 548:
+                                            v191 = 8;
+                                            break;
+                                          default:
+                                            if ( v113 != 550 )
+                                            {
+                                              v114 = v113 - 105;
+LABEL_272:
+                                              if ( v114 < 0 || v114 >= 10 )
+                                                goto LABEL_293;
+LABEL_274:
+                                              v115 = v114 + 10 * v239;
+                                              v116 = dword_511788[v115];
+                                              v115 *= 8;
+                                              v117 = papredoll_4E4C28 + *(int *)((char *)&dword_4E56B0 + v115);
+                                              a2h = papredoll_4E4C28 + *(int *)((char *)&dword_4E56B0 + v115);
+                                              a3h = paperdoll_4E4C2C + *(int *)((char *)&dword_4E56B4 + v115);
+                                              if ( v116 == pIcons_LOD->FindTextureByName("pending") )
+                                              {
+LABEL_292:
+                                                v68 = v217;
+LABEL_293:
+                                                if ( v244 == 12 || v244 == 13 )
+                                                {
+                                                  v122 = papredoll_dbrds[v244];
+                                                  if ( v122 != pIcons_LOD->FindTextureByName("Pending") )
+                                                    pRenderer->DrawTextureTransparent(
+                                                      papredoll_4E4C28 + dword_4E5AD0[2 * v244 - 24],
+                                                      paperdoll_4E4C2C + dword_4E5AD4[2 * v244 - 24],
+                                                      (Texture *)(v122 != -1 ? (int)&pIcons_LOD->pTextures[v122] : 0));
+                                                }
+                                                v123 = v68->pEquipment.uHelm;
+                                                if ( !v123 )
+                                                  goto LABEL_335;
+                                                v237 = v123;
+                                                v124 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v123 + 5];
+                                                v226 = v124;
+                                                if ( *(int *)v124 != 521 )
+                                                {
+                                                  switch ( *(int *)v124 )
+                                                  {
+                                                    case 0x20A:
+                                                      v192 = 12;
+                                                      break;
+                                                    case 0x20B:
+                                                      v192 = 13;
+                                                      break;
+                                                    case 0x214:
+                                                      v192 = 14;
+                                                      break;
+                                                    default:
+                                                      if ( *(int *)v124 != 544 )
+                                                      {
+                                                        v125 = *(int *)v124 - 89;
+LABEL_310:
+                                                        if ( v125 < 0 || v125 >= 16 )
+                                                          goto LABEL_335;
+                                                        goto LABEL_312;
+                                                      }
+                                                      v192 = 15;
+                                                      break;
+                                                  }
+                                                  v125 = v192;
+LABEL_312:
+                                                  v126 = 2 * (v125 + 16 * v239);
+                                                  a2j = papredoll_4E4C28 + dword_4E58D0[v126];
+                                                  a3i = paperdoll_4E4C2C + dword_4E58D4[v126];
+                                                  if ( v248 != 1 || *(int *)v124 != 92 )
+                                                    v127 = stru_511698.texids[v125 + 16 * v250];
+                                                  else
+                                                    v127 = papredoll_dbrds[11];
+                                                  v128 = *(int *)(v124 + 20);
+                                                  if ( *(int *)(v124 + 20) & 0xF0 )
+                                                  {
+                                                    if ( (*(int *)(v124 + 20) & 0xF0) != 16 )
+                                                    {
+                                                      if ( (*(int *)(v124 + 20) & 0xF0) == 32 )
+                                                      {
+                                                        v180 = "sp28a";
+                                                        goto LABEL_325;
+                                                      }
+                                                      if ( (*(int *)(v124 + 20) & 0xF0) == 64 )
+                                                      {
+                                                        v180 = "sp30a";
+                                                        goto LABEL_325;
+                                                      }
+                                                      if ( (*(int *)(v124 + 20) & 0xF0) == 128 )
+                                                      {
+                                                        v180 = "sp91a";
+LABEL_325:
+                                                        v129 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v180, TEXTURE_16BIT_PALETTE)];
+                                                        dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                                                        if ( dword_50C9A8 <= 0 )
+                                                        {
+                                                          dword_50C9A8 = 0;
+                                                          *(char *)(v226 + 20) &= 0xFu;
+                                                          ptr_50C9A4 = 0;
+                                                        }
+                                                        v130 = (double)GetTickCount() * 0.1;
+                                                        pRenderer->_4A63E6(
+                                                          a2j,
+                                                          a3i,
+                                                          (Texture *)(v127 != -1 ? (int)&pIcons_LOD->pTextures[v127] : 0),
+                                                          v129,
+                                                          (signed __int64)v130,
+                                                          0,
+                                                          255);
+                                                        goto LABEL_335;
+                                                      }
+                                                    }
+                                                    v180 = "sptext01";
+                                                    goto LABEL_325;
+                                                  }
+                                                  v131 = v127 + 1;
+                                                  v132 = (char *)&pIcons_LOD->pTextures[v127];
+                                                  if ( v128 & 2 )
+                                                  {
+                                                    v133 = (Texture *)(v131 != 0 ? (int)v132 : 0);
+                                                    pRenderer->_4A6776(a2j, a3i, v133);
+                                                  }
+                                                  else
+                                                  {
+                                                    if ( v128 & 1 )
+                                                    {
+                                                      v133 = (Texture *)(v131 != 0 ? (int)v132 : 0);
+                                                      pRenderer->DrawTextureTransparent(a2j, a3i, v133);
+                                                    }
+                                                    else
+                                                    {
+                                                      v133 = (Texture *)(v131 != 0 ? (int)v132 : 0);
+                                                      pRenderer->DrawTransparentGreenShade(a2j, a3i, v133);
+                                                    }
+                                                  }
+                                                  if ( !bRingsShownInCharScreen )
+                                                    pRenderer->_4A612A(a2j, a3i, v133, v237);
+LABEL_335:
+                                                  v134 = v217->pEquipment.uMainHand;
+                                                  if ( !v134 )
+                                                    goto LABEL_358;
+                                                  v238 = v217->pEquipment.uMainHand;
+                                                  v135 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v134 + 5];
+                                                  v227 = v135;
+                                                  v136 = *(int *)v135;
+                                                  v137 = *(int *)v135;
+                                                  a2k = papredoll_4E4C28
+                                                      + array_4E4C30[v239].field_8
+                                                      - pItemsTable->pItems[v137].uEquipX;
+                                                  a3j = paperdoll_4E4C2C
+                                                      + array_4E4C30[v239].field_C
+                                                      - pItemsTable->pItems[v137].uEquipY;
+                                                  if ( v136 == 64 )
+                                                    v181 = "item64v1";
+                                                  else
+                                                    v181 = pItemsTable->pItems[v137].pIconName;
+                                                  v138 = pIcons_LOD->LoadTexture(v181, TEXTURE_16BIT_PALETTE);
+                                                  v139 = *(int *)(v227 + 20);
+                                                  if ( !(*(int *)(v227 + 20) & 0xF0) )
+                                                  {
+                                                    v142 = v138 + 1;
+                                                    v143 = (char *)&pIcons_LOD->pTextures[v138];
+                                                    if ( v139 & 2 )
+                                                    {
+                                                      v144 = (Texture *)(v142 != 0 ? (int)v143 : 0);
+                                                      pRenderer->_4A6776(a2k, a3j, v144);
+                                                    }
+                                                    else
+                                                    {
+                                                      if ( v139 & 1 )
+                                                      {
+                                                        v144 = (Texture *)(v142 != 0 ? (int)v143 : 0);
+                                                        pRenderer->DrawTextureTransparent(a2k, a3j, v144);
+                                                      }
+                                                      else
+                                                      {
+                                                        v144 = (Texture *)(v142 != 0 ? (int)v143 : 0);
+                                                        pRenderer->DrawTransparentGreenShade(a2k, a3j, v144);
+                                                      }
+                                                    }
+                                                    if ( !bRingsShownInCharScreen )
+                                                      pRenderer->_4A612A(a2k, a3j, v144, v238);
+LABEL_358:
+                                                    v145 = v217->pEquipment.uOffHand;
+                                                    v249 = v217->pEquipment.uOffHand;
+                                                    if ( !v145 )
+                                                      goto LABEL_393;
+                                                    v146 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v145 + 5];
+                                                    v228 = v146;
+                                                    v147 = *(int *)v146;
+                                                    v148 = *(int *)v146;
+                                                    v149 = pItemsTable->pItems[v148].uSkillType;
+                                                    if ( v149 != 2 && v149 != 1 )
+                                                    {
+                                                      v245 = 0;
+LABEL_362:
+                                                      v150 = papredoll_4E4C28
+                                                           + array_4E4C30[v239].field_0
+                                                           - pItemsTable->pItems[v148].uEquipX;
+                                                      a3k = paperdoll_4E4C2C
+                                                          + LODWORD(array_4E4C30[v239].field_4)
+                                                          - pItemsTable->pItems[v148].uEquipY;
+                                                      goto LABEL_370;
+                                                    }
+                                                    v151 = v147 - 400;
+                                                    v245 = 1;
+                                                    if ( v151 )
+                                                    {
+                                                      v152 = v151 - 3;
+                                                      if ( v152 )
+                                                      {
+                                                        if ( v152 != 12 )
+                                                          goto LABEL_362;
+                                                        v150 = 595;
+                                                        a3k = 33;
+LABEL_370:
+                                                        v153 = pIcons_LOD->LoadTexture(pItemsTable->pItems[v148].pIconName, TEXTURE_16BIT_PALETTE);
+                                                        v154 = v153;
+                                                        v243 = v153;
+                                                        v155 = *(int *)(v228 + 20);
+                                                        if ( !(*(int *)(v228 + 20) & 0xF0) )
+                                                        {
+                                                          if ( v155 & 2 )
+                                                          {
+                                                            v159 = (Texture *)(v243 != -1 ? (int)&pIcons_LOD->pTextures[v243] : 0);
+                                                            pRenderer->_4A6776(v150, a3k, v159);
+                                                          }
+                                                          else
+                                                          {
+                                                            v29 = (v155 & 1) == 0;
+                                                            v160 = (char *)&pIcons_LOD->pTextures[v243];
+                                                            if ( v29 )
+                                                            {
+                                                              v159 = (Texture *)(v243 != -1 ? (int)v160 : 0);
+                                                              pRenderer->DrawTransparentGreenShade(
+                                                                v150,
+                                                                a3k,
+                                                                (Texture *)(v243 != -1 ? (int)v160 : 0));
+                                                            }
+                                                            else
+                                                            {
+                                                              v159 = (Texture *)(v243 != -1 ? (int)v160 : 0);
+                                                              pRenderer->DrawTextureTransparent(
+                                                                v150,
+                                                                a3k,
+                                                                (Texture *)(v243 != -1 ? (int)v160 : 0));
+                                                            }
+                                                          }
+                                                          if ( !bRingsShownInCharScreen )
+                                                            pRenderer->_4A612A(v150, a3k, v159, v249);
+                                                          goto LABEL_391;
+                                                        }
+                                                        if ( (*(int *)(v228 + 20) & 0xF0) != 16 )
+                                                        {
+                                                          if ( (*(int *)(v228 + 20) & 0xF0) == 32 )
+                                                          {
+                                                            v183 = "sp28a";
+                                                          }
+                                                          else
+                                                          {
+                                                            if ( (*(int *)(v228 + 20) & 0xF0) != 64 )
+                                                            {
+                                                              v156 = pIcons_LOD;
+                                                              if ( (*(int *)(v228 + 20) & 0xF0) == 128 )
+                                                              {
+                                                                v183 = "sp91a";
+LABEL_381:
+                                                                v157 = &pIcons_LOD->pTextures[v156->LoadTexture(
+                                                                                               v183,
+                                                                                               TEXTURE_16BIT_PALETTE)];
+                                                                dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                                                                if ( dword_50C9A8 <= 0 )
+                                                                {
+                                                                  dword_50C9A8 = 0;
+                                                                  *(char *)(v228 + 20) &= 0xFu;
+                                                                  ptr_50C9A4 = 0;
+                                                                }
+                                                                v158 = (double)GetTickCount() * 0.1;
+                                                                pRenderer->_4A63E6(
+                                                                  v150,
+                                                                  a3k,
+                                                                  (Texture *)(v154 != -1 ? (int)&pIcons_LOD->pTextures[v154] : 0),
+                                                                  v157,
+                                                                  (signed __int64)v158,
+                                                                  0,
+                                                                  255);
+LABEL_391:
+                                                                if ( v245 )
+                                                                  pRenderer->DrawTextureTransparent(
+                                                                    papredoll_4E4C28
+                                                                  + pPaperdollLeftEmptyHand[uPlayerID_a],
+                                                                    paperdoll_4E4C2C
+                                                                  + pPaperdollLeftEmptyHand[uPlayerID_a + 1],
+                                                                    (Texture *)(*(unsigned int *)((char *)papredoll_dlhs
+                                                                                                + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_dlhs + v240)] : 0));
+                                                                goto LABEL_393;
+                                                              }
+LABEL_380:
+                                                              v183 = "sptext01";
+                                                              goto LABEL_381;
+                                                            }
+                                                            v183 = "sp30a";
+                                                          }
+                                                          v156 = pIcons_LOD;
+                                                          goto LABEL_381;
+                                                        }
+                                                        v156 = pIcons_LOD;
+                                                        goto LABEL_380;
+                                                      }
+                                                      a3k = 28;
+                                                    }
+                                                    else
+                                                    {
+                                                      a3k = 86;
+                                                    }
+                                                    v150 = 596;
+                                                    goto LABEL_370;
+                                                  }
+                                                  if ( (*(int *)(v227 + 20) & 0xF0) != 16 )
+                                                  {
+                                                    if ( (*(int *)(v227 + 20) & 0xF0) == 32 )
+                                                    {
+                                                      v182 = "sp28a";
+                                                      goto LABEL_348;
+                                                    }
+                                                    if ( (*(int *)(v227 + 20) & 0xF0) == 64 )
+                                                    {
+                                                      v182 = "sp30a";
+                                                      goto LABEL_348;
+                                                    }
+                                                    if ( (*(int *)(v227 + 20) & 0xF0) == 128 )
+                                                    {
+                                                      v182 = "sp91a";
+LABEL_348:
+                                                      v140 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v182, TEXTURE_16BIT_PALETTE)];
+                                                      dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                                                      if ( dword_50C9A8 <= 0 )
+                                                      {
+                                                        dword_50C9A8 = 0;
+                                                        *(char *)(v227 + 20) &= 0xFu;
+                                                        ptr_50C9A4 = 0;
+                                                      }
+                                                      v141 = (double)GetTickCount() * 0.1;
+                                                      pRenderer->_4A63E6(
+                                                        a2k,
+                                                        a3j,
+                                                        (Texture *)(v138 != -1 ? (int)&pIcons_LOD->pTextures[v138] : 0),
+                                                        v140,
+                                                        (signed __int64)v141,
+                                                        0,
+                                                        255);
+                                                      goto LABEL_358;
+                                                    }
+                                                  }
+                                                  v182 = "sptext01";
+                                                  goto LABEL_348;
+                                                }
+                                                v125 = 11;
+                                                goto LABEL_310;
+                                              }
+                                              if ( !(*(int *)(v225 + 20) & 0xF0) )
+                                              {
+                                                v119 = v116 + 1;
+                                                v120 = (char *)&pIcons_LOD->pTextures[v116];
+                                                if ( *(int *)(v225 + 20) & 2 )
+                                                {
+                                                  v121 = (Texture *)(v119 != 0 ? (int)v120 : 0);
+                                                  pRenderer->_4A6776(a2h, a3h, v121);
+                                                }
+                                                else
+                                                {
+                                                  v121 = (Texture *)(v119 != 0 ? (int)v120 : 0);
+                                                  pRenderer->DrawTextureTransparent(a2h, a3h, v121);
+                                                }
+                                                if ( !bRingsShownInCharScreen )
+                                                  pRenderer->_4A612A(a2h, a3h, v121, v236);
+                                                goto LABEL_292;
+                                              }
+                                              if ( (*(int *)(v225 + 20) & 0xF0) != 16 )
+                                              {
+                                                if ( (*(int *)(v225 + 20) & 0xF0) == 32 )
+                                                {
+                                                  v179 = "sp28a";
+                                                  goto LABEL_284;
+                                                }
+                                                if ( (*(int *)(v225 + 20) & 0xF0) == 64 )
+                                                {
+                                                  v179 = "sp30a";
+                                                  goto LABEL_284;
+                                                }
+                                                if ( (*(int *)(v225 + 20) & 0xF0) == 128 )
+                                                {
+                                                  v179 = "sp91a";
+LABEL_284:
+                                                  a2i = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v179, TEXTURE_16BIT_PALETTE)];
+                                                  dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                                                  if ( dword_50C9A8 <= 0 )
+                                                  {
+                                                    dword_50C9A8 = 0;
+                                                    *(char *)(v225 + 20) &= 0xFu;
+                                                    ptr_50C9A4 = 0;
+                                                  }
+                                                  v118 = (double)GetTickCount() * 0.1;
+                                                  pRenderer->_4A63E6(
+                                                    v117,
+                                                    a3h,
+                                                    (Texture *)(v116 != -1 ? (int)&pIcons_LOD->pTextures[v116] : 0),
+                                                    a2i,
+                                                    (signed __int64)v118,
+                                                    0,
+                                                    255);
+                                                  goto LABEL_292;
+                                                }
+                                              }
+                                              v179 = "sptext01";
+                                              goto LABEL_284;
+                                            }
+                                            v191 = 9;
+                                            break;
+                                        }
+                                        v114 = v191;
+                                        goto LABEL_274;
+                                      }
+                                      v114 = 5;
+                                      goto LABEL_272;
+                                    }
+LABEL_209:
+                                    if ( v68->pEquipment.uMainHand
+                                      && (v68->GetEquippedItemEquipType(1u) == 1
+                                       || v68->GetEquippedItemSkillType(EQUIP_TWO_HANDED) == 4
+                                       && !v68->pEquipment.uOffHand) )
+                                    {
+                                      v91 = 17 * v239 + v90;
+                                      v92 = v91;
+                                      v223 = paperdoll_array_511290[0][v91][2];
+                                      if ( v223 == pIcons_LOD->FindTextureByName("pending") )
+                                      {
+                                        v93 = 2 * v91;
+                                        v94 = paperdoll_array_511290[0][v92][1];
+                                        a2g = papredoll_4E4C28 + dword_4E5050[v93];
+                                        v95 = dword_4E5050[v93 + 1];
+                                      }
+                                      else
+                                      {
+                                        v94 = v223;
+                                        a2g = papredoll_4E4C28 + dword_4E5270[2 * v91];
+                                        v95 = dword_4E5270[2 * v91 + 1];
+                                      }
+                                      a3g = paperdoll_4E4C2C + v95;
+                                      if ( v94 == pIcons_LOD->FindTextureByName("pending") )
+                                        goto LABEL_258;
+                                      if ( *(int *)(v242 + 516) & 0xF0 )
+                                      {
+                                        if ( (*(int *)(v242 + 516) & 0xF0) != 16 )
+                                        {
+                                          if ( (*(int *)(v242 + 516) & 0xF0) == 32 )
+                                          {
+                                            v173 = "sp28a";
+                                            goto LABEL_226;
+                                          }
+                                          if ( (*(int *)(v242 + 516) & 0xF0) == 64 )
+                                          {
+                                            v173 = "sp30a";
+                                            goto LABEL_226;
+                                          }
+                                          if ( (*(int *)(v242 + 516) & 0xF0) == 128 )
+                                          {
+                                            v173 = "sp91a";
+LABEL_226:
+                                            v96 = (char *)&pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v173, TEXTURE_16BIT_PALETTE)];
+                                            dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                                            if ( dword_50C9A8 <= 0 )
+                                            {
+                                              dword_50C9A8 = 0;
+                                              *(char *)(v242 + 516) &= 0xFu;
+                                              ptr_50C9A4 = 0;
+                                            }
+                                            v187 = 255;
+                                            v174 = 0;
+                                            v97 = (double)GetTickCount();
+LABEL_249:
+                                            pRenderer->_4A63E6(
+                                              a2g,
+                                              a3g,
+                                              (Texture *)(v94 != -1 ? (int)&pIcons_LOD->pTextures[v94] : 0),
+                                              (Texture *)v96,
+                                              (signed __int64)(v97 * 0.1),
+                                              v174,
+                                              v187);
+                                            goto LABEL_258;
+                                          }
+                                        }
+                                        v173 = "sptext01";
+                                        goto LABEL_226;
+                                      }
+                                      v98 = v94 + 1;
+                                      v99 = (char *)&pIcons_LOD->pTextures[v94];
+                                      v100 = pRenderer;
+                                      if ( *(int *)(v242 + 516) & 2 )
+                                      {
+                                        v101 = (Texture *)(v98 != 0 ? (int)v99 : 0);
+                                        v188 = v101;
+                                        v175 = a3g;
+                                        v163 = a2g;
+LABEL_231:
+                                        v100->_4A6776(v163, v175, v188);
+                                        goto LABEL_256;
+                                      }
+                                      if ( *(char *)(v242 + 516) & 1 )
+                                      {
+                                        v101 = (Texture *)(v98 != 0 ? (int)v99 : 0);
+                                        v189 = v101;
+                                        v176 = a3g;
+                                        v164 = a2g;
+LABEL_234:
+                                        pRenderer->DrawTextureTransparent(v164, v176, v189);
+                                        goto LABEL_256;
+                                      }
+                                      v101 = (Texture *)(v98 != 0 ? (int)v99 : 0);
+                                      v190 = v101;
+                                      v177 = a3g;
+                                      v165 = a2g;
+                                      goto LABEL_255;
+                                    }
+                                    v102 = 17 * v239 + v90;
+                                    v94 = paperdoll_array_511290[0][v102][1];
+                                    if ( v94 == pIcons_LOD->FindTextureByName("pending") )
+                                    {
+LABEL_258:
+                                      v68 = v217;
+                                      goto LABEL_259;
+                                    }
+                                    v103 = papredoll_4E4C28 + dword_4E5050[2 * v102];
+                                    v104 = paperdoll_4E4C2C + dword_4E5050[2 * v102 + 1];
+                                    v224 = *(int *)(v242 + 516);
+                                    v105 = *(int *)(v242 + 516) & 0xF0;
+                                    a2g = papredoll_4E4C28 + dword_4E5050[2 * v102];
+                                    a3g = paperdoll_4E4C2C + dword_4E5050[2 * v102 + 1];
+                                    if ( !v105 )
+                                    {
+                                      v109 = v94 + 1;
+                                      v110 = (char *)&pIcons_LOD->pTextures[v94];
+                                      if ( v224 & 2 )
+                                      {
+                                        v101 = (Texture *)(v109 != 0 ? (int)v110 : 0);
+                                        v188 = v101;
+                                        v175 = v104;
+                                        v163 = v103;
+                                        v100 = pRenderer;
+                                        goto LABEL_231;
+                                      }
+                                      if ( v224 & 1 )
+                                      {
+                                        v101 = (Texture *)(v109 != 0 ? (int)v110 : 0);
+                                        v189 = v101;
+                                        v176 = v104;
+                                        v164 = v103;
+                                        v100 = pRenderer;
+                                        goto LABEL_234;
+                                      }
+                                      v101 = (Texture *)(v109 != 0 ? (int)v110 : 0);
+                                      v190 = v101;
+                                      v177 = v104;
+                                      v165 = v103;
+                                      v100 = pRenderer;
+LABEL_255:
+                                      pRenderer->DrawTransparentGreenShade(v165, v177, v190);
+LABEL_256:
+                                      if ( !bRingsShownInCharScreen )
+                                        pRenderer->_4A612A(a2g, a3g, v101, v235);
+                                      goto LABEL_258;
+                                    }
+                                    v106 = v105 - 16;
+                                    if ( v106 )
+                                    {
+                                      v107 = v106 - 16;
+                                      if ( !v107 )
+                                      {
+                                        v178 = "sp28a";
+                                        goto LABEL_246;
+                                      }
+                                      v108 = v107 - 32;
+                                      if ( !v108 )
+                                      {
+                                        v178 = "sp30a";
+                                        goto LABEL_246;
+                                      }
+                                      if ( v108 == 64 )
+                                      {
+                                        v178 = "sp91a";
+LABEL_246:
+                                        v96 = (char *)&pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v178, TEXTURE_16BIT_PALETTE)];
+                                        dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                                        if ( dword_50C9A8 <= 0 )
+                                        {
+                                          dword_50C9A8 = 0;
+                                          *(char *)(v242 + 516) &= 0xFu;
+                                          ptr_50C9A4 = 0;
+                                        }
+                                        v187 = 255;
+                                        v174 = 0;
+                                        v97 = (double)GetTickCount();
+                                        goto LABEL_249;
+                                      }
+                                    }
+                                    v178 = "sptext01";
+                                    goto LABEL_246;
+                                  }
+                                  v186 = 16;
+                                }
+                                else
+                                {
+                                  v186 = 13;
+                                }
+                              }
+                              else
+                              {
+                                v186 = 14;
+                              }
+                              v90 = v186;
+                              goto LABEL_209;
+                            }
+                            v90 = 15;
+                            goto LABEL_207;
+                          }
+                          if ( (*(int *)(v57 + 20) & 0xF0) != 16 )
+                          {
+                            if ( (*(int *)(v57 + 20) & 0xF0) == 32 )
+                            {
+                              v171 = "sp28a";
+                              goto LABEL_145;
+                            }
+                            if ( (*(int *)(v57 + 20) & 0xF0) == 64 )
+                            {
+                              v171 = "sp30a";
+                              goto LABEL_145;
+                            }
+                            if ( (*(int *)(v57 + 20) & 0xF0) == 128 )
+                            {
+                              v171 = "sp91a";
+LABEL_145:
+                              v63 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v171, TEXTURE_16BIT_PALETTE)];
+                              dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                              if ( dword_50C9A8 <= 0 )
+                              {
+                                dword_50C9A8 = 0;
+                                *(char *)(v221 + 20) &= 0xFu;
+                                ptr_50C9A4 = 0;
+                              }
+                              v64 = (double)GetTickCount() * 0.1;
+                              pRenderer->_4A63E6(
+                                a2e,
+                                a3e,
+                                (Texture *)(v59 != -1 ? (int)&pIcons_LOD->pTextures[v59] : 0),
+                                v63,
+                                (signed __int64)v64,
+                                0,
+                                255);
+                              goto LABEL_155;
+                            }
+                          }
+                          v171 = "sptext01";
+                          goto LABEL_145;
+                        }
+                        if ( (*(int *)(v44 + 20) & 0xF0) != 16 )
+                        {
+                          if ( (*(int *)(v44 + 20) & 0xF0) == 32 )
+                          {
+                            v170 = "sp28a";
+                          }
+                          else
+                          {
+                            if ( (*(int *)(v44 + 20) & 0xF0) != 64 )
+                            {
+                              v50 = pIcons_LOD;
+                              if ( (*(int *)(v44 + 20) & 0xF0) == 128 )
+                              {
+                                v170 = "sp91a";
+LABEL_117:
+                                v51 = &pIcons_LOD->pTextures[v50->LoadTexture(v170, TEXTURE_16BIT_PALETTE)];
+                                dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                                if ( dword_50C9A8 <= 0 )
+                                {
+                                  dword_50C9A8 = 0;
+                                  *(char *)(v220 + 20) &= 0xFu;
+                                  ptr_50C9A4 = 0;
+                                }
+                                v52 = (double)GetTickCount() * 0.1;
+                                pRenderer->_4A63E6(
+                                  a2d,
+                                  a3d,
+                                  (Texture *)(v48 != -1 ? (int)&pIcons_LOD->pTextures[v48] : 0),
+                                  v51,
+                                  (signed __int64)v52,
+                                  0,
+                                  255);
+                                goto LABEL_127;
+                              }
+LABEL_116:
+                              v170 = "sptext01";
+                              goto LABEL_117;
+                            }
+                            v170 = "sp30a";
+                          }
+                          v50 = pIcons_LOD;
+                          goto LABEL_117;
+                        }
+                        v50 = pIcons_LOD;
+                        goto LABEL_116;
+                      }
+                      v185 = 16;
+                    }
+                  }
+                  v45 = v185;
+                  goto LABEL_106;
+                }
+                v45 = 15;
+                goto LABEL_104;
+              }
+              if ( (*(int *)(v32 + 20) & 0xF0) != 16 )
+              {
+                if ( (*(int *)(v32 + 20) & 0xF0) == 32 )
+                {
+                  v169 = "sp28a";
+                }
+                else
+                {
+                  if ( (*(int *)(v32 + 20) & 0xF0) != 64 )
+                  {
+                    v38 = pIcons_LOD;
+                    if ( (*(int *)(v32 + 20) & 0xF0) == 128 )
+                    {
+                      v169 = "sp91a";
+LABEL_85:
+                      v39 = &pIcons_LOD->pTextures[v38->LoadTexture(v169, TEXTURE_16BIT_PALETTE)];
+                      dword_50C9A8 -= pEventTimer->uTimeElapsed;
+                      if ( dword_50C9A8 <= 0 )
+                      {
+                        dword_50C9A8 = 0;
+                        *(char *)(v219 + 20) &= 0xFu;
+                        ptr_50C9A4 = 0;
+                      }
+                      v40 = (double)GetTickCount() * 0.1;
+                      pRenderer->_4A63E6(
+                        a2c,
+                        a3c,
+                        (Texture *)(v35 != -1 ? (int)&pIcons_LOD->pTextures[v35] : 0),
+                        v39,
+                        (signed __int64)v40,
+                        0,
+                        255);
+                      goto LABEL_93;
+                    }
+LABEL_84:
+                    v169 = "sptext01";
+                    goto LABEL_85;
+                  }
+                  v169 = "sp30a";
+                }
+                v38 = pIcons_LOD;
+                goto LABEL_85;
+              }
+              v38 = pIcons_LOD;
+              goto LABEL_84;
+            }
+            v184 = 9;
+            break;
+        }
+        v33 = v184;
+        goto LABEL_74;
+      }
+      v33 = 5;
+      goto LABEL_72;
+    }
+    if ( (*(int *)(v22 + 20) & 0xF0) != 16 )
+    {
+      if ( (*(int *)(v22 + 20) & 0xF0) == 32 )
+      {
+        v168 = "sp28a";
+      }
+      else
+      {
+        if ( (*(int *)(v22 + 20) & 0xF0) != 64 )
+        {
+          v26 = pIcons_LOD;
+          if ( (*(int *)(v22 + 20) & 0xF0) == 128 )
+          {
+            v168 = "sp91a";
+LABEL_49:
+            a2b = &pIcons_LOD->pTextures[v26->LoadTexture(v168, TEXTURE_16BIT_PALETTE)];
+            dword_50C9A8 -= pEventTimer->uTimeElapsed;
+            if ( dword_50C9A8 <= 0 )
+            {
+              dword_50C9A8 = 0;
+              *(char *)(v22 + 20) &= 0xFu;
+              ptr_50C9A4 = 0;
+            }
+            v27 = (Texture *)(v241 != -1 ? (int)&pIcons_LOD->pTextures[v241] : 0);
+            v28 = (double)GetTickCount() * 0.1;
+            pRenderer->_4A63E6(v24, a3b, v27, a2b, (signed __int64)v28, 0, 255);
+            goto LABEL_57;
+          }
+LABEL_48:
+          v168 = "sptext01";
+          goto LABEL_49;
+        }
+        v168 = "sp30a";
+      }
+      v26 = pIcons_LOD;
+      goto LABEL_49;
+    }
+    v26 = pIcons_LOD;
+    goto LABEL_48;
+  }
+  a3 = paperdoll_4E4C2C;
+  a2 = papredoll_4E4C28;
+  v240 = 4 * uPlayerID_ - 4;
+  pRenderer->DrawTextureTransparent(
+    papredoll_4E4C28,
+    paperdoll_4E4C2C,
+    (Texture *)(*(unsigned int *)((char *)papredoll_dbods + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_dbods + v240)] : 0));
+    //(Texture *)(*(unsigned int *)((char *)papredoll_dbods + v240) != -1 ? 72
+    //                                                                    * *(unsigned int *)((char *)papredoll_dbods
+    //                                                                                      + v240)
+    //                                                                    + 7145548 : 0));
+  if ( !bRingsShownInCharScreen )
+    pRenderer->_4A612A(
+      a2,
+      a3,
+      //(Texture *)(*(unsigned int *)((char *)papredoll_dbods + v240) != -1 ? 72
+      //                                                                    * *(unsigned int *)((char *)papredoll_dbods
+      //                                                                                      + v240)
+      //                                                                    + 7145548 : 0),
+      (Texture *)(*(unsigned int *)((char *)papredoll_dbods + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_dbods + v240)] : 0),
+      pPlayer->pEquipment.uBody);
+  uPlayerID_a = 2 * v5;
+  v6 = pPlayer->pEquipment.uMainHand;
+  if ( !v6
+    || (v7 = *(int *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6 + 5], pItemsTable->pItems[v7].uEquipType != 1)
+    && (pItemsTable->pItems[v7].uSkillType != 4 || pPlayer->pEquipment.uOffHand) )
+    pRenderer->DrawTextureTransparent(
+      papredoll_4E4C28 + dword_4E5AE0[2 * v5],
+      paperdoll_4E4C2C + dword_4E5AE0[2 * v5 + 1],
+      (Texture *)(*(unsigned int *)((char *)papredoll_dlads + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_dlads + v240)] : 0));
+      //(Texture *)(*(unsigned int *)((char *)papredoll_dlads + v240) != -1 ? 72
+      //                                                                    * *(unsigned int *)((char *)papredoll_dlads
+      //                                                                                      + v240)
+      //                                                                    + 7145548 : 0));
+  v8 = pPlayer->pEquipment.uMainHand;
+  if ( v8 )
+  {
+    v229 = pPlayer->pEquipment.uMainHand;
+    v9 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
+    v10 = v5 << 7;
+    v218 = v9;
+    v11 = *(int *)v9;
+    v12 = *(int *)v9;
+    v13 = papredoll_4E4C28 + array_4E4C30[v5].field_8 - pItemsTable->pItems[v12].uEquipX;
+    a2a = v13;
+    a3a = paperdoll_4E4C2C + *(int *)((char *)&array_4E4C30[0].field_C + v10) - pItemsTable->pItems[v12].uEquipY;
+    if ( v11 == 64 )
+      v166 = "item64v1";
+    else
+      v166 = pItemsTable->pItems[v12].pIconName;
+    v14 = pIcons_LOD->LoadTexture(v166, TEXTURE_16BIT_PALETTE);
+    v15 = *(int *)(v218 + 20);
+    if ( *(int *)(v218 + 20) & 0xF0 )
+    {
+      if ( (*(int *)(v218 + 20) & 0xF0) != 16 )
+      {
+        if ( (*(int *)(v218 + 20) & 0xF0) == 32 )
+        {
+          v167 = "sp28a";
+          goto LABEL_27;
+        }
+        if ( (*(int *)(v218 + 20) & 0xF0) == 64 )
+        {
+          v167 = "sp30a";
+          goto LABEL_27;
+        }
+        if ( (*(int *)(v218 + 20) & 0xF0) == 128 )
+        {
+          v167 = "sp91a";
+LABEL_27:
+          //v16 = (Texture *)(72 * pIcons_LOD->LoadTexture(v167, TEXTURE_16BIT_PALETTE) + 7145548);
+          v16 = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(v167, TEXTURE_16BIT_PALETTE)];
+
+          dword_50C9A8 -= pEventTimer->uTimeElapsed;
+          if ( dword_50C9A8 <= 0 )
+          {
+            dword_50C9A8 = 0;
+            *(char *)(v218 + 20) &= 0xFu;
+            ptr_50C9A4 = 0;
+          }
+          v17 = (double)GetTickCount() * 0.1;
+          pRenderer->_4A63E6(
+            v13,
+            a3a,
+            (Texture *)(v14 != -1 ? (int)&pIcons_LOD->pTextures[v14] : 0),
+            v16,
+            (signed __int64)v17,
+            0,
+            255);
+          goto LABEL_393;
+        }
+      }
+      v167 = "sptext01";
+      goto LABEL_27;
+    }
+    v18 = v14 + 1;
+    v19 = (char *)&pIcons_LOD->pTextures[v14];
+    if ( v15 & 2 )
+    {
+      v20 = (Texture *)(v18 != 0 ? (int)v19 : 0);
+      pRenderer->_4A6776(a2a, a3a, v20);
+    }
+    else
+    {
+      if ( v15 & 1 )
+      {
+        v20 = (Texture *)(v18 != 0 ? (int)v19 : 0);
+        pRenderer->DrawTextureTransparent(a2a, a3a, v20);
+      }
+      else
+      {
+        v20 = (Texture *)(v18 != 0 ? (int)v19 : 0);
+        pRenderer->DrawTransparentGreenShade(a2a, a3a, v20);
+      }
+    }
+    if ( !bRingsShownInCharScreen )
+      pRenderer->_4A612A(a2a, a3a, v20, v229);
+  }
+LABEL_393:
+  pRenderer->DrawTextureTransparent(
+    papredoll_4E4C28 + pPaperdollRightHand[uPlayerID_a],
+    paperdoll_4E4C2C + pPaperdollRightHand[uPlayerID_a + 1],
+    (Texture *)(*(unsigned int *)((char *)papredoll_drhs + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_drhs + v240)] : 0));
+    //(Texture *)(*(unsigned int *)((char *)papredoll_drhs + v240) != -1 ? 72
+    //                                                                   * *(unsigned int *)((char *)papredoll_drhs + v240)
+    //                                                                   + 7145548 : 0));
+  v161 = v217->pEquipment.uMainHand;
+  if ( v161 )
+  {
+    v162 = *(int *)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v161 + 5];
+    if ( pItemsTable->pItems[v162].uEquipType == 1
+      || pItemsTable->pItems[v162].uSkillType == 4 && !v217->pEquipment.uOffHand )
+      pRenderer->DrawTextureTransparent(
+        papredoll_4E4C28 + pPaperdollLeftHand[uPlayerID_a],
+        paperdoll_4E4C2C + pPaperdollLeftHand[uPlayerID_a + 1],
+        (Texture *)(*(unsigned int *)((char *)papredoll_dlhus + v240) != -1 ? (int)&pIcons_LOD->pTextures[*(unsigned int *)((char *)papredoll_dlhus + v240)] : 0));
+        //(Texture *)(*(unsigned int *)((char *)papredoll_dlhus + v240) != -1 ? 72
+        //                                                                    * *(unsigned int *)((char *)papredoll_dlhus
+        //                                                                                      + v240)
+        //                                                                    + 7145548 : 0));
+  }
+  if ( !bRingsShownInCharScreen )
+    pRenderer->DrawTextureTransparent(
+      0x25Bu,
+      0x12Bu,
+      (Texture *)(uTextureID_MAGNIF_B != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_MAGNIF_B] : 0));
+  pRenderer->DrawTextureTransparent(
+    0x1D4u,
+    0,
+    (Texture *)(uTextureID_507B04 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507B04] : 0));
+}
+
+
+//----- (0043E825) --------------------------------------------------------
+void __fastcall CharacterUI_DrawPaperdollWithRingOverlay(unsigned int uPlayerID)
+{
+  unsigned int v1; // ebx@1
+  Player *pPlayer; // edi@1
+  int v3; // ecx@1
+  int v4; // edi@3
+  unsigned int v5; // ebx@3
+  int v6; // eax@3
+  LODFile_IconsBitmaps *v7; // ecx@7
+  double v8; // st7@16
+  int v9; // edi@17
+  Texture *v10; // edi@18
+  unsigned __int8 v11; // zf@19
+  Texture *v12; // eax@19
+  char v13; // sf@24
+  unsigned __int8 v14; // of@24
+  unsigned int v15; // eax@25
+  unsigned int v16; // ebx@26
+  int v17; // eax@26
+  LODFile_IconsBitmaps *v18; // ecx@30
+  double v19; // st7@39
+  int v20; // edi@40
+  int v21; // eax@41
+  signed int v22; // ebx@41
+  Texture *v23; // edi@41
+  int v24; // eax@42
+  char *v25; // eax@42
+  unsigned int v26; // eax@46
+  int v27; // edi@47
+  unsigned int v28; // ebx@47
+  int v29; // eax@47
+  LODFile_IconsBitmaps *v30; // ecx@51
+  Texture *v31; // esi@58
+  double v32; // st7@60
+  int v33; // esi@61
+  int v34; // esi@62
+  Texture *v35; // eax@63
+  const char *v36; // [sp-8h] [bp-38h]@8
+  const char *v37; // [sp-8h] [bp-38h]@31
+  const char *v38; // [sp-8h] [bp-38h]@52
+  int v39; // [sp+10h] [bp-20h]@3
+  Texture *v40; // [sp+10h] [bp-20h]@14
+  int v41; // [sp+10h] [bp-20h]@26
+  Texture *v42; // [sp+10h] [bp-20h]@37
+  int v43; // [sp+10h] [bp-20h]@47
+  unsigned int a3; // [sp+14h] [bp-1Ch]@3
+  unsigned int a2; // [sp+18h] [bp-18h]@3
+  int v46; // [sp+1Ch] [bp-14h]@1
+  Player *v47; // [sp+20h] [bp-10h]@1
+  int v48; // [sp+24h] [bp-Ch]@1
+  int v49; // [sp+24h] [bp-Ch]@26
+
+  v1 = uPlayerID;
+  pPlayer = pPlayers[uPlayerID];
+  v47 = pPlayers[uPlayerID];
+  pIcons_LOD->LoadTexture("sptext01", TEXTURE_16BIT_PALETTE);
+  CharacterUI_DrawPaperdoll(v1);
+  pRenderer->DrawTextureTransparent(
+    0x1D9u,
+    0,
+    (Texture *)(uTextureID_BACKHAND != -1 ? &pIcons_LOD->pTextures[uTextureID_BACKHAND] : 0));
+  pRenderer->DrawTextureTransparent(
+    0x1D4u,
+    0,
+    (Texture *)(uTextureID_507B04 != -1 ? &pIcons_LOD->pTextures[uTextureID_507B04] : 0));
+  pRenderer->DrawTextureIndexed(
+    pCharacterScreen_DetalizBtn->uX,
+    pCharacterScreen_DetalizBtn->uY,
+    (Texture *)(uTextureID_5118C8 != -1 ? &pIcons_LOD->pTextures[uTextureID_5118C8] : 0));
+  v3 = 0;
+  v46 = (int)&pPlayer->pEquipment.field_28;
+  v48 = 0;
+  do
+  {
+    if ( !*(int *)v46 )
+      goto LABEL_24;
+    v39 = *(int *)v46;
+    v4 = (int)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v46 + 5];
+    a3 = *(int *)((char *)dword_4E5C34 + v3);
+    a2 = *(int *)((char *)dword_4E5C1C + v3);
+    v5 = pIcons_LOD->LoadTexture(pItemsTable->pItems[*(int *)v4].pIconName, TEXTURE_16BIT_PALETTE);
+    v6 = *(int *)(v4 + 20);
+    if ( *(int *)(v4 + 20) & 0xF0 )
+    {
+      if ( (*(int *)(v4 + 20) & 0xF0) != 16 )
+      {
+        if ( (*(int *)(v4 + 20) & 0xF0) == 32 )
+        {
+          v36 = "sp28a";
+        }
+        else
+        {
+          if ( (*(int *)(v4 + 20) & 0xF0) != 64 )
+          {
+            v7 = pIcons_LOD;
+            if ( (*(int *)(v4 + 20) & 0xF0) == 128 )
+            {
+              v36 = "sp91a";
+LABEL_14:
+              v40 = &pIcons_LOD->pTextures[v7->LoadTexture(v36, TEXTURE_16BIT_PALETTE)];
+              dword_50C9A8 -= pEventTimer->uTimeElapsed;
+              if ( dword_50C9A8 <= 0 )
+              {
+                dword_50C9A8 = 0;
+                *(char *)(v4 + 20) &= 0xFu;
+                ptr_50C9A4 = 0;
+              }
+              v8 = (double)GetTickCount() * 0.1;
+              pRenderer->_4A63E6(
+                a2,
+                a3,
+                (Texture *)(v5 != -1 ? (int)&pIcons_LOD->pTextures[v5] : 0),
+                v40,
+                (signed __int64)v8,
+                0,
+                255);
+              goto LABEL_23;
+            }
+LABEL_13:
+            v36 = "sptext01";
+            goto LABEL_14;
+          }
+          v36 = "sp30a";
+        }
+        v7 = pIcons_LOD;
+        goto LABEL_14;
+      }
+      v7 = pIcons_LOD;
+      goto LABEL_13;
+    }
+    v9 = v5 + 1;
+    if ( v6 & 2 )
+    {
+      v10 = (Texture *)(v9 != 0 ? (int)&pIcons_LOD->pTextures[v5] : 0);
+      pRenderer->_4A6776(a2, a3, v10);
+    }
+    else
+    {
+      v11 = (v6 & 1) == 0;
+      v12 = &pIcons_LOD->pTextures[v5];
+      if ( v11 )
+      {
+        v10 = (Texture *)(v9 != 0 ? (int)v12 : 0);
+        pRenderer->DrawTransparentGreenShade(a2, a3, v10);
+      }
+      else
+      {
+        v10 = (Texture *)(v9 != 0 ? (int)v12 : 0);
+        pRenderer->DrawTextureTransparent(a2, a3, v10);
+      }
+    }
+    pRenderer->_4A601E(a2, a3, v10, v39);
+LABEL_23:
+    pPlayer = v47;
+LABEL_24:
+    v46 += 4;
+    v3 = v48 + 4;
+    v14 = __OFSUB__(v48 + 4, 20);
+    v11 = v48 == 16;
+    v13 = v48 - 16 < 0;
+    v48 += 4;
+  }
+  while ( (unsigned __int8)(v13 ^ v14) | v11 );
+  v15 = pPlayer->pEquipment.field_24;
+  if ( !v15 )
+    goto LABEL_46;
+  v41 = pPlayer->pEquipment.field_24;
+  v49 = (int)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5];
+  v16 = pIcons_LOD->LoadTexture(pItemsTable->pItems[*(int *)v49].pIconName, TEXTURE_16BIT_PALETTE);
+  v17 = *(int *)(v49 + 20);
+  if ( !(*(int *)(v49 + 20) & 0xF0) )
+  {
+    v20 = v16 + 1;
+    if ( v17 & 2 )
+    {
+      v21 = 9 * v16;
+      v22 = 493;
+      v23 = (Texture *)(v20 != 0 ? (int)&pIcons_LOD->pTextures[8 * v21 / 0x48u] : 0);
+      pRenderer->_4A6776(0x1EDu, 0x5Bu, v23);
+    }
+    else
+    {
+      v11 = (v17 & 1) == 0;
+      v24 = 9 * v16;
+      v22 = 493;
+      v25 = (char *)&pIcons_LOD->pTextures[8 * v24 / 0x48u];
+      if ( v11 )
+      {
+        v23 = (Texture *)(v20 != 0 ? (int)v25 : 0);
+        pRenderer->DrawTransparentGreenShade(493, 91, v23);
+      }
+      else
+      {
+        v23 = (Texture *)(v20 != 0 ? (int)v25 : 0);
+        pRenderer->DrawTextureTransparent(0x1EDu, 0x5Bu, v23);
+      }
+    }
+    pRenderer->_4A601E(v22, 91, v23, v41);
+    pPlayer = v47;
+    goto LABEL_46;
+  }
+  if ( (*(int *)(v49 + 20) & 0xF0) == 16 )
+  {
+    v18 = pIcons_LOD;
+    goto LABEL_36;
+  }
+  if ( (*(int *)(v49 + 20) & 0xF0) == 32 )
+  {
+    v37 = "sp28a";
+    goto LABEL_34;
+  }
+  if ( (*(int *)(v49 + 20) & 0xF0) == 64 )
+  {
+    v37 = "sp30a";
+LABEL_34:
+    v18 = pIcons_LOD;
+    goto LABEL_37;
+  }
+  v18 = pIcons_LOD;
+  if ( (*(int *)(v49 + 20) & 0xF0) == 128 )
+  {
+    v37 = "sp91a";
+    goto LABEL_37;
+  }
+LABEL_36:
+  v37 = "sptext01";
+LABEL_37:
+  v42 = &pIcons_LOD->pTextures[v18->LoadTexture(v37, TEXTURE_16BIT_PALETTE)];
+  dword_50C9A8 -= pEventTimer->uTimeElapsed;
+  if ( dword_50C9A8 <= 0 )
+  {
+    dword_50C9A8 = 0;
+    *(char *)(v49 + 20) &= 0xFu;
+    ptr_50C9A4 = 0;
+  }
+  v19 = (double)GetTickCount() * 0.1;
+  pRenderer->_4A63E6(
+    0x1EDu,
+    0x5Bu,
+    (Texture *)(v16 != -1 ? (int)&pIcons_LOD->pTextures[v16] : 0),
+    v42,
+    (signed __int64)v19,
+    0,
+    255);
+LABEL_46:
+  v26 = pPlayer->pEquipment.field_1C;
+  if ( !v26 )
+    return;
+  v43 = pPlayer->pEquipment.field_1C;
+  v27 = (int)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v26 + 5];
+  v28 = pIcons_LOD->LoadTexture(pItemsTable->pItems[*(int *)v27].pIconName, TEXTURE_16BIT_PALETTE);
+  v29 = *(int *)(v27 + 20);
+  if ( !(*(int *)(v27 + 20) & 0xF0) )
+  {
+    v33 = v28 + 1;
+    if ( v29 & 2 )
+    {
+      v34 = v33 != 0 ? (int)&pIcons_LOD->pTextures[v28] : 0;
+      pRenderer->_4A6776(0x24Au, 0x58u, (Texture *)v34);
+    }
+    else
+    {
+      v11 = (v29 & 1) == 0;
+      v35 = &pIcons_LOD->pTextures[v28];
+      if ( v11 )
+      {
+        v34 = v33 != 0 ? (int)v35 : 0;
+        pRenderer->DrawTransparentGreenShade(586, 88, (Texture *)v34);
+      }
+      else
+      {
+        v34 = v33 != 0 ? (int)v35 : 0;
+        pRenderer->DrawTextureTransparent(0x24Au, 0x58u, (Texture *)v34);
+      }
+    }
+    pRenderer->_4A601E(586, 88, (Texture *)v34, v43);
+    return;
+  }
+  if ( (*(int *)(v27 + 20) & 0xF0) == 16 )
+  {
+    v30 = pIcons_LOD;
+    goto LABEL_57;
+  }
+  if ( (*(int *)(v27 + 20) & 0xF0) == 32 )
+  {
+    v38 = "sp28a";
+    goto LABEL_55;
+  }
+  if ( (*(int *)(v27 + 20) & 0xF0) == 64 )
+  {
+    v38 = "sp30a";
+LABEL_55:
+    v30 = pIcons_LOD;
+    goto LABEL_58;
+  }
+  v30 = pIcons_LOD;
+  if ( (*(int *)(v27 + 20) & 0xF0) == 128 )
+  {
+    v38 = "sp91a";
+    goto LABEL_58;
+  }
+LABEL_57:
+  v38 = "sptext01";
+LABEL_58:
+  v31 = &pIcons_LOD->pTextures[v30->LoadTexture(v38, TEXTURE_16BIT_PALETTE)];
+  dword_50C9A8 -= pEventTimer->uTimeElapsed;
+  if ( dword_50C9A8 <= 0 )
+  {
+    dword_50C9A8 = 0;
+    *(char *)(v27 + 20) &= 0xFu;
+    ptr_50C9A4 = 0;
+  }
+  v32 = (double)GetTickCount() * 0.1;
+  pRenderer->_4A63E6(
+    0x24Au,
+    0x58u,
+    (Texture *)(v28 != -1 ? (int)&pIcons_LOD->pTextures[v28] : 0),
+    v31,
+    (signed __int64)v32,
+    0,
+    255);
+}
+
+
+//----- (0043ED6F) --------------------------------------------------------
+bool _43ED6F_check_party_races(bool a1)
+{
+  bool v6; // zf@5
+
+  for (uint i = 0; i < 4; ++i)
+  {
+    auto player = pParty->pPlayers + i;
+    auto race = player->GetRace();
+
+    if (race != CHARACTER_RACE_HUMAN &&
+        race != CHARACTER_RACE_ELF &&
+        race != CHARACTER_RACE_GOBLIN)
+      v6 = a1 == 1;
+    else
+      v6 = !a1;
+
+    if (v6)
+      return true;
+  }
+  return false;
+}
+// A750D8: using guessed type __int64 qword_A750D8;
+
+//----- (0043EDB9) --------------------------------------------------------
+bool __thiscall sub_43EDB9_get_some_race_sex_relation_2(unsigned int _this)
+{
+  unsigned int v1; // ebp@1
+  Player **v2; // ebx@1
+  Player *v3; // esi@2
+  enum CHARACTER_RACE v4; // edi@2
+  bool result; // eax@2
+  char v6; // zf@7
+
+  v1 = _this;
+  v2 = &pPlayers[1];
+  while ( 1 )
+  {
+    v3 = *v2;
+    v4 = v3->GetRace();
+    result = v3->GetSexByVoice();
+    if ( !v4 )
+      break;
+    if ( v4 == 1 || v4 == 2 )
+      break;
+    if ( !result && v1 == 2 )
+      goto LABEL_15;
+    v6 = v1 == 3;
+LABEL_11:
+    if ( v6 )
+      goto LABEL_15;
+    ++v2;
+    if ( (signed int)v2 >= (signed int)&qword_A750D8 )
+    {
+      LOBYTE(result) = 0;
+      return result;
+    }
+  }
+  if ( result || v1 )
+  {
+    v6 = v1 == 1;
+    goto LABEL_11;
+  }
+LABEL_15:
+  LOBYTE(result) = 1;
+  return result;
+}
+// A750D8: using guessed type __int64 qword_A750D8;
+
+//----- (0043EE15) --------------------------------------------------------
+bool __fastcall sub_43EE15_player_has_item(unsigned int uItemID, Player *pPlayer, char a3)
+{
+  bool result; // eax@0
+  signed int v4; // edi@3
+  int *v5; // esi@3
+  signed int v6; // edi@7
+  bool *v7; // esi@7
+
+  if ( !a3 || pParty->pPickedItem.uItemID != uItemID )
+  {
+    v4 = 0;
+    v5 = pPlayer->pInventoryIndices;
+    while ( 1 )
+    {
+      if ( *v5 )
+      {
+        result = 9 * *v5;
+        if ( *(int *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *v5 + 5] == uItemID )
+          break;
+      }
+      ++v4;
+      ++v5;
+      if ( v4 >= 126 )
+      {
+        v6 = 0;
+        v7 = (bool *)&pPlayer->pEquipment;
+        while ( 1 )
+        {
+          result = *v7;
+          if ( *v7 )
+          {
+            result *= 9;
+            if ( *(int *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5] == uItemID )
+              break;
+          }
+          ++v6;
+          ++v7;
+          if ( v6 >= 16 )
+          {
+            LOBYTE(result) = 0;
+            return result;
+          }
+        }
+        break;
+      }
+    }
+  }
+  LOBYTE(result) = 1;
+  return result;
+}
+
+//----- (0043EE77) --------------------------------------------------------
+bool __fastcall sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(signed int a1)
+{
+  bool result; // eax@0
+  Player *v2; // edx@3
+  int v3; // ecx@3
+  Player **pPlayers; // esi@8
+  unsigned int v5; // ecx@8
+  Player *v6; // edx@9
+
+  if ( a1 < 1 || a1 > 4 )
+  {
+    if ( !a1 )
+    {
+      pPlayers = &::pPlayers[1];
+      v5 = 604;
+      while ( 1 )
+      {
+        result = sub_43EE15_player_has_item(v5, *pPlayers, 0);
+        if ( !result )
+          break;
+        result = v6->pEquipment.uBody;
+        if ( !result )
+          break;
+        result *= 9;
+        if ( *(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5] != v5 )
+          break;
+        ++pPlayers;
+        if ( (signed int)pPlayers >= (signed int)&qword_A750D8 )
+          goto LABEL_13;
+      }
+    }
+    goto LABEL_6;
+  }
+  result = sub_43EE15_player_has_item(604u, ::pPlayers[a1], 0);
+  if ( !result
+    || (result = v2->pEquipment.uBody) == 0
+    || (result *= 9, *(int *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5] != v3) )
+  {
+LABEL_6:
+    LOBYTE(result) = 0;
+    return result;
+  }
+LABEL_13:
+  LOBYTE(result) = 1;
+  return result;
+}
+// A750D8: using guessed type __int64 qword_A750D8;
+
+//----- (0043EF2B) --------------------------------------------------------
+void __fastcall WetsuitOn(unsigned int uPlayerID)
+{
+  unsigned int v1; // ebx@1
+  Player **v2; // esi@2
+  enum CHARACTER_RACE v3; // edi@2
+  signed int v4; // eax@2
+  int v5; // ecx@5
+  unsigned __int8 v6; // al@7
+  char pContainer[20]; // [sp+4h] [bp-1Ch]@7
+  unsigned int v8; // [sp+18h] [bp-8h]@1
+  int v9; // [sp+1Ch] [bp-4h]@7
+
+  v1 = uPlayerID - 1;
+  v8 = uPlayerID;
+  if ( ((uPlayerID - 1) & 0x80000000u) == 0 )
+  {
+    v2 = &pPlayers[uPlayerID];
+    v3 = (*v2)->GetRace();
+    v4 = (*v2)->GetSexByVoice();
+    if ( v3 && v3 != 1 && v3 != 2 )
+      v5 = (v4 != 0) + 3;
+    else
+      v5 = (v4 != 0) + 1;
+    v9 = v5;
+    wsprintfA(pContainer, "pc23v%dBod", v5);
+    papredoll_dbods[v1] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    wsprintfA(pContainer, "pc23v%dlad", v9);
+    papredoll_dlads[v1] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    wsprintfA(pContainer, "pc23v%dlau", v9);
+    papredoll_dlaus[v1] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    wsprintfA(pContainer, "pc23v%drh", v9);
+    papredoll_drhs[v1] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    wsprintfA(pContainer, "pc23v%dlh", v9);
+    papredoll_dlhs[v1] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    wsprintfA(pContainer, "pc23v%dlhu", v9);
+    papredoll_dlhus[v1] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    v6 = pPlayers[v1 + 1]->uFace;
+    if ( v6 == 12 || v6 == 13 )
+      papredoll_dbrds[pPlayers[v8]->uFace] = 0;
+    papredoll_flying_feet[pPlayers[v8]->uFace] = 0;
+    IsPlayerWearingWatersuit[v8] = 1;
+  }
+}
+
+//----- (0043F0BD) --------------------------------------------------------
+unsigned int __fastcall WetsuitOff(unsigned int uPlayerID)
+{
+  unsigned int result; // eax@1
+  Player **v2; // edi@2
+  unsigned int v3; // ebx@2
+  int v4; // ebx@2
+  char v5; // al@2
+  char pContainer[20]; // [sp+0h] [bp-18h]@4
+  unsigned int v7; // [sp+14h] [bp-4h]@1
+
+  result = uPlayerID - 1;
+  v7 = uPlayerID;
+  if ( ((uPlayerID - 1) & 0x80000000u) == 0 )
+  {
+    v2 = &pPlayers[uPlayerID];
+    v3 = uPlayerID - 1;
+    papredoll_dbods[v3] = pIcons_LOD->LoadTexture(dbod_texnames_by_face[(*v2)->uFace], TEXTURE_16BIT_PALETTE);
+    papredoll_dlads[v3] = pIcons_LOD->LoadTexture(dlad_texnames_by_face[(*v2)->uFace], TEXTURE_16BIT_PALETTE);
+    papredoll_dlaus[v3] = pIcons_LOD->LoadTexture(dlau_texnames_by_face[(*v2)->uFace], TEXTURE_16BIT_PALETTE);
+    papredoll_drhs[v3] = pIcons_LOD->LoadTexture(drh_texnames_by_face[(*v2)->uFace], TEXTURE_16BIT_PALETTE);
+    papredoll_dlhs[v3] = pIcons_LOD->LoadTexture(dlh_texnames_by_face[(*v2)->uFace], TEXTURE_16BIT_PALETTE);
+    papredoll_dlhus[v3] = pIcons_LOD->LoadTexture(dlhu_texnames_by_face[(*v2)->uFace], TEXTURE_16BIT_PALETTE);
+    v4 = (int)&(*v2)->uFace;
+    v5 = *(char *)v4;
+    if ( *(char *)v4 == 12 || v5 == 13 )
+    {
+      wsprintfA(pContainer, "pc%02dbrd", v5 + 1);
+      v4 = (int)&(*v2)->uFace;
+      papredoll_dbrds[*(char *)v4] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    }
+    wsprintfA(pContainer, "item281pc%02d", *(char *)v4 + 1);
+    papredoll_flying_feet[(*v2)->uFace] = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+    result = v7;
+    IsPlayerWearingWatersuit[v7] = 0;
+  }
+  return result;
+}
+
+
+//----- (0043F333) --------------------------------------------------------
+void BspRenderer::MakeVisibleSectorList()
+{
+  int v6; // ebx@3
+
+  uNumVisibleNotEmptySectors = 0;
+  for (uint i = 0; i < std__vector_000FA8; ++i)
+  {
+      v6 = 0;
+      if (!uNumVisibleNotEmptySectors)
+      {
+LABEL_7:
+        pVisibleSectorIDs_toDrawDecorsActorsEtcFrom[uNumVisibleNotEmptySectors++] = field_FA8[i].uSectorID;
+      }
+      else
+      {
+        while (pVisibleSectorIDs_toDrawDecorsActorsEtcFrom[v6] != field_FA8[i].uSectorID )
+        {
+          ++v6;
+          if ( v6 >= uNumVisibleNotEmptySectors)
+          {
+            pVisibleSectorIDs_toDrawDecorsActorsEtcFrom[uNumVisibleNotEmptySectors++] = field_FA8[i].uSectorID;
+            continue;
+          }
+        }
+      }
+  }
+}
+
+
+//----- (0043F515) --------------------------------------------------------
+void MessWithBillboards_BLV()
+{
+  for (uint i = 0; i < uNumBillboardsToDraw; ++i)
+  {
+    auto p = pBillboardRenderList + i;
+
+    if (p->field_1E & 2 || uCurrentlyLoadedLevelType == LEVEL_Indoor && !p->uIndoorSectorID)
+      p->uPaletteSubindex = 0;
+    else
+      p->uPaletteSubindex = _43F55F_get_billboard_light_level(p, -1);
+  }
+}
+
+//----- (0043F55F) --------------------------------------------------------
+int __fastcall _43F55F_get_billboard_light_level(RenderBillboard *a1, int uBaseLightLevel)
+{
+  signed int v3; // ecx@2
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
+  {
+    v3 = pIndoor->pSectors[a1->uIndoorSectorID].uMinAmbientLightLevel;
+  }
+  else
+  {
+    if ( uBaseLightLevel == -1 )
+      v3 = a1->uPaletteSubindex;
+    else
+      v3 = uBaseLightLevel;
+  }
+  return _43F5C8_get_point_light_level_with_respect_to_lights(v3, a1->uIndoorSectorID, a1->some_x, a1->some_y, a1->some_z);
+}
+
+//----- (0043F5C8) --------------------------------------------------------
+int __fastcall _43F5C8_get_point_light_level_with_respect_to_lights(unsigned int uBaseLightLevel, int uSectorID, float x, float y, float z)
+{
+  int v5; // esi@1
+  signed int v6; // edi@1
+  int v8; // eax@6
+  int v9; // ebx@6
+  unsigned int v10; // ecx@6
+  unsigned int v11; // edx@9
+  unsigned int v12; // edx@11
+  signed int v13; // ecx@12
+  BLVLightMM7 *v16; // esi@20
+  int v17; // ebx@21
+  int v18; // eax@24
+  int v19; // ebx@24
+  unsigned int v20; // ecx@24
+  int v21; // edx@25
+  unsigned int v22; // edx@27
+  unsigned int v23; // edx@29
+  signed int v24; // ecx@30
+  int v26; // ebx@35
+  int v27; // eax@38
+  int v28; // ebx@38
+  unsigned int v29; // ecx@38
+  int v30; // edx@39
+  unsigned int v31; // edx@41
+  unsigned int v32; // edx@43
+  signed int v33; // ecx@44
+  int v37; // [sp+Ch] [bp-18h]@37
+  int v38; // [sp+10h] [bp-14h]@5
+  int v39; // [sp+10h] [bp-14h]@23
+  int v40; // [sp+10h] [bp-14h]@36
+  int v42; // [sp+14h] [bp-10h]@22
+  unsigned int v43; // [sp+18h] [bp-Ch]@12
+  unsigned int v44; // [sp+18h] [bp-Ch]@30
+  unsigned int v45; // [sp+18h] [bp-Ch]@44
+
+  v6 = uBaseLightLevel;
+  for (uint i = 0; i < pMobileLightsStack->uNumLightsActive; ++i)
+  {
+    auto p = pMobileLightsStack->pLights + i;
+
+      auto distX = abs(p->vPosition.x - x);
+      if ( distX <= p->uRadius)
+      {
+        auto distY = abs(p->vPosition.y - y);
+        if ( distY <= p->uRadius)
+        {
+          auto distZ = abs(p->vPosition.z - z);
+          if ( distZ <= p->uRadius)
+          {
+            v8 = distX;
+            v9 = distY;
+            v10 = distZ;
+            if (distX < distY)
+            {
+              v8 = distY;
+              v9 = distX;
+            }
+            if ( v8 < distZ )
+            {
+              v11 = v8;
+              v8 = distZ;
+              v10 = v11;
+            }
+            if ( v9 < (signed int)v10 )
+            {
+              v12 = v10;
+              v10 = v9;
+              v9 = v12;
+            }
+            v43 = ((unsigned int)(11 * v9) / 32) + (v10 / 4) + v8;
+            v13 = p->uRadius;
+            if ( (signed int)v43 < v13 )
+              v6 += ((unsigned __int64)(30i64 * (signed int)(v43 << 16) / v13) >> 16) - 30;
+          }
+        }
+      }
+  }
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+  {
+    auto pSector = pIndoor->pSectors + uSectorID;
+
+    for (uint i = 0; i < pSector->uNumLights; ++i)
+    {
+        v16 = pIndoor->pLights + pSector->pLights[i];
+        if (~v16->uAtributes & 8)
+        {
+          v17 = abs(v16->vPosition.x - x);
+          if ( v17 <= v16->uRadius )
+          {
+            v42 = abs(v16->vPosition.y - y);
+            if ( v42 <= v16->uRadius )
+            {
+              v39 = abs(v16->vPosition.z - z);
+              if ( v39 <= v16->uRadius )
+              {
+                v18 = v17;
+                v19 = v42;
+                v20 = v39;
+                if ( v18 < v42 )
+                {
+                  v21 = v18;
+                  v18 = v42;
+                  v19 = v21;
+                }
+                if ( v18 < v39 )
+                {
+                  v22 = v18;
+                  v18 = v39;
+                  v20 = v22;
+                }
+                if ( v19 < (signed int)v20 )
+                {
+                  v23 = v20;
+                  v20 = v19;
+                  v19 = v23;
+                }
+                v44 = ((unsigned int)(11 * v19) >> 5) + (v20 >> 2) + v18;
+                v24 = v16->uRadius;
+                if ( (signed int)v44 < v24 )
+                  v6 += ((unsigned __int64)(30i64 * (signed int)(v44 << 16) / v24) >> 16) - 30;
+              }
+            }
+          }
+        }
+    }
+  }
+
+  for (uint i = 0; i < pStationaryLightsStack->uNumLightsActive; ++i)
+  {
+    auto p = pStationaryLightsStack->pLights + i;
+      v26 = abs(p->vPosition.x - x);
+      if ( v26 <= p->uRadius)
+      {
+        v40 = abs(p->vPosition.y - y);
+        if ( v40 <= p->uRadius)
+        {
+          v37 = abs(p->vPosition.z - z);
+          if ( v37 <= p->uRadius)
+          {
+            v27 = v26;
+            v28 = v40;
+            v29 = v37;
+            if ( v27 < v40 )
+            {
+              v30 = v27;
+              v27 = v40;
+              v28 = v30;
+            }
+            if ( v27 < v37 )
+            {
+              v31 = v27;
+              v27 = v37;
+              v29 = v31;
+            }
+            if ( v28 < (signed int)v29 )
+            {
+              v32 = v29;
+              v29 = v28;
+              v28 = v32;
+            }
+            v45 = ((unsigned int)(11 * v28) >> 5) + (v29 >> 2) + v27;
+            v33 = p->uRadius;
+            if ( (signed int)v45 < v33 )
+              v6 += ((unsigned __int64)(30i64 * (signed int)(v45 << 16) / v33) >> 16) - 30;
+          }
+        }
+      }
+  }
+
+  if ( v6 <= 31 )
+  {
+    if ( v6 < 0 )
+      v6 = 0;
+  }
+  else
+  {
+    v6 = 31;
+  }
+  return v6;
+}
+
+//----- (00406051) --------------------------------------------------------
+__int16 stru262_TurnBased::StartTurn()
+{
+  stru262_TurnBased *v1; // esi@1
+  int v2; // ecx@1
+  int v3; // ebx@1
+  char *v4; // edi@1
+  int v5; // eax@4
+  int v6; // eax@12
+  char *v7; // eax@15
+  TurnBased_QueueElem *v8; // edi@17
+  unsigned int v9; // edx@23
+  char *v10; // eax@26
+  int v11; // eax@30
+  int v12; // ebx@30
+  char *v13; // edi@31
+  int v15; // [sp+Ch] [bp-10h]@5
+  TurnBased_QueueElem *v16; // [sp+10h] [bp-Ch]@3
+  int v17; // [sp+14h] [bp-8h]@2
+  int v18; // [sp+14h] [bp-8h]@16
+  signed int v19; // [sp+18h] [bp-4h]@1
+  int v20; // [sp+18h] [bp-4h]@14
+
+  v1 = this;
+  v2 = 0;
+  v19 = 0;
+  v3 = v1->uActorQueueSize;
+  v1->field_1C = 0;
+  v4 = (char *)&v1->pQueue[v3].field_4;
+  do
+  {
+    v17 = v2;
+    if ( v1->uActorQueueSize <= v2 )
+      goto LABEL_11;
+    v16 = v1->pQueue;
+    while ( 1 )
+    {
+      v5 = v16->uPackedID;
+      if ( (v16->uPackedID & 7) == 4 )
+        break;
+LABEL_8:
+      ++v17;
+      ++v16;
+      if ( v17 >= v1->uActorQueueSize )
+        goto LABEL_11;
+    }
+    v15 = v5 >> 3;
+    if ( !pPlayers[(v5 >> 3) + 1]->CanAct() || v19 != v15 )
+    {
+      v2 = 0;
+      goto LABEL_8;
+    }
+    v2 = 0;
+LABEL_11:
+    if ( v17 == v1->uActorQueueSize )
+    {
+      *(int *)v4 = 100;
+      v6 = 8 * v19;
+      LOBYTE(v6) = 8 * v19 | 4;
+      *((int *)v4 + 2) = v2;
+      *((int *)v4 - 1) = v6;
+      *((int *)v4 + 1) = v2;
+      ++v3;
+      v4 += 16;
+    }
+    ++v19;
+  }
+  while ( v19 < 4 );
+  v1->uActorQueueSize = v3;
+  v20 = v2;
+  if ( ai_arrays_size > v2 )
+  {
+    v7 = (char *)&v1->pQueue[v3].field_4;
+    do
+    {
+      v18 = v2;
+      if ( v1->uActorQueueSize > v2 )
+      {
+        v8 = v1->pQueue;
+        do
+        {
+          if ( (v8->uPackedID & 7) == 3 && ai_array_4F7DB0_actor_ids[v20] == v8->uPackedID >> 3 )
+            break;
+          ++v18;
+          ++v8;
+        }
+        while ( v18 < v1->uActorQueueSize );
+        v2 = 0;
+      }
+      if ( v18 == v1->uActorQueueSize )
+      {
+        v9 = ai_array_4F7DB0_actor_ids[v20];
+        *(int *)v7 = 1;
+        *((int *)v7 + 2) = v2;
+        *((int *)v7 - 1) = 8 * v9 | 3;
+        *((int *)v7 + 1) = v2;
+        ++v3;
+        v7 += 16;
+      }
+      ++v20;
+    }
+    while ( v20 < ai_arrays_size );
+  }
+  ++v1->field_0;
+  v1->uActorQueueSize = v3;
+  v1->field_10 = 100;
+  if ( v3 > 0 )
+  {
+    v10 = (char *)&v1->pQueue[0].field_4;
+    do
+    {
+      if ( *(int *)v10 <= 0 )
+        *(int *)v10 = 100;
+      ++v2;
+      v10 += 16;
+    }
+    while ( v2 < v1->uActorQueueSize );
+  }
+  LOWORD(v11) = v1->_4063A1();
+  v12 = 0;
+  if ( v1->uActorQueueSize > 0 )
+  {
+    v13 = (char *)&v1->pQueue[0].field_4;
+    do
+    {
+      v11 = *((int *)v13 - 1) & 7;
+      if ( (char)v11 == 4 )
+        break;
+      if ( *(int *)v13 > 0 )
+        break;
+      LOWORD(v11) = v1->_40680F(v12++);
+      v13 += 16;
+    }
+    while ( v12 < v1->uActorQueueSize );
+  }
+  return v11;
+}
+// 4F75D8: using guessed type int ai_arrays_size;
+
+//----- (004061CA) --------------------------------------------------------
+void stru262_TurnBased::NextTurn()
+{
+  stru262_TurnBased *v1; // esi@1
+  TurnBased_QueueElem *v2; // ebp@1
+  int v3; // ebx@1
+  int v4; // edi@7
+  Actor *v5; // eax@9
+  int v6; // ecx@9
+  signed int v7; // ebx@17
+  int v8; // ebp@27
+  TurnBased_QueueElem *v9; // edi@28
+  int v10; // ecx@30
+  unsigned __int16 v11; // ax@30
+  signed int v12; // edx@35
+  signed int v13; // [sp+10h] [bp-4h]@7
+
+  v1 = this;
+  _404544();
+  v2 = v1->pQueue;
+  v3 = 0;
+  if ( (v1->pQueue[0].uPackedID & 7) == 4 )
+    uActiveCharacter = (v1->pQueue[0].uPackedID >> 3) + 1;
+  else
+    uActiveCharacter = 0;
+  viewparams->bRedrawGameUI = 1;
+  if ( v1->field_1C )
+  {
+    pTurnEngine->field_18 |= 2u;
+    return;
+  }
+  pTurnEngine->field_18 &= 0xFFFFFFFDu;
+  if ( v1->pQueue[0].field_4 <= 0 )
+    return;
+  v4 = 0;
+  v13 = 0;
+  if ( v1->uActorQueueSize <= 0 )
+    goto LABEL_27;
+  do
+  {
+    if ( (v2->uPackedID & 7) != 4 )
+    {
+      v5 = &pActors[v2->uPackedID >> 3];
+      LOWORD(v6) = v5->uAIState;
+      if ( (short)v6 == 4
+        || (short)v6 == 8
+        || (short)v6 == 2
+        || (short)v6 == 3
+        || (short)v6 == 12
+        || (short)v6 == 13
+        || (short)v6 == 18
+        || (short)v6 == 17 )
+      {
+        v7 = v5->uCurrentActionLength;
+        v5->uCurrentActionTime += pEventTimer->uTimeElapsed;
+        if ( (signed int)v5->uCurrentActionTime < v7 )
+        {
+          v13 = 1;
+LABEL_19:
+          v3 = 0;
+          goto LABEL_20;
+        }
+        v6 = (signed __int16)v6;
+        if ( (signed __int16)v6 == 4 )
+        {
+          v3 = 0;
+          v5->uAIState = Dead;
+          v5->uCurrentActionTime = 0;
+          v5->uCurrentActionLength = 0;
+          v5->UpdateAnimation();
+        }
+        else
+        {
+          if ( v6 != 8 )
+            goto LABEL_19;
+          v3 = 0;
+          Actor::_403F58(v2->uPackedID >> 3, dword_4F6E08[v2->uPackedID >> 3], 32, 0);
+        }
+      }
+    }
+LABEL_20:
+    ++v4;
+    ++v2;
+  }
+  while ( v4 < v1->uActorQueueSize );
+  if ( v13 != v3 )
+  {
+    v1->field_18 |= 1u;
+    return;
+  }
+LABEL_27:
+  v1->field_18 &= 0xFFFFFFFEu;
+  v8 = 0;
+  if ( v1->uActorQueueSize > v3 )
+  {
+    v9 = v1->pQueue;
+    do
+    {
+      if ( (v9->uPackedID & 7) != 4 )
+      {
+        v10 = v9->uPackedID >> 3;
+        v11 = pActors[v10].uAIState;
+        if ( v11 != 5 )
+        {
+          if ( v11 != 4 && v11 != 11 && v11 != 19 )
+          {
+            if ( v11 != 17 )
+            {
+              v12 = dword_4F6E08[v10];
+              v9->uActionLength = v3;
+              Actor::_403F58(v10, v12, 32, (AIDirection *)v3);
+            }
+          }
+        }
+      }
+      ++v8;
+      ++v9;
+    }
+    while ( v8 < v1->uActorQueueSize );
+  }
+  v1->field_4 = 3;
+  pParty->uTimePlayed += __PAIR__(v3, 213);
+  _494035_timed_effects__water_walking_damage__etc();
+  v1->uActionPointsLeft = 130;
+}
+
+//----- (004063A1) --------------------------------------------------------
+int stru262_TurnBased::_4063A1()
+{
+  stru262_TurnBased *v1; // esi@1
+  int v2; // ebp@1
+  signed int result; // eax@1
+  int v4; // edx@1
+  int v5; // edx@3
+  int v6; // edi@4
+  int v7; // ecx@5
+  Actor *v8; // ecx@11
+  unsigned __int16 v9; // dx@12
+  int v10; // edi@16
+  int v11; // edx@17
+  char v12; // zf@18
+
+  v1 = this;
+  _404544();
+  v2 = (int)&v1->pQueue[0].field_4;
+  result = 1;
+  viewparams->bRedrawGameUI = 1;
+  v4 = v1->pQueue[0].field_4;
+  if ( v4 )
+  {
+    if ( (v1->pQueue[0].uPackedID & 7) == 4 )
+    {
+      v5 = v1->uActorQueueSize;
+      while ( 1 )
+      {
+        v6 = 0;
+        if ( v5 > 0 )
+        {
+          v7 = (int)&v1->pQueue[0].field_4;
+          do
+          {
+            --*(int *)v7;
+            v5 = v1->uActorQueueSize;
+            ++v6;
+            v7 += 16;
+          }
+          while ( v6 < v5 );
+        }
+        --v1->field_10;
+        if ( v1->field_10 <= 0 )
+          break;
+        if ( !*(int *)v2 )
+          goto LABEL_9;
+      }
+LABEL_24:
+      result = 1;
+    }
+    else
+    {
+      v8 = &pActors[v1->pQueue[0].uPackedID >> 3];
+      if ( v4 > 0 )
+      {
+        do
+        {
+          v9 = v8->uAIState;
+          if ( v9 == 5 )
+            break;
+          if ( v9 == 4 || v9 == 19 || v9 == 11 )
+            break;
+          v10 = 0;
+          if ( v1->uActorQueueSize > 0 )
+          {
+            v11 = (int)&v1->pQueue[0].field_4;
+            do
+            {
+              v12 = (*(int *)v11)-- == 1;
+              if ( v12 )
+                *(int *)(v11 + 4) = 0;
+              ++v10;
+              v11 += 16;
+            }
+            while ( v10 < v1->uActorQueueSize );
+          }
+          --v1->field_10;
+          if ( v1->field_10 <= 0 )
+            goto LABEL_24;
+        }
+        while ( *(int *)v2 > 0 );
+      }
+LABEL_9:
+      result = 0;
+    }
+  }
+  return result;
+}
+
+//----- (00406457) --------------------------------------------------------
+int stru262_TurnBased::_406457(int a2)
+{
+  stru262_TurnBased *v2; // esi@1
+  signed int v3; // eax@1
+  signed int v4; // ecx@2
+  char *v5; // edx@2
+  signed int v6; // eax@2
+  int result; // eax@11
+  int v8; // edx@13
+  int v9; // ecx@14
+  char v10; // zf@15
+
+  v2 = this;
+  v3 = *(&this->field_0 + 4 * (a2 + 2));
+  if ( (*((char *)&this->field_0 + 16 * (a2 + 2)) & 7) == 4 )
+  {
+    v4 = v3 >> 3;
+    v5 = (char *)&pParty->pTurnBasedPlayerRecoveryTimes[v3 >> 3];
+    v6 = *(int *)v5;
+    if ( *(int *)v5 )
+      *(int *)v5 = 0;
+    else
+      v6 = pPlayers[v4 + 1]->GetAttackRecoveryTime(0);
+    if ( v6 < 30 )
+      v6 = 30;
+  }
+  else
+  {
+    v6 = pMonsterStats->pInfos[pActors[v3 >> 3].pMonsterInfo.uID].uRecoveryTime;
+  }
+  v2->pQueue[a2].field_4 = v6;
+  v2->_404544();
+  if ( (v2->pQueue[0].uPackedID & 7) == 4 )
+    uActiveCharacter = (v2->pQueue[0].uPackedID >> 3) + 1;
+  else
+    uActiveCharacter = 0;
+  result = (int)&v2->pQueue[0].field_4;
+  viewparams->bRedrawGameUI = 1;
+  while ( *(int *)result > 0 )
+  {
+    if ( v2->field_10 <= 0 )
+      break;
+    v8 = 0;
+    if ( v2->uActorQueueSize > 0 )
+    {
+      v9 = (int)&v2->pQueue[0].field_4;
+      do
+      {
+        v10 = (*(int *)v9)-- == 1;
+        if ( v10 )
+          *(int *)(v9 + 4) = 0;
+        ++v8;
+        v9 += 16;
+      }
+      while ( v8 < v2->uActorQueueSize );
+    }
+    --v2->field_10;
+    if ( v2->field_10 <= 0 )
+      break;
+  }
+  return result;
+}
+
+//----- (0040652A) --------------------------------------------------------
+void stru262_TurnBased::_40652A()
+{
+  char *v1; // edx@2
+  Actor *v2; // eax@5
+  unsigned __int16 v3; // si@5
+  unsigned int v4; // esi@8
+  int v5; // [sp+Ch] [bp-4h]@1
+
+  v5 = 0;
+  if ( this->uActorQueueSize > 0 )
+  {
+    v1 = (char *)&this->pQueue[0].field_4;
+    do
+    {
+      if ( !*(int *)v1 )
+      {
+        if ( (*(v1 - 4) & 7) == 4 )
+          return;
+        v2 = &pActors[*((int *)v1 - 1) >> 3];
+        v3 = v2->uAIState;
+        if ( !v3 || v3 == 9 || v3 == 7 )
+        {
+          v4 = pMonsterStats->pInfos[v2->pMonsterInfo.uID].uRecoveryTime;
+          *(int *)v1 = v4;
+          if ( (signed __int64)v2->pActorBuffs[7].uExpireTime > 0 )
+            *(int *)v1 = 2 * v4;
+        }
+      }
+      ++v5;
+      v1 += 16;
+    }
+    while ( v5 < this->uActorQueueSize );
+  }
+}
+
+//----- (004065B0) --------------------------------------------------------
+__int16 stru262_TurnBased::_4065B0()
+{
+  stru262_TurnBased *v1; // esi@1
+  signed int v2; // eax@1
+  int v3; // ebx@6
+  int v4; // edi@7
+  unsigned int v5; // edi@14
+
+  v1 = this;
+  LOWORD(v2) = _404544();
+  if ( v1->pQueue[0].field_4 <= 0
+    || ((_4063A1(), v2 = v1->pQueue[0].uPackedID, (v1->pQueue[0].uPackedID & 7) != 4) ? (uActiveCharacter = 0) : (v2 = (v2 >> 3) + 1, uActiveCharacter = v2),
+        viewparams->bRedrawGameUI = 1,
+        v1->pQueue[0].field_4 <= 0) )
+  {
+    v3 = 0;
+    if ( v1->uActorQueueSize > 0 )
+    {
+      v4 = (int)v1->pQueue;
+      do
+      {
+        v2 = *(int *)v4;
+        if ( (*(char *)v4 & 7) == 4 || *(int *)(v4 + 4) > 0 )
+          break;
+        if ( *(int *)(v4 + 8) <= 0 )
+        {
+          LOWORD(v2) = v2 & 3;
+          if ( (char)v2 == 3 )
+            LOWORD(v2) = v1->_40680F(v3);
+        }
+        ++v3;
+        v4 += 16;
+      }
+      while ( v3 < v1->uActorQueueSize );
+    }
+  }
+  v5 = 0;
+  if ( v1->uActorQueueSize > 0 )
+  {
+    do
+      LOWORD(v2) = v1->_406648(v5++);
+    while ( (signed int)v5 < v1->uActorQueueSize );
+  }
+  return v2;
+}
+
+//----- (00406648) --------------------------------------------------------
+__int16 stru262_TurnBased::_406648(unsigned int a2)
+{
+  TurnBased_QueueElem *v1; // ecx@1
+  int v3; // eax@1
+  unsigned int v4; // ebx@2
+  Actor *v5; // esi@2
+  signed int v6; // edi@5
+  int v7; // ecx@6
+  int v8; // eax@6
+  int v9; // eax@7
+  int v10; // eax@8
+  int v11; // eax@9
+  int v12; // eax@10
+  int v13; // eax@11
+  int v14; // eax@14
+  unsigned int v15; // ecx@14
+  unsigned int v16; // edx@14
+  int v17; // eax@17
+  int v18; // eax@20
+  char v19; // al@24
+  unsigned int v21; // [sp-8h] [bp-50h]@16
+  int v22; // [sp-8h] [bp-50h]@17
+  AIDirection *v23; // [sp-4h] [bp-4Ch]@14
+  unsigned int v24; // [sp-4h] [bp-4Ch]@17
+  char v25; // [sp-4h] [bp-4Ch]@20
+  AIDirection a3; // [sp+Ch] [bp-3Ch]@2
+  AIDirection a4; // [sp+28h] [bp-20h]@2
+  TurnBased_QueueElem *v28; // [sp+44h] [bp-4h]@1
+  unsigned int a2a; // [sp+50h] [bp+8h]@2
+
+  v1 = (TurnBased_QueueElem *)((char *)this + 16 * (a2 + 2));
+  v28 = v1;
+  v3 = v1->uPackedID;
+  if ( (v1->uPackedID & 7) != 4 )
+  {
+    v4 = v3 >> 3;                               // turn based only stuff
+    a2a = dword_4F6E08[v3 >> 3];
+    memcpy(&a3, Actor::GetDirectionInfo(v1->uPackedID, dword_4F6E08[v3 >> 3], &a3, 0), sizeof(a3));
+    memcpy(&a4, &a3, sizeof(a4));
+    v5 = &pActors[v3 >> 3];
+    LOWORD(v3) = v5->uAIState;
+    if ( (short)v3 != Dead )
+    {
+      if ( (short)v3 != Disabled )
+      {
+        if ( (short)v3 != Removed )
+        {
+          v6 = v5->uCurrentActionLength;
+          v5->uCurrentActionTime += pEventTimer->uTimeElapsed;
+          if ( (signed int)v5->uCurrentActionTime >= v6 )
+          {
+            v7 = (signed __int16)v3;
+            v8 = (signed __int16)v3 - 2;
+            if ( !v8 )
+            {
+              v19 = stru_50C198.special_ability_use_check(&pActors[v4], v4);
+              stru_50FE08.Add(
+                v28->uPackedID,
+                5120,
+                v5->vPosition.x,
+                v5->vPosition.y,
+                v5->vPosition.z + ((signed int)v5->uActorHeight >> 1),
+                v19,
+                1);
+              goto LABEL_25;
+            }
+            v9 = v8 - 1;
+            if ( v9 )
+            {
+              v10 = v9 - 1;
+              if ( !v10 )
+                goto LABEL_21;
+              v11 = v10 - 4;
+              if ( !v11 )
+                goto LABEL_25;
+              v12 = v11 - 4;
+              if ( v12 )
+              {
+                v13 = v12 - 1;
+                if ( v13 )
+                {
+                  if ( v13 != Dead )
+                  {
+                    if ( v7 != 4 )
+                    {
+                      v14 = rand();
+                      v15 = v4;
+                      v23 = &a4;
+                      v16 = a2a;
+                      if ( !(v14 % 2) )
+                      {
+                        LOWORD(v3) = Actor::_402F87(v4, a2a, &a4);
+                        return v3;
+                      }
+                      v21 = 64;
+LABEL_26:
+                      LOWORD(v3) = Actor::_403EB6(v15, v16, v21, v23);
+                      return v3;
+                    }
+LABEL_21:
+                    v5->uCurrentActionTime = 0;
+                    v5->uCurrentActionLength = 0;
+                    v5->uAIState = Dead;
+                    return pActors[v4].UpdateAnimation();
+                  }
+                  v24 = v5->pMonsterInfo.uSpellSkillAndMastery2;
+                  v22 = 3;
+                  v17 = v5->pMonsterInfo.uSpell2ID;
+                }
+                else
+                {
+                  v24 = v5->pMonsterInfo.uSpellSkillAndMastery1;
+                  v22 = 2;
+                  v17 = v5->pMonsterInfo.uSpell1ID;
+                }
+                Actor::_404AC7(v4, &a4, v17, v22, v24);
+LABEL_25:
+                v16 = a2a;
+                v23 = &a4;
+                v21 = 0;
+                v15 = v4;
+                goto LABEL_26;
+              }
+              v18 = v5->pMonsterInfo.uMissleAttack2Type;
+              v25 = 1;
+            }
+            else
+            {
+              v18 = v5->pMonsterInfo.uMissleAttack1Type;
+              v25 = 0;
+            }
+            Actor::_404874(v4, &a4, v18, v25);
+            goto LABEL_25;
+          }
+        }
+      }
+    }
+  }
+  return v3;
+}
+// 50FE08: using guessed type stru298 stru_50FE08;
+
+//----- (0040680F) --------------------------------------------------------
+__int16 stru262_TurnBased::_40680F(int a2)
+{
+  TurnBased_QueueElem *v2; // eax@1
+  TurnBased_QueueElem *v3; // eax@1
+  TurnBased_QueueElem *v4; // edi@2
+  Actor *v5; // ebx@2
+  unsigned int *v6; // esi@7
+  AIDirection *v7; // esi@10
+  int v8; // eax@10
+  unsigned int v9; // ecx@10
+  signed int v10; // eax@13
+  unsigned __int8 v11; // sf@19
+  unsigned __int8 v12; // of@19
+  int v13; // esi@29
+  bool v14; // eax@29
+  unsigned __int8 v15; // cl@33
+  AIDirection a3; // [sp+Ch] [bp-44h]@10
+  AIDirection v18; // [sp+28h] [bp-28h]@10
+  int a2a; // [sp+44h] [bp-Ch]@2
+  unsigned int v20; // [sp+48h] [bp-8h]@10
+  TurnBased_QueueElem *v21; // [sp+4Ch] [bp-4h]@1
+  signed int v22; // [sp+58h] [bp+8h]@10
+
+  v2 = (TurnBased_QueueElem *)((char *)this + 16 * (a2 + 2));
+  v21 = v2;
+  v2->uActionLength = 0;
+  v3 = (TurnBased_QueueElem *)v2->uPackedID;
+  if ( (unsigned __int8)v3 & 3 )
+  {
+    v3 = (TurnBased_QueueElem *)((signed int)v3 >> 3);
+    v4 = v3;
+    a2a = (int)v3;
+    v5 = &pActors[(int)v3];
+    LOWORD(v3) = v5->uAIState;
+    if ( (short)v3 != 5 )
+    {
+      if ( (short)v3 != 4 && (short)v3 != 11 && (short)v3 != 19 && (short)v3 != 17 )
+      {
+        v6 = (unsigned int *)&dword_4F6E08[(int)v4];
+        Actor::_401221((unsigned int)v4, &dword_4F6E08[(int)v4], 1u);
+        if ( v5->pMonsterInfo.uHostilityType && !*v6 )
+          v5->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+        v22 = *v6;
+        v7 = Actor::GetDirectionInfo(8 * (int)v4 | 3, *v6, &a3, 0);
+        v8 = v5->uActorRadius;
+        memcpy(&a3, v7, sizeof(a3));
+        memcpy(&v18, &a3, sizeof(v18));
+        v9 = a3.uDistance - v8;
+        v20 = a3.uDistance - v8;
+        if ( ((a3.uDistance - v8) & 0x80000000u) != 0 )
+        {
+          v9 = 0;
+          v20 = 0;
+        }
+        if ( (v22 & 7) == 3 )
+          v10 = (unsigned __int8)*(&byte_5C8D1A[89
+                                              * (pMonsterStats->pInfos[pActors[v22 >> 3].pMonsterInfo.uID].uID - 1)
+                                              / 3]
+                                 + (v5->pMonsterInfo.uID - 1) / 3);
+        else
+          v10 = 4;
+        if ( v10 == 1 )
+        {
+          if ( (double)(signed int)v20 < 307.2 )
+            goto LABEL_25;
+        }
+        else
+        {
+          if ( v10 == 2 )
+          {
+            v12 = __OFSUB__(v9, 1024);
+            v11 = ((v9 - 1024) & 0x80000000u) != 0;
+          }
+          else
+          {
+            if ( v10 == 3 )
+            {
+              v12 = __OFSUB__(v9, 2560);
+              v11 = ((v9 - 2560) & 0x80000000u) != 0;
+            }
+            else
+            {
+              if ( v10 != 4 )
+                goto LABEL_26;
+              v12 = __OFSUB__(v9, 5120);
+              v11 = ((v9 - 5120) & 0x80000000u) != 0;
+            }
+          }
+          if ( v11 ^ v12 )
+          {
+LABEL_25:
+            v5->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Long;
+            goto LABEL_26;
+          }
+        }
+LABEL_26:
+        if ( v5->pMonsterInfo.uHostilityType != 4 || !v22 || (signed int)v9 >= 5120 )
+        {
+          v13 = a2a;
+          goto LABEL_47;
+        }
+        v13 = a2a;
+        v14 = stru_50C198.special_ability_use_check(v5, a2a);
+        if ( v14 == 1 )
+        {
+          if ( v5->pMonsterInfo.uMissleAttack2Type )
+          {
+            Actor::_40368B(v13, v22, &v18);
+            goto LABEL_43;
+          }
+        }
+        else
+        {
+          if ( v14 > 1 && v14 <= 3 )
+          {
+            if ( v14 == 2 )
+              v15 = v5->pMonsterInfo.uSpell1ID;
+            else
+              v15 = v5->pMonsterInfo.uSpell2ID;
+            if ( v15 )
+            {
+              if ( v14 == 2 )
+                Actor::_403854(v13, v22, &v18);
+              else
+                Actor::_403A60(v13, v22, &v18);
+              goto LABEL_43;
+            }
+            goto LABEL_44;
+          }
+          if ( v5->pMonsterInfo.uMissleAttack1Type )
+          {
+            Actor::_403476(v13, v22, &v18);
+LABEL_43:
+            v3 = v21;
+            v21->field_C = 1;
+LABEL_48:
+            v3->uActionLength = v5->uCurrentActionLength;
+            return (signed __int16)v3;
+          }
+        }
+LABEL_44:
+        if ( (double)(signed int)v20 < 307.2 )
+        {
+          Actor::_403C6C(v13, v22, &v18);
+          v3 = v21;
+          v21->field_C = 3;
+          goto LABEL_48;
+        }
+LABEL_47:
+        Actor::_403EB6(v13, v22, 0x40u, &v18);
+        v3 = v21;
+        v21->field_C = 0;
+        goto LABEL_48;
+      }
+    }
+  }
+  return (signed __int16)v3;
+}
+
+//----- (00406A63) --------------------------------------------------------
+void stru262_TurnBased::_406A63()
+{
+  stru262_TurnBased *v1; // ebx@1
+  int v2; // esi@1
+  unsigned __int8 v3; // zf@1
+  unsigned __int8 v4; // sf@1
+  signed int v5; // ecx@4
+  AIDirection a3; // [sp+8h] [bp-44h]@5
+  AIDirection v7; // [sp+24h] [bp-28h]@5
+  unsigned int v8; // [sp+40h] [bp-Ch]@5
+  signed int a2; // [sp+44h] [bp-8h]@1
+  TurnBased_QueueElem *v10; // [sp+48h] [bp-4h]@2
+
+  v1 = this;
+  v2 = 0;
+  this->field_8 = 64;
+  dword_50C994 = 0;
+  uActiveCharacter = 0;
+  v3 = this->uActorQueueSize == 0;
+  v4 = this->uActorQueueSize < 0;
+  a2 = 0;
+  if ( !(v4 | v3) )
+  {
+    v10 = this->pQueue;
+    while ( 1 )
+    {
+      v5 = v10->uPackedID;
+      if ( (v10->uPackedID & 7) == 3 )
+      {
+        v8 = dword_4F6E08[v5 >> 3];
+        memcpy(&v7, Actor::GetDirectionInfo(v5, v8, &a3, v2), sizeof(v7));
+        if ( !v1->_406D10(a2) )
+          Actor::_403EB6(v10->uPackedID >> 3, v8, 0x20u, &v7);
+      }
+      ++a2;
+      ++v10;
+      if ( a2 >= v1->uActorQueueSize )
+        break;
+      v2 = 0;
+    }
+  }
+}
+// 50C994: using guessed type int dword_50C994;
+
+//----- (00406AFE) --------------------------------------------------------
+void stru262_TurnBased::_406AFE()
+{
+  stru262_TurnBased *v1; // edi@1
+  TurnBased_QueueElem *v2; // ebx@2
+  int v3; // esi@4
+  int v4; // ecx@5
+  AIDirection a3; // [sp+4h] [bp-48h]@5
+  AIDirection v6; // [sp+20h] [bp-2Ch]@5
+  stru262_TurnBased *v7; // [sp+3Ch] [bp-10h]@1
+  unsigned int v8; // [sp+40h] [bp-Ch]@4
+  unsigned int v9; // [sp+44h] [bp-8h]@5
+  int v10; // [sp+48h] [bp-4h]@1
+
+  v10 = 0;
+  v1 = this;
+  v7 = this;
+  if ( this->uActorQueueSize > 0 )
+  {
+    v2 = this->pQueue;
+    do
+    {
+      if ( (v2->uPackedID & 7) == 3 )
+      {
+        v3 = v2->uPackedID >> 3;
+        v8 = v3;
+        if ( pActors[v3].CanAct() )
+        {
+          v4 = v2->uPackedID;
+          v9 = dword_4F6E08[v3];
+          memcpy(&v6, Actor::GetDirectionInfo(v4, v9, &a3, 0), sizeof(v6));
+          Actor::_403EB6(v8, v9, 0x20u, &v6);
+          v2->field_C = 0;
+          v2->uActionLength = 0;
+          v1 = v7;
+        }
+      }
+      ++v10;
+      ++v2;
+    }
+    while ( v10 < v1->uActorQueueSize );
+  }
+  v1->field_4 = 2;
+  v1->field_8 = 100;
+}
+
+//----- (00406B9F) --------------------------------------------------------
+int stru262_TurnBased::_406B9F()
+{
+  signed int result; // eax@1
+  unsigned __int8 v2; // zf@1
+  unsigned __int8 v3; // sf@1
+  int v4; // esi@4
+  unsigned int v5; // esi@5
+  Actor *v6; // ebx@5
+  unsigned __int16 v7; // cx@15
+  AIDirection a3; // [sp+0h] [bp-50h]@15
+  AIDirection v9; // [sp+1Ch] [bp-34h]@15
+  signed int a1; // [sp+38h] [bp-18h]@4
+  stru262_TurnBased *thisa; // [sp+3Ch] [bp-14h]@1
+  unsigned int v12; // [sp+40h] [bp-10h]@5
+  unsigned int v13; // [sp+44h] [bp-Ch]@8
+  TurnBased_QueueElem *v14; // [sp+48h] [bp-8h]@2
+  signed int a2; // [sp+4Ch] [bp-4h]@1
+
+  result = 0;
+  thisa = this;
+  v2 = this->uActorQueueSize == 0;
+  v3 = this->uActorQueueSize < 0;
+  a2 = 0;
+  if ( !(v3 | v2) )
+  {
+    v14 = this->pQueue;
+    while ( 1 )
+    {
+      v4 = v14->uPackedID;
+      a1 = v14->uPackedID;
+      if ( (a1 & 7) != 4 )
+      {
+        v5 = v4 >> 3;
+        v12 = v5;
+        v6 = &pActors[v5];
+        if ( SHIDWORD(v6->pActorBuffs[5].uExpireTime) < result
+          || SHIDWORD(v6->pActorBuffs[5].uExpireTime) <= result && LODWORD(v6->pActorBuffs[5].uExpireTime) <= result )
+          v13 = result;
+        else
+          v13 = 1;
+        if ( SHIDWORD(v6->pActorBuffs[6].uExpireTime) >= result
+          && (SHIDWORD(v6->pActorBuffs[6].uExpireTime) > result || LODWORD(v6->pActorBuffs[6].uExpireTime) > result) )
+          result = 1;
+        if ( !(v13 | result | v6->uAIState == 5 | v6->uAIState == 11 | v6->uAIState == 19) )
+        {
+          v13 = dword_4F6E08[v5];
+          memcpy(&v9, Actor::GetDirectionInfo(a1, v13, &a3, 0), sizeof(v9));
+          v7 = v6->uAIState;
+          if ( v7 == 6 || v7 == 1 )
+          {
+            if ( (double)(signed int)v9.uDistance < 307.2 )
+              goto LABEL_26;
+          }
+          v6->uCurrentActionTime += pEventTimer->uTimeElapsed;
+          if ( (signed int)v6->uCurrentActionTime > v6->uCurrentActionLength )
+          {
+            if ( v7 == 4 )
+            {
+              v6->uCurrentActionTime = 0;
+              v6->uCurrentActionLength = 0;
+              v6->uAIState = Dead;
+              v6->UpdateAnimation();
+            }
+            if ( !thisa->_406D10(a2) )
+LABEL_26:
+              Actor::_403EB6(v12, v13, 0x20u, &v9);
+          }
+        }
+      }
+      ++a2;
+      result = (signed int)thisa;
+      ++v14;
+      if ( a2 >= thisa->uActorQueueSize )
+        break;
+      result = 0;
+    }
+  }
+  return result;
+}
+
+//----- (00406D10) --------------------------------------------------------
+bool stru262_TurnBased::_406D10(signed int a2)
+{
+  int v2; // ecx@1
+  int v3; // ecx@2
+  Actor *v4; // ebx@2
+  unsigned __int16 v5; // dx@2
+  int *v6; // esi@7
+  TurnBased_QueueElem *v7; // edi@7
+  int v8; // eax@7
+  AIDirection *v9; // esi@10
+  int v10; // eax@10
+  unsigned int v11; // ecx@10
+  unsigned __int8 v12; // al@12
+  unsigned __int8 v13; // sf@16
+  unsigned __int8 v14; // of@16
+  unsigned int v15; // edx@22
+  unsigned int v16; // ecx@23
+  TurnBased_QueueElem *v17; // eax@25
+  double v18; // st7@33
+  double v19; // st6@33
+  int v21; // [sp-8h] [bp-5Ch]@23
+  int v22; // [sp-8h] [bp-5Ch]@26
+  AIDirection *v23; // [sp-4h] [bp-58h]@23
+  int v24; // [sp-4h] [bp-58h]@26
+  AIDirection a3; // [sp+Ch] [bp-48h]@10
+  AIDirection pDir; // [sp+28h] [bp-2Ch]@10
+  int v27; // [sp+44h] [bp-10h]@33
+  unsigned int v28; // [sp+48h] [bp-Ch]@10
+  TurnBased_QueueElem *v29; // [sp+4Ch] [bp-8h]@7
+  unsigned int uActorID; // [sp+50h] [bp-4h]@2
+  unsigned int a2a; // [sp+5Ch] [bp+8h]@7
+
+  v2 = *(&this->field_0 + 4 * (a2 + 2));
+  if ( (v2 & 7) == 4 )
+    return 0;
+  v3 = v2 >> 3;
+  uActorID = v3;
+  v4 = &pActors[v3];
+  v5 = v4->uAIState;
+  if ( v5 == 5 || v5 == 4 || v5 == 11 || v5 == 19 || v5 == 17 )
+    return 1;
+  v6 = &dword_4F6E08[v3];
+  v7 = &pTurnEngine->pQueue[a2];
+  v8 = *v6;
+  v29 = &pTurnEngine->pQueue[a2];
+  a2a = v8;
+  Actor::_401221(v3, &dword_4F6E08[v3], 1u);
+  if ( v4->pMonsterInfo.uHostilityType && !*v6 )
+    v4->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+  v9 = Actor::GetDirectionInfo(v7->uPackedID, a2a, &a3, 0);
+  v10 = v4->uActorRadius;
+  memcpy(&a3, v9, sizeof(a3));
+  memcpy(&pDir, &a3, sizeof(pDir));
+  v11 = a3.uDistance - v10;
+  v28 = a3.uDistance - v10;
+  if ( ((a3.uDistance - v10) & 0x80000000u) != 0 )
+  {
+    v11 = 0;
+    v28 = 0;
+  }
+  v12 = v4->pMonsterInfo.uHostilityType;
+  if ( v12 == 1 )
+  {
+    if ( (double)(signed int)v28 >= 307.2 )
+      goto LABEL_21;
+LABEL_20:
+    v4->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Long;
+    goto LABEL_21;
+  }
+  if ( v12 == 2 )
+  {
+    v14 = __OFSUB__(v11, 1024);
+    v13 = ((v11 - 1024) & 0x80000000u) != 0;
+  }
+  else
+  {
+    if ( v12 != 3 )
+      goto LABEL_21;
+    v14 = __OFSUB__(v11, 2560);
+    v13 = ((v11 - 2560) & 0x80000000u) != 0;
+  }
+  if ( v13 ^ v14 )
+    goto LABEL_20;
+LABEL_21:
+  if ( (signed __int64)v4->pActorBuffs[4].uExpireTime > 0 )
+  {
+    v15 = a2a;
+    if ( (signed int)v11 < 10240 )
+    {
+      v23 = &pDir;
+      v16 = uActorID;
+      v21 = 0;
+      goto LABEL_24;
+    }
+    v24 = 0;
+    v22 = 1024;
+    goto LABEL_58;
+  }
+  if ( v4->pMonsterInfo.uHostilityType != 4 )
+    goto LABEL_46;
+  if ( !(v4->uAttributes & 0x020000) || v4->pMonsterInfo.uAIType == 1 )
+  {
+    if ( v4->pMonsterInfo.uAIType == 1 )
+      goto LABEL_36;
+    if ( v4->pMonsterInfo.uAIType == 2 )
+    {
+      v27 = v4->sCurrentHP;
+      v18 = (double)v27;
+      v19 = (double)(signed int)v4->pMonsterInfo.uHP * 0.2;
+      goto LABEL_34;
+    }
+    if ( v4->pMonsterInfo.uAIType == 3 )
+    {
+      v27 = v4->sCurrentHP;
+      v18 = (double)v27;
+      v19 = (double)(signed int)v4->pMonsterInfo.uHP * 0.1;
+LABEL_34:
+      if ( v19 > v18 && (signed int)v11 < 10240 )
+      {
+LABEL_36:
+        v16 = uActorID;
+        v15 = a2a;
+        v23 = 0;
+        v21 = 32;
+        if ( v4->pMonsterInfo.uMovementType == 5 )
+        {
+          Actor::_403EB6(uActorID, a2a, 0x20u, 0);
+          goto LABEL_25;
+        }
+LABEL_24:
+        Actor::_402968(v16, v15, v21, v23);
+LABEL_25:
+        v17 = v29;
+        v29->field_C = 4;
+LABEL_60:
+        v17->uActionLength = v4->uCurrentActionLength;
+        return 1;
+      }
+      goto LABEL_39;
+    }
+  }
+LABEL_39:
+  if ( (double)(signed int)v28 < 307.2 )
+    return 0;
+  if ( (signed int)v11 < 5120 )
+  {
+    if ( v4->pMonsterInfo.uMissleAttack1Type && (signed int)v11 < 1024 )
+      Actor::_402AD7(uActorID, a2a, uActorID, 32, &pDir);
+    else
+      Actor::_40281C(uActorID, a2a, 32, &pDir, 307);
+    goto LABEL_59;
+  }
+LABEL_46:
+  if ( !v4->pMonsterInfo.uMovementType )
+  {
+    v24 = 32;
+    v22 = 1024;
+    goto LABEL_57;
+  }
+  if ( v4->pMonsterInfo.uMovementType == 1 )
+  {
+    v24 = 32;
+    v22 = 2560;
+    goto LABEL_57;
+  }
+  if ( v4->pMonsterInfo.uMovementType == 2 )
+  {
+    v24 = 32;
+    v22 = 5120;
+LABEL_57:
+    v15 = a2a;
+LABEL_58:
+    Actor::_4032B2(uActorID, v15, v22, v24);
+LABEL_59:
+    v17 = v29;
+    v29->field_C = 2;
+    goto LABEL_60;
+  }
+  if ( v4->pMonsterInfo.uMovementType == 4 )
+  {
+    Actor::_4032B2(uActorID, a2a, 10240, 32);
+    goto LABEL_53;
+  }
+  if ( v4->pMonsterInfo.uMovementType == 5 )
+  {
+    Actor::_403EB6(uActorID, a2a, 0x20u, 0);
+LABEL_53:
+    v17 = v29;
+    v29->field_C = 2;
+    goto LABEL_60;
+  }
+  return 1;
+}
+
+//----- (00406FA8) --------------------------------------------------------
+void stru262_TurnBased::_406FA8()
+{
+  unsigned __int8 v1; // zf@1
+  unsigned __int8 v2; // sf@1
+  TurnBased_QueueElem *v3; // edi@2
+  int v4; // eax@4
+  Actor *v5; // ebx@4
+  unsigned __int16 v6; // cx@4
+  unsigned int *v7; // edx@8
+  unsigned int v8; // esi@8
+  unsigned __int8 v9; // of@13
+  AIDirection a3; // [sp+Ch] [bp-6Ch]@8
+  AIDirection v11; // [sp+28h] [bp-50h]@8
+  AIDirection a4; // [sp+44h] [bp-34h]@8
+  stru262_TurnBased *v13; // [sp+60h] [bp-18h]@1
+  TurnBased_QueueElem *v14; // [sp+64h] [bp-14h]@2
+  int uActorID; // [sp+68h] [bp-10h]@4
+  unsigned int a2; // [sp+6Ch] [bp-Ch]@8
+  int v17; // [sp+70h] [bp-8h]@1
+  unsigned int v18; // [sp+74h] [bp-4h]@2
+
+  v17 = 0;
+  v1 = this->uActorQueueSize == 0;
+  v2 = this->uActorQueueSize < 0;
+  v13 = this;
+  if ( !(v2 | v1) )
+  {
+    v3 = this->pQueue;
+    v18 = (char *)&pTurnEngine - (char *)this;
+    v14 = this->pQueue;
+    do
+    {
+      if ( (v3->uPackedID & 7) != 4 )
+      {
+        v4 = v3->uPackedID >> 3;
+        uActorID = v4;
+        v5 = &pActors[v4];
+        v6 = v5->uAIState;
+        if ( v6 != 5 )
+        {
+          if ( v6 != 11 )
+          {
+            if ( v6 != 19 )
+            {
+              if ( v6 != 17 )
+              {
+                v7 = (unsigned int *)&dword_4F6E08[v4];
+                a2 = *v7;
+                v8 = a2;
+                Actor::_401221(v4, (int *)v7, 1u);
+                memcpy(&v11, Actor::GetDirectionInfo(*(int *)((char *)&v3->uPackedID + v18), v8, &a3, 0), sizeof(v11));
+                memcpy(&a4, &v11, sizeof(a4));
+                v5->uCurrentActionTime += pMiscTimer->uTimeElapsed;
+                if ( (signed int)v5->uCurrentActionTime >= v5->uCurrentActionLength )
+                {
+                  if (v5->uAIState == Dying)
+                  {
+                    v5->uCurrentActionTime = 0;
+                    v5->uCurrentActionLength = 0;
+                    v5->uAIState = Dead;
+                    v5->UpdateAnimation();
+                    return;
+                  }
+                  if ( rand() % 2 )
+                    Actor::_403EB6(uActorID, a2, 0x40u, &a4);
+                  else
+                    Actor::_402F87(uActorID, a2, &a4);
+                }
+              }
+            }
+          }
+        }
+      }
+      ++v17;
+      v3 = v14 + 1;
+      v9 = __OFSUB__(v17, v13->uActorQueueSize);
+      v2 = v17 - v13->uActorQueueSize < 0;
+      ++v14;
+    }
+    while ( v2 ^ v9 );
+  }
+}
+
+//----- (004070EF) --------------------------------------------------------
+bool __fastcall sub_4070EF_prolly_collide_objects(unsigned int uObjID, unsigned int uObj2ID)
+{
+  signed int v2; // eax@1
+  unsigned int v3; // ecx@1
+  signed int v4; // esi@1
+  int v5; // ecx@2
+  signed int v6; // eax@4
+  int v7; // eax@4
+  float v8; // ST24_4@5
+  double v9; // ST18_8@5
+  signed int v10; // eax@6
+  int v11; // ecx@6
+  signed int v12; // eax@7
+  int v13; // esi@7
+  int v14; // esi@8
+  int v15; // esi@9
+  signed int v16; // eax@11
+  int v17; // edi@11
+  int v18; // esi@11
+  int v19; // eax@13
+  float v20; // ST24_4@14
+  double v21; // ST18_8@14
+  signed int v22; // eax@15
+  int v23; // ebx@16
+  signed int v24; // ecx@16
+  int v25; // eax@18
+  int v26; // eax@28
+  BLVSector *v27; // edx@31
+  int v28; // ecx@31
+  BLVFace *v29; // ebx@32
+  Vec3_short_ *v30; // esi@32
+  int v31; // eax@32
+  int v32; // ST50_4@44
+  int v33; // ST54_4@44
+  int v34; // eax@44
+  char v35; // zf@44
+  int v36; // edi@44
+  int v37; // eax@45
+  signed int v38; // esi@45
+  int v39; // ST4C_4@49
+  signed __int64 v40; // qtt@50
+  __int16 v42; // bx@58
+  int v43; // [sp-8h] [bp-70h]@11
+  int v44; // [sp-4h] [bp-6Ch]@11
+  int v45; // [sp+Ch] [bp-5Ch]@32
+  __int16 v46; // [sp+10h] [bp-58h]@32
+  int v47; // [sp+18h] [bp-50h]@20
+  int v48; // [sp+1Ch] [bp-4Ch]@20
+  int v49; // [sp+20h] [bp-48h]@20
+  int v50; // [sp+24h] [bp-44h]@16
+  signed int v51; // [sp+24h] [bp-44h]@27
+  signed int v52; // [sp+28h] [bp-40h]@26
+  signed int v53; // [sp+2Ch] [bp-3Ch]@23
+  signed int v54; // [sp+30h] [bp-38h]@22
+  signed int v55; // [sp+34h] [bp-34h]@21
+  signed int v56; // [sp+38h] [bp-30h]@20
+  signed int v57; // [sp+3Ch] [bp-2Ch]@28
+  int v58; // [sp+44h] [bp-24h]@50
+  int v59; // [sp+48h] [bp-20h]@44
+  int v60; // [sp+50h] [bp-18h]@11
+  signed int v61; // [sp+50h] [bp-18h]@31
+  int v62; // [sp+54h] [bp-14h]@16
+  int v63; // [sp+58h] [bp-10h]@4
+  int v64; // [sp+5Ch] [bp-Ch]@4
+  int v65; // [sp+60h] [bp-8h]@4
+  int v66; // [sp+64h] [bp-4h]@7
+
+  v2 = (signed int)uObjID >> 3;
+  v3 = (uObjID & 7) - 2;
+  v4 = uObj2ID;
+  if ( v3 )
+  {
+    v5 = v3 - 1;
+    if ( v5 )
+    {
+      if ( v5 != 2 )
+        return 0;
+      v6 = v2;
+      v63 = pLevelDecorations[v6].vPosition.x;
+      v64 = pLevelDecorations[v6].vPosition.y;
+      v65 = pLevelDecorations[v6].vPosition.z;
+      v7 = pIndoor->GetSector(v63, v64, v65);
+    }
+    else
+    {
+      v63 = pActors[v2].vPosition.x;
+      v64 = pActors[v2].vPosition.y;
+      v8 = (double)pActors[v2].uActorHeight * 0.69999999;
+      v9 = v8 + 6.7553994e15;
+      v65 = LODWORD(v9) + pActors[v2].vPosition.z;
+      v7 = pActors[v2].uSectorID;
+    }
+  }
+  else
+  {
+    v10 = v2;
+    v63 = pLayingItems[v10].vPosition.x;
+    v64 = pLayingItems[v10].vPosition.y;
+    v11 = pLayingItems[v10].vPosition.z;
+    v7 = pLayingItems[v10].uSectorID;
+    v65 = v11;
+  }
+  v66 = v7;
+  v12 = v4 >> 3;
+  v13 = (v4 & 7) - 2;
+  if ( v13 )
+  {
+    v14 = v13 - 1;
+    if ( v14 )
+    {
+      v15 = v14 - 1;
+      if ( v15 )
+      {
+        if ( v15 != 1 )
+          return 0;
+        v16 = v12;
+        v17 = pLevelDecorations[v16].vPosition.z;
+        v18 = pLevelDecorations[v16].vPosition.x;
+        v44 = pLevelDecorations[v16].vPosition.z;
+        v60 = pLevelDecorations[v16].vPosition.y;
+        v43 = pLevelDecorations[v16].vPosition.y;
+      }
+      else
+      {
+        v18 = pParty->vPosition.x;
+        v17 = pParty->sEyelevel + pParty->vPosition.z;
+        v60 = pParty->vPosition.y;
+        v44 = pParty->sEyelevel + pParty->vPosition.z;
+        v43 = pParty->vPosition.y;
+      }
+      v19 = pIndoor->GetSector(v18, v43, v44);
+    }
+    else
+    {
+      v60 = pActors[v12].vPosition.y;
+      v18 = pActors[v12].vPosition.x;
+      v20 = (double)pActors[v12].uActorHeight * 0.69999999;
+      v21 = v20 + 6.7553994e15;
+      v17 = LODWORD(v21) + pActors[v12].vPosition.z;
+      v19 = pActors[v12].uSectorID;
+    }
+  }
+  else
+  {
+    v22 = v12;
+    v18 = pLayingItems[v22].vPosition.x;
+    v17 = pLayingItems[v22].vPosition.z;
+    v60 = pLayingItems[v22].vPosition.y;
+    v19 = pLayingItems[v22].uSectorID;
+  }
+  v62 = v19;
+  v23 = v18 - v63;
+  v50 = v17 - v65;
+  v24 = sub_452A9E(v23 * v23 + (v60 - v64) * (v60 - v64) + v50 * v50);
+  if ( v24 > 5120 )
+    return 0;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    return 1;
+  v25 = 65536;
+  if ( v24 )
+    v25 = 65536 / v24;
+  v49 = v23 * v25;
+  v47 = v50 * v25;
+  v48 = (v60 - v64) * v25;
+  v56 = v63;
+  if ( v63 < v18 )
+  {
+    v55 = v18;
+  }
+  else
+  {
+    v56 = v18;
+    v55 = v63;
+  }
+  v54 = v64;
+  if ( v64 < v60 )
+  {
+    v53 = v60;
+  }
+  else
+  {
+    v54 = v60;
+    v53 = v64;
+  }
+  v52 = v65;
+  if ( v65 < v17 )
+  {
+    v51 = v17;
+  }
+  else
+  {
+    v52 = v17;
+    v51 = v65;
+  }
+  v57 = 0;
+  v26 = v66;
+  while ( 2 )
+  {
+    if ( v26 == v62 )
+      return 1;
+    if ( v57 >= 30 || (v27 = pIndoor->pSectors, v28 = v66, v61 = 0, pIndoor->pSectors[v66].uNumPortals <= 0) )
+      break;
+    while ( 1 )
+    {
+      v29 = &pIndoor->pFaces[v27[v28].pPortals[v61]];
+      v30 = &pIndoor->pVertices[*v29->pVertexIDs];
+      v45 = *(int *)&v30->x;
+      v46 = v30->z;
+      v31 = v29->pFacePlane_old.vNormal.z * (v46 - v65)
+          + v29->pFacePlane_old.vNormal.y * (SHIWORD(v45) - v64)
+          + v29->pFacePlane_old.vNormal.x * ((signed __int16)v45 - v63);
+      if ( v66 != v29->uSectorID )
+        v31 = -v31;
+      if ( v31 >= 0 && (signed __int16)v45 != v63 && SHIWORD(v45) != v64 && v46 != v65
+        || v56 > v29->pBounding.x2
+        || v55 < v29->pBounding.x1
+        || v54 > v29->pBounding.y2
+        || v53 < v29->pBounding.y1
+        || v52 > v29->pBounding.z2
+        || v51 < v29->pBounding.z1 )
+        goto LABEL_54;
+      v32 = (unsigned __int64)(v49 * (signed __int64)v29->pFacePlane_old.vNormal.x) >> 16;
+      v33 = (unsigned __int64)(v47 * (signed __int64)v29->pFacePlane_old.vNormal.z) >> 16;
+      v34 = (unsigned __int64)(v48 * (signed __int64)v29->pFacePlane_old.vNormal.y) >> 16;
+      v35 = v32 + v33 + v34 == 0;
+      v36 = v32 + v33 + v34;
+      v59 = v32 + v33 + v34;
+      if ( v35 )
+        goto LABEL_53;
+      v37 = v65 * v29->pFacePlane_old.vNormal.z;
+      v38 = -(v29->pFacePlane_old.dist + v37 + v63 * v29->pFacePlane_old.vNormal.x + v64 * v29->pFacePlane_old.vNormal.y);
+      if ( v36 <= 0 )
+        break;
+      if ( v29->pFacePlane_old.dist + v37 + v63 * v29->pFacePlane_old.vNormal.x + v64 * v29->pFacePlane_old.vNormal.y <= 0 )
+        goto LABEL_49;
+LABEL_53:
+      v27 = pIndoor->pSectors;
+LABEL_54:
+      ++v61;
+      if ( v61 >= v27[v28].uNumPortals )
+        goto LABEL_55;
+    }
+    if ( v29->pFacePlane_old.dist + v37 + v63 * v29->pFacePlane_old.vNormal.x + v64 * v29->pFacePlane_old.vNormal.y < 0 )
+      goto LABEL_53;
+LABEL_49:
+    v39 = abs(-(v29->pFacePlane_old.dist
+              + v37
+              + v63 * v29->pFacePlane_old.vNormal.x
+              + v64 * v29->pFacePlane_old.vNormal.y)) >> 14;
+    if ( v39 > abs(v36)
+      || (LODWORD(v40) = v38 << 16, HIDWORD(v40) = v38 >> 16, v58 = v40 / v59, (signed int)(v40 / v59) < 0)
+      || !sub_4075DB(
+            v63 + ((signed int)(((unsigned __int64)(v58 * (signed __int64)v49) >> 16) + 32768) >> 16),
+            v64 + ((signed int)(((unsigned __int64)(v58 * (signed __int64)v48) >> 16) + 32768) >> 16),
+            v65 + ((signed int)(((unsigned __int64)(v58 * (signed __int64)v47) >> 16) + 32768) >> 16),
+            v29) )
+    {
+      v28 = v66;
+      goto LABEL_53;
+    }
+    if ( v29->uSectorID == v66 )
+      v42 = v29->uBackSectorID;
+    else
+      v42 = v29->uSectorID;
+    v26 = v42;
+    if ( v42 != v66 )
+    {
+      ++v57;
+      v66 = v42;
+      continue;
+    }
+    break;
+  }
+LABEL_55:
+  if ( v66 != v62 )
+    return 0;
+  return 1;
+}
+
+//----- (004075DB) --------------------------------------------------------
+bool __fastcall sub_4075DB(int a1, int a2, int a3, BLVFace *a4)
+{
+  BLVFace *v4; // eax@1
+  unsigned int v5; // esi@1
+  signed int v6; // esi@2
+  char v7; // zf@2
+  int v8; // edi@2
+  Vec3_short_ *v9; // ecx@3
+  int v10; // edx@4
+  signed int v11; // esi@7
+  Vec3_short_ *v12; // ecx@8
+  int v13; // edx@9
+  signed int v14; // esi@11
+  Vec3_short_ *v15; // ecx@12
+  int v16; // edx@13
+  int v17; // eax@14
+  bool v18; // esi@14
+  int v19; // ecx@14
+  int v20; // ecx@16
+  int v21; // edx@16
+  int v22; // eax@17
+  signed int v23; // ebx@18
+  int v24; // esi@20
+  signed int v25; // eax@22
+  signed __int64 v26; // qtt@22
+  bool result; // eax@25
+  int v28; // [sp+8h] [bp-14h]@14
+  int v29; // [sp+10h] [bp-Ch]@14
+  signed int a3a; // [sp+24h] [bp+8h]@14
+  int a4a; // [sp+28h] [bp+Ch]@2
+
+  v4 = a4;
+  v5 = a4->uAttributes;
+  if ( v5 & 0x100 )
+  {
+    v6 = 0;
+    v7 = a4->uNumVertices == 0;
+    a4a = a1;
+    v8 = a2;
+    if ( !v7 )
+    {
+      v9 = pIndoor->pVertices;
+      do
+      {
+        dword_4F5D98_xs[v6] = v9[v4->pVertexIDs[v6]].x;
+        v10 = v4->pVertexIDs[v6++];
+        dword_4F5CC4_ys[v6] = v9[v10].y;
+      }
+      while ( v6 < v4->uNumVertices );
+    }
+  }
+  else
+  {
+    v8 = a3;
+    if ( v5 & 0x200 )
+    {
+      v11 = 0;
+      v7 = a4->uNumVertices == 0;
+      a4a = a1;
+      if ( !v7 )
+      {
+        v12 = pIndoor->pVertices;
+        do
+        {
+          dword_4F5D98_xs[v11] = v12[v4->pVertexIDs[v11]].x;
+          v13 = v4->pVertexIDs[v11++];
+          dword_4F5CC4_ys[v11] = v12[v13].z;
+        }
+        while ( v11 < v4->uNumVertices );
+      }
+    }
+    else
+    {
+      v14 = 0;
+      v7 = a4->uNumVertices == 0;
+      a4a = a2;
+      if ( !v7 )
+      {
+        v15 = pIndoor->pVertices;
+        do
+        {
+          dword_4F5D98_xs[v14] = v15[v4->pVertexIDs[v14]].y;
+          v16 = v4->pVertexIDs[v14++];
+          dword_4F5CC4_ys[v14] = v15[v16].z;
+        }
+        while ( v14 < v4->uNumVertices );
+      }
+    }
+  }
+  v17 = v4->uNumVertices;
+  a3a = 0;
+  dword_4F5D98_xs[v17] = dword_4F5D98_xs[0];
+  dword_4F5CC4_ys[v17 + 1] = dword_4F5CC4_ys[1];
+  v28 = v17;
+  v18 = dword_4F5CC4_ys[1] >= v8;
+  v19 = 0;
+  v29 = 0;
+  if ( v17 <= 0 )
+    goto LABEL_29;
+  do
+  {
+    if ( a3a >= 2 )
+      break;
+    v20 = v19;
+    v21 = dword_4F5CC4_ys[v20 + 2];
+    if ( v18 ^ v21 >= v8 )
+    {
+      v22 = dword_4F5D98_xs[v20 + 1];
+      if ( v22 >= a4a )
+        v23 = 0;
+      else
+        v23 = 2;
+      v24 = v23 | dword_4F5D98_xs[v20] < a4a;
+      if ( v24 != 3 )
+      {
+        if ( !v24
+          || (v25 = v22 - dword_4F5D98_xs[v20],
+              LODWORD(v26) = v25 << 16,
+              HIDWORD(v26) = v25 >> 16,
+              dword_4F5D98_xs[v20]
+            + ((signed int)(((unsigned __int64)(v26
+                                              / (v21 - dword_4F5CC4_ys[v20 + 1])
+                                              * ((v8 - dword_4F5CC4_ys[v20 + 1]) << 16)) >> 16)
+                          + 32768) >> 16) >= a4a) )
+          ++a3a;
+      }
+    }
+    v18 = v21 >= v8;
+    v19 = v29++ + 1;
+  }
+  while ( v29 < v28 );
+  result = 1;
+  if ( a3a != 1 )
+LABEL_29:
+    result = 0;
+  return result;
+}
+
+//----- (004077F1) --------------------------------------------------------
+bool __fastcall sub_4077F1(int a1, int a2, int a3, ODMFace *a4, BSPVertexBuffer *a5)
+{
+  ODMFace *v5; // eax@1
+  unsigned int v6; // esi@1
+  signed int v7; // edi@1
+  char v8; // zf@2
+  unsigned __int16 *v9; // edx@3
+  int v10; // ecx@4
+  unsigned __int16 *v11; // edx@8
+  int v12; // ecx@9
+  int v13; // edx@12
+  int v14; // ecx@13
+  int v15; // esi@14
+  bool v16; // edi@14
+  int v17; // ecx@16
+  int v18; // edx@16
+  int v19; // eax@17
+  signed int v20; // ebx@18
+  int v21; // edi@20
+  signed int v22; // eax@22
+  signed __int64 v23; // qtt@22
+  bool result; // eax@25
+  int v25; // [sp+14h] [bp-8h]@14
+  int a4a; // [sp+28h] [bp+Ch]@2
+  signed int a5a; // [sp+2Ch] [bp+10h]@14
+
+  v5 = a4;
+  v6 = a4->uAttributes;
+  v7 = 0;
+  if ( v6 & 0x100 )
+  {
+    v8 = a4->uNumVertices == 0;
+    a4a = a1;
+    a3 = a2;
+    if ( !v8 )
+    {
+      v9 = v5->pVertexIDs;
+      do
+      {
+        ++v7;
+        dword_4F5BF4_xs[v7] = a5->pVertices[*v9].x;
+        v10 = *v9;
+        ++v9;
+        dword_4F5B24_ys[v7] = a5->pVertices[v10].y;
+      }
+      while ( v7 < v5->uNumVertices );
+    }
+  }
+  else
+  {
+    if ( v6 & 0x200 )
+    {
+      v8 = a4->uNumVertices == 0;
+      a4a = a1;
+      if ( !v8 )
+      {
+        v11 = v5->pVertexIDs;
+        do
+        {
+          ++v7;
+          dword_4F5BF4_xs[v7] = a5->pVertices[*v11].x;
+          v12 = *v11;
+          ++v11;
+          dword_4F5B24_ys[v7] = a5->pVertices[v12].z;
+        }
+        while ( v7 < v5->uNumVertices );
+      }
+    }
+    else
+    {
+      v8 = a4->uNumVertices == 0;
+      a4a = a2;
+      if ( !v8 )
+      {
+        v13 = (int)v5->pVertexIDs;
+        do
+        {
+          ++v7;
+          dword_4F5BF4_xs[v7] = a5->pVertices[*(short *)v13].y;
+          v14 = *(short *)v13;
+          v13 += 2;
+          dword_4F5B24_ys[v7] = a5->pVertices[v14].z;
+        }
+        while ( v7 < v5->uNumVertices );
+      }
+    }
+  }
+  v15 = v5->uNumVertices;
+  a5a = 0;
+  dword_4F5BF4_xs[v15 + 1] = dword_4F5BF4_xs[1];
+  dword_4F5B24_ys[v15 + 1] = dword_4F5B24_ys[1];
+  v25 = 0;
+  v16 = dword_4F5B24_ys[1] >= a3;
+  if ( v15 <= 0 )
+    goto LABEL_29;
+  do
+  {
+    if ( a5a >= 2 )
+      break;
+    v17 = v25;
+    v18 = dword_4F5B24_ys[v25 + 2];
+    if ( v16 ^ v18 >= a3 )
+    {
+      v19 = dword_4F5BF4_xs[v17 + 2];
+      if ( v19 >= a4a )
+        v20 = 0;
+      else
+        v20 = 2;
+      v21 = v20 | dword_4F5BF4_xs[v17 + 1] < a4a;
+      if ( v21 != 3 )
+      {
+        if ( !v21
+          || (v22 = v19 - dword_4F5BF4_xs[v17 + 1],
+              LODWORD(v23) = v22 << 16,
+              HIDWORD(v23) = v22 >> 16,
+              dword_4F5BF4_xs[v17 + 1]
+            + ((signed int)(((unsigned __int64)(v23
+                                              / (v18 - dword_4F5B24_ys[v17 + 1])
+                                              * ((a3 - dword_4F5B24_ys[v17 + 1]) << 16)) >> 16)
+                          + 32768) >> 16) >= a4a) )
+          ++a5a;
+      }
+    }
+    ++v25;
+    v16 = v18 >= a3;
+  }
+  while ( v25 < v15 );
+  result = 1;
+  if ( a5a != 1 )
+LABEL_29:
+    result = 0;
+  return result;
+}
+
+//----- (00407A1C) --------------------------------------------------------
+bool __fastcall sub_407A1C(int x, int z, int y, Vec3_int_ v)
+{
+  unsigned int v4; // esi@1
+  Vec3_int_ v5; // ST08_12@2
+  int v6; // edi@2
+  int v7; // ebx@2
+  int v8; // esi@2
+  signed int v9; // ecx@2
+  int v10; // eax@2
+  int v11; // ecx@4
+  int v12; // eax@4
+  int v13; // ebx@4
+  int v14; // edx@6
+  char *v15; // edi@16
+  ODMFace *v16; // esi@19
+  int v17; // ST34_4@25
+  int v18; // ST38_4@25
+  int v19; // eax@25
+  char v20; // zf@25
+  int v21; // ebx@25
+  int v22; // eax@26
+  signed int v23; // edi@26
+  int v24; // ST34_4@30
+  signed __int64 v25; // qtt@31
+  int v26; // eax@31
+  Vec3_int_ v27; // ST08_12@37
+  Vec3_int_ v28; // ST08_12@37
+  int v29; // edi@37
+  int v30; // ebx@37
+  int v31; // esi@37
+  signed int v32; // ecx@37
+  int v33; // eax@37
+  int v34; // ecx@39
+  int v35; // eax@39
+  int v36; // ebx@39
+  int v37; // edx@41
+  char *v38; // edi@51
+  ODMFace *v39; // esi@54
+  int v40; // ebx@60
+  int v41; // eax@61
+  signed int v42; // edi@61
+  signed __int64 v43; // qtt@66
+  int v44; // eax@66
+  Vec3_int_ v45; // ST08_12@73
+  int v46; // edi@73
+  int v47; // ebx@73
+  int v48; // esi@73
+  signed int v49; // ecx@73
+  int v50; // eax@73
+  int v51; // edx@75
+  int v52; // ecx@75
+  int v53; // eax@75
+  int v54; // ebx@75
+  int v55; // edi@77
+  int v56; // ecx@77
+  int v57; // eax@81
+  int v58; // esi@81
+  int v59; // eax@90
+  BLVSector *v60; // edx@90
+  int v61; // ecx@90
+  BLVFace *v62; // esi@91
+  int v63; // ST34_4@98
+  int v64; // ST30_4@98
+  int v65; // eax@98
+  int v66; // ebx@98
+  int v67; // eax@99
+  signed int v68; // edi@99
+  int v69; // ST2C_4@103
+  signed __int64 v70; // qtt@104
+  int v71; // eax@104
+  Vec3_int_ v72; // ST08_12@111
+  Vec3_int_ v73; // ST08_12@111
+  int v74; // edi@111
+  int v75; // ebx@111
+  int v76; // esi@111
+  signed int v77; // ecx@111
+  int v78; // eax@111
+  int v79; // edx@113
+  int v80; // ecx@113
+  int v81; // eax@113
+  int v82; // ebx@113
+  int v83; // edi@115
+  int v84; // ecx@115
+  int v85; // eax@119
+  int v86; // esi@119
+  int v87; // ecx@128
+  BLVSector *v88; // eax@128
+  int v89; // ecx@128
+  BLVFace *v90; // esi@129
+  int v91; // ebx@136
+  int v92; // eax@137
+  signed int v93; // edi@137
+  signed __int64 v94; // qtt@142
+  int v95; // eax@142
+  Vec3_int_ v97; // [sp-18h] [bp-94h]@1
+  int v98; // [sp-Ch] [bp-88h]@88
+  int v99; // [sp-Ch] [bp-88h]@126
+  int v100; // [sp-8h] [bp-84h]@88
+  int v101; // [sp-8h] [bp-84h]@126
+  int v102; // [sp-4h] [bp-80h]@88
+  int v103; // [sp-4h] [bp-80h]@126
+  int v104; // [sp+Ch] [bp-70h]@13
+  int v105; // [sp+Ch] [bp-70h]@48
+  int v106; // [sp+10h] [bp-6Ch]@18
+  int v107; // [sp+10h] [bp-6Ch]@98
+  int v108; // [sp+10h] [bp-6Ch]@104
+  int v109; // [sp+18h] [bp-64h]@25
+  int v110; // [sp+18h] [bp-64h]@31
+  int i; // [sp+18h] [bp-64h]@90
+  int v112; // [sp+18h] [bp-64h]@128
+  signed int v113; // [sp+20h] [bp-5Ch]@1
+  signed int v114; // [sp+24h] [bp-58h]@1
+  unsigned __int64 a4; // [sp+28h] [bp-54h]@1
+  unsigned int a4_8; // [sp+30h] [bp-4Ch]@1
+  int v117; // [sp+34h] [bp-48h]@4
+  int v118; // [sp+34h] [bp-48h]@39
+  int v119; // [sp+34h] [bp-48h]@75
+  int v120; // [sp+34h] [bp-48h]@113
+  int v121; // [sp+38h] [bp-44h]@4
+  int v122; // [sp+38h] [bp-44h]@39
+  int v123; // [sp+38h] [bp-44h]@76
+  int v124; // [sp+38h] [bp-44h]@114
+  int v125; // [sp+3Ch] [bp-40h]@4
+  int v126; // [sp+3Ch] [bp-40h]@39
+  int v127; // [sp+3Ch] [bp-40h]@77
+  int v128; // [sp+3Ch] [bp-40h]@115
+  int v129; // [sp+40h] [bp-3Ch]@11
+  int v130; // [sp+40h] [bp-3Ch]@46
+  int v131; // [sp+40h] [bp-3Ch]@78
+  int v132; // [sp+40h] [bp-3Ch]@116
+  int v133; // [sp+44h] [bp-38h]@10
+  int v134; // [sp+44h] [bp-38h]@45
+  int v135; // [sp+44h] [bp-38h]@81
+  int v136; // [sp+44h] [bp-38h]@119
+  int v137; // [sp+48h] [bp-34h]@7
+  int v138; // [sp+48h] [bp-34h]@42
+  int v139; // [sp+48h] [bp-34h]@82
+  int v140; // [sp+48h] [bp-34h]@120
+  int v141; // [sp+4Ch] [bp-30h]@6
+  int v142; // [sp+4Ch] [bp-30h]@41
+  int v143; // [sp+4Ch] [bp-30h]@75
+  int v144; // [sp+4Ch] [bp-30h]@113
+  int v145; // [sp+50h] [bp-2Ch]@5
+  int v146; // [sp+50h] [bp-2Ch]@40
+  int v147; // [sp+50h] [bp-2Ch]@75
+  int v148; // [sp+50h] [bp-2Ch]@113
+  int v149; // [sp+54h] [bp-28h]@4
+  int v150; // [sp+54h] [bp-28h]@39
+  int v151; // [sp+54h] [bp-28h]@75
+  int v152; // [sp+54h] [bp-28h]@113
+  int sDepth; // [sp+58h] [bp-24h]@17
+  int sDeptha; // [sp+58h] [bp-24h]@52
+  int sDepthb; // [sp+58h] [bp-24h]@90
+  char *a5; // [sp+5Ch] [bp-20h]@16
+  char *a5a; // [sp+5Ch] [bp-20h]@51
+  signed int a5b; // [sp+5Ch] [bp-20h]@83
+  signed int a5c; // [sp+5Ch] [bp-20h]@121
+  signed int v160; // [sp+60h] [bp-1Ch]@12
+  signed int v161; // [sp+60h] [bp-1Ch]@47
+  int v162; // [sp+60h] [bp-1Ch]@128
+  int v163; // [sp+64h] [bp-18h]@2
+  int outx; // [sp+68h] [bp-14h]@2
+  int outy; // [sp+6Ch] [bp-10h]@2
+  int outz; // [sp+70h] [bp-Ch]@2
+  Vec3_int_ pOut; // [sp+74h] [bp-8h]@2
+  int ya; // [sp+84h] [bp+8h]@60
+  int yb; // [sp+84h] [bp+8h]@136
+  int ve; // [sp+88h] [bp+Ch]@60
+  int va; // [sp+88h] [bp+Ch]@60
+  int vb; // [sp+88h] [bp+Ch]@66
+  int vf; // [sp+88h] [bp+Ch]@136
+  int vc; // [sp+88h] [bp+Ch]@136
+  int vd; // [sp+88h] [bp+Ch]@142
+  int v_4; // [sp+8Ch] [bp+10h]@60
+  int v_4a; // [sp+8Ch] [bp+10h]@65
+  int v_4b; // [sp+8Ch] [bp+10h]@136
+  int v_4c; // [sp+8Ch] [bp+10h]@141
+  int v_8; // [sp+90h] [bp+14h]@53
+
+  a4 = __PAIR__(z, x);
+  v4 = stru_5C6E00->Atan2(v.x - x, v.y - z);
+  v114 = 0;
+  v97.z = y;
+  v113 = 0;
+  a4_8 = v4;
+  *(_QWORD *)&v97.x = a4;
+  if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor)
+  {
+    Vec3_int_::Rotate(32, stru_5C6E00->uIntegerHalfPi + v4, 0, v97, &pOut.x, &pOut.y, &outz);
+    v45.z = v.z;
+    *(_QWORD *)&v45.x = *(_QWORD *)&v;
+    Vec3_int_::Rotate(32, stru_5C6E00->uIntegerHalfPi + v4, 0, v45, &outx, &outy, &v163);
+    v46 = outy - pOut.y;
+    v47 = v163 - outz;
+    v48 = outx - pOut.x;
+    v49 = sub_452A9E(v48 * v48 + v46 * v46 + v47 * v47);
+    v50 = 65536;
+    if ( v49 )
+      v50 = 65536 / v49;
+    v51 = outx;
+    v143 = v48 * v50;
+    v52 = v46 * v50;
+    v53 = v47 * v50;
+    v54 = pOut.x;
+    v147 = v52;
+    v151 = v53;
+    v119 = pOut.x;
+    if ( pOut.x < outx )
+    {
+      v123 = outx;
+    }
+    else
+    {
+      v119 = outx;
+      v123 = pOut.x;
+    }
+    v55 = pOut.y;
+    v56 = outy;
+    v127 = pOut.y;
+    if ( pOut.y < outy )
+    {
+      v131 = outy;
+    }
+    else
+    {
+      v127 = outy;
+      v131 = pOut.y;
+    }
+    v57 = v163;
+    v58 = outz;
+    v135 = outz;
+    if ( outz < v163 )
+    {
+      v139 = v163;
+    }
+    else
+    {
+      v135 = v163;
+      v139 = outz;
+    }
+    a5b = 0;
+    while ( !v114 )
+    {
+      if ( a5b )
+      {
+        v102 = v58;
+        v100 = v55;
+        v98 = v54;
+      }
+      else
+      {
+        v102 = v57;
+        v100 = v56;
+        v98 = v51;
+      }
+      v59 = pIndoor->GetSector(v98, v100, v102);
+      v60 = pIndoor->pSectors;
+      v61 = 116 * v59;
+      sDepthb = 0;
+      for ( i = 116 * v59;
+            sDepthb < *(__int16 *)((char *)&pIndoor->pSectors->field_C + v61)
+                    + 2 * *(__int16 *)((char *)&pIndoor->pSectors->uNumFloors + v61);
+            ++sDepthb )
+      {
+        v62 = &pIndoor->pFaces[(*(unsigned __int16 **)((char *)&v60->pWalls + v61))[sDepthb]];
+        if ( v62->uAttributes & 1
+          || v119 > v62->pBounding.x2
+          || v123 < v62->pBounding.x1
+          || v127 > v62->pBounding.y2
+          || v131 < v62->pBounding.y1
+          || v135 > v62->pBounding.z2
+          || v139 < v62->pBounding.z1
+          || (v63 = (unsigned __int64)(v143 * (signed __int64)v62->pFacePlane_old.vNormal.x) >> 16,
+              v64 = (unsigned __int64)(v151 * (signed __int64)v62->pFacePlane_old.vNormal.z) >> 16,
+              v65 = (unsigned __int64)(v147 * (signed __int64)v62->pFacePlane_old.vNormal.y) >> 16,
+              v20 = v63 + v64 + v65 == 0,
+              v66 = v63 + v64 + v65,
+              v107 = v63 + v64 + v65,
+              v20) )
+          goto LABEL_107;
+        v67 = outz * v62->pFacePlane_old.vNormal.z;
+        v68 = -(v62->pFacePlane_old.dist
+              + v67
+              + pOut.y * v62->pFacePlane_old.vNormal.y
+              + pOut.x * v62->pFacePlane_old.vNormal.x);
+        if ( v66 <= 0 )
+        {
+          if ( v62->pFacePlane_old.dist
+             + v67
+             + pOut.y * v62->pFacePlane_old.vNormal.y
+             + pOut.x * v62->pFacePlane_old.vNormal.x < 0 )
+            goto LABEL_107;
+        }
+        else
+        {
+          if ( v62->pFacePlane_old.dist
+             + v67
+             + pOut.y * v62->pFacePlane_old.vNormal.y
+             + pOut.x * v62->pFacePlane_old.vNormal.x > 0 )
+            goto LABEL_107;
+        }
+        v69 = abs(-(v62->pFacePlane_old.dist
+                  + v67
+                  + pOut.y * v62->pFacePlane_old.vNormal.y
+                  + pOut.x * v62->pFacePlane_old.vNormal.x)) >> 14;
+        if ( v69 <= abs(v66) )
+        {
+          LODWORD(v70) = v68 << 16;
+          HIDWORD(v70) = v68 >> 16;
+          v71 = v70 / v107;
+          v108 = v70 / v107;
+          if ( v71 >= 0 )
+          {
+            if ( sub_4075DB(
+                   pOut.x + ((signed int)(((unsigned __int64)(v108 * (signed __int64)v143) >> 16) + 32768) >> 16),
+                   pOut.y + ((signed int)(((unsigned __int64)(v108 * (signed __int64)v147) >> 16) + 32768) >> 16),
+                   outz + ((signed int)(((unsigned __int64)(v108 * (signed __int64)v151) >> 16) + 32768) >> 16),
+                   v62) )
+            {
+              v114 = 1;
+              break;
+            }
+          }
+        }
+        v61 = i;
+LABEL_107:
+        v60 = pIndoor->pSectors;
+      }
+      ++a5b;
+      if ( a5b >= 2 )
+        break;
+      v57 = v163;
+      v56 = outy;
+      v51 = outx;
+      v58 = outz;
+      v55 = pOut.y;
+      v54 = pOut.x;
+    }
+    v72.z = y;
+    *(_QWORD *)&v72.x = a4;
+    Vec3_int_::Rotate(32, a4_8 - stru_5C6E00->uIntegerHalfPi, 0, v72, &pOut.x, &pOut.y, &outz);
+    v73.z = v.z;
+    *(_QWORD *)&v73.x = *(_QWORD *)&v;
+    Vec3_int_::Rotate(32, a4_8 - stru_5C6E00->uIntegerHalfPi, 0, v73, &outx, &outy, &v163);
+    v74 = outy - pOut.y;
+    v75 = v163 - outz;
+    v76 = outx - pOut.x;
+    v77 = sub_452A9E(v76 * v76 + v74 * v74 + v75 * v75);
+    v78 = 65536;
+    if ( v77 )
+      v78 = 65536 / v77;
+    v79 = outx;
+    v144 = v76 * v78;
+    v80 = v74 * v78;
+    v81 = v75 * v78;
+    v82 = pOut.x;
+    v148 = v80;
+    v152 = v81;
+    v120 = pOut.x;
+    if ( pOut.x < outx )
+    {
+      v124 = outx;
+    }
+    else
+    {
+      v120 = outx;
+      v124 = pOut.x;
+    }
+    v83 = pOut.y;
+    v84 = outy;
+    v128 = pOut.y;
+    if ( pOut.y < outy )
+    {
+      v132 = outy;
+    }
+    else
+    {
+      v128 = outy;
+      v132 = pOut.y;
+    }
+    v85 = v163;
+    v86 = outz;
+    v136 = outz;
+    if ( outz < v163 )
+    {
+      v140 = v163;
+    }
+    else
+    {
+      v136 = v163;
+      v140 = outz;
+    }
+    a5c = 0;
+    while ( 1 )
+    {
+      if ( v113 )
+        return !v114 || !v113;
+      if ( a5c )
+      {
+        v103 = v86;
+        v101 = v83;
+        v99 = v82;
+      }
+      else
+      {
+        v103 = v85;
+        v101 = v84;
+        v99 = v79;
+      }
+      v87 = pIndoor->GetSector(v99, v101, v103);
+      v88 = pIndoor->pSectors;
+      v89 = 116 * v87;
+      v162 = 0;
+      v112 = v89;
+      if ( *(__int16 *)((char *)&pIndoor->pSectors->field_C + v89)
+         + 2 * *(__int16 *)((char *)&pIndoor->pSectors->uNumFloors + v89) > 0 )
+        break;
+LABEL_148:
+      ++a5c;
+      if ( a5c >= 2 )
+        return !v114 || !v113;
+      v85 = v163;
+      v84 = outy;
+      v79 = outx;
+      v86 = outz;
+      v83 = pOut.y;
+      v82 = pOut.x;
+    }
+    while ( 1 )
+    {
+      v90 = &pIndoor->pFaces[(*(unsigned __int16 **)((char *)&v88->pWalls + v89))[v162]];
+      if ( v90->uAttributes & 1
+        || v120 > v90->pBounding.x2
+        || v124 < v90->pBounding.x1
+        || v128 > v90->pBounding.y2
+        || v132 < v90->pBounding.y1
+        || v136 > v90->pBounding.z2
+        || v140 < v90->pBounding.z1
+        || (yb = (unsigned __int64)(v144 * (signed __int64)v90->pFacePlane_old.vNormal.x) >> 16,
+            v_4b = (unsigned __int64)(v148 * (signed __int64)v90->pFacePlane_old.vNormal.y) >> 16,
+            vf = (unsigned __int64)(v152 * (signed __int64)v90->pFacePlane_old.vNormal.z) >> 16,
+            v20 = yb + vf + v_4b == 0,
+            v91 = yb + vf + v_4b,
+            vc = yb + vf + v_4b,
+            v20) )
+        goto LABEL_145;
+      v92 = outz * v90->pFacePlane_old.vNormal.z;
+      v93 = -(v90->pFacePlane_old.dist
+            + v92
+            + pOut.y * v90->pFacePlane_old.vNormal.y
+            + pOut.x * v90->pFacePlane_old.vNormal.x);
+      if ( v91 <= 0 )
+      {
+        if ( v90->pFacePlane_old.dist
+           + v92
+           + pOut.y * v90->pFacePlane_old.vNormal.y
+           + pOut.x * v90->pFacePlane_old.vNormal.x < 0 )
+          goto LABEL_145;
+      }
+      else
+      {
+        if ( v90->pFacePlane_old.dist
+           + v92
+           + pOut.y * v90->pFacePlane_old.vNormal.y
+           + pOut.x * v90->pFacePlane_old.vNormal.x > 0 )
+          goto LABEL_145;
+      }
+      v_4c = abs(-(v90->pFacePlane_old.dist
+                 + v92
+                 + pOut.y * v90->pFacePlane_old.vNormal.y
+                 + pOut.x * v90->pFacePlane_old.vNormal.x)) >> 14;
+      if ( v_4c <= abs(v91) )
+      {
+        LODWORD(v94) = v93 << 16;
+        HIDWORD(v94) = v93 >> 16;
+        v95 = v94 / vc;
+        vd = v94 / vc;
+        if ( v95 >= 0 )
+        {
+          if ( sub_4075DB(
+                 pOut.x + ((signed int)(((unsigned __int64)(vd * (signed __int64)v144) >> 16) + 32768) >> 16),
+                 pOut.y + ((signed int)(((unsigned __int64)(vd * (signed __int64)v148) >> 16) + 32768) >> 16),
+                 outz + ((signed int)(((unsigned __int64)(vd * (signed __int64)v152) >> 16) + 32768) >> 16),
+                 v90) )
+          {
+            v113 = 1;
+            goto LABEL_148;
+          }
+        }
+      }
+      v89 = v112;
+LABEL_145:
+      v88 = pIndoor->pSectors;
+      ++v162;
+      if ( v162 >= *(__int16 *)((char *)&pIndoor->pSectors->field_C + v89)
+                 + 2 * *(__int16 *)((char *)&pIndoor->pSectors->uNumFloors + v89) )
+        goto LABEL_148;
+    }
+  }
+  Vec3_int_::Rotate(32, stru_5C6E00->uIntegerHalfPi + v4, 0, v97, &pOut.x, &pOut.y, &outz);
+  v5.z = v.z;
+  *(_QWORD *)&v5.x = *(_QWORD *)&v;
+  Vec3_int_::Rotate(32, stru_5C6E00->uIntegerHalfPi + v4, 0, v5, &outx, &outy, &v163);
+  v6 = outy - pOut.y;
+  v7 = v163 - outz;
+  v8 = outx - pOut.x;
+  v9 = sub_452A9E(v8 * v8 + v6 * v6 + v7 * v7);
+  v10 = 65536;
+  if ( v9 )
+    v10 = 65536 / v9;
+  v125 = v8 * v10;
+  v11 = v10;
+  v12 = v7 * v10;
+  v13 = pOut.x;
+  v117 = v12;
+  v121 = v6 * v11;
+  v149 = pOut.x;
+  if ( pOut.x < outx )
+  {
+    v145 = outx;
+  }
+  else
+  {
+    v149 = outx;
+    v145 = pOut.x;
+  }
+  v14 = outy;
+  v141 = pOut.y;
+  if ( pOut.y < outy )
+  {
+    v137 = outy;
+  }
+  else
+  {
+    v141 = outy;
+    v137 = pOut.y;
+  }
+  v133 = outz;
+  if ( outz < v163 )
+  {
+    v129 = v163;
+  }
+  else
+  {
+    v133 = v163;
+    v129 = outz;
+  }
+  v160 = 0;
+  if ( (signed int)pOutdoor->uNumBModels > 0 )
+  {
+    v104 = 0;
+    while ( 1 )
+    {
+      v15 = (char *)&pOutdoor->pBModels[v104].pVertices;
+      a5 = (char *)&pOutdoor->pBModels[v104].pVertices;
+      if ( sub_4088E9(v13, pOut.y, outx, v14, pOutdoor->pBModels[v104].vPosition.x, pOutdoor->pBModels[v104].vPosition.y) <= pOutdoor->pBModels[v104].sBoundingRadius + 128 )
+      {
+        sDepth = 0;
+        if ( *((int *)v15 + 2) > 0 )
+          break;
+      }
+LABEL_36:
+      ++v160;
+      ++v104;
+      if ( v160 >= (signed int)pOutdoor->uNumBModels )
+        goto LABEL_37;
+      v14 = outy;
+      v13 = pOut.x;
+    }
+    v106 = 0;
+    while ( 1 )
+    {
+      v16 = (ODMFace *)(v106 + *((int *)a5 + 4));
+      if ( v149 > v16->pBoundingBox.x2
+        || v145 < v16->pBoundingBox.x1
+        || v141 > v16->pBoundingBox.y2
+        || v137 < v16->pBoundingBox.y1
+        || v133 > v16->pBoundingBox.z2
+        || v129 < v16->pBoundingBox.z1
+        || (v17 = (unsigned __int64)(v125 * (signed __int64)v16->pFacePlane.vNormal.x) >> 16,
+            v18 = (unsigned __int64)(v121 * (signed __int64)v16->pFacePlane.vNormal.y) >> 16,
+            v19 = (unsigned __int64)(v117 * (signed __int64)v16->pFacePlane.vNormal.z) >> 16,
+            v20 = v17 + v18 + v19 == 0,
+            v21 = v17 + v18 + v19,
+            v109 = v17 + v18 + v19,
+            v20) )
+        goto LABEL_33;
+      v22 = pOut.y * v16->pFacePlane.vNormal.y;
+      v23 = -(v16->pFacePlane.dist + v22 + outz * v16->pFacePlane.vNormal.z + pOut.x * v16->pFacePlane.vNormal.x);
+      if ( v21 <= 0 )
+      {
+        if ( v16->pFacePlane.dist + v22 + outz * v16->pFacePlane.vNormal.z + pOut.x * v16->pFacePlane.vNormal.x < 0 )
+          goto LABEL_33;
+      }
+      else
+      {
+        if ( v16->pFacePlane.dist + v22 + outz * v16->pFacePlane.vNormal.z + pOut.x * v16->pFacePlane.vNormal.x > 0 )
+          goto LABEL_33;
+      }
+      v24 = abs(-(v16->pFacePlane.dist + v22 + outz * v16->pFacePlane.vNormal.z + pOut.x * v16->pFacePlane.vNormal.x)) >> 14;
+      if ( v24 <= abs(v21) )
+      {
+        LODWORD(v25) = v23 << 16;
+        HIDWORD(v25) = v23 >> 16;
+        v26 = v25 / v109;
+        v110 = v25 / v109;
+        if ( v26 >= 0 )
+        {
+          if ( sub_4077F1(
+                 pOut.x + ((signed int)(((unsigned __int64)(v110 * (signed __int64)v125) >> 16) + 32768) >> 16),
+                 pOut.y + ((signed int)(((unsigned __int64)(v110 * (signed __int64)v121) >> 16) + 32768) >> 16),
+                 outz + ((signed int)(((unsigned __int64)(v110 * (signed __int64)v117) >> 16) + 32768) >> 16),
+                 v16,
+                 (BSPVertexBuffer *)a5) )
+          {
+            v114 = 1;
+            goto LABEL_36;
+          }
+        }
+      }
+LABEL_33:
+      ++sDepth;
+      v106 += 308;
+      if ( sDepth >= *((int *)a5 + 2) )
+        goto LABEL_36;
+    }
+  }
+LABEL_37:
+  v27.z = y;
+  *(_QWORD *)&v27.x = a4;
+  Vec3_int_::Rotate(32, a4_8 - stru_5C6E00->uIntegerHalfPi, 0, v27, &pOut.x, &pOut.y, &outz);
+  v28.z = v.z;
+  *(_QWORD *)&v28.x = *(_QWORD *)&v;
+  Vec3_int_::Rotate(32, a4_8 - stru_5C6E00->uIntegerHalfPi, 0, v28, &outx, &outy, &v163);
+  v29 = outy - pOut.y;
+  v30 = v163 - outz;
+  v31 = outx - pOut.x;
+  v32 = sub_452A9E(v31 * v31 + v29 * v29 + v30 * v30);
+  v33 = 65536;
+  if ( v32 )
+    v33 = 65536 / v32;
+  v126 = v31 * v33;
+  v34 = v33;
+  v35 = v30 * v33;
+  v36 = pOut.x;
+  v118 = v35;
+  v122 = v29 * v34;
+  v150 = pOut.x;
+  if ( pOut.x < outx )
+  {
+    v146 = outx;
+  }
+  else
+  {
+    v150 = outx;
+    v146 = pOut.x;
+  }
+  v37 = outy;
+  v142 = pOut.y;
+  if ( pOut.y < outy )
+  {
+    v138 = outy;
+  }
+  else
+  {
+    v142 = outy;
+    v138 = pOut.y;
+  }
+  v134 = outz;
+  if ( outz < v163 )
+  {
+    v130 = v163;
+  }
+  else
+  {
+    v134 = v163;
+    v130 = outz;
+  }
+  v161 = 0;
+  if ( (signed int)pOutdoor->uNumBModels > 0 )
+  {
+    v105 = 0;
+    while ( 1 )
+    {
+      v38 = (char *)&pOutdoor->pBModels[v105].pVertices;
+      a5a = (char *)&pOutdoor->pBModels[v105].pVertices;
+      if ( sub_4088E9(v36, pOut.y, outx, v37, pOutdoor->pBModels[v105].vPosition.x, pOutdoor->pBModels[v105].vPosition.y) <= pOutdoor->pBModels[v105].sBoundingRadius + 128 )
+      {
+        sDeptha = 0;
+        if ( *((int *)v38 + 2) > 0 )
+          break;
+      }
+LABEL_71:
+      ++v161;
+      ++v105;
+      if ( v161 >= (signed int)pOutdoor->uNumBModels )
+        return !v114 || !v113;
+      v37 = outy;
+      v36 = pOut.x;
+    }
+    v_8 = 0;
+    while ( 1 )
+    {
+      v39 = (ODMFace *)(v_8 + *((int *)a5a + 4));
+      if ( v150 > v39->pBoundingBox.x2
+        || v146 < v39->pBoundingBox.x1
+        || v142 > v39->pBoundingBox.y2
+        || v138 < v39->pBoundingBox.y1
+        || v134 > v39->pBoundingBox.z2
+        || v130 < v39->pBoundingBox.z1
+        || (ya = (unsigned __int64)(v126 * (signed __int64)v39->pFacePlane.vNormal.x) >> 16,
+            ve = (unsigned __int64)(v122 * (signed __int64)v39->pFacePlane.vNormal.y) >> 16,
+            v_4 = (unsigned __int64)(v118 * (signed __int64)v39->pFacePlane.vNormal.z) >> 16,
+            v20 = ya + ve + v_4 == 0,
+            v40 = ya + ve + v_4,
+            va = ya + ve + v_4,
+            v20) )
+        goto LABEL_68;
+      v41 = pOut.y * v39->pFacePlane.vNormal.y;
+      v42 = -(v39->pFacePlane.dist + v41 + outz * v39->pFacePlane.vNormal.z + pOut.x * v39->pFacePlane.vNormal.x);
+      if ( v40 <= 0 )
+      {
+        if ( v39->pFacePlane.dist + v41 + outz * v39->pFacePlane.vNormal.z + pOut.x * v39->pFacePlane.vNormal.x < 0 )
+          goto LABEL_68;
+      }
+      else
+      {
+        if ( v39->pFacePlane.dist + v41 + outz * v39->pFacePlane.vNormal.z + pOut.x * v39->pFacePlane.vNormal.x > 0 )
+          goto LABEL_68;
+      }
+      v_4a = abs(-(v39->pFacePlane.dist + v41 + outz * v39->pFacePlane.vNormal.z + pOut.x * v39->pFacePlane.vNormal.x)) >> 14;
+      if ( v_4a <= abs(v40) )
+      {
+        LODWORD(v43) = v42 << 16;
+        HIDWORD(v43) = v42 >> 16;
+        v44 = v43 / va;
+        vb = v43 / va;
+        if ( v44 >= 0 )
+        {
+          if ( sub_4077F1(
+                 pOut.x + ((signed int)(((unsigned __int64)(vb * (signed __int64)v126) >> 16) + 32768) >> 16),
+                 pOut.y + ((signed int)(((unsigned __int64)(vb * (signed __int64)v122) >> 16) + 32768) >> 16),
+                 outz + ((signed int)(((unsigned __int64)(vb * (signed __int64)v118) >> 16) + 32768) >> 16),
+                 v39,
+                 (BSPVertexBuffer *)a5a) )
+          {
+            v113 = 1;
+            goto LABEL_71;
+          }
+        }
+      }
+LABEL_68:
+      ++sDeptha;
+      v_8 += 308;
+      if ( sDeptha >= *((int *)a5a + 2) )
+        goto LABEL_71;
+    }
+  }
+  return !v114 || !v113;
+}
+
+
+//----- (00408768) --------------------------------------------------------
+void InitializeActors()
+{
+  signed int v5; // [sp+Ch] [bp-10h]@1
+  signed int v6; // [sp+10h] [bp-Ch]@1
+  signed int v7; // [sp+14h] [bp-8h]@1
+  signed int v8; // [sp+18h] [bp-4h]@1
+
+  v8 = 0;
+  v6 = 0;
+  v7 = 0;
+  v5 = 0;
+  if ( !_strcmpi(pCurrentMapName, "d25.blv") )
+    v8 = 1;
+  if ( !_strcmpi(pCurrentMapName, "d26.blv") )
+    v6 = 1;
+  if (_449B57_test_bit(pParty->_award_bits, 99))
+    v7 = 1;
+  if (_449B57_test_bit(pParty->_award_bits, 100))
+    v5 = 1;
+  for (uint i = 0; i < uNumActors; ++i)
+  {
+    auto actor = pActors + i;
+
+    if (actor->CanAct() || actor->uAIState == Disabled)
+    {
+      actor->vPosition.x = actor->vInitialPosition.x;
+      actor->vPosition.y = actor->vInitialPosition.y;
+      actor->vPosition.z = actor->vInitialPosition.z;
+      actor->sCurrentHP = actor->pMonsterInfo.uHP;
+      if (actor->uAIState != Disabled)
+        Actor::_403EB6(i, dword_4F6E08[i], actor->pMonsterInfo.uRecoveryTime, 0);
+    }
+
+    actor->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
+
+    if (!v8 || v7)
+      if (!v6 || v5)
+        if (actor->_438B9B())
+          BYTE2(actor->uAttributes) &= 0xF7u;
+
+    BYTE2(actor->uAttributes) &= 0x7Fu;
+    if (BYTE2(actor->uAttributes) & 0x40)
+        Actor::_4031C1_update_job(i, pParty->uCurrentHour, 1);
+  }
+}
+
+//----- (00408896) --------------------------------------------------------
+void InitializeLayingItems()
+{
+  for (uint i = 0; i < uNumLayingItems; ++i)
+  {
+    auto item = pLayingItems + i;
+
+    if (item->uItemType &&
+        (item->uSoundID & 8 || pObjectList->pObjects[item->uItemType].uFlags & 0x10))
+      LayingItem::_42F933(i);
+  }
+
+  for (uint i = 0; i < 100; ++i)
+    array_5118E8.pElements[i].field_C_time_left = 0;
+}
+
+//----- (004088E9) --------------------------------------------------------
+signed int __fastcall sub_4088E9(int a1, int a2, int a3, int a4, int a5, int a6)
+{
+  int v6; // esi@1
+  int v7; // edi@1
+  int v8; // eax@1
+  signed int result; // eax@1
+  int v10; // [sp+Ch] [bp-4h]@1
+  int v11; // [sp+18h] [bp+8h]@1
+
+  v6 = a1;
+  v10 = a2;
+  v7 = a3 - a1;
+  v11 = abs(a3 - a1);
+  v8 = abs(a4 - v10);
+  result = sub_452A9E(v11 * v11 + v8 * v8);
+  if ( result )
+    result = abs((v7 * (v10 - a6) - (a4 - v10) * (v6 - a5)) / result);
+  return result;
+}
+
+
+//----- (00408A27) --------------------------------------------------------
+unsigned int __thiscall SearchAliveActors(unsigned int *pTotalActors)
+{
+  unsigned int *v1; // esi@1
+  int v2; // eax@1
+  unsigned int v3; // ebp@1
+  signed int v4; // ebx@1
+  Actor *v5; // edi@2
+  unsigned int v6; // eax@3
+  int v8; // [sp+Ch] [bp-4h]@1
+
+  v1 = pTotalActors;
+  v2 = GetAlertStatus();
+  v3 = 0;
+  v4 = 0;
+  *v1 = 0;
+  v8 = v2;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v5 = pActors;
+    do
+    {
+      v6 = v5->uAttributes;
+      if ( (v6 & 0x100000) == v8 )
+      {
+        ++*v1;
+        if ( v5->IsAlive() == 1 )
+          ++v3;
+      }
+      ++v4;
+      ++v5;
+    }
+    while ( v4 < (signed int)uNumActors );
+  }
+  return v3;
+}
+
+//----- (00408A7E) --------------------------------------------------------
+unsigned int __fastcall SearchActorByMonsterID(unsigned int *pTotalActors, int uMonsterID)
+{
+  unsigned int *v2; // esi@1
+  signed int v3; // ebx@1
+  char *v4; // edi@2
+  int v5; // eax@3
+  int v7; // [sp+8h] [bp-Ch]@1
+  int v8; // [sp+Ch] [bp-8h]@1
+  unsigned int v9; // [sp+10h] [bp-4h]@1
+
+  v7 = uMonsterID;
+  v2 = pTotalActors;
+  v3 = 0;
+  v8 = GetAlertStatus();
+  *v2 = 0;
+  v9 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v4 = (char *)&pActors[0].pMonsterInfo.uID;
+    do
+    {
+      v5 = *((int *)v4 - 15);                // actor::attributes
+      if ( (v5 & 0x100000) == v8 )
+      {
+        if ( *(short *)v4 - 1 == v7 )
+        {
+          ++*v2;
+          if ( ((Actor *)(v4 - 96))->IsAlive() == 1 )
+            ++v9;
+        }
+      }
+      ++v3;
+      v4 += 836;
+    }
+    while ( v3 < (signed int)uNumActors );
+  }
+  return v9;
+}
+
+//----- (00408AE7) --------------------------------------------------------
+unsigned int __fastcall SearchActorByGroup(unsigned int *pTotalActors, unsigned int uGroup)
+{
+  unsigned int *v2; // esi@1
+  signed int v3; // ebx@1
+  char *v4; // edi@2
+  int v5; // eax@3
+  unsigned int v7; // [sp+8h] [bp-Ch]@1
+  int v8; // [sp+Ch] [bp-8h]@1
+  unsigned int v9; // [sp+10h] [bp-4h]@1
+
+  v7 = uGroup;
+  v2 = pTotalActors;
+  v3 = 0;
+  v8 = GetAlertStatus();
+  *v2 = 0;
+  v9 = 0;
+  if ( (signed int)uNumActors > 0 )
+  {
+    v4 = (char *)&pActors[0].uGroup;
+    do
+    {
+      v5 = *((int *)v4 - 168);
+      if ( (v5 & 0x100000) == v8 )
+      {
+        if ( *(int *)v4 == v7 )
+        {
+          ++*v2;
+          if ( ((Actor *)(v4 - 708))->IsAlive() == 1 )
+            ++v9;
+        }
+      }
+      ++v3;
+      v4 += 836;
+    }
+    while ( v3 < (signed int)uNumActors );
+  }
+  return v9;
+}
+
+//----- (00408B54) --------------------------------------------------------
+unsigned int __fastcall SearchActorByID(unsigned int *pTotalActors, unsigned int a2)
+{
+  unsigned int v2; // edi@1
+  unsigned int *v3; // esi@1
+  int v4; // eax@1
+  unsigned int v5; // ebx@1
+  unsigned int v6; // edx@1
+
+  v2 = a2;
+  v3 = pTotalActors;
+  v4 = GetAlertStatus();
+  v5 = 0;
+  *v3 = 0;
+  v6 = pActors[v2].uAttributes;
+  if ( (v6 & 0x100000) == v4 )
+  {
+    *v3 = 1;
+    if ( pActors[v2].IsAlive() == 1 )
+      v5 = 1;
+  }
+  return v5;
+}
+
+
+//----- (00409BE8) --------------------------------------------------------
+void __cdecl sub_409BE8()
+{
+  void *v0; // eax@1
+  stru348 *v1; // eax@1
+  int v2; // ecx@1
+  int v3; // eax@1
+
+  v0 = ptr_507BC0->ptr_1C;
+  dword_4E1874 = 5;
+  v1 = &stru_4E1890[(int)((char *)v0 - 108)];
+  amuint_4E1860 = v1->field_4;
+  amuint_4E1864 = v1->field_6;
+  amuint_4E1868 = v1->field_8 - 1;
+  amuint_4E186C = v1->field_A - 1;
+  amuint_4E1870 = v1->field_C - 1;
+  amuint_505884 = v1->field_E;
+  amuint_505888 = v1->field_10;
+  amuint_50588C = v1->field_12;
+  dword_4E1878 = 1;
+  dword_4E187C = 1;
+  dword_4E1880 = 1;
+  dword_4E1884 = v1->field_0;
+  v2 = v1->field_2;
+  v3 = v1->field_14;
+  dword_4E1888 = v2;
+  dword_4DF3A4 = v3;
+}
+// 4DF3A4: using guessed type int dword_4DF3A4;
+// 4E1860: using guessed type int amuint_4E1860;
+// 4E1864: using guessed type int amuint_4E1864;
+// 4E1868: using guessed type int amuint_4E1868;
+// 4E186C: using guessed type int amuint_4E186C;
+// 4E1870: using guessed type int amuint_4E1870;
+// 4E1874: using guessed type int dword_4E1874;
+// 4E1878: using guessed type int dword_4E1878;
+// 4E187C: using guessed type int dword_4E187C;
+// 4E1880: using guessed type int dword_4E1880;
+// 4E1884: using guessed type int dword_4E1884;
+// 4E1888: using guessed type int dword_4E1888;
+// 505884: using guessed type int amuint_505884;
+// 505888: using guessed type int amuint_505888;
+// 50588C: using guessed type int amuint_50588C;
+
+
+
+
+
+
+
+//----- (0040D75D) --------------------------------------------------------
+char __fastcall pPrimaryWindow_draws_text(int a1, const char *pText, int *pXY)
+{
+  const char *v3; // ST0C_4@1
+  __int64 v4; // qax@1
+
+  v3 = pText;
+  v4 = LOBYTE(pFontComic->uFontHeight) - 3;
+  return pPrimaryWindow->DrawText(
+           pFontComic,
+           *pXY,
+           pXY[1] - (((signed int)v4 - HIDWORD(v4)) >> 1) + 3,
+           0,
+           v3,
+           0,
+           0,
+           0);
+}
+
+
+
+//----- (0040DB27) --------------------------------------------------------
+void __fastcall DrawRect(Vec4_int_ *pXYZW, unsigned __int16 uColor, char bSolidFill)
+{
+  Vec4_int_ *v3; // esi@1
+  unsigned __int16 v4; // bp@1
+  unsigned int i; // ebx@3
+
+  v3 = pXYZW;
+  v4 = uColor;
+  pRenderer->BeginScene();
+  pRenderer->Clip_v2(0, 0, 639u, 479u);
+  if ( bSolidFill )
+  {
+    for ( i = v3->y; (signed int)i <= v3->w; ++i )
+      pRenderer->Line2D(v3->x, i, v3->z, i, v4);
+  }
+  else
+  {
+    pRenderer->Line2D(v3->x, v3->y, v3->z, v3->y, v4);
+    pRenderer->Line2D(v3->z, v3->y, v3->z, v3->w, v4);
+    pRenderer->Line2D(v3->z, v3->w, v3->x, v3->w, v4);
+    pRenderer->Line2D(v3->x, v3->w, v3->x, v3->y, v4);
+  }
+  pRenderer->EndScene();
+}
+
+
+
+
+//----- (0040DDB1) --------------------------------------------------------
+int __fastcall rand_interval(int a, int b)
+{
+  return a + rand() % (b - a + 1);
+}
+
+//----- (0040DEB4) --------------------------------------------------------
+char *__fastcall inv_strcat(const char *Source, char *Dest)
+{
+  return strcat(Dest, Source);
+}
+
+//----- (0040DEBE) --------------------------------------------------------
+char *__fastcall inv_strcpy(const char *Source, char *Dest)
+{
+  return strcpy(Dest, Source);
+}
+
+//----- (0040DEC8) --------------------------------------------------------
+void __fastcall intToString(int val, char *pOut)
+{
+  sprintf(pOut, "%d", val);
+}
+
+//----- (0040DEDB) --------------------------------------------------------
+unsigned int __stdcall R8G8B8_to_TargetFormat(int uColor)
+{
+  return GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat((unsigned __int8)uColor, BYTE1(uColor), BYTE2(uColor));
+}
+
+//----- (0040DEF3) --------------------------------------------------------
+unsigned int __fastcall GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(unsigned __int16 r, unsigned __int16 g, unsigned __int16 b)
+{
+  return ((unsigned int)b >> (8 - LOBYTE(pRenderer->uTargetBBits))) | pRenderer->uTargetGMask & (g << (LOBYTE(pRenderer->uTargetGBits) + LOBYTE(pRenderer->uTargetBBits) - 8)) | pRenderer->uTargetRMask & (r << (LOBYTE(pRenderer->uTargetGBits) + LOBYTE(pRenderer->uTargetRBits) + LOBYTE(pRenderer->uTargetBBits) - 8));
+}
+
+//----- (0040DF3D) --------------------------------------------------------
+void __cdecl CallRenderPresent()
+{
+  pRenderer->Present();
+}
+
+
+//----- (0040DFA7) --------------------------------------------------------
+int __stdcall retzero_sub_40DFA7(int a1)
+{
+  return 0;
+}
+// 40DFA7: using guessed type int __stdcall retzero_sub_40DFA7(int);
+
+//----- (0040DFD1) --------------------------------------------------------
+void stru272::_40DFD1()
+{
+  stru272 *v1; // esi@1
+  stru272_stru0 *v2; // eax@1
+
+  v1 = this;
+  v2 = (stru272_stru0 *)malloc(0x5Cu);
+  v1->ptr_0 = v2;
+  v2->field_0 = 0x67707274u;
+  v1->ptr_0->field_8 = 0;
+  v1->ptr_0->field_30 = 0.0;
+  v1->ptr_0->field_58 = 0;
+  v1->ptr_0->field_59 = 0;
+}
+
+//----- (0040DFFE) --------------------------------------------------------
+int stru272_stru0::_40DFFE()
+{
+  signed int result; // eax@2
+
+  if ( this->field_0 == 0x67707274 )
+  {
+    this->field_0 = 0x78787878u;
+    free(this);
+    result = 0;
+  }
+  else
+  {
+    result = 2;
+  }
+  return result;
+}
+
+//----- (0040E01A) --------------------------------------------------------
+int stru272_stru0::_40E01A(int a2)
+{
+  signed int result; // eax@2
+
+  auto a1 = this;
+  if ( a1->field_0 == 0x67707274 )
+  {
+    a1->field_4 = *(int *)(a2 + 32);
+    a1->field_C = *(int *)a2 << 16;
+    a1->field_10 = *(int *)(a2 + 4) << 16;
+    a1->field_14 = *(int *)(a2 + 8) << 16;
+    a1->field_18 = *(int *)(a2 + 12) << 16;
+    a1->field_1C = *(int *)(a2 + 16);
+    a1->field_20 = *(int *)(a2 + 20);
+    a1->field_24 = *(int *)(a2 + 24);
+    a1->field_28 = *(float *)(a2 + 28) * 65536.0;
+    LODWORD(a1->field_2C) = *(int *)(a2 + 36);
+    a1->field_34 = (signed __int64)(*(float *)(a2 + 40) * 65536.0);
+    a1->field_38 = (signed __int64)(*(float *)(a2 + 44) * 65536.0);
+    a1->field_3C = *(int *)(a2 + 48);
+    a1->field_40 = *(int *)(a2 + 52);
+    a1->field_54 = *(int *)(a2 + 56);
+    a1->field_59 = 1;
+    result = 0;
+  }
+  else
+  {
+    result = 2;
+  }
+  return result;
+}
+
+//----- (0040E0F5) --------------------------------------------------------
+int stru272_stru0::_40E0F5(char a2, char a3)
+{
+  signed int result; // eax@2
+  int v4; // edx@7
+  int v5; // eax@7
+
+  auto a1 = this;
+  if ( a1->field_0 == 0x67707274 )
+  {
+    if ( a2 )
+    {
+      a1->field_8 = 0;
+      a1->field_30 = 0.0;
+    }
+    if ( a1->field_59 && a3 )
+    {
+      v4 = a1->field_4;
+      v5 = a1->field_54;
+      do
+      {
+        *(int *)v5 = 0;
+        v5 += 28;
+        --v4;
+      }
+      while ( v4 );
+      a1->field_58 = 0;
+    }
+    result = 0;
+  }
+  else
+  {
+    result = 2;
+  }
+  return result;
+}
+
+//----- (0040E133) --------------------------------------------------------
+int stru272_stru0::_40E133()
+{
+  stru272_stru0 *v1; // edi@1
+  int v3; // ST18_4@3
+  double v4; // st7@3
+  double v5; // st6@4
+  char v6; // bl@8
+  int v7; // esi@8
+  int v8; // ecx@10
+  signed int v9; // eax@10
+  int v10; // ecx@10
+  signed int v11; // eax@10
+  signed int v12; // edx@12
+  signed int v13; // edx@12
+  int v14; // [sp+8h] [bp-10h]@8
+  int v15; // [sp+Ch] [bp-Ch]@8
+  float v16; // [sp+14h] [bp-4h]@3
+
+  v1 = this;
+  if ( this->field_0 != 0x67707274 )
+    return 2;
+  v3 = this->field_8;
+  v16 = this->field_30;
+  v4 = (double)v3;
+  if ( v3 > 0 )
+  {
+    v5 = v16 + this->field_2C;
+    v16 = v5;
+    if ( v5 > v4 )
+      v16 = v4;
+  }
+  if ( v16 >= 1.0 || this->field_58 )
+  {
+    v6 = 0;
+    v7 = this->field_54;
+    v14 = (signed __int64)this->field_28;
+    v15 = this->field_4;
+    while ( *(int *)v7 <= 0 )
+    {
+      if ( v16 >= 1.0 )
+      {
+        *(int *)v7 = v1->field_3C + rand() % (v1->field_40 - v1->field_3C + 1);
+        *(int *)(v7 + 20) = (rand() % 17 - 8) << 16;
+        *(int *)(v7 + 24) = (rand() % 17 - 8) << 16;
+        v12 = v1->field_C + rand() % (v1->field_14 - 1 - v1->field_C + 1);
+        *(int *)(v7 + 12) = v12;
+        *(int *)(v7 + 4) = v12 >> 16;
+        v16 = v16 - 1.0;
+        v13 = v1->field_10 + rand() % (v1->field_18 - 1 - v1->field_10 + 1);
+        *(int *)(v7 + 16) = v13;
+        *(int *)(v7 + 8) = v13 >> 16;
+        --v1->field_8;
+        goto LABEL_13;
+      }
+LABEL_14:
+      v7 += 28;
+      --v15;
+      if ( !v15 )
+      {
+        v1->field_58 = v6;
+        v1->field_30 = v16;
+        return 0;
+      }
+    }
+    v8 = *(int *)(v7 + 20);
+    --*(int *)v7;
+    v9 = v8 + *(int *)(v7 + 12);
+    v10 = v14 + *(int *)(v7 + 24);
+    *(int *)(v7 + 12) = v9;
+    *(int *)(v7 + 4) = v9 >> 16;
+    v11 = v10 + *(int *)(v7 + 16);
+    *(int *)(v7 + 24) = v10;
+    *(int *)(v7 + 16) = v11;
+    *(int *)(v7 + 8) = v11 >> 16;
+LABEL_13:
+    v6 = 1;
+    goto LABEL_14;
+  }
+  return 0;
+}
+
+//----- (0040E2A7) --------------------------------------------------------
+int stru272_stru0::_40E2A7()
+{
+  int result; // eax@2
+
+  if ( this->field_0 == 0x67707274 )
+  {
+    if ( this->field_8 <= 0 )
+      result = this->field_58 != 0 ? 2 : 0;
+    else
+      result = 1;
+  }
+  else
+  {
+    result = 3;
+  }
+  return result;
+}
+
+
+
+
+
+
+
+//----- (0040F82D) --------------------------------------------------------
+void __fastcall ZBuffer_Fill(int *pZBuffer, int uTextureId, int iZValue)
+{
+  ZBuffer_DoFill(pZBuffer, (Texture *)(uTextureId != -1 ? 72 * uTextureId + 0x6D084C : 0), iZValue);
+}
+
+//----- (0040F845) --------------------------------------------------------
+__int16 __fastcall sub_40F845(int a1, int a2, int a3, int a4, int a5, __int16 a6, int a7)
+{
+  int v7; // edi@1
+  int v8; // esi@1
+  int v9; // ecx@2
+  int v10; // eax@3
+
+  v7 = a1;
+  v8 = a2;
+  do
+  {
+    v9 = a3;
+    do
+    {
+      v10 = *(char *)v8++;
+      if ( (char)v10 )
+      {
+        if ( (char)v10 == 1 )
+        {
+          LOWORD(v10) = *(short *)(a5 + 2 * v10);
+          *(short *)v7 = v10;
+        }
+        else
+        {
+          LOWORD(v10) = a6;
+          *(short *)v7 = a6;
+        }
+      }
+      v7 += 2;
+      --v9;
+    }
+    while ( v9 );
+    v7 = a7 + v7 - a3 - a3;
+    --a4;
+  }
+  while ( a4 );
+  return v10;
+}
+
+//----- (0040F89C) --------------------------------------------------------
+void __fastcall ZBuffer_DoFill(int *pZBuffer, Texture *pTex, int uZValue)
+{
+  void *v3; // eax@3
+  void *v4; // esi@5
+  int *v5; // edi@5
+  int v6; // eax@5
+  int v7; // ecx@6
+  Texture *v8; // [sp+Ch] [bp-14h]@1
+  int *v9; // [sp+10h] [bp-10h]@1
+  int v10; // [sp+14h] [bp-Ch]@1
+  int v11; // [sp+18h] [bp-8h]@1
+  void *v12; // [sp+1Ch] [bp-4h]@5
+
+  v10 = pTex->uTextureWidth;
+  v8 = pTex;
+  v9 = pZBuffer;
+  v11 = pTex->uTextureHeight;
+  if ( pIcons_LOD->dword_011BA4 && pTex->uDecompressedSize )
+    v3 = pTex->UnzipPalette();
+  else
+    v3 = pTex->pLevelOfDetail0;
+  v12 = v3;
+  v4 = v3;
+  v5 = v9;
+  v6 = 0;
+  do
+  {
+    v7 = v10;
+    do
+    {
+      LOBYTE(v6) = *(char *)v4;
+      v4 = (char *)v4 + 1;
+      if ( v6 )
+        *v5 = uZValue;
+      ++v5;
+      --v7;
+    }
+    while ( v7 );
+    v5 += 640 - v10;
+    --v11;
+  }
+  while ( v11 );
+  if ( pIcons_LOD->dword_011BA4 )
+  {
+    if ( v8->uDecompressedSize )
+      free(v12);
+  }
+}
+
+
+//----- (0040F92A) --------------------------------------------------------
+void __fastcall sub_40F92A(int *pZBuffer, Texture *a2, int a3)
+{
+  Texture *v3; // esi@1
+  void *v4; // eax@3
+  int *v5; // edi@5
+  int v6; // ecx@6
+  int *v7; // [sp+Ch] [bp-10h]@1
+  int v8; // [sp+10h] [bp-Ch]@1
+  int v9; // [sp+18h] [bp-4h]@1
+
+  v3 = a2;
+  v7 = pZBuffer;
+  v8 = a2->uTextureWidth;
+  v9 = a2->uTextureHeight;
+  if ( pIcons_LOD->dword_011BA4 && a2->uDecompressedSize )
+    v4 = a2->UnzipPalette();
+  else
+    v4 = a2->pLevelOfDetail0;
+  v5 = v7;
+  do
+  {
+    v6 = v8;
+    do
+    {
+      *v5 = a3;
+      ++v5;
+      --v6;
+    }
+    while ( v6 );
+    v5 += 640 - v8;
+    --v9;
+  }
+  while ( v9 );
+  if ( pIcons_LOD->dword_011BA4 )
+  {
+    if ( v3->uDecompressedSize )
+      free(v4);
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//----- (00410AF5) --------------------------------------------------------
+void __cdecl SetMoonPhaseNames()
+{
+  aMoonPhaseNames[0] = pGlobalTXT_LocalizationStrings[150];
+  aMoonPhaseNames[1] = pGlobalTXT_LocalizationStrings[171];
+  aMoonPhaseNames[2] = pGlobalTXT_LocalizationStrings[102];
+  aMoonPhaseNames[3] = pGlobalTXT_LocalizationStrings[169];
+  aMoonPhaseNames[4] = pGlobalTXT_LocalizationStrings[92];
+}
+
+//----- (00410B28) --------------------------------------------------------
+void __thiscall DrawSpellDescriptionPopup(void *_this)
+{
+  Player *v1; // edi@1
+  SpellInfo *v2; // esi@1
+  unsigned int v3; // eax@2
+  int v4; // eax@4
+  LONG v5; // ecx@4
+  int v6; // eax@10
+  char *v7; // ST44_4@12
+  unsigned __int16 v8; // ax@12
+  GUIWindow a1; // [sp+Ch] [bp-68h]@4
+  void *v10; // [sp+60h] [bp-14h]@1
+  POINT a2; // [sp+64h] [bp-10h]@1
+  int v12; // [sp+6Ch] [bp-8h]@4
+  int v13; // [sp+70h] [bp-4h]@4
+
+  v1 = pPlayers[uActiveCharacter];
+  v10 = _this;
+  v2 = &pSpellStats->pInfos[(signed int)((char *)_this + 11 * v1->pNumSpellBookPage) + 1];
+  if ( pMouse->GetCursorPos(&a2)->y <= 250 )
+    v3 = pMouse->GetCursorPos(&a2)->y + 30;
+  else
+    v3 = 30;
+  a1.uFrameY = v3;
+  a1.uFrameWidth = 328;
+  a1.uFrameHeight = 68;
+  a1.uFrameX = 90;
+  a1.uFrameZ = 417;
+  a1.uFrameW = v3 + 67;
+  a1.Hint = 0;
+  a2.y = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[431]);
+  v13 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[433]);
+  v12 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[432]);
+  v4 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[96]);
+  v5 = a2.y;
+  if ( v13 > a2.y )
+    v5 = v13;
+  if ( v12 > v5 )
+    v5 = v12;
+  if ( v4 > v5 )
+    v5 = v4;
+  sprintf(
+    pTmpBuf2,
+    "%s\n\n%s\t%03d:\t%03d%s\t000\n%s\t%03d:\t%03d%s\t000\n%s\t%03d:\t%03d%s\t000\n%s\t%03d:\t%03d%s",
+    v2->pDescription,
+    pGlobalTXT_LocalizationStrings[431],
+    v5 + 3,
+    v5 + 10,
+    v2->pBasicSkillDesc,
+    pGlobalTXT_LocalizationStrings[433],
+    v5 + 3,
+    v5 + 10,
+    v2->pExpertSkillDesc,
+    pGlobalTXT_LocalizationStrings[432],
+    v5 + 3,
+    v5 + 10,
+    v2->pMasterSkillDesc,
+    pGlobalTXT_LocalizationStrings[96],
+    v5 + 3,
+    v5 + 10,
+    v2->pGrandmasterSkillDesc);
+  v6 = pFontSmallnum->CalcTextHeight(pTmpBuf2, &a1, 0, 0);
+  a1.uFrameHeight += v6;
+  if ( (signed int)a1.uFrameHeight < 150 )
+    a1.uFrameHeight = 150;
+  a1.uFrameWidth = 460;
+  a1.DrawMessageBox(0);
+  a1.uFrameWidth -= 12;
+  a1.uFrameHeight -= 12;
+  v7 = v2->pName;
+  a1.uFrameZ = a1.uFrameX + a1.uFrameWidth - 1;
+  a1.uFrameW = a1.uFrameHeight + a1.uFrameY - 1;
+  v8 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  a1.DrawTitleText(pFontArrus, 0x78u, 0xCu, v8, v7, 3u);
+  a1.DrawText(pFontSmallnum, 120, 44, 0, pTmpBuf2, 0, 0, 0);
+  a1.uFrameWidth = 108;
+  a1.uFrameZ = a1.uFrameX + 107;
+  a1.DrawTitleText(pFontComic, 0xCu, 0x4Bu, 0, pSkillNames[v1->pNumSpellBookPage + 12], 3u);
+  sprintf(
+    pTmpBuf,
+    "%s\n%d",
+    pGlobalTXT_LocalizationStrings[522],
+    *(&pSpellDatas[0].field_14
+    + ((unsigned int)LOBYTE(v1->pActiveSkills[v1->pNumSpellBookPage + 12]) >> 6)
+    + 10 * (int)((char *)v10 + 11 * v1->pNumSpellBookPage)));
+  a1.DrawTitleText(pFontComic, 0xCu, a1.uFrameHeight - LOBYTE(pFontComic->uFontHeight) - 16, 0, pTmpBuf, 3u);
+  dword_507B00_spell_info_to_draw_in_popup = 0;
+}
+// 507B00: using guessed type int dword_507B00_spell_info_to_draw_in_popup;
+
+//----- (00410D99) --------------------------------------------------------
+signed int __fastcall sub_410D99_get_map_index(int a1)
+{
+  int v1; // edi@1
+  signed int v2; // ebp@1
+  const char **v3; // esi@2
+  char *v4; // ebx@2
+
+  v1 = a1;
+  v2 = 1;
+  if ( _strcmpi(pMapStats->pInfos[1].pFilename, (const char *)&pGames_LOD->pSubIndices[a1]) )
+  {
+    v3 = (const char **)&pMapStats->pInfos[1].pFilename;
+    v4 = (char *)&pMapStats->pInfos[1].pFilename;
+    do
+    {
+      if ( !*(int *)v4 )
+        break;
+      v3 += 17;
+      ++v2;
+      v4 = (char *)v3;
+    }
+    while ( _strcmpi(*v3, (const char *)&pGames_LOD->pSubIndices[v1]) );
+  }
+  return v2;
+}
+
+//----- (00410DEC) --------------------------------------------------------
+unsigned int __cdecl DrawLloydBeaconsScreen()
+{
+  Player *v0; // esi@1
+  char *v1; // eax@1
+  unsigned __int16 v2; // ax@6
+  unsigned int result; // eax@11
+  unsigned int v4; // esi@13
+  unsigned int v5; // ecx@13
+  char v6; // zf@13
+  LloydBeacon *v7; // esi@14
+  int v8; // eax@14
+  unsigned __int64 v9; // kr08_8@14
+  unsigned int v10; // esi@14
+  unsigned int v11; // eax@14
+  char *v12; // eax@19
+  char *v13; // ecx@22
+  int v14; // eax@27
+  unsigned int v15; // [sp-10h] [bp-98h]@25
+  unsigned __int16 v16; // [sp-Ch] [bp-94h]@25
+  int v17; // [sp-8h] [bp-90h]@21
+  char *v18; // [sp-8h] [bp-90h]@25
+  Texture *v19; // [sp-4h] [bp-8Ch]@4
+  char *v20; // [sp-4h] [bp-8Ch]@21
+  unsigned int v21; // [sp-4h] [bp-8Ch]@25
+  GUIWindow v22; // [sp+Ch] [bp-7Ch]@1
+  unsigned int v23; // [sp+64h] [bp-24h]@14
+  __int64 v24; // [sp+68h] [bp-20h]@14
+  unsigned int v25; // [sp+70h] [bp-18h]@13
+  char *Str; // [sp+74h] [bp-14h]@14
+  int v27; // [sp+78h] [bp-10h]@11
+  LloydBeacon *v28; // [sp+7Ch] [bp-Ch]@12
+  RGBTexture *v29; // [sp+80h] [bp-8h]@12
+  int uNumMaxBeacons; // [sp+84h] [bp-4h]@6
+
+  v0 = &pParty->pPlayers[_506348_current_lloyd_playerid];
+  pRenderer->DrawTextureIndexed(8u, 8u, pTexture_LloydBeacons[(unsigned __int8)bRecallingBeacon]);
+  v1 = pGlobalTXT_LocalizationStrings[523];     // Recall Beacon
+  v22.uFrameX = 8;
+  v22.uFrameY = 8;
+  v22.uFrameWidth = 428;
+  v22.uFrameHeight = 344;
+  v22.uFrameZ = 435;
+  v22.uFrameW = 351;
+  if ( !bRecallingBeacon )
+    v1 = pGlobalTXT_LocalizationStrings[375];   // Set Beacon
+  sprintf(pTmpBuf, "%s", v1);
+  v22.DrawTitleText(pBook2Font, 0, 22u, 0, pTmpBuf, 3u);
+  if ( bRecallingBeacon )
+  {
+    pRenderer->DrawTextureTransparent(pBtn_Book_1->uX, pBtn_Book_1->uY, pTex_tab_an_6b__zoom_on);
+    v19 = pTex_tab_an_6a__zoom_off;
+  }
+  else
+  {
+    pRenderer->DrawTextureTransparent(pBtn_Book_1->uX, pBtn_Book_1->uY, pTex_tab_an_6a__zoom_off);
+    v19 = pTex_tab_an_6b__zoom_on;
+  }
+  pRenderer->DrawTextureTransparent(pBtn_Book_2->uX, pBtn_Book_2->uY, v19);
+  v2 = v0->pActiveSkills[14];
+  uNumMaxBeacons = 1;
+  if ( HIBYTE(v2) & 1 || (v2 & 0x80u) != 0 )
+  {
+    uNumMaxBeacons = 5;
+  }
+  else
+  {
+    if ( v2 & 0x40 )
+      uNumMaxBeacons = 3;
+  }
+  result = 0;
+  v27 = 0;
+  if ( uNumMaxBeacons > 0 )
+  {
+    v29 = pSavegameThumbnails;
+    v28 = v0->pInstalledBeacons;
+    while ( 1 )
+    {
+      v22.uFrameWidth = 92;
+      v4 = result;
+      v22.uFrameHeight = 68;
+      v5 = pLloydsBeaconsPreviewXs[result];
+      v22.uFrameY = pLloydsBeaconsPreviewYs[result];
+      v25 = v22.uFrameY;
+      v22.uFrameX = v5;
+      v22.uFrameW = v22.uFrameY + 67;
+      v6 = v29->pPixels == 0;
+      v22.uFrameZ = v5 + 91;
+      if ( !v6 )
+        break;
+      if ( !bRecallingBeacon )
+      {
+        pRenderer->DrawTextureTransparent(
+          pLloydsBeacons_SomeXs[v4],
+          pLloydsBeacons_SomeYs[v4],
+          pTexture_CurrentBook);
+        v21 = 3;
+        v18 = pGlobalTXT_LocalizationStrings[19];
+        v16 = 1;
+        v14 = pSpellFont->CalcTextHeight(pGlobalTXT_LocalizationStrings[19], &v22, 0, 0);
+        v15 = (signed int)v22.uFrameHeight / 2 - v14 / 2;
+        goto LABEL_28;
+      }
+LABEL_29:
+      ++v29;
+      ++v28;
+      result = v27++ + 1;
+      if ( v27 >= uNumMaxBeacons )
+        goto LABEL_30;
+    }
+    pRenderer->DrawTextureTransparent(
+      pLloydsBeacons_SomeXs[v4],
+      pLloydsBeacons_SomeYs[v4],
+      pTexture_CurrentBook);
+    pRenderer->DrawTextureRGB(pLloydsBeaconsPreviewXs[v4], pLloydsBeaconsPreviewYs[v4], v29);
+    v7 = v28;
+    Str = pMapStats->pInfos[sub_410D99_get_map_index(HIWORD(v28->field_18))].pName;
+    v8 = pSpellFont->CalcTextHeight(Str, &v22, 0, 0);
+    v22.uFrameY += -6 - v8;
+    v22.DrawTitleText(pSpellFont, 0, 0, 1u, Str, 3u);
+    v9 = v7->uBeaconTime - pParty->uTimePlayed;
+    LODWORD(v24) = LODWORD(v7->uBeaconTime) - LODWORD(pParty->uTimePlayed);
+    HIDWORD(v24) = HIDWORD(v9);
+    v23 = (unsigned __int64)((signed __int64)((double)v24 * 0.234375) / 60 / 60) >> 32;
+    v10 = (signed __int64)((double)v24 * 0.234375) / 60 / 60;
+    v11 = v10 / 0x18;
+    if ( (unsigned int)((signed __int64)((double)v24 * 0.234375) / 60 / 60) / 0x18 )
+    {
+      v13 = pGlobalTXT_LocalizationStrings[57]; // Days
+      if ( v11 > 1 )
+      {
+LABEL_24:
+        v20 = v13;
+        v17 = v11 + 1;
+LABEL_25:
+        sprintf(pTmpBuf, "%lu %s", v17, v20);
+        v21 = 3;
+        v18 = pTmpBuf;
+        v16 = 1;
+        v22.uFrameY = v25 + v22.uFrameHeight + 4;
+        v15 = 0;
+LABEL_28:
+        v22.DrawTitleText(pSpellFont, 0, v15, v16, v18, v21);
+        goto LABEL_29;
+      }
+    }
+    else
+    {
+      if ( (signed __int64)(__PAIR__(v23, v10) + 1) <= 23 )
+      {
+        if ( (v23 & 0x80000000u) != 0 || (signed int)v23 <= 0 && v10 <= 1 )
+          v12 = pGlobalTXT_LocalizationStrings[109];// Hour
+        else
+          v12 = pGlobalTXT_LocalizationStrings[110];// Hours
+        v20 = v12;
+        v17 = v10 + 1;
+        goto LABEL_25;
+      }
+    }
+    v13 = pGlobalTXT_LocalizationStrings[56];   // Day
+    goto LABEL_24;
+  }
+LABEL_30:
+  if ( byte_506360 )
+  {
+    result = pMessageQueue_50CBD0->uNumMessages;
+    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)181;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+      result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
+      *(&pMessageQueue_50CBD0->uNumMessages + result) = 0;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+  }
+  return result;
+}
+
+
+//----- (00411150) --------------------------------------------------------
+char *__cdecl DrawTownPortalScreen()
+{
+  signed int v0; // edi@1
+  __int16 v1; // dx@8
+  POINT *v2; // edi@17
+  int v3; // edi@17
+  __int16 v4; // dx@24
+  GUIWindow v6; // [sp+Ch] [bp-64h]@1
+  POINT v7; // [sp+60h] [bp-10h]@17
+  POINT a2; // [sp+68h] [bp-8h]@17
+
+  pRenderer->ClearZBuffer(0, 479);
+  pRenderer->DrawTextureTransparent(8u, 8u, pTexture_CurrentBook);
+  pRenderer->DrawTextureTransparent(
+    0x1D7u,
+    0x1BDu,
+    (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0));
+  v6.uFrameX = 8;
+  v6.uFrameY = 8;
+  v6.uFrameWidth = 460;
+  v6.uFrameHeight = 344;
+  v6.uFrameZ = 467;
+  v6.uFrameW = 351;
+  v0 = 0;
+  do
+  {
+    if ( !v0 )
+    {
+      v1 = 206;
+LABEL_14:
+      if ( !(unsigned __int16)_449B57_test_bit(pParty->_award_bits, v1) )
+        goto LABEL_16;
+      goto LABEL_15;
+    }
+    if ( v0 == 1 )
+    {
+      v1 = 208;
+      goto LABEL_14;
+    }
+    if ( v0 == 2 )
+    {
+      v1 = 207;
+      goto LABEL_14;
+    }
+    if ( v0 == 3 )
+    {
+      v1 = 211;
+      goto LABEL_14;
+    }
+    if ( v0 == 4 )
+    {
+      v1 = 209;
+      goto LABEL_14;
+    }
+    if ( v0 == 5 )
+    {
+      v1 = 210;
+      goto LABEL_14;
+    }
+LABEL_15:
+    pRenderer->_4A612A(
+      pTownPortalBook_xs[v0],
+      pTownPortalBook_ys[v0],
+      *(&pTexture_TownPortalHarmn + v0),
+      v0 + 1);
+LABEL_16:
+    ++v0;
+  }
+  while ( v0 < 6 );
+  v2 = pMouse->GetCursorPos(&a2);
+  v3 = pRenderer->pActiveZBuffer[v2->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&v7)->y]] & 0xFFFF;
+  if ( !v3 )                                    // Town Portal
+    return v6.DrawTitleText(pBook2Font, 0, 22u, 0, pGlobalTXT_LocalizationStrings[10], 3u);
+  if ( v3 == 1 )
+  {
+    v4 = 206;
+LABEL_30:
+    if ( (unsigned __int16)_449B57_test_bit(pParty->_award_bits, v4) )
+      goto LABEL_31;
+    return v6.DrawTitleText(pBook2Font, 0, 22u, 0, pGlobalTXT_LocalizationStrings[10], 3u);
+  }
+  if ( v3 == 2 )
+  {
+    v4 = 208;
+    goto LABEL_30;
+  }
+  if ( v3 == 3 )
+  {
+    v4 = 207;
+    goto LABEL_30;
+  }
+  if ( v3 == 4 )
+  {
+    v4 = 211;
+    goto LABEL_30;
+  }
+  if ( v3 == 5 )
+  {
+    v4 = 209;
+    goto LABEL_30;
+  }
+  if ( v3 == 6 )
+  {
+    v4 = 210;
+    goto LABEL_30;
+  }
+LABEL_31:
+  pRenderer->DrawTextureIndexed(word_4E1D3A[v3], pTownPortalBook_xs[v3 + 5], *(&pTex_tab_an_6b__zoom_on + v3));
+  return v6.DrawTitleText(pBook2Font, 0, 22u, 0, pGlobalTXT_LocalizationStrings[10], 3u);
+}
+// 4E1D3A: using guessed type __int16 word_4E1D3A[];
+
+//----- (00411300) --------------------------------------------------------
+Texture *__fastcall LoadSpellbook(unsigned int uID)
+{
+  unsigned int v1; // esi@1
+  Player *pPlayer; // ecx@1
+  char v3; // al@1
+  int v4; // edi@5
+  Texture *result; // eax@6
+  char *v6; // edi@7
+  unsigned int v7; // eax@7
+  unsigned __int8 v8; // sf@8
+  unsigned __int8 v9; // of@8
+  char pContainer[20]; // [sp+Ch] [bp-1Ch]@7
+  Texture *v11; // [sp+20h] [bp-8h]@5
+  int v12; // [sp+24h] [bp-4h]@5
+
+  byte_506550 = 0;
+  v1 = uID;
+  pPlayer = pPlayers[uActiveCharacter];
+  v3 = pPlayer->uQuickSpell;
+  if ( v3 && (unsigned __int8)v3 / 11 == v1 )
+    dword_50654C = (unsigned __int8)v3 - 11 * v1;
+  else
+    dword_50654C = 0;
+  v4 = 1;
+  v12 = 1;
+  v11 = (Texture *)&pPlayer->field_152[11 * v1 + 63];
+  do
+  {
+    result = v11;
+    if ( v11->pName[v4] )
+    {
+      v6 = &byte_4E2430[12 * v1] + v4;
+      sprintf(pContainer, "SB%sS%02d", spellbook_texture_filename_suffices[v1], (unsigned __int8)*v6);
+      v7 = pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE);
+      dword_506408[v12] = 72 * v7 + 7145548;
+      sprintf(pContainer, "SB%sC%02d", spellbook_texture_filename_suffices[v1], (unsigned __int8)*v6);
+      result = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE)];
+      dword_5063D8[v12] = result;
+    }
+    v4 = v12 + 1;
+    v9 = __OFSUB__(v12 + 1, 12);
+    v8 = v12++ - 11 < 0;
+  }
+  while ( v8 ^ v9 );
+  return result;
+}
+// 4E1D18: using guessed type char *spellbook_texture_filename_suffices[8];
+// 506408: using guessed type int dword_506408[];
+// 50654C: using guessed type int dword_50654C;
+// 506550: using guessed type char byte_506550;
+
+//----- (0041140B) --------------------------------------------------------
+GUIWindow *__cdecl sub_41140B()
+{
+  signed int v0; // esi@1
+  GUIButton *v1; // eax@3
+  GUIButton *v2; // esi@4
+  GUIWindow *result; // eax@5
+
+  v0 = 0;
+  do
+  {
+    dword_506404[v0]->Release();
+    dword_506434[v0]->Release();
+    --v0;
+  }
+  while ( v0 >= -11 );
+  pIcons_LOD->_40F9C5();
+  v1 = pGUIWindow_CurrentMenu->pControlsHead;
+  if ( v1 )
+  {
+    do
+    {
+      v2 = v1->pNext;
+      pAllocator->FreeChunk(v1);
+      v1 = v2;
+    }
+    while ( v2 );
+  }
+  pGUIWindow_CurrentMenu->pControlsHead = 0;
+  pGUIWindow_CurrentMenu->pControlsTail = 0;
+  result = pGUIWindow_CurrentMenu;
+  pGUIWindow_CurrentMenu->uNumControls = 0;
+  return result;
+}
+
+//----- (00411473) --------------------------------------------------------
+void __cdecl sub_411473()
+{
+  Texture **v0; // esi@1
+  Texture **v1; // edi@1
+  Texture *v2; // ecx@2
+  Texture *v3; // ecx@2
+
+  pTexture_pagemask->Release();
+  pTexture_506448->Release();
+  pTexture_50643C->Release();
+  v0 = &pTextures_tabs[0][1];
+  v1 = pTextures_5064A0;
+  do
+  {
+    (*v1)->Release();
+    v2 = (Texture *)*((int *)v0 - 1);
+    *v1 = 0;
+    v2->Release();
+    v3 = *(Texture **)v0;
+    *((int *)v0 - 1) = 0;
+    v3->Release();
+    *(int *)v0 = 0;
+    ++v1;
+    v0 += 8;
+  }
+  while ( (signed int)v1 < (signed int)&pTextures_5064A0[9] );
+  pAudioPlayer->PlaySound((SoundID)231, 0, 0, -1, 0, 0, 0, 0);
+  pIcons_LOD->_4114F2();
+}
+
+
+//----- (00411597) --------------------------------------------------------
+void __cdecl OnCloseSpellook()
+{
+  pAllocator->FreeChunk(pSpellFont);
+  pSpellFont = 0;
+  pAllocator->FreeChunk(pBookFont);
+  pBookFont = 0;
+  pAllocator->FreeChunk(pBook2Font);
+  pBook2Font = 0;
+  pAllocator->FreeChunk(pAutonoteFont);
+  pAutonoteFont = 0;
+  pTexture_mapbordr->Release();
+  pAudioPlayer->PlaySound((SoundID)231, 0, 0, -1, 0, 0, 0, 0);
+  pIcons_LOD->_4114F2();
+  dword_506364 = 0;
+}
+// 506364: using guessed type int dword_506364;
+
+
+
+
+
+
+
+//----- (00412AF9) --------------------------------------------------------
+void __cdecl sub_412AF9()
+{
+  int v0; // ecx@1
+
+  v0 = 0;
+  if ( uActiveCharacter )
+    v0 = *((char *)&pParty->pPartyBuffs[5].uExpireTime + 6972 * uActiveCharacter + 2);
+  pRenderer->DrawTextureIndexed(8u, 8u, pTextures_5064A0[v0]);
+  pRenderer->DrawTextureIndexed(0x1DCu, 0x1C2u, pTexture_50643C);
+  pRenderer->DrawTextureIndexed(0x231u, 0x1C2u, pTexture_506448);
+}
+
+//----- (00412B58) --------------------------------------------------------
+void __cdecl sub_412B58()
+{
+  Player *v0; // ebx@1
+  int v1; // ebp@1
+  unsigned int v2; // eax@1
+  Texture *v3; // edi@1
+  int v4; // esi@1
+  Texture *v5; // eax@3
+  Texture *v6; // edx@5
+  int v7; // eax@8
+  int v8; // eax@11
+  POINT *v9; // esi@13
+  int v10; // eax@13
+  Texture *v11; // edx@14
+  int v12; // eax@15
+  signed int v13; // ecx@18
+  unsigned int v14; // esi@18
+  unsigned int v15; // edi@18
+  Texture *v16; // eax@21
+  unsigned int v17; // [sp-Ch] [bp-2Ch]@8
+  unsigned int v18; // [sp-Ch] [bp-2Ch]@15
+  unsigned int v19; // [sp-8h] [bp-28h]@8
+  unsigned int v20; // [sp-8h] [bp-28h]@15
+  Texture *v21; // [sp-4h] [bp-24h]@15
+  signed int v22; // [sp-4h] [bp-24h]@22
+  int v23[2]; // [sp+10h] [bp-10h]@5
+  POINT a2; // [sp+18h] [bp-8h]@13
+
+  sub_412AF9();
+  v0 = pPlayers[uActiveCharacter];
+  v1 = 11 * v0->pNumSpellBookPage;
+  v2 = pIcons_LOD->FindTextureByName("Pending");
+  v3 = (Texture *)(v2 != -1 ? (int)&pIcons_LOD->pTextures[v2] : 0);
+  pRenderer->ClearZBuffer(0, 479);
+  v4 = 1;
+  if ( __OFSUB__(v1, v1 + 11) ^ 1 )
+  {
+    do
+    {
+      if ( *(&v0->field_152[v1 + 63] + v4) )
+      {
+        v5 = (Texture *)dword_506408[v4];
+        if ( v5 != v3 )
+        {
+          if ( dword_50654C == v4 )
+          {
+            v6 = dword_5063D8[v4];
+            v23[0] = (int)dword_5063D8[v4];
+          }
+          else
+          {
+            v23[0] = dword_506408[v4];
+            v6 = v5;
+          }
+          if ( v6->pLevelOfDetail0 )
+          {
+            v7 = 2 * (12 * v0->pNumSpellBookPage + (unsigned __int8)*(&byte_4E2430[12 * v0->pNumSpellBookPage + v4]));
+            v19 = pViewport->uViewportY + dword_4E20D0[v7 + 1];
+            v17 = pViewport->uViewportX + dword_4E20D0[v7];
+            if ( BYTE1(v6->pBits) & 2 )
+              pRenderer->DrawTextureTransparent(v17, v19, v6);
+            else
+              pRenderer->DrawTextureIndexed(v17, v19, v6);
+            v8 = 2 * (12 * v0->pNumSpellBookPage + (unsigned __int8)*(&byte_4E2430[12 * v0->pNumSpellBookPage] + v4));
+            pRenderer->_4A612A(dword_4E20D0[v8], dword_4E20D0[v8 + 1], (Texture *)v23[0], v4);
+          }
+        }
+      }
+      ++v4;
+    }
+    while ( v4 + v1 - 1 < v1 + 11 );
+  }
+  v9 = pMouse->GetCursorPos(&a2);
+  v10 = pRenderer->pActiveZBuffer[v9->x + pSRZBufferLineOffsets[pMouse->GetCursorPos((POINT *)v23)->y]] & 0xFFFF;
+  if ( v10 )
+  {
+    v11 = dword_5063D8[v10];
+    if ( v11->pLevelOfDetail0 )
+    {
+      v21 = dword_5063D8[v10];
+      v12 = 2 * (12 * v0->pNumSpellBookPage + (unsigned __int8)*(&byte_4E2430[12 * v0->pNumSpellBookPage] + v10));
+      v20 = pViewport->uViewportY + dword_4E20D0[v12 + 1];
+      v18 = pViewport->uViewportX + dword_4E20D0[v12];
+      if ( BYTE1(v11->pBits) & 2 )
+        pRenderer->DrawTextureTransparent(v18, v20, v21);
+      else
+        pRenderer->DrawTextureIndexed(v18, v20, v21);
+    }
+  }
+  v13 = 0;
+  a2.x = (LONG)&v0->pActiveSkills[12];
+  v14 = (unsigned int)&v0->pActiveSkills[12];
+  v15 = (unsigned int)&v0->pActiveSkills[12];
+  v23[0] = 0;
+  do
+  {
+    if ( *(short *)a2.x )
+    {
+      if ( v0->pNumSpellBookPage == v13 )
+      {
+        v16 = pTextures_tabs[v13][1];
+        switch ( v13 )
+        {
+          case 0:
+            v14 = 406;
+            v22 = 9;
+            goto LABEL_27;
+          case 1:
+            v14 = 406;
+            goto LABEL_38;
+          case 2:
+            v14 = 406;
+            v22 = 84;
+            goto LABEL_27;
+          case 3:
+            v14 = 406;
+            goto LABEL_26;
+          case 4:
+            v14 = 407;
+            goto LABEL_29;
+          case 5:
+            v15 = 196;
+            goto LABEL_34;
+          case 6:
+            v15 = 234;
+            goto LABEL_34;
+          case 7:
+            v15 = 272;
+            goto LABEL_34;
+          case 8:
+            v15 = 309;
+LABEL_34:
+            v14 = 405;
+            break;
+          default:
+            break;
+        }
+      }
+      else
+      {
+        v16 = pTextures_tabs[v13][0];
+        switch ( v13 )
+        {
+          case 0:
+            v14 = 415;
+            v22 = 10;
+            goto LABEL_27;
+          case 1:
+            v14 = 415;
+LABEL_38:
+            v22 = 46;
+            goto LABEL_27;
+          case 2:
+            v14 = 415;
+            v22 = 83;
+            goto LABEL_27;
+          case 3:
+            v14 = 415;
+LABEL_26:
+            v22 = 121;
+LABEL_27:
+            v15 = v22;
+            break;
+          case 4:
+            v14 = 415;
+LABEL_29:
+            v15 = 158;
+            break;
+          case 5:
+            v15 = 196;
+            goto LABEL_46;
+          case 6:
+            v15 = 234;
+            goto LABEL_46;
+          case 7:
+            v15 = 271;
+            goto LABEL_46;
+          case 8:
+            v15 = 307;
+LABEL_46:
+            v14 = 416;
+            break;
+          default:
+            break;
+        }
+      }
+      pRenderer->DrawTextureTransparent(v14, v15, v16);
+      v13 = v23[0];
+    }
+    a2.x += 2;
+    ++v13;
+    v23[0] = v13;
+  }
+  while ( v13 < 9 );
+}
+// 506408: using guessed type int dword_506408[];
+// 50654C: using guessed type int dword_50654C;
+
+//----- (00412E85) --------------------------------------------------------
+char __cdecl sub_412E85()
+{
+  unsigned int v0; // eax@3
+  unsigned int v1; // eax@7
+  int v2; // eax@10
+  const char *v3; // eax@10
+  signed int v4; // ecx@12
+  int v5; // ecx@14
+  int v6; // eax@21
+  int v7; // esi@21
+  char *v8; // eax@21
+  int v9; // eax@22
+  unsigned int v11; // [sp-8h] [bp-64h]@3
+  unsigned int v12; // [sp-8h] [bp-64h]@7
+  Texture *v13; // [sp-4h] [bp-60h]@3
+  Texture *v14; // [sp-4h] [bp-60h]@7
+  GUIWindow a1; // [sp+8h] [bp-54h]@10
+
+  pRenderer->DrawTextureIndexed(pViewport->uViewportX, pViewport->uViewportY, pTextures_5064A0[11]);
+  if ( dword_506548 || !dword_506528 )
+  {
+    v13 = pTex_tab_an_6a__zoom_off;
+    v11 = pViewport->uViewportY + 2;
+    v0 = pViewport->uViewportX + 407;
+  }
+  else
+  {
+    v13 = pTex_tab_an_6b__zoom_on;
+    v11 = pViewport->uViewportY + 1;
+    v0 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v0, v11, v13);
+  if ( dword_506544 || dword_506528 + dword_506520 >= dword_506524 )
+  {
+    v14 = pTex_tab_an_7a__zoot_off;
+    v12 = pViewport->uViewportY + 38;
+    v1 = pViewport->uViewportX + 407;
+  }
+  else
+  {
+    v14 = pTex_tab_an_7b__zoot_on;
+    v12 = pViewport->uViewportY + 38;
+    v1 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v1, v12, v14);
+  if ( !byte_5C6D50[dword_506528] )
+  {
+    v2 = pStru179->field_0[dword_506528];
+    a1.uFrameWidth = 460;
+    a1.uFrameX = 8;
+    a1.uFrameY = 8;
+    a1.uFrameHeight = 344;
+    v3 = (const char *)pStorylineText->field_4[3 * v2];
+    a1.uFrameZ = 467;
+    a1.uFrameW = 351;
+    if ( v3 )
+      a1.DrawTitleText(pBook2Font, 0, 0x16u, 0, v3, 3u);
+  }
+  a1.uFrameX = 48;
+  a1.uFrameY = 70;
+  a1.uFrameWidth = 360;
+  a1.uFrameHeight = 264;
+  v4 = LOBYTE(pAutonoteFont->uFontHeight) - 3;
+  a1.uFrameZ = 407;
+  a1.uFrameHeight = v4 * 264 / v4;
+  a1.uFrameW = a1.uFrameHeight + 69;
+  if ( dword_506544 && dword_506528 + dword_506520 < dword_506524 )
+  {
+    pAudioPlayer->PlaySound((SoundID)230, 0, 0, -1, 0, 0, 0, 0);
+    v5 = dword_50651C++;
+    dword_506528 += dword_506520;
+    byte_506130[v5] = dword_506520;
+  }
+  if ( dword_506548 && dword_50651C )
+  {
+    pAudioPlayer->PlaySound((SoundID)230, 0, 0, -1, 0, 0, 0, 0);
+    --dword_50651C;
+    dword_506528 -= (unsigned __int8)byte_506130[dword_50651C];
+  }
+  if ( !dword_506520 || dword_506528 < 1 )
+  {
+    dword_506528 = 0;
+    dword_50651C = 0;
+  }
+  dword_506544 = 0;
+  v6 = pStru179->field_0[dword_506528];
+  dword_506548 = 0;
+  dword_506520 = 0;
+  v7 = *(&pStorylineText->field_0 + 3 * v6);
+  v8 = sub_495461(
+         *((char **)&pStorylineText->field_0 + 3 * v6),
+         uActiveCharacter - 1,
+         0,
+         0,
+         0,
+         (__int64 *)&pParty->field_3C.field_440[2 * v6 + 42]);
+  if ( v7 )
+  {
+    v9 = pAutonoteFont->_44C6C2(v8, &a1, 1u, (unsigned __int8)byte_5C6D50[dword_506528]);
+    LOBYTE(v8) = a1.DrawText(pAutonoteFont, 1, 0, 0, (const char *)v9, 0, a1.uFrameY + a1.uFrameHeight, 0);
+    ++dword_506520;
+  }
+  return (char)v8;
+}
+
+
+//----- (00413126) --------------------------------------------------------
+void __cdecl DrawSpellbook_Quests()
+{
+  unsigned int v0; // eax@3
+  unsigned int v1; // eax@7
+  int v2; // ecx@11
+  int v3; // ebx@16
+  int v4; // eax@19
+  const char *v5; // edi@19
+  int v6; // eax@19
+  unsigned int v7; // edi@19
+  unsigned int v8; // [sp-8h] [bp-68h]@3
+  unsigned int v9; // [sp-8h] [bp-68h]@7
+  Texture *v10; // [sp-4h] [bp-64h]@3
+  Texture *v11; // [sp-4h] [bp-64h]@7
+  GUIWindow a1; // [sp+Ch] [bp-54h]@9
+
+  pRenderer->DrawTextureIndexed(pViewport->uViewportX, pViewport->uViewportY, pTexture_CurrentBook);
+  if ( dword_506548 || !dword_506528 )
+  {
+    v10 = pTex_tab_an_6a__zoom_off;
+    v8 = pViewport->uViewportY + 2;
+    v0 = pViewport->uViewportX + 407;
+  }
+  else
+  {
+    v10 = pTex_tab_an_6b__zoom_on;
+    v8 = pViewport->uViewportY + 1;
+    v0 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v0, v8, v10);
+  if ( dword_506544 || dword_506528 + dword_506520 >= dword_506524 )
+  {
+    v11 = pTex_tab_an_7a__zoot_off;
+    v9 = pViewport->uViewportY + 38;
+    v1 = pViewport->uViewportX + 407;
+  }
+  else
+  {
+    v11 = pTex_tab_an_7b__zoot_on;
+    v9 = pViewport->uViewportY + 38;
+    v1 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v1, v9, v11);
+  a1.uFrameWidth = 460;
+  a1.uFrameHeight = 344;
+  a1.uFrameX = 8;
+  a1.uFrameY = 8;
+  a1.uFrameZ = 467;
+  a1.uFrameW = 351;
+  a1.DrawTitleText(pBook2Font, 0, 0x16u, 0, pGlobalTXT_LocalizationStrings[174], 3u);
+  a1.uFrameX = 48;
+  a1.uFrameY = 70;
+  a1.uFrameWidth = 360;
+  a1.uFrameHeight = 264;
+  a1.uFrameZ = 407;
+  a1.uFrameW = 333;
+  if ( dword_506544 && dword_506528 + dword_506520 < dword_506524 )
+  {
+    pAudioPlayer->PlaySound((SoundID)230, 0, 0, -1, 0, 0, 0, 0);
+    v2 = dword_50651C++;
+    dword_506528 += dword_506520;
+    byte_506130[v2] = dword_506520;
+  }
+  if ( dword_506548 && dword_50651C )
+  {
+    pAudioPlayer->PlaySound((SoundID)230, 0, 0, -1, 0, 0, 0, 0);
+    --dword_50651C;
+    dword_506528 -= (unsigned __int8)byte_506130[dword_50651C];
+  }
+  if ( !dword_506520 || (v3 = dword_506528, dword_506528 < 1) )
+  {
+    v3 = 0;
+    dword_50651C = 0;
+    dword_506528 = 0;
+  }
+  dword_506544 = 0;
+  dword_506548 = 0;
+  dword_506520 = 0;
+  while ( v3 < dword_506524 )
+  {
+    v4 = pStru179->field_0[v3];
+    ++dword_506520;
+    v5 = (&dword_722F10)[4 * v4];
+    a1.DrawText(pAutonoteFont, 1, 0, 0, (&dword_722F10)[4 * v4], 0, 0, 0);
+    v6 = pAutonoteFont->CalcTextHeight(v5, &a1, 1, 0);
+    v7 = a1.uFrameY + v6;
+    if ( (signed int)(a1.uFrameY + v6) > (signed int)a1.uFrameHeight )
+      break;
+    pRenderer->DrawTextureTransparent(0x64u, v7 + 12, pTextures_5064A0[10]);
+    ++v3;
+    a1.uFrameY = v7 + 24;
+  }
+}
+
+
+//----- (0041338E) --------------------------------------------------------
+void __cdecl DrawSpellbook_Autonotes()
+{
+  unsigned int v0; // eax@3
+  unsigned int v1; // eax@7
+  signed int v2; // ebp@11
+  unsigned int v3; // eax@18
+  unsigned int v4; // eax@24
+  unsigned int v5; // eax@30
+  unsigned int v6; // eax@36
+  unsigned int v7; // eax@42
+  signed int v8; // ebp@47
+  int v9; // eax@52
+  int v10; // eax@56
+  int v11; // edx@57
+  int v12; // ebp@64
+  int v13; // eax@65
+  const char *v14; // edi@65
+  int v15; // eax@65
+  unsigned int v16; // edi@65
+  unsigned int v17; // [sp-8h] [bp-70h]@3
+  unsigned int v18; // [sp-8h] [bp-70h]@7
+  unsigned int v19; // [sp-8h] [bp-70h]@18
+  unsigned int v20; // [sp-8h] [bp-70h]@24
+  unsigned int v21; // [sp-8h] [bp-70h]@30
+  unsigned int v22; // [sp-8h] [bp-70h]@36
+  unsigned int v23; // [sp-8h] [bp-70h]@42
+  Texture *v24; // [sp-4h] [bp-6Ch]@3
+  Texture *v25; // [sp-4h] [bp-6Ch]@7
+  Texture *v26; // [sp-4h] [bp-6Ch]@18
+  Texture *v27; // [sp-4h] [bp-6Ch]@24
+  Texture *v28; // [sp-4h] [bp-6Ch]@30
+  Texture *v29; // [sp-4h] [bp-6Ch]@36
+  Texture *v30; // [sp-4h] [bp-6Ch]@42
+  signed __int16 v31; // [sp+10h] [bp-58h]@1
+  char *v32; // [sp+10h] [bp-58h]@49
+  GUIWindow a1; // [sp+14h] [bp-54h]@46
+
+  v31 = 0;
+  pRenderer->DrawTextureIndexed(pViewport->uViewportX, pViewport->uViewportY, pTexture_AutonotesBook);
+  if ( dword_506548 || !dword_506528 )
+  {
+    v24 = pTex_tab_an_6a__zoom_off;
+    v17 = pViewport->uViewportY + 2;
+    v0 = pViewport->uViewportX + 407;
+  }
+  else
+  {
+    v24 = pTex_tab_an_6b__zoom_on;
+    v17 = pViewport->uViewportY + 1;
+    v0 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v0, v17, v24);
+  if ( dword_506544 || dword_506528 + dword_506520 >= dword_506524 )
+  {
+    v25 = pTex_tab_an_7a__zoot_off;
+    v18 = pViewport->uViewportY + 38;
+    v1 = pViewport->uViewportX + 407;
+  }
+  else
+  {
+    v25 = pTex_tab_an_7b__zoot_on;
+    v18 = pViewport->uViewportY + 38;
+    v1 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v1, v18, v25);
+  if ( !dword_506540 )
+  {
+    if ( dword_506568 )
+    {
+      pRenderer->DrawTextureTransparent(
+        pViewport->uViewportX + 408,
+        pViewport->uViewportY + 113,
+        pTexture_506390);
+      v2 = 1;
+      goto LABEL_16;
+    }
+    goto LABEL_14;
+  }
+  if ( !dword_506568 )
+  {
+LABEL_14:
+    v2 = 1;
+    goto LABEL_15;
+  }
+  v2 = 1;
+  v31 = 1;
+  pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+LABEL_15:
+  dword_506568 = 0;
+  pRenderer->DrawTextureTransparent(pViewport->uViewportX + 398, pViewport->uViewportY + 113, pTexture_506394);
+LABEL_16:
+  if ( dword_50653C )
+  {
+    if ( dword_506568 != v2 )
+    {
+      v31 = v2;
+      pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+    }
+  }
+  else
+  {
+    if ( dword_506568 != v2 )
+    {
+      v26 = pTexture_506388;
+      v19 = pViewport->uViewportY + 150;
+      v3 = pViewport->uViewportX + 408;
+      goto LABEL_22;
+    }
+  }
+  v26 = pTexture_50638C;
+  dword_506568 = v2;
+  v19 = pViewport->uViewportY + 150;
+  v3 = pViewport->uViewportX + 399;
+LABEL_22:
+  pRenderer->DrawTextureTransparent(v3, v19, v26);
+  if ( dword_506538 )
+  {
+    if ( dword_506568 != 2 )
+    {
+      v31 = v2;
+      pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+    }
+  }
+  else
+  {
+    if ( dword_506568 != 2 )
+    {
+      v27 = pTexture_506380;
+      v20 = pViewport->uViewportY + 188;
+      v4 = pViewport->uViewportX + 408;
+      goto LABEL_28;
+    }
+  }
+  v27 = pTexture_506384;
+  dword_506568 = 2;
+  v20 = pViewport->uViewportY + 188;
+  v4 = pViewport->uViewportX + 397;
+LABEL_28:
+  pRenderer->DrawTextureTransparent(v4, v20, v27);
+  if ( dword_506534 )
+  {
+    if ( dword_506568 != 3 )
+    {
+      v31 = v2;
+      pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+    }
+  }
+  else
+  {
+    if ( dword_506568 != 3 )
+    {
+      v28 = pTexture_506378;
+      v21 = pViewport->uViewportY + 226;
+      v5 = pViewport->uViewportX + 408;
+      goto LABEL_34;
+    }
+  }
+  v28 = pTexture_50637C;
+  dword_506568 = 3;
+  v21 = pViewport->uViewportY + 226;
+  v5 = pViewport->uViewportX + 397;
+LABEL_34:
+  pRenderer->DrawTextureTransparent(v5, v21, v28);
+  if ( dword_506530 )
+  {
+    if ( dword_506568 != 4 )
+    {
+      v31 = v2;
+      pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+    }
+  }
+  else
+  {
+    if ( dword_506568 != 4 )
+    {
+      v29 = pTexture_506370;
+      v22 = pViewport->uViewportY + 263;
+      v6 = pViewport->uViewportX + 408;
+      goto LABEL_40;
+    }
+  }
+  v29 = pTexture_506374;
+  dword_506568 = 4;
+  v22 = pViewport->uViewportY + 264;
+  v6 = pViewport->uViewportX + 397;
+LABEL_40:
+  pRenderer->DrawTextureTransparent(v6, v22, v29);
+  if ( dword_50652C )
+  {
+    if ( dword_506568 != 5 )
+    {
+      v31 = v2;
+      pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+    }
+  }
+  else
+  {
+    if ( dword_506568 != 5 )
+    {
+      v30 = pTexture_506368;
+      v23 = pViewport->uViewportY + 302;
+      v7 = pViewport->uViewportX + 408;
+      goto LABEL_46;
+    }
+  }
+  v30 = pTexture_50636C;
+  dword_506568 = 5;
+  v23 = pViewport->uViewportY + 302;
+  v7 = pViewport->uViewportX + 397;
+LABEL_46:
+  pRenderer->DrawTextureTransparent(v7, v23, v30);
+  a1.uFrameWidth = 460;
+  a1.uFrameHeight = 344;
+  a1.uFrameX = 8;
+  a1.uFrameY = 8;
+  a1.uFrameZ = 467;
+  a1.uFrameW = 467;
+  a1.DrawTitleText(pBook2Font, 0, 0x16u, 0, pGlobalTXT_LocalizationStrings[154], 3u);
+  a1.uFrameX = 48;
+  a1.uFrameY = 70;
+  a1.uFrameWidth = 360;
+  a1.uFrameHeight = 264;
+  a1.uFrameZ = 407;
+  a1.uFrameW = 333;
+  if ( v31 )
+  {
+    dword_506524 = 0;
+    dword_506528 = 0;
+    dword_50651C = 0;
+    dword_506520 = 0;
+    v8 = 0;
+    do
+    {
+      if ( dword_72371C[2 * v8] == dword_506568 )
+      {
+        v32 = (&dword_723718_autonote_related)[8 * (signed __int16)v8];
+        if ( (short)v8 )
+        {
+          if ( (unsigned __int16)_449B57_test_bit(pParty->_autonote_bits, v8) && v32 )
+          {
+            v9 = dword_506520++;
+            pStru179->field_0[v9] = (signed __int16)v8;
+          }
+        }
+      }
+      ++v8;
+    }
+    while ( v8 < 196 );
+    dword_506524 = dword_506520;
+  }
+  else
+  {
+    if ( dword_506544 )
+    {
+      v10 = dword_506520 + dword_506528;
+      if ( dword_506520 + dword_506528 < dword_506524 )
+      {
+        v11 = dword_50651C++;
+        byte_506130[v11] = dword_506520;
+        dword_506528 = v10;
+        pAudioPlayer->PlaySound((SoundID)230, 0, 0, -1, 0, 0, 0, 0);
+      }
+    }
+    if ( dword_506548 && dword_50651C )
+    {
+      --dword_50651C;
+      dword_506528 -= (unsigned __int8)byte_506130[dword_50651C];
+      pAudioPlayer->PlaySound((SoundID)230, 0, 0, -1, 0, 0, 0, 0);
+    }
+    if ( !dword_506520 || dword_506528 < 1 )
+    {
+      dword_506528 = 0;
+      dword_50651C = 0;
+    }
+  }
+  v12 = dword_506528;
+  dword_50652C = 0;
+  dword_506544 = 0;
+  dword_506548 = 0;
+  dword_506520 = 0;
+  dword_506530 = 0;
+  dword_506534 = 0;
+  dword_506538 = 0;
+  dword_50653C = 0;
+  dword_506540 = 0;
+  while ( v12 < dword_506524 )
+  {
+    v13 = pStru179->field_0[v12];
+    ++dword_506520;
+    v14 = (&dword_723718_autonote_related)[8 * v13];
+    a1.DrawText(pAutonoteFont, 1, 0, 0, (&dword_723718_autonote_related)[8 * v13], 0, 0, 0);
+    v15 = pAutonoteFont->CalcTextHeight(v14, &a1, 1, 0);
+    v16 = a1.uFrameY + v15;
+    if ( (signed int)(a1.uFrameY + v15) > (signed int)a1.uFrameHeight )
+      break;
+    pRenderer->DrawTextureTransparent(0x64u, v16 + 12, pTextures_5064A0[10]);
+    ++v12;
+    a1.uFrameY = v16 + 24;
+  }
+}
+
+
+//----- (00413980) --------------------------------------------------------
+char *__cdecl DrawSpellbook_Map()
+{
+  unsigned int v0; // eax@3
+  unsigned int v1; // eax@7
+  unsigned int v2; // eax@10
+  unsigned int v3; // eax@13
+  unsigned int v4; // eax@16
+  unsigned int v5; // eax@19
+  int v6; // eax@31
+  unsigned int v7; // eax@35
+  unsigned int v9; // [sp-8h] [bp-E0h]@3
+  unsigned int v10; // [sp-8h] [bp-E0h]@7
+  unsigned int v11; // [sp-8h] [bp-E0h]@10
+  unsigned int v12; // [sp-8h] [bp-E0h]@13
+  unsigned int v13; // [sp-8h] [bp-E0h]@16
+  unsigned int v14; // [sp-8h] [bp-E0h]@19
+  Texture *v15; // [sp-4h] [bp-DCh]@3
+  Texture *v16; // [sp-4h] [bp-DCh]@7
+  Texture *v17; // [sp-4h] [bp-DCh]@10
+  Texture *v18; // [sp-4h] [bp-DCh]@13
+  Texture *v19; // [sp-4h] [bp-DCh]@16
+  Texture *v20; // [sp-4h] [bp-DCh]@19
+  char Str[120]; // [sp+Ch] [bp-CCh]@37
+  GUIWindow v22; // [sp+84h] [bp-54h]@35
+
+  pRenderer->DrawTextureIndexed(pViewport->uViewportX, pViewport->uViewportY, pTextures_5064A0[12]);
+  if ( dword_506548 || viewparams->field_2C / 128 >= 12 )
+  {
+    v15 = pTex_tab_an_6a__zoom_off;
+    v9 = pViewport->uViewportY + 2;
+    v0 = pViewport->uViewportX + 408;
+  }
+  else
+  {
+    v15 = pTex_tab_an_6b__zoom_on;
+    v9 = pViewport->uViewportY + 1;
+    v0 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v0, v9, v15);
+  if ( dword_506544 || viewparams->field_2C / 128 <= 3 )
+  {
+    v16 = pTex_tab_an_7a__zoot_off;
+    v10 = pViewport->uViewportY + 38;
+    v1 = pViewport->uViewportX + 408;
+  }
+  else
+  {
+    v16 = pTex_tab_an_7b__zoot_on;
+    v10 = pViewport->uViewportY + 38;
+    v1 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v1, v10, v16);
+  if ( dword_506540 )
+  {
+    v17 = pTexture_506390;
+    v11 = pViewport->uViewportY + 113;
+    v2 = pViewport->uViewportX + 408;
+  }
+  else
+  {
+    v17 = pTexture_506394;
+    v11 = pViewport->uViewportY + 113;
+    v2 = pViewport->uViewportX + 398;
+  }
+  pRenderer->DrawTextureTransparent(v2, v11, v17);
+  if ( dword_50653C )
+  {
+    v18 = pTexture_506388;
+    v12 = pViewport->uViewportX + 150;
+    v3 = pViewport->uViewportY + 408;
+  }
+  else
+  {
+    v18 = pTexture_50638C;
+    v12 = pViewport->uViewportX + 150;
+    v3 = pViewport->uViewportY + 399;
+  }
+  pRenderer->DrawTextureTransparent(v3, v12, v18);
+  if ( dword_506538 )
+  {
+    v19 = pTexture_506380;
+    v13 = pViewport->uViewportY + 188;
+    v4 = pViewport->uViewportX + 408;
+  }
+  else
+  {
+    v19 = pTexture_506384;
+    v13 = pViewport->uViewportY + 188;
+    v4 = pViewport->uViewportX + 397;
+  }
+  pRenderer->DrawTextureTransparent(v4, v13, v19);
+  if ( dword_506534 )
+  {
+    v20 = pTexture_506378;
+    v14 = pViewport->uViewportY + 226;
+    v5 = pViewport->uViewportX + 408;
+  }
+  else
+  {
+    v20 = pTexture_50637C;
+    v14 = pViewport->uViewportY + 226;
+    v5 = pViewport->uViewportX + 397;
+  }
+  pRenderer->DrawTextureTransparent(v5, v14, v20);
+  if ( dword_506544 )
+    viewparams->_443291();
+  if ( dword_506548 )
+    viewparams->_443249();
+  if ( dword_506540 )
+    viewparams->_443219();
+  if ( dword_50653C )
+    viewparams->_443231();
+  if ( dword_506538 )
+    viewparams->_44323D();
+  v6 = dword_506534;
+  if ( dword_506534 )
+  {
+    viewparams->_443225();
+    v6 = dword_506534;
+  }
+  if ( dword_506548 | dword_506544 | dword_506540 | dword_50653C | dword_506538 | v6 )
+    pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+  dword_506548 = 0;
+  dword_506544 = 0;
+  dword_506534 = 0;
+  dword_506538 = 0;
+  dword_50653C = 0;
+  dword_506540 = 0;
+  DrawSpellbook_Map_sub(0x61u, 0x31u, 0x169u, 313, 0);
+  pRenderer->DrawTextureTransparent(0x4Bu, 0x16u, pTexture_mapbordr);
+  v22.uFrameWidth = 460;
+  v22.uFrameHeight = 344;
+  v22.uFrameX = 8;
+  v22.uFrameY = 8;
+  v22.uFrameZ = 467;
+  v22.uFrameW = 467;
+  v7 = pMapStats->GetMapInfo(pCurrentMapName);
+  if ( v7 )
+    v22.DrawTitleText(pBook2Font, 0xFFFFFFF2u, 0xCu, 0, pMapStats->pInfos[v7].pName, 3u);
+  v22.uFrameX = 0;
+  sprintf(Str, pGlobalTXT_LocalizationStrings[659], pParty->vPosition.x, pParty->vPosition.y);
+  return v22.DrawTitleText(pFontComic, 0, 0x140u, 0, Str, 0);
+}
+
+
+//----- (00413CC6) --------------------------------------------------------
+void __thiscall DrawSpellbook(unsigned int uBook)
+{
+  unsigned int v1; // esi@1
+
+  v1 = uBook;
+  pRenderer->DrawTextureIndexed(
+    471u,
+    445u,
+    (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0));
+  switch ( v1 )
+  {
+    case 0xB1u:
+      DrawLloydBeaconsScreen();
+      break;
+    case 0xC3u:
+      DrawTownPortalScreen();
+      break;
+    case 0xC8u:
+      DrawSpellbook_Quests();
+      break;
+    case 0xC9u:
+      DrawSpellbook_Autonotes();
+      break;
+    case 0xCAu:
+      DrawSpellbook_Map();
+      break;
+    case 0xCBu:
+      DrawSpellbook_Calendar();
+      break;
+    case 0xE0u:
+      sub_412E85();
+      break;
+  }
+}
+
+//----- (00413D3C) --------------------------------------------------------
+char *__cdecl GetDayPart()
+{
+  if ( pParty->uCurrentHour > 4 )
+  {
+    if ( pParty->uCurrentHour == 5 )
+      return pGlobalTXT_LocalizationStrings[55];
+    if ( pParty->uCurrentHour == 20 )
+      return pGlobalTXT_LocalizationStrings[566];
+    if ( pParty->uCurrentHour <= 0x14 || pParty->uCurrentHour > 0x17 )
+      return pGlobalTXT_LocalizationStrings[56];
+  }
+  return pGlobalTXT_LocalizationStrings[567];
+}
+
+//----- (00413D6F) --------------------------------------------------------
+char __cdecl DrawSpellbook_Calendar()
+{
+  unsigned int v0; // esi@1
+  char *v1; // eax@5
+  int v2; // ecx@5
+  char *v3; // eax@6
+  GUIWindow a1; // [sp+Ch] [bp-60h]@5
+  unsigned int v6; // [sp+60h] [bp-Ch]@1
+  int v7; // [sp+64h] [bp-8h]@1
+  int a5; // [sp+68h] [bp-4h]@1
+
+  v0 = pParty->uCurrentHour;
+  v6 = pMapStats->GetMapInfo(pCurrentMapName);
+  a5 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0x4Bu, 0x4Bu, 0x4Bu);
+  pRenderer->DrawTextureIndexed(pViewport->uViewportX, pViewport->uViewportY, pTextures_5064A0[13]);
+  v7 = (unsigned __int8)pDayMoonPhase[pParty->uDaysPlayed];
+  if ( (signed int)v0 <= 12 )
+  {
+    if ( !v0 )
+      v0 = 12;
+  }
+  else
+  {
+    v0 -= 12;
+  }
+  a1.uFrameX = 8;
+  a1.uFrameY = 8;
+  a1.uFrameWidth = 460;
+  a1.uFrameHeight = 344;
+  a1.uFrameZ = 467;
+  a1.uFrameW = 467;
+  a1.DrawTitleText(pBook2Font, 0, 0x16u, 0, pGlobalTXT_LocalizationStrings[186], 3u);
+  v1 = GetDayPart();
+  sprintf(
+    pTmpBuf,
+    "%s\t100:\t110%d:%02d %s - %s",
+    pGlobalTXT_LocalizationStrings[526],
+    v0,
+    pParty->uCurrentMinute,
+    aAMPMNames[v2],
+    v1);
+  a1.DrawText(pBookFont, 70, 55, a5, pTmpBuf, 0, 0, 0);
+  sprintf(
+    pTmpBuf,
+    "%s\t100:\t110%d - %s",
+    pGlobalTXT_LocalizationStrings[56],
+    pParty->uDaysPlayed + 1,
+    aDayNames[pParty->uDaysPlayed % 7]);
+  a1.DrawText(pBookFont, 70, 2 * LOBYTE(pBookFont->uFontHeight) + 49, a5, pTmpBuf, 0, 0, 0);
+  sprintf(
+    pTmpBuf,
+    "%s\t100:\t110%d - %s",
+    pGlobalTXT_LocalizationStrings[146],
+    pParty->uCurrentMonth + 1,
+    aMonthNames[pParty->uCurrentMonth]);
+  a1.DrawText(pBookFont, 70, 4 * LOBYTE(pBookFont->uFontHeight) + 43, a5, pTmpBuf, 0, 0, 0);
+  sprintf(pTmpBuf, "%s\t100:\t110%d", pGlobalTXT_LocalizationStrings[245], pParty->uCurrentYear);
+  a1.DrawText(pBookFont, 70, 6 * LOBYTE(pBookFont->uFontHeight) + 37, a5, pTmpBuf, 0, 0, 0);
+  sprintf(pTmpBuf, "%s\t100:\t110%s", pGlobalTXT_LocalizationStrings[530], aMoonPhaseNames[v7]);
+  a1.DrawText(pBookFont, 70, 8 * LOBYTE(pBookFont->uFontHeight) + 31, a5, pTmpBuf, 0, 0, 0);
+  if ( v6 )
+    v3 = pMapStats->pInfos[v6].pName;
+  else
+    v3 = "Unknown";
+  sprintf(pTmpBuf, "%s\t100:\t110%s", pGlobalTXT_LocalizationStrings[531], v3);
+  return a1.DrawText(pBookFont, 70, 10 * LOBYTE(pBookFont->uFontHeight) + 25, a5, pTmpBuf, 0, 0, 0);
+}
+
+//----- (00413FF1) --------------------------------------------------------
+void __cdecl SetMonthNames()
+{
+  aMonthNames[0] = pGlobalTXT_LocalizationStrings[415];
+  aMonthNames[1] = pGlobalTXT_LocalizationStrings[416];
+  aMonthNames[2] = pGlobalTXT_LocalizationStrings[417];
+  aMonthNames[3] = pGlobalTXT_LocalizationStrings[418];
+  aMonthNames[4] = pGlobalTXT_LocalizationStrings[419];
+  aMonthNames[5] = pGlobalTXT_LocalizationStrings[420];
+  aMonthNames[6] = pGlobalTXT_LocalizationStrings[421];
+  aMonthNames[7] = pGlobalTXT_LocalizationStrings[422];
+  aMonthNames[8] = pGlobalTXT_LocalizationStrings[423];
+  aMonthNames[9] = pGlobalTXT_LocalizationStrings[424];
+  aMonthNames[10] = pGlobalTXT_LocalizationStrings[425];
+  aMonthNames[11] = pGlobalTXT_LocalizationStrings[426];
+}
+
+//----- (0041406F) --------------------------------------------------------
+void __cdecl SetDayNames()
+{
+  aDayNames[0] = pGlobalTXT_LocalizationStrings[145];
+  aDayNames[1] = pGlobalTXT_LocalizationStrings[230];
+  aDayNames[2] = pGlobalTXT_LocalizationStrings[243];
+  aDayNames[3] = pGlobalTXT_LocalizationStrings[227];
+  aDayNames[4] = pGlobalTXT_LocalizationStrings[91];
+  aDayNames[5] = pGlobalTXT_LocalizationStrings[188];
+  aDayNames[6] = pGlobalTXT_LocalizationStrings[222];
+}
+
+//----- (004140BB) --------------------------------------------------------
+void __cdecl SetSpellSchoolNames()
+{
+  aSpellSchoolNames[0] = pGlobalTXT_LocalizationStrings[87];
+  aSpellSchoolNames[1] = pGlobalTXT_LocalizationStrings[6];
+  aSpellSchoolNames[2] = pGlobalTXT_LocalizationStrings[240];
+  aSpellSchoolNames[3] = pGlobalTXT_LocalizationStrings[70];
+  aSpellSchoolNames[4] = pGlobalTXT_LocalizationStrings[214];
+  aSpellSchoolNames[5] = pGlobalTXT_LocalizationStrings[142];
+  aSpellSchoolNames[6] = pGlobalTXT_LocalizationStrings[29];
+  aSpellSchoolNames[7] = pGlobalTXT_LocalizationStrings[133];
+  aSpellSchoolNames[8] = pGlobalTXT_LocalizationStrings[54];
+}
+
+//----- (0041411B) --------------------------------------------------------
+void __cdecl SetAttributeNames()
+{
+  aAttributeNames[0] = pGlobalTXT_LocalizationStrings[144];
+  aAttributeNames[1] = pGlobalTXT_LocalizationStrings[116];
+  aAttributeNames[2] = pGlobalTXT_LocalizationStrings[163];
+  aAttributeNames[3] = pGlobalTXT_LocalizationStrings[75];
+  aAttributeNames[4] = pGlobalTXT_LocalizationStrings[1];
+  aAttributeNames[5] = pGlobalTXT_LocalizationStrings[211];
+  aAttributeNames[6] = pGlobalTXT_LocalizationStrings[136];
+}
+
+//----- (00414162) --------------------------------------------------------
+void __cdecl uGameUIFontMain_initialize()
+{
+  uGameUIFontMain = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xAu, 0, 0);
+}
+
+//----- (00414174) --------------------------------------------------------
+void __cdecl uGameUIFontShadow_initialize()
+{
+  uGameUIFontShadow = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE6u, 214u, 193u);
+}
+
+
+
+
+
+//----- (004141CA) --------------------------------------------------------
+GUIWindow *__fastcall ModalWindow(const char *pStr, int a4)
+{
+  const char *v2; // edi@1
+  int v3; // esi@1
+  GUIWindow *result; // eax@1
+
+  v2 = pStr;
+  v3 = a4;
+  pEventTimer->Pause();
+  dword_506F0C[0] = pCurrentScreen;
+  result = GUIWindow::Create(0, 0, 640, 480, WINDOW_FinalWindow, v3, (int)v2);
+  ptr_507BDC = result;
+  pCurrentScreen = 22;
+  return result;
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (0041420D) --------------------------------------------------------
+void __cdecl sub_41420D_press_esc()
+{
+  GUIWindow v0; // [sp+4h] [bp-54h]@1
+
+  sprintf(pTmpBuf2, "%s\n \n%s", ptr_507BDC->Hint, pGlobalTXT_LocalizationStrings[61]);// Press Escape
+  v0.Hint = pTmpBuf2;
+  v0.uFrameWidth = 400;
+  v0.uFrameHeight = 100;
+  v0.uFrameX = 120;
+  v0.uFrameY = 140;
+  v0.uFrameZ = 519;
+  v0.uFrameW = 239;
+  v0.DrawMessageBox(0);
+}
+
+//----- (0041426F) --------------------------------------------------------
+void __cdecl sub_41426F()
+{
+  GUIWindow *v0; // ecx@1
+
+  v0 = ptr_507BDC;
+  if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+  {
+    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)(int)ptr_507BDC->ptr_1C;
+    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+    *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+    ++pMessageQueue_50CBD0->uNumMessages;
+  }
+  v0->Release();
+  ptr_507BDC = 0;
+  pCurrentScreen = dword_506F0C[0];
+  pEventTimer->Resume();
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+//----- (004142D3) --------------------------------------------------------
+char __cdecl GameMenuUI_DrawKeyBindings()
+{
+  unsigned int v0; // ebp@1
+  int v1; // ecx@2
+  unsigned int v2; // eax@6
+  GUIWindow *v3; // edx@6
+  signed int v4; // ecx@7
+  signed int v5; // eax@8
+  const char *v6; // ST0C_4@16
+  unsigned int v7; // eax@16
+  const char *v8; // ST0C_4@16
+  unsigned int v9; // eax@16
+  const char *v10; // ST0C_4@16
+  unsigned int v11; // eax@16
+  const char *v12; // ST0C_4@16
+  unsigned int v13; // eax@16
+  const char *v14; // ST0C_4@16
+  unsigned int v15; // eax@16
+  const char *v16; // ST0C_4@16
+  unsigned int v17; // eax@16
+  const char *v18; // ST0C_4@16
+  unsigned int v19; // eax@16
+  const char *v20; // ST0C_4@16
+  unsigned int v21; // eax@16
+  signed int v22; // ebp@16
+  const char *v23; // ST0C_4@16
+  unsigned int v24; // eax@16
+  const char *v25; // ST0C_4@16
+  unsigned int v26; // eax@16
+  const char *v27; // ST0C_4@16
+  unsigned int v28; // eax@16
+  const char *v29; // ST0C_4@16
+  unsigned int v30; // eax@16
+  const char *v31; // ST0C_4@16
+  unsigned int v32; // eax@16
+  const char *v33; // ST0C_4@17
+  unsigned int v34; // eax@17
+  const char *v35; // ST0C_4@17
+  unsigned int v36; // eax@17
+  const char *v37; // ST0C_4@17
+  unsigned int v38; // eax@17
+  const char *v39; // ST0C_4@17
+  unsigned int v40; // eax@17
+  const char *v41; // ST0C_4@17
+  unsigned int v42; // eax@17
+  const char *v43; // ST0C_4@17
+  unsigned int v44; // eax@17
+  const char *v45; // ST0C_4@17
+  unsigned int v46; // eax@17
+  const char *v47; // ST0C_4@17
+  unsigned int v48; // eax@17
+  const char *v49; // ST0C_4@17
+  unsigned int v50; // eax@17
+  const char *v51; // ST0C_4@17
+  unsigned int v52; // eax@17
+  const char *v53; // ST0C_4@17
+  unsigned int v54; // eax@17
+  const char *v55; // ST0C_4@17
+  unsigned int v56; // eax@17
+  const char *v57; // ST0C_4@17
+  unsigned int v58; // eax@17
+  unsigned int v59; // eax@18
+  int v61; // [sp-14h] [bp-28h]@16
+  const char *v62; // [sp-10h] [bp-24h]@16
+  int v63; // [sp-Ch] [bp-20h]@16
+  int v64; // [sp-8h] [bp-1Ch]@16
+  unsigned int v65; // [sp-4h] [bp-18h]@16
+  unsigned int a5; // [sp+10h] [bp-4h]@1
+
+  v0 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  a5 = v0;
+  if ( byte_4E28FC )
+  {
+    v1 = dword_507C0C + 15;
+    dword_507C0C = v1;
+    if ( v1 == 255 )
+      byte_4E28FC = 0;
+  }
+  else
+  {
+    v1 = dword_507C0C - 15;
+    dword_507C0C = v1;
+    if ( v1 == 15 )
+      byte_4E28FC = 1;
+  }
+  v2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v1, 0, 0);
+  v3 = pGUIWindow_CurrentMenu;
+  dword_507C08 = v2;
+  if ( pGUIWindow_CurrentMenu->field_40 == 2 )
+  {
+    pPrevVirtualCidesMapping[dword_506E68] = pKeyActionMap->pPressedKeysBuffer[0];
+    memset(word_506E6C, 0, 0x1Cu);
+    v4 = 0;
+    do
+    {
+      v5 = 0;
+      do
+      {
+        if ( v4 != v5 && pPrevVirtualCidesMapping[v4] == pPrevVirtualCidesMapping[v5] )
+        {
+          *((char *)word_506E6C + v4) = 1;
+          *((char *)word_506E6C + v5) = 1;
+        }
+        ++v5;
+      }
+      while ( v5 < 28 );
+      ++v4;
+    }
+    while ( v4 < 28 );
+    dword_506E68 = -1;
+    v3->field_40 = 0;
+  }
+  pRenderer->DrawTextureIndexed(
+    8u,
+    8u,
+    (Texture *)(uTextureID_507BF4 != -1 ? &pIcons_LOD->pTextures[uTextureID_507BF4] : 0));
+  if ( dword_506F08 == 1 )
+  {
+    pRenderer->DrawTextureIndexed(
+      0x13u,
+      0x12Eu,
+      (Texture *)(uTextureID_507C00 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C00] : 0));
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 142, v0, ascii_4E2D5C, 0, 0, 0);
+    v6 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[0]);
+    v7 = sub_414D24(0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 142, v7, v6, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 163, v0, ascii_4E2D50, 0, 0, 0);
+    v8 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[1]);
+    v9 = sub_414D24(1);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 163, v9, v8, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 184, v0, ascii_4E2D48, 0, 0, 0);
+    v10 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[2]);
+    v11 = sub_414D24(2);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 184, v11, v10, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 205, v0, ascii_4E2D40, 0, 0, 0);
+    v12 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[3]);
+    v13 = sub_414D24(3);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 205, v13, v12, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 226, v0, ascii_4E2D38, 0, 0, 0);
+    v14 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[4]);
+    v15 = sub_414D24(4);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 226, v15, v14, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 247, v0, ascii_4E2D30, 0, 0, 0);
+    v16 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[5]);
+    v17 = sub_414D24(5);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 247, v17, v16, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 268, v0, ascii_4E2D28, 0, 0, 0);
+    v18 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[6]);
+    v19 = sub_414D24(6);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 268, v19, v18, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 142, v0, ascii_4E2D1C, 0, 0, 0);
+    v20 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[7]);
+    v21 = sub_414D24(7);
+    v22 = 350;
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 142, v21, v20, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 163, a5, ascii_4E2D14, 0, 0, 0);
+    v23 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[8]);
+    v24 = sub_414D24(8);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 163, v24, v23, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 184, a5, ascii_4E2D0C, 0, 0, 0);
+    v25 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[9]);
+    v26 = sub_414D24(9);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 184, v26, v25, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 205, a5, ascii_4E2D04, 0, 0, 0);
+    v27 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[10]);
+    v28 = sub_414D24(10);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 205, v28, v27, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 226, a5, ascii_4E2CFC, 0, 0, 0);
+    v29 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[11]);
+    v30 = sub_414D24(11);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 226, v30, v29, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 247, a5, ascii_4E2CF0, 0, 0, 0);
+    v31 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[12]);
+    v32 = sub_414D24(12);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 247, v32, v31, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 268, a5, ascii_4E2CE8, 0, 0, 0);
+    v65 = 0;
+    v64 = 0;
+    v63 = 0;
+    v62 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[13]);
+    v61 = 13;
+  }
+  else
+  {
+    pRenderer->DrawTextureIndexed(
+      0x7Fu,
+      0x12Eu,
+      (Texture *)(uTextureID_507C04 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C04] : 0));
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 142, v0, ascii_4E2CDC, 0, 0, 0);
+    v33 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[14]);
+    v34 = sub_414D24(14);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 142, v34, v33, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 163, v0, ascii_4E2CD4, 0, 0, 0);
+    v35 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[15]);
+    v36 = sub_414D24(15);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 163, v36, v35, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 184, v0, ascii_4E2CC8, 0, 0, 0);
+    v37 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[16]);
+    v38 = sub_414D24(16);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 184, v38, v37, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 205, v0, ascii_4E2CBC, 0, 0, 0);
+    v39 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[17]);
+    v40 = sub_414D24(17);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 205, v40, v39, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 226, v0, ascii_4E2CB0, 0, 0, 0);
+    v41 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[18]);
+    v42 = sub_414D24(18);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 226, v42, v41, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 247, v0, ascii_4E2CA4, 0, 0, 0);
+    v43 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[19]);
+    v44 = sub_414D24(19);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 247, v44, v43, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 23, 268, v0, ascii_4E2C9C, 0, 0, 0);
+    v45 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[20]);
+    v46 = sub_414D24(20);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 127, 268, v46, v45, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 142, v0, ascii_4E2C90, 0, 0, 0);
+    v47 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[21]);
+    v48 = sub_414D24(21);
+    v22 = 350;
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 142, v48, v47, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 163, a5, ascii_4E2C84, 0, 0, 0);
+    v49 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[22]);
+    v50 = sub_414D24(22);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 163, v50, v49, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 184, a5, ascii_4E2C7C, 0, 0, 0);
+    v51 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[23]);
+    v52 = sub_414D24(23);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 184, v52, v51, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 205, a5, ascii_4E2C70, 0, 0, 0);
+    v53 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[24]);
+    v54 = sub_414D24(24);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 205, v54, v53, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 226, a5, ascii_4E2C68, 0, 0, 0);
+    v55 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[25]);
+    v56 = sub_414D24(25);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 226, v56, v55, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 247, a5, ascii_4E2C5C, 0, 0, 0);
+    v57 = pKeyActionMap->GetVKeyDisplayName(pPrevVirtualCidesMapping[26]);
+    v58 = sub_414D24(26);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 350, 247, v58, v57, 0, 0, 0);
+    pGUIWindow_CurrentMenu->DrawText(pFontLucida, 247, 268, a5, ascii_4E2C54, 0, 0, 0);
+    v65 = 0;
+    v64 = 0;
+    v63 = 0;
+    v62 = pKeyActionMap->GetVKeyDisplayName(pWindowList_at_506F50_minus1_indexing[0]);
+    v61 = 27;
+  }
+  v59 = sub_414D24(v61);
+  return pGUIWindow_CurrentMenu->DrawText(pFontLucida, v22, 268, v59, v62, v63, v64, v65);
+}
+
+
+//----- (00414D24) --------------------------------------------------------
+unsigned int __thiscall sub_414D24(int _this)
+{
+  int v1; // esi@1
+  unsigned int v2; // edi@1
+  unsigned int v3; // ebx@1
+  unsigned int result; // eax@1
+
+  v1 = _this;
+  v2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  v3 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFu, 0, 0);
+  result = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  if ( dword_506E68 == v1 )
+  {
+    if ( GetTickCount() % 0x3E8 <= 0x1F4 )
+      result = v3;
+    else
+      result = v2;
+  }
+  else
+  {
+    if ( *((char *)word_506E6C + v1) )
+      result = dword_507C08;
+  }
+  return result;
+}
+// 506E68: using guessed type int dword_506E68;
+// 506E6C: using guessed type __int16 word_506E6C[18];
+// 507C08: using guessed type int dword_507C08;
+
+//----- (00414D9A) --------------------------------------------------------
+void __cdecl GameMenuUI_DrawVideoOptions()
+{
+  const char *v0; // ST0C_4@3
+  unsigned __int16 v1; // ax@3
+  int v2; // eax@10
+  GUIWindow v3; // [sp+8h] [bp-54h]@3
+
+  pRenderer->DrawTextureIndexed(
+    8u,
+    8u,
+    (Texture *)(uTextureID_507C10 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C10] : 0));
+  if ( !pRenderer->bWindowMode && GammaController::IsGammaSupported() )
+  {
+    pRenderer->DrawTextureIndexed(
+      17 * uGammaPos + 42,
+      162u,
+      (Texture *)(pTextureIDs_GammaPositions[uGammaPos] != -1 ? &pIcons_LOD->pTextures[pTextureIDs_GammaPositions[uGammaPos]] : 0));
+    pRenderer->DrawTextureRGB(0x112u, 0xA9u, &stru_506E40);
+    v3.uFrameX = 22;
+    v0 = pGlobalTXT_LocalizationStrings[226];
+    v3.uFrameY = 190;
+    v3.uFrameWidth = 211;
+    v3.uFrameHeight = 79;
+    v3.uFrameZ = 232;
+    v3.uFrameW = 268;
+    v1 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+    v3.DrawTitleText(pFontSmallnum, 0, 0, v1, v0, 3u);
+  }
+  if ( !pRenderer->pRenderD3D )
+  {
+    pRenderer->DrawTextureIndexed(
+      0x14u,
+      0x119u,
+      (Texture *)(uTextureID_507C50 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C50] : 0));
+    pRenderer->DrawTextureIndexed(
+      0x14u,
+      0x12Fu,
+      (Texture *)(uTextureID_507C54 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C54] : 0));
+    v2 = uTextureID_507C58;
+    goto LABEL_12;
+  }
+  if ( pGame->uFlags2 & 0x20 )
+    pRenderer->DrawTextureIndexed(
+      0x14u,
+      0x119u,
+      (Texture *)(uTextureID_507C14 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C14] : 0));
+  if ( pRenderer->bUseColoredLights )
+    pRenderer->DrawTextureIndexed(
+      0x14u,
+      0x12Fu,
+      (Texture *)(uTextureID_507C18 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C18] : 0));
+  if ( pRenderer->bTinting )
+  {
+    v2 = uTextureID_507C1C;
+LABEL_12:
+    pRenderer->DrawTextureIndexed(0x14u, 0x145u, (Texture *)(v2 != -1 ? &pIcons_LOD->pTextures[v2] : 0));
+  }
+}
+
+
+
+//----- (00414F82) --------------------------------------------------------
+void __cdecl sub_414F82_DrawGameOptions()
+{
+  signed int v0; // eax@1
+
+  pRenderer->DrawTextureIndexed(
+    8u,
+    8u,
+    (Texture *)(uTextureID_507944 != -1 ? &pIcons_LOD->pTextures[uTextureID_507944] : 0));
+  pRenderer->DrawTextureIndexed(
+    8u,
+    0x84u,
+    (Texture *)(uTextureID_507C60 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C60] : 0));
+  v0 = 0;
+  if ( uTurnSpeed == 128 )
+  {
+    v0 = 2;
+  }
+  else
+  {
+    if ( uTurnSpeed == 64 )
+      v0 = 1;
+  }
+  pRenderer->DrawTextureIndexed(
+    dword_4E2910[v0],
+    0x10Eu,
+    (Texture *)(uTextureID_507C64[v0] != -1 ? &pIcons_LOD->pTextures[uTextureID_507C64[v0]] : 0));
+  if ( bWalkSound )
+    pRenderer->DrawTextureIndexed(
+      0x14u,
+      0x12Fu,
+      (Texture *)(uTextureID_507CB4 != -1 ? &pIcons_LOD->pTextures[uTextureID_507CB4] : 0));
+  if ( bShowDamage )
+    pRenderer->DrawTextureIndexed(
+      0x80u,
+      0x12Fu,
+      (Texture *)(uTextureID_507CB8 != -1 ? &pIcons_LOD->pTextures[uTextureID_507CB8] : 0));
+  if ( bFlipOnExit )
+    pRenderer->DrawTextureIndexed(
+      0x80u,
+      0x145u,
+      (Texture *)(uTextureID_507C84 != -1 ? &pIcons_LOD->pTextures[uTextureID_507C84] : 0));
+  if ( bAlwaysRun )
+    pRenderer->DrawTextureIndexed(
+      0x14u,
+      0x145u,
+      (Texture *)(uTextureID_507CB0 != -1 ? &pIcons_LOD->pTextures[uTextureID_507CB0] : 0));
+  pRenderer->DrawTextureIndexed(
+    17 * (char)uSoundVolumeMultiplier + 265,
+    0xA2u,
+    (Texture *)(pTextureIDs_SoundLevels[(char)uSoundVolumeMultiplier] != -1 ? &pIcons_LOD->pTextures[pTextureIDs_SoundLevels[(char)uSoundVolumeMultiplier]] : 0));
+  pRenderer->DrawTextureIndexed(
+    17 * (char)uMusicVolimeMultiplier + 265,
+    0xD8u,
+    (Texture *)(pTextureIDs_SoundLevels[(char)uMusicVolimeMultiplier] != -1 ? &pIcons_LOD->pTextures[pTextureIDs_SoundLevels[(char)uMusicVolimeMultiplier]] : 0));
+  pRenderer->DrawTextureIndexed(
+    17 * (char)uVoicesVolumeMultiplier + 265,
+    0x10Eu,
+    (Texture *)(pTextureIDs_SoundLevels[(char)uVoicesVolumeMultiplier] != -1 ? &pIcons_LOD->pTextures[pTextureIDs_SoundLevels[(char)uVoicesVolumeMultiplier]] : 0));
+}
+
+
+
+
+//----- (004151D9) --------------------------------------------------------
+void __fastcall DrawPopupWindow(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight)
+{
+  unsigned int v4; // ebx@1
+  Texture *v5; // edi@1
+  signed int uTileWidth; // ecx@1
+  int v7; // eax@5
+  int v8; // ecx@10
+  unsigned int v9; // ebx@14
+  int v10; // [sp+10h] [bp-28h]@5
+  signed int uTileHeight; // [sp+18h] [bp-20h]@1
+  int v12; // [sp+1Ch] [bp-1Ch]@7
+  int v13; // [sp+20h] [bp-18h]@1
+  int a5; // [sp+24h] [bp-14h]@5
+  unsigned int a5a; // [sp+24h] [bp-14h]@11
+  unsigned int a4; // [sp+28h] [bp-10h]@1
+  int uNumXTiles; // [sp+2Ch] [bp-Ch]@3
+  unsigned int uNumXTilesa; // [sp+2Ch] [bp-Ch]@6
+  unsigned int uNumXTilesb; // [sp+2Ch] [bp-Ch]@11
+  unsigned int a2a; // [sp+30h] [bp-8h]@1
+  unsigned int v21; // [sp+34h] [bp-4h]@5
+  unsigned int v22; // [sp+34h] [bp-4h]@11
+
+  v4 = uY;
+  a2a = uX;
+  a4 = uX + uWidth;
+  pRenderer->Clip(uX, v4, uX + uWidth, v4 + uHeight);
+  v5 = (Texture *)(uTextureID_Parchment != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Parchment] : 0);
+  uTileWidth = (uTextureID_Parchment != -1 ? pIcons_LOD->pTextures[uTextureID_Parchment].uTextureWidth : 24);
+  v13 = (uTextureID_Parchment != -1 ? pIcons_LOD->pTextures[uTextureID_Parchment].uTextureWidth : 24);
+  uTileHeight = (uTextureID_Parchment != -1 ? pIcons_LOD->pTextures[uTextureID_Parchment].uTextureHeight : 26);
+  if ( (uTextureID_Parchment != -1 ? pIcons_LOD->pTextures[uTextureID_Parchment].uTextureWidth : 24)
+    && (uTextureID_Parchment != -1 ? pIcons_LOD->pTextures[uTextureID_Parchment].uTextureHeight : 26) )
+  {
+    uNumXTiles = (signed int)uWidth / uTileWidth;
+    if ( (signed int)uWidth % uTileWidth )
+      ++uNumXTiles;
+    a5 = 0;
+    v21 = v4;
+    v7 = uNumXTiles + 1;
+    v10 = uNumXTiles + 1;
+    do
+    {
+      uNumXTilesa = a2a - v13;
+      if ( v7 > 0 )
+      {
+        v12 = v7;
+        do
+        {
+          uNumXTilesa += v13;
+          pRenderer->DrawTextureIndexed(uNumXTilesa, v21, v5);
+          --v12;
+        }
+        while ( v12 );
+        v7 = v10;
+      }
+      v21 += uTileHeight;
+      v8 = a5++;
+    }
+    while ( v8 < (signed int)uHeight / uTileHeight );
+    a5a = v4 + uHeight - 32;
+    pRenderer->DrawTextureTransparent(
+      a2a,
+      v4,
+      (Texture *)(uTextureID_5076AC != -1 ? &pIcons_LOD->pTextures[uTextureID_5076AC] : 0));
+    pRenderer->DrawTextureTransparent(
+      a2a,
+      a5a,
+      (Texture *)(uTextureID_5076B4 != -1 ? &pIcons_LOD->pTextures[uTextureID_5076B4] : 0));
+    pRenderer->DrawTextureTransparent(
+      a4 - 32,
+      v4,
+      (Texture *)(uTextureID_5076A8 != -1 ? &pIcons_LOD->pTextures[uTextureID_5076A8] : 0));
+    pRenderer->DrawTextureTransparent(
+      a4 - 32,
+      a5a,
+      (Texture *)(uTextureID_5076B0 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_5076B0] : 0));
+    uNumXTilesb = a2a + 32;
+    v22 = v4 + uHeight - 10;
+    if ( (signed int)uWidth > 64 )
+    {
+      pRenderer->Clip(a2a + 32, v4, a4 - 32, v4 + uHeight);
+      pRenderer->DrawTextureTransparent(
+        uNumXTilesb,
+        v4,
+        (Texture *)(uTextureID_507698 != -1 ? &pIcons_LOD->pTextures[uTextureID_507698] : 0));
+      pRenderer->DrawTextureTransparent(
+        uNumXTilesb,
+        v22,
+        (Texture *)(uTextureID_5076A4 != -1 ? &pIcons_LOD->pTextures[uTextureID_5076A4] : 0));
+      if ( (signed int)uWidth > 512 )
+      {
+        pRenderer->DrawTextureTransparent(
+          a2a + 544,
+          v4,
+          (Texture *)(uTextureID_507698 != -1 ? &pIcons_LOD->pTextures[uTextureID_507698] : 0));
+        pRenderer->DrawTextureTransparent(
+          a2a + 544,
+          v22,
+          (Texture *)(uTextureID_5076A4 != -1 ? &pIcons_LOD->pTextures[uTextureID_5076A4] : 0));
+      }
+    }
+    v9 = v4 + 32;
+    if ( (signed int)uHeight > 64 )
+    {
+      pRenderer->Clip(a2a, v9, a4, a5a);
+      pRenderer->DrawTextureTransparent(
+        a2a,
+        v9,
+        (Texture *)(uTextureID_5076A0 != -1 ? &pIcons_LOD->pTextures[uTextureID_5076A0] : 0));
+      pRenderer->DrawTextureTransparent(
+        a4 - 10,
+        v9,
+        (Texture *)(uTextureID_50769C != -1 ? &pIcons_LOD->pTextures[uTextureID_50769C] : 0));
+    }
+    pRenderer->ResetClip();
+  }
+}
+
+
+//----- (00415485) --------------------------------------------------------
+char *__cdecl DrawCopyrightWindow()
+{
+  GUIWindow Dst; // [sp+8h] [bp-54h]@1
+
+  memset(&Dst, 0, 0x54u);
+  Dst.uFrameWidth = 624;
+  Dst.uFrameHeight = 256;
+  Dst.uFrameX = 8;
+  Dst.uFrameY = 30;                             // c 1999 The 3DO Company.
+  Dst.uFrameHeight = pFontSmallnum->CalcTextHeight(pGlobalTXT_LocalizationStrings[157], &Dst, 24, 0)
+                   + 2 * LOBYTE(pFontSmallnum->uFontHeight)
+                   + 24;
+  Dst.uFrameY = 470 - Dst.uFrameHeight;
+  Dst.uFrameZ = Dst.uFrameX + Dst.uFrameWidth - 1;
+  Dst.uFrameW = 469;
+  Dst.DrawMessageBox(0);
+  Dst.uFrameWidth -= 24;
+  Dst.uFrameX += 12;
+  Dst.uFrameY += 12;
+  Dst.uFrameHeight -= 12;
+  Dst.uFrameZ = Dst.uFrameX + Dst.uFrameWidth - 1;
+  Dst.uFrameW = Dst.uFrameY + Dst.uFrameHeight - 1;
+  return Dst.DrawTitleText(pFontSmallnum, 0, 0xCu, 0, pGlobalTXT_LocalizationStrings[157], 3u);
+}
+
+
+
+
+//----- (004156F0) --------------------------------------------------------
+void __cdecl GUI_UpdateWindows()
+{
+  GUIWindow *pWindow; // esi@4
+  unsigned int pWindowType; // eax@4
+  int v2; // eax@10
+  int v3; // eax@11
+  int v4; // eax@12
+  int v5; // eax@20
+  int v6; // eax@21
+  int v7; // eax@29
+  int v8; // eax@30
+  int v9; // eax@31
+  void *v10; // eax@41
+  int v11; // ecx@42
+  int v12; // eax@48
+  int v13; // eax@49
+  int v14; // eax@57
+  int v15; // eax@58
+  int v16; // eax@59
+  int v17; // eax@60
+  int v18; // eax@61
+  int v19; // eax@62
+  void *v20; // ebp@66
+  char *pHint; // edx@66
+  GUIButton *pButtonPtr_1C; // ebp@79
+  char *v23; // edx@80
+  char v24; // zf@81
+  //unsigned int v25; // eax@91
+  int v26; // eax@98
+  unsigned int v27; // ebp@106
+  GUIWindow *pGUIWindow2; // ecx@109
+  unsigned int v29; // eax@111
+  GUIFont *pGUIFont; // ST1C_4@115
+  int v31; // eax@115
+  void *v32; // ebp@118
+  int v33; // eax@119
+  int v34; // eax@120
+  int v35; // eax@121
+  int v36; // eax@122
+  int v37; // eax@123
+  int v38; // eax@124
+  int v39; // eax@129
+  //char *v40; // edx@138
+  unsigned int pNumMessages; // eax@142
+  GUIButton *pGUIButton; // ebp@146
+  //char *v43; // edx@146
+  unsigned int pX; // [sp-1Ch] [bp-124h]@17
+  unsigned int pY; // [sp-18h] [bp-120h]@17
+  Texture *pTexture; // [sp-14h] [bp-11Ch]@17
+  Texture *pTexture2; // [sp-14h] [bp-11Ch]@86
+  int i; // [sp+0h] [bp-108h]@3
+  ItemGen pItemGen; // [sp+4h] [bp-104h]@98
+  GUIButton GUIButton2; // [sp+28h] [bp-E0h]@133
+  ItemGen ItemGen2; // [sp+E4h] [bp-24h]@129
+
+  if (GetCurrentMenuID() != MENU_CREATEPARTY)
+    sub_41CD4F(34);
+  for ( i = 1; i <= uNumVisibleWindows; ++i )
+  {
+    //v0 = (GUIWindow *)&pWindowList_at_506F50_minus1_indexing[21 * pVisibleWindowsIdxs[i]];
+    pWindow = &pWindowList[pVisibleWindowsIdxs[i] - 1];
+    pWindowType = pWindow->eWindowType;
+    switch (pWindow->eWindowType)
+    {
+      case WINDOW_MainMenu_Load:
+        GameUI_MainMenu_DrawLoad();
+        continue;
+      case WINDOW_5E: // window that initiates savegame loading
+      {
+        if (pWindow->Hint != (char *)1)
+          pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+        auto pGUIButton3 = (GUIButton *)pWindow->ptr_1C;
+        pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, pGUIButton3->pTextures[0]);
+        pHint = pWindow->Hint;
+        viewparams->bRedrawGameUI = 1;
+        if ( pHint && pHint != (char *)1 )
+          pGUIButton3->DrawLabel(pHint, pFontCreate, 0, 0);
+        pWindow->Release();
+        if (pCurrentScreen == 11)//îêíî ñîõðàíåíèÿ èãðû
+          pMessageQueue_50CBD0->SendMessage(UIMSG_SaveGame, 0, 0);
+        else
+          pMessageQueue_50CBD0->SendMessage(UIMSG_LoadGame, 0, 0);
+      }
+      continue;
+    }
+    if ( (signed int)pWindowType > 70 )
+    {
+      if ( (signed int)pWindowType > 95 )
+      {
+        v33 = pWindowType - 96;
+        if ( !v33 )
+        {
+          if ( pWindow->Hint != (char *)1 )
+            pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+          pGUIButton = (GUIButton *)pWindow->ptr_1C;
+          pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, pGUIButton->pTextures[0]);
+          pHint = pWindow->Hint;
+          viewparams->bRedrawGameUI = 1;
+          if ( pHint && pHint != (char *)1 )
+            pGUIButton->DrawLabel(pHint, pFontCreate, 0, 0);
+          pWindow->Release();
+          if ( (signed int)pMessageQueue_50CBD0->uNumMessages >= 40 )
+            continue;
+          pNumMessages = pMessageQueue_50CBD0->uNumMessages;
+//LABEL_151:
+          pMessageQueue_50CBD0->pMessages[pNumMessages].eType = (UIMessageType)113;
+//LABEL_152:
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+          *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+          ++pMessageQueue_50CBD0->uNumMessages;
+          continue;
+        }
+        v34 = v33 - 1;
+        if ( v34 )
+        {
+          v35 = v34 - 1;
+          if ( v35 )
+          {
+            v36 = v35 - 1;
+            if ( v36 )
+            {
+              v37 = v36 - 4;
+              if ( v37 )
+              {
+                v38 = v37 - 2;
+                if ( v38 )
+                {
+                  if ( v38 == 1 )
+                    GameMenuUI_DrawVideoOptions();
+                }
+                else
+                {
+                  GameMenuUI_DrawKeyBindings();
+                }
+              }
+              else
+              {
+                pWindow->DrawMessageBox(0);
+                pWindow->DrawText(pFontLucida, 10, 20, 0, "Making item number", 0, 0, 0);
+                pWindow->DrawText(pFontLucida, 10, 40, 0, (const char *)pKeyActionMap->pPressedKeysBuffer, 0, 0, 0);
+                if ( !pKeyActionMap->field_204 )
+                {
+                  ItemGen2.Reset();
+                  pWindow->Release();
+                  pEventTimer->Resume();
+                  pCurrentScreen = 0;
+                  viewparams->bRedrawGameUI = 1;
+                  v39 = atoi((const char *)pKeyActionMap->pPressedKeysBuffer);
+                  if ( v39 > 0 )
+                  {
+                    if ( v39 < 800 )
+                      SpawnActor(v39);
+                  }
+                }
+              }
+              continue;
+            }
+            pTexture = (Texture *)*((_DWORD *)pWindow->ptr_1C + 15);
+            pY = pWindow->uFrameY;
+            pX = pWindow->uFrameX;
+//LABEL_18:
+            pRenderer->DrawTextureIndexed(pX, pY, pTexture);
+//LABEL_114:
+            viewparams->bRedrawGameUI = 1;
+            continue;
+          }
+          memset(&GUIButton2, 0, 0xBCu);
+          GUIButton2.uZ = 197;
+          GUIButton2.uW = 197;
+          GUIButton2.uX = 27;
+          GUIButton2.uY = 161;
+          GUIButton2.uWidth = 171;
+          GUIButton2.uHeight = 37;
+          GUIButton2.pParent = pButton_RestUI_WaitUntilDawn->pParent;
+          pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+          pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, *((Texture **)pWindow->ptr_1C + 15));
+          viewparams->bRedrawGameUI = 1;
+          GUIButton2.DrawLabel(pGlobalTXT_LocalizationStrings[183], pFontCreate, 0, 0);//Îòäûõ è ëå÷åíèå 8 ÷àñîâ
+          GUIButton2.pParent = 0;
+          //goto LABEL_134;
+		  pGUIWindow2 = pWindow;
+          //goto LABEL_110;
+		  pGUIWindow2->Release();
+          continue;
+        }
+        if ( pWindow->Hint != (char *)1 )
+          pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+        v32 = pWindow->ptr_1C;
+        pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, *((Texture **)v32 + 16));
+        goto LABEL_138;
+      }
+      if ( pWindowType == 95 )
+      {
+        if ( pWindow->Hint != (char *)1 )
+          pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+        v32 = pWindow->ptr_1C;
+        pRenderer->DrawTextureTransparent(pWindow->uFrameX, pWindow->uFrameY, *((Texture **)v32 + 15));
+LABEL_138:
+        pHint = pWindow->Hint;
+        viewparams->bRedrawGameUI = 1;
+        if ( pHint && pHint != (char *)1 )
+          ((GUIButton *)v32)->DrawLabel(pHint, pFontCreate, 0, 0);
+        pWindow->Release();
+LABEL_142:
+        pNumMessages = pMessageQueue_50CBD0->uNumMessages;
+        if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+          //goto LABEL_151;
+		{
+		  pMessageQueue_50CBD0->pMessages[pNumMessages].eType = (UIMessageType)113;
+          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+          *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+          ++pMessageQueue_50CBD0->uNumMessages;
+          continue;
+		}
+        continue;
+      }
+      v14 = pWindowType - 80;
+      if ( v14 )
+      {
+        v15 = v14 - 9;
+        if ( !v15 )
+        {
+          pWindow->DrawMessageBox(0);
+          pWindow->DrawText(pFontLucida, 10, 20, 0, "Making item number", 0, 0, 0);
+          pWindow->DrawText(pFontLucida, 10, 40, 0, (const char *)pKeyActionMap->pPressedKeysBuffer, 0, 0, 0);
+          if ( !pKeyActionMap->field_204 )
+          {
+            pItemGen.Reset();
+            pWindow->Release();
+            pEventTimer->Resume();
+            pCurrentScreen = 0;
+            viewparams->bRedrawGameUI = 1;
+            v26 = atoi((const char *)pKeyActionMap->pPressedKeysBuffer);
+            if ( v26 > 0 )
+            {
+              if ( v26 < 800 )
+              {
+                pItemGen.uAttributes |= 1u;
+                pItemGen.uItemID = v26;
+                if ( pItemsTable->pItems[v26].uEquipType == 12 )
+                {
+                  pItemGen.uNumCharges = rand() % 6 + pItemsTable->pItems[pItemGen.uItemID].uDamageMod + 1;
+                  pItemGen.uMaxCharges = LOBYTE(pItemGen.uNumCharges);
+                }
+                else
+                {
+                  if ( v26 >= 221 && v26 < 271 )
+                    pItemGen._bonus_type = rand() % 10 + 1;
+                }
+                pItemsTable->SetSpecialBonus(&pItemGen);
+                pParty->SetHoldingItem(&pItemGen);
+              }
+            }
+          }
+          continue;
+        }
+        v16 = v15 - 1;
+        if ( !v16 )
+        {
+          if ( pWindow->Hint != (char *)1 )
+            pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+          pButtonPtr_1C = (GUIButton *)pWindow->ptr_1C;
+          if ( (pButtonPtr_1C->uX /*& 0x80000000u*/) == 0 )
+          {
+            if ( (signed int)pButtonPtr_1C->uX <= 640 )
+            {
+              //v25 = pButtonPtr_1C->uY;
+              if ( (pButtonPtr_1C->uY /*& 0x80000000u*/) == 0 )
+              {
+                if ( (signed int)pButtonPtr_1C->uY <= 480 )
+                {
+                  pTexture2 = pButtonPtr_1C->pTextures[0];
+                  goto LABEL_94;
+                }
+              }
+            }
+          }
+          v23 = pWindow->Hint;
+          viewparams->bRedrawGameUI = 1;
+          if ( v23 )
+          {
+            v24 = v23 == (char *)1;
+            goto LABEL_82;
+          }
+//LABEL_134:
+          pGUIWindow2 = pWindow;
+          //goto LABEL_110;
+		  pGUIWindow2->Release();
+          continue;
+        }
+        v17 = v16 - 1;
+        if ( !v17 )
+        {
+          if ( pWindow->Hint != (char *)1 )
+            pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+          pButtonPtr_1C = (GUIButton *)pWindow->ptr_1C;
+          pTexture2 = pButtonPtr_1C->pTextures[1];
+LABEL_94:
+          pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, pTexture2);
+LABEL_80:
+          v23 = pWindow->Hint;
+          viewparams->bRedrawGameUI = 1;
+          if ( v23 )
+          {
+            v24 = v23 == (char *)1;
+LABEL_82:
+            if ( !v24 )
+              pButtonPtr_1C->DrawLabel(v23, pFontCreate, 0, 0);
+          }
+          //goto LABEL_134;
+		  pGUIWindow2 = pWindow;
+          //goto LABEL_110;
+		  pGUIWindow2->Release();
+          continue;
+        }
+        v18 = v17 - 1;
+        if ( !v18 )
+        {
+          if ( pWindow->Hint != (char *)1 )
+            pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+          pButtonPtr_1C = (GUIButton *)pWindow->ptr_1C;
+          pRenderer->DrawTextureTransparent(pWindow->uFrameX, pWindow->uFrameY, pButtonPtr_1C->pTextures[0]);
+          goto LABEL_80;
+        }
+        v19 = v18 - 1;
+        if ( !v19 )
+        {
+          if ( pWindow->Hint != (char *)1 )
+            pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+          pRenderer->DrawTextureTransparent(pWindow->uFrameX, pWindow->uFrameY, *((Texture **)pWindow->ptr_1C + 16));
+          viewparams->bRedrawGameUI = 1;
+          //goto LABEL_134;
+		  pGUIWindow2 = pWindow;
+          //goto LABEL_110;
+		  pGUIWindow2->Release();
+          continue;
+        }
+      }
+      else
+      {
+        v27 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+        if ( ptr_507BD0->field_40 == 1 )
+        {
+          ptr_507BD0->DrawMessageBox(0);
+          ptr_507BD0->DrawText(pFontCreate, 30, 40, v27, (const char *)pKeyActionMap->pPressedKeysBuffer, 0, 0, 0);
+          pGUIFont = pFontCreate;
+          v31 = pFontCreate->GetLineWidth((const char *)pKeyActionMap->pPressedKeysBuffer);
+          ptr_507BD0->DrawFlashingInputCursor(v31 + 30, 40, pGUIFont);
+          continue;
+        }
+        if ( ptr_507BD0->field_40 == 2 )
+        {
+          v29 = pMessageQueue_50CBD0->uNumMessages;
+          pWindow->field_40 = 0;
+          if ( (signed int)v29 < 40 )
+          {
+            pMessageQueue_50CBD0->pMessages[v29].eType = (UIMessageType)(int)ptr_507BD0->ptr_1C;
+            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+            *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+            ++pMessageQueue_50CBD0->uNumMessages;
+          }
+          pEventTimer->Resume();
+          ptr_507BD0->Release();
+          pCurrentScreen = 0;
+          //goto LABEL_114;
+		  viewparams->bRedrawGameUI = 1;
+          continue;
+        }
+        if ( ptr_507BD0->field_40 == 3 )
+        {
+          pWindow->field_40 = 0;
+          pEventTimer->Resume();
+          pGUIWindow2 = ptr_507BD0;
+//LABEL_110:
+          pGUIWindow2->Release();
+          continue;
+        }
+      }
+    }
+    else
+    {
+      if ( pWindowType == 70 )
+      {
+        sub_41420D_press_esc();
+        continue;
+      }
+      if ( (signed int)pWindowType > 18 )
+      {
+        if ( (signed int)pWindowType > 25 )
+        {
+          v12 = pWindowType - 26;
+          if ( v12 )
+          {
+            v13 = v12 - 4;
+            if ( v13 )
+            {
+              if ( v13 == 1 )
+              {
+                pRenderer->ClearZBuffer(0, 479);
+                draw_leather();
+                CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+                CharacterUI_DrawPaperdoll(uActiveCharacter);
+                pRenderer->DrawTextureTransparent(pBtn_ExitCancel->uX, pBtn_ExitCancel->uY,
+                  (Texture *)(uTextureID_x_x_u != -1 ? &pIcons_LOD->pTextures[uTextureID_x_x_u] : 0));
+              }
+            }
+            else
+            {
+              sub_467FB6();
+            }
+          }
+          else
+          {
+            TransitionUI_Draw();
+          }
+          continue;
+        }
+        if ( pWindowType != 25 )
+        {
+          v7 = pWindowType - 19;
+          if ( v7 )
+          {
+            v8 = v7 - 1;
+            if ( v8 )
+            {
+              v9 = v8 - 3;
+              if ( v9 )
+              {
+                //if ( v9 == 1 )
+                //  sub_4606F7();
+              }
+              else
+              {
+                sub_4606FE();
+              }
+            }
+            else
+            {
+              if ( pCurrentScreen == 10 )
+              {
+                Chest::DrawChestUI((unsigned int)pWindow->ptr_1C);
+              }
+              else
+              {
+                if ( pCurrentScreen == 15 )
+                {
+                  pRenderer->ClearZBuffer(0, 479);
+                  draw_leather();
+                  CharacterUI_InventoryTab_Draw(uActiveCharacter, 1);
+                  pRenderer->DrawTextureIndexed(pBtn_ExitCancel->uX, pBtn_ExitCancel->uY,
+                    (Texture *)(uTextureID_506438 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_506438] : 0));
+                }
+              }
+            }
+          }
+          else
+          {
+            DrawBranchlessDialogueUI();
+          }
+          continue;
+        }
+        pWindowList[pVisibleWindowsIdxs[i] - 1]._4B3157();
+        if ( !ptr_507BC0 )
+          continue;
+        v10 = ptr_507BC0->ptr_1C;
+        if ( (signed int)v10 >= 53 )
+          continue;
+        v11 = pParty->field_3C._shop_ban_times[2 * (_DWORD)v10 + 1];
+        if ( !__PAIR__(v11, pParty->field_3C._shop_ban_times[2 * (_DWORD)v10])
+          || v11 < SHIDWORD(pParty->uTimePlayed)
+          || v11 <= SHIDWORD(pParty->uTimePlayed)
+          && (unsigned int)pParty->field_3C._shop_ban_times[2 * (_DWORD)v10] <= LODWORD(pParty->uTimePlayed) )
+        {
+          if ( (signed int)v10 < 53 )
+          {
+            pParty->field_3C._shop_ban_times[2 * (_DWORD)v10] = 0;
+            pParty->field_3C._shop_ban_times[2 * (_DWORD)v10 + 1] = 0;
+          }
+          continue;
+        }
+        goto LABEL_142;
+      }
+      if ( pWindowType == 18 )
+      {
+        sub_412B58();
+      }
+      else
+      {
+        if ( (signed int)pWindowType > 10 )
+        {
+          v5 = pWindowType - 12;
+          if ( v5 )
+          {
+            v6 = v5 - 4;
+            if ( v6 )
+            {
+              if ( v6 == 1 )
+                TravelUI_Draw();
+            }
+            else
+            {
+              RestUI_Draw();
+            }
+          }
+          else
+          {
+            QuickRefDraw();
+          }
+          continue;
+        }
+        if ( pWindowType != 10 )
+        {
+          v2 = pWindowType - 3;
+          if ( v2 )
+          {
+            v3 = v2 - 1;
+            if ( v3 )
+            {
+              v4 = v3 - 2;
+              if ( v4 )
+              {
+                if ( v4 == 3 )
+                  DrawSpellbook((unsigned int)pWindow->ptr_1C);
+              }
+              else
+              {
+                sub_414F82_DrawGameOptions();
+              }
+            }
+            else
+            {
+              CharacterUI_CharacterScreen_Draw(uActiveCharacter);
+            }
+            continue;
+          }
+          pTexture = (Texture *)(uTextureID_507944 != -1 ? &pIcons_LOD->pTextures[uTextureID_507944] : 0);
+          pY = pViewport->uViewportY;
+          pX = pViewport->uViewportX;
+          //goto LABEL_18;
+		  pRenderer->DrawTextureIndexed(pX, pY, pTexture);
+          viewparams->bRedrawGameUI = 1;
+          continue;
+        }
+        DrawDialogueUI();
+      }
+    }
+  }
+  if ( GetCurrentMenuID() == -1 )
+    GameUI_DrawFoodAndGold();
+  if ( sub_4637E0_is_there_popup_onscreen() )
+    sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(0);
+}
+
+//----- (00416196) --------------------------------------------------------
+void __cdecl identify_item()
+{
+  Player *v0; // esi@2
+  POINT *v1; // edi@2
+  signed int v2; // ecx@5
+  signed int v3; // eax@5
+  int v4; // eax@5
+  char v5; // sf@5
+  int v6; // eax@5
+  int v7; // eax@7
+  unsigned __int16 v8; // ax@10
+  int v9; // edi@10
+  int v10; // eax@10
+  int v11; // edx@13
+  LONG v12; // edx@23
+  signed int v13; // edx@23
+  int v14; // edx@25
+  unsigned int v15; // edi@25
+  signed int v16; // edx@27
+  int v17; // eax@54
+  unsigned int v18; // edx@57
+  int v19; // eax@65
+  int v20; // edi@67
+  int v21; // eax@72
+  int v22; // ecx@74
+  int v23; // edx@78
+  int v24; // eax@79
+  int v25; // eax@80
+  int v26; // eax@84
+  ItemGen *v27; // esi@98
+  unsigned int v28; // eax@98
+  ItemGen *v29; // edi@98
+  unsigned int v30; // ecx@103
+  double v31; // st7@112
+  unsigned __int64 v32; // qax@113
+  unsigned int v33; // ecx@117
+  int v34; // eax@126
+  unsigned int v35; // ecx@127
+  double v36; // st7@132
+  signed __int64 v37; // qax@135
+  unsigned int v38; // eax@138
+  Vec3_int_ v39; // [sp-18h] [bp-A8h]@83
+  int *v40; // [sp-Ch] [bp-9Ch]@83
+  int *v41; // [sp-8h] [bp-98h]@83
+  int *v42; // [sp-4h] [bp-94h]@83
+  GUIWindow v43; // [sp+Ch] [bp-84h]@137
+  unsigned int pY; // [sp+60h] [bp-30h]@2
+  int v45; // [sp+64h] [bp-2Ch]@10
+  unsigned int pX; // [sp+68h] [bp-28h]@2
+  int v47; // [sp+6Ch] [bp-24h]@25
+  POINT y; // [sp+70h] [bp-20h]@2
+  POINT a2; // [sp+78h] [bp-18h]@2
+  Vec3_int_ pOut; // [sp+80h] [bp-10h]@2
+  unsigned int v51; // [sp+8Ch] [bp-4h]@23
+
+  if ( dword_50CDCC )
+    return;
+  v0 = pPlayers[uActiveCharacter];
+  v1 = pMouse->GetCursorPos(&a2);
+  pOut.z = pRenderer->pActiveZBuffer[v1->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&y)->y]] & 0xFFFF;
+  pMouse->GetClickPos(&pX, &pY);
+  if ( !pOut.z )
+  {
+    if ( (signed int)pX <= 13
+      || (signed int)pX >= 462
+      || (v2 = pX - 14,
+          v3 = pY - 17,
+          pX = v2,
+          pY = v3,
+          v4 = 14 * (v3 >> 5),
+          v2 >>= 5,
+          v5 = v2 + v4 < 0,
+          v6 = v2 + v4,
+          pOut.z = v6,
+          v5)
+      || v6 > 126
+      || (v7 = v0->GetItemIDAtInventoryIndex(&pOut.z)) == 0 )
+      return;
+    pOut.z = v7;
+  }
+  if ( !v0->CanAct() )
+  {
+    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[427], v0->pName, pGlobalTXT_LocalizationStrings[541]);
+    v43.Hint = pTmpBuf;
+    v43.uFrameWidth = 384;
+    v43.uFrameHeight = 180;
+    v43.uFrameY = 40;
+    if ( pMouse->GetCursorPos(&a2)->x <= 320 )
+      v38 = pMouse->GetCursorPos(&a2)->x + 30;
+    else
+      v38 = pMouse->GetCursorPos(&a2)->x - 414;
+    v43.uFrameX = v38;
+    v43.DrawMessageBox(0);
+    return;
+  }
+  --pOut.z;
+  LOBYTE(v8) = v0->GetActualSkillLevel(PLAYER_SKILL_ALCHEMY);
+  v9 = v8 & 0x3F;
+  v45 = v8 & 0x3F;
+  pOut.y = SkillToMastery(v8);
+  v10 = pOut.z;
+  if ( pParty->pPickedItem.uItemID == 220 )
+  {
+LABEL_116:
+    GameUI_DrawItemInfo(&v0->pInventoryItems[v10]);
+    return;
+  }
+  if ( (signed int)pParty->pPickedItem.uItemID < 200
+    || (signed int)pParty->pPickedItem.uItemID > 219
+    || (v11 = (int)((char *)v0 + 36 * pOut.z), *(int *)(v11 + 532) != 220) )
+  {
+    if ( (signed int)pParty->pPickedItem.uItemID < 221
+      || (signed int)pParty->pPickedItem.uItemID > 271
+      || (v12 = (LONG)((char *)v0 + 36 * pOut.z), a2.y = v12, v13 = *(int *)(v12 + 532), v51 = v13, v13 < 221)
+      || v13 > 271 )
+    {
+      if ( pParty->pPickedItem.uItemID != 236
+        && ((signed int)pParty->pPickedItem.uItemID < 246 || (signed int)pParty->pPickedItem.uItemID > 250)
+        && pParty->pPickedItem.uItemID != 263
+        && pParty->pPickedItem.uItemID != 233 )
+        goto LABEL_116;
+      v27 = &v0->pInventoryItems[pOut.z];
+      v28 = v27->uItemID;
+      v51 = pItemsTable->pItems[v27->uItemID].uEquipType;
+      v29 = (ItemGen *)(1800 * pParty->pPickedItem._bonus_type);
+      if ( pParty->pPickedItem.uItemID != 233 )
+      {
+        if ( pParty->pPickedItem.uItemID == 236 )
+        {
+          v35 = v27->uAttributes;
+          if ( v35 & 2 || (v51 & 0x80000000u) != 0 || (signed int)v51 > 12 || (signed int)v28 >= 500 )
+            goto LABEL_92;
+          LOWORD(v35) = v35 | 0x210;
+          v27->uAttributes = v35;
+        }
+        else
+        {
+          if ( (signed int)pParty->pPickedItem.uItemID <= 245 )
+            goto LABEL_92;
+          if ( (signed int)pParty->pPickedItem.uItemID <= 250 )
+          {
+            v27->UpdateTempBonus(pParty->uTimePlayed);
+            v33 = v27->uItemID;
+            if ( (signed int)v27->uItemID >= 64 && (signed int)v33 <= 65
+              || (pOut.y = v27->uAttributes, pOut.y & 2)
+              || v27->uAdditionalValue
+              || v27->_bonus_type
+              || v51 && v51 != 1 && v51 != 2
+              || (signed int)v33 >= 500 )
+              goto LABEL_92;
+            v34 = *(int *)&aSbwb00[4 * pParty->pPickedItem.uItemID + 4];
+            a2.y = (int)v29 << 7;
+            v31 = (double)(signed int)((int)v29 << 7);
+            v27->uAdditionalValue = v34;
+          }
+          else
+          {
+            if ( pParty->pPickedItem.uItemID != 263
+              || (v27->UpdateTempBonus(pParty->uTimePlayed), v30 = v27->uItemID, (signed int)v27->uItemID >= 64)
+              && (signed int)v30 <= 65
+              || (pOut.y = v27->uAttributes, pOut.y & 2)
+              || v27->uAdditionalValue
+              || v27->_bonus_type
+              || v51 && v51 != 1 && v51 != 2
+              || (signed int)v30 >= 500 )
+              goto LABEL_92;
+            a2.y = (int)v29 << 7;
+            v27->uAdditionalValue = 40;
+            v31 = (double)a2.y;
+          }
+          v32 = pParty->uTimePlayed + (signed int)(signed __int64)(v31 * 0.033333335);
+          LODWORD(v27->uExpireTime) = v32;
+          LODWORD(v32) = pOut.y;
+          LOBYTE(v32) = LOBYTE(pOut.y) | 0x18;
+          HIDWORD(v27->uExpireTime) = HIDWORD(v32);
+          v27->uAttributes = v32;
+        }
+        dword_50C9A8 = 256;
+        goto LABEL_92;
+      }
+      v36 = (70.0 - (double)pParty->pPickedItem._bonus_type) * 0.01;
+      if ( v36 < 0.0 )
+        v36 = 0.0;
+      if ( v51 != 12 )
+      {
+        pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+        return;
+      }
+      a2.y = v27->uMaxCharges;
+      v37 = (signed __int64)((double)a2.y - v36 * (double)a2.y);
+      v27->uMaxCharges = v37;
+      v27->uNumCharges = (unsigned __int8)v37;
+      goto LABEL_92;
+    }
+    v14 = v13 - 222;
+    v15 = pParty->pPickedItem.uItemID - 222;
+    v47 = v14;
+    y.y = 0;
+    if ( pParty->pPickedItem.uItemID == 221 || v51 == 221 )
+    {
+      v16 = 5;
+    }
+    else
+    {
+      v16 = *(short *)&pItemsTable->field_EDE0[2 * (v14 + 50 * v15) + 388];
+      v10 = pOut.z;
+    }
+    v51 = v16;
+    if ( v45 )
+    {
+      if ( v16 < 225 || v16 > 227 )
+      {
+        if ( v16 < 228 || v16 > 239 )
+        {
+          if ( v16 < 240 || v16 > 261 )
+          {
+            if ( v16 >= 262 && pOut.y != 4 )
+            {
+LABEL_53:
+              v51 = 4;
+              goto LABEL_54;
+            }
+          }
+          else
+          {
+            if ( pOut.y <= 2 )
+            {
+LABEL_38:
+              v51 = 3;
+              goto LABEL_54;
+            }
+          }
+        }
+        else
+        {
+          if ( pOut.y == 1 )
+          {
+LABEL_35:
+            v51 = 2;
+            goto LABEL_54;
+          }
+        }
+      }
+    }
+    else
+    {
+      if ( v16 >= 225 && v16 <= 227 )
+      {
+        v51 = 1;
+        goto LABEL_54;
+      }
+      if ( v16 >= 228 && v16 <= 239 )
+        goto LABEL_35;
+      if ( v16 >= 240 && v16 <= 261 )
+        goto LABEL_38;
+      if ( v16 >= 262 )
+        goto LABEL_53;
+    }
+LABEL_54:
+    pOut.y = 0;
+    pOut.x = v10 + 1;
+    v17 = (int)v0->pInventoryIndices;
+    while ( *(int *)v17 != pOut.x )
+    {
+      ++pOut.y;
+      v17 += 4;
+      if ( pOut.y >= 126 )
+      {
+        v18 = y.y;
+        goto LABEL_59;
+      }
+    }
+    v18 = pOut.y;
+LABEL_59:
+    if ( !v51 )
+    {
+LABEL_115:
+      v10 = pOut.z;
+      goto LABEL_116;
+    }
+    if ( v51 == 1 )
+    {
+      v0->RemoveItemAtInventoryIndex(v18);
+      v26 = rand();
+      v0->ReceiveDamage(v26 % 11 + 10, 0);
+      pAudioPlayer->PlaySound(SOUND_8, 0, 0, -1, 0, 0, 0, 0);
+      if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+      {
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+        *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+        ++pMessageQueue_50CBD0->uNumMessages;
+      }
+      v42 = (int *)&a2.y;
+      v41 = (int *)&y.y;
+      v40 = (int *)&pOut;
+      v39.z = pParty->vPosition.z + pParty->sEyelevel;
+    }
+    else
+    {
+      if ( v51 == 2 )
+      {
+        v0->RemoveItemAtInventoryIndex(v18);
+        v25 = rand();
+        v0->ReceiveDamage(v25 % 71 + 30, 0);
+        v23 = 1;
+      }
+      else
+      {
+        if ( v51 == 3 )
+        {
+          v0->RemoveItemAtInventoryIndex(v18);
+          v24 = rand();
+          v0->ReceiveDamage(v24 % 201 + 50, 0);
+          v23 = 5;
+        }
+        else
+        {
+          if ( v51 != 4 )
+          {
+            if ( v51 != 5 )
+            {
+              v19 = v0->AddItem(0xFFFFFFFFu, 0xDCu);
+              if ( v19 )
+                *(int *)&v0->field_1F5[36 * v19 + 15] = 1;
+              v20 = v47 + 50 * v15;
+              v0->pInventoryItems[pOut.z].uItemID = v51;
+              v0->pInventoryItems[pOut.z]._bonus_type = (pParty->pPickedItem._bonus_type
+                                                       + v0->pInventoryItems[pOut.z]._bonus_type)
+                                                      / 2;
+              v0->SetVariable(VAR_AutoNotes, *(short *)&pItemsTable->field_10168[2 * v20 + 388]);
+LABEL_74:
+              v22 = (int)((char *)v0 + 36 * pOut.z);
+              if ( !BYTE2(pItemsTable->pItems[*(int *)(v22 + 532) + 1].uItemID) )
+                *(int *)(v22 + 552) |= 1u;
+              if ( !dword_4E455C )
+                goto LABEL_92;
+              v0->PlaySound(16, 0);
+              goto LABEL_91;
+            }
+            if ( v45 )
+            {
+              if ( *(int *)(a2.y + 532) == 221 )
+                *(int *)(a2.y + 532) = pParty->pPickedItem.uItemID;
+              else
+                *(int *)(a2.y + 536) = pParty->pPickedItem._bonus_type;
+              v21 = v0->AddItem(0xFFFFFFFFu, 0xDCu);
+              if ( v21 )
+                *(int *)&v0->field_1F5[36 * v21 + 15] = 1;
+              goto LABEL_74;
+            }
+            goto LABEL_115;
+          }
+          v0->RemoveItemAtInventoryIndex(v18);
+          v0->SetCondition(0x10u, 0);
+          v23 = 0;
+        }
+      }
+      v0->_4160CA(v23);
+      pAudioPlayer->PlaySound(SOUND_8, 0, 0, -1, 0, 0, 0, 0);
+      if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+      {
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)113;
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+        *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+        ++pMessageQueue_50CBD0->uNumMessages;
+      }
+      v42 = (int *)&a2.y;
+      v41 = (int *)&y.y;
+      v40 = (int *)&pOut;
+      v39.z = pParty->vPosition.z + pParty->sEyelevel;
+    }
+    *(_QWORD *)&v39.x = *(_QWORD *)&pParty->vPosition.x;
+    Vec3_int_::Rotate(64, pParty->sRotationY, pParty->sRotationX, v39, v40, v41, v42);
+    sub_42F7EB_DropItemAt(0x41Bu, pOut.x, y.y, a2.y, 0, 1, 0, 0, 0);
+    if ( dword_4E455C )
+    {
+      if ( v0->CanAct() )
+        v0->PlaySound(17, 0);
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[444], 2u);
+LABEL_91:
+      dword_4E455C = 0;
+    }
+LABEL_92:
+    pMouse->RemoveHoldingItem();
+    dword_50CDCC = 1;
+    return;
+  }
+  *(int *)(v11 + 536) = v9 + pItemsTable->pItems[pParty->pPickedItem.uItemID].uDamageDice;
+  switch ( pParty->pPickedItem.uItemID )
+  {
+    case 0xC8u:
+    case 0xC9u:
+    case 0xCAu:
+    case 0xCBu:
+    case 0xCCu:
+      v0->pInventoryItems[pOut.z].uItemID = 222;
+      break;
+    case 0xCDu:
+    case 0xCEu:
+    case 0xCFu:
+    case 0xD0u:
+    case 0xD1u:
+      v0->pInventoryItems[pOut.z].uItemID = 223;
+      break;
+    case 0xD2u:
+    case 0xD3u:
+    case 0xD4u:
+    case 0xD5u:
+    case 0xD6u:
+      v0->pInventoryItems[pOut.z].uItemID = 224;
+      break;
+    case 0xD7u:
+    case 0xD8u:
+    case 0xD9u:
+    case 0xDAu:
+    case 0xDBu:
+      v0->pInventoryItems[pOut.z].uItemID = 221;
+      break;
+    default:
+      break;
+  }
+  pMouse->RemoveHoldingItem();
+  dword_50CDCC = 1;
+  if ( dword_4E455C )
+  {
+    v0->PlaySound(16, 0);
+    dword_4E455C = 0;
+  }
+}
+
+
+//----- (00416B01) --------------------------------------------------------
+void __thiscall sub_416B01(void *_this)
+{
+  int v1; // edi@2
+  int v2; // ecx@2
+  NPCData *v3; // eax@2
+  NPCData *v4; // esi@7
+  NPCData *v5; // eax@16
+  NPCData *v6; // esi@16
+  const CHAR *v7; // eax@18
+  unsigned int v8; // eax@25
+  unsigned int v9; // eax@25
+  const char *v10; // ST14_4@26
+  char *v11; // esi@26
+  const char *v12; // ST18_4@27
+  unsigned __int16 v13; // ax@28
+  char *v14; // eax@28
+  GUIWindow a1; // [sp+Ch] [bp-60h]@23
+  int a2; // [sp+60h] [bp-Ch]@16
+  void *v17; // [sp+64h] [bp-8h]@1
+  LPCSTR lpsz; // [sp+68h] [bp-4h]@6
+
+  v17 = _this;
+  if ( bNoNPCHiring != 1 )
+  {
+    v1 = 0;
+    v2 = 0;
+    v3 = pParty->pHirelings;
+    do
+    {
+      if ( v3->pName )
+        pTmpBuf[v1++] = v2;
+      ++v3;
+      ++v2;
+    }
+    while ( (signed int)v3 < (signed int)&pParty->pPickedItem );
+    lpsz = 0;
+    if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+    {
+      v4 = pNPCStats->pNewNPCData;
+      do
+      {
+        if ( v4->uFlags & 0x80
+          && (!pParty->pHirelings[0].pName || strcmp(v4->pName, pParty->pHirelings[0].pName))
+          && (!pParty->pHirelings[1].pName || strcmp(v4->pName, pParty->pHirelings[1].pName)) )
+          pTmpBuf[v1++] = (char)lpsz + 2;
+        ++lpsz;
+        ++v4;
+      }
+      while ( (signed int)lpsz < (signed int)pNPCStats->uNumNewNPCs );
+    }
+    if ( (signed int)((char *)v17 + (unsigned __int8)pParty->field_709) < v1 )
+    {
+      uDialogue_SpeakingActorNPC_ID = -1 - (unsigned __int8)pParty->field_709 - (int)v17;
+      v5 = GetNewNPCData(uDialogue_SpeakingActorNPC_ID, (int)&a2);
+      v6 = v5;
+      if ( v5 )
+      {
+        if ( a2 == 57 )
+          v7 = pNPCTopics[512].pText;
+        else
+          v7 = (const CHAR *)*(&pNPCStats->field_13A5C + 5 * v5->uProfession);
+        lpsz = v7;
+        if ( !v7 )
+        {
+          lpsz = (LPCSTR)*(&pNPCStats->field_13A64 + 5 * v6->uProfession);
+          if ( !lpsz )
+            lpsz = "";
+        }
+        a1.Hint = 0;
+        a1.uFrameX = 38;
+        a1.uFrameY = 60;
+        a1.uFrameWidth = 276;
+        a1.uFrameZ = 313;
+        a1.uFrameHeight = pFontArrus->CalcTextHeight(lpsz, &a1, 0, 0)
+                        + 2 * LOBYTE(pFontArrus->uFontHeight)
+                        + 24;
+        if ( (signed int)a1.uFrameHeight < 130 )
+          a1.uFrameHeight = 130;
+        a1.uFrameWidth = 400;
+        a1.uFrameZ = a1.uFrameX + 399;
+        a1.DrawMessageBox(0);
+        sprintf(pTmpBuf2, "NPC%03d", v6->uPortraitID);
+        v8 = pIcons_LOD->LoadTexture(pTmpBuf2, TEXTURE_16BIT_PALETTE);
+        pRenderer->DrawTextureIndexed(
+          a1.uFrameX + 22,
+          a1.uFrameY + 36,
+          (Texture *)(v8 != -1 ? &pIcons_LOD->pTextures[v8] : 0));
+        v9 = v6->uProfession;
+        if ( v9 )
+        {
+          v10 = v6->pName;
+          v11 = pTmpBuf;
+          sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[429], v10, aNPCProfessionNames[v9]);
+        }
+        else
+        {
+          v12 = v6->pName;
+          v11 = pTmpBuf;
+          strcpy(pTmpBuf, v12);
+        }
+        v13 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+        a1.DrawTitleText(pFontArrus, 0, 0xCu, v13, v11, 3u);
+        a1.uFrameWidth -= 24;
+        a1.uFrameZ = a1.uFrameX + a1.uFrameWidth - 1;
+        v14 = sub_495461((char *)lpsz, uActiveCharacter - 1, 0, 0, 0, 0);
+        a1.DrawText(pFontArrus, 100, 36, 0, v14, 0, 0, 0);
+      }
+    }
+  }
+}
+
+
+//----- (00416D62) --------------------------------------------------------
+void sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(Vec2_int_ *_this)
+{
+  signed int pPlayerNum; // eax@12
+  char *v2; // eax@32
+  void *v3; // ecx@52
+  unsigned int v4; // eax@59
+  int v5; // esi@62
+  signed int v6; // esi@64
+  signed int v7; // esi@69
+  ItemGen *v8; // ecx@70
+  unsigned int v9; // eax@72
+  unsigned int v10; // eax@76
+  char v11; // zf@83
+  GUIButton *pButton; // esi@84
+  unsigned int v13; // ecx@85
+  char *pStr; // edi@85
+  signed int pControlID; // eax@92
+  int v16; // eax@95
+  int v17; // eax@96
+  enum PLAYER_SKILL_TYPE v18; // eax@98
+  char *pStr2; // eax@99
+  unsigned int v20; // eax@108
+  unsigned int pSkillId; // eax@109
+  const char *pSkillInfo; // eax@111
+  //char *v23; // ebx@112
+  char *pHint; // edx@113
+  unsigned int pColor; // eax@113
+  GUIWindow pWindow; // [sp+4h] [bp-74h]@32
+  double v27; // [sp+58h] [bp-20h]@33
+  struct tagPOINT Point; // [sp+60h] [bp-18h]@6
+  char *v29; // [sp+68h] [bp-10h]@33
+  float v30; // [sp+6Ch] [bp-Ch]@33
+  unsigned int pX; // [sp+70h] [bp-8h]@3
+  unsigned int pY; // [sp+74h] [bp-4h]@3
+
+  if ( pCurrentScreen == 16 )//îêíî âèäåî ðîëèêà 
+    return;
+  if ( _this )
+  {
+    pX = _this->x;
+    pY = _this->y;
+  }
+  else
+  {
+    pMouse->GetClickPos(&pX, &pY);
+  }
+  if ( pRenderer->bWindowMode )
+  {
+    GetCursorPos(&Point);
+    ScreenToClient(hWnd, &Point);
+    if ( Point.x < 1 || Point.y < 1 || Point.x > 638 || Point.y > 478 )
+    {
+      back_to_game();
+      return;
+    }
+  }
+  if ( pParty->pPickedItem.uItemID )//íàæàòèå íà ïîðòðåò ïåðñà ïðàâîé êíîïêîé ìûøè ñ ðàñòâîðîì
+  {
+    //v1 = 0;
+    //do
+	for ( pPlayerNum = 0; pPlayerNum < 4; ++pPlayerNum)
+    {
+      if ( (signed int)pX > RightClickPortraitXmin[pPlayerNum] && (signed int)pX < RightClickPortraitXmax[pPlayerNum]
+        && (signed int)pY > 375 && (signed int)pY < 466 )
+      {
+        pPlayers[uActiveCharacter]->UseItem_DrinkPotion_etc(pPlayerNum + 1, 1);
+        return;
+      }
+      //++v1;
+    }
+    //while ( v1 < 4 );
+  }
+  pEventTimer->Pause();
+  if ( pCurrentScreen <= 10 )
+  {
+    if ( pCurrentScreen == 10 )//îêíî ÿùèêà
+    {
+      __debugbreak();
+      if ( !pPlayers[uActiveCharacter]->CanAct() )
+      {
+        sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[427],//%s íå â ñîñòîÿíèè %s
+          pPlayers[uActiveCharacter]->pName, pGlobalTXT_LocalizationStrings[541]);//Îïîçíàòü ïðåäìåòû
+        pWindow.Hint = pTmpBuf;
+        pWindow.uFrameWidth = 384;
+        pWindow.uFrameHeight = 180;
+        pWindow.uFrameY = 40;
+        if ( (signed int)pX <= 320 )
+          v10 = pX + 30;
+        else
+          v10 = pX - 414;
+        pWindow.uFrameX = v10;
+		pWindow.DrawMessageBox(0);
+        goto LABEL_132;
+      }
+      v9 = pX + pSRZBufferLineOffsets[pY];
+      if ( !(pRenderer->pActiveZBuffer[v9] & 0xFFFF) )
+        goto LABEL_132;
+      v8 = (ItemGen *)(&pOtherOverlayList->pOverlays[49].field_4 + 2662 * (unsigned int)pChestWindow->ptr_1C + 18* *((short *)&pChests[0].mm7__vector_pItems[139].uExpireTime
+                       + (pRenderer->pActiveZBuffer[v9] & 0xFFFF) + 2662 * (unsigned int)pChestWindow->ptr_1C + 3));
+    }
+    else
+    {
+      if ( pCurrentScreen )
+      {
+        if ( pCurrentScreen != 3 )
+        {
+          if ( pCurrentScreen != 7 )
+          {
+            if ( pCurrentScreen == 8 )//îêíî êíèãè çàêëîâ
+            {
+              if ( dword_507B00_spell_info_to_draw_in_popup )
+                DrawSpellDescriptionPopup((void *)(dword_507B00_spell_info_to_draw_in_popup - 1));
+            }
+            goto LABEL_132;
+          }
+LABEL_119:
+          if ( (signed int)pX > 467 && pCurrentScreen != 14 )
+          {
+            identify_item();
+            goto LABEL_132;
+          }
+          if ( (signed int)pY >= 345 )
+            goto LABEL_132;
+          if ( pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] == 100 )//2DEvent - CharacerScreenStats
+          {
+            CharacterUI_StatsTab_ShowHint();
+            goto LABEL_132;
+          }
+          if ( pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] == 101 )//2DEvent - CharacerScreenSkills
+          {
+            CharacterUI_SkillsTab_ShowHint();
+            goto LABEL_132;
+          }
+          v11 = pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] == 103;//2DEvent - CharacerScreenInventory
+          if ( !v11 )
+            goto LABEL_132;
+ 		  identify_item();
+          goto LABEL_132;
+        }
+        if ( !dword_506364
+          || (signed int)pX < (signed int)pViewport->uViewportX
+          || (signed int)pX > (signed int)pViewport->uViewportZ
+          || (signed int)pY < (signed int)pViewport->uViewportY
+          || (signed int)pY > (signed int)pViewport->uViewportW
+          || (v2 = (char *)sub_444564(), (pWindow.Hint = v2) == 0) )
+          goto LABEL_132;
+        v30 = (double)(pFontArrus->GetLineWidth(v2) + 32);
+        v27 = v30 + 6.7553994e15;
+        v29 = (char *)LODWORD(v27);
+        pWindow.uFrameWidth = LODWORD(v27);
+        pWindow.uFrameX = pX + 5;
+        pWindow.uFrameY = pY + 5;
+		pWindow.uFrameHeight = 64;
+        pAudioPlayer->StopChannels(-1, -1);
+        pWindow.DrawMessageBox(0);
+        goto LABEL_132;
+      }
+      if (GetCurrentMenuID() > 0)
+        goto LABEL_132;
+
+      if ( (signed int)pY > (signed int)pViewport->uViewportW )
+      {
+        pWindow.ptr_1C = (void *)((signed int)pX / 118);
+        if ( (signed int)pX / 118 < 4 )
+        {
+          pWindow.Hint = 0;
+          pWindow.uFrameWidth = 400;
+          pWindow.uFrameHeight = 200;
+          pWindow.uFrameX = 38;
+          pWindow.uFrameY = 60;
+          pAudioPlayer->StopChannels(-1, -1);
+          pWindow.DrawQuickCharRecord();
+        }
+        goto LABEL_132;
+      }
+      if ( (signed int)pX > (signed int)pViewport->uViewportZ )
+      {
+        if ( (signed int)pY >= 130 )
+        {
+          if ( (signed int)pX >= 476 && (signed int)pX <= 636 && (signed int)pY >= 240 && (signed int)pY <= 300 )
+          {
+            pWindow.Hint = 0;
+            pWindow.uFrameWidth = 400;
+            pWindow.uFrameHeight = 200;
+            pWindow.uFrameX = 38;
+            pWindow.uFrameY = 60;
+            pAudioPlayer->StopChannels(-1, -1);
+            pWindow._41D73D_draw_buff_tooltip();
+            goto LABEL_132;
+          }
+          if ( (signed int)pX < 485 || (signed int)pX > 548 || (signed int)pY < 156 || (signed int)pY > 229 )
+          {
+            if ( (signed int)pX < 566 || (signed int)pX > 629 || (signed int)pY < 156 || (signed int)pY > 229 )
+              goto LABEL_132;
+            pAudioPlayer->StopChannels(-1, -1);
+            v3 = (void *)1;
+          }
+          else
+          {
+            pAudioPlayer->StopChannels(-1, -1);
+            v3 = 0;
+          }
+          sub_416B01(v3);
+          goto LABEL_132;
+        }
+        pWindow.Hint = _4443D5_GetMinimapRightClickText();
+        pWindow.uFrameWidth = 256;
+        pWindow.uFrameX = 130;
+        pWindow.uFrameY = 140;
+        pWindow.uFrameHeight = 64;
+        pAudioPlayer->StopChannels(-1, -1);
+        pWindow.DrawMessageBox(0);
+        goto LABEL_132;
+      }
+      pWindow.Hint = 0;
+      pWindow.uFrameWidth = 320;
+      pWindow.uFrameHeight = 320;
+      v4 = pX - 350;
+      if ( (signed int)pX <= 320 )
+        v4 = pX + 30;
+      pWindow.uFrameX = v4;
+      pWindow.uFrameY = 40;
+      if ( pRenderer->pRenderD3D )
+        LOWORD(v5) = pGame->pVisInstance->get_picked_object_zbuf_val();
+      else
+        v5 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]];
+      v6 = (unsigned __int16)v5;
+      if ( (v6 & 7) != 2 )
+      {
+        if ( (v6 & 7) == 3 )
+        {
+          if ( pRenderer->uNumSceneBegins )
+          {
+            pWindow.DrawMessageBox(1);
+            MonsterPopup_Draw(v6 >> 3, &pWindow);
+          }
+          else
+          {
+            pRenderer->BeginScene();
+            pWindow.DrawMessageBox(1);
+            MonsterPopup_Draw(v6 >> 3, &pWindow);
+            pRenderer->EndScene();
+          }
+        }
+        goto LABEL_132;
+      }
+      v7 = v6 >> 3;
+      if ( pObjectList->pObjects[pLayingItems[v7].uObjectDescID].uFlags & 0x10 )
+        goto LABEL_132;
+      v8 = &pLayingItems[v7].stru_24;
+    }
+    GameUI_DrawItemInfo(v8);
+    goto LABEL_132;
+  }
+  if ( pCurrentScreen == 13 )//îêíî äîìà
+  {
+    if ( (signed int)pY < 345 && (signed int)pX < 469 )
+      sub_4B1A2D();
+    goto LABEL_132;
+  }
+  if ( pCurrentScreen <= 13 )
+    goto LABEL_132;
+  if ( pCurrentScreen <= 15 )
+    goto LABEL_119;
+  if ( pCurrentScreen != 21 )
+  {
+    v11 = pCurrentScreen == 23;
+    if ( !v11 )
+      goto LABEL_132;
+    identify_item();
+    goto LABEL_132;
+  }
+  pWindow.Hint = 0;
+  pStr = 0;
+  for ( pButton = pGUIWindow_CurrentMenu->pControlsHead; pButton; pButton = pButton->pNext)
+  {
+    if ( pButton->uButtonType == 1 && pButton->uButtonType != 3 && (signed int)pX > (signed int)pButton->uX && (signed int)pX < (signed int)pButton->uZ
+      && (signed int)pY > (signed int)pButton->uY && (signed int)pY < (signed int)pButton->uW )
+    {
+     pControlID = pButton->uControlID;
+     switch ( pControlID )
+	 {
+	 case 0: //stats info
+      pWindow.Hint = pAttributeDescriptions[(signed int)pButton->uControlParam % 7];
+      pStr = aAttributeNames[(signed int)pButton->uControlParam % 7];
+      break;
+	 case 62: //Plus button info 
+      pStr = pGlobalTXT_LocalizationStrings[670];//Äîáàâèòü
+      pWindow.Hint = pGlobalTXT_LocalizationStrings[671];//"Äîáàâëÿåò î÷êî ê âûäåëåííîìó íàâûêó, çàáèðàÿ åãî èç íàêîïèòåëÿ î÷êîâ"
+	  break;
+	 case 63: //Minus button info
+      pStr = pGlobalTXT_LocalizationStrings[668];//Âû÷åñòü
+      pWindow.Hint = pGlobalTXT_LocalizationStrings[669];//"Âû÷èòàåò î÷êî èç âûäåëåííîãî íàâûêà, âîçâðàùàÿ åãî â íàêîïèòåëü î÷êîâ"
+	  break;
+	 case 64: //Available skill button info
+      v18 = pParty->pPlayers[uPlayerCreationUI_SelectedCharacter].GetSkillIdxByOrder(pButton->uControlParam + 4);
+      pStr = pSkillNames[v18];
+      pWindow.Hint = pSkillDesc[v18];
+	  break;
+	 case 65: //Available Class Info
+      pWindow.Hint = pClassDescriptions[pButton->uControlParam];
+      pStr = pClassNames[pButton->uControlParam];
+	  break;
+     case 66: //OK Info
+      pWindow.Hint = pGlobalTXT_LocalizationStrings[664];//Ùåëêíèòå çäåñü äëÿ óòâåðæäåíèÿ ñîñòàâà îòðÿäà è ïðîäîëæåíèÿ èãðû.
+      pStr = pGlobalTXT_LocalizationStrings[665];//Êíîïêà ÎÊ
+	  break;
+	 case 67: //Clear info
+      pWindow.Hint = pGlobalTXT_LocalizationStrings[666];//Ñáðàñûâàåò âñå ïàðàìåòðû è íàâûêè îòðÿäà.
+      pStr = pGlobalTXT_LocalizationStrings[667];//Êíîïêà Î÷èñòèòü
+      break;
+	 case 118: // Character info
+      pStr = pParty->pPlayers[pButton->uControlParam].pName;
+      pWindow.Hint = pClassDescriptions[pParty->pPlayers[pButton->uControlParam].uClass];
+      break;
+     }
+     if ( pControlID > 68 && pControlID <= 75 ) //Sellected skills info
+     {
+      pSkillId = pParty->pPlayers[pButton->uControlParam].GetSkillIdxByOrder(pControlID - 72);
+      pY = 0;
+      if ( (signed int)pSkillId < 37 )
+      {
+	   pSkillInfo = CharacterUI_GetSkillDescText(pButton->uControlParam, (enum PLAYER_SKILL_TYPE)pSkillId);
+       strcpy(pTmpBuf2, pSkillInfo);
+       pWindow.Hint = pTmpBuf2;
+       pStr = pSkillNames[pSkillId];
+	  }
+     }
+	}
+  }
+  if ( pWindow.Hint )
+  {
+    pHint = pWindow.Hint;
+    pWindow.Hint = 0;
+    pWindow.uFrameWidth = 384;
+    pWindow.uFrameHeight = 256;
+    pWindow.uFrameX = 128;
+    pWindow.uFrameY = 40;
+    pWindow.uFrameHeight = pFontSmallnum->CalcTextHeight(pHint, &pWindow, 24, 0) + 2 * LOBYTE(pFontLucida->uFontHeight) + 24;
+    pWindow.uFrameZ = pWindow.uFrameX + pWindow.uFrameWidth - 1;
+    pWindow.uFrameW = pWindow.uFrameY + pWindow.uFrameHeight - 1;
+    pWindow.DrawMessageBox(0);
+    pWindow.uFrameX += 12;
+    pWindow.uFrameWidth -= 24;
+    pWindow.uFrameY += 12;
+    pWindow.uFrameHeight -= 12;
+    pWindow.uFrameZ = pWindow.uFrameX + pWindow.uFrameWidth - 1;
+    pWindow.uFrameW = pWindow.uFrameY + pWindow.uFrameHeight - 1;
+    pColor = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFF, 0xFF, 0x9B);
+    sprintf(pTmpBuf, pStr, pColor, format_4E2D80);//sprintfex äîëæåí áûòü - íå ðàáîòàåò sprintfex(pTmpBuf, format_4E2D80, v25, pStr)
+    pWindow.DrawTitleText(pFontCreate, 0, 0, 0, pTmpBuf, 3);
+    pWindow.DrawText(pFontSmallnum, 1, LOBYTE(pFontLucida->uFontHeight), 0, pHint, 0, 0, 0);
+  }
+LABEL_132:
+  dword_507BF0_is_there_popup_onscreen = 1;
+  viewparams->bRedrawGameUI = 1;
+}
+
+//----- (004175C0) --------------------------------------------------------
+void __thiscall UI_OnMouseLeftClick(int *pXY)
+{
+  int *pXY_; // esi@1
+  signed int y; // eax@7
+  signed int x; // ecx@7
+  unsigned int v4; // eax@11
+  signed int v5; // eax@17
+  signed int v6; // esi@19
+  int v7; // esi@30
+  GUIWindow *v8; // edx@31
+  GUIButton *i; // esi@37
+  signed int v10; // eax@50
+  int v11; // ecx@52
+  unsigned int pX; // [sp+14h] [bp-8h]@7
+  unsigned int pY; // [sp+18h] [bp-4h]@7
+
+  pXY_ = pXY;
+  if ( pCurrentScreen == 16
+    || sub_4637E0_is_there_popup_onscreen() )
+    return;
+  if ( pGUIWindow2 && pGUIWindow2->ptr_1C == (void *)33 )
+  {
+    sub_4452BB();
+    return;
+  }
+  if ( pXY_ )
+  {
+    x = *pXY_;
+    y = pXY_[1];
+    pX = *pXY_;
+    pY = y;
+  }
+  else
+  {
+    pMouse->GetClickPos(&pX, &pY);
+    y = pY;
+    x = pX;
+  }
+  if ( pCurrentScreen
+    || !dword_507B98_ctrl_pressed )
+    goto LABEL_30;
+  v4 = GetCurrentMenuID();
+  x = pX;
+  if ( (v4 & 0x80000000u) == 0
+    || (signed int)pX < (signed int)pViewport->uViewportX
+    || (signed int)pX > (signed int)pViewport->uViewportZ )
+  {
+    y = pY;
+LABEL_30:
+    v7 = uNumVisibleWindows;
+    if ( uNumVisibleWindows < 0 )
+      return;
+    while ( 1 )
+    {
+      //v8 = (GUIWindow *)&pWindowList_at_506F50_minus1_indexing[21 * pVisibleWindowsIdxs[v7]];
+      v8 = &pWindowList[pVisibleWindowsIdxs[v7] - 1];
+      if ( x >= (signed int)v8->uFrameX )
+      {
+        if ( x <= (signed int)v8->uFrameZ && y >= (signed int)v8->uFrameY && y <= (signed int)v8->uFrameW )
+          break;
+      }
+      --v7;
+      if ( v7 < 0 )
+        return;
+    }
+    for ( i = v8->pControlsHead; ; i = i->pNext )
+    {
+      if ( !i )
+        return;
+      if ( i->uButtonType == 1 )
+        goto LABEL_41;
+      if ( i->uButtonType != 2 )
+        break;
+      if ( (signed int)(signed __int64)sqrt((double)((x - i->uX) * (x - i->uX) + (y - i->uY) * (y - i->uY))) < (signed int)i->uWidth )
+        goto LABEL_50;
+      y = pY;
+      x = pX;
+LABEL_45:
+      ;
+    }
+    if ( i->uButtonType != 3 )
+      goto LABEL_45;
+LABEL_41:
+    if ( x >= (signed int)i->uX && x <= (signed int)i->uZ && y >= (signed int)i->uY && y <= (signed int)i->uW )
+    {
+LABEL_50:
+      i->field_2C = 1;
+      v10 = pMessageQueue_50CBD0->uNumMessages;
+      if ( pMessageQueue_50CBD0->uNumMessages )
+      {
+        v10 = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+        pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
+      }
+      //v11 = i->uControlParam;
+      pMessageQueue_50CBD0->SendMessage((UIMessageType)i->uControlID, i->uControlParam, 0);
+      return;
+    }
+    goto LABEL_45;
+  }
+  y = pY;
+  if ( (signed int)pY < (signed int)pViewport->uViewportY || (signed int)pY > (signed int)pViewport->uViewportW )
+    goto LABEL_30;
+  if ( pRenderer->pRenderD3D )
+    v5 = pGame->pVisInstance->get_picked_object_zbuf_val();
+  else
+    v5 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]];
+  v6 = (unsigned __int16)v5;
+  if ( (v5 & 7) == 3
+    && uActiveCharacter
+    && v5 < 33554432
+    && pPlayers[uActiveCharacter]->CanAct()
+    && pPlayers[uActiveCharacter]->CanSteal() )
+  {
+    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+    {
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)27;
+      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = v6 >> 3;
+      *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+      ++pMessageQueue_50CBD0->uNumMessages;
+    }
+    if ( pParty->bTurnBasedModeOn == 1 )
+    {
+      if ( pTurnEngine->field_4 == 3 )
+        pTurnEngine->field_18 |= 8u;
+    }
+  }
+}
+
+
+
+//----- (00417871) --------------------------------------------------------
+void __thiscall sub_417871(int *pXY)
+{
+  POINT v1; // [sp+0h] [bp-18h]@5
+  POINT a2; // [sp+8h] [bp-10h]@5
+  unsigned int pY; // [sp+10h] [bp-8h]@3
+  unsigned int pX; // [sp+14h] [bp-4h]@3
+
+  if ( !pRenderer->pRenderD3D )
+  {
+    if ( pXY )
+    {
+      pX = *pXY;
+      pY = pXY[1];
+    }
+    else
+    {
+      pMouse->GetClickPos(&pX, &pY);
+    }
+    pMouse->GetCursorPos(&a2);
+    pMouse->GetCursorPos(&v1);
+  }
+}
+
+//----- (004178C4) --------------------------------------------------------
+void __cdecl sub_4178C4()
+{
+  if ( pArcomageGame->bGameInProgress == 1 )
+  {
+    if (pAsyncMouse)
+      pArcomageGame->stru1.field_0 = 7;
+  }
+}
+
+//----- (004178E1) --------------------------------------------------------
+void __cdecl sub_4178E1()
+{
+  if ( pArcomageGame->bGameInProgress == 1 )
+  {
+    if (pAsyncMouse)
+      pArcomageGame->stru1.field_0 = 8;
+  }
+}
+
+//----- (004178FE) --------------------------------------------------------
+unsigned int __fastcall UI_GetHealthManaStringColor(signed int a1, signed int a2)
+{
+  unsigned __int16 v2; // dx@2
+  unsigned __int16 v3; // cx@2
+  int v5; // eax@5
+  unsigned __int16 v6; // [sp-4h] [bp-8h]@2
+
+  if ( a1 <= a2 )
+  {
+    if ( a1 == a2 )
+      return 0;
+    v5 = 100 * a1 / a2;
+    v3 = 255;
+    if ( v5 >= 25 )
+    {
+      v6 = 100;
+      v2 = 255;
+    }
+    else
+    {
+      v6 = 0;
+      v2 = 0;
+    }
+  }
+  else
+  {
+    v6 = 0;
+    v2 = 255;
+    v3 = 0;
+  }
+  return GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(v3, v2, v6);
+}
+
+//----- (00417939) --------------------------------------------------------
+signed int __thiscall GetConditionDrawColor(unsigned int uConditionIdx)
+{
+  unsigned int v1; // ebx@1
+  signed int v2; // edi@1
+  unsigned int v3; // esi@1
+  unsigned int v4; // eax@1
+  unsigned int v6; // [sp+Ch] [bp-4h]@1
+
+  v1 = uConditionIdx;
+  v2 = 65535;
+  v3 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
+  v6 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0x23u, 0);
+  v4 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0);
+  switch ( v1 )
+  {
+    case 0u:
+    case 1u:
+    case 3u:
+    case 4u:
+    case 5u:
+    case 6u:
+    case 7u:
+      v2 = v4;
+      break;
+    case 2u:
+    case 8u:
+    case 9u:
+    case 0xCu:
+    case 0xDu:
+      v2 = v3;
+      break;
+    case 0xAu:
+    case 0xBu:
+    case 0xEu:
+    case 0xFu:
+    case 0x10u:
+      v2 = v6;
+      break;
+    default:
+      return v2;
+  }
+  return v2;
+}
+
+//----- (004179BC) --------------------------------------------------------
+char __fastcall sub_4179BC_draw_tooltip(const char *a1, const char *a2)
+{
+  const char *v2; // ebx@1
+  const char *v3; // edi@1
+  unsigned int v4; // eax@1
+  GUIWindow Dst; // [sp+Ch] [bp-5Ch]@1
+  POINT v6; // [sp+60h] [bp-8h]@1
+
+  v2 = a2;
+  v3 = a1;
+  memset(&Dst, 0, 0x54u);
+  Dst.uFrameWidth = 384;
+  Dst.uFrameHeight = 256;
+  Dst.uFrameX = 128;
+  Dst.uFrameY = pMouse->GetCursorPos(&v6)->y + 30;
+  Dst.uFrameHeight = pFontSmallnum->CalcTextHeight(v2, &Dst, 24, 0) + 2 * LOBYTE(pFontLucida->uFontHeight) + 24;
+  Dst.uFrameZ = Dst.uFrameX + Dst.uFrameWidth - 1;
+  Dst.uFrameW = Dst.uFrameY + Dst.uFrameHeight - 1;
+  Dst.DrawMessageBox(0);
+  Dst.uFrameX += 12;
+  Dst.uFrameWidth -= 24;
+  Dst.uFrameY += 12;
+  Dst.uFrameHeight -= 12;
+  Dst.uFrameZ = Dst.uFrameX + Dst.uFrameWidth - 1;
+  Dst.uFrameW = Dst.uFrameY + Dst.uFrameHeight - 1;
+  v4 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  sprintf(pTmpBuf, format_4E2D80, v4, v3);
+  Dst.DrawTitleText(pFontCreate, 0, 0, 0, pTmpBuf, 3u);
+  return Dst.DrawText(pFontSmallnum, 1, LOBYTE(pFontLucida->uFontHeight), 0, v2, 0, 0, 0);
+}
+
+//----- (00417AD4) --------------------------------------------------------
+unsigned int __fastcall sub_417AD4(unsigned int uPlayerClass, enum PLAYER_SKILL_TYPE uPlayerSkillType, signed int a3)
+{
+  enum PLAYER_SKILL_TYPE v3; // ebx@1
+  signed int v4; // edi@1
+  unsigned int v5; // ecx@1
+  int v6; // edx@1
+  int v7; // eax@7
+  int v8; // eax@10
+  unsigned __int8 v9; // sf@10
+  unsigned __int8 v10; // of@10
+  int v11; // eax@11
+  int v12; // eax@14
+  unsigned int yellow; // [sp+Ch] [bp-Ch]@1
+  unsigned int red; // [sp+10h] [bp-8h]@1
+  unsigned int white; // [sp+14h] [bp-4h]@1
+
+  v3 = uPlayerSkillType;
+  v4 = uPlayerClass;
+  white = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+  red = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0, 0);
+  yellow = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0);
+  v5 = 0;
+  v6 = v4 % 4;
+  if ( !(v4 % 4) )
+  {
+    v11 = 37 * v4 + v3;
+    if ( byte_4ED970_skill_learn_ability_by_class_table[0][v11] >= a3 )
+      goto LABEL_8;
+    if ( byte_4ED970_skill_learn_ability_by_class_table[1][v11] < a3
+      && byte_4ED970_skill_learn_ability_by_class_table[2][v11] < a3 )
+    {
+      v12 = byte_4ED970_skill_learn_ability_by_class_table[3][v11];
+      v10 = __OFSUB__(v12, a3);
+      v9 = v12 - a3 < 0;
+LABEL_15:
+      v5 = red;
+      if ( v9 ^ v10 )
+        return v5;
+    }
+    return yellow;
+  }
+  if ( v6 == 1 )
+  {
+    v7 = 37 * v4 + v3;
+    if ( byte_4ED970_skill_learn_ability_by_class_table[0][v7] >= a3 )
+      goto LABEL_8;
+    if ( byte_4ED970_skill_learn_ability_by_class_table[1][v7] < a3 )
+    {
+      v8 = byte_4ED970_skill_learn_ability_by_class_table[2][v7];
+      v10 = __OFSUB__(v8, a3);
+      v9 = v8 - a3 < 0;
+      goto LABEL_15;
+    }
+    return yellow;
+  }
+  if ( v6 > 1 && v6 <= 3 )
+  {
+    if ( byte_4ED970_skill_learn_ability_by_class_table[v4][v3] < a3 )
+      return red;
+LABEL_8:
+    v5 = white;
+  }
+  return v5;
+}
+
+//----- (00417BB5) --------------------------------------------------------
+const char *__fastcall CharacterUI_GetSkillDescText(unsigned int uPlayerID, enum PLAYER_SKILL_TYPE uPlayerSkillType)
+{
+  enum PLAYER_SKILL_TYPE v2; // esi@1
+  unsigned int v3; // ebx@1
+  int v4; // edi@1
+  int v5; // eax@1
+  Player *pPlayer; // ebx@7
+  char v7; // al@7
+  char v8; // cl@7
+  unsigned int v9; // eax@8
+  unsigned int v10; // eax@8
+  unsigned int v11; // eax@8
+  enum PLAYER_SKILL_TYPE v12; // edi@8
+  unsigned int v13; // eax@8
+  unsigned int v14; // eax@8
+  enum PLAYER_SKILL_TYPE v15; // esi@8
+  int v16; // edi@8
+  char v17; // al@8
+  int v18; // ST5C_4@8
+  int v19; // ST4C_4@8
+  int v20; // ST3C_4@8
+  int v21; // ST2C_4@8
+  int v22; // ST1C_4@8
+  char *v23; // esi@8
+  unsigned int v24; // eax@9
+  unsigned int v25; // eax@9
+  unsigned int v26; // eax@9
+  unsigned int v27; // ecx@9
+  enum PLAYER_SKILL_TYPE v28; // ebx@9
+  unsigned int v29; // eax@9
+  char a2[1200]; // [sp+Ch] [bp-538h]@7
+  char Source[120]; // [sp+4BCh] [bp-88h]@7
+  unsigned __int16 *v33; // [sp+534h] [bp-10h]@1
+  int v34; // [sp+538h] [bp-Ch]@1
+  unsigned __int16 *v35; // [sp+53Ch] [bp-8h]@1
+  enum PLAYER_SKILL_TYPE v36; // [sp+540h] [bp-4h]@1
+
+  v2 = uPlayerSkillType;
+  v3 = uPlayerID;
+  v36 = uPlayerSkillType;
+  v4 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[431]);// Normal
+  v34 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[433]);// Expert
+  v33 = (unsigned __int16 *)pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[432]);// Master
+  v5 = pFontSmallnum->GetLineWidth(pGlobalTXT_LocalizationStrings[96]);// Grand
+  v35 = (unsigned __int16 *)v4;
+  if ( v34 > v4 )
+    v35 = (unsigned __int16 *)v34;
+  if ( (signed int)v33 > (signed int)v35 )
+    v35 = v33;
+  if ( v5 > (signed int)v35 )
+    v35 = (unsigned __int16 *)v5;
+  pPlayer = &pParty->pPlayers[v3];
+  v33 = &pPlayer->pActiveSkills[v2];
+  v7 = pPlayer->GetActualSkillLevel(v2);
+  v8 = LOBYTE(pPlayer->pActiveSkills[v2]);
+  a2[0] = 0;
+  Source[0] = 0;
+  if ( (v8 & 0x3F) == (v7 & 0x3F) )
+  {
+    strcpy(a2, "%s\n\n");
+    v24 = sub_417AD4(pPlayer->uClass, v2, 1);
+    sprintf(Source, format_4E2DC8, v24);
+    strcat(a2, Source);
+    strcat(a2, "%s\t%03d:\t%03d%s\t000\n");
+    v25 = sub_417AD4(pPlayer->uClass, v36, 2);
+    sprintf(Source, format_4E2DC8, v25);
+    strcat(a2, Source);
+    strcat(a2, "%s\t%03d:\t%03d%s\t000\n");
+    v26 = sub_417AD4(pPlayer->uClass, v36, 3);
+    sprintf(Source, format_4E2DC8, v26);
+    strcat(a2, Source);
+    strcat(a2, "%s\t%03d:\t%03d%s\t000\n");
+    v27 = pPlayer->uClass;
+    v28 = v36;
+    v29 = sub_417AD4(v27, v36, 4);
+    sprintf(Source, format_4E2DC8, v29);
+    strcat(a2, Source);
+    strcat(a2, "%s\t%03d:\t%03d%s\t000\n");
+
+    v23 = static_sub_417BB5_out_string;
+    sprintf(
+      static_sub_417BB5_out_string,
+      a2,
+      pSkillDesc[v28],
+      pGlobalTXT_LocalizationStrings[431],      // Normal
+      (char *)v35 + 3,
+      v35 + 5,
+      pNormalSkillDesc[v28],
+      pGlobalTXT_LocalizationStrings[433],      // Expert
+      (char *)v35 + 3,
+      v35 + 5,
+      pExpertSkillDesc[v28],
+      pGlobalTXT_LocalizationStrings[432],      // Master
+      (char *)v35 + 3,
+      v35 + 5,
+      pMasterSkillDesc[v28],
+      pGlobalTXT_LocalizationStrings[96],       // Grand
+      (char *)v35 + 3,
+      v35 + 5,
+      pGrandSkillDesc[v28]);
+  }
+  else
+  {
+    strcpy(a2, "%s\n\n");
+    v9 = sub_417AD4(pPlayer->uClass, v2, 1);
+    sprintf(Source, format_4E2DC8, v9);
+    strcat(a2, Source);
+    strcat(a2, "%s\t%03d:\t%03d%s\t000\n");
+    v10 = sub_417AD4(pPlayer->uClass, v36, 2);
+    sprintf(Source, format_4E2DC8, v10);
+    strcat(a2, Source);
+    strcat(a2, "%s\t%03d:\t%03d%s\t000\n");
+    v11 = sub_417AD4(pPlayer->uClass, v36, 3);
+    sprintf(Source, format_4E2DC8, v11);
+    strcat(a2, Source);
+    strcat(a2, "%s\t%03d:\t%03d%s\t000\n");
+    v12 = v36;
+    v13 = sub_417AD4(pPlayer->uClass, v36, 4);
+    sprintf(Source, format_4E2DC8, v13);
+    strcat(a2, Source);
+    strcat(a2, "%s\t%03d:\t%03d%s\t000\n\n");
+    v14 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
+    sprintf(Source, format_4E2DC8, v14);
+    strcat(a2, Source);
+    strcat(a2, "%s: +%d");
+    v15 = v12;
+    v16 = (int)(v35 + 5);
+    v15 = (PLAYER_SKILL_TYPE)((int)v15 * 4);
+    v34 = (int)((char *)v35 + 3);
+    v17 = pPlayer->GetActualSkillLevel(v36);
+    v18 = *(int *)((char *)pGrandSkillDesc + v15);
+    v19 = *(int *)((char *)pMasterSkillDesc + v15);
+    v20 = *(int *)((char *)pExpertSkillDesc + v15);
+    v21 = *(int *)((char *)pNormalSkillDesc + v15);
+    v22 = *(int *)((char *)pSkillDesc + v15);
+    v23 = static_sub_417BB5_out_string;
+    sprintf(
+      static_sub_417BB5_out_string,
+      a2,
+      v22,
+      pGlobalTXT_LocalizationStrings[431],
+      v34,
+      v16,
+      v21,
+      pGlobalTXT_LocalizationStrings[433],
+      v34,
+      v16,
+      v20,
+      pGlobalTXT_LocalizationStrings[432],
+      v34,
+      v16,
+      v19,
+      pGlobalTXT_LocalizationStrings[96],
+      v34,
+      v16,
+      v18,
+      pGlobalTXT_LocalizationStrings[623],
+      (v17 & 0x3F) - (*(char *)v33 & 0x3F));
+  }
+  return v23;
+}
+
+//----- (00417FE5) --------------------------------------------------------
+char __cdecl CharacterUI_SkillsTab_ShowHint()
+{
+  unsigned int v0; // ecx@1
+  unsigned int v1; // eax@1
+  GUIButton *i; // esi@6
+  const char *v3; // eax@12
+  unsigned int pX; // [sp+4h] [bp-8h]@1
+  unsigned int pY; // [sp+8h] [bp-4h]@1
+
+  pMouse->GetClickPos(&pX, &pY);
+  v0 = pX;
+  v1 = pY;
+  if ( (signed int)pX < 24 || (signed int)pX > 455 || (signed int)pY < 18 || (signed int)pY > 36 )
+  {
+    for ( i = pGUIWindow_CurrentMenu->pControlsHead; i; i = i->pNext )
+    {
+      if ( i->uControlID == 121
+        && (signed int)v0 >= (signed int)i->uX
+        && (signed int)v0 <= (signed int)i->uZ
+        && (signed int)v1 >= (signed int)i->uY
+        && (signed int)v1 <= (signed int)i->uW )
+      {
+        v3 = CharacterUI_GetSkillDescText(uActiveCharacter - 1, (enum PLAYER_SKILL_TYPE)i->uControlParam);
+        sub_4179BC_draw_tooltip(pSkillNames[i->uControlParam], v3);
+        v1 = pY;
+        v0 = pX;
+      }
+    }
+  }
+  else
+  {
+    LOBYTE(v1) = sub_4179BC_draw_tooltip(pGlobalTXT_LocalizationStrings[207], pSkillPointsAttributeDescription);
+  }
+  return v1;
+}
+
+//----- (00418083) --------------------------------------------------------
+char __cdecl CharacterUI_StatsTab_ShowHint()
+{
+  LONG _x; // esi@1
+  Player *_y; // eax@1
+  int v2; // edi@1
+  __int16 *v3; // ecx@1
+  LONG v4; // edx@2
+  signed int v5; // edx@4
+  char *v6; // ecx@9
+  char *v7; // ebx@9
+  unsigned int v8; // ebx@15
+  unsigned __int64 v9; // kr00_8@15
+  char *v10; // ST2C_4@15
+  signed int v11; // eax@15
+  char *v12; // ecx@17
+  char *v13; // eax@20
+  Player *v14; // esi@28
+  int v15; // ebx@28
+  int v16; // eax@33
+  POINT a2; // [sp+Ch] [bp-24h]@1
+  __int64 v19; // [sp+14h] [bp-1Ch]@15
+  char *v20; // [sp+1Ch] [bp-14h]@13
+  Player *v21; // [sp+20h] [bp-10h]@13
+  unsigned int v22; // [sp+24h] [bp-Ch]@15
+  int *v23; // [sp+28h] [bp-8h]@13
+  const char *v24; // [sp+2Ch] [bp-4h]@10
+
+  _x = pMouse->GetCursorPos(&a2)->x;
+  _y = (Player *)pMouse->GetCursorPos(&a2)->y;
+  v2 = 0;
+  v3 = &array_4E2940[0].field_2;
+  while ( 1 )
+  {
+    v4 = *(v3 - 1);
+    if ( _x >= v4 )
+    {
+      if ( _x <= v4 + v3[1] )
+      {
+        v5 = *v3;
+        if ( (signed int)_y >= v5 )
+        {
+          if ( (signed int)_y <= v5 + v3[2] )
+            break;
+        }
+      }
+    }
+    v3 += 4;
+    ++v2;
+    if ( (signed int)v3 >= (signed int)&off_4E2A12 )
+      return (char)_y;
+  }
+  switch ( v2 )
+  {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+      LOBYTE(_y) = 4 * v2;
+      v6 = aAttributeNames[v2];
+      v7 = pAttributeDescriptions[v2];
+      goto LABEL_46;
+    case 7:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[108]);
+      v7 = pHealthPointsAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[108];
+      goto LABEL_47;
+    case 8:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[212]);
+      v7 = pSpellPointsAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[212];
+      goto LABEL_47;
+    case 9:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[12]);
+      v7 = pArmourClassAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[12];
+      goto LABEL_47;
+    case 10:
+      v24 = pGlobalTXT_LocalizationStrings[47];
+      strcpy(pTmpBuf2, pPlayerConditionAttributeDescription);
+      v7 = pTmpBuf2;
+      v20 = pTmpBuf2;
+      strcat(pTmpBuf2, "\n");
+
+      extern unsigned int pConditionImportancyTable[18];
+      v23 = (int *)pConditionImportancyTable;
+      _y = pPlayers[uActiveCharacter];
+      v21 = pPlayers[uActiveCharacter];
+      do
+      {
+        if ( _y->pConditions[*v23] )
+        {
+          strcat(pTmpBuf2, " \n");
+          v8 = *v23;
+          v9 = pParty->uTimePlayed - v21->pConditions[*v23];
+          a2.x = LODWORD(pParty->uTimePlayed) - LODWORD(v21->pConditions[*v23]);
+          a2.y = HIDWORD(v9);
+          v19 = (signed __int64)((double)*(signed __int64 *)&a2 * 0.234375) / 60 / 60;
+          v22 = (unsigned int)v19 / 0x18;
+          v10 = aCharacterConditionNames[v8];
+          v19 %= 24i64;
+          v11 = GetConditionDrawColor(v8);
+          sprintf(pTmpBuf, &byte_4E2DE8, v11, v10);
+          strcat(pTmpBuf2, pTmpBuf);
+          if ( v19 && v19 <= 1 )
+            v12 = pGlobalTXT_LocalizationStrings[109];
+          else
+            v12 = pGlobalTXT_LocalizationStrings[110];
+          if ( !v22 || (v13 = pGlobalTXT_LocalizationStrings[56], v22 > 1) )
+            v13 = pGlobalTXT_LocalizationStrings[57];
+          sprintf(pTmpBuf, "%lu %s, %lu %s", v22, v13, v19, v12);
+          strcat(pTmpBuf2, pTmpBuf);
+          v7 = v20;
+          _y = v21;
+        }
+        ++v23;
+      }
+      while ( (signed int)v23 < (signed int)&unk_4EDF40 );
+      goto LABEL_47;
+    case 11:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[172]);
+      v7 = pFastSpellAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[172];
+      goto LABEL_47;
+    case 12:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[5]);
+      v7 = pPlayerAgeAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[5];
+      goto LABEL_47;
+    case 13:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[131]);
+      v7 = pPlayerLevelAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[131];
+      goto LABEL_47;
+    case 14:
+      v14 = pPlayers[uActiveCharacter];
+      v24 = pGlobalTXT_LocalizationStrings[83];
+      v15 = v14->uLevel;
+      do
+      {
+        if ( (signed __int64)v14->uExperience < (unsigned int)sub_4B46F8(v15) )
+          break;
+        ++v15;
+      }
+      while ( v15 <= 10000 );
+      pTmpBuf[0] = 0;
+      pTmpBuf2[0] = 0;
+      if ( v15 > v14->uLevel )
+        sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[147], v15);
+      v16 = sub_4B46F8(v15) - LODWORD(v14->uExperience);
+      sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[538], v16, v15 + 1);
+      strcat(pTmpBuf, "\n");
+      strcat(pTmpBuf, pTmpBuf2);
+      LOBYTE(_y) = sprintf(pTmpBuf2, "%s\n \n%s", pPlayerExperienceAttributeDescription, pTmpBuf);
+      v7 = pTmpBuf2;
+      goto LABEL_47;
+    case 15:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[587]);
+      v7 = pAttackBonusAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[587];
+      goto LABEL_47;
+    case 16:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[588]);
+      v7 = pAttackDamageAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[588];
+      goto LABEL_47;
+    case 17:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[589]);
+      v7 = pMissleBonusAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[589];
+      goto LABEL_47;
+    case 18:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[590]);
+      v7 = pMissleDamageAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[590];
+      goto LABEL_47;
+    case 19:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[87]);
+      v7 = pFireResistanceAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[87];
+      goto LABEL_47;
+    case 20:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[6]);
+      v7 = pAirResistanceAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[6];
+      goto LABEL_47;
+    case 21:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[240]);
+      v7 = pWaterResistanceAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[240];
+      goto LABEL_47;
+    case 22:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[70]);
+      v7 = pEarthResistanceAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[70];
+      goto LABEL_47;
+    case 23:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[142]);
+      v7 = pMindResistanceAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[142];
+      goto LABEL_47;
+    case 24:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[29]);
+      v7 = pBodyResistanceAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[29];
+      goto LABEL_47;
+    case 25:
+      LOBYTE(_y) = LOBYTE(pGlobalTXT_LocalizationStrings[207]);
+      v7 = pSkillPointsAttributeDescription;
+      v24 = pGlobalTXT_LocalizationStrings[207];
+      goto LABEL_47;
+    case 26:
+      _y = (Player *)(4 * pPlayers[uActiveCharacter]->uClass);
+      v6 = *(char **)((char *)_y->pConditions + (int)pClassNames);
+      v7 = *(char **)((char *)_y->pConditions + (int)pClassDescriptions);
+LABEL_46:
+      v24 = v6;
+LABEL_47:
+      if ( v24 && v7 )
+        LOBYTE(_y) = sub_4179BC_draw_tooltip(v24, v7);
+      break;
+    default:
+      return (char)_y;
+  }
+  return (char)_y;
+}
+
+//----- (00418511) --------------------------------------------------------
+char __fastcall CharacterUI_StatsTab_Draw(unsigned int uPlayerID)
+{
+  Player *pPlayer; // edi@1
+  unsigned int v2; // eax@1
+  unsigned int v3; // eax@1
+  unsigned int v4; // eax@2
+  int v5; // ST20_4@4
+  int v6; // ST1C_4@4
+  int v7; // ebp@4
+  int v8; // eax@4
+  unsigned int v9; // eax@4
+  int v10; // ST34_4@4
+  int v11; // ST20_4@4
+  int v12; // ST1C_4@4
+  int v13; // ebp@4
+  int v14; // eax@4
+  unsigned int v15; // eax@4
+  int v16; // ST34_4@4
+  int v17; // ST20_4@4
+  int v18; // ST1C_4@4
+  int v19; // ebp@4
+  int v20; // eax@4
+  unsigned int v21; // eax@4
+  int v22; // ST34_4@4
+  int v23; // ST20_4@4
+  int v24; // ST1C_4@4
+  int v25; // ebp@4
+  int v26; // eax@4
+  unsigned int v27; // eax@4
+  int v28; // ST34_4@4
+  int v29; // ST20_4@4
+  int v30; // ST1C_4@4
+  int v31; // ebp@4
+  int v32; // eax@4
+  unsigned int v33; // eax@4
+  int v34; // ST34_4@4
+  int v35; // ST20_4@4
+  int v36; // ST1C_4@4
+  int v37; // ebp@4
+  int v38; // eax@4
+  unsigned int v39; // eax@4
+  int v40; // ST34_4@4
+  int v41; // ST20_4@4
+  int v42; // ST1C_4@4
+  int v43; // ebp@4
+  int v44; // eax@4
+  unsigned int v45; // eax@4
+  int v46; // ebp@4
+  signed int v47; // ST20_4@6
+  int v48; // ST1C_4@6
+  signed int v49; // eax@6
+  unsigned int v50; // eax@6
+  int v51; // ST20_4@8
+  int v52; // ST1C_4@8
+  int v53; // eax@8
+  unsigned int v54; // eax@8
+  int v55; // ST34_4@8
+  int v56; // ST20_4@8
+  int v57; // ST1C_4@8
+  int v58; // ebp@8
+  int v59; // eax@8
+  unsigned int v60; // eax@8
+  unsigned int v61; // ebp@8
+  unsigned int v62; // eax@8
+  char *v63; // ST20_4@8
+  signed int v64; // eax@8
+  unsigned int v65; // ebp@8
+  unsigned __int8 v66; // al@8
+  char *v67; // eax@9
+  unsigned int v68; // ST20_4@11
+  unsigned int v69; // ST1C_4@11
+  signed int v70; // ebp@11
+  signed int v71; // eax@11
+  unsigned int v72; // eax@11
+  int v73; // ST20_4@13
+  int v74; // ST1C_4@13
+  int v75; // ebp@13
+  int v76; // eax@13
+  unsigned int v77; // eax@13
+  char *v78; // ecx@14
+  int v79; // ST20_4@16
+  char *v80; // ST40_4@16
+  unsigned int v81; // eax@16
+  int v82; // ST34_4@16
+  int v83; // eax@16
+  int v84; // ST34_4@16
+  char *v85; // eax@16
+  int v86; // ST34_4@16
+  int v87; // eax@16
+  int v88; // ST34_4@16
+  char *v89; // eax@16
+  int v90; // eax@16
+  int v91; // ST20_4@19
+  unsigned int v92; // eax@19
+  int v93; // eax@19
+  int v94; // ST20_4@22
+  unsigned int v95; // eax@22
+  int v96; // eax@22
+  int v97; // ST20_4@25
+  unsigned int v98; // eax@25
+  int v99; // eax@25
+  int v100; // ST20_4@27
+  unsigned int v101; // eax@27
+  int v102; // eax@27
+  int v103; // ST20_4@30
+  unsigned int v104; // eax@30
+  char *v105; // ST20_4@32
+  unsigned int v106; // eax@32
+  int v107; // eax@33
+  int v108; // ST20_4@36
+  unsigned int v109; // eax@36
+  char *v110; // ST20_4@38
+  unsigned int v111; // eax@38
+  int uY; // [sp+10h] [bp-10h]@6
+  int uYa; // [sp+10h] [bp-10h]@11
+  int uYb; // [sp+10h] [bp-10h]@13
+  int uYc; // [sp+10h] [bp-10h]@16
+  int uYd; // [sp+10h] [bp-10h]@19
+  int uYe; // [sp+10h] [bp-10h]@22
+  int uYf; // [sp+10h] [bp-10h]@25
+  int uYg; // [sp+10h] [bp-10h]@27
+  int uYh; // [sp+10h] [bp-10h]@33
+  const char *a2; // [sp+14h] [bp-Ch]@4
+  const char *a2a; // [sp+14h] [bp-Ch]@6
+  const char *a2b; // [sp+14h] [bp-Ch]@11
+  const char *a2c; // [sp+14h] [bp-Ch]@16
+  const char *a2d; // [sp+14h] [bp-Ch]@19
+  const char *a2e; // [sp+14h] [bp-Ch]@22
+  const char *a2f; // [sp+14h] [bp-Ch]@25
+  const char *a2g; // [sp+14h] [bp-Ch]@27
+  const char *a2h; // [sp+14h] [bp-Ch]@33
+  int v131; // [sp+18h] [bp-8h]@16
+  int v132; // [sp+18h] [bp-8h]@19
+  int v133; // [sp+18h] [bp-8h]@22
+  int v134; // [sp+18h] [bp-8h]@25
+  int v135; // [sp+18h] [bp-8h]@27
+  int v136; // [sp+18h] [bp-8h]@33
+  int v137; // [sp+1Ch] [bp-4h]@27
+  int v138; // [sp+1Ch] [bp-4h]@33
+
+  pPlayer = (Player *)&stru_AA1058[3].pSounds[6972 * uPlayerID + 40552];
+  v2 = pIcons_LOD->LoadTexture("fr_stats", TEXTURE_16BIT_PALETTE);
+  pRenderer->DrawTextureIndexed(8u, 8u, (Texture *)(v2 != -1 ? (int)&pIcons_LOD->pTextures[v2] : 0));
+  v3 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
+  sprintf(pTmpBuf, format_4E2DC8, v3);
+  sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[429], pPlayer->pName, pClassNames[pPlayer->uClass]);
+  strcat(pTmpBuf, pTmpBuf2);
+  if ( pPlayer->uSkillPoints )
+    v4 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0, 0xFFu, 0);
+  else
+    v4 = 0xFFFFu;
+  sprintf(pTmpBuf2, "\xC" "00000\xD" "180%s: \xC%05d%d\xC" "00000\n\n\n", pGlobalTXT_LocalizationStrings[207], v4, pPlayer->uSkillPoints);
+  strcat(pTmpBuf, pTmpBuf2);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, 18, 0, pTmpBuf, 0, 0, 0);
+  v5 = pPlayer->GetBaseStrength();
+  v6 = pPlayer->GetActualMight();
+  v7 = pPlayer->GetBaseStrength();
+  v8 = pPlayer->GetActualMight();
+  v9 = UI_GetHealthManaStringColor(v8, v7);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[144], v9, v6, v5);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, 53, 0, pTmpBuf, 0, 0, 0);
+  v10 = LOBYTE(pFontArrus->uFontHeight) + 51;
+  v11 = pPlayer->GetBaseIntelligence();
+  v12 = pPlayer->GetActualIntelligence();
+  v13 = pPlayer->GetBaseIntelligence();
+  v14 = pPlayer->GetActualIntelligence();
+  v15 = UI_GetHealthManaStringColor(v14, v13);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[116], v15, v12, v11);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v10, 0, pTmpBuf, 0, 0, 0);
+  v16 = LOBYTE(pFontArrus->uFontHeight) + v10 - 2;
+  v17 = pPlayer->GetBaseWillpower();
+  v18 = pPlayer->GetActualWillpower();
+  v19 = pPlayer->GetBaseWillpower();
+  v20 = pPlayer->GetActualWillpower();
+  v21 = UI_GetHealthManaStringColor(v20, v19);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[163], v21, v18, v17);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v16, 0, pTmpBuf, 0, 0, 0);
+  v22 = LOBYTE(pFontArrus->uFontHeight) + v16 - 2;
+  v23 = pPlayer->GetBaseEndurance();
+  v24 = pPlayer->GetActualEndurance();
+  v25 = pPlayer->GetBaseEndurance();
+  v26 = pPlayer->GetActualEndurance();
+  v27 = UI_GetHealthManaStringColor(v26, v25);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[75], v27, v24, v23);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v22, 0, pTmpBuf, 0, 0, 0);
+  v28 = LOBYTE(pFontArrus->uFontHeight) + v22 - 2;
+  v29 = pPlayer->GetBaseAccuracy();
+  v30 = pPlayer->GetActualAccuracy();
+  v31 = pPlayer->GetBaseAccuracy();
+  v32 = pPlayer->GetActualAccuracy();
+  v33 = UI_GetHealthManaStringColor(v32, v31);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[1], v33, v30, v29);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v28, 0, pTmpBuf, 0, 0, 0);
+  v34 = LOBYTE(pFontArrus->uFontHeight) + v28 - 2;
+  v35 = pPlayer->GetBaseSpeed();
+  v36 = pPlayer->GetActualSpeed();
+  v37 = pPlayer->GetBaseSpeed();
+  v38 = pPlayer->GetActualSpeed();
+  v39 = UI_GetHealthManaStringColor(v38, v37);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[211], v39, v36, v35);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v34, 0, pTmpBuf, 0, 0, 0);
+  v40 = LOBYTE(pFontArrus->uFontHeight) + v34 - 2;
+  v41 = pPlayer->GetBaseLuck();
+  v42 = pPlayer->GetActualLuck();
+  v43 = pPlayer->GetBaseLuck();
+  v44 = pPlayer->GetActualLuck();
+  v45 = UI_GetHealthManaStringColor(v44, v43);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[136], v45, v42, v41);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v40, 0, pTmpBuf, 0, 0, 0);
+  a2 = "%s";
+  v46 = v40 + 2 * LOBYTE(pFontArrus->uFontHeight) + 5;
+  if ( pPlayer->GetMaxHealth() >= 1000 )
+    a2 = (const char *)&unk_4E2EB8;
+  v47 = pPlayer->GetMaxHealth();
+  v48 = pPlayer->sHealth;
+  v49 = pPlayer->GetMaxHealth();
+  v50 = UI_GetHealthManaStringColor(pPlayer->sHealth, v49);
+  sprintf(pTmpBuf, a2, pGlobalTXT_LocalizationStrings[108], v50, v48, v47);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v46, 0, pTmpBuf, 0, 0, 0);
+  a2a = "%s";
+  uY = LOBYTE(pFontArrus->uFontHeight) + v46 - 2;
+  if ( pPlayer->GetMaxMana() >= 1000 )
+    a2a = (const char *)&unk_4E2EB8;
+  v51 = pPlayer->GetMaxMana();
+  v52 = pPlayer->sMana;
+  v53 = pPlayer->GetMaxMana();
+  v54 = UI_GetHealthManaStringColor(pPlayer->sMana, v53);
+  sprintf(pTmpBuf, a2a, pGlobalTXT_LocalizationStrings[212], v54, v52, v51);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, uY, 0, pTmpBuf, 0, 0, 0);
+  v55 = LOBYTE(pFontArrus->uFontHeight) + uY - 2;
+  v56 = pPlayer->GetBaseAC();
+  v57 = pPlayer->GetActualAC();
+  v58 = pPlayer->GetBaseAC();
+  v59 = pPlayer->GetActualAC();
+  v60 = UI_GetHealthManaStringColor(v59, v58);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[12], v60, v57, v56);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v55, 0, pTmpBuf, 0, 0, 0);
+  v61 = v55 + 2 * LOBYTE(pFontArrus->uFontHeight) - 2;
+  v62 = pPlayer->GetMajorConditionIdx();
+  v63 = aCharacterConditionNames[v62];
+  v64 = GetConditionDrawColor(v62);
+  sprintf(pTmpBuf, "%s: ", pGlobalTXT_LocalizationStrings[47], v64, v63);
+  pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 0x1Au, v61, 0, pTmpBuf, 226, 0);
+  v65 = LOBYTE(pFontArrus->uFontHeight) + v61 - 1;
+  v66 = pPlayer->uQuickSpell;
+  if ( v66 )
+    v67 = pSpellStats->pInfos[v66].pShortName;
+  else
+    v67 = pGlobalTXT_LocalizationStrings[153];
+  sprintf(pTmpBuf, "%s: %s", pGlobalTXT_LocalizationStrings[172], v67);
+  pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 0x1Au, v65, 0, pTmpBuf, 226, 0);
+  v68 = pPlayer->GetBaseAge();
+  v69 = pPlayer->GetActualAge();
+  v70 = pPlayer->GetBaseAge();
+  v71 = pPlayer->GetActualAge();
+  v72 = UI_GetHealthManaStringColor(v71, v70);
+  sprintf(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[5], v72, v69, v68);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, 50, 0, pTmpBuf, 0, 0, 0);
+  a2b = "%s";
+  uYa = LOBYTE(pFontArrus->uFontHeight) + 48;
+  if ( pPlayer->GetBaseLevel() > 99 )
+    a2b = format_4E2E68;
+  v73 = pPlayer->GetBaseLevel();
+  v74 = pPlayer->GetActualLevel();
+  v75 = pPlayer->GetBaseLevel();
+  v76 = pPlayer->GetActualLevel();
+  v77 = UI_GetHealthManaStringColor(v76, v75);
+  sprintf(pTmpBuf, a2b, pGlobalTXT_LocalizationStrings[131], v77, v74, v73);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, uYa, 0, pTmpBuf, 0, 0, 0);
+  uYb = uYa + LOBYTE(pFontArrus->uFontHeight) - 2;
+  if ( (signed __int64)pPlayer->uExperience <= 9999999 )
+    v78 = pGlobalTXT_LocalizationStrings[83];
+  else
+    v78 = pGlobalTXT_LocalizationStrings[17];
+  v79 = LODWORD(pPlayer->uExperience);
+  v80 = v78;
+  v81 = pPlayer->GetExperienceDisplayColor();
+  sprintf(pTmpBuf, "%s\r180", v80, v81, v79);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, uYb, 0, pTmpBuf, 0, 0, 0);
+  v82 = uYb + 2 * LOBYTE(pFontArrus->uFontHeight);
+  v83 = pPlayer->GetActualAttack(0);
+  sprintf(pTmpBuf, "%s\t100%+d\n", pGlobalTXT_LocalizationStrings[18], v83);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, v82, 0, pTmpBuf, 0, 0, 0);
+  v84 = v82 + LOBYTE(pFontArrus->uFontHeight) - 2;
+  v85 = pPlayer->GetMeleeDamageString();
+  sprintf(pTmpBuf, "%s\t100 %s\n", pGlobalTXT_LocalizationStrings[53], v85);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, v84, 0, pTmpBuf, 0, 0, 0);
+  v86 = v84 + LOBYTE(pFontArrus->uFontHeight) - 2;
+  v87 = pPlayer->GetRangedAttack();
+  sprintf(pTmpBuf, "%s\t100%+d\n", pGlobalTXT_LocalizationStrings[203], v87);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, v86, 0, pTmpBuf, 0, 0, 0);
+  v88 = v86 + LOBYTE(pFontArrus->uFontHeight) - 2;
+  v89 = pPlayer->GetRangedDamageString();
+  sprintf(pTmpBuf, "%s\t100 %s\n\n", pGlobalTXT_LocalizationStrings[53], v89);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, v88, 0, pTmpBuf, 0, 0, 0);
+  a2c = format_4E2E10;
+  uYc = v88 + 2 * LOBYTE(pFontArrus->uFontHeight) - 4;
+  v131 = pPlayer->GetActualResistance(CHARACTER_ATTRIBUTE_RESIST_FIRE);
+  v90 = pPlayer->GetBaseResistance(CHARACTER_ATTRIBUTE_RESIST_FIRE);
+  if ( v131 > 99 || v90 > 99 )
+    a2c = format_4E2E68;
+  v91 = v90;
+  v92 = UI_GetHealthManaStringColor(v131, v90);
+  sprintf(pTmpBuf, a2c, pGlobalTXT_LocalizationStrings[87], v92, v131, v91);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, uYc, 0, pTmpBuf, 0, 0, 0);
+  a2d = format_4E2E10;
+  uYd = uYc + LOBYTE(pFontArrus->uFontHeight) - 2;
+  v132 = pPlayer->GetActualResistance(CHARACTER_ATTRIBUTE_RESIST_AIR);
+  v93 = pPlayer->GetBaseResistance(CHARACTER_ATTRIBUTE_RESIST_AIR);
+  if ( v132 > 99 || v93 > 99 )
+    a2d = format_4E2E68;
+  v94 = v93;
+  v95 = UI_GetHealthManaStringColor(v132, v93);
+  sprintf(pTmpBuf, a2d, pGlobalTXT_LocalizationStrings[6], v95, v132, v94);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, uYd, 0, pTmpBuf, 0, 0, 0);
+  a2e = format_4E2E10;
+  uYe = uYd + LOBYTE(pFontArrus->uFontHeight) - 2;
+  v133 = pPlayer->GetActualResistance(CHARACTER_ATTRIBUTE_RESIST_WATER);
+  v96 = pPlayer->GetBaseResistance(CHARACTER_ATTRIBUTE_RESIST_WATER);
+  if ( v133 > 99 || v96 > 99 )
+    a2e = format_4E2E68;
+  v97 = v96;
+  v98 = UI_GetHealthManaStringColor(v133, v96);
+  sprintf(pTmpBuf, a2e, pGlobalTXT_LocalizationStrings[240], v98, v133, v97);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, uYe, 0, pTmpBuf, 0, 0, 0);
+  a2f = format_4E2E10;
+  uYf = uYe + LOBYTE(pFontArrus->uFontHeight) - 2;
+  v134 = pPlayer->GetActualResistance(CHARACTER_ATTRIBUTE_RESIST_EARTH);
+  v99 = pPlayer->GetBaseResistance(CHARACTER_ATTRIBUTE_RESIST_EARTH);
+  if ( v134 > 99 )
+    a2f = format_4E2E68;
+  v100 = v99;
+  v101 = UI_GetHealthManaStringColor(v134, v99);
+  sprintf(pTmpBuf, a2f, pGlobalTXT_LocalizationStrings[70], v101, v134, v100);
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, uYf, 0, pTmpBuf, 0, 0, 0);
+  a2g = format_4E2E10;
+  uYg = uYf + LOBYTE(pFontArrus->uFontHeight) - 2;
+  v135 = pPlayer->GetActualResistance(CHARACTER_ATTRIBUTE_RESIST_MIND);
+  v102 = pPlayer->GetBaseResistance(CHARACTER_ATTRIBUTE_RESIST_MIND);
+  v137 = v102;
+  if ( v135 > 99 || v102 > 99 )
+    a2g = format_4E2E68;
+  v103 = v102;
+  v104 = UI_GetHealthManaStringColor(v135, v102);
+  sprintf(pTmpBuf, a2g, pGlobalTXT_LocalizationStrings[142], v104, v135, v103);
+  if ( pPlayer->uClass == 35 && v137 == 200 )
+  {
+    v105 = pGlobalTXT_LocalizationStrings[625];
+    v106 = UI_GetHealthManaStringColor(v135, 200);
+    sprintf(pTmpBuf, format_4E2E00, pGlobalTXT_LocalizationStrings[142], v106, v105);
+  }
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, uYg, 0, pTmpBuf, 0, 0, 0);
+  a2h = format_4E2E10;
+  uYh = uYg + LOBYTE(pFontArrus->uFontHeight) - 2;
+  v136 = pPlayer->GetActualResistance(CHARACTER_ATTRIBUTE_RESIST_BODY);
+  v107 = pPlayer->GetBaseResistance(CHARACTER_ATTRIBUTE_RESIST_BODY);
+  v138 = v107;
+  if ( v136 > 99 || v107 > 99 )
+    a2h = format_4E2E68;
+  v108 = v107;
+  v109 = UI_GetHealthManaStringColor(v136, v107);
+  sprintf(pTmpBuf, a2h, pGlobalTXT_LocalizationStrings[29], v109, v136, v108);
+  if ( pPlayer->uClass == 35 && v138 == 200 )
+  {
+    v110 = pGlobalTXT_LocalizationStrings[625];
+    v111 = UI_GetHealthManaStringColor(v136, 200);
+    sprintf(pTmpBuf, format_4E2E00, pGlobalTXT_LocalizationStrings[29], v111, v110);
+  }
+  return pGUIWindow_CurrentMenu->DrawText(pFontArrus, 266, uYh, 0, pTmpBuf, 0, 0, 0);
+}
+
+//----- (00419100) --------------------------------------------------------
+int __cdecl sub_419100()
+{
+  Player *v0; // esi@1
+  int v1; // ebx@1
+  unsigned __int8 *v2; // esi@1
+  int v3; // eax@4
+  int result; // eax@6
+  int v5; // esi@6
+  unsigned __int8 v6; // zf@6
+  unsigned __int8 v7; // sf@6
+  int v8; // edx@7
+  int v9; // ecx@7
+  unsigned __int8 v10; // of@7
+  stru179 *v11; // edi@9
+  int v12; // edx@11
+  int v13; // [sp+Ch] [bp-8h]@2
+  signed int v14; // [sp+Ch] [bp-8h]@9
+  int i; // [sp+10h] [bp-4h]@10
+
+  v0 = pPlayers[uActiveCharacter];
+  memset(&pStru179, 0, 0xFA0u);
+  memset(pTmpBuf2, 0, 0x7D0u);
+  v1 = 0;
+  dword_506544 = 0;
+  dword_506548 = 0;
+  dword_506520 = 0;
+  dword_50651C = 0;
+  dword_506528 = 0;
+  v2 = (unsigned __int8 *)v0->field_152;
+  do
+  {
+    v13 = dword_723E80_award_related[2 * v1];
+    if ( (unsigned __int16)_449B57_test_bit(v2, v1) && v13 )
+    {
+      v3 = dword_506520++;
+      pStru179->field_0[v3] = v1;
+    }
+    ++v1;
+  }
+  while ( v1 < 105 );
+  result = dword_506520;
+  v5 = 0;
+  v6 = dword_506520 == 0;
+  v7 = dword_506520 < 0;
+  dword_506524 = dword_506520;
+  dword_506520 = 0;
+  if ( !(v7 | v6) )
+  {
+    do
+    {
+      v8 = rand() % 16;
+      result = dword_506524;
+      v9 = dword_506524 + v5++;
+      v10 = __OFSUB__(v5, dword_506524);
+      v7 = v5 - dword_506524 < 0;
+      pStru179->field_0[v9] = v8;
+    }
+    while ( v7 ^ v10 );
+    if ( result > 0 )
+    {
+      v14 = 1;
+      v11 = pStru179;
+      do
+      {
+        for ( i = v14; i < result; ++i )
+        {
+          v12 = pStru179->field_0[i];
+          if ( dword_723E84[2 * v12] < dword_723E84[2 * v11->field_0[0]] )
+          {
+            pStru179->field_0[i] = v11->field_0[0];
+            v11->field_0[0] = v12;
+          }
+        }
+        ++v14;
+        v11 = (stru179 *)((char *)v11 + 4);
+      }
+      while ( v14 - 1 < result );
+    }
+  }
+  return result;
+}
+
+
+//----- (00419220) --------------------------------------------------------
+void __cdecl sub_419220()
+{
+  GUIButton *i; // eax@2
+
+  if ( !dword_507CBC )
+  {
+    dword_507CBC = 1;
+    for ( i = pGUIWindow_CurrentMenu->pControlsHead; i; i = i->pNext )
+    {
+      if ( i->uControlID == 120 )
+      {
+        dword_50698C = i->uX;
+        dword_506988 = i->uY;
+        dword_506984 = i->uZ;
+        dword_506980 = i->uW;
+        i->uW = 0;
+        i->uZ = 0;
+        i->uY = 0;
+        i->uX = 0;
+      }
+    }
+    pBtn_Up = pGUIWindow_CurrentMenu->CreateButton(
+                   0x1B6u,
+                   0x2Eu,
+                   (uTextureID_ar_up_up != -1 ? pIcons_LOD->pTextures[uTextureID_ar_up_up].uTextureWidth : 24),
+                   (uTextureID_ar_up_up != -1 ? pIcons_LOD->pTextures[uTextureID_ar_up_up].uTextureHeight : 26),
+                   1,
+                   0,
+                   0xA9u,
+                   0,
+                   0,
+                   "",
+                   (Texture *)(uTextureID_ar_up_up != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_ar_up_up] : 0),
+                   uTextureID_ar_up_dn != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_ar_up_dn] : 0,
+                   0);
+    pBtn_Down = pGUIWindow_CurrentMenu->CreateButton(
+                   0x1B6u,
+                   0x124u,
+                   (uTextureID_ar_dn_up != -1 ? pIcons_LOD->pTextures[uTextureID_ar_dn_up].uTextureWidth : 24),
+                   (uTextureID_ar_dn_up != -1 ? pIcons_LOD->pTextures[uTextureID_ar_dn_up].uTextureHeight : 26),
+                   1,
+                   0,
+                   0xAAu,
+                   0,
+                   0,
+                   "",
+                   (Texture *)(uTextureID_ar_dn_up != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_ar_dn_up] : 0),
+                   uTextureID_ar_dn_dn != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_ar_dn_dn] : 0,
+                   0);
+    ptr_507BA4 = pGUIWindow_CurrentMenu->CreateButton(
+                   0x1B8u,
+                   0x3Eu,
+                   0x10u,
+                   0xE8u,
+                   1,
+                   0,
+                   0xC0u,
+                   0,
+                   0,
+                   "",
+                   0);
+  }
+}
+
+
+
+//----- (00419379) --------------------------------------------------------
+void __cdecl sub_419379()
+{
+  GUIButton *i; // esi@2
+
+  if ( dword_507CBC )
+  {
+    dword_507CBC = 0;
+    GUIButton::_41D0D8(ptr_507BA4);
+    GUIButton::_41D0D8(pBtn_Up);
+    GUIButton::_41D0D8(pBtn_Down);
+    pBtn_Down = 0;
+    pBtn_Up = 0;
+    for ( i = pGUIWindow_CurrentMenu->pControlsHead; i; i = i->pNext )
+    {
+      if ( i->uControlID == 120 )
+      {
+        i->uX = dword_50698C;
+        i->uY = dword_506988;
+        i->uZ = dword_506984;
+        i->uW = dword_506980;
+        pGUIWindow_CurrentMenu->_41D08F(1, 0, 0, 0);
+      }
+    }
+  }
+}
+
+
+//----- (00419401) --------------------------------------------------------
+void __cdecl sub_419401()
+{
+  unsigned int v0; // ecx@3
+  GUIButton *i; // eax@3
+  GUIFont *v2; // eax@8
+  unsigned int v3; // esi@8
+  int v4; // eax@10
+  unsigned int v5; // esi@14
+  int v6; // eax@17
+  unsigned int v7; // esi@19
+  int v8; // eax@21
+  unsigned int v9; // esi@25
+  int v10; // eax@27
+  int a2; // [sp+10h] [bp-14h]@1
+  int v12; // [sp+14h] [bp-10h]@8
+  int v13; // [sp+14h] [bp-10h]@19
+  unsigned int *v14; // [sp+18h] [bp-Ch]@8
+  unsigned int *v15; // [sp+18h] [bp-Ch]@14
+  unsigned int *v16; // [sp+18h] [bp-Ch]@19
+  unsigned int *v17; // [sp+18h] [bp-Ch]@25
+  char *v18; // [sp+1Ch] [bp-8h]@8
+  int a5; // [sp+20h] [bp-4h]@8
+
+  a2 = 0;
+  if ( dword_507CC0 )
+    sub_4196A0();
+  v0 = uActiveCharacter;
+  dword_507CC0 = uActiveCharacter;
+  for ( i = pGUIWindow_CurrentMenu->pControlsHead; i; i = i->pNext )
+  {
+    if ( i->uControlID == 120 )
+    {
+      dword_50698C = i->uX;
+      dword_506988 = i->uY;
+      dword_506984 = i->uZ;
+      dword_506980 = i->uW;
+      i->uW = 0;
+      i->uZ = 0;
+      i->uY = 0;
+      i->uX = 0;
+      v0 = uActiveCharacter;
+    }
+  }
+  v12 = 0;
+  a5 = pGUIWindow_CurrentMenu->uNumControls;
+  v18 = &stru_AA1058[3].pSounds[6972 * v0 + 40552];
+  v2 = pFontLucida;
+  v14 = (unsigned int *)dword_4E2A2C;
+  v3 = 2 * LOBYTE(pFontLucida->uFontHeight) + 13;
+  do
+  {
+    if ( v18[2 * *v14 + 264] & 0x3F )
+    {
+      v4 = LOBYTE(v2->uFontHeight);
+      v3 = v3 + v4 - 3;
+      ++a2;
+      ++v12;
+      pGUIWindow_CurrentMenu->CreateButton(
+        0x18u,
+        v3,
+        0xCCu,
+        v4 - 3,
+        3,
+        *v14 | 0x8000,
+        0x79u,
+        *v14,
+        0,
+        "",
+        0);
+      v2 = pFontLucida;
+    }
+    ++v14;
+  }
+  while ( (signed int)v14 < (signed int)dword_4E2A50 );
+  if ( !v12 )
+    v3 = v3 + LOBYTE(v2->uFontHeight) - 3;
+  v15 = (unsigned int *)_4E2A80_skills;
+  v5 = v3 + 2 * LOBYTE(v2->uFontHeight) - 6;
+  do
+  {
+    if ( v18[2 * *v15 + 264] & 0x3F && a2 < 15 )
+    {
+      v6 = LOBYTE(v2->uFontHeight);
+      v5 = v5 + v6 - 3;
+      ++a2;
+      pGUIWindow_CurrentMenu->CreateButton(
+        0x18u,
+        v5,
+        0xCCu,
+        v6 - 3,
+        3,
+        *v15 | 0x8000,
+        0x79u,
+        *v15,
+        0,
+        "",
+        0);
+      v2 = pFontLucida;
+    }
+    ++v15;
+  }
+  while ( (signed int)v15 < (signed int)pAwardsTextColors );
+  v13 = 0;
+  v16 = (unsigned int *)dword_4E2A18;
+  v7 = 2 * LOBYTE(v2->uFontHeight) + 13;
+  do
+  {
+    if ( v18[2 * *v16 + 264] & 0x3F )
+    {
+      v8 = LOBYTE(v2->uFontHeight);
+      v7 = v7 + v8 - 3;
+      ++a2;
+      ++v13;
+      pGUIWindow_CurrentMenu->CreateButton(
+        0xF6u,
+        v7,
+        0xCCu,
+        v8 - 3,
+        3,
+        *v16 | 0x8000,
+        0x79u,
+        *v16,
+        0,
+        "",
+        0);
+      v2 = pFontLucida;
+    }
+    ++v16;
+  }
+  while ( (signed int)v16 < (signed int)dword_4E2A2C );
+  if ( !v13 )
+    v7 = v7 + LOBYTE(v2->uFontHeight) - 3;
+  v17 = (unsigned int *)dword_4E2A50;
+  v9 = v7 + 2 * LOBYTE(v2->uFontHeight) - 6;
+  do
+  {
+    if ( v18[2 * *v17 + 264] & 0x3F )
+    {
+      v10 = LOBYTE(v2->uFontHeight);
+      v9 = v9 + v10 - 3;
+      ++a2;
+      pGUIWindow_CurrentMenu->CreateButton(
+        0xF6u,
+        v9,
+        0xCCu,
+        v10 - 3,
+        3,
+        *v17 | 0x8000,
+        0x79u,
+        *v17,
+        0,
+        "",
+        0);
+      v2 = pFontLucida;
+    }
+    ++v17;
+  }
+  while ( (signed int)v17 < (signed int)_4E2A80_skills );
+  if ( a2 )
+    pGUIWindow_CurrentMenu->_41D08F(a2, 1, 0, a5);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mm7_6.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,9308 @@
+#include "MM7.h"
+
+#include "MapInfo.h"
+#include "Game.h"
+#include "GUIWindow.h"
+#include "GUIFont.h"
+#include "GUIButton.h"
+#include "GUIProgressBar.h"
+#include "Party.h"
+#include "AudioPlayer.h"
+#include "Outdoor.h"
+#include "IndoorCamera.h"
+#include "Overlays.h"
+#include "Monsters.h"
+#include "Arcomage.h"
+#include "LOD.h"
+#include "Actor.h"
+#include "Allocator.h"
+#include "Events.h"
+#include "Viewport.h"
+#include "FrameTableInc.h"
+#include "Math.h"
+#include "LayingItem.h"
+#include "ObjectList.h"
+#include "Chest.h"
+#include "PaletteManager.h"
+#include "DecorationList.h"
+#include "SaveLoad.h"
+#include "stru123.h"
+#include "Time.h"
+#include "IconFrameTable.h"
+#include "stru179.h"
+#include "Awards.h"
+#include "Autonotes.h"
+#include "stru160.h"
+#include "stru279.h"
+#include "TurnEngine.h"
+#include "stru277.h"
+#include "Weather.h"
+#include "stru272.h"
+#include "stru298.h"
+#include "StorylineTextTable.h"
+#include "Events2D.h"
+
+#include "mm7_data.h"
+
+
+
+//----- (00424EE0) --------------------------------------------------------
+signed int __fastcall sr_424EE0_MakeFanFromTriangle(unsigned int uVertexID)
+{
+  unsigned int v1; // edx@1
+  double v2; // st7@1
+  signed int v3; // edi@1
+  char *v4; // esi@4
+  char *v5; // ecx@4
+  unsigned int v6; // eax@4
+  char *v7; // edx@4
+  double v8; // st6@10
+  double v9; // st5@10
+  double v10; // st6@11
+  unsigned __int8 v11; // c2@15
+  unsigned __int8 v12; // c3@15
+  void *v13; // edi@22
+  char *v14; // eax@22
+  double v15; // st6@22
+  char *v16; // ecx@22
+  signed int result; // eax@24
+  unsigned int v18; // [sp+8h] [bp-2Ch]@4
+  bool v19; // [sp+Ch] [bp-28h]@6
+  char *v20; // [sp+10h] [bp-24h]@4
+  char *v21; // [sp+14h] [bp-20h]@4
+  signed int v22; // [sp+18h] [bp-1Ch]@1
+  char *v23; // [sp+1Ch] [bp-18h]@4
+  RenderVertexSoft *v24; // [sp+20h] [bp-14h]@4
+  char *v25; // [sp+24h] [bp-10h]@4
+  char *v26; // [sp+28h] [bp-Ch]@4
+  char *v27; // [sp+2Ch] [bp-8h]@4
+  char *v28; // [sp+30h] [bp-4h]@4
+
+  v1 = uVertexID;
+  v2 = (double)pOutdoorCamera->shading_dist_mist;
+  memcpy(&array_50AC10[uVertexID], array_50AC10, sizeof(array_50AC10[uVertexID]));
+  v3 = 0;
+  v22 = 0;
+  if ( array_50AC10[0].vWorldViewPosition.x <= v2 )
+    v3 = 1;
+  if ( (signed int)(uVertexID + 1) <= 1 )
+    return 0;
+  v4 = (char *)&array_507D30[0].vWorldViewPosition.z;
+  v5 = (char *)&array_507D30[0].vWorldViewPosition.y;
+  v6 = v1;
+  v23 = (char *)&array_507D30[0].flt_2C;
+  v26 = (char *)&array_507D30[0].flt_20;
+  v24 = array_507D30;
+  v20 = (char *)&array_507D30[0].vWorldViewPosition.z;
+  v21 = (char *)&array_507D30[0].vWorldViewPosition.y;
+  v25 = (char *)&array_507D30[0].vWorldViewPosition;
+  v27 = (char *)&array_507D30[0].v;
+  v28 = (char *)&array_507D30[0].u;
+  v7 = (char *)&array_50AC10[0].v;
+  v18 = v6;
+  do
+  {
+    v19 = v2 >= *((float *)v7 + 5);
+    if ( v3 != v19 )
+    {
+      if ( v19 )
+      {
+        v8 = (v2 - *((float *)v7 - 7)) / (*((float *)v7 + 5) - *((float *)v7 - 7));
+        *(float *)v5 = (*((float *)v7 + 6) - *((float *)v7 - 6)) * v8 + *((float *)v7 - 6);
+        *(float *)v4 = (*((float *)v7 + 7) - *((float *)v7 - 5)) * v8 + *((float *)v7 - 5);
+        *(float *)v28 = (*((float *)v7 + 11) - *((float *)v7 - 1)) * v8 + *((float *)v7 - 1);
+        v9 = (*((float *)v7 + 12) - *(float *)v7) * v8 + *(float *)v7;
+      }
+      else
+      {
+        v10 = (v2 - *((float *)v7 + 5)) / (*((float *)v7 - 7) - *((float *)v7 + 5));
+        *(float *)v5 = (*((float *)v7 - 6) - *((float *)v7 + 6)) * v10 + *((float *)v7 + 6);
+        *(float *)v4 = (*((float *)v7 - 5) - *((float *)v7 + 7)) * v10 + *((float *)v7 + 7);
+        *(float *)v28 = (*((float *)v7 - 1) - *((float *)v7 + 11)) * v10 + *((float *)v7 + 11);
+        v9 = (*(float *)v7 - *((float *)v7 + 12)) * v10 + *((float *)v7 + 12);
+      }
+      *(float *)v27 = v9;
+      *(float *)v25 = v2;
+      *(float *)v26 = 1.0 / v2;
+      if ( v3 )
+      {
+        if ( v2 == *((float *)v7 - 7) && *(float *)v5 == *((float *)v7 - 6) )
+        {
+          v11 = 0;
+          v12 = *(float *)v4 == *((float *)v7 - 5);
+          goto LABEL_19;
+        }
+      }
+      else
+      {
+        if ( v2 == *((float *)v7 + 5) && *(float *)v5 == *((float *)v7 + 6) )
+        {
+          v11 = 0;
+          v12 = *(float *)v4 == *((float *)v7 + 7);
+LABEL_19:
+          if ( v12 | v11 )
+            goto LABEL_21;
+          goto LABEL_20;
+        }
+      }
+LABEL_20:
+      v26 += 48;
+      ++v24;
+      v25 += 48;
+      v27 += 48;
+      v28 += 48;
+      v5 += 48;
+      v4 += 48;
+      ++v22;
+      v23 += 48;
+      v21 = v5;
+      v20 = v4;
+    }
+LABEL_21:
+    if ( v19 )
+    {
+      v13 = v24;
+      v14 = v26;
+      v21 += 48;
+      v15 = 1.0 / (*((float *)v7 + 5) + 0.0000001);
+      v20 += 48;
+      ++v22;
+      v28 += 48;
+      v27 += 48;
+      v25 += 48;
+      ++v24;
+      v26 += 48;
+      memcpy(v13, v7 + 8, 0x30u);
+      v16 = v23;
+      v23 += 48;
+      v4 = v20;
+      *(float *)v14 = v15;
+      *(int *)v16 = *((int *)v7 + 13);
+      v5 = v21;
+    }
+    v3 = v19;
+    v7 += 48;
+    --v18;
+  }
+  while ( v18 );
+  result = v22;
+  if ( v22 < 3 )
+    return 0;
+  return result;
+}
+
+//----- (004250FE) --------------------------------------------------------
+signed int __fastcall sr_4250FE(unsigned int uVertexID)
+{
+  unsigned int v1; // edx@1
+  char *v2; // edi@5
+  char *v3; // esi@5
+  char *v4; // ecx@5
+  int v5; // ebx@6
+  double v6; // st6@11
+  double v7; // st5@11
+  double v8; // st6@12
+  unsigned __int8 v9; // c2@16
+  unsigned __int8 v10; // c3@16
+  void *v11; // edi@23
+  double v12; // st6@23
+  char *v13; // ecx@23
+  char v14; // zf@24
+  signed int result; // eax@25
+  unsigned int v16; // [sp+8h] [bp-28h]@5
+  bool v17; // [sp+Ch] [bp-24h]@2
+  bool v18; // [sp+10h] [bp-20h]@7
+  char *v19; // [sp+14h] [bp-1Ch]@5
+  char *v20; // [sp+18h] [bp-18h]@5
+  signed int v21; // [sp+1Ch] [bp-14h]@1
+  RenderVertexSoft *v22; // [sp+20h] [bp-10h]@5
+  char *v23; // [sp+24h] [bp-Ch]@5
+  char *v24; // [sp+28h] [bp-8h]@5
+  char *v25; // [sp+2Ch] [bp-4h]@5
+
+  v1 = uVertexID;
+  memcpy(&array_50AC10[uVertexID], array_50AC10, sizeof(array_50AC10[uVertexID]));
+  v21 = 0;
+  v17 = array_50AC10[0].vWorldViewPosition.x >= 8.0;
+  if ( (signed int)(uVertexID + 1) <= 1 )
+    return 0;
+  v2 = (char *)&array_507D30[0].vWorldViewPosition.z;
+  v3 = (char *)&array_507D30[0].vWorldViewPosition.y;
+  v24 = (char *)&array_507D30[0].flt_20;
+  v22 = array_507D30;
+  v19 = (char *)&array_507D30[0].vWorldViewPosition.z;
+  v20 = (char *)&array_507D30[0].vWorldViewPosition.y;
+  v23 = (char *)&array_507D30[0].vWorldViewPosition;
+  v25 = (char *)&array_507D30[0].flt_2C;
+  v4 = (char *)&array_50AC10[0].vWorldViewPosition;
+  v16 = v1;
+  do
+  {
+    v5 = (int)(v4 + 48);
+    v18 = *((float *)v4 + 12) >= 8.0;
+    if ( v17 != v18 )
+    {
+      if ( v18 )
+      {
+        v6 = (8.0 - *(float *)v4) / (*(float *)v5 - *(float *)v4);
+        *(float *)v3 = (*((float *)v4 + 13) - *((float *)v4 + 1)) * v6 + *((float *)v4 + 1);
+        *(float *)v2 = (*((float *)v4 + 14) - *((float *)v4 + 2)) * v6 + *((float *)v4 + 2);
+        v7 = (*((float *)v4 + 20) - *((float *)v4 + 8)) * v6 + *((float *)v4 + 8);
+      }
+      else
+      {
+        v8 = (8.0 - *(float *)v5) / (*(float *)v4 - *(float *)v5);
+        *(float *)v3 = (*((float *)v4 + 1) - *((float *)v4 + 13)) * v8 + *((float *)v4 + 13);
+        *(float *)v2 = (*((float *)v4 + 2) - *((float *)v4 + 14)) * v8 + *((float *)v4 + 14);
+        v7 = (*((float *)v4 + 8) - *((float *)v4 + 20)) * v8 + *((float *)v4 + 20);
+      }
+      *(float *)v25 = v7;
+      *(float *)v23 = 8.0;
+      *(int *)v24 = 0x3E000000u;
+      if ( v17 )
+      {
+        if ( 8.0 == *(float *)v4 && *(float *)v3 == *((float *)v4 + 1) )
+        {
+          v9 = 0;
+          v10 = *(float *)v2 == *((float *)v4 + 2);
+          goto LABEL_20;
+        }
+      }
+      else
+      {
+        if ( 8.0 == *(float *)v5 && *(float *)v3 == *((float *)v4 + 13) )
+        {
+          v9 = 0;
+          v10 = *(float *)v2 == *((float *)v4 + 14);
+LABEL_20:
+          if ( v10 | v9 )
+            goto LABEL_22;
+          goto LABEL_21;
+        }
+      }
+LABEL_21:
+      ++v22;
+      v23 += 48;
+      v25 += 48;
+      v3 += 48;
+      v2 += 48;
+      ++v21;
+      v24 += 48;
+      v20 = v3;
+      v19 = v2;
+    }
+LABEL_22:
+    if ( v18 )
+    {
+      v11 = v22;
+      v20 += 48;
+      v19 += 48;
+      v12 = 1.0 / (*(float *)v5 + 0.0000001);
+      ++v21;
+      v25 += 48;
+      v23 += 48;
+      ++v22;
+      memcpy(v11, v4 + 36, 0x30u);
+      v13 = v24;
+      v24 += 48;
+      v3 = v20;
+      v2 = v19;
+      *(float *)v13 = v12;
+    }
+    v14 = v16-- == 1;
+    v17 = v18;
+    v4 = (char *)v5;
+  }
+  while ( !v14 );
+  result = v21;
+  if ( v21 < 3 )
+    return 0;
+  return result;
+}
+
+//----- (004252E8) --------------------------------------------------------
+signed int __fastcall sr_4252E8(unsigned int uVertexID)
+{
+  unsigned int v1; // edx@1
+  double v2; // st7@1
+  char *v3; // edi@5
+  char *v4; // esi@5
+  char *v5; // ecx@5
+  int v6; // ebx@6
+  double v7; // st6@11
+  double v8; // st5@11
+  double v9; // st6@12
+  unsigned __int8 v10; // c2@16
+  unsigned __int8 v11; // c3@16
+  void *v12; // edi@23
+  double v13; // st6@23
+  char *v14; // ecx@23
+  char v15; // zf@24
+  signed int result; // eax@25
+  unsigned int v17; // [sp+8h] [bp-28h]@5
+  bool v18; // [sp+Ch] [bp-24h]@2
+  bool v19; // [sp+10h] [bp-20h]@7
+  char *v20; // [sp+14h] [bp-1Ch]@5
+  char *v21; // [sp+18h] [bp-18h]@5
+  signed int v22; // [sp+1Ch] [bp-14h]@1
+  RenderVertexSoft *v23; // [sp+20h] [bp-10h]@5
+  char *v24; // [sp+24h] [bp-Ch]@5
+  char *v25; // [sp+28h] [bp-8h]@5
+  char *v26; // [sp+2Ch] [bp-4h]@5
+
+  v1 = uVertexID;
+  v2 = (double)pOutdoorCamera->shading_dist_mist;
+  memcpy(&array_50AC10[uVertexID], array_50AC10, sizeof(array_50AC10[uVertexID]));
+  v22 = 0;
+  v18 = array_50AC10[0].vWorldViewPosition.x <= v2;
+  if ( (signed int)(uVertexID + 1) <= 1 )
+    return 0;
+  v3 = (char *)&array_507D30[0].vWorldViewPosition.z;
+  v4 = (char *)&array_507D30[0].vWorldViewPosition.y;
+  v25 = (char *)&array_507D30[0].flt_20;
+  v23 = array_507D30;
+  v20 = (char *)&array_507D30[0].vWorldViewPosition.z;
+  v21 = (char *)&array_507D30[0].vWorldViewPosition.y;
+  v24 = (char *)&array_507D30[0].vWorldViewPosition;
+  v26 = (char *)&array_507D30[0].flt_2C;
+  v5 = (char *)&array_50AC10[0].vWorldViewPosition;
+  v17 = v1;
+  do
+  {
+    v6 = (int)(v5 + 48);
+    v19 = v2 >= *((float *)v5 + 12);
+    if ( v18 != v19 )
+    {
+      if ( v19 )
+      {
+        v7 = (v2 - *(float *)v5) / (*(float *)v6 - *(float *)v5);
+        *(float *)v4 = (*((float *)v5 + 13) - *((float *)v5 + 1)) * v7 + *((float *)v5 + 1);
+        *(float *)v3 = (*((float *)v5 + 14) - *((float *)v5 + 2)) * v7 + *((float *)v5 + 2);
+        v8 = (*((float *)v5 + 20) - *((float *)v5 + 8)) * v7 + *((float *)v5 + 8);
+      }
+      else
+      {
+        v9 = (v2 - *(float *)v6) / (*(float *)v5 - *(float *)v6);
+        *(float *)v4 = (*((float *)v5 + 1) - *((float *)v5 + 13)) * v9 + *((float *)v5 + 13);
+        *(float *)v3 = (*((float *)v5 + 2) - *((float *)v5 + 14)) * v9 + *((float *)v5 + 14);
+        v8 = (*((float *)v5 + 8) - *((float *)v5 + 20)) * v9 + *((float *)v5 + 20);
+      }
+      *(float *)v26 = v8;
+      *(float *)v24 = v2;
+      *(float *)v25 = 1.0 / v2;
+      if ( v18 )
+      {
+        if ( v2 == *(float *)v5 && *(float *)v4 == *((float *)v5 + 1) )
+        {
+          v10 = 0;
+          v11 = *(float *)v3 == *((float *)v5 + 2);
+          goto LABEL_20;
+        }
+      }
+      else
+      {
+        if ( v2 == *(float *)v6 && *(float *)v4 == *((float *)v5 + 13) )
+        {
+          v10 = 0;
+          v11 = *(float *)v3 == *((float *)v5 + 14);
+LABEL_20:
+          if ( v11 | v10 )
+            goto LABEL_22;
+          goto LABEL_21;
+        }
+      }
+LABEL_21:
+      ++v23;
+      v24 += 48;
+      v26 += 48;
+      v4 += 48;
+      v3 += 48;
+      ++v22;
+      v25 += 48;
+      v21 = v4;
+      v20 = v3;
+    }
+LABEL_22:
+    if ( v19 )
+    {
+      v12 = v23;
+      v21 += 48;
+      v20 += 48;
+      v13 = 1.0 / (*(float *)v6 + 0.0000001);
+      ++v22;
+      v26 += 48;
+      v24 += 48;
+      ++v23;
+      memcpy(v12, v5 + 36, 0x30u);
+      v14 = v25;
+      v25 += 48;
+      v4 = v21;
+      v3 = v20;
+      *(float *)v14 = v13;
+    }
+    v15 = v17-- == 1;
+    v18 = v19;
+    v5 = (char *)v6;
+  }
+  while ( !v15 );
+  result = v22;
+  if ( v22 < 3 )
+    return 0;
+  return result;
+}
+
+
+
+//----- (004361EF) --------------------------------------------------------
+IndoorCameraD3D::IndoorCameraD3D()
+{
+  IndoorCameraD3D *v1; // esi@1
+  double v2; // st7@1
+  double v3; // st6@1
+  double v4; // st5@1
+  double v5; // st7@1
+  double v6; // st6@1
+  double v7; // st5@1
+
+  v1 = this;
+  //IndoorCameraD3D_Vec3::IndoorCameraD3D_Vec3(&this->field_4);
+  //IndoorCameraD3D_Vec3::IndoorCameraD3D_Vec3(&v1->field_14);
+  //IndoorCameraD3D_Vec3::IndoorCameraD3D_Vec3(&v1->field_24);
+  /*_eh_vector_constructor_iterator_(v1->std__vector_000034_prolly_frustrum,
+    24,
+    6,
+    (void (__thiscall *)(void *))IndoorCameraD3D_Vec4::IndoorCameraD3D_Vec4,
+    (void (__thiscall *)(void *))IndoorCameraD3D_Vec4::dtor);*/
+  v2 = 0;//(double)pBLVRenderParams->vPartyPos.z;
+  v3 = 0;//(double)pBLVRenderParams->vPartyPos.y;
+  v4 = 0;//(double)pBLVRenderParams->vPartyPos.x;
+  v1->field_108 = 0.0;
+  v1->field_DC = v4;
+  v1->field_E0 = v3;
+  v1->field_E4 = v2;
+  v5 = 0;//(double)pBLVRenderParams->vPartyPos.z;
+  v6 = 0;//(double)pBLVRenderParams->vPartyPos.y;
+  v7 = 300;//(double)(pBLVRenderParams->vPartyPos.x + 300);
+  v1->field_138 = 0.0;
+  v1->field_10C = v7;
+  v1->field_110 = v6;
+  v1->field_114 = v5;
+  v1->field_168 = 0.0;
+  v1->field_198 = 0.0;
+  v1->field_1C8 = 0.0;
+  v1->field_1F8 = 0.0;
+  v1->field_228 = 0.0;
+  v1->field_258 = 0.0;
+  v1->field_288 = 0.0;
+  v1->field_2B8 = 0.0;
+  v1->field_2E8 = 0.0;
+  v1->field_2BC = 0.0;
+  v1->field_2C0 = 0.0;
+  v1->field_2C4 = 0.0;
+  v1->field_318 = 0.0;
+  v1->field_2EC = 0.0;
+  v1->field_2F0 = 0.0;
+  v1->field_2F4 = 0.0;
+  v1->field_348 = 0.0;
+  v1->field_31C = 0.0;
+  v1->field_320 = 0.0;
+  v1->field_324 = 0.0;
+  v1->field_378 = 0.0;
+  v1->field_34C = 0.0;
+  v1->field_350 = 0.0;
+  v1->field_354 = 0.0;
+  for (uint i = 0; i < 16384; ++i)
+  {
+    list_0037C[i].field_0 = 0;
+    list_0037C[i].flt_30 = 0.0f;
+  }
+
+  list_0037C_size = 0;
+  for (uint i = 0; i < 256; ++i)
+    list_E0380[i].mm7__vector_000004_size = 0;
+  /*v10 = v1->list_E0380;
+  v12 = 256;
+  do
+  {
+    v10->mm7__vector_000004_size = 0;
+    //mm7__vector_constructor(
+    //  v10->mm7__vector_000004,
+    //  48,
+    //  64,
+    //  (int (__thiscall *)(int))IndoorCameraD3D_stru1::IndoorCameraD3D_stru1);
+    //++v10;
+    --v12;
+  }
+  while ( v12 );*/
+  list_E0380_size = 0;
+  //v1->vdestructor_ptr = &stru8_pvdtor;
+}
+
+
+//----- (004254D2) --------------------------------------------------------
+int __fastcall sr_4254D2(signed int a1)
+{
+  signed int v1; // ebx@2
+  int v2; // ecx@2
+  int result; // eax@11
+  double v4; // ST74_8@12
+  bool v5; // edi@12
+  char *v6; // esi@13
+  char *v7; // ebx@13
+  double v8; // st7@15
+  double v9; // st7@16
+  double v10; // st6@16
+  double v11; // st7@17
+  float v12; // eax@18
+  double v13; // ST4C_8@19
+  double v14; // ST10_8@19
+  double v15; // ST28_8@20
+  double v16; // ST34_8@20
+  char v17; // zf@20
+  double v18; // ST18_8@21
+  double v19; // ST3C_8@21
+  double v20; // ST44_8@22
+  double v21; // ST54_8@22
+  void *v22; // edi@26
+  double v23; // ST54_8@29
+  bool v24; // esi@29
+  char *v25; // edi@30
+  char *v26; // ebx@30
+  bool v27; // ecx@32
+  double v28; // st7@33
+  double v29; // st7@34
+  double v30; // st6@34
+  double v31; // st7@35
+  double v32; // ST44_8@37
+  double v33; // ST3C_8@37
+  double v34; // ST18_8@38
+  double v35; // ST34_8@38
+  char v36; // zf@38
+  double v37; // ST28_8@39
+  double v38; // ST10_8@39
+  double v39; // ST20_8@40
+  double v40; // ST5C_8@40
+  void *v41; // edi@44
+  double v42; // ST5C_8@47
+  bool v43; // edi@47
+  char *v44; // esi@48
+  char *v45; // ebx@48
+  bool v46; // ecx@49
+  double v47; // st6@50
+  double v48; // st6@51
+  double v49; // st5@51
+  double v50; // st6@52
+  double v51; // ST20_8@54
+  double v52; // ST54_8@54
+  double v53; // ST44_8@55
+  double v54; // ST3C_8@55
+  char v55; // zf@55
+  double v56; // ST18_8@56
+  double v57; // ST34_8@56
+  double v58; // ST28_8@57
+  double v59; // ST10_8@57
+  void *v60; // edi@61
+  double v61; // ST5C_8@64
+  bool v62; // edi@64
+  char *v63; // esi@65
+  char *v64; // ebx@65
+  bool v65; // ecx@66
+  double v66; // st6@67
+  double v67; // st6@68
+  double v68; // st5@68
+  double v69; // st6@69
+  double v70; // ST20_8@71
+  double v71; // ST54_8@71
+  double v72; // ST44_8@72
+  double v73; // ST3C_8@72
+  char v74; // zf@72
+  double v75; // ST18_8@73
+  double v76; // ST34_8@73
+  double v77; // ST28_8@74
+  double v78; // ST10_8@74
+  void *v79; // edi@78
+  int v80; // ebx@81
+  char *v81; // ecx@82
+  signed int v82; // esi@82
+  float v83; // ST78_4@83
+  double v84; // ST5C_8@83
+  float v85; // eax@84
+  double v86; // ST20_8@85
+  double v87; // ST54_8@88
+  float v88; // eax@89
+  double v89; // ST44_8@90
+  unsigned __int8 v90; // sf@94
+  unsigned __int8 v91; // of@94
+  int v92; // edx@97
+  int v93; // esi@97
+  int v94; // edi@97
+  int v95; // eax@97
+  int v96; // eax@104
+  double v97; // [sp+4Ch] [bp-8Ch]@32
+  double v98; // [sp+54h] [bp-84h]@49
+  double v99; // [sp+54h] [bp-84h]@66
+  float v100; // [sp+5Ch] [bp-7Ch]@1
+  float v101; // [sp+60h] [bp-78h]@1
+  float v102; // [sp+64h] [bp-74h]@1
+  double v103; // [sp+6Ch] [bp-6Ch]@14
+  float v104; // [sp+A8h] [bp-30h]@1
+  signed int v105; // [sp+A8h] [bp-30h]@96
+  bool v106; // [sp+ACh] [bp-2Ch]@14
+  bool v107; // [sp+ACh] [bp-2Ch]@32
+  bool v108; // [sp+ACh] [bp-2Ch]@49
+  bool v109; // [sp+ACh] [bp-2Ch]@66
+  signed int v110; // [sp+B0h] [bp-28h]@12
+  char *v111; // [sp+B8h] [bp-20h]@30
+  signed int v112; // [sp+B8h] [bp-20h]@48
+  signed int v113; // [sp+B8h] [bp-20h]@65
+  char *v114; // [sp+BCh] [bp-1Ch]@13
+  signed int v115; // [sp+BCh] [bp-1Ch]@29
+  signed int v116; // [sp+BCh] [bp-1Ch]@64
+  signed int v117; // [sp+C0h] [bp-18h]@1
+  char *v118; // [sp+C0h] [bp-18h]@30
+  char *v119; // [sp+C0h] [bp-18h]@48
+  char *v120; // [sp+C0h] [bp-18h]@65
+  char *v121; // [sp+C4h] [bp-14h]@13
+  char *v122; // [sp+C4h] [bp-14h]@30
+  signed int v123; // [sp+C4h] [bp-14h]@47
+  char *v124; // [sp+C8h] [bp-10h]@30
+  char *v125; // [sp+C8h] [bp-10h]@48
+  char *v126; // [sp+C8h] [bp-10h]@65
+  signed int v127; // [sp+CCh] [bp-Ch]@2
+  char *v128; // [sp+CCh] [bp-Ch]@13
+  char *v129; // [sp+CCh] [bp-Ch]@30
+  RenderVertexSoft *v130; // [sp+CCh] [bp-Ch]@48
+  RenderVertexSoft *v131; // [sp+CCh] [bp-Ch]@65
+  RenderVertexSoft *v132; // [sp+D0h] [bp-8h]@13
+  char *v133; // [sp+D0h] [bp-8h]@30
+  char *v134; // [sp+D0h] [bp-8h]@48
+  char *v135; // [sp+D0h] [bp-8h]@65
+  signed int v136; // [sp+D4h] [bp-4h]@1
+  char *v137; // [sp+D4h] [bp-4h]@13
+  RenderVertexSoft *v138; // [sp+D4h] [bp-4h]@30
+  char *v139; // [sp+D4h] [bp-4h]@48
+  char *v140; // [sp+D4h] [bp-4h]@65
+
+  v101 = (double)(signed int)pViewport->uViewportX;
+  v100 = (double)(signed int)pViewport->uViewportZ;
+  v117 = a1;
+  v136 = 1;
+  v104 = (double)(signed int)pViewport->uViewportY;
+  v102 = (double)(pViewport->uViewportW + 1);
+  if ( a1 <= 0 )
+    return v117;
+  v127 = a1;
+  v1 = a1;
+  memcpy(array_508690, array_50AC10, 4 * ((unsigned int)(48 * a1) >> 2));
+  v2 = 0;
+  do
+  {
+    if ( array_50AC10[v2].vWorldViewProjX < (double)v101 || array_50AC10[v2].vWorldViewProjX > (double)v100 )
+      v136 = 0;
+    if ( *(float *)(v2 * 48 + 5286956) < (double)v104 || *(float *)(v2 * 48 + 5286956) > (double)v102 )
+      v136 = 0;
+    ++v2;
+    --v127;
+  }
+  while ( v127 );
+  if ( v136 )
+    return v117;
+  v110 = 0;
+  memcpy(&array_50AC10[v1], array_50AC10, sizeof(array_50AC10[v1]));
+  v4 = array_50AC10[0].vWorldViewProjX + 6.7553994e15;
+  v5 = SLODWORD(v4) >= (signed int)pViewport->uViewportX;
+  if ( v117 < 1 )
+    goto LABEL_112;
+  v6 = (char *)&array_50A2B0[0].vWorldViewProjY;
+  v132 = array_50A2B0;
+  v137 = (char *)&array_50A2B0[0].vWorldViewProjX;
+  v128 = (char *)&array_50A2B0[0].vWorldViewProjY;
+  v121 = (char *)&array_50A2B0[0].flt_2C;
+  v114 = (char *)&array_50A2B0[0].flt_20;
+  v7 = (char *)&array_50AC10[0].flt_2C;
+  do
+  {
+    v103 = *((float *)v7 + 7) + 6.7553994e15;
+    v106 = SLODWORD(v103) >= (signed int)pViewport->uViewportX;
+    if ( !(v5 ^ v106) )
+      goto LABEL_25;
+    v8 = v101;
+    if ( SLODWORD(v103) >= (signed int)pViewport->uViewportX )
+    {
+      v9 = (v8 - *((float *)v7 - 5)) / (*((float *)v7 + 7) - *((float *)v7 - 5));
+      *(float *)v6 = (*((float *)v7 + 8) - *((float *)v7 - 4)) * v9 + *((float *)v7 - 4);
+      *(float *)v114 = (*((float *)v7 + 9) - *((float *)v7 - 3)) * v9 + *((float *)v7 - 3);
+      v10 = (*((float *)v7 + 12) - *(float *)v7) * v9 + *(float *)v7;
+    }
+    else
+    {
+      v11 = (v8 - *((float *)v7 + 7)) / (*((float *)v7 - 5) - *((float *)v7 + 7));
+      *(float *)v6 = (*((float *)v7 - 4) - *((float *)v7 + 8)) * v11 + *((float *)v7 + 8);
+      *(float *)v114 = (*((float *)v7 - 3) - *((float *)v7 + 9)) * v11 + *((float *)v7 + 9);
+      v10 = (*(float *)v7 - *((float *)v7 + 12)) * v11 + *((float *)v7 + 12);
+    }
+    *(float *)v121 = v10;
+    *(int *)v137 = LODWORD(v101);
+    LODWORD(v12) = *(int *)v6;
+    if ( v5 )
+    {
+      v13 = v12 + 6.7553994e15;
+      v14 = *((float *)v7 - 4) + 6.7553994e15;
+      if ( LODWORD(v13) == LODWORD(v14) )
+      {
+        v15 = *(float *)v137 + 6.7553994e15;
+        v16 = *((float *)v7 - 5) + 6.7553994e15;
+        v17 = LODWORD(v15) == LODWORD(v16);
+        goto LABEL_23;
+      }
+    }
+    else
+    {
+      v18 = v12 + 6.7553994e15;
+      v19 = *((float *)v7 + 8) + 6.7553994e15;
+      if ( LODWORD(v18) == LODWORD(v19) )
+      {
+        v20 = *(float *)v137 + 6.7553994e15;
+        v21 = *((float *)v7 + 7) + 6.7553994e15;
+        v17 = LODWORD(v20) == LODWORD(v21);
+LABEL_23:
+        if ( v17 )
+          goto LABEL_25;
+        goto LABEL_24;
+      }
+    }
+LABEL_24:
+    v121 += 48;
+    v114 += 48;
+    v6 += 48;
+    ++v110;
+    ++v132;
+    v128 = v6;
+    v137 += 48;
+LABEL_25:
+    if ( v106 )
+    {
+      v22 = v132;
+      v128 += 48;
+      ++v110;
+      v114 += 48;
+      v121 += 48;
+      v137 += 48;
+      ++v132;
+      memcpy(v22, v7 + 4, 0x30u);
+      v6 = v128;
+    }
+    v5 = v106;
+    v7 += 48;
+    --v117;
+  }
+  while ( v117 );
+  if ( v110 < 3
+    || (v115 = 0,
+        memcpy(&array_50A2B0[v110], array_50A2B0, sizeof(array_50A2B0[v110])),
+        v23 = array_50A2B0[0].vWorldViewProjX + 6.7553994e15,
+        v24 = SLODWORD(v23) <= (signed int)pViewport->uViewportZ,
+        v110 < 1) )
+    goto LABEL_112;
+  v25 = (char *)&array_509950[0].flt_20;
+  v138 = array_509950;
+  v129 = (char *)&array_50A2B0[0].vWorldViewProjX;
+  v118 = (char *)&array_50A2B0[0].vWorldViewProjY;
+  v133 = (char *)&array_509950[0].vWorldViewProjX;
+  v122 = (char *)&array_509950[0].vWorldViewProjY;
+  v124 = (char *)&array_509950[0].flt_2C;
+  v111 = (char *)&array_509950[0].flt_20;
+  v26 = (char *)&array_50A2B0[0].flt_2C;
+  while ( 2 )
+  {
+    v97 = *((float *)v26 + 7) + 6.7553994e15;
+    v27 = SLODWORD(v97) <= (signed int)pViewport->uViewportZ;
+    v107 = SLODWORD(v97) <= (signed int)pViewport->uViewportZ;
+    if ( v24 != v27 )
+    {
+      v28 = v100;
+      if ( SLODWORD(v97) <= (signed int)pViewport->uViewportZ )
+      {
+        v29 = (v28 - *((float *)v26 - 5)) / (*((float *)v26 + 7) - *((float *)v26 - 5));
+        *(float *)v122 = (*((float *)v26 + 8) - *((float *)v26 - 4)) * v29 + *((float *)v26 - 4);
+        *(float *)v25 = (*((float *)v26 + 9) - *((float *)v26 - 3)) * v29 + *((float *)v26 - 3);
+        v30 = (*((float *)v26 + 12) - *(float *)v26) * v29 + *(float *)v26;
+      }
+      else
+      {
+        v31 = (v28 - *((float *)v26 + 7)) / (*((float *)v26 - 5) - *((float *)v26 + 7));
+        *(float *)v122 = (*((float *)v26 - 4) - *((float *)v26 + 8)) * v31 + *((float *)v26 + 8);
+        *(float *)v25 = (*((float *)v26 - 3) - *((float *)v26 + 9)) * v31 + *((float *)v26 + 9);
+        v30 = (*(float *)v26 - *((float *)v26 + 12)) * v31 + *((float *)v26 + 12);
+      }
+      *(float *)v124 = v30;
+      *(int *)v133 = LODWORD(v100);
+      if ( v24 )
+      {
+        v32 = *(float *)v122 + 6.7553994e15;
+        v33 = *((float *)v26 - 4) + 6.7553994e15;
+        if ( LODWORD(v32) == LODWORD(v33) )
+        {
+          v34 = *(float *)v133 + 6.7553994e15;
+          v35 = *((float *)v26 - 5) + 6.7553994e15;
+          v36 = LODWORD(v34) == LODWORD(v35);
+          goto LABEL_41;
+        }
+        goto LABEL_42;
+      }
+      v37 = *(float *)v118 + 6.7553994e15;
+      v38 = *((float *)v26 + 8) + 6.7553994e15;
+      if ( LODWORD(v37) != LODWORD(v38) )
+        goto LABEL_42;
+      v39 = *(float *)v129 + 6.7553994e15;
+      v40 = *((float *)v26 + 7) + 6.7553994e15;
+      v36 = LODWORD(v39) == LODWORD(v40);
+LABEL_41:
+      if ( !v36 )
+      {
+LABEL_42:
+        v129 += 48;
+        v118 += 48;
+        v133 += 48;
+        v122 += 48;
+        v124 += 48;
+        v111 += 48;
+        ++v115;
+        ++v138;
+      }
+    }
+    if ( v27 )
+    {
+      v41 = v138;
+      ++v115;
+      v111 += 48;
+      v124 += 48;
+      v122 += 48;
+      v133 += 48;
+      v118 += 48;
+      v129 += 48;
+      ++v138;
+      memcpy(v41, v26 + 4, 0x30u);
+    }
+    v24 = v107;
+    v26 += 48;
+    --v110;
+    if ( v110 )
+    {
+      v25 = v111;
+      continue;
+    }
+    break;
+  }
+  if ( v115 < 3
+    || (v123 = 0,
+        memcpy(&array_509950[v115], array_509950, sizeof(array_509950[v115])),
+        v42 = array_509950[0].vWorldViewProjY + 6.7553994e15,
+        v43 = SLODWORD(v42) >= (signed int)pViewport->uViewportY,
+        v115 < 1) )
+    goto LABEL_112;
+  v44 = (char *)&array_508FF0[0].vWorldViewProjX;
+  v130 = array_508FF0;
+  v119 = (char *)&array_508FF0[0].vWorldViewProjX;
+  v139 = (char *)&array_508FF0[0].vWorldViewProjY;
+  v125 = (char *)&array_508FF0[0].flt_2C;
+  v134 = (char *)&array_508FF0[0].flt_20;
+  v45 = (char *)&array_509950[0].flt_2C;
+  v112 = v115;
+  while ( 2 )
+  {
+    v98 = *((float *)v45 + 8) + 6.7553994e15;
+    v46 = SLODWORD(v98) >= (signed int)pViewport->uViewportY;
+    v108 = SLODWORD(v98) >= (signed int)pViewport->uViewportY;
+    if ( v43 != v46 )
+    {
+      v47 = v104;
+      if ( SLODWORD(v98) >= (signed int)pViewport->uViewportY )
+      {
+        v48 = (v47 - *((float *)v45 - 4)) / (*((float *)v45 + 8) - *((float *)v45 - 4));
+        *(float *)v44 = (*((float *)v45 + 7) - *((float *)v45 - 5)) * v48 + *((float *)v45 - 5);
+        *(float *)v134 = (*((float *)v45 + 9) - *((float *)v45 - 3)) * v48 + *((float *)v45 - 3);
+        v49 = (*((float *)v45 + 12) - *(float *)v45) * v48 + *(float *)v45;
+      }
+      else
+      {
+        v50 = (v47 - *((float *)v45 + 8)) / (*((float *)v45 - 4) - *((float *)v45 + 8));
+        *(float *)v44 = (*((float *)v45 - 5) - *((float *)v45 + 7)) * v50 + *((float *)v45 + 7);
+        *(float *)v134 = (*((float *)v45 - 3) - *((float *)v45 + 9)) * v50 + *((float *)v45 + 9);
+        v49 = (*(float *)v45 - *((float *)v45 + 12)) * v50 + *((float *)v45 + 12);
+      }
+      *(float *)v125 = v49;
+      *(float *)v139 = v104;
+      if ( v43 )
+      {
+        v51 = v104 + 6.7553994e15;
+        v52 = *((float *)v45 - 4) + 6.7553994e15;
+        if ( LODWORD(v51) == LODWORD(v52) )
+        {
+          v53 = *(float *)v44 + 6.7553994e15;
+          v54 = *((float *)v45 - 5) + 6.7553994e15;
+          v55 = LODWORD(v53) == LODWORD(v54);
+          goto LABEL_58;
+        }
+        goto LABEL_59;
+      }
+      v56 = v104 + 6.7553994e15;
+      v57 = *((float *)v45 + 8) + 6.7553994e15;
+      if ( LODWORD(v56) != LODWORD(v57) )
+        goto LABEL_59;
+      v58 = *(float *)v44 + 6.7553994e15;
+      v59 = *((float *)v45 + 7) + 6.7553994e15;
+      v55 = LODWORD(v58) == LODWORD(v59);
+LABEL_58:
+      if ( !v55 )
+      {
+LABEL_59:
+        v139 += 48;
+        v125 += 48;
+        v134 += 48;
+        v44 += 48;
+        ++v123;
+        ++v130;
+        v119 = v44;
+      }
+    }
+    if ( v46 )
+    {
+      v60 = v130;
+      v119 += 48;
+      ++v123;
+      v134 += 48;
+      v125 += 48;
+      v139 += 48;
+      ++v130;
+      memcpy(v60, v45 + 4, 0x30u);
+      v44 = v119;
+    }
+    v43 = v108;
+    v45 += 48;
+    --v112;
+    if ( v112 )
+      continue;
+    break;
+  }
+  if ( v123 < 3
+    || (v116 = 0,
+        memcpy(&array_508FF0[v123], array_508FF0, sizeof(array_508FF0[v123])),
+        v61 = array_508FF0[0].vWorldViewProjY + 6.7553994e15,
+        v62 = SLODWORD(v61) <= (signed int)pViewport->uViewportW,
+        v123 < 1) )
+    goto LABEL_112;
+  v63 = (char *)&array_508690[0].vWorldViewProjX;
+  v131 = array_508690;
+  v120 = (char *)&array_508690[0].vWorldViewProjX;
+  v140 = (char *)&array_508690[0].vWorldViewProjY;
+  v126 = (char *)&array_508690[0].flt_2C;
+  v135 = (char *)&array_508690[0].flt_20;
+  v64 = (char *)&array_508FF0[0].flt_2C;
+  v113 = v123;
+  while ( 2 )
+  {
+    v99 = *((float *)v64 + 8) + 6.7553994e15;
+    v65 = SLODWORD(v99) <= (signed int)pViewport->uViewportW;
+    v109 = SLODWORD(v99) <= (signed int)pViewport->uViewportW;
+    if ( v62 != v65 )
+    {
+      v66 = v102;
+      if ( SLODWORD(v99) <= (signed int)pViewport->uViewportW )
+      {
+        v67 = (v66 - *((float *)v64 - 4)) / (*((float *)v64 + 8) - *((float *)v64 - 4));
+        *(float *)v63 = (*((float *)v64 + 7) - *((float *)v64 - 5)) * v67 + *((float *)v64 - 5);
+        *(float *)v135 = (*((float *)v64 + 9) - *((float *)v64 - 3)) * v67 + *((float *)v64 - 3);
+        v68 = (*((float *)v64 + 12) - *(float *)v64) * v67 + *(float *)v64;
+      }
+      else
+      {
+        v69 = (v66 - *((float *)v64 + 8)) / (*((float *)v64 - 4) - *((float *)v64 + 8));
+        *(float *)v63 = (*((float *)v64 - 5) - *((float *)v64 + 7)) * v69 + *((float *)v64 + 7);
+        *(float *)v135 = (*((float *)v64 - 3) - *((float *)v64 + 9)) * v69 + *((float *)v64 + 9);
+        v68 = (*(float *)v64 - *((float *)v64 + 12)) * v69 + *((float *)v64 + 12);
+      }
+      *(float *)v126 = v68;
+      *(float *)v140 = v102;
+      if ( v62 )
+      {
+        v70 = v102 + 6.7553994e15;
+        v71 = *((float *)v64 - 4) + 6.7553994e15;
+        if ( LODWORD(v70) == LODWORD(v71) )
+        {
+          v72 = *(float *)v63 + 6.7553994e15;
+          v73 = *((float *)v64 - 5) + 6.7553994e15;
+          v74 = LODWORD(v72) == LODWORD(v73);
+          goto LABEL_75;
+        }
+        goto LABEL_76;
+      }
+      v75 = v102 + 6.7553994e15;
+      v76 = *((float *)v64 + 8) + 6.7553994e15;
+      if ( LODWORD(v75) != LODWORD(v76) )
+        goto LABEL_76;
+      v77 = *(float *)v63 + 6.7553994e15;
+      v78 = *((float *)v64 + 7) + 6.7553994e15;
+      v74 = LODWORD(v77) == LODWORD(v78);
+LABEL_75:
+      if ( !v74 )
+      {
+LABEL_76:
+        v140 += 48;
+        v126 += 48;
+        v135 += 48;
+        v63 += 48;
+        ++v116;
+        ++v131;
+        v120 = v63;
+      }
+    }
+    if ( v65 )
+    {
+      v79 = v131;
+      v120 += 48;
+      ++v116;
+      v135 += 48;
+      v126 += 48;
+      v140 += 48;
+      ++v131;
+      memcpy(v79, v64 + 4, 0x30u);
+      v63 = v120;
+    }
+    v62 = v109;
+    v64 += 48;
+    --v113;
+    if ( v113 )
+      continue;
+    break;
+  }
+  if ( v116 < 3 )
+    goto LABEL_112;
+  v80 = v116;
+  memcpy(&array_508690[v116], array_508690, sizeof(array_508690[v116]));
+  if ( v116 > 0 )
+  {
+    v81 = (char *)&array_508690[0].vWorldViewProjX;
+    v82 = v116;
+    do
+    {
+      LODWORD(v83) = *(int *)v81;
+      *((float *)v81 - 3) = 1.0 / *((float *)v81 + 2);
+      v84 = v83 + 6.7553994e15;
+      if ( SLODWORD(v84) <= (signed int)pViewport->uViewportZ )
+      {
+        v86 = *(float *)v81 + 6.7553994e15;
+        if ( SLODWORD(v86) >= (signed int)pViewport->uViewportX )
+          goto LABEL_88;
+        v85 = v101;
+      }
+      else
+      {
+        v85 = v100;
+      }
+      *(int *)v81 = LODWORD(v85);
+LABEL_88:
+      v87 = *((float *)v81 + 1) + 6.7553994e15;
+      if ( SLODWORD(v87) > (signed int)pViewport->uViewportW )
+      {
+        v88 = v102;
+LABEL_92:
+        *((int *)v81 + 1) = LODWORD(v88);
+        goto LABEL_93;
+      }
+      v89 = *((float *)v81 + 1) + 6.7553994e15;
+      if ( SLODWORD(v89) < (signed int)pViewport->uViewportY )
+      {
+        v88 = v104;
+        goto LABEL_92;
+      }
+LABEL_93:
+      v81 += 48;
+      --v82;
+    }
+    while ( v82 );
+  }
+  v91 = __OFSUB__(v116, 3);
+  v90 = v116 - 3 < 0;
+  if ( v116 > 3 )
+  {
+    memcpy(&array_508690[v116 + 1], &array_508690[1], sizeof(array_508690[v116 + 1]));
+    if ( v116 > 0 )
+    {
+      v105 = 1;
+      do
+      {
+        v92 = v105;
+        v93 = v105 - 1;
+        v94 = v105 + 1;
+        v95 = v105 + 1;
+        if ( v105 - 1 >= v80 )
+          v93 -= v80;
+        if ( v105 >= v80 )
+          v92 = v105 - v80;
+        if ( v94 >= v80 )
+          v95 = v94 - v80;
+        if ( (array_508690[v92].vWorldViewProjX - array_508690[v93].vWorldViewProjX)
+           * (array_508690[v95].vWorldViewProjY - array_508690[v93].vWorldViewProjY)
+           - (array_508690[v95].vWorldViewProjX - array_508690[v93].vWorldViewProjX)
+           * (array_508690[v92].vWorldViewProjY - array_508690[v93].vWorldViewProjY) < 0.0 )
+        {
+          ++v105;
+        }
+        else
+        {
+          v96 = v105;
+          if ( v105 < v80 || (v96 = v105 - v80, v105 - v80 < v80) )
+            memcpy(&array_508690[v96], &array_508690[v96 + 1], 4 * ((unsigned int)(48 * v80 - 48 * v96) >> 2));
+          --v80;
+        }
+      }
+      while ( v105 - 1 < v80 );
+    }
+    v91 = __OFSUB__(v80, 3);
+    v90 = v80 - 3 < 0;
+  }
+  if ( v90 ^ v91 )
+LABEL_112:
+    result = 0;
+  else
+    result = v80;
+  return result;
+}
+
+//----- (0042620A) --------------------------------------------------------
+bool __thiscall sr_42620A(RenderVertexSoft *p)
+{
+  __int16 v1; // fps@1
+  unsigned __int8 v2; // c0@2
+  char v3; // c2@2
+  unsigned __int8 v4; // c3@2
+  bool result; // eax@2
+  unsigned __int8 v6; // c0@4
+  char v7; // c2@4
+  unsigned __int8 v8; // c3@4
+  unsigned __int8 v9; // c0@6
+  char v10; // c2@6
+  unsigned __int8 v11; // c3@6
+  double v12; // st6@7
+  float v13; // ST04_4@7
+  float v14; // ST00_4@7
+  double v15; // st7@7
+  double v16; // st6@8
+  float v17; // ST04_4@8
+  float v18; // ST00_4@8
+  double v19; // st7@8
+
+  //UNDEF(v1);
+  if ( p->vWorldViewPosition.x < 300.0
+    || (v2 = 300.0 < p[1].vWorldViewPosition.x,
+        v3 = 0,
+        v4 = 300.0 == p[1].vWorldViewPosition.x,
+        BYTE1(result) = HIBYTE(v1),
+        !(v2 | v4)) )
+  {
+    if ( p->vWorldViewPosition.x < 300.0 )
+    {
+      v6 = 300.0 < p[1].vWorldViewPosition.x;
+      v7 = 0;
+      v8 = 300.0 == p[1].vWorldViewPosition.x;
+      BYTE1(result) = HIBYTE(v1);
+      if ( !(v6 | v8) )
+      {
+        LOBYTE(result) = 0;
+        return result;
+      }
+    }
+    v9 = 300.0 < p->vWorldViewPosition.x;
+    v10 = 0;
+    v11 = 300.0 == p->vWorldViewPosition.x;
+    BYTE1(result) = HIBYTE(v1);
+    if ( v9 | v11 )
+    {
+      v16 = 1.0 / (p->vWorldViewPosition.x - p[1].vWorldViewPosition.x);
+      v17 = (p->vWorldViewPosition.y - p[1].vWorldViewPosition.y) * v16;
+      v18 = (p->vWorldViewPosition.z - p[1].vWorldViewPosition.z) * v16;
+      v19 = 300.0 - p[1].vWorldViewPosition.x;
+      p[1].vWorldViewPosition.x = v19 + p[1].vWorldViewPosition.x;
+      p[1].vWorldViewPosition.y = v17 * v19 + p[1].vWorldViewPosition.y;
+      p[1].vWorldViewPosition.z = v19 * v18 + p[1].vWorldViewPosition.z;
+    }
+    else
+    {
+      v12 = 1.0 / (p[1].vWorldViewPosition.x - p->vWorldViewPosition.x);
+      v13 = (p[1].vWorldViewPosition.y - p->vWorldViewPosition.y) * v12;
+      v14 = (p[1].vWorldViewPosition.z - p->vWorldViewPosition.z) * v12;
+      v15 = 300.0 - p->vWorldViewPosition.x;
+      p->vWorldViewPosition.x = v15 + p->vWorldViewPosition.x;
+      p->vWorldViewPosition.y = v13 * v15 + p->vWorldViewPosition.y;
+      p->vWorldViewPosition.z = v15 * v14 + p->vWorldViewPosition.z;
+    }
+  }
+  LOBYTE(result) = 1;
+  return result;
+}
+
+
+
+
+//----- (004268E3) --------------------------------------------------------
+int __fastcall _4268E3_smthn_to_a1r5g5b5(unsigned int uColor)
+{
+  unsigned int v1; // eax@1
+  unsigned int v2; // edx@1
+  int v3; // eax@1
+  int v4; // edx@1
+  unsigned int v5; // ecx@1
+
+  v1 = uColor >> 9;
+  v2 = uColor >> 6;
+  LOWORD(v1) = (uColor >> 9) & 0x7C00;
+  LOWORD(v2) = (uColor >> 6) & 0x3E0;
+  v3 = v2 | v1;
+  v4 = (unsigned __int8)uColor >> 3;
+  v5 = uColor >> 16;
+  LOWORD(v5) = v5 & 0x8000;
+  return v5 | v4 | v3;
+}
+
+//----- (0042690D) --------------------------------------------------------
+int __fastcall _42690D_colors_cvt(unsigned int a1)
+{
+  unsigned int v1; // eax@1
+  unsigned int v2; // edx@1
+
+  v1 = a1 >> 8;
+  v2 = a1 >> 5;
+  LOWORD(v1) = (a1 >> 8) & 0xF800;
+  LOWORD(v2) = (a1 >> 5) & 0x7E0;
+  return ((unsigned __int8)a1 >> 3) | v2 | v1;
+}
+
+//----- (00426947) --------------------------------------------------------
+void __cdecl sub_426947()
+{
+  dword_50C968 = 0;
+  dword_50C994 = 0;
+  dword_50C998_turnbased_icon_1A = 0;
+}
+// 50C968: using guessed type int dword_50C968;
+// 50C994: using guessed type int dword_50C994;
+// 50C998: using guessed type int dword_50C998_turnbased_icon_1A;
+
+
+
+//----- (004269A2) --------------------------------------------------------
+int __fastcall sub_4269A2_GivePartyExp(unsigned int a1)
+{
+  unsigned __int64 v1; // qax@1
+  signed int v2; // ecx@1
+  char *v3; // esi@1
+  bool v4; // edi@6
+  char *v5; // edi@10
+  char *v6; // esi@10
+  int v7; // eax@13
+  unsigned __int8 v8; // cf@13
+  char v10; // [sp+Ch] [bp-14h]@1
+  int v11; // [sp+1Ch] [bp-4h]@10
+
+  v1 = __PAIR__((int)((char *)&pParty + 2620), a1);
+  v2 = 0;
+  v3 = &v10;
+  do
+  {
+    v4 = !(*(int *)(HIDWORD(v1) - 4) | *(int *)(HIDWORD(v1) - 8))
+      && !*(int *)HIDWORD(v1)
+      && !*(_QWORD *)(HIDWORD(v1) + 8)
+      && !*(_QWORD *)(HIDWORD(v1) + 16);
+    *(int *)v3 = v4;
+    HIDWORD(v1) += 6972;
+    v2 += v4;
+    v3 += 4;
+  }
+  while ( SHIDWORD(v1) < (signed int)&pParty->pHirelings[1].field_24 );
+  if ( v2 )
+  {
+    LODWORD(v1) = (signed int)v1 / v2;
+    v5 = &v10;
+    v6 = (char *)&pParty->pPlayers[0].uExperience;
+    v11 = v1;
+    do
+    {
+      if ( *(int *)v5 )
+      {
+        if ( v11 )
+        {
+          LOBYTE(v7) = ((Player *)(v6 - 160))->GetLearningPercent();
+          v1 = v11 + v11 * v7 / 100;
+          v8 = __CFADD__((int)v1, *(int *)v6);
+          *(int *)v6 += v1;
+          *((int *)v6 + 1) += HIDWORD(v1) + v8;
+          if ( *(_QWORD *)v6 > 4000000000i64 )
+          {
+            *((int *)v6 + 1) = 0;
+            *(int *)v6 = -294967296;
+          }
+        }
+      }
+      v6 += 6972;
+      v5 += 4;
+    }
+    while ( (signed int)v6 < (signed int)&pParty->pPickedItem._bonus_strength );
+  }
+  return v1;
+}
+
+//----- (00426A5A) --------------------------------------------------------
+void stru319::LootActor(Actor *pActor)
+{
+  signed int v2; // edi@1
+  char v3; // zf@1
+  unsigned int v4; // eax@13
+  unsigned int v5; // esi@13
+  int v6; // eax@14
+  unsigned __int8 v7; // al@30
+  Party *v8; // esi@34
+  char *v9; // [sp-4h] [bp-3Ch]@10
+  char *v10; // [sp-4h] [bp-3Ch]@31
+  char *v11; // [sp-4h] [bp-3Ch]@38
+  ItemGen Dst; // [sp+Ch] [bp-2Ch]@1
+  int v13; // [sp+30h] [bp-8h]@1
+  int v14; // [sp+34h] [bp-4h]@1
+
+  sub_421B2C_PlaceInInventory_or_DropPickedItem();
+  Dst.Reset();
+  v2 = 0;
+  v3 = ((unsigned int)&array_77EC08[1975].pEdgeList1[1] & pActor->uAttributes) == 0;
+  v13 = 0;
+  v14 = 0;
+  if ( v3 )
+  {
+    if ( !pActor->pMonsterInfo.uTreasureDiceRolls )
+      goto LABEL_9;
+    do
+    {
+      ++v2;
+      v14 += rand() % pActor->pMonsterInfo.uTreasureDiceSides + 1;
+    }
+    while ( v2 < pActor->pMonsterInfo.uTreasureDiceRolls );
+  }
+  else
+  {
+    if ( pItemsTable->pItems[pActor->array_000234[3].uItemID].uEquipType != 18 )
+      goto LABEL_9;
+    v14 = pActor->array_000234[3].uAdditionalValue;
+    pActor->array_000234[3].Reset();
+  }
+  if ( v14 )
+  {
+    party_finds_gold(v14, 0);
+    viewparams->bRedrawGameUI = 1;
+  }
+LABEL_9:
+  if ( pActor->uCarriedItemID )
+  {
+    Dst.Reset();
+    Dst.uItemID = pActor->uCarriedItemID;
+    v9 = pItemsTable->pItems[Dst.uItemID].pUnidentifiedName;
+    if ( v14 )
+      sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[490], v14, v9);
+    else
+      sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[471], v9);
+    ShowStatusBarString(pTmpBuf2, 2u);
+    v4 = Dst.uItemID;
+    v5 = Dst.uItemID;
+    if ( pItemsTable->pItems[Dst.uItemID].uEquipType == 12 )
+    {
+      v5 = Dst.uItemID;
+      v6 = rand() % 6 + pItemsTable->pItems[Dst.uItemID].uDamageMod + 1;
+      Dst.uNumCharges = v6;
+      Dst.uMaxCharges = v6;
+      v4 = Dst.uItemID;
+    }
+    if ( pItemsTable->pItems[v5].uEquipType == 14 && v4 != 220 )
+      Dst._bonus_type = 2 * rand() % 4 + 2;
+    pItemsTable->SetSpecialBonus(&Dst);
+    if ( !pParty->AddItem(&Dst) )
+      pParty->SetHoldingItem(&Dst);
+    pActor->uCarriedItemID = 0;
+    if ( pActor->array_000234[0].uItemID )
+    {
+      if ( !pParty->AddItem(pActor->array_000234) )
+      {
+        sub_421B2C_PlaceInInventory_or_DropPickedItem();
+        pParty->SetHoldingItem(pActor->array_000234);
+      }
+      pActor->array_000234[0].Reset();
+    }
+    if ( pActor->array_000234[1].uItemID )
+    {
+      if ( !pParty->AddItem(&pActor->array_000234[1]) )
+      {
+        sub_421B2C_PlaceInInventory_or_DropPickedItem();
+        pParty->SetHoldingItem(&pActor->array_000234[1]);
+      }
+      pActor->array_000234[1].Reset();
+    }
+LABEL_55:
+    pActor->Remove();
+    return;
+  }
+  if ( (unsigned int)&array_77EC08[1975].pEdgeList1[1] & pActor->uAttributes )
+  {
+    if ( pActor->array_000234[3].uItemID )
+    {
+      memcpy(&Dst, &pActor->array_000234[3], sizeof(Dst));
+      pActor->array_000234[3].Reset();
+      v11 = pItemsTable->pItems[Dst.uItemID].pUnidentifiedName;
+      if ( v14 )
+        sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[490], v14, v11);
+      else
+        sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[471], v11);
+      ShowStatusBarString(pTmpBuf2, 2u);
+      if ( !pParty->AddItem(&Dst) )
+        pParty->SetHoldingItem(&Dst);
+      v13 = 1;
+    }
+    goto LABEL_44;
+  }
+  if ( rand() % 100 >= pActor->pMonsterInfo.uTreasureDropChance || (v7 = pActor->pMonsterInfo.uTreasureLevel) == 0 )
+  {
+LABEL_44:
+    v8 = pParty;
+    goto LABEL_45;
+  }
+  pItemsTable->GenerateItem(v7, pActor->pMonsterInfo.uTreasureType, &Dst);
+  v10 = pItemsTable->pItems[Dst.uItemID].pUnidentifiedName;
+  if ( v14 )
+    sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[490], v14, v10);
+  else
+    sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[471], v10);
+  ShowStatusBarString(pTmpBuf2, 2u);
+  v8 = pParty;
+  if ( !pParty->AddItem(&Dst) )
+    pParty->SetHoldingItem(&Dst);
+  v13 = 1;
+LABEL_45:
+  if ( pActor->array_000234[0].uItemID )
+  {
+    if ( !v8->AddItem(pActor->array_000234) )
+    {
+      sub_421B2C_PlaceInInventory_or_DropPickedItem();
+      v8->SetHoldingItem(pActor->array_000234);
+      v13 = 1;
+    }
+    pActor->array_000234[0].Reset();
+  }
+  if ( pActor->array_000234[1].uItemID )
+  {
+    if ( !v8->AddItem(&pActor->array_000234[1]) )
+    {
+      sub_421B2C_PlaceInInventory_or_DropPickedItem();
+      v8->SetHoldingItem(&pActor->array_000234[1]);
+      v13 = 1;
+    }
+    pActor->array_000234[1].Reset();
+  }
+  if ( !v13 || rand() % 100 < 90 )
+    goto LABEL_55;
+}
+
+//----- (00426E10) --------------------------------------------------------
+int stru319::which_player_would_attack(Actor *pActor)
+{
+  signed int v2; // ebx@1
+  int v3; // ecx@2
+  signed int v4; // edx@3
+  char v5; // zf@3
+  unsigned int v6; // eax@3
+  int v7; // eax@6
+  int v8; // eax@7
+  int v9; // eax@8
+  int v10; // eax@9
+  int v11; // eax@10
+  int v12; // eax@11
+  int v13; // esi@35
+  signed int v14; // edi@37
+  enum CHARACTER_RACE v15; // eax@44
+  Player *v16; // ecx@47
+  unsigned __int8 v17; // sf@50
+  unsigned __int8 v18; // of@50
+  int v19; // esi@52
+  Player *v20; // ecx@53
+  int result; // eax@57
+  int v22[16]; // [sp+8h] [bp-140h]@3
+  int v23[60]; // [sp+48h] [bp-100h]@48
+  int v24; // [sp+138h] [bp-10h]@2
+  int v25; // [sp+13Ch] [bp-Ch]@1
+  int v26; // [sp+140h] [bp-8h]@1
+  int v27; // [sp+144h] [bp-4h]@1
+
+  v27 = -1;
+  v26 = -1;
+  v25 = -1;
+  v2 = 0;
+  if ( pActor->pMonsterInfo.uAttackPreference )
+  {
+    v3 = 0;
+    v24 = 0;
+    do
+    {
+      v4 = 1;
+      v6 = pActor->pMonsterInfo.uAttackPreference & (1 << v3);
+      v5 = (pActor->pMonsterInfo.uAttackPreference & (1 << v3)) == 0;
+      v22[v3] = v6;
+      if ( !v5 )
+      {
+        if ( (signed int)v6 > 128 )
+        {
+          switch ( v6 )
+          {
+            case 0x100u:
+              v27 = 8;
+              break;
+            case 0x200u:
+              v25 = 0;
+              break;
+            case 0x400u:
+              v25 = 1;
+              break;
+            case 0x800u:
+              v26 = 0;
+              break;
+            case 0x1000u:
+              v26 = 1;
+              break;
+            case 0x2000u:
+              v26 = 3;
+              break;
+            case 0x4000u:
+              v26 = 2;
+              break;
+          }
+        }
+        else
+        {
+          if ( v6 == 128 )
+          {
+            v27 = 4;
+          }
+          else
+          {
+            v7 = v6 - 1;
+            if ( v7 )
+            {
+              v8 = v7 - 1;
+              if ( v8 )
+              {
+                v9 = v8 - 2;
+                if ( v9 )
+                {
+                  v10 = v9 - 4;
+                  if ( v10 )
+                  {
+                    v11 = v10 - 8;
+                    if ( v11 )
+                    {
+                      v12 = v11 - 16;
+                      if ( v12 )
+                      {
+                        if ( v12 == 32 )
+                          v27 = 20;
+                      }
+                      else
+                      {
+                        v27 = 32;
+                      }
+                    }
+                    else
+                    {
+                      v27 = 24;
+                    }
+                  }
+                  else
+                  {
+                    v27 = 28;
+                  }
+                }
+                else
+                {
+                  v27 = 16;
+                }
+              }
+              else
+              {
+                v27 = 12;
+              }
+            }
+            else
+            {
+              v27 = 0;
+            }
+          }
+        }
+        v2 = 0;
+        v13 = 0;
+        while ( 1 )
+        {
+          v14 = 0;
+          if ( v27 != -1 && v27 == pPlayers[v13 + 1]->uClass )
+            v14 = v4;
+          if ( v25 != -1 && v25 == pPlayers[v13 + 1]->uSex )
+            v14 = v4;
+          if ( v26 != -1 )
+          {
+            v15 = pPlayers[v13 + 1]->GetRace();
+            if ( v26 == v15 )
+              v14 = 1;
+          }
+          if ( v14 == 1 )
+          {
+            v16 = pPlayers[v13 + 1];
+            if ( !(v16->pConditions[12] | v16->pConditions[13] | v16->pConditions[14] | v16->pConditions[15] | v16->pConditions[16]) )
+              v23[v2++] = v13;
+          }
+          ++v13;
+          if ( v13 >= 4 )
+            break;
+          v4 = 1;
+        }
+      }
+      v3 = v24 + 1;
+      v18 = __OFSUB__(v24 + 1, 15);
+      v17 = v24++ - 14 < 0;
+    }
+    while ( v17 ^ v18 );
+    if ( v2 )
+      goto LABEL_61;
+  }
+  v19 = 0;
+  do
+  {
+    v20 = pPlayers[v19 + 1];
+    if ( !(v20->pConditions[12] | v20->pConditions[13] | v20->pConditions[14] | v20->pConditions[15] | v20->pConditions[16]) )
+      v23[v2++] = v19;
+    ++v19;
+  }
+  while ( v19 < 4 );
+  if ( v2 )
+LABEL_61:
+    result = v23[rand() % v2];
+  else
+    result = 0;
+  return result;
+}
+
+
+//----- (0042704B) --------------------------------------------------------
+bool stru319::special_ability_use_check(Actor *pActor, int a2)
+{
+  stru319 *v3; // edi@1
+  signed int v4; // ebx@5
+  signed int v5; // edi@5
+
+  v3 = this;
+  if ( pActor->pMonsterInfo.uSpecialAbilityType == 2
+    && pActor->pMonsterInfo.uSpecialAbilityDamageDiceBonus < 3u
+    && rand() % 100 < 5 )
+    pActor->_44FD29(a2);
+  v4 = v3->_427102(pActor, pActor->pMonsterInfo.uSpell1ID);
+  v5 = v3->_427102(pActor, pActor->pMonsterInfo.uSpell2ID);
+  if ( v4 && pActor->pMonsterInfo.uSpell1UseChance && rand() % 100 < pActor->pMonsterInfo.uSpell1UseChance )
+    return 2;
+  if ( v5 && pActor->pMonsterInfo.uSpell2UseChance && rand() % 100 < pActor->pMonsterInfo.uSpell2UseChance )
+    return 3;
+  return pActor->pMonsterInfo.uAttack2Chance && rand() % 100 < pActor->pMonsterInfo.uAttack2Chance;
+}
+
+//----- (00427102) --------------------------------------------------------
+int stru319::_427102(Actor *pActor, signed int a2)
+{
+  unsigned __int8 v3; // cf@11
+  unsigned __int8 v4; // zf@11
+  SpellBuff *v6; // ecx@46
+  char *v7; // esi@49
+  signed int v8; // edx@50
+  char *v9; // ecx@50
+
+  if ( a2 > 73 )
+  {
+    if ( a2 == 77 )
+    {
+      if ( pActor->sCurrentHP >= (signed int)pActor->pMonsterInfo.uHP )
+        return 0;
+      return 1;
+    }
+    if ( a2 == 80 )
+    {
+      v6 = pParty->pPartyBuffs;
+      while ( (signed __int64)v6->uExpireTime <= 0 )
+      {
+        ++v6;
+        if ( (signed int)v6 >= (signed int)pParty->pPlayers )
+        {
+          v7 = (char *)pParty->pPlayers[0].pPlayerBuffs;
+LABEL_50:
+          v8 = 0;
+          v9 = v7;
+          while ( *(_QWORD *)v9 <= 0i64 )
+          {
+            ++v8;
+            v9 += 16;
+            if ( v8 >= 24 )
+            {
+              v7 += 6972;
+              if ( (signed int)v7 < (signed int)&pParty->field_871C[464] )
+                goto LABEL_50;
+              return 0;
+            }
+          }
+          return 1;
+        }
+      }
+      return 1;
+    }
+    if ( a2 == 85 )
+    {
+      if ( SHIDWORD(pActor->pActorBuffs[13].uExpireTime) < 0 )
+        return 1;
+      if ( SHIDWORD(pActor->pActorBuffs[13].uExpireTime) > 0 )
+        return 0;
+      v3 = 0;
+      v4 = LODWORD(pActor->pActorBuffs[13].uExpireTime) == 0;
+    }
+    else
+    {
+      if ( a2 == 86 )
+      {
+        if ( SHIDWORD(pActor->pActorBuffs[14].uExpireTime) < 0 )
+          return 1;
+        if ( SHIDWORD(pActor->pActorBuffs[14].uExpireTime) > 0 )
+          return 0;
+        v3 = 0;
+        v4 = LODWORD(pActor->pActorBuffs[14].uExpireTime) == 0;
+      }
+      else
+      {
+        if ( a2 != 95 || SHIDWORD(pActor->pActorBuffs[20].uExpireTime) < 0 )
+          return 1;
+        if ( SHIDWORD(pActor->pActorBuffs[20].uExpireTime) > 0 )
+          return 0;
+        v3 = 0;
+        v4 = LODWORD(pActor->pActorBuffs[20].uExpireTime) == 0;
+      }
+    }
+  }
+  else
+  {
+    if ( a2 == 73 )
+    {
+      if ( SHIDWORD(pActor->pActorBuffs[21].uExpireTime) < 0 )
+        return 1;
+      if ( SHIDWORD(pActor->pActorBuffs[21].uExpireTime) > 0 )
+        return 0;
+      v3 = 0;
+      v4 = LODWORD(pActor->pActorBuffs[21].uExpireTime) == 0;
+      goto LABEL_15;
+    }
+    if ( a2 == 5 )
+    {
+      if ( SHIDWORD(pActor->pActorBuffs[19].uExpireTime) < 0 )
+        return 1;
+      if ( SHIDWORD(pActor->pActorBuffs[19].uExpireTime) > 0 )
+        return 0;
+      v3 = 0;
+      v4 = LODWORD(pActor->pActorBuffs[19].uExpireTime) == 0;
+      goto LABEL_15;
+    }
+    if ( a2 == 17 )
+    {
+      if ( SHIDWORD(pActor->pActorBuffs[15].uExpireTime) < 0 )
+        return 1;
+      if ( SHIDWORD(pActor->pActorBuffs[15].uExpireTime) > 0 )
+        return 0;
+      v3 = 0;
+      v4 = LODWORD(pActor->pActorBuffs[15].uExpireTime) == 0;
+      goto LABEL_15;
+    }
+    if ( a2 == 38 )
+    {
+      if ( SHIDWORD(pActor->pActorBuffs[16].uExpireTime) < 0 )
+        return 1;
+      if ( SHIDWORD(pActor->pActorBuffs[16].uExpireTime) > 0 )
+        return 0;
+      v3 = 0;
+      v4 = LODWORD(pActor->pActorBuffs[16].uExpireTime) == 0;
+      goto LABEL_15;
+    }
+    if ( a2 == 46 )
+    {
+      if ( SHIDWORD(pActor->pActorBuffs[17].uExpireTime) < 0 )
+        return 1;
+      if ( SHIDWORD(pActor->pActorBuffs[17].uExpireTime) > 0 )
+        return 0;
+      v3 = 0;
+      v4 = LODWORD(pActor->pActorBuffs[17].uExpireTime) == 0;
+      goto LABEL_15;
+    }
+    if ( a2 != 47 )
+    {
+      if ( a2 != 51 || SHIDWORD(pActor->pActorBuffs[18].uExpireTime) < 0 )
+        return 1;
+      if ( SHIDWORD(pActor->pActorBuffs[18].uExpireTime) <= 0 )
+      {
+        v3 = 0;
+        v4 = LODWORD(pActor->pActorBuffs[18].uExpireTime) == 0;
+        goto LABEL_15;
+      }
+      return 0;
+    }
+    if ( SHIDWORD(pActor->pActorBuffs[11].uExpireTime) < 0 )
+      return 1;
+    if ( SHIDWORD(pActor->pActorBuffs[11].uExpireTime) > 0 )
+      return 0;
+    v3 = 0;
+    v4 = LODWORD(pActor->pActorBuffs[11].uExpireTime) == 0;
+  }
+LABEL_15:
+  if ( !(v3 | v4) )
+    return 0;
+  return 1;
+}
+
+//----- (004272F5) --------------------------------------------------------
+int stru319::PlayerHitOrMiss(Player *pPlayer, Actor *pActor, int a3, int a4)
+{
+  signed int v5; // esi@1
+  signed int v6; // edi@1
+  int v7; // esi@8
+  int v8; // eax@9
+  int v9; // edx@11
+  int v10; // edx@13
+  int v11; // esi@13
+  unsigned __int8 v12; // sf@13
+  unsigned __int8 v13; // of@13
+  int v14; // edx@14
+  int v15; // eax@14
+  signed int result; // eax@17
+
+  v5 = pActor->pMonsterInfo.uAC;
+  v6 = 0;
+  if ( (signed __int64)pActor->pActorBuffs[8].uExpireTime > 0 )
+    v5 /= 2;
+  if ( (signed __int64)pActor->pActorBuffs[14].uExpireTime > 0 )
+    v6 = pActor->pActorBuffs[15].uPower;
+  if ( (signed __int64)pActor->pActorBuffs[16].uExpireTime > 0 && pActor->pActorBuffs[16].uPower > v6 )
+    v6 = pActor->pActorBuffs[16].uPower;
+  v7 = v6 + v5;
+  if ( a3 )
+    v8 = pPlayer->GetRangedAttack();
+  else
+    v8 = pPlayer->GetActualAttack(0);
+  v9 = rand() % (v7 + 2 * v8 + 30);
+  if ( a3 == 2 )
+  {
+    v14 = a4 + v9;
+    v15 = ((v7 + 15) >> 1) + v7 + 15;
+  }
+  else
+  {
+    if ( a3 != 3 )
+    {
+      v10 = a4 + v9;
+      v11 = v7 + 15;
+      v13 = __OFSUB__(v10, v11);
+      v12 = v10 - v11 < 0;
+      goto LABEL_16;
+    }
+    v14 = a4 + v9;
+    v15 = 2 * v7 + 30;
+  }
+  v13 = __OFSUB__(v14, v15);
+  v12 = v14 - v15 < 0;
+LABEL_16:
+  if ( v12 ^ v13 )
+    result = 0;
+  else
+    result = 1;
+  return result;
+}
+
+//----- (004273BB) --------------------------------------------------------
+bool stru319::_4273BB(Actor *pActor, Actor *a2, int a3, int a4)
+{
+  Actor *v5; // ecx@1
+  signed int v6; // ebx@1
+  signed int v7; // esi@1
+  unsigned __int8 v8; // zf@1
+  unsigned __int8 v9; // sf@1
+  int v10; // ebx@10
+  signed int a2a; // [sp+18h] [bp+Ch]@1
+
+  v5 = a2;
+  v6 = a2->pMonsterInfo.uAC;
+  v7 = 0;
+  v8 = HIDWORD(a2->pActorBuffs[8].uExpireTime) == 0;
+  v9 = SHIDWORD(a2->pActorBuffs[8].uExpireTime) < 0;
+  a2a = 0;
+  if ( !v9 && (!(v9 | v8) || LODWORD(v5->pActorBuffs[8].uExpireTime) > 0) )
+    v6 /= 2;
+  if ( (signed __int64)v5->pActorBuffs[14].uExpireTime > 0 )
+    v7 = v5->pActorBuffs[14].uPower;
+  if ( (signed __int64)v5->pActorBuffs[16].uExpireTime > 0 && v5->pActorBuffs[16].uPower > v7 )
+    v7 = v5->pActorBuffs[16].uPower;
+  v10 = v7 + v6;
+  if ( (signed __int64)pActor->pActorBuffs[14].uExpireTime > 0 )
+    a2a = pActor->pActorBuffs[14].uPower;
+  if ( (signed __int64)pActor->pActorBuffs[17].uExpireTime > 0 && pActor->pActorBuffs[17].uPower > a2a )
+    a2a = pActor->pActorBuffs[17].uPower;
+  if ( (signed __int64)pActor->pActorBuffs[11].uExpireTime > 0 )
+  {
+    a2a += pActor->pActorBuffs[11].uPower;
+    pActor->pActorBuffs[11].Reset();
+  }
+  return rand() % (v10 + 2 * pActor->pMonsterInfo.uLevel + 10) + a2a + 1 > v10 + 5;
+}
+
+//----- (004274AD) --------------------------------------------------------
+bool stru319::ActorHitOrMiss(Actor *pActor, Player *pPlayer)
+{
+  signed int v3; // edi@1
+  signed int v4; // esi@8
+  int v5; // esi@8
+
+  v3 = 0;
+  if ( (signed __int64)pActor->pActorBuffs[14].uExpireTime > 0 )
+    v3 = pActor->pActorBuffs[14].uPower;
+  if ( (signed __int64)pActor->pActorBuffs[17].uExpireTime > 0 && pActor->pActorBuffs[17].uPower > v3 )
+    v3 = pActor->pActorBuffs[17].uPower;
+  if ( (signed __int64)pActor->pActorBuffs[11].uExpireTime > 0 )
+  {
+    v3 += pActor->pActorBuffs[11].uPower;
+    pActor->pActorBuffs[11].Reset();
+  }
+  v4 = pPlayer->GetActualAC() + 2 * pActor->pMonsterInfo.uLevel + 10;
+  v5 = rand() % v4 + 1;
+  return v3 + v5 > pPlayer->GetActualAC() + 5;
+}
+
+//----- (00427546) --------------------------------------------------------
+int stru319::_427546(int a2)
+{
+  int result; // eax@2
+
+  if ( a2 >= 0 )
+  {
+    if ( a2 >= 1 )
+      result = (a2 >= 2) + 2;
+    else
+      result = 1;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+//----- (0042756B) --------------------------------------------------------
+int stru319::CalcMagicalDamageToActor(Actor *pActor, int a2, signed int a3)
+{
+  int v4; // edx@1
+  int v5; // ecx@1
+  signed int v6; // eax@4
+  signed int result; // eax@17
+  signed int v8; // esi@18
+
+  v4 = 0;
+  v5 = 0;
+  if ( (signed __int64)pActor->pActorBuffs[14].uExpireTime > 0 )
+    v5 = pActor->pActorBuffs[14].uPower;
+  switch ( a2 )
+  {
+    case 4:
+      v6 = pActor->pMonsterInfo.uResPhysical;
+      break;
+    case 0:
+      v6 = pActor->pMonsterInfo.uResFire;
+      goto LABEL_12;
+    case 1:
+      v6 = pActor->pMonsterInfo.uResAir;
+      goto LABEL_12;
+    case 2:
+      v6 = pActor->pMonsterInfo.uResWater;
+      goto LABEL_12;
+    case 3:
+      v6 = pActor->pMonsterInfo.uResEarth;
+      goto LABEL_12;
+    case 6:
+      v6 = pActor->pMonsterInfo.uResSpirit;
+      break;
+    case 7:
+      v6 = pActor->pMonsterInfo.uResMind;
+      goto LABEL_12;
+    case 8:
+      v6 = pActor->pMonsterInfo.uResBody;
+LABEL_12:
+      v4 = v5;
+      break;
+    case 9:
+      v6 = pActor->pMonsterInfo.uResLight;
+      break;
+    case 10:
+      v6 = pActor->pMonsterInfo.uResDark;
+      break;
+    default:
+      v6 = 0;
+      break;
+  }
+  if ( v6 < 200 )
+  {
+    v8 = v4 + v6 + 30;
+    if ( rand() % v8 >= 30 )
+    {
+      a3 >>= 1;
+      if ( rand() % v8 >= 30 )
+      {
+        a3 >>= 1;
+        if ( rand() % v8 >= 30 )
+        {
+          a3 >>= 1;
+          if ( rand() % v8 >= 30 )
+            a3 >>= 1;
+        }
+      }
+    }
+    result = a3;
+  }
+  else
+  {
+    result = 0;
+  }
+  return result;
+}
+
+//----- (00427662) --------------------------------------------------------
+bool stru319::GetMagicalResistance(Actor *pActor, unsigned int uType)
+{
+  Actor *v3; // edi@2
+  signed int v4; // esi@2
+  bool result; // eax@13
+
+  switch ( uType )
+  {
+    case 0u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResFire;
+      goto LABEL_12;
+    case 1u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResAir;
+      goto LABEL_12;
+    case 2u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResWater;
+      goto LABEL_12;
+    case 3u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResEarth;
+      goto LABEL_12;
+    case 7u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResMind;
+      goto LABEL_12;
+    case 6u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResSpirit;
+      goto LABEL_12;
+    case 8u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResBody;
+      goto LABEL_12;
+    case 9u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResLight;
+      goto LABEL_12;
+    case 0xAu:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResDark;
+      goto LABEL_12;
+    case 4u:
+      v3 = pActor;
+      v4 = pActor->pMonsterInfo.uResPhysical;
+LABEL_12:
+      if ( v4 < 200 )
+        result = rand() % (signed int)(((unsigned int)v3->pMonsterInfo.uLevel >> 2) + v4 + 30) < 30;
+      else
+        result = 0;
+      break;
+    default:
+      result = 1;
+      break;
+  }
+  return result;
+}
+
+
+//----- (00427769) --------------------------------------------------------
+bool __fastcall sub_427769_spell(unsigned int uSpellID)
+{
+  bool result; // eax@2
+
+  if ( *(&pSpellDatas[0].field_12 + 20 * uSpellID) & 0xC )
+    result = 1;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0042777D) --------------------------------------------------------
+bool __fastcall _42777D_CastSpell_UseWand_ShootArrow(int a1, unsigned int uPlayerID, unsigned int a4, __int16 a5, int a6)
+{
+  bool result; // eax@2
+  __int16 v6; // bx@4
+  Player *v7; // eax@4
+  char v8; // zf@12
+  unsigned __int16 v9; // cx@16
+  unsigned int v10; // eax@18
+  unsigned __int8 v11; // sf@18
+  unsigned __int8 v12; // of@18
+  unsigned __int16 v13; // cx@21
+  unsigned int v14; // eax@23
+  stru277 *v15; // esi@27
+  stru277 *v16; // eax@28
+  GUIWindow *v17; // eax@43
+  GUIWindow *v18; // [sp-30h] [bp-48h]@44
+  unsigned int v19; // [sp-2Ch] [bp-44h]@44
+  unsigned int v20; // [sp-28h] [bp-40h]@44
+  unsigned int v21; // [sp-24h] [bp-3Ch]@44
+  unsigned int v22; // [sp-20h] [bp-38h]@44
+  int v23; // [sp-1Ch] [bp-34h]@44
+  int v24; // [sp-18h] [bp-30h]@44
+  unsigned int v25; // [sp-14h] [bp-2Ch]@43
+  unsigned int v26; // [sp-10h] [bp-28h]@43
+  unsigned __int8 v27; // [sp-Ch] [bp-24h]@43
+  char *v28; // [sp-8h] [bp-20h]@43
+  Texture *v29; // [sp-4h] [bp-1Ch]@43
+  __int16 a3a; // [sp+10h] [bp-8h]@1
+  __int16 a2a; // [sp+14h] [bp-4h]@1
+
+  a3a = uPlayerID;
+  a2a = a1;
+  if ( pParty->bTurnBasedModeOn != 1
+    || (result = pTurnEngine->field_4, pTurnEngine->field_4 != 1) && pTurnEngine->field_4 != 3 )
+  {
+    v6 = a5;
+    v7 = &pParty->pPlayers[uPlayerID];
+    if ( !(a5 & 0x10) )
+    {
+      switch ( a1 )
+      {
+        case 47:
+        case 68:
+        case 89:
+          HIBYTE(v6) = HIBYTE(a5) | 1;
+          break;
+        case 4:
+        case 28:
+        case 30:
+        case 91:
+          LOBYTE(v6) = a5 | 0x80;
+          break;
+        case 2:
+        case 6:
+        case 11:
+        case 18:
+        case 20:
+        case 24:
+        case 26:
+        case 29:
+        case 32:
+        case 34:
+        case 35:
+        case 37:
+        case 39:
+        case 44:
+        case 52:
+        case 57:
+        case 60:
+        case 65:
+        case 70:
+        case 76:
+        case 78:
+        case 79:
+        case 87:
+        case 90:
+        case 92:
+        case 93:
+        case 97:
+          if ( !a6 )
+            goto LABEL_9;
+          break;
+        case 59:
+        case 62:
+        case 66:
+        case 81:
+        case 94:
+LABEL_9:
+          v6 = a5 | 8;
+          break;
+        case 42:
+          v6 = a5 | 0x40;
+          break;
+        case 46:
+          if ( a4 )
+            v8 = (a4 & 0x1C0) == 0;
+          else
+            v8 = (v7->pActiveSkills[16] & 0x1C0) == 0;
+          if ( v8 )
+            goto LABEL_25;
+          break;
+        case 50:
+          v9 = a4;
+          if ( !a4 )
+            v9 = v7->pActiveSkills[16];
+          goto LABEL_18;
+        case 95:
+          v9 = a4;
+          if ( !a4 )
+            v9 = v7->pActiveSkills[20];
+LABEL_18:
+          v10 = SkillToMastery(v9);
+          v12 = __OFSUB__(v10, 3);
+          v11 = ((v10 - 3) & 0x80000000u) != 0;
+          goto LABEL_24;
+        case 73:
+          v13 = a4;
+          if ( !a4 )
+            v13 = v7->pActiveSkills[18];
+          v14 = SkillToMastery(v13);
+          v12 = __OFSUB__(v14, 4);
+          v11 = ((v14 - 4) & 0x80000000u) != 0;
+LABEL_24:
+          if ( v11 ^ v12 )
+            goto LABEL_25;
+          break;
+        case 40:
+        case 49:
+        case 53:
+        case 55:
+        case 56:
+        case 61:
+        case 64:
+        case 67:
+        case 71:
+        case 72:
+        case 74:
+LABEL_25:
+          v6 = a5 | 2;
+          break;
+        case 96:
+          HIBYTE(v6) = HIBYTE(a5) | 2;
+          break;
+        default:
+          break;
+      }
+    }
+    v15 = pStru277;
+    if ( v6 & 0x3CA )
+    {
+      v16 = pStru277;
+      while ( !(v16->field_8 & 0x3CA) )
+      {
+        ++v16;
+        if ( (signed int)v16 >= (signed int)&unk_50C190 )
+          goto LABEL_33;
+      }
+      v16->spellnum = 0;
+    }
+    do
+    {
+LABEL_33:
+      if ( v15->spellnum )
+      {
+        v8 = (v15->field_8 & 0x3CA) == 0;
+        v15->spellnum = 0;
+        if ( !v8 )
+        {
+          pGUIWindow_Settings->Release();
+          pGUIWindow_Settings = 0;
+          pMouse->SetCursorBitmap("MICON1");
+          GameUI_StatusBar_TimedStringTimeLeft = 0;
+          unk_50C9A0 = 0;
+          back_to_game();
+        }
+      }
+      ++v15;
+    }
+    while ( (signed int)v15 < (signed int)&unk_50C190 );
+    result = pStru277->PushStru277(a2a, a3a, a4, v6, a6);
+    if ( result != -1 )
+    {
+      if ( v6 & 2 )
+      {
+        if ( pGUIWindow_Settings )
+          return result;
+        pGUIWindow_Settings = GUIWindow::Create(0, 0, 640, 480, (WindowType)(WINDOW_HouseInterior|0x2), (int)&pStru277[result], 0);
+        pGUIWindow_Settings->CreateButton(0x34u, 0x1A6u, 0x23u, 0, 2, 0, 0x45u, 0, 0x31u, "", 0);
+        pGUIWindow_Settings->CreateButton(0xA5u, 0x1A6u, 0x23u, 0, 2, 0, 0x45u, 1u, 0x32u, "", 0);
+        pGUIWindow_Settings->CreateButton(0x118u, 0x1A6u, 0x23u, 0, 2, 0, 0x45u, 2u, 0x33u, "", 0);
+        pGUIWindow_Settings->CreateButton(0x186u, 0x1A6u, 0x23u, 0, 2, 0, 0x45u, 3u, 0x34u, "", 0);
+        return sub_421B2C_PlaceInInventory_or_DropPickedItem();
+      }
+      if ( v6 & 8 )
+      {
+        if ( pGUIWindow_Settings )
+          return result;
+        v17 = GUIWindow::Create(0, 0, 640, 480, (WindowType)(WINDOW_HouseInterior|0x2), (int)&pStru277[result], 0);
+        v29 = 0;
+        v28 = "";
+        v27 = 0;
+        v26 = 0;
+        v25 = 70;
+LABEL_44:
+        v24 = 0;
+        v23 = 1;
+        v22 = 344;
+        v21 = 460;
+        v20 = 8;
+        v19 = 8;
+        pGUIWindow_Settings = v17;
+        v18 = v17;
+LABEL_56:
+        v18->CreateButton(v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29);
+        return sub_421B2C_PlaceInInventory_or_DropPickedItem();
+      }
+      if ( v6 & 0x40 )
+      {
+        if ( pGUIWindow_Settings )
+          return result;
+        v17 = GUIWindow::Create(0, 0, 640, 480, (WindowType)(WINDOW_HouseInterior|0x2), (int)&pStru277[result], 0);
+        v29 = 0;
+        v28 = "";
+        v27 = 0;
+        v26 = 0;
+        v25 = 190;
+        goto LABEL_44;
+      }
+      if ( (char)v6 < 0 )
+      {
+        if ( pGUIWindow_Settings )
+          return result;
+        ++pIcons_LOD->uTexturePacksCount;
+        if ( !pIcons_LOD->uNumPrevLoadedFiles )
+          pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+        pGUIWindow_Settings = pStru277[result].sub_4219BE();
+        unk_50C9A0 = 1;
+        some_active_character = uActiveCharacter;
+        return sub_421B2C_PlaceInInventory_or_DropPickedItem();
+      }
+      if ( HIBYTE(v6) & 1 )
+      {
+        if ( pGUIWindow_Settings )
+          return result;
+        pGUIWindow_Settings = GUIWindow::Create(0, 0, 640, 480, (WindowType)(WINDOW_HouseInterior|0x2), 20 * result + 5292232, 0);
+        pGUIWindow_Settings->CreateButton(0x34u, 0x1A6u, 0x23u, 0, 2, 0, 0x8Du, 0, 0x31u, "", 0);
+        pGUIWindow_Settings->CreateButton(0xA5u, 0x1A6u, 0x23u, 0, 2, 0, 0x8Du, 1u, 0x32u, "", 0);
+        pGUIWindow_Settings->CreateButton(0x118u, 0x1A6u, 0x23u, 0, 2, 0, 0x8Du, 2u, 0x33u, "", 0);
+        pGUIWindow_Settings->CreateButton(0x186u, 0x1A6u, 0x23u, 0, 2, 0, 0x8Du, 3u, 0x34u, "", 0);
+        v29 = 0;
+        v28 = "";
+        v27 = 0;
+        v26 = 0;
+        v25 = 140;
+        v24 = 0;
+        v23 = 1;
+        v22 = 344;
+        v21 = 460;
+        v20 = 8;
+        v19 = 8;
+        v18 = pGUIWindow_Settings;
+        goto LABEL_56;
+      }
+      if ( HIBYTE(v6) & 2 && !pGUIWindow_Settings )
+      {
+        pGUIWindow_Settings = GUIWindow::Create(0, 0, 640, 480, (WindowType)(WINDOW_HouseInterior|0x2), 20 * result + 5292232, 0);
+        pBtn_NPCLeft = pGUIWindow_Settings->CreateButton(
+                       0x1D5u,
+                       0xB2u,
+                       (uTextureID_507990 != -1 ? pIcons_LOD->pTextures[uTextureID_507990].uTextureWidth : 24),
+                       (uTextureID_507990 != -1 ? pIcons_LOD->pTextures[uTextureID_507990].uTextureHeight : 26),
+                       1,
+                       0,
+                       0xBCu,
+                       0,
+                       0,
+                       "",
+                       (Texture *)(uTextureID_507990 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507990] : 0),
+                       0);
+        pBtn_NPCRight = pGUIWindow_Settings->CreateButton(
+                       0x272u,
+                       0xB2u,
+                       (uTextureID_50798C != -1 ? pIcons_LOD->pTextures[uTextureID_50798C].uTextureWidth : 24),
+                       (uTextureID_50798C != -1 ? pIcons_LOD->pTextures[uTextureID_50798C].uTextureHeight : 26),
+                       1,
+                       0,
+                       0xBCu,
+                       1u,
+                       0,
+                       "",
+                       (Texture *)(uTextureID_50798C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50798C] : 0),
+                       0);
+        pGUIWindow_Settings->CreateButton(0x1EBu, 0x95u, 0x40u, 0x4Au, 1, 0, 0x8Fu, 4u, 0x35u, "", 0);
+        result = (bool)pGUIWindow_Settings->CreateButton(
+                         0x231u,
+                         0x95u,
+                         0x40u,
+                         0x4Au,
+                         1,
+                         0,
+                         0x8Fu,
+                         5u,
+                         0x36u,
+                         "",
+                         0);
+      }
+    }
+  }
+  return result;
+}
+
+
+
+//----- (00427D48) --------------------------------------------------------
+void stru277::_427D48(unsigned int uPlayerID)
+{
+  stru277 *v2; // esi@1
+  signed int v3; // ebx@1
+
+  v2 = this;
+  v3 = 10;
+  do
+  {
+    if ( v2->spellnum )
+    {
+      if ( v2->field_8 & 0x3CA )
+      {
+        v2->spellnum = 0;
+        pGUIWindow_Settings->Release();
+        pGUIWindow_Settings = 0;
+        pMouse->SetCursorBitmap("MICON1");
+        GameUI_StatusBar_TimedStringTimeLeft = 0;
+        unk_50C9A0 = 0;
+        back_to_game();
+      }
+    }
+    ++v2;
+    --v3;
+  }
+  while ( v3 );
+}
+
+//----- (00427DA0) --------------------------------------------------------
+unsigned int stru277::PushStru277(__int16 a2, __int16 uPlayerID, __int16 a4, __int16 a5, int a6)
+{
+  unsigned int result; // eax@1
+  stru277 *v7; // edx@1
+  stru277 *v8; // ecx@5
+
+  result = 0;
+  v7 = this;
+  while ( v7->spellnum )
+  {
+    ++result;
+    ++v7;
+    if ( (signed int)result >= 10 )
+      goto LABEL_8;
+  }
+  v8 = &this[result];
+  v8->spellnum = a2;
+  v8->uPlayerID = uPlayerID;
+  if ( a5 & 0x10 )
+    v8->uPlayerID_2 = uPlayerID;
+  v8->field_6 = 0;
+  *(int *)&v8->field_C = 0;
+  v8->field_8 = a5;
+  v8->field_A = a4;
+  v8->field_10 = a6;
+LABEL_8:
+  if ( result == 10 )
+    result = -1;
+  return result;
+}
+
+//----- (00427E01) --------------------------------------------------------
+void stru277::_427E01_cast_spell()
+{
+  int v1; // esi@1
+  int v2; // edi@1
+  stru277 *v3; // ebx@2
+  signed int v4; // eax@8
+  __int16 v5; // ax@9
+  signed int v6; // eax@14
+  __int16 v7; // ax@23
+  __int16 v8; // ax@24
+  char v9; // al@44
+  int v10; // eax@45
+  unsigned __int16 v11; // cx@45
+  signed int v12; // ecx@48
+  int v13; // eax@53
+  unsigned __int8 v14; // zf@53
+  unsigned int v15; // edx@53
+  signed int v16; // eax@53
+  Player *v17; // esi@70
+  int v18; // eax@72
+  int v19; // eax@74
+  char *v20; // eax@74
+  signed int i; // esi@76
+  int v22; // eax@88
+  __int16 v23; // ax@88
+  int v24; // ecx@93
+  int v25; // ecx@94
+  signed __int64 v26; // qax@100
+  char *v27; // ecx@100
+  unsigned __int64 v28; // qax@102
+  int v29; // ecx@105
+  int v30; // ecx@106
+  int v31; // eax@112
+  int v32; // eax@112
+  char *v33; // edx@113
+  int v34; // eax@121
+  int v35; // eax@123
+  int v36; // edx@125
+  int v37; // eax@129
+  signed int v38; // edi@129
+  signed int v39; // eax@129
+  int v40; // ecx@129
+  int v41; // eax@129
+  signed int v42; // eax@129
+  int *v43; // ecx@129
+  int v44; // eax@132
+  int v45; // ecx@132
+  int v46; // eax@132
+  unsigned int v47; // edx@133
+  int v48; // eax@137
+  int v49; // eax@137
+  int v50; // eax@141
+  int v51; // eax@146
+  __int16 v52; // ax@153
+  int v53; // eax@153
+  signed __int64 v54; // qax@164
+  int v55; // edi@164
+  stru6 *v56; // eax@165
+  int v57; // eax@169
+  signed __int64 v58; // qax@177
+  int v59; // edi@177
+  unsigned __int16 v60; // ax@184
+  int v61; // ecx@184
+  int v62; // eax@186
+  int v63; // ecx@187
+  int v64; // ecx@188
+  int v65; // ecx@189
+  const char *v66; // ecx@200
+  unsigned int v67; // edx@201
+  char v68; // al@207
+  int v69; // esi@211
+  int v70; // ecx@214
+  int v71; // ecx@215
+  int v72; // ecx@216
+  __int16 v73; // ST1C_2@222
+  __int16 v74; // ST18_2@222
+  stru6 *v75; // eax@222
+  int v76; // ecx@223
+  int v77; // ecx@224
+  int v78; // ecx@225
+  int v79; // eax@227
+  int v80; // eax@232
+  __int16 v81; // ST18_2@245
+  stru6 *v82; // eax@245
+  signed int v83; // edi@245
+  __int16 v84; // ST18_2@245
+  stru6 *v85; // eax@245
+  __int16 v86; // ST18_2@245
+  stru6 *v87; // eax@245
+  __int16 v88; // ST18_2@245
+  stru6 *v89; // eax@245
+  double v90; // st7@245
+  int v91; // eax@250
+  char *v92; // eax@255
+  __int16 v93; // ST18_2@260
+  stru6 *v94; // eax@260
+  __int16 v95; // ST18_2@260
+  stru6 *v96; // eax@260
+  __int16 v97; // ST18_2@260
+  stru6 *v98; // eax@260
+  __int16 v99; // ST18_2@260
+  stru6 *v100; // eax@260
+  int v101; // ecx@261
+  int v102; // ecx@262
+  int v103; // ecx@263
+  int v104; // eax@265
+  int v105; // edi@271
+  __int16 v106; // ST18_2@272
+  stru6 *v107; // eax@272
+  __int16 v108; // ST1C_2@274
+  __int16 v109; // ST18_2@274
+  stru6 *v110; // eax@274
+  int v111; // eax@274
+  Actor *v112; // esi@278
+  int v113; // eax@278
+  int v114; // ebx@278
+  unsigned int v115; // ecx@278
+  int v116; // edx@279
+  int v117; // edx@281
+  int v118; // edx@283
+  int v119; // edi@286
+  int v120; // eax@286
+  int v121; // eax@286
+  signed int v122; // eax@286
+  int v123; // ecx@288
+  int v124; // ecx@289
+  int v125; // ecx@290
+  int v126; // eax@292
+  int v127; // eax@296
+  __int16 v128; // ST18_2@303
+  stru6 *v129; // eax@303
+  __int16 v130; // ST18_2@303
+  stru6 *v131; // eax@303
+  __int16 v132; // ST18_2@303
+  stru6 *v133; // eax@303
+  __int16 v134; // ST18_2@303
+  stru6 *v135; // eax@303
+  unsigned __int64 v136; // qax@304
+  char *v137; // ecx@304
+  int v138; // ecx@305
+  int v139; // ecx@306
+  int v140; // eax@308
+  __int16 v141; // ST18_2@311
+  stru6 *v142; // eax@311
+  __int16 v143; // ST18_2@311
+  stru6 *v144; // eax@311
+  __int16 v145; // ST18_2@311
+  stru6 *v146; // eax@311
+  __int16 v147; // ST18_2@311
+  stru6 *v148; // eax@311
+  int v149; // ecx@312
+  int v150; // ecx@313
+  int v151; // ecx@314
+  signed int v152; // eax@322
+  int v153; // ecx@322
+  int v154; // eax@322
+  int v155; // eax@323
+  int v156; // eax@323
+  int v157; // eax@326
+  double v158; // st7@326
+  double v159; // st6@326
+  signed __int64 v160; // qtt@334
+  int v161; // eax@339
+  int v162; // edi@340
+  int v163; // eax@340
+  signed int v164; // eax@340
+  signed int v165; // edi@340
+  stru6 *v166; // eax@340
+  stru6 *v167; // eax@340
+  signed int v168; // edi@343
+  int v169; // eax@344
+  int v170; // ecx@346
+  int v171; // ecx@347
+  int v172; // ecx@348
+  int v173; // edi@350
+  signed int v174; // edi@355
+  __int16 v175; // ST18_2@357
+  stru6 *v176; // eax@357
+  __int16 v177; // ST18_2@357
+  stru6 *v178; // eax@357
+  __int16 v179; // ST18_2@357
+  stru6 *v180; // eax@357
+  __int16 v181; // ST18_2@357
+  stru6 *v182; // eax@357
+  signed __int64 v183; // qax@357
+  int v184; // ecx@358
+  int v185; // ecx@359
+  int v186; // ecx@360
+  int v187; // eax@367
+  int v188; // esi@369
+  int v189; // edi@369
+  const char *v190; // ecx@377
+  signed int v191; // edi@379
+  int v192; // ecx@382
+  int v193; // ecx@383
+  int v194; // ecx@384
+  int v195; // eax@386
+  int v196; // eax@387
+  __int16 v197; // ST18_2@395
+  stru6 *v198; // eax@395
+  __int16 v199; // ST18_2@395
+  stru6 *v200; // eax@395
+  __int16 v201; // ST18_2@395
+  stru6 *v202; // eax@395
+  __int16 v203; // ST18_2@395
+  stru6 *v204; // eax@395
+  signed int v205; // edi@405
+  int v206; // eax@407
+  __int16 v207; // cx@407
+  int v208; // eax@411
+  signed int v209; // ecx@412
+  int v210; // edx@412
+  signed int v211; // ecx@412
+  int v212; // eax@413
+  int v213; // eax@413
+  int v214; // eax@413
+  int v215; // eax@415
+  double v216; // st7@415
+  double v217; // st6@415
+  signed __int64 v218; // qtt@423
+  int v219; // ecx@425
+  int v220; // ecx@426
+  int v221; // edi@428
+  char *v222; // edi@434
+  char v223; // al@438
+  int v224; // ecx@442
+  int v225; // ecx@443
+  int v226; // eax@451
+  int v227; // esi@453
+  unsigned int v228; // edi@454
+  int v229; // edi@466
+  __int16 v230; // ST18_2@469
+  stru6 *v231; // eax@469
+  signed int v232; // esi@469
+  __int16 v233; // ST18_2@469
+  stru6 *v234; // eax@469
+  __int16 v235; // ST18_2@469
+  stru6 *v236; // eax@469
+  __int16 v237; // ST18_2@469
+  stru6 *v238; // eax@469
+  __int16 v239; // ST1C_2@469
+  char *v240; // ecx@472
+  double v241; // st7@478
+  signed __int64 v242; // qax@484
+  char *v243; // ecx@484
+  char *v244; // eax@488
+  int v245; // edi@492
+  int v246; // eax@492
+  char *v247; // eax@497
+  char v248; // al@497
+  char v249; // cf@500
+  float v250; // esi@507
+  char v251; // al@507
+  int v252; // edx@510
+  int m; // esi@510
+  int v254; // eax@513
+  int v255; // esi@513
+  int v256; // ecx@513
+  int v257; // edx@514
+  int v258; // ecx@514
+  char v259; // al@516
+  int v260; // eax@518
+  int v261; // esi@519
+  int v262; // edx@521
+  int v263; // ecx@521
+  int v264; // esi@521
+  int v265; // edx@521
+  int *ii; // eax@522
+  int v267; // eax@524
+  int v268; // eax@524
+  int v269; // eax@526
+  char *v270; // eax@531
+  char v271; // al@531
+  char v272; // cf@534
+  float v273; // esi@541
+  char v274; // al@541
+  int v275; // edx@544
+  int k; // esi@544
+  int v277; // edx@548
+  int v278; // ecx@548
+  char v279; // al@550
+  int v280; // eax@552
+  int v281; // esi@553
+  int v282; // edx@555
+  int v283; // ecx@555
+  int v284; // esi@555
+  int v285; // edx@555
+  int *l; // eax@556
+  int v287; // eax@558
+  int v288; // eax@558
+  ItemGen *v289; // eax@560
+  signed int v290; // eax@560
+  unsigned __int8 v291; // al@564
+  char v292; // al@573
+  int v293; // eax@575
+  ItemGen *v294; // esi@575
+  int v295; // edx@575
+  int kk; // edi@575
+  int v297; // edx@579
+  int v298; // ecx@579
+  char v299; // al@581
+  int v300; // eax@583
+  int v301; // edi@584
+  int v302; // edx@586
+  int v303; // ecx@586
+  int v304; // edi@586
+  int v305; // edx@586
+  int *jj; // eax@587
+  int v307; // eax@589
+  int v308; // eax@589
+  char *v309; // ecx@593
+  char v310; // sf@593
+  unsigned __int8 v311; // of@593
+  char v312; // cl@597
+  char v313; // al@606
+  int v314; // edx@607
+  int j; // esi@607
+  unsigned int v316; // eax@613
+  const char *v317; // ecx@617
+  Player *v318; // ecx@619
+  unsigned int v319; // edi@627
+  int v320; // ecx@629
+  int v321; // ecx@630
+  int v322; // edi@632
+  int v323; // edi@635
+  char *v324; // eax@635
+  Player *v325; // ecx@640
+  int v326; // eax@643
+  int v327; // eax@648
+  int v328; // ecx@651
+  int v329; // ecx@652
+  int v330; // edi@654
+  __int16 v331; // ST18_2@658
+  stru6 *v332; // eax@658
+  __int16 v333; // ST18_2@658
+  stru6 *v334; // eax@658
+  __int16 v335; // ST18_2@658
+  stru6 *v336; // eax@658
+  __int16 v337; // ST18_2@658
+  stru6 *v338; // eax@658
+  int v339; // ecx@659
+  int v340; // ecx@660
+  int v341; // eax@663
+  signed int v342; // edi@668
+  signed int v343; // edi@670
+  unsigned __int64 v344; // ST08_8@670
+  __int16 v345; // ST1C_2@671
+  __int16 v346; // ST18_2@671
+  stru6 *v347; // eax@671
+  int v348; // ecx@672
+  int v349; // ecx@673
+  int v350; // edi@676
+  Player *v351; // edi@680
+  __int16 v352; // ST18_2@685
+  stru6 *v353; // eax@685
+  int v354; // ecx@686
+  int v355; // ecx@687
+  int v356; // eax@689
+  SpellBuff *v357; // edi@694
+  unsigned __int16 v358; // ST1C_2@695
+  __int16 v359; // ST18_2@695
+  stru6 *v360; // eax@695
+  __int16 v361; // ST1C_2@697
+  __int16 v362; // ST18_2@697
+  stru6 *v363; // eax@697
+  int v364; // ecx@698
+  int v365; // ecx@699
+  int v366; // eax@701
+  stru6 *v367; // eax@704
+  int v368; // eax@704
+  Actor *v369; // edi@705
+  int v370; // eax@706
+  int v371; // ecx@709
+  int v372; // ecx@710
+  int v373; // eax@715
+  int v374; // eax@717
+  char *v375; // edi@717
+  int v376; // eax@717
+  Player *v377; // ecx@719
+  int v378; // ecx@721
+  int v379; // ecx@722
+  int v380; // eax@724
+  int v381; // edi@727
+  int v382; // ecx@727
+  Player *v383; // eax@728
+  int v384; // eax@733
+  int v385; // edi@736
+  signed int v386; // eax@736
+  Player *v387; // edi@738
+  int v388; // edi@740
+  unsigned __int16 v389; // ST1C_2@740
+  __int16 v390; // ST18_2@740
+  stru6 *v391; // eax@740
+  int v392; // ecx@742
+  int v393; // ecx@743
+  int v394; // ecx@744
+  int v395; // edi@747
+  int v396; // eax@752
+  int v397; // eax@757
+  int v398; // eax@757
+  int v399; // eax@757
+  char *v400; // esi@757
+  Game *v401; // ecx@759
+  __int16 v402; // ST1C_2@759
+  __int16 v403; // ST18_2@759
+  stru6 *v404; // eax@759
+  int v405; // ecx@761
+  int v406; // ecx@762
+  int v407; // edi@765
+  __int16 v408; // ST1C_2@769
+  __int16 v409; // ST18_2@769
+  stru6 *v410; // eax@769
+  int v411; // ecx@772
+  int v412; // ecx@773
+  int v413; // edi@775
+  __int16 v414; // ST1C_2@781
+  __int16 v415; // ST18_2@781
+  stru6 *v416; // eax@781
+  int v417; // eax@787
+  int v418; // ecx@789
+  __int16 v419; // ax@791
+  signed int v420; // eax@793
+  int v421; // edx@793
+  const char *v422; // eax@801
+  int v423; // ecx@808
+  int v424; // ecx@809
+  int v425; // eax@811
+  signed int v426; // eax@815
+  signed int v427; // eax@820
+  int v428; // ecx@825
+  int v429; // ecx@826
+  int v430; // eax@828
+  stru6 *v431; // eax@831
+  int v432; // eax@831
+  Actor *v433; // edi@832
+  int v434; // eax@833
+  int v435; // ecx@837
+  int v436; // ecx@838
+  __int16 v437; // ST1C_2@843
+  __int16 v438; // ST18_2@843
+  stru6 *v439; // eax@843
+  int v440; // eax@843
+  int v441; // eax@847
+  int v442; // ecx@850
+  int v443; // ecx@851
+  int v444; // eax@853
+  signed int v445; // edi@857
+  int v446; // ecx@862
+  LevelDecoration *v447; // edi@864
+  __int16 v448; // ax@864
+  char *v449; // esi@870
+  int v450; // eax@870
+  int v451; // ecx@875
+  int v452; // ecx@876
+  int v453; // edi@878
+  __int16 v454; // ST1C_2@884
+  __int16 v455; // ST18_2@884
+  stru6 *v456; // eax@884
+  int v457; // ecx@887
+  int v458; // ecx@888
+  int v459; // eax@890
+  signed int v460; // eax@895
+  Actor *v461; // eax@897
+  unsigned __int16 v462; // cx@897
+  signed int v463; // edx@897
+  int v464; // ecx@905
+  int v465; // ecx@906
+  int v466; // edi@909
+  __int16 v467; // ST1C_2@913
+  __int16 v468; // ST18_2@913
+  stru6 *v469; // eax@913
+  int v470; // edi@913
+  int v471; // eax@917
+  int v472; // eax@917
+  char *v473; // esi@918
+  __int16 v474; // ST18_2@920
+  stru6 *v475; // eax@920
+  __int16 v476; // ST18_2@920
+  stru6 *v477; // eax@920
+  __int16 v478; // ST18_2@920
+  stru6 *v479; // eax@920
+  __int16 v480; // ST18_2@920
+  stru6 *v481; // eax@920
+  __int16 v482; // ST18_2@923
+  stru6 *v483; // eax@923
+  __int16 v484; // ST18_2@923
+  stru6 *v485; // eax@923
+  __int16 v486; // ST18_2@923
+  stru6 *v487; // eax@923
+  __int16 v488; // ST18_2@923
+  stru6 *v489; // eax@923
+  __int16 v490; // ST1C_2@924
+  __int16 v491; // ST18_2@924
+  stru6 *v492; // eax@924
+  int v493; // ecx@925
+  int v494; // ecx@926
+  __int16 v495; // ST1C_2@931
+  __int16 v496; // ST18_2@931
+  stru6 *v497; // eax@931
+  int v498; // edi@931
+  int v499; // eax@935
+  int v500; // eax@935
+  Player *v501; // edi@939
+  __int16 v502; // ST18_2@940
+  stru6 *v503; // eax@940
+  stru6 *v504; // eax@943
+  int v505; // eax@943
+  int v506; // eax@943
+  int v507; // edi@944
+  int v508; // eax@944
+  signed int v509; // eax@944
+  signed int v510; // edi@944
+  Actor *v511; // edi@946
+  int v512; // eax@946
+  SpellBuff *v513; // edi@946
+  int v514; // ecx@950
+  int v515; // ecx@951
+  int v516; // eax@953
+  int v517; // eax@956
+  char *v518; // edx@957
+  __int16 v519; // cx@958
+  int v520; // ecx@968
+  int v521; // ecx@969
+  int v522; // eax@971
+  __int16 v523; // ST18_2@975
+  stru6 *v524; // eax@975
+  __int16 v525; // ST18_2@975
+  stru6 *v526; // eax@975
+  __int16 v527; // ST18_2@975
+  stru6 *v528; // eax@975
+  __int16 v529; // ST18_2@975
+  stru6 *v530; // eax@975
+  int v531; // eax@982
+  int v532; // eax@982
+  int v533; // edi@983
+  int v534; // eax@983
+  signed int v535; // eax@983
+  signed int v536; // edi@983
+  stru6 *v537; // eax@984
+  int v538; // ecx@985
+  int v539; // ecx@986
+  int v540; // eax@988
+  __int16 v541; // ST18_2@991
+  stru6 *v542; // eax@991
+  __int16 v543; // ST18_2@991
+  stru6 *v544; // eax@991
+  __int16 v545; // ST18_2@991
+  stru6 *v546; // eax@991
+  __int16 v547; // ST18_2@991
+  stru6 *v548; // eax@991
+  double v549; // st7@991
+  unsigned __int16 v550; // di@991
+  int v551; // ecx@993
+  int v552; // ecx@994
+  char *v553; // edi@1001
+  __int16 v554; // ST18_2@1002
+  stru6 *v555; // eax@1002
+  __int16 v556; // ST18_2@1002
+  stru6 *v557; // eax@1002
+  __int16 v558; // ST18_2@1002
+  stru6 *v559; // eax@1002
+  __int16 v560; // ST18_2@1002
+  stru6 *v561; // eax@1002
+  unsigned __int16 v562; // di@1005
+  signed int v563; // eax@1010
+  unsigned int v564; // ecx@1011
+  signed int v565; // eax@1012
+  Player **v566; // ecx@1012
+  int v567; // eax@1012
+  unsigned __int16 v568; // ST1C_2@1012
+  __int16 v569; // ST18_2@1012
+  stru6 *v570; // eax@1012
+  Player *v571; // eax@1013
+  char *v572; // ecx@1013
+  int v573; // ecx@1017
+  int v574; // ecx@1018
+  int v575; // eax@1020
+  signed int v576; // eax@1025
+  Player *v577; // eax@1026
+  int v578; // eax@1028
+  __int16 v579; // ax@1029
+  int v580; // eax@1031
+  int v581; // edi@1031
+  int v582; // eax@1031
+  __int16 v583; // ST1C_2@1034
+  __int16 v584; // ST18_2@1034
+  char *v585; // esi@1034
+  stru6 *v586; // eax@1034
+  signed int v587; // eax@1035
+  int v588; // ecx@1036
+  int v589; // ecx@1037
+  int v590; // ecx@1038
+  char v591; // al@1048
+  int v592; // esi@1052
+  int v593; // ecx@1057
+  int v594; // ecx@1058
+  int v595; // eax@1064
+  int v596; // esi@1066
+  unsigned int v597; // edi@1067
+  int v598; // eax@1079
+  signed int v599; // eax@1082
+  int v600; // edi@1086
+  int v601; // edx@1086
+  int v602; // eax@1086
+  int v603; // ecx@1086
+  int v604; // eax@1087
+  char *v605; // eax@1089
+  int v606; // edx@1091
+  int v607; // ecx@1100
+  __int16 v608; // ax@1102
+  signed int v609; // eax@1104
+  int v610; // edi@1106
+  unsigned int v611; // eax@1106
+  char *v612; // edi@1106
+  char *v613; // eax@1108
+  int v614; // eax@1116
+  int v615; // edi@1119
+  __int16 v616; // ST1C_2@1122
+  __int16 v617; // ST18_2@1122
+  stru6 *v618; // eax@1122
+  SpellBuff *v619; // edi@1123
+  unsigned __int16 v620; // ST1C_2@1124
+  __int16 v621; // ST18_2@1124
+  stru6 *v622; // eax@1124
+  signed __int64 v623; // qax@1127
+  int v624; // eax@1127
+  int v625; // edi@1129
+  int v626; // eax@1129
+  signed int v627; // eax@1129
+  signed int v628; // edi@1129
+  int v629; // ecx@1130
+  Player *v630; // eax@1131
+  int v631; // eax@1137
+  int v632; // edi@1140
+  Player *v633; // eax@1140
+  signed int v634; // eax@1140
+  int v635; // edi@1142
+  unsigned __int16 v636; // ST1C_2@1142
+  __int16 v637; // ST18_2@1142
+  stru6 *v638; // eax@1142
+  stru6 *v639; // eax@1143
+  int v640; // ecx@1146
+  int v641; // ecx@1147
+  int v642; // edi@1156
+  int v643; // eax@1156
+  int v644; // eax@1156
+  signed int v645; // eax@1158
+  Player *v646; // ebx@1169
+  int v647; // edi@1169
+  signed int v648; // ST1C_4@1170
+  Player *v649; // ecx@1170
+  unsigned __int64 v650; // [sp-10h] [bp-E94h]@103
+  unsigned __int16 v651; // [sp-8h] [bp-E8Ch]@100
+  unsigned __int16 v652; // [sp-8h] [bp-E8Ch]@304
+  unsigned __int16 v653; // [sp-4h] [bp-E88h]@100
+  int v654; // [sp-4h] [bp-E88h]@124
+  unsigned __int16 v655; // [sp-4h] [bp-E88h]@304
+  unsigned int v656; // [sp-4h] [bp-E88h]@639
+  int v657; // [sp-4h] [bp-E88h]@807
+  int v658; // [sp+0h] [bp-E84h]@100
+  int v659; // [sp+0h] [bp-E84h]@123
+  int v660; // [sp+0h] [bp-E84h]@146
+  Actor *v661; // [sp+0h] [bp-E84h]@164
+  int v662; // [sp+0h] [bp-E84h]@304
+  unsigned __int64 v663; // [sp+0h] [bp-E84h]@639
+  const char *v664; // [sp+0h] [bp-E84h]@802
+  int v665; // [sp+0h] [bp-E84h]@807
+  int v666; // [sp+4h] [bp-E80h]@12
+  enum PLAYER_SKILL_TYPE v667; // [sp+4h] [bp-E80h]@25
+  unsigned __int8 v668; // [sp+4h] [bp-E80h]@100
+  int v669; // [sp+4h] [bp-E80h]@123
+  Vec3_int_ *v670; // [sp+4h] [bp-E80h]@133
+  int v671; // [sp+4h] [bp-E80h]@146
+  unsigned int v672; // [sp+4h] [bp-E80h]@164
+  unsigned __int8 v673; // [sp+4h] [bp-E80h]@304
+  __int16 v674; // [sp+4h] [bp-E80h]@684
+  const char *v675; // [sp+4h] [bp-E80h]@800
+  int v676; // [sp+4h] [bp-E80h]@807
+  int v677; // [sp+4h] [bp-E80h]@861
+  int v678; // [sp+4h] [bp-E80h]@997
+  int v679; // [sp+14h] [bp-E70h]@515
+  AIDirection a3; // [sp+C94h] [bp-1F0h]@21
+  int v681[4]; // [sp+CB0h] [bp-1D4h]@1137
+  int v682[4]; // [sp+CC0h] [bp-1C4h]@731
+  ItemGen v683; // [sp+CD0h] [bp-1B4h]@791
+  int v684; // [sp+D04h] [bp-180h]@416
+  unsigned __int64 v685; // [sp+D08h] [bp-17Ch]@416
+  int x; // [sp+D20h] [bp-164h]@327
+  unsigned __int64 v687; // [sp+D24h] [bp-160h]@327
+  int v688; // [sp+D2Ch] [bp-158h]@943
+  int v689; // [sp+D30h] [bp-154h]@943
+  int v690; // [sp+D34h] [bp-150h]@943
+  int v691; // [sp+D38h] [bp-14Ch]@137
+  int v692; // [sp+D3Ch] [bp-148h]@137
+  int v693; // [sp+D40h] [bp-144h]@137
+  int v694; // [sp+D44h] [bp-140h]@982
+  int v695; // [sp+D48h] [bp-13Ch]@982
+  int v696; // [sp+D4Ch] [bp-138h]@982
+  int v697; // [sp+D50h] [bp-134h]@129
+  int v698; // [sp+D54h] [bp-130h]@129
+  int v699; // [sp+D58h] [bp-12Ch]@129
+  Vec3_int_ v700; // [sp+D5Ch] [bp-128h]@339
+  int v701; // [sp+D68h] [bp-11Ch]@286
+  int v702; // [sp+D6Ch] [bp-118h]@286
+  int v703; // [sp+D70h] [bp-114h]@286
+  int v704; // [sp+D74h] [bp-110h]@132
+  int v705; // [sp+D78h] [bp-10Ch]@132
+  int v706; // [sp+D7Ch] [bp-108h]@132
+  int v707; // [sp+D80h] [bp-104h]@1127
+  int v708; // [sp+D84h] [bp-100h]@1127
+  int v709; // [sp+D88h] [bp-FCh]@1127
+  char v710; // [sp+D8Ch] [bp-F8h]@1156
+  stru277 *v711; // [sp+D90h] [bp-F4h]@1
+  __int64 v712; // [sp+D94h] [bp-F0h]@991
+  int v713; // [sp+D9Ch] [bp-E8h]@324
+  int n; // [sp+DA0h] [bp-E4h]@1
+  AIDirection v715; // [sp+DA4h] [bp-E0h]@21
+  int v716; // [sp+DC0h] [bp-C4h]@272
+  __int64 v717; // [sp+DC4h] [bp-C0h]@271
+  float v718; // [sp+DCCh] [bp-B8h]@176
+  signed int sRecoveryTime; // [sp+DD0h] [bp-B4h]@53
+  char *y; // [sp+DD4h] [bp-B0h]@325
+  int v721; // [sp+DD8h] [bp-ACh]@163
+  //LayingItem a1; // [sp+DDCh] [bp-A8h]@1
+  int v723; // [sp+E4Ch] [bp-38h]@1
+  ItemGen *_this; // [sp+E50h] [bp-34h]@23
+  float v725; // [sp+E54h] [bp-30h]@23
+  Player *v726; // [sp+E58h] [bp-2Ch]@131
+  float v727; // [sp+E5Ch] [bp-28h]@1
+  unsigned int uRequiredMana; // [sp+E60h] [bp-24h]@53
+  Player *pPlayer; // [sp+E64h] [bp-20h]@8
+  int v730; // [sp+E68h] [bp-1Ch]@53
+  int v731; // [sp+E6Ch] [bp-18h]@48
+  signed int v732; // [sp+E70h] [bp-14h]@325
+  unsigned __int64 v733; // [sp+E74h] [bp-10h]@1
+  signed int a2; // [sp+E7Ch] [bp-8h]@14
+  int amount; // [sp+E80h] [bp-4h]@1
+
+  auto ecx0 = this;
+
+  v711 = ecx0;
+
+  LayingItem a1; // [sp+DDCh] [bp-A8h]@1
+  //LayingItem::LayingItem(&a1);
+
+  v1 = 0;
+  v2 = 0;
+  amount = 0;
+  LODWORD(v733) = 0;
+  v723 = 0;
+  v727 = 0.0;
+  n = 0;
+  while ( 1 )
+  {
+    v3 = &v711[n];
+    HIDWORD(v733) = (int)v3;
+    if ( v3->spellnum == (short)v1 )
+      goto LABEL_1166;
+    if ( pParty->pPartyBuffs[11].NotExpired() )
+      pParty->pPartyBuffs[11].Reset();
+    if ( v3->field_8 & 0x3CA )
+    {
+      if ( !pParty->pPlayers[v3->uPlayerID].CanAct() )
+        v711->_427D48(1u);
+      goto LABEL_1166;
+    }
+    pPlayer = &pParty->pPlayers[v3->uPlayerID];
+    v4 = *(int *)&v3->field_C;
+    if ( v4 != v1 )
+      goto LABEL_18;
+    v5 = v3->spellnum;
+    if ( v3->spellnum == 79 || v5 == 48 || v5 == 94 )
+      v666 = 1;
+    else
+      v666 = v1;
+    a2 = stru_50C198.FindClosesActor(5120, 1, v666);
+    v6 = pMouse->uPointingObjectID;
+    if ( pMouse->uPointingObjectID != v1 && (v6 & 7) == 3 && pActors[v6 >> 3].CanAct() )
+    {
+      v4 = pMouse->uPointingObjectID;
+LABEL_18:
+      a2 = v4;
+    }
+    a1.uItemType = stru_4E3ACC[v3->spellnum].uItemType;
+    if ( (short)a1.uItemType != (short)v1 )
+    {
+      if ( (a2 & 7) == 3 )
+      {
+        memcpy(&v715, Actor::GetDirectionInfo((8 * v3->uPlayerID + 8) | 4, a2, &a3, 0), sizeof(v715));
+        v2 = v723;
+        v1 = 0;
+      }
+      else
+      {
+        v715.uYawAngle = pParty->sRotationY;
+        v715.uPitchAngle = pParty->sRotationX;
+      }
+    }
+    v7 = v3->field_A;
+    LODWORD(v725) = v1;
+    _this = (ItemGen *)v1;
+    if ( v7 == (short)v1 )
+    {
+      v8 = v3->spellnum;
+      if ( v3->spellnum >= 12 )
+      {
+        if ( v8 >= 23 )
+        {
+          if ( v8 >= 34 )
+          {
+            if ( v8 >= 45 )
+            {
+              if ( v8 >= 56 )
+              {
+                if ( v8 >= 67 )
+                {
+                  if ( v8 >= 78 )
+                  {
+                    if ( v8 >= 89 )
+                    {
+                      if ( v8 >= 100 )
+                      {
+                        if ( v8 != 100 )
+                        {
+LABEL_45:
+                          HIWORD(v10) = HIWORD(pPlayer);
+                          v11 = pPlayer->pActiveSkills[LODWORD(v725)];
+                          goto LABEL_47;
+                        }
+                        v667 = (PLAYER_SKILL_TYPE)5;
+                      }
+                      else
+                      {
+                        v667 = (PLAYER_SKILL_TYPE)20;
+                      }
+                    }
+                    else
+                    {
+                      v667 = (PLAYER_SKILL_TYPE)19;
+                    }
+                  }
+                  else
+                  {
+                    v667 = (PLAYER_SKILL_TYPE)18;
+                  }
+                }
+                else
+                {
+                  v667 = (PLAYER_SKILL_TYPE)17;
+                }
+              }
+              else
+              {
+                v667 = (PLAYER_SKILL_TYPE)16;
+              }
+            }
+            else
+            {
+              v667 = (PLAYER_SKILL_TYPE)15;
+            }
+          }
+          else
+          {
+            v667 = (PLAYER_SKILL_TYPE)14;
+          }
+        }
+        else
+        {
+          v667 = (PLAYER_SKILL_TYPE)13;
+        }
+      }
+      else
+      {
+        v667 = (PLAYER_SKILL_TYPE)12;
+      }
+      LODWORD(v725) = v667;
+      v9 = pPlayer->GetActualSkillLevel(v667);
+      v723 = v9 & 0x3F;
+      v2 = v9 & 0x3F;
+      goto LABEL_45;
+    }
+    v11 = v7;
+    v10 = v7 & 0x3F;
+    v723 = v10;
+    v2 = v10;
+LABEL_47:
+    if ( HIBYTE(v11) & 1 )
+    {
+      v12 = 4;
+      v731 = 4;
+    }
+    else
+    {
+      if ( (v11 & 0x80u) == 0 )
+      {
+        v10 = ((v11 & 0x40) != 0) + 1;
+        v731 = ((v11 & 0x40) != 0) + 1;
+      }
+      else
+      {
+        v731 = 3;
+      }
+      v12 = v731;
+    }
+    LOWORD(v10) = v3->spellnum;
+    v730 = v10;
+    v13 = v12 + 10 * (signed __int16)v10;
+    v14 = v3->field_A == (short)v1;
+    v15 = (unsigned __int16)word_4E3C66[v13];   // pSpellDatas [negoffset] indexing
+    v16 = *(unsigned __int16 *)((char *)&pSpellDatas[0].uMagisterLevelMana + v13 * 2);
+    uRequiredMana = v15;
+    sRecoveryTime = v16;
+    if ( !v14 )
+      uRequiredMana = v1;
+    if ( pParty->uCurrentHour == v1 )
+    {
+      if ( pParty->uCurrentMinute != v1 )
+        goto LABEL_62;
+      if ( LODWORD(v725) == 20 )
+        goto LABEL_61;
+    }
+    if ( pParty->uCurrentHour == 12 && pParty->uCurrentMinute == v1 && LODWORD(v725) == 19 )
+LABEL_61:
+      uRequiredMana = v1;
+LABEL_62:
+    if ( (signed __int16)v730 >= 100 || ((pPlayer->sMana - uRequiredMana) & 0x80000000u) == 0 )
+      break;
+    ShowStatusBarString(pGlobalTXT_LocalizationStrings[586], 2u);
+LABEL_203:
+    v3->spellnum = v1;
+LABEL_1166:
+    ++n;
+    if ( n >= 10 )
+      return;
+  }
+  if ( !pPlayer->pConditions[0] || (signed __int16)v730 >= 100 )
+    goto LABEL_69;
+  if ( rand() % 100 >= 50 )
+  {
+    v12 = v731;
+LABEL_69:
+    switch ( v3->spellnum )
+    {
+      case 100:
+      case 101:
+        v17 = pPlayer;
+        _this = (ItemGen *)1;
+        if ( (signed int)SkillToMastery(pPlayer->pActiveSkills[5]) >= 3 )
+          _this = (ItemGen *)2;
+        sRecoveryTime = v17->GetAttackRecoveryTime(1);
+        a1.stru_24.Reset();
+        v18 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_48 = v18;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        if ( v17->WearsItem(510, 2) )
+          a1.uObjectDescID = pObjectList->ObjectIDByItemID(0xBD6u);
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.uAttributes = 0;
+        a1.uSpriteFrameID = 0;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+        v19 = 8 * v3->uPlayerID;
+        LOBYTE(v19) = v19 | 4;
+        a1.field_58 = v19;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uFacing = LOWORD(v715.uYawAngle);
+        a1.uSoundID = LOWORD(v3->field_10);
+        v20 = (char *)&pParty->pPlayers[v3->uPlayerID];
+        memcpy(&a1.stru_24, &v20[36 * *((int *)v20 + 1620) + 496], sizeof(a1.stru_24));
+        a1.uAttributes = 256;
+        if ( pParty->bTurnBasedModeOn == 1 )
+          a1.uAttributes = 260;
+        for ( i = 0; i < (signed int)this; ++i )
+        {
+          if ( i )
+            a1.vPosition.z += 32;
+          a1.uSectorID = pIndoor->GetSector(a1.vPosition.x, a1.vPosition.y, a1.vPosition.z);
+          if ( a1.Create(
+                 v715.uYawAngle,
+                 v715.uPitchAngle,
+                 pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                 v3->uPlayerID + 1) != -1
+            && pParty->bTurnBasedModeOn == 1 )
+            ++pTurnEngine->field_1C;
+        }
+        goto LABEL_83;
+      case 102:
+        sRecoveryTime = pPlayer->GetAttackRecoveryTime(0);
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v723;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.uAttributes = 0;
+        a1.uSpriteFrameID = 0;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
+        v22 = 8 * v3->uPlayerID;
+        LOBYTE(v22) = v22 | 4;
+        a1.field_58 = v22;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uFacing = LOWORD(v715.uYawAngle);
+        a1.uSoundID = LOWORD(v3->field_10);
+        memcpy(
+          &a1.stru_24,
+          &pParty->pPlayers[v3->uPlayerID].spellbook.pDarkSpellbook.bIsSpellAvailable[36
+                                                                         * pParty->pPlayers[v3->uPlayerID].pEquipment.uMainHand
+                                                                         + 5],
+          sizeof(a1.stru_24));
+        v23 = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, a1.vPosition.z);
+        HIBYTE(a1.uAttributes) |= 1u;
+        a1.uSectorID = v23;
+        if ( pParty->bTurnBasedModeOn == 1 )
+          LOBYTE(a1.uAttributes) |= 4u;
+        if ( a1.Create(
+               v715.uYawAngle,
+               v715.uPitchAngle,
+               pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+               v3->uPlayerID + 1) != -1
+          && pParty->bTurnBasedModeOn == 1 )
+          ++pTurnEngine->field_1C;
+        goto LABEL_83;
+      case 1:
+        LODWORD(v733) = 3600 * v2;
+        v24 = v12 - 2;
+        if ( v24 )
+        {
+          v25 = v24 - 1;
+          if ( v25 && v25 != 1 )
+            amount = 2;
+          else
+            amount = 4;
+        }
+        else
+        {
+          amount = 3;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v668 = v1;
+        v658 = v1;
+        v653 = amount;
+        v651 = v731;
+        v26 = (signed __int64)((double)(signed int)v733 * 4.2666669);
+        v27 = (char *)&pParty->pPartyBuffs[16];
+        goto LABEL_101;
+      case 7:
+        v29 = v12 - 2;
+        if ( v29 )
+        {
+          v30 = v29 - 1;
+          if ( v30 )
+          {
+            if ( v30 == 1 )
+              amount = 9;
+            else
+              amount = 3;
+          }
+          else
+          {
+            amount = 7;
+          }
+        }
+        else
+        {
+          amount = 5;
+        }
+        v31 = v3->uPlayerID;
+        HIDWORD(v733) = v1;
+        v32 = 8 * v31;
+        LOBYTE(v32) = v32 | 4;
+        if ( (signed int)uNumLayingItems > v1 )
+        {
+          v33 = (char *)&pLayingItems[0].field_48;
+          v730 = uNumLayingItems;
+          do
+          {
+            if ( *((short *)v33 - 36) != (short)v1 && *(int *)v33 == 7 && *((int *)v33 + 4) == v32 )
+              ++HIDWORD(v733);
+            v33 += 112;
+            --v730;
+          }
+          while ( v730 );
+        }
+        if ( SHIDWORD(v733) > amount )
+          goto LABEL_200;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.uAttributes = v1;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+        a1.uSectorID = pIndoor->GetSector(
+                         pParty->vPosition.x,
+                         pParty->vPosition.y,
+                         pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
+        a1.uSpriteFrameID = v1;
+        v34 = 8 * v3->uPlayerID;
+        LOBYTE(v34) = v34 | 4;
+        a1.field_58 = v34;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uFacing = LOWORD(v715.uYawAngle);
+        a1.uSoundID = LOWORD(v3->field_10);
+        if ( pParty->bTurnBasedModeOn == 1 )
+          LOBYTE(a1.uAttributes) |= 4u;
+        v669 = v3->uPlayerID + 1;
+        v659 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
+        v35 = pParty->sRotationX + 10;
+        goto LABEL_124;
+      case 20:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( a2 == v1 )
+          goto LABEL_200;
+        if ( (a2 & 7) != 3 )
+          goto LABEL_1056;
+        v699 = v1;
+        v698 = v1;
+        v697 = v1;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v37 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        v37 *= 8;
+        LOBYTE(v37) = v37 | 4;
+        a1.uFacing = v1;
+        a1.field_58 = v37;
+        v38 = a2 >> 3;
+        a1.uSoundID = LOWORD(v3->field_10);
+        v39 = a2 >> 3;
+        a1.vPosition.x = pActors[v39].vPosition.x;
+        v40 = pActors[v39].vPosition.y;
+        a1.vPosition.z = pActors[v39].vPosition.z;
+        v41 = 8 * (a2 >> 3);
+        a1.vPosition.y = v40;
+        LOBYTE(v41) = v41 | 3;
+        a1.field_5C = v41;
+        v42 = a1.Create(0, v1, v1, v1);
+        v43 = &v697;
+        goto LABEL_133;
+      case 44:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v726 = (Player *)(a2 >> 3);
+        HIDWORD(v733) = 836 * (a2 >> 3);
+        if ( !stru_50C198.GetMagicalResistance((Actor *)((char *)pActors + HIDWORD(v733)), 3u) )
+          goto LABEL_1056;
+        ((SpellBuff *)((char *)&pActors[0].pActorBuffs[10] + HIDWORD(v733)))->Apply(
+          pMiscTimer->uTotalGameTimeElapsed + 128,
+          v1,
+          v1,
+          v1,
+          v1);
+        v706 = v1;
+        v705 = v1;
+        v704 = v1;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v44 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        a1.uFacing = v1;
+        v44 *= 8;
+        LOBYTE(v44) = v44 | 4;
+        v38 = (signed int)v726;
+        a1.field_58 = v44;
+        a1.uSoundID = LOWORD(v3->field_10);
+        a1.vPosition.x = *(__int16 *)((char *)&pActors[0].vPosition.x + HIDWORD(v733));
+        v45 = *(__int16 *)((char *)&pActors[0].vPosition.y + HIDWORD(v733));
+        a1.vPosition.z = *(__int16 *)((char *)&pActors[0].vPosition.z + HIDWORD(v733));
+        v46 = 8 * (int)v726;
+        a1.vPosition.y = v45;
+        LOBYTE(v46) = 8 * (char)v726 | 3;
+        a1.field_5C = v46;
+        v42 = a1.Create(0, v1, v1, v1);
+        v43 = &v704;
+LABEL_133:
+        v670 = (Vec3_int_ *)v43;
+        v47 = v38;
+        goto LABEL_139;
+      case 79:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) || a2 == v1 || (a2 & 7) != 3 )
+          goto LABEL_83;
+        v730 = a2 >> 3;
+        v693 = v1;
+        HIDWORD(v733) = (int)&pActors[a2 >> 3];
+        v692 = v1;
+        v691 = v1;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.x = *(short *)(HIDWORD(v733) + 142);
+        a1.vPosition.y = *(short *)(HIDWORD(v733) + 144);
+        v48 = *(short *)(HIDWORD(v733) + 138);
+        a1.vPosition.z = *(short *)(HIDWORD(v733) + 138);
+        a1.uAttributes = v1;
+        a1.uSectorID = pIndoor->GetSector(a1.vPosition.x, a1.vPosition.y, v48);
+        a1.uSpriteFrameID = v1;
+        v49 = 8 * v3->uPlayerID;
+        LOBYTE(v49) = v49 | 4;
+        a1.field_58 = v49;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uFacing = LOWORD(v715.uYawAngle);
+        LOWORD(v49) = LOWORD(v3->field_10);
+        LOBYTE(a1.uAttributes) |= 0x80u;
+        a1.uSoundID = v49;
+        v726 = (Player *)a1.Create(0, v1, v1, v1);
+        if ( !MonsterStats::BelongsToSupertype(*(short *)(HIDWORD(v733) + 96), MONSTER_SUPERTYPE_UNDEAD) )
+          goto LABEL_200;
+        v47 = v730;
+        v670 = (Vec3_int_ *)&v691;
+        v42 = (signed int)v726;
+LABEL_139:
+        DamageMonsterFromParty(8 * v42 | 2, v47, v670);
+        goto LABEL_1056;
+      case 2:
+      case 6:
+      case 11:
+      case 18:
+      case 26:
+      case 32:
+      case 34:
+      case 37:
+      case 57:
+      case 65:
+      case 70:
+      case 78:
+      case 97:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.uAttributes = v1;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+        a1.uSectorID = pIndoor->GetSector(
+                         pParty->vPosition.x,
+                         pParty->vPosition.y,
+                         pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
+        a1.uSpriteFrameID = v1;
+        v50 = 8 * v3->uPlayerID;
+        LOBYTE(v50) = v50 | 4;
+        a1.field_58 = v50;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uFacing = LOWORD(v715.uYawAngle);
+        a1.uSoundID = LOWORD(v3->field_10);
+        if ( pParty->bTurnBasedModeOn == 1 )
+          LOBYTE(a1.uAttributes) |= 4u;
+        if ( v3->spellnum == 18 )
+          LOBYTE(a1.uAttributes) |= 0x40u;
+        goto LABEL_156;
+      case 29:
+      case 39:
+      case 76:
+      case 90:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        v51 = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
+        a1.vPosition.y = pParty->vPosition.y;
+        v671 = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
+        v660 = pParty->vPosition.y;
+        goto LABEL_153;
+      case 87:
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor
+          || uCurrentlyLoadedLevelType == LEVEL_Outdoor && (pParty->uCurrentHour < 5 || pParty->uCurrentHour >= 0x15) )
+          goto LABEL_200;
+        if ( pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_152;
+        goto LABEL_83;
+      case 81:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( a2 == v1
+          || (a2 & 7) != 3
+          || (v730 = a2 >> 3,
+              v721 = (int)&pActors[a2 >> 3],
+              !stru_50C198.GetMagicalResistance(&pActors[a2 >> 3], 9u)) )
+          goto LABEL_1056;
+        Actor::_403EB6(v730, 4u, 0x80u, (AIDirection *)v1);
+        v726 = (Player *)(23040 * v2);
+        v54 = (signed __int64)((double)(23040 * v2) * 0.033333335);
+        v55 = v721;
+        ((SpellBuff *)(v721 + 308))->Apply(pParty->uTimePlayed + (signed int)v54, v731, v1, v1, v1);
+        *(char *)(v55 + 38) |= 8u;
+        *(short *)(v55 + 148) = v1;
+        v672 = v1;
+        *(short *)(v55 + 150) = v1;
+        v661 = (Actor *)v55;
+        goto LABEL_165;
+      case 35:
+        if ( v12 == 2 )
+        {
+          v57 = 300 * v2;
+        }
+        else
+        {
+          if ( v12 == 3 )
+          {
+            amount = 4;
+            v57 = 300 * v2;
+            goto LABEL_174;
+          }
+          if ( v12 == 4 )
+          {
+            v57 = 300 * v2;
+            amount = 8;
+            goto LABEL_174;
+          }
+          v57 = 180 * v2;
+        }
+        amount = 2;
+LABEL_174:
+        LODWORD(v733) = v57;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( (a2 & 7) != 3
+          || (v721 = 836 * (a2 >> 3),
+              LODWORD(v718) = (int)(char *)pActors + v721,
+              !stru_50C198.GetMagicalResistance((Actor *)((char *)pActors + v721), 3u)) )
+          goto LABEL_1056;
+        v726 = (Player *)(23040 * v2);
+        v58 = (signed __int64)((double)(23040 * v2) * 0.033333335);
+        v59 = v721;
+        ((SpellBuff *)((char *)&pActors[0].pActorBuffs[7] + v721))->Apply(
+          pParty->uTimePlayed + (signed int)v58,
+          v731,
+          amount,
+          v1,
+          v1);
+        *((char *)&pActors[0].uAttributes + v59 + 2) |= 8u;
+        v672 = v1;
+        v661 = (Actor *)LODWORD(v718);
+        goto LABEL_165;
+      case 60:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v730 = 836 * (a2 >> 3);
+        if ( !stru_50C198.GetMagicalResistance((Actor *)((char *)pActors + v730), 7u) )
+          goto LABEL_1056;
+        LODWORD(v733) = 300 * v2;
+        if ( v731 == 2 )
+        {
+          LODWORD(v733) = 600 * v2;
+        }
+        else
+        {
+          if ( v731 == 3 )
+            LODWORD(v733) = 29030400;
+        }
+        ((SpellBuff *)((char *)&pActors[0].pActorBuffs[9] + v730))->Reset();
+        ((SpellBuff *)((char *)&pActors[0].pActorBuffs[12] + v730))->Reset();
+        v726 = (Player *)((int)v733 << 7);
+        ((SpellBuff *)((char *)&pActors[0].pActorBuffs[1] + v730))->Apply(
+          pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335),
+          v731,
+          v1,
+          v1,
+          v1);
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        v60 = pObjectList->ObjectIDByItemID(a1.uItemType);
+        v61 = v730;
+        goto LABEL_1086;
+      case 92:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        a1.stru_24.Reset();
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.uAttributes = v1;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+        a1.uSectorID = pIndoor->GetSector(
+                         pParty->vPosition.x,
+                         pParty->vPosition.y,
+                         pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
+        a1.uSpriteFrameID = v1;
+        v62 = 8 * v3->uPlayerID;
+        LOBYTE(v62) = v62 | 4;
+        a1.field_58 = v62;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uFacing = LOWORD(v715.uYawAngle);
+        a1.uSoundID = LOWORD(v3->field_10);
+        a1.field_50 = v731;
+        a1.field_48 = 3;
+        a1.field_4C = 300 * v2;
+        goto LABEL_154;
+      case 4:
+        v63 = v12 - 1;
+        if ( !v63 )
+        {
+          amount = 10;
+          goto LABEL_195;
+        }
+        v64 = v63 - 1;
+        if ( !v64 )
+        {
+          amount = 11;
+          goto LABEL_195;
+        }
+        v65 = v64 - 1;
+        if ( !v65 )
+        {
+          amount = 12;
+LABEL_195:
+          LODWORD(v733) = 3600 * v2;
+          goto LABEL_196;
+        }
+        if ( v65 == 1 )
+        {
+          LODWORD(v733) = v1;
+          amount = 12;
+        }
+LABEL_196:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v730 = (int)&pParty->pPlayers[v3->uPlayerID_2].pInventoryItems[a2];
+        v726 = (Player *)&pItemsTable->pItems[*(int *)v730].pIconName;
+        ((ItemGen *)v730)->UpdateTempBonus(pParty->uTimePlayed);
+        if ( *(int *)v730 < 64 || *(int *)v730 > 65 )
+        {
+          if ( !(*(char *)(v730 + 20) & 2) )
+          {
+            if ( *(int *)(v730 + 12) == v1 )
+            {
+              if ( *(int *)(v730 + 4) == v1 )
+              {
+                v68 = BYTE4(v726->pConditions[3]);
+                if ( !v68 || v68 == 1 || v68 == 2 )
+                {
+                  if ( !pItemsTable->_456D5E_is_some_material((ItemGen *)v730) )
+                  {
+                    v69 = v730;
+                    v14 = v731 == 4;
+                    *(int *)(v730 + 12) = amount;
+                    if ( !v14 )
+                    {
+                      v726 = (Player *)((int)v733 << 7);
+                      *(_QWORD *)(v69 + 28) = pParty->uTimePlayed
+                                            + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7)
+                                                                         * 0.033333335);
+                      *(int *)(v69 + 20) |= 8u;
+                    }
+                    *(int *)(v69 + 20) |= 0x10u;
+LABEL_1055:
+                    dword_50C9A8 = 256;
+LABEL_1056:
+                    LODWORD(v727) = 1;
+LABEL_83:
+                    if ( v3->field_8 & 0x20 )
+                    {
+LABEL_1162:
+                      if ( v727 != 0.0 )
+                        pAudioPlayer->PlaySound(
+                          (SoundID)word_4EE088_sound_ids[v3->spellnum],
+                          0,
+                          0,
+                          -1,
+                          0,
+                          v3->field_10,
+                          0,
+                          0);
+                    }
+                    else
+                    {
+                      if ( sRecoveryTime < 0 )
+                        sRecoveryTime = 0;
+                      if ( pParty->bTurnBasedModeOn )
+                      {
+                        v645 = sRecoveryTime;
+                        pParty->pTurnBasedPlayerRecoveryTimes[v3->uPlayerID] = sRecoveryTime;
+                        pPlayer->SetRecoveryTime(v645);
+                        if ( !some_active_character )
+                          pTurnEngine->_40471C();
+                      }
+                      else
+                      {
+                        pPlayer->SetRecoveryTime(
+                          (signed __int64)(flt_6BE3A4_debug_recmod1 * (double)sRecoveryTime * 2.133333333333333));
+                      }
+                      if ( v727 != 0.0 )
+                      {
+                        pPlayer->PlaySound(49, 0);
+                        goto LABEL_1162;
+                      }
+                    }
+                    v3->spellnum = 0;
+                    v1 = 0;
+LABEL_1165:
+                    v2 = v723;
+                    goto LABEL_1166;
+                  }
+                }
+              }
+            }
+          }
+        }
+LABEL_199:
+        dword_50C9D0 = 113;
+        dword_50C9D4 = v1;
+        dword_50C9D8 = 1;
+LABEL_200:
+        v66 = pGlobalTXT_LocalizationStrings[428];
+LABEL_201:
+        v67 = 2;
+LABEL_202:
+        ShowStatusBarString(v66, v67);
+        pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, v1, v1, -1, v1, v1, v1, v1);
+        goto LABEL_203;
+      case 71:
+        v70 = v12 - 1;
+        LODWORD(v733) = 3600 * v2;
+        if ( v70 && (v71 = v70 - 1) != 0 )
+        {
+          v72 = v71 - 1;
+          if ( v72 )
+          {
+            if ( v72 == 1 )
+              amount = 10;
+          }
+          else
+          {
+            amount = 3;
+          }
+        }
+        else
+        {
+          amount = 1;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v73 = v3->uPlayerID_2;
+        v74 = v3->spellnum;
+        v75 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v74, v73);
+        v668 = v1;
+        v658 = v1;
+        v653 = amount;
+        v651 = v731;
+        v28 = pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)v733 * 4.2666669);
+        v27 = (char *)&pParty->pPlayers[v3->uPlayerID_2].pPlayerBuffs[12];
+        goto LABEL_103;
+      case 3:
+      case 14:
+      case 25:
+      case 36:
+      case 58:
+      case 69:
+        v76 = v12 - 1;
+        LODWORD(v733) = 3600 * v2;
+        if ( v76 )
+        {
+          v77 = v76 - 1;
+          if ( v77 )
+          {
+            v78 = v77 - 1;
+            if ( v78 )
+            {
+              if ( v78 != 1 )
+                goto LABEL_232;
+              v79 = 4 * v2;
+            }
+            else
+            {
+              v79 = 3 * v2;
+            }
+          }
+          else
+          {
+            v79 = 2 * v2;
+          }
+          amount = v79;
+        }
+        else
+        {
+          amount = v2;
+        }
+LABEL_232:
+        v80 = v3->spellnum;
+        switch ( v80 )
+        {
+          case 3:
+            LODWORD(v725) = 6;
+            break;
+          case 14:
+            LODWORD(v725) = v1;
+            break;
+          case 25:
+            LODWORD(v725) = 17;
+            break;
+          case 36:
+            LODWORD(v725) = 4;
+            break;
+          case 58:
+            LODWORD(v725) = 12;
+            break;
+          default:
+            if ( v80 != 69 )
+              goto LABEL_1166;
+            LODWORD(v725) = 1;
+            break;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v81 = v3->spellnum;
+        v82 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v81, v1);
+        v83 = 1;
+        v84 = v3->spellnum;
+        v85 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v84, 1u);
+        v86 = v3->spellnum;
+        v87 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v86, 2u);
+        v88 = v3->spellnum;
+        v89 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v88, 3u);
+        v90 = (double)(signed int)v733 * 4.2666669;
+        goto LABEL_304;
+      case 5:
+        if ( v12 <= v1 )
+          goto LABEL_254;
+        if ( v12 <= 2 )
+        {
+          v91 = 60 * (v2 + 60);
+        }
+        else
+        {
+          if ( v12 == 3 )
+          {
+            v91 = 180 * (v2 + 20);
+          }
+          else
+          {
+            if ( v12 != 4 )
+              goto LABEL_254;
+            v91 = 240 * (v2 + 15);
+          }
+        }
+        LODWORD(v733) = v91;
+LABEL_254:
+        if ( pPlayer->CanCastSpell(uRequiredMana) )
+        {
+          v92 = (char *)&pParty->pPlayers[0].pConditions[1];
+          LODWORD(v727) = 1;
+          do
+          {
+            if ( *(_QWORD *)v92 )
+              LODWORD(v727) = v1;
+            v92 += 6972;
+          }
+          while ( (signed int)v92 < (signed int)&pParty->pHirelings[0].uFlags );
+          if ( LODWORD(v727) != v1 )
+          {
+            v726 = (Player *)((int)v733 << 7);
+            pParty->pPartyBuffs[8].Apply(
+              pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335),
+              v731,
+              v1,
+              v1,
+              v1);
+            v93 = v3->spellnum;
+            v94 = pGame->GetStru6();
+            pGame->GetStru6()->SetPlayerBuffAnim(v93, v1);
+            v95 = v3->spellnum;
+            v96 = pGame->GetStru6();
+            pGame->GetStru6()->SetPlayerBuffAnim(v95, 1u);
+            v97 = v3->spellnum;
+            v98 = pGame->GetStru6();
+            pGame->GetStru6()->SetPlayerBuffAnim(v97, 2u);
+            v99 = v3->spellnum;
+            v100 = pGame->GetStru6();
+            pGame->GetStru6()->SetPlayerBuffAnim(v99, 3u);
+          }
+        }
+        goto LABEL_83;
+      case 46:
+        v101 = v12 - 1;
+        if ( v101 && (v102 = v101 - 1) != 0 )
+        {
+          v103 = v102 - 1;
+          if ( v103 )
+          {
+            if ( v103 != 1 )
+              goto LABEL_269;
+            v104 = 3600 * (v2 + 1);
+          }
+          else
+          {
+            v104 = 900 * (v2 + 4);
+          }
+        }
+        else
+        {
+          v104 = 300 * (v2 + 12);
+        }
+        LODWORD(v733) = v104;
+LABEL_269:
+        amount = v2 + 5;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( v731 == 1 )
+        {
+          v108 = v3->uPlayerID_2;
+          v109 = v3->spellnum;
+          v110 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v109, v108);
+          v111 = pOtherOverlayList->_4418B1(10000, v3->uPlayerID_2 + 310, v1, 65536);
+          v668 = v1;
+          v716 = v111;
+          v658 = v111;
+          v653 = amount;
+          v726 = (Player *)((int)v733 << 7);
+          v651 = 1;
+          v28 = pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+          v27 = (char *)&pParty->pPlayers[v3->uPlayerID_2].pPlayerBuffs[1];
+          goto LABEL_103;
+        }
+        v105 = 0;
+        v726 = (Player *)((int)v733 << 7);
+        v717 = (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v730 = (int)&pParty->pPlayers[0].pPlayerBuffs[1];
+        do
+        {
+          v106 = v3->spellnum;
+          v107 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v106, v105);
+          v716 = pOtherOverlayList->_4418B1(10000, v105 + 310, v1, 65536);
+          ((SpellBuff *)v730)->Apply(pParty->uTimePlayed + v717, v731, amount, v716, v1);
+          v730 += 6972;
+          ++v105;
+        }
+        while ( v730 < (signed int)&pParty->field_871C[468] );
+        goto LABEL_1056;
+      case 52:
+        if ( pPlayer->CanCastSpell(uRequiredMana) && a2 != v1 && (a2 & 7) == 3 )
+        {
+          v730 = a2 >> 3;
+          v112 = &pActors[a2 >> 3];
+          v726 = (Player *)abs(v112->vPosition.z - pParty->vPosition.z);
+          v721 = abs(v112->vPosition.y - pParty->vPosition.y);
+          v113 = abs(v112->vPosition.x - pParty->vPosition.x);
+          _this = (ItemGen *)v113;
+          v114 = v721;
+          v115 = (unsigned int)v726;
+          if ( v113 < v721 )
+          {
+            v116 = v113;
+            v113 = v721;
+            v114 = v116;
+          }
+          if ( v113 < (signed int)v726 )
+          {
+            v117 = v113;
+            v113 = (int)v726;
+            v115 = v117;
+          }
+          if ( v114 < (signed int)v115 )
+          {
+            v118 = v115;
+            v115 = v114;
+            v114 = v118;
+          }
+          _this = (ItemGen *)(((unsigned int)(11 * v114) >> 5) + (v115 >> 2) + v113);
+          if ( (double)(signed int)this <= 307.2 )
+          {
+            v703 = 0;
+            v702 = 0;
+            v701 = 0;
+            a1.stru_24.Reset();
+            v119 = HIDWORD(v733);
+            a1.field_48 = *(int *)HIDWORD(v733);
+            a1.field_4C = v723;
+            a1.field_50 = v731;
+            a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+            a1.uAttributes = 0;
+            a1.uSectorID = 0;
+            a1.uSpriteFrameID = 0;
+            v120 = 8 * *(short *)(v119 + 2);
+            LOBYTE(v120) = v120 | 4;
+            a1.field_60_distance_related_prolly_lod = 0;
+            a1.field_58 = v120;
+            a1.uFacing = 0;
+            a1.uSoundID = *(short *)(v119 + 16);
+            a1.vPosition.x = v112->vPosition.x;
+            a1.vPosition.y = v112->vPosition.y;
+            v726 = (Player *)v112->uActorHeight;
+            v121 = 8 * a2;
+            a1.vPosition.z = v112->vPosition.z - (unsigned int)(signed __int64)((double)(signed int)v726 * unk_4D8548);
+            LOBYTE(v121) = 8 * a2 | 3;
+            a1.field_5C = v121;
+            v122 = a1.Create(0, 0, 0, 0);
+            DamageMonsterFromParty(8 * v122 | 2, v730, (Vec3_int_ *)&v701);
+            LODWORD(v727) = 1;
+          }
+          else
+          {
+            ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2u);
+            pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, 0, 0, -1, 0, 0, 0, 0);
+            *(int *)HIDWORD(v733) = 0;
+          }
+          v3 = (stru277 *)HIDWORD(v733);
+        }
+        goto LABEL_83;
+      case 17:
+      case 38:
+      case 51:
+        v123 = v12 - 1;
+        if ( v123 && (v124 = v123 - 1) != 0 )
+        {
+          v125 = v124 - 1;
+          if ( v125 )
+          {
+            if ( v125 != 1 )
+              goto LABEL_296;
+            v126 = 3600 * (v2 + 1);
+          }
+          else
+          {
+            v126 = 900 * (v2 + 4);
+          }
+        }
+        else
+        {
+          v126 = 300 * (v2 + 12);
+        }
+        LODWORD(v733) = v126;
+LABEL_296:
+        v127 = v3->spellnum;
+        if ( v127 == 17 )
+        {
+          amount = v1;
+          LODWORD(v725) = 14;
+        }
+        else
+        {
+          if ( v127 == 38 )
+          {
+            LODWORD(v725) = 15;
+            amount = v2 + 5;
+          }
+          else
+          {
+            if ( v127 != 51 )
+              goto LABEL_1166;
+            LODWORD(v725) = 9;
+            amount = v2 + 5;
+          }
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v128 = v3->spellnum;
+        v129 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v128, v1);
+        v83 = 1;
+        v130 = v3->spellnum;
+        v131 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v130, 1u);
+        v132 = v3->spellnum;
+        v133 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v132, 2u);
+        v134 = v3->spellnum;
+        v135 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v134, 3u);
+        v726 = (Player *)((int)v733 << 7);
+        v90 = (double)(signed int)((int)v733 << 7) * 0.033333335;
+LABEL_304:
+        v673 = v1;
+        v662 = v1;
+        v655 = amount;
+        v652 = v731;
+        v136 = pParty->uTimePlayed + (signed int)(signed __int64)v90;
+        v137 = (char *)&pParty->pPartyBuffs[LODWORD(v725)];
+        goto LABEL_977;
+      case 8:
+        v138 = v12 - 2;
+        if ( v138 && (v139 = v138 - 1) != 0 && v139 == 1 )
+          v140 = 600 * v2;
+        else
+          v140 = 60 * v2;
+        LODWORD(v733) = v140;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v141 = v3->spellnum;
+        v142 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v141, v1);
+        v143 = v3->spellnum;
+        v144 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v143, 1u);
+        v145 = v3->spellnum;
+        v146 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v145, 2u);
+        v147 = v3->spellnum;
+        v148 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v147, 3u);
+        v668 = v1;
+        v726 = (Player *)((int)v733 << 7);
+        v658 = v1;
+        v653 = v2;
+        v651 = v731;
+        v26 = (signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v27 = (char *)&pParty->pPartyBuffs[10];
+        goto LABEL_102;
+      case 9:
+        v149 = v12 - 1;
+        if ( v149 && (v150 = v149 - 1) != 0 && (v151 = v150 - 1) != 0 )
+        {
+          if ( v151 == 1 )
+            _this = (ItemGen *)20;
+        }
+        else
+        {
+          _this = (ItemGen *)16;
+        }
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+        {
+          v66 = pGlobalTXT_LocalizationStrings[491];
+          goto LABEL_201;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        LODWORD(v725) = a2 & 7;
+        if ( (a2 & 7) == 3 )
+        {
+          v152 = a2 >> 3;
+          uRequiredMana = pActors[v152].vPosition.x;
+          v153 = pActors[v152].vPosition.y;
+          v154 = pActors[v152].vPosition.z;
+          LODWORD(v727) = v153;
+        }
+        else
+        {
+          v155 = stru_5C6E00->SinCos(pParty->sRotationY);
+          uRequiredMana = pParty->vPosition.x + sub_42EBBE(2048, v155);
+          v156 = stru_5C6E00->_42EBDB(pParty->sRotationY);
+          LODWORD(v727) = pParty->vPosition.y + sub_42EBBE(2048, v156);
+          v154 = pParty->vPosition.z;
+        }
+        HIDWORD(v733) = v154;
+        v713 = v154 + 2500;
+        v721 = v1;
+        LODWORD(v718) = v1;
+        if ( (signed int)this > v1 )
+        {
+          *(float *)&y = (double)SHIDWORD(v733);
+          *(float *)&v732 = (double)v713;
+          v730 = LODWORD(v725) == 3 ? a2 : 0;
+          v726 = (Player *)this;
+          do
+          {
+            v157 = rand();
+            v158 = (double)SLODWORD(v718);
+            v718 = v158;
+            v159 = (double)v721;
+            *(float *)&v721 = v159;
+            a2 = v157 % 1000;
+            *((float *)&v733 + 1) = (double)(v157 % 1000) + *(float *)&y - *(float *)&v732;
+            v725 = v159 * v159;
+            *(float *)&_this = v158 * v158;
+            if ( sqrt(*((float *)&v733 + 1) * *((float *)&v733 + 1) + *(float *)&_this + v725) <= 1.0 )
+            {
+              LODWORD(v687) = v1;
+              HIDWORD(v687) = v1;
+            }
+            else
+            {
+              x = (signed __int64)sqrt(*(float *)&_this + v725);
+              v687 = __PAIR__(
+                       stru_5C6E00->Atan2(x, (signed __int64)*((float *)&v733 + 1)),
+                       stru_5C6E00->Atan2((signed __int64)v718, (signed __int64)*(float *)&v721));
+            }
+            a1.stru_24.Reset();
+            a1.field_48 = v3->spellnum;
+            a1.field_4C = v2;
+            a1.field_50 = v731;
+            a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+            a1.uAttributes = v1;
+            a1.vPosition.x = uRequiredMana;
+            a1.vPosition.y = LODWORD(v727);
+            a1.uSectorID = v1;
+            a1.vPosition.z = a2 + v713;
+            a1.uSpriteFrameID = v1;
+            a1.field_58 = 8 * v3->uPlayerID | 4;
+            a1.field_5C = v730;
+            a1.field_60_distance_related_prolly_lod = stru_50C198._427546(a2 + 2500);
+            a1.uFacing = v687;
+            a1.uSoundID = LOWORD(v3->field_10);
+            if ( pParty->bTurnBasedModeOn == 1 )
+              a1.uAttributes = 4;
+            if ( a1.Create(
+                   v687,
+                   SHIDWORD(v687),
+                   pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                   v1) != -1
+              && pParty->bTurnBasedModeOn == 1 )
+              ++pTurnEngine->field_1C;
+            LODWORD(v718) = rand() % 1024 - 512;
+            v160 = rand();
+            v14 = v726 == (Player *)1;
+            v726 = (Player *)((char *)v726 - 1);
+            v721 = (unsigned __int64)(v160 % 1024) - 512;
+          }
+          while ( !v14 );
+        }
+        goto LABEL_1056;
+      case 10:
+        v67 = 2;
+        if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+        {
+          v66 = pGlobalTXT_LocalizationStrings[492];
+          goto LABEL_202;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v726 = (Player *)sub_46A6AC((int)dword_50BF30, 100, 4096);
+        v700.z = v1;
+        v700.y = v1;
+        v700.x = v1;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v161 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        a1.uFacing = v1;
+        v161 *= 8;
+        LOBYTE(v161) = v161 | 4;
+        a1.field_58 = v161;
+        a1.uSoundID = LOWORD(v3->field_10);
+        a2 = v1;
+        if ( (signed int)v726 > v1 )
+        {
+          do
+          {
+            v162 = dword_50BF30[a2];
+            a1.vPosition.x = pActors[v162].vPosition.x;
+            a1.vPosition.y = pActors[v162].vPosition.y;
+            v732 = pActors[v162].uActorHeight;
+            a1.vPosition.z = pActors[v162].vPosition.z - (unsigned int)(signed __int64)((double)v732 * unk_4D8548);
+            v163 = 8 * dword_50BF30[a2];
+            LOBYTE(v163) = v163 | 3;
+            a1.field_5C = v163;
+            v164 = a1.Create(0, v1, v1, v1);
+            v165 = a2;
+            DamageMonsterFromParty(8 * v164 | AI_OBJECT_LAYING_ITEM, dword_50BF30[a2], &v700);
+            v166 = pGame->GetStru6();
+            v166->_4A81CA(&a1);
+            v167 = pGame->GetStru6();
+            v167->FadeScreen__like_Turn_Undead_and_mb_Armageddon(0xFF3C1Eu, 0x40u);
+            a2 = v165 + 1;
+          }
+          while ( v165 + 1 < (signed int)v726 );
+        }
+        goto LABEL_1056;
+      case 12:
+        LODWORD(v733) = 3600 * v2;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v168 = 0;
+        do
+        {
+          v169 = pOtherOverlayList->_4418B1(2000, v168++ + 100, v1, 65536);
+          v716 = v169;
+        }
+        while ( v168 < 4 );
+        v668 = v1;
+        v732 = (int)v733 << 7;
+        v658 = v1;
+        v653 = v1;
+        v651 = v731;
+        v28 = pParty->uTimePlayed + (signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        goto LABEL_992;
+      case 13:
+        v170 = v12 - 1;
+        if ( !v170 )
+        {
+          v173 = 300 * v2;
+          goto LABEL_353;
+        }
+        v171 = v170 - 1;
+        if ( !v171 )
+        {
+          v173 = 600 * v2;
+          goto LABEL_353;
+        }
+        v172 = v171 - 1;
+        if ( !v172 || v172 == 1 )
+        {
+          v173 = 3600 * v2;
+LABEL_353:
+          LODWORD(v733) = v173;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v174 = 0;
+        do
+          pOtherOverlayList->_4418B1(2010, v174++ + 100, v1, 65536);
+        while ( v174 < 4 );
+        v175 = v3->spellnum;
+        v176 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v175, v1);
+        v83 = 1;
+        v177 = v3->spellnum;
+        v178 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v177, 1u);
+        v179 = v3->spellnum;
+        v180 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v179, 2u);
+        v181 = v3->spellnum;
+        v182 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v181, 3u);
+        v673 = v1;
+        v732 = (int)v733 << 7;
+        v662 = v1;
+        v655 = v1;
+        v652 = v731;
+        v183 = (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v137 = (char *)&pParty->pPartyBuffs[5];
+        goto LABEL_976;
+      case 15:
+        v184 = v12 - 1;
+        if ( v184 )
+        {
+          v185 = v184 - 1;
+          if ( v185 )
+          {
+            v186 = v185 - 1;
+            if ( v186 )
+            {
+              if ( v186 == 1 )
+                amount = 9;
+            }
+            else
+            {
+              amount = 7;
+            }
+          }
+          else
+          {
+            amount = 5;
+          }
+        }
+        else
+        {
+          amount = 3;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v726 = (Player *)((signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360);
+        v732 = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360 / (amount - 1);
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.uAttributes = v1;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+        a1.uSectorID = pIndoor->GetSector(
+                         pParty->vPosition.x,
+                         pParty->vPosition.y,
+                         pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
+        a1.uSpriteFrameID = v1;
+        v187 = 8 * v3->uPlayerID;
+        LOBYTE(v187) = v187 | 4;
+        a1.field_58 = v187;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uSoundID = LOWORD(v3->field_10);
+        if ( pParty->bTurnBasedModeOn == 1 )
+          LOBYTE(a1.uAttributes) |= 4u;
+        v188 = (signed int)v726 / -2;
+        v189 = (signed int)v726 / 2;
+        while ( v188 <= v189 )
+        {
+          a1.uFacing = v188 + LOWORD(v715.uYawAngle);
+          if ( a1.Create(
+                 (signed __int16)(v188 + LOWORD(v715.uYawAngle)),
+                 v715.uPitchAngle,
+                 pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                 v3->uPlayerID + 1) != -1
+            && pParty->bTurnBasedModeOn == 1 )
+            ++pTurnEngine->field_1C;
+          v188 += v732;
+        }
+        goto LABEL_1056;
+      case 16:
+        if ( pParty->uFlags & 8 )
+        {
+          v190 = pGlobalTXT_LocalizationStrings[493];
+          goto LABEL_462;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v191 = 0;
+        do
+          pOtherOverlayList->_4418B1(2040, v191++ + 100, v1, 65536);
+        while ( v191 < 4 );
+        BYTE1(pParty->uFlags) |= 1u;
+        pParty->uFallSpeed = 1000;
+        goto LABEL_1056;
+      case 19:
+        v192 = v12 - 1;
+        if ( !v192 )
+        {
+          amount = v2;
+          goto LABEL_391;
+        }
+        v193 = v192 - 1;
+        if ( !v193 )
+        {
+          v196 = 2 * v2;
+LABEL_389:
+          amount = v196;
+LABEL_391:
+          v195 = 600 * v2;
+          goto LABEL_392;
+        }
+        v194 = v193 - 1;
+        if ( !v194 )
+        {
+          v196 = 3 * v2;
+          goto LABEL_389;
+        }
+        if ( v194 != 1 )
+          goto LABEL_393;
+        amount = 4 * v2;
+        v195 = 3600 * v2;
+LABEL_392:
+        LODWORD(v733) = v195;
+LABEL_393:
+        if ( pParty->uFlags & 0x30 )
+        {
+          v66 = pGlobalTXT_LocalizationStrings[638];
+          goto LABEL_201;
+        }
+        if ( pPlayer->CanCastSpell(uRequiredMana) )
+        {
+          v197 = v3->spellnum;
+          v198 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v197, v1);
+          v83 = 1;
+          v199 = v3->spellnum;
+          v200 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v199, 1u);
+          v201 = v3->spellnum;
+          v202 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v201, 2u);
+          v203 = v3->spellnum;
+          v204 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v203, 3u);
+          v673 = v1;
+          v732 = (int)v733 << 7;
+          v662 = v1;
+          v655 = amount;
+          v652 = v731;
+          v183 = (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+          v137 = (char *)&pParty->pPartyBuffs[11];
+LABEL_976:
+          v136 = pParty->uTimePlayed + v183;
+LABEL_977:
+          ((SpellBuff *)v137)->Apply(v136, v652, v655, v662, v673);
+LABEL_978:
+          LODWORD(v727) = v83;
+        }
+        goto LABEL_83;
+      case 21:
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+        {
+          v190 = pGlobalTXT_LocalizationStrings[494];
+LABEL_462:
+          ShowStatusBarString(v190, 2u);
+          pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, v1, v1, -1, v1, v1, v1, v1);
+          goto LABEL_83;
+        }
+        if ( !pPlayers[v3->uPlayerID + 1]->GetMaxMana() )
+        {
+LABEL_461:
+          v190 = pGlobalTXT_LocalizationStrings[428];
+          goto LABEL_462;
+        }
+        LODWORD(v733) = 3600 * v2;
+        if ( v731 == 2 || v731 == 3 || (amount = v1, v731 != 4) )
+          amount = 1;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v205 = 0;
+        do
+          pOtherOverlayList->_4418B1(2090, v205++ + 100, v1, 65536);
+        while ( v205 < 4 );
+        v206 = pOtherOverlayList->_4418B1(10008, 203, v1, 65536);
+        v207 = v3->uPlayerID + 1;
+        v716 = v206;
+        v668 = v207;
+        v658 = v206;
+        v653 = amount;
+        v732 = (int)v733 << 7;
+        v651 = v731;
+        v26 = (signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v27 = (char *)&pParty->pPartyBuffs[7];
+LABEL_101:
+        v26 = (signed int)v26;
+LABEL_102:
+        v28 = pParty->uTimePlayed + v26;
+LABEL_103:
+        HIDWORD(v650) = HIDWORD(v28);
+LABEL_104:
+        LODWORD(v650) = v28;
+        ((SpellBuff *)v27)->Apply(v650, v651, v653, v658, v668);
+        goto LABEL_1056;
+      case 22:
+        v67 = 2;
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+        {
+          v66 = pGlobalTXT_LocalizationStrings[495];
+          goto LABEL_202;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v208 = a2 & 7;
+        LODWORD(v725) = a2 & 7;
+        if ( v208 == 3 )
+        {
+          v209 = a2 >> 3;
+          LODWORD(v718) = pActors[v209].vPosition.x;
+          v210 = pActors[v209].vPosition.y;
+          v211 = pActors[v209].vPosition.z;
+          v713 = v210;
+        }
+        else
+        {
+          v212 = stru_5C6E00->SinCos(pParty->sRotationY);
+          LODWORD(v718) = pParty->vPosition.x + sub_42EBBE(2048, v212);
+          v213 = stru_5C6E00->_42EBDB(pParty->sRotationY);
+          v214 = sub_42EBBE(2048, v213);
+          v211 = pParty->vPosition.z;
+          v713 = pParty->vPosition.y + v214;
+          v208 = LODWORD(v725);
+        }
+        v726 = (Player *)v211;
+        HIDWORD(v733) = v1;
+        *(float *)&v732 = (double)v211;
+        LODWORD(v725) = v211 + 2500;
+        v721 = v1;
+        *(float *)&y = (double)(v211 + 2500);
+        v730 = v208 == 3 ? a2 : 0;
+        a2 = 20;
+        do
+        {
+          v215 = rand();
+          v216 = (double)v721;
+          v727 = v216;
+          v217 = (double)SHIDWORD(v733);
+          *(float *)&uRequiredMana = v217;
+          _this = (ItemGen *)(v215 % 1000);
+          *((float *)&v733 + 1) = (double)(v215 % 1000) + *(float *)&v732 - *(float *)&y;
+          *(float *)&v721 = v217 * v217;
+          *(float *)&v726 = v216 * v216;
+          if ( sqrt(*((float *)&v733 + 1) * *((float *)&v733 + 1) + *(float *)&v726 + *(float *)&v721) <= 1.0 )
+          {
+            LODWORD(v685) = v1;
+            HIDWORD(v685) = v1;
+          }
+          else
+          {
+            v684 = (signed __int64)sqrt(*(float *)&v726 + *(float *)&v721);
+            v685 = __PAIR__(
+                     stru_5C6E00->Atan2(v684, (signed __int64)*((float *)&v733 + 1)),
+                     stru_5C6E00->Atan2((signed __int64)v727, (signed __int64)*(float *)&uRequiredMana));
+          }
+          a1.stru_24.Reset();
+          a1.field_48 = v3->spellnum;
+          a1.field_4C = v2;
+          a1.field_50 = v731;
+          a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+          a1.uAttributes = v1;
+          a1.vPosition.x = LODWORD(v718);
+          a1.vPosition.y = v713;
+          a1.uSectorID = v1;
+          a1.vPosition.z = (int)((char *)_this + LODWORD(v725));
+          a1.uSpriteFrameID = v1;
+          a1.field_58 = 8 * v3->uPlayerID | 4;
+          a1.field_5C = v730;
+          a1.field_60_distance_related_prolly_lod = stru_50C198._427546((int)&_this[69].uNumCharges);
+          a1.uFacing = v685;
+          a1.uSoundID = LOWORD(v3->field_10);
+          if ( pParty->bTurnBasedModeOn == 1 )
+            a1.uAttributes = 4;
+          if ( a1.Create(
+                 v685,
+                 SHIDWORD(v685),
+                 pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                 v1) != -1
+            && pParty->bTurnBasedModeOn == 1 )
+            ++pTurnEngine->field_1C;
+          v721 = rand() % 1024 - 512;
+          v218 = rand();
+          v14 = a2-- == 1;
+          HIDWORD(v733) = (unsigned __int64)(v218 % 1024) - 512;
+        }
+        while ( !v14 );
+        goto LABEL_1056;
+      case 23:
+        v219 = v12 - 2;
+        if ( v219 )
+        {
+          v220 = v219 - 1;
+          if ( v220 )
+          {
+            if ( v220 == 1 )
+            {
+              amount = v1;
+              goto LABEL_433;
+            }
+            v221 = 180 * v2;
+          }
+          else
+          {
+            v221 = 86400 * v2;
+          }
+        }
+        else
+        {
+          v221 = 3600 * v2;
+        }
+        amount = v221;
+LABEL_433:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v222 = (char *)pParty->pPlayers;
+        HIDWORD(v733) = (int)(char *)&pParty + 2508;
+        break;
+      case 24:
+        v224 = v12 - 2;
+        if ( v224 )
+        {
+          v225 = v224 - 1;
+          if ( v225 )
+          {
+            if ( v225 == 1 )
+              amount = 7;
+            else
+              amount = 1;
+          }
+          else
+          {
+            amount = 5;
+          }
+        }
+        else
+        {
+          amount = 3;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        HIDWORD(v733) = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
+        if ( amount == 1 )
+        {
+LABEL_152:
+          a1.stru_24.Reset();
+          a1.field_48 = v3->spellnum;
+          a1.field_50 = v731;
+          a1.field_4C = v2;
+          a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+          a1.vPosition.y = pParty->vPosition.y;
+          v51 = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+          v671 = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+          v660 = pParty->vPosition.y;
+LABEL_153:
+          a1.uAttributes = v1;
+          a1.vPosition.x = pParty->vPosition.x;
+          a1.vPosition.z = v51;
+          v52 = pIndoor->GetSector(pParty->vPosition.x, v660, v671);
+          a1.uSpriteFrameID = v1;
+          a1.uSectorID = v52;
+          v53 = 8 * v3->uPlayerID;
+          LOBYTE(v53) = v53 | 4;
+          a1.field_58 = v53;
+          a1.field_5C = a2;
+          a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+          a1.uFacing = LOWORD(v715.uYawAngle);
+          a1.uSoundID = LOWORD(v3->field_10);
+LABEL_154:
+          if ( pParty->bTurnBasedModeOn == 1 )
+            LOBYTE(a1.uAttributes) |= 4u;
+LABEL_156:
+          v669 = v3->uPlayerID + 1;
+          v36 = v715.uYawAngle;
+          v659 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
+          v654 = v715.uPitchAngle;
+LABEL_157:
+          if ( a1.Create(v36, v654, v659, v669) != -1 && pParty->bTurnBasedModeOn == 1 )
+            ++pTurnEngine->field_1C;
+        }
+        else
+        {
+          v732 = SHIDWORD(v733) / (amount - 1);
+          a1.stru_24.Reset();
+          a1.field_48 = v3->spellnum;
+          a1.field_4C = v2;
+          a1.field_50 = v731;
+          a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+          a1.vPosition.y = pParty->vPosition.y;
+          a1.vPosition.x = pParty->vPosition.x;
+          a1.uAttributes = v1;
+          a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+          a1.uSectorID = pIndoor->GetSector(
+                           pParty->vPosition.x,
+                           pParty->vPosition.y,
+                           pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
+          a1.uSpriteFrameID = v1;
+          v226 = 8 * v3->uPlayerID;
+          LOBYTE(v226) = v226 | 4;
+          a1.field_58 = v226;
+          a1.field_5C = a2;
+          a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+          a1.uSoundID = LOWORD(v3->field_10);
+          if ( pParty->bTurnBasedModeOn == 1 )
+            LOBYTE(a1.uAttributes) |= 4u;
+          v227 = SHIDWORD(v733) / -2;
+          y = (char *)(SHIDWORD(v733) / 2);
+          if ( SHIDWORD(v733) / -2 <= SHIDWORD(v733) / 2 )
+          {
+            v228 = v715.uYawAngle;
+            do
+            {
+              a1.uFacing = v227 + v228;
+              if ( a1.Create(
+                     v227 + v228,
+                     v715.uPitchAngle,
+                     pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                     v3->uPlayerID + 1) != -1
+                && pParty->bTurnBasedModeOn == 1 )
+                ++pTurnEngine->field_1C;
+              v227 += v732;
+            }
+            while ( v227 <= (signed int)y );
+          }
+        }
+        goto LABEL_1056;
+      case 27:
+        if ( !pPlayers[v3->uPlayerID + 1]->GetMaxMana() )
+          goto LABEL_461;
+        if ( v731 == 2 || v731 != 3 && v731 != 4 )
+          v229 = 600 * v2;
+        else
+          v229 = 3600 * v2;
+        LODWORD(v733) = v229;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v716 = pOtherOverlayList->_4418B1(10005, 201, v1, 65536);
+        v230 = v3->spellnum;
+        v231 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v230, v1);
+        v232 = 1;
+        v233 = v3->spellnum;
+        v234 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v233, 1u);
+        v235 = v3->spellnum;
+        v236 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v235, 2u);
+        v237 = v3->spellnum;
+        v238 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v237, 3u);
+        v239 = v3->uPlayerID + 1;
+        v732 = v229 << 7;
+        pParty->pPartyBuffs[18].Apply(
+          pParty->uTimePlayed + (signed int)(signed __int64)((double)(v229 << 7) * 0.033333335),
+          v731,
+          amount,
+          v716,
+          v239);
+        if ( v731 == 4 )
+          pParty->pPartyBuffs[18].uFlags = 1;
+        goto LABEL_1112;
+      case 28:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v240 = (char *)&pParty->pPlayers[v3->uPlayerID_2].pInventoryItems[a2];
+        y = v240;
+        if ( pItemsTable->pItems[*(int *)v240].uEquipType != 12 || v240[20] & 2 )
+          goto LABEL_199;
+        if ( v731 == 1 || v731 == 2 )
+        {
+          v241 = (double)v723 * 0.0099999998 + 0.5;
+        }
+        else
+        {
+          if ( v731 == 3 )
+          {
+            v241 = (double)v723 * 0.0099999998 + 0.69999999;
+          }
+          else
+          {
+            if ( v731 != 4 )
+            {
+              v241 = 0.0;
+              goto LABEL_484;
+            }
+            v241 = (double)v723 * 0.0099999998 + 0.80000001;
+          }
+        }
+        if ( v241 > 1.0 )
+          v241 = 1.0;
+LABEL_484:
+        v732 = (unsigned __int8)v240[25];
+        v242 = (signed __int64)((double)v732 * v241);
+        v243 = y;
+        y[25] = v242;
+        *((int *)v243 + 4) = (unsigned __int8)v242;
+        if ( (unsigned __int8)v242 <= v1 )
+        {
+          *(int *)v243 = v1;
+          dword_50C9D0 = 113;
+          dword_50C9D4 = v1;
+          dword_50C9D8 = 1;
+          ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2u);
+          pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, v1, v1, -1, v1, v1, v1, v1);
+          v3->spellnum = v1;
+          goto LABEL_1165;
+        }
+        *((int *)v243 + 5) |= 0x40u;
+        goto LABEL_1055;
+      case 30:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        uRequiredMana = v1;
+        HIDWORD(v733) = 10 * v2;
+        v730 = 1;
+        v244 = (char *)&pParty->pPlayers[v3->uPlayerID_2];
+        v726 = &pParty->pPlayers[v3->uPlayerID_2];
+        if ( v731 == 1 )
+        {
+          v245 = (int)&v244[36 * a2 + 532];
+          v309 = (char *)&pItemsTable->pItems[*(int *)v245].pIconName;
+          v311 = __OFSUB__(*(int *)v245, 134);
+          v14 = *(int *)v245 == 134;
+          v310 = *(int *)v245 - 134 < 0;
+          LODWORD(v725) = (int)(char *)&pItemsTable + 48 * *(int *)v245 + 4;
+          if ( (unsigned __int8)(v310 ^ v311) | v14 )
+          {
+            if ( *(int *)&v244[36 * a2 + 544] == v1 )
+            {
+              if ( *(int *)&v244[36 * a2 + 536] == v1 )
+              {
+                if ( *(int *)&v244[36 * a2 + 540] == v1 )
+                {
+                  v312 = v309[28];
+                  if ( v312 )
+                  {
+                    if ( v312 != 1 )
+                    {
+                      if ( v312 != 2 )
+                      {
+                        _this = (ItemGen *)&v244[36 * a2 + 552];
+                        if ( !(v244[36 * a2 + 552] & 2) )
+                        {
+                          if ( ((ItemGen *)v245)->GetValue() < 0x1C2 )
+                          {
+                            uRequiredMana = 1;
+                            v730 = v1;
+                          }
+                          if ( rand() % 100 >= SHIDWORD(v733) )
+                            uRequiredMana = 1;
+                          if ( uRequiredMana == v1 )
+                          {
+                            v313 = *(char *)(LODWORD(v725) + 28);
+                            if ( v313 == 3 | v313 == 4 | v313 == 5 | v313 == 6 | v313 == 7 | v313 == 8 | v313 == 9 | v313 == 10 | v313 == 11 )
+                            {
+                              v314 = rand() % pItemsTable->field_116D8[pItemsTable->pItems[*(int *)v245].uEquipType];
+                              *(int *)(v245 + 4) = 0;
+                              for ( j = pItemsTable->pEnchantments[0].field_8[pItemsTable->pItems[*(int *)v245].uEquipType
+                                                                           + 1];
+                                    ;
+                                    j += pItemsTable->pEnchantments[*(int *)(v245 + 4)].field_8[pItemsTable->pItems[*(int *)v245].uEquipType
+                                                                                                + 1] )
+                              {
+                                ++*(int *)(v245 + 4);
+                                if ( j >= v314 )
+                                  break;
+                              }
+                              v254 = rand();
+                              v255 = pItemsTable->field_116D8[17];
+                              v256 = pItemsTable->field_116D8[16];
+LABEL_611:
+                              *(int *)(v245 + 8) = v256 + v254 % (v255 - v256 + 1);
+LABEL_612:
+                              _this->uItemID |= 0x20u;
+                              goto LABEL_1055;
+                            }
+                            goto LABEL_615;
+                          }
+LABEL_613:
+                          v316 = _this->uItemID;
+                          if ( !(BYTE1(v316) & 2) )
+                          {
+                            LOBYTE(v316) = v316 | 2;
+                            _this->uItemID = v316;
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+LABEL_616:
+          if ( LODWORD(v727) == v1 )
+          {
+            v317 = pGlobalTXT_LocalizationStrings[428];
+            if ( v730 == v1 )
+              v317 = pGlobalTXT_LocalizationStrings[585];
+            ShowStatusBarString(v317, 2u);
+            pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, v1, v1, -1, v1, v1, v1, v1);
+            v318 = v726;
+            v3->spellnum = v1;
+            v318->PlaySound(43, v1);
+          }
+          goto LABEL_83;
+        }
+        if ( v731 != 2 )
+        {
+          if ( v731 == 3 )
+          {
+            v245 = (int)&v244[36 * a2 + 532];
+            v269 = *(int *)v245;
+            if ( *(int *)v245 > 134
+              || *(int *)(v245 + 12) != v1
+              || *(int *)(v245 + 4) != v1
+              || *(int *)(v245 + 8) != v1
+              || (_this = (ItemGen *)(v245 + 20), *(char *)(v245 + 20) & 2) )
+              goto LABEL_616;
+            v270 = (char *)&pItemsTable->pItems[v269].pIconName;
+            LODWORD(v725) = (int)v270;
+            v271 = v270[28];
+            if ( v271 && v271 != 1 && v271 != 2 )
+              v272 = ((ItemGen *)v245)->GetValue() < 0x1C2;
+            else
+              v272 = ((ItemGen *)v245)->GetValue() < 0xFA;
+            if ( v272 )
+            {
+              uRequiredMana = 1;
+              v730 = v1;
+            }
+            if ( rand() % 100 >= SHIDWORD(v733) )
+              uRequiredMana = 1;
+            if ( uRequiredMana != v1 )
+              goto LABEL_613;
+            v273 = v725;
+            v274 = *(char *)(LODWORD(v725) + 28);
+            if ( v274 == 0 | v274 == 1 | v274 == 2 | v274 == 3 | v274 == 4 | v274 == 5 | v274 == 6 | v274 == 7 | v274 == 8 | v274 == 9 | v274 == 10 | v274 == 11 )
+            {
+              if ( rand() % 100 < 80
+                && !(*(char *)(LODWORD(v273) + 28) == 0 | *(char *)(LODWORD(v273) + 28) == 1 | *(char *)(LODWORD(v273) + 28) == 2) )
+              {
+                v275 = rand() % pItemsTable->field_116D8[pItemsTable->pItems[*(int *)v245].uEquipType];
+                *(int *)(v245 + 4) = 0;
+                for ( k = pItemsTable->pEnchantments[0].field_8[pItemsTable->pItems[*(int *)v245].uEquipType + 1];
+                      ;
+                      k += pItemsTable->pEnchantments[*(int *)(v245 + 4)].field_8[pItemsTable->pItems[*(int *)v245].uEquipType
+                                                                                  + 1] )
+                {
+                  ++*(int *)(v245 + 4);
+                  if ( k >= v275 )
+                    break;
+                }
+                v254 = rand();
+                v255 = pItemsTable->field_116D8[19];
+                v256 = pItemsTable->field_116D8[18];
+                goto LABEL_611;
+              }
+              v277 = pItemsTable->field_11798;
+              v278 = 0;
+              v725 = 0.0;
+              HIDWORD(v733) = 0;
+              if ( pItemsTable->field_11798 > 0 )
+              {
+                v730 = (int)&v679;
+                do
+                {
+                  v279 = LOBYTE(pItemsTable->pSpecialEnchantments[v278 + 1].pName);
+                  if ( !v279 || v279 == 1 )
+                  {
+                    v280 = *(&pItemsTable->pSpecialEnchantments[0].field_8[pItemsTable->pItems[*(int *)v245].uEquipType
+                                                                        + 4]
+                           + v278 * 28);
+                    LODWORD(v725) += v280;
+                    if ( v280 )
+                    {
+                      v281 = v730;
+                      v730 += 4;
+                      *(int *)v281 = HIDWORD(v733);
+                    }
+                  }
+                  ++HIDWORD(v733);
+                  ++v278;
+                }
+                while ( SHIDWORD(v733) < v277 );
+              }
+              v282 = rand() % SLODWORD(v725);
+              v283 = v679;
+              *(int *)(v245 + 12) = v679;
+              v284 = pItemsTable->pSpecialEnchantments[v283].field_8[pItemsTable->pItems[*(int *)v245].uEquipType + 4];
+              v285 = v282 + 1;
+              if ( v284 < v285 )
+              {
+                for ( l = &v679; ; l = (int *)v732 )
+                {
+                  v287 = (int)(l + 1);
+                  v732 = v287;
+                  v288 = *(int *)v287;
+                  *(int *)(v245 + 12) = v288;
+                  v284 += pItemsTable->pSpecialEnchantments[v288].field_8[pItemsTable->pItems[*(int *)v245].uEquipType
+                                                                       + 4];
+                  if ( v284 >= v285 )
+                    break;
+                }
+              }
+              goto LABEL_525;
+            }
+          }
+          else
+          {
+            if ( v731 != 4
+              || (v245 = (int)&v726->pInventoryItems[a2], v246 = *(int *)v245, *(int *)v245 > 134)
+              || v726->pInventoryItems[a2].uAdditionalValue != v1
+              || v726->pInventoryItems[a2]._bonus_type != v1
+              || v726->pInventoryItems[a2]._bonus_strength != v1
+              || (_this = (ItemGen *)((char *)&v726->pInventoryItems[a2] + 20), v726->pInventoryItems[a2].uAttributes & 2) )
+              goto LABEL_616;
+            v247 = (char *)&pItemsTable->pItems[v246].pIconName;
+            LODWORD(v725) = (int)v247;
+            v248 = v247[28];
+            if ( v248 && v248 != 1 && v248 != 2 )
+              v249 = v726->pInventoryItems[a2].GetValue() < 0x1C2;
+            else
+              v249 = v726->pInventoryItems[a2].GetValue() < 0xFA;
+            if ( v249 )
+            {
+              uRequiredMana = 1;
+              v730 = v1;
+            }
+            if ( rand() % 100 >= SHIDWORD(v733) )
+              uRequiredMana = 1;
+            if ( uRequiredMana != v1 )
+              goto LABEL_613;
+            v250 = v725;
+            v251 = *(char *)(LODWORD(v725) + 28);
+            if ( v251 == 0 | v251 == 1 | v251 == 2 | v251 == 3 | v251 == 4 | v251 == 5 | v251 == 6 | v251 == 7 | v251 == 8 | v251 == 9 | v251 == 10 | v251 == 11 )
+            {
+              if ( rand() % 100 < 80
+                && !(*(char *)(LODWORD(v250) + 28) == 0 | *(char *)(LODWORD(v250) + 28) == 1 | *(char *)(LODWORD(v250) + 28) == 2) )
+              {
+                v252 = rand() % pItemsTable->field_116D8[pItemsTable->pItems[*(int *)v245].uEquipType];
+                *(int *)(v245 + 4) = 0;
+                for ( m = pItemsTable->pEnchantments[0].field_8[pItemsTable->pItems[*(int *)v245].uEquipType + 1];
+                      ;
+                      m += pItemsTable->pEnchantments[*(int *)(v245 + 4)].field_8[pItemsTable->pItems[*(int *)v245].uEquipType
+                                                                                  + 1] )
+                {
+                  ++*(int *)(v245 + 4);
+                  if ( m >= v252 )
+                    break;
+                }
+                v254 = rand();
+                v255 = pItemsTable->field_116D8[21];
+                v256 = pItemsTable->field_116D8[20];
+                goto LABEL_611;
+              }
+              v257 = pItemsTable->field_11798;
+              v258 = 0;
+              v725 = 0.0;
+              HIDWORD(v733) = 0;
+              if ( pItemsTable->field_11798 > 0 )
+              {
+                v730 = (int)&v679;
+                do
+                {
+                  v259 = LOBYTE(pItemsTable->pSpecialEnchantments[v258 + 1].pName);
+                  if ( !v259 || v259 == 1 )
+                  {
+                    v260 = *(&pItemsTable->pSpecialEnchantments[0].field_8[pItemsTable->pItems[*(int *)v245].uEquipType
+                                                                        + 4]
+                           + v258 * 28);
+                    LODWORD(v725) += v260;
+                    if ( v260 )
+                    {
+                      v261 = v730;
+                      v730 += 4;
+                      *(int *)v261 = HIDWORD(v733);
+                    }
+                  }
+                  ++HIDWORD(v733);
+                  ++v258;
+                }
+                while ( SHIDWORD(v733) < v257 );
+              }
+              v262 = rand() % SLODWORD(v725);
+              v263 = v679;
+              *(int *)(v245 + 12) = v679;
+              v264 = pItemsTable->pSpecialEnchantments[v263].field_8[pItemsTable->pItems[*(int *)v245].uEquipType + 4];
+              v265 = v262 + 1;
+              if ( v264 < v265 )
+              {
+                for ( ii = &v679; ; ii = (int *)v732 )
+                {
+                  v267 = (int)(ii + 1);
+                  v732 = v267;
+                  v268 = *(int *)v267;
+                  *(int *)(v245 + 12) = v268;
+                  v264 += pItemsTable->pSpecialEnchantments[v268].field_8[pItemsTable->pItems[*(int *)v245].uEquipType
+                                                                       + 4];
+                  if ( v264 >= v265 )
+                    break;
+                }
+              }
+LABEL_525:
+              ++*(int *)(v245 + 12);
+              goto LABEL_612;
+            }
+          }
+LABEL_615:
+          v1 = 0;
+          goto LABEL_616;
+        }
+        v289 = (ItemGen *)&v244[36 * a2 + 532];
+        _this = v289;
+        v290 = v289->uItemID;
+        LODWORD(v725) = (int)(char *)&pItemsTable + 48 * v290 + 4;
+        if ( v290 > 134
+          || _this->uAdditionalValue != v1
+          || _this->_bonus_type != v1
+          || _this->_bonus_strength != v1
+          || (v291 = pItemsTable->pItems[v290].uEquipType) == 0
+          || v291 == 1
+          || v291 == 2
+          || _this->uAttributes & 2 )
+          goto LABEL_616;
+        if ( _this->GetValue() < 0x1C2 )
+          uRequiredMana = 1;
+        if ( rand() % 100 >= SHIDWORD(v733) )
+          uRequiredMana = 1;
+        if ( uRequiredMana != v1 )
+          goto LABEL_199;
+        v292 = *(char *)(LODWORD(v725) + 28);
+        if ( !(v292 == 3 | v292 == 4 | v292 == 5 | v292 == 6 | v292 == 7 | v292 == 8 | v292 == 9 | v292 == 10 | v292 == 11) )
+        {
+          v2 = v723;
+          v1 = 0;
+          goto LABEL_199;
+        }
+        if ( rand() % 100 >= 80 )
+        {
+          v297 = pItemsTable->field_11798;
+          v294 = _this;
+          v298 = 0;
+          v725 = 0.0;
+          HIDWORD(v733) = 0;
+          if ( pItemsTable->field_11798 > 0 )
+          {
+            v730 = (int)&v679;
+            do
+            {
+              v299 = LOBYTE(pItemsTable->pSpecialEnchantments[v298 + 1].pName);
+              if ( !v299 || v299 == 1 )
+              {
+                v300 = *(&pItemsTable->pSpecialEnchantments[0].field_8[pItemsTable->pItems[v294->uItemID].uEquipType + 4]
+                       + v298 * 28);
+                LODWORD(v725) += v300;
+                if ( v300 )
+                {
+                  v301 = v730;
+                  v730 += 4;
+                  *(int *)v301 = HIDWORD(v733);
+                }
+              }
+              ++HIDWORD(v733);
+              ++v298;
+            }
+            while ( SHIDWORD(v733) < v297 );
+          }
+          v302 = rand() % SLODWORD(v725);
+          v303 = v679;
+          v294->uAdditionalValue = v679;
+          v304 = pItemsTable->pSpecialEnchantments[v303].field_8[pItemsTable->pItems[v294->uItemID].uEquipType + 4];
+          v305 = v302 + 1;
+          if ( v304 < v305 )
+          {
+            for ( jj = &v679; ; jj = (int *)v732 )
+            {
+              v307 = (int)(jj + 1);
+              v732 = v307;
+              v308 = *(int *)v307;
+              v294->uAdditionalValue = v308;
+              v304 += pItemsTable->pSpecialEnchantments[v308].field_8[pItemsTable->pItems[v294->uItemID].uEquipType + 4];
+              if ( v304 >= v305 )
+                break;
+            }
+          }
+          ++v294->uAdditionalValue;
+        }
+        else
+        {
+          v293 = rand();
+          v294 = _this;
+          v295 = v293 % pItemsTable->field_116D8[pItemsTable->pItems[_this->uItemID].uEquipType];
+          _this->_bonus_type = 0;
+          for ( kk = pItemsTable->pEnchantments[0].field_8[pItemsTable->pItems[v294->uItemID].uEquipType + 1];
+                ;
+                kk += pItemsTable->pEnchantments[v294->_bonus_type].field_8[pItemsTable->pItems[v294->uItemID].uEquipType
+                                                                         + 1] )
+          {
+            ++v294->_bonus_type;
+            if ( kk >= v295 )
+              break;
+          }
+          v294->_bonus_strength = pItemsTable->field_116D8[18]
+                                + rand() % (pItemsTable->field_116D8[19] - pItemsTable->field_116D8[18] + 1);
+        }
+        v294->uAttributes |= 0x20u;
+        goto LABEL_1055;
+      case 31:
+        amount = 10 * v2;
+        if ( pPlayer->sMana < (signed int)uRequiredMana )
+          goto LABEL_83;
+        if ( pParty->uFlags & 0x30 && v12 != 4 || rand() % 100 >= amount && v731 != 4 )
+          goto LABEL_200;
+        byte_50C0C0 = LOBYTE(v3->uPlayerID);
+        pMessageQueue_50CBD0->SendMessage((UIMessageType)195, v1, v1);
+        goto LABEL_1056;
+      case 33:
+        LODWORD(v733) = 604800 * v2;
+        if ( !_strcmpi(pCurrentMapName, "d05.blv") )
+          goto LABEL_200;
+        v319 = uRequiredMana;
+        if ( pPlayer->sMana >= (signed int)uRequiredMana )
+        {
+          pEventTimer->Pause();
+          pMessageQueue_50CBD0->SendMessage((UIMessageType)177, v1, v1);
+          qword_506350 = (signed int)v733;
+          _506348_current_lloyd_playerid = v3->uPlayerID;
+          ::uRequiredMana = v319;
+          ::sRecoveryTime = sRecoveryTime;
+          dword_50633C = v3->field_10;
+          dword_506338 = v3->spellnum;
+          LOBYTE(v3->field_8) |= 0x20u;
+        }
+        goto LABEL_83;
+      case 40:
+        v320 = v12 - 2;
+        if ( !v320 )
+          goto LABEL_632;
+        v321 = v320 - 1;
+        if ( v321 )
+        {
+          if ( v321 == 1 )
+            goto LABEL_634;
+LABEL_632:
+          v322 = 3600 * v2;
+        }
+        else
+        {
+          v322 = 86400 * v2;
+        }
+        amount = v322;
+LABEL_634:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v323 = v3->uPlayerID_2;
+        v324 = (char *)&pParty->pPlayers[v323].pConditions[15];
+        if ( !pParty->pPlayers[v323].pConditions[15] )
+          goto LABEL_1056;
+        if ( v731 == 4 )
+          goto LABEL_637;
+        v732 = amount << 7;
+        v663 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed - (double)(amount << 7) * 0.033333335);
+        v656 = 15;
+        goto LABEL_640;
+      case 41:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.uAttributes = v1;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+        a1.uSectorID = pIndoor->GetSector(
+                         pParty->vPosition.x,
+                         pParty->vPosition.y,
+                         pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3);
+        a1.uSpriteFrameID = v1;
+        v326 = 8 * v3->uPlayerID;
+        LOBYTE(v326) = v326 | 4;
+        a1.field_58 = v326;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uFacing = LOWORD(pParty->sRotationY);
+        a1.uSoundID = LOWORD(v3->field_10);
+        if ( pParty->bTurnBasedModeOn == 1 )
+          LOBYTE(a1.uAttributes) |= 4u;
+        v669 = v3->uPlayerID + 1;
+        v659 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
+        v654 = pParty->sRotationX;
+        goto LABEL_125;
+      case 43:
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+          goto LABEL_200;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        a1.uItemType = 4090;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 3;
+        v327 = 8 * v3->uPlayerID;
+        LOBYTE(v327) = v327 | 4;
+        a1.field_60_distance_related_prolly_lod = 0;
+        a1.field_58 = v327;
+        a1.field_5C = a2;
+        a1.uFacing = LOWORD(pParty->sRotationY);
+        a1.uSoundID = LOWORD(v3->field_10);
+        if ( pParty->bTurnBasedModeOn == 1 )
+          a1.uAttributes = 4;
+        v669 = v1;
+        v659 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
+        v35 = (signed int)stru_5C6E00->uIntegerHalfPi / 2;
+LABEL_124:
+        v654 = v35;
+LABEL_125:
+        v36 = pParty->sRotationY;
+        goto LABEL_157;
+      case 45:
+        v328 = v12 - 2;
+        if ( v328 )
+        {
+          v329 = v328 - 1;
+          if ( v329 && v329 != 1 )
+            v330 = 600 * v2;
+          else
+            v330 = 3600 * v2;
+        }
+        else
+        {
+          v330 = 1800 * v2;
+        }
+        LODWORD(v733) = v330;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v331 = v3->spellnum;
+        v332 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v331, v1);
+        v83 = 1;
+        v333 = v3->spellnum;
+        v334 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v333, 1u);
+        v335 = v3->spellnum;
+        v336 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v335, 2u);
+        v337 = v3->spellnum;
+        v338 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v337, 3u);
+        v673 = v1;
+        v732 = (int)v733 << 7;
+        v662 = v1;
+        v655 = v1;
+        v652 = v731;
+        v183 = (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v137 = (char *)&pParty->pPartyBuffs[3];
+        goto LABEL_976;
+      case 47:
+        LODWORD(v733) = 300;
+        v339 = v12 - 2;
+        if ( v339 )
+        {
+          v340 = v339 - 1;
+          if ( v340 )
+          {
+            if ( v340 != 1 )
+            {
+              amount = v2;
+              goto LABEL_667;
+            }
+            v341 = 6 * v2;
+          }
+          else
+          {
+            v341 = 4 * v2;
+          }
+        }
+        else
+        {
+          v341 = 2 * v2;
+        }
+        amount = v341;
+LABEL_667:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v342 = *(int *)&v3->field_C;
+        if ( v342 == v1 )
+        {
+          v345 = v3->uPlayerID_2;
+          v346 = v3->spellnum;
+          v347 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v346, v345);
+          v668 = v1;
+          v658 = v1;
+          v653 = amount;
+          LODWORD(v28) = LODWORD(pParty->uTimePlayed) + 1280;
+          v651 = v731;
+          HIDWORD(v650) = v1 + ((pParty->uTimePlayed + 1280) >> 32);
+          v27 = (char *)&pParty->pPlayers[v3->uPlayerID_2].pPlayerBuffs[4];
+          goto LABEL_104;
+        }
+        if ( (v342 & 7) == 3 )
+        {
+          v343 = v342 >> 3;
+          HIDWORD(v344) = v1 + ((pParty->uTimePlayed + 1280) >> 32);
+          LODWORD(v344) = LODWORD(pParty->uTimePlayed) + 1280;
+          pActors[v343].pActorBuffs[11].Apply(v344, v731, amount, v1, v1);
+          BYTE2(pActors[v343].uAttributes) |= 8u;
+          v672 = v1;
+          v661 = &pActors[v343];
+LABEL_165:
+          v56 = pGame->GetStru6();
+          pGame->GetStru6()->_4A7E89_sparkles_on_actor_after_it_casts_buff(v661, v672);
+        }
+        goto LABEL_1056;
+      case 49:
+        v348 = v12 - 2;
+        if ( !v348 )
+          goto LABEL_677;
+        v349 = v348 - 1;
+        if ( v349 )
+        {
+          if ( v349 == 1 )
+          {
+            amount = v1;
+            goto LABEL_679;
+          }
+LABEL_677:
+          v350 = 3600 * v2;
+        }
+        else
+        {
+          v350 = 86400 * v2;
+        }
+        amount = v350;
+LABEL_679:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v351 = &pParty->pPlayers[v3->uPlayerID_2];
+        if ( !v351->pConditions[0] )
+          goto LABEL_1056;
+        if ( v731 == 4 )
+        {
+          LODWORD(v351->pConditions[0]) = v1;
+          HIDWORD(v351->pConditions[0]) = v1;
+          goto LABEL_904;
+        }
+        v732 = amount << 7;
+        v351->DiscardConditionIfLastsLongerThan(
+          v1,
+          (signed __int64)((double)(signed __int64)pParty->uTimePlayed - (double)(amount << 7) * 0.033333335));
+        if ( HIDWORD(pParty->pPlayers[v3->uPlayerID_2].pConditions[0]) | LODWORD(pParty->pPlayers[v3->uPlayerID_2].pConditions[0]) )
+          goto LABEL_1056;
+        v674 = v3->uPlayerID_2;
+        goto LABEL_685;
+      case 50:
+        v354 = v12 - 2;
+        if ( v354 && (v355 = v354 - 1) != 0 && v355 == 1 )
+          v356 = 900 * (v2 + 4);
+        else
+          v356 = 300 * (v2 + 12);
+        LODWORD(v733) = v356;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( v731 == 1 || v731 == 2 )
+        {
+          v361 = v3->uPlayerID_2;
+          v362 = v3->spellnum;
+          v363 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v362, v361);
+          v668 = v1;
+          v732 = (int)v733 << 7;
+          v658 = v1;
+          v653 = v1;
+          v651 = v731;
+          v28 = pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+          v27 = (char *)&pParty->pPlayers[v3->uPlayerID_2].pPlayerBuffs[11];
+          goto LABEL_103;
+        }
+        a2 = v1;
+        v732 = (int)v733 << 7;
+        v717 = (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v357 = &pParty->pPlayers[0].pPlayerBuffs[11];
+        do
+        {
+          v358 = a2;
+          v359 = v3->spellnum;
+          v360 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v359, v358);
+          v357->Apply(pParty->uTimePlayed + v717, v731, v1, v1, v1);
+          ++a2;
+          v357 = (SpellBuff *)((char *)v357 + 6972);
+        }
+        while ( (signed int)v357 < (signed int)&pParty->field_871C[508] );
+        goto LABEL_1056;
+      case 48:
+        v364 = v12 - 2;
+        if ( !v364 || (v365 = v364 - 1) != 0 && v365 != 1 )
+          v366 = 60 * (v2 + 3);
+        else
+          v366 = 300 * v2 + 180;
+        LODWORD(v733) = v366;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v726 = (Player *)sub_46A6AC((int)dword_50BF30, 100, 4096);
+        v367 = pGame->GetStru6();
+        pGame->GetStru6()->FadeScreen__like_Turn_Undead_and_mb_Armageddon(0xFFFFFFu, 0xC0u);
+        ++a1.uItemType;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v368 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        a1.uFacing = v1;
+        v368 *= 8;
+        LOBYTE(v368) = v368 | 4;
+        a1.field_58 = v368;
+        a1.uSoundID = LOWORD(v3->field_10);
+        for ( a2 = v1; a2 < (signed int)v726; ++a2 )
+        {
+          v369 = &pActors[dword_50BF30[a2]];
+          if ( MonsterStats::BelongsToSupertype(v369->pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD) )
+          {
+            a1.vPosition.x = v369->vPosition.x;
+            a1.vPosition.y = v369->vPosition.y;
+            v732 = v369->uActorHeight;
+            a1.vPosition.z = v369->vPosition.z - (unsigned int)(signed __int64)((double)v732 * unk_4D8548);
+            v370 = 8 * dword_50BF30[a2];
+            LOBYTE(v370) = v370 | 3;
+            a1.field_5C = v370;
+            a1.Create(0, v1, v1, v1);
+            v732 = (int)v733 << 7;
+            v369->pActorBuffs[4].Apply(
+              pParty->uTimePlayed + (signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335),
+              v731,
+              v1,
+              v1,
+              v1);
+          }
+        }
+        goto LABEL_1056;
+      case 53:
+        v371 = v12 - 2;
+        if ( v371 && (v372 = v371 - 1) != 0 && v372 == 1 )
+          amount = v1;
+        else
+          amount = 86400 * v2;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        pOtherOverlayList->_4418B1(5080, v3->uPlayerID_2 + 100, v1, 65536);
+        v373 = v3->uPlayerID_2;
+        if ( !(HIDWORD(pParty->pPlayers[v373].pConditions[14]) | LODWORD(pParty->pPlayers[v373].pConditions[14])) )
+          goto LABEL_1056;
+        v14 = v731 == 4;
+        pParty->pPlayers[v373].sHealth = 1;
+        if ( v14 )
+        {
+          v374 = v3->uPlayerID_2;
+          v375 = (char *)pParty->pPlayers;
+          LODWORD(pParty->pPlayers[v374].pConditions[14]) = v1;
+          HIDWORD(pParty->pPlayers[v374].pConditions[14]) = v1;
+          v376 = v3->uPlayerID_2;
+          LODWORD(pParty->pPlayers[v376].pConditions[13]) = v1;
+          HIDWORD(pParty->pPlayers[v376].pConditions[13]) = v1;
+        }
+        else
+        {
+          v732 = amount << 7;
+          *(float *)&a2 = (double)(amount << 7) * 0.033333335;
+          v375 = (char *)pParty->pPlayers;
+          pParty->pPlayers[v3->uPlayerID_2].DiscardConditionIfLastsLongerThan(
+            0xEu,
+            (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+          pParty->pPlayers[v3->uPlayerID_2].DiscardConditionIfLastsLongerThan(
+            0xDu,
+            (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+        }
+        v377 = (Player *)&v375[6972 * v3->uPlayerID_2];
+        goto LABEL_720;
+      case 54:
+        v378 = v12 - 2;
+        if ( v378 && (v379 = v378 - 1) != 0 && v379 == 1 )
+          v380 = 4 * v2;
+        else
+          v380 = 3 * v2;
+        amount = v380;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v381 = 0;
+        HIDWORD(v733) = amount;
+        v730 = 0;
+        v382 = 1;
+        do
+        {
+          v383 = pPlayers[v382];
+          if ( !v383->pConditions[14] && !v383->pConditions[15] && !v383->pConditions[16] )
+            v682[v381++] = v382;
+          ++v382;
+        }
+        while ( v382 <= 4 );
+        v384 = 0;
+        v730 = v381;
+        if ( v381 > v1 )
+        {
+          do
+            HIDWORD(v733) += pPlayers[v682[v384++]]->sHealth;
+          while ( v384 < v381 );
+        }
+        v732 = (signed __int64)((double)SHIDWORD(v733) / (double)v730);
+        HIDWORD(v733) = v1;
+        if ( v381 > v1 )
+        {
+          do
+          {
+            v385 = 4 * v682[HIDWORD(v733)] + 10965188;
+            pPlayers[v682[HIDWORD(v733)]]->sHealth = v732;
+            v726 = *(Player **)v385;
+            v386 = v726->GetMaxHealth();
+            if ( v726->sHealth > v386 )
+              *(int *)(*(int *)v385 + 6460) = v726->GetMaxHealth();
+            v387 = *(Player **)v385;
+            if ( v387->sHealth > v1 )
+            {
+              LODWORD(v387->pConditions[13]) = v1;
+              HIDWORD(v387->pConditions[13]) = v1;
+            }
+            v388 = HIDWORD(v733);
+            v389 = LOWORD(v682[HIDWORD(v733)]) - 1;
+            v390 = v3->spellnum;
+            v391 = pGame->GetStru6();
+            pGame->GetStru6()->SetPlayerBuffAnim(v390, v389);
+            HIDWORD(v733) = v388 + 1;
+          }
+          while ( v388 + 1 < v730 );
+        }
+        goto LABEL_1056;
+      case 55:
+        v392 = v12 - 1;
+        if ( !v392 )
+        {
+          v395 = 180 * v2;
+          goto LABEL_750;
+        }
+        v393 = v392 - 1;
+        if ( !v393 )
+        {
+          v395 = 10800 * v2;
+          goto LABEL_750;
+        }
+        v394 = v393 - 1;
+        if ( !v394 )
+        {
+          v395 = 259200 * v2;
+LABEL_750:
+          amount = v395;
+          goto LABEL_751;
+        }
+        if ( v394 == 1 )
+          amount = v1;
+LABEL_751:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v396 = v3->uPlayerID_2;
+        if ( HIDWORD(pParty->pPlayers[v396].pConditions[16]) | LODWORD(pParty->pPlayers[v396].pConditions[16])
+          || HIDWORD(pParty->pPlayers[v396].pConditions[14]) | LODWORD(pParty->pPlayers[v396].pConditions[14]) )
+        {
+          if ( !(HIDWORD(pParty->pPlayers[v396].pConditions[1]) | LODWORD(pParty->pPlayers[v396].pConditions[1])) )
+            pParty->pPlayers[v396].PlaySound(25, v1);
+          if ( v731 == 4 )
+          {
+            v397 = v3->uPlayerID_2;
+            LODWORD(pParty->pPlayers[v397].pConditions[16]) = v1;
+            HIDWORD(pParty->pPlayers[v397].pConditions[16]) = v1;
+            v398 = v3->uPlayerID_2;
+            LODWORD(pParty->pPlayers[v398].pConditions[14]) = v1;
+            HIDWORD(pParty->pPlayers[v398].pConditions[14]) = v1;
+            v399 = v3->uPlayerID_2;
+            LODWORD(pParty->pPlayers[v399].pConditions[13]) = v1;
+            HIDWORD(pParty->pPlayers[v399].pConditions[13]) = v1;
+            v400 = (char *)pParty->pPlayers;
+          }
+          else
+          {
+            v732 = amount << 7;
+            *(float *)&a2 = (double)(amount << 7) * 0.033333335;
+            v400 = (char *)pParty->pPlayers;
+            pParty->pPlayers[v3->uPlayerID_2].DiscardConditionIfLastsLongerThan(
+              0x10u,
+              (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+            pParty->pPlayers[v3->uPlayerID_2].DiscardConditionIfLastsLongerThan(
+              0xEu,
+              (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+            pParty->pPlayers[v3->uPlayerID_2].DiscardConditionIfLastsLongerThan(
+              0xDu,
+              (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+          }
+          v83 = 1;
+          ((Player *)&v400[6972 * v3->uPlayerID_2])->SetCondition(1u, 1);
+          v401 = pGame;
+          pParty->pPlayers[v3->uPlayerID_2].sHealth = 1;
+          v402 = v3->uPlayerID_2;
+          v403 = v3->spellnum;
+          v404 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v403, v402);
+        }
+        else
+        {
+          v83 = 1;
+        }
+        goto LABEL_978;
+      case 61:
+        v405 = v12 - 2;
+        if ( !v405 )
+          goto LABEL_766;
+        v406 = v405 - 1;
+        if ( v406 )
+        {
+          if ( v406 == 1 )
+          {
+            amount = v1;
+            goto LABEL_768;
+          }
+LABEL_766:
+          v407 = 3600 * v2;
+        }
+        else
+        {
+          v407 = 86400 * v2;
+        }
+        amount = v407;
+LABEL_768:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v408 = v3->uPlayerID_2;
+        v409 = v3->spellnum;
+        v410 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v409, v408);
+        v323 = v3->uPlayerID_2;
+        v324 = (char *)&pParty->pPlayers[v323].pConditions[12];
+        if ( !pParty->pPlayers[v323].pConditions[12] )
+          goto LABEL_1056;
+        if ( v731 == 4 )
+          goto LABEL_637;
+        v732 = amount << 7;
+        v663 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed - (double)(amount << 7) * 0.033333335);
+        v656 = 12;
+        goto LABEL_640;
+      case 56:
+        v411 = v12 - 2;
+        if ( v411 )
+        {
+          v412 = v411 - 1;
+          if ( v412 )
+          {
+            if ( v412 == 1 )
+            {
+              amount = v1;
+              goto LABEL_780;
+            }
+            v413 = 180 * v2;
+          }
+          else
+          {
+            v413 = 86400 * v2;
+          }
+        }
+        else
+        {
+          v413 = 3600 * v2;
+        }
+        amount = v413;
+LABEL_780:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v414 = v3->uPlayerID_2;
+        v415 = v3->spellnum;
+        v416 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v415, v414);
+        v323 = v3->uPlayerID_2;
+        v324 = (char *)&pParty->pPlayers[v323].pConditions[3];
+        if ( !pParty->pPlayers[v323].pConditions[3] )
+          goto LABEL_1056;
+        if ( v731 == 4 )
+          goto LABEL_637;
+        v732 = amount << 7;
+        v663 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed - (double)(amount << 7) * 0.033333335);
+        v656 = 3;
+        goto LABEL_640;
+      case 59:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( a2 == v1 || (a2 & 7) != 3 )
+          goto LABEL_1056;
+        v417 = (int)&pActors[a2 >> 3];
+        v730 = v417;
+        if ( !(*(char *)(v417 + 38) & 0x80) )
+        {
+          ((Actor *)v417)->SetRandomGoldIfTheresNoItem();
+          v417 = v730;
+        }
+        v418 = *(int *)(v417 + 672);
+        HIDWORD(v733) = v1;
+        if ( pItemsTable->pItems[v418].uEquipType == 18 )
+          HIDWORD(v733) = *(int *)(v417 + 684);
+
+        //ItemGen::ItemGen(&v683);
+        v683.Reset();
+
+        v419 = *(short *)(v730 + 180);
+        if ( v419 != (short)v1 )
+        {
+          v683.uItemID = v419;
+          goto LABEL_799;
+        }
+        v420 = 0;
+        v421 = v730 + 564;
+        while ( *(int *)v421 == v1 || pItemsTable->pItems[*(int *)v421].uEquipType == 18 )
+        {
+          ++v420;
+          v421 += 36;
+          if ( v420 >= 4 )
+            goto LABEL_799;
+        }
+        memcpy(&v683, (const void *)(v730 + 36 * v420 + 564), sizeof(v683));
+        v2 = v723;
+        v1 = 0;
+LABEL_799:
+        if ( HIDWORD(v733) != v1 )
+        {
+          v675 = (const char *)HIDWORD(v733);
+          if ( v683.uItemID != v1 )
+          {
+            v422 = v683.GetDisplayName();
+            sprintf(pTmpBuf2, "(%s), and %d gold", v422, v675);
+            goto LABEL_807;
+          }
+          v664 = "%d gold";
+          goto LABEL_803;
+        }
+        if ( v683.uItemID != v1 )
+        {
+          v675 = v683.GetDisplayName();
+          v664 = "(%s)";
+LABEL_803:
+          sprintf(pTmpBuf2, v664, v675);
+          goto LABEL_807;
+        }
+        strcpy(pTmpBuf2, "nothing");
+LABEL_807:
+        ShowStatusBarString(pTmpBuf2, 2u);
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.x = *(short *)(v730 + 142);
+        a1.vPosition.y = *(short *)(v730 + 144);
+        v676 = *(short *)(v730 + 138);
+        v665 = a1.vPosition.y;
+        a1.vPosition.z = *(short *)(v730 + 138);
+        v657 = a1.vPosition.x;
+        goto LABEL_1087;
+      case 62:
+        v423 = v12 - 2;
+        if ( !v423 )
+          goto LABEL_813;
+        v424 = v423 - 1;
+        if ( v424 )
+        {
+          if ( v424 == 1 )
+            v425 = 3600 * v2;
+          else
+LABEL_813:
+            v425 = 300 * v2;
+        }
+        else
+        {
+          v425 = 600 * v2;
+        }
+        amount = v425;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v426 = a2 >> 3;
+        if ( (a2 & 7) != 3 )
+          goto LABEL_1056;
+        v730 = 836 * v426;
+        if ( stru_50C198.GetMagicalResistance(&pActors[v426], 7u) )
+        {
+          ((SpellBuff *)((char *)&pActors[0].pActorBuffs[1] + v730))->Reset();
+          ((SpellBuff *)((char *)&pActors[0].pActorBuffs[12] + v730))->Reset();
+          v732 = amount << 7;
+          ((SpellBuff *)((char *)&pActors[0].pActorBuffs[9] + v730))->Apply(
+            pParty->uTimePlayed + (signed __int64)((double)(amount << 7) * 0.033333335),
+            v731,
+            v1,
+            v1,
+            v1);
+          *(&pActors[0].pMonsterInfo.uHostilityType + v730) = MonsterInfo::Hostility_Long;
+        }
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        v60 = pObjectList->ObjectIDByItemID(a1.uItemType);
+        v61 = v730;
+        goto LABEL_1086;
+      case 66:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        amount = 600 * v2;
+        v427 = a2 >> 3;
+        if ( (a2 & 7) != 3 )
+          goto LABEL_1056;
+        v730 = 836 * v427;
+        if ( MonsterStats::BelongsToSupertype(pActors[v427].pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD) )
+          goto LABEL_83;
+        if ( stru_50C198.GetMagicalResistance((Actor *)((char *)pActors + v730), 7u) )
+        {
+          ((SpellBuff *)((char *)&pActors[0].pActorBuffs[9] + v730))->Reset();
+          ((SpellBuff *)((char *)&pActors[0].pActorBuffs[1] + v730))->Reset();
+          v732 = amount << 7;
+          ((SpellBuff *)((char *)&pActors[0].pActorBuffs[12] + v730))->Apply(
+            pParty->uTimePlayed + (signed __int64)((double)(amount << 7) * 0.033333335),
+            v731,
+            v1,
+            v1,
+            v1);
+        }
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        v60 = pObjectList->ObjectIDByItemID(a1.uItemType);
+        v61 = v730;
+        goto LABEL_1086;
+      case 63:
+        v428 = v12 - 2;
+        if ( v428 && (v429 = v428 - 1) != 0 && v429 == 1 )
+          v430 = 300 * v2;
+        else
+          v430 = 180 * v2;
+        amount = v430;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v726 = (Player *)sub_46A6AC((int)dword_50BF30, 100, 4096);
+        v431 = pGame->GetStru6();
+        pGame->GetStru6()->FadeScreen__like_Turn_Undead_and_mb_Armageddon(0xA0A0Au, 0xC0u);
+        ++a1.uItemType;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v432 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        a1.uFacing = v1;
+        v432 *= 8;
+        LOBYTE(v432) = v432 | 4;
+        a1.field_58 = v432;
+        a1.uSoundID = LOWORD(v3->field_10);
+        for ( a2 = v1; a2 < (signed int)v726; ++a2 )
+        {
+          v433 = &pActors[dword_50BF30[a2]];
+          if ( MonsterStats::BelongsToSupertype(v433->pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD) )
+            break;
+          a1.vPosition.x = v433->vPosition.x;
+          a1.vPosition.y = v433->vPosition.y;
+          v732 = v433->uActorHeight;
+          a1.vPosition.z = v433->vPosition.z - (unsigned int)(signed __int64)((double)v732 * unk_4D8548);
+          v434 = 8 * dword_50BF30[a2];
+          LOBYTE(v434) = v434 | 3;
+          a1.field_5C = v434;
+          a1.Create(0, v1, v1, v1);
+          if ( stru_50C198.GetMagicalResistance(v433, 7u) )
+          {
+            v732 = amount << 7;
+            v433->pActorBuffs[4].Apply(
+              pParty->uTimePlayed + (signed __int64)((double)(amount << 7) * 0.033333335),
+              v731,
+              v1,
+              v1,
+              v1);
+          }
+        }
+        goto LABEL_1056;
+      case 64:
+        v435 = v12 - 2;
+        if ( v435 && (v436 = v435 - 1) != 0 && v436 == 1 )
+          amount = v1;
+        else
+          amount = 86400 * v2;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v437 = v3->uPlayerID_2;
+        v438 = v3->spellnum;
+        v439 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v438, v437);
+        v440 = v3->uPlayerID_2;
+        if ( HIDWORD(pParty->pPlayers[v440].pConditions[5]) | LODWORD(pParty->pPlayers[v440].pConditions[5]) )
+        {
+          if ( !(HIDWORD(pParty->pPlayers[v440].pConditions[1]) | LODWORD(pParty->pPlayers[v440].pConditions[1])) )
+            pParty->pPlayers[v440].PlaySound(25, v1);
+          if ( v731 == 4 )
+          {
+            v441 = v3->uPlayerID_2;
+            LODWORD(pParty->pPlayers[v441].pConditions[5]) = v1;
+            HIDWORD(pParty->pPlayers[v441].pConditions[5]) = v1;
+          }
+          else
+          {
+            v732 = amount << 7;
+            pParty->pPlayers[v3->uPlayerID_2].DiscardConditionIfLastsLongerThan(
+              5u,
+              (signed __int64)((double)(signed __int64)pParty->uTimePlayed - (double)(amount << 7) * 0.033333335));
+          }
+          v377 = &pParty->pPlayers[v3->uPlayerID_2];
+LABEL_720:
+          v377->SetCondition(1u, v1);
+        }
+        goto LABEL_1056;
+      case 42:
+        v442 = v12 - 2;
+        if ( !v442 )
+          goto LABEL_855;
+        v443 = v442 - 1;
+        if ( v443 )
+        {
+          if ( v443 == 1 )
+            v444 = 4 * v2;
+          else
+LABEL_855:
+            v444 = 2 * v2;
+        }
+        else
+        {
+          v444 = 3 * v2;
+        }
+        amount = v444;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v445 = a2 >> 3;
+        if ( (a2 & 7) == 2 )
+        {
+          v449 = (char *)&pLayingItems[v445].stru_24;
+          v450 = *(int *)v449;
+          if ( pItemsTable->pItems[v450].uEquipType == 18 )
+          {
+            party_finds_gold(*((int *)v449 + 3), 0);
+            viewparams->bRedrawGameUI = 1;
+          }
+          else
+          {
+            sprintf(pTmpBuf2, pGlobalTXT_LocalizationStrings[471], pItemsTable->pItems[v450].pUnidentifiedName);
+            ShowStatusBarString(pTmpBuf2, 2u);
+            if ( !pParty->AddItem(&pLayingItems[v445].stru_24) )
+              pParty->SetHoldingItem(&pLayingItems[v445].stru_24);
+          }
+          LayingItem::_42F933(v445);
+        }
+        else
+        {
+          if ( (a2 & 7) == 3 )
+          {
+            stru_50C198.LootActor(&pActors[v445]);
+          }
+          else
+          {
+            if ( (a2 & 7) != 5 )
+            {
+              if ( (a2 & 7) != 6 )
+                goto LABEL_1056;
+              dword_507CD8 = 1;
+              v677 = 1;
+              if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+                v446 = pIndoor->pFaceExtras[pIndoor->pFaces[v445].uFaceExtraID].uEventID;
+              else
+                v446 = pOutdoor->pBModels[a2 >> 9].pFaces[v445 & 0x3F].sCogTriggeredID;
+              goto LABEL_866;
+            }
+            v447 = &pLevelDecorations[v445];
+            dword_507CD8 = 1;
+            v448 = v447->field_16_event_id;
+            if ( v448 != (short)v1 )
+            {
+              v677 = 1;
+              v446 = v448;
+LABEL_866:
+              EventProcessor(v446, a2, v677);
+              goto LABEL_1056;
+            }
+            if ( v447->IsInteractive() )
+            {
+              _5C3420_pDecoration = v447;
+              EventProcessor(stru_5E4C90._decor_events[v447->_idx_in_stru123 - 75] + 380, 0, 1);
+              _5C3420_pDecoration = (LevelDecoration *)v1;
+            }
+          }
+        }
+        goto LABEL_1056;
+      case 67:
+        v451 = v12 - 2;
+        if ( v451 )
+        {
+          v452 = v451 - 1;
+          if ( v452 )
+          {
+            if ( v452 == 1 )
+            {
+              amount = v1;
+              goto LABEL_883;
+            }
+            v453 = 180 * v2;
+          }
+          else
+          {
+            v453 = 86400 * v2;
+          }
+        }
+        else
+        {
+          v453 = 3600 * v2;
+        }
+        amount = v453;
+LABEL_883:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v454 = v3->uPlayerID_2;
+        v455 = v3->spellnum;
+        v456 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v455, v454);
+        v323 = v3->uPlayerID_2;
+        v324 = (char *)&pParty->pPlayers[v323].pConditions[1];
+        if ( !pParty->pPlayers[v323].pConditions[1] )
+          goto LABEL_1056;
+        if ( v731 == 4 )
+        {
+LABEL_637:
+          *(int *)v324 = v1;
+          *((int *)v324 + 1) = v1;
+          goto LABEL_1056;
+        }
+        v732 = amount << 7;
+        v663 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed - (double)(amount << 7) * 0.033333335);
+        v656 = 1;
+LABEL_640:
+        v325 = &pParty->pPlayers[v323];
+        goto LABEL_641;
+      case 68:
+        v457 = v12 - 2;
+        if ( v457 )
+        {
+          v458 = v457 - 1;
+          if ( v458 )
+          {
+            if ( v458 == 1 )
+              v459 = 5 * v2 + 5;
+            else
+              v459 = 2 * v2 + 5;
+          }
+          else
+          {
+            v459 = 4 * v2 + 5;
+          }
+        }
+        else
+        {
+          v459 = 3 * v2 + 5;
+        }
+        amount = v459;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v460 = *(int *)&v3->field_C;
+        if ( v460 == v1 )
+        {
+          pParty->pPlayers[v3->uPlayerID_2].Heal(amount);
+LABEL_904:
+          v674 = v3->uPlayerID_2;
+LABEL_685:
+          v352 = v3->spellnum;
+          v353 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v352, v674);
+        }
+        else
+        {
+          if ( (v460 & 7) == 3 )
+          {
+            v461 = &pActors[v460 >> 3];
+            v462 = v461->uAIState;
+            v463 = v461->pMonsterInfo.uHP;
+            if ( v462 != 5 )
+            {
+              if ( v462 != 4 )
+              {
+                if ( v462 != 19 )
+                {
+                  if ( v462 != 11 )
+                  {
+                    v461->sCurrentHP += amount;
+                    if ( v461->sCurrentHP > v463 )
+                      v461->sCurrentHP = v463;
+                  }
+                }
+              }
+            }
+          }
+        }
+        goto LABEL_1056;
+      case 72:
+        v464 = v12 - 2;
+        if ( !v464 )
+          goto LABEL_910;
+        v465 = v464 - 1;
+        if ( v465 )
+        {
+          if ( v465 == 1 )
+          {
+            amount = v1;
+            goto LABEL_912;
+          }
+LABEL_910:
+          v466 = 3600 * v2;
+        }
+        else
+        {
+          v466 = 86400 * v2;
+        }
+        amount = v466;
+LABEL_912:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v467 = v3->uPlayerID_2;
+        v468 = v3->spellnum;
+        v469 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v468, v467);
+        v470 = v3->uPlayerID_2;
+        if ( !(HIDWORD(pParty->pPlayers[v470].pConditions[6]) | LODWORD(pParty->pPlayers[v470].pConditions[6]))
+          && !(HIDWORD(pParty->pPlayers[v470].pConditions[8]) | LODWORD(pParty->pPlayers[v470].pConditions[8]))
+          && !(HIDWORD(pParty->pPlayers[v470].pConditions[10]) | LODWORD(pParty->pPlayers[v470].pConditions[10])) )
+          goto LABEL_1056;
+        if ( v731 == 4 )
+        {
+          LODWORD(pParty->pPlayers[v470].pConditions[6]) = v1;
+          HIDWORD(pParty->pPlayers[v470].pConditions[6]) = v1;
+          v471 = v3->uPlayerID_2;
+          LODWORD(pParty->pPlayers[v471].pConditions[8]) = v1;
+          HIDWORD(pParty->pPlayers[v471].pConditions[8]) = v1;
+          v472 = v3->uPlayerID_2;
+          LODWORD(pParty->pPlayers[v472].pConditions[10]) = v1;
+          HIDWORD(pParty->pPlayers[v472].pConditions[10]) = v1;
+          goto LABEL_1056;
+        }
+        v732 = amount << 7;
+        *(float *)&a2 = (double)(amount << 7) * 0.033333335;
+        pParty->pPlayers[v470].DiscardConditionIfLastsLongerThan(
+          6u,
+          (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+        v473 = (char *)pParty->pPlayers;
+        pParty->pPlayers[v3->uPlayerID_2].DiscardConditionIfLastsLongerThan(
+          8u,
+          (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+        v663 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2);
+        v656 = 10;
+        goto LABEL_937;
+      case 75:
+        amount = v2;
+        LODWORD(v733) = 3600 * v2;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v474 = v3->spellnum;
+        v475 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v474, v1);
+        v476 = v3->spellnum;
+        v477 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v476, 1u);
+        v478 = v3->spellnum;
+        v479 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v478, 2u);
+        v480 = v3->spellnum;
+        v481 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v480, 3u);
+        v668 = v1;
+        v732 = (int)v733 << 7;
+        v658 = v1;
+        v653 = v2;
+        v651 = v731;
+        v26 = (signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v27 = (char *)&pParty->pPartyBuffs[13];
+        goto LABEL_101;
+      case 73:
+        LODWORD(v733) = 3600 * v2;
+        amount = v2;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( v731 == 4 )
+        {
+          v482 = v3->spellnum;
+          v483 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v482, v1);
+          v484 = v3->spellnum;
+          v485 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v484, 1u);
+          v486 = v3->spellnum;
+          v487 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v486, 2u);
+          v488 = v3->spellnum;
+          v489 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v488, 3u);
+          v732 = (int)v733 << 7;
+          v717 = (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+          pParty->pPlayers[0].pPlayerBuffs[6].Apply(pParty->uTimePlayed + v717, 4u, v2, v2, v1);
+          pParty->pPlayers[1].pPlayerBuffs[6].Apply(pParty->uTimePlayed + v717, 4u, v2, v2, v1);
+          pParty->pPlayers[2].pPlayerBuffs[6].Apply(pParty->uTimePlayed + v717, 4u, v2, v2, v1);
+          v668 = v1;
+          v658 = v2;
+          v653 = v2;
+          LODWORD(v28) = LODWORD(pParty->uTimePlayed) + v717;
+          v651 = 4;
+          HIDWORD(v650) = (pParty->uTimePlayed + v717) >> 32;
+          v27 = (char *)&pParty->pPlayers[3].pPlayerBuffs[6];
+          goto LABEL_104;
+        }
+        v490 = v3->uPlayerID_2;
+        v491 = v3->spellnum;
+        v492 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v491, v490);
+        v668 = v1;
+        v732 = (int)v733 << 7;
+        v658 = v2;
+        v653 = v2;
+        v651 = v731;
+        v28 = pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v27 = (char *)&pParty->pPlayers[v3->uPlayerID_2].pPlayerBuffs[6];
+        goto LABEL_103;
+      case 74:
+        v493 = v12 - 2;
+        if ( v493 && (v494 = v493 - 1) != 0 && v494 == 1 )
+          amount = v1;
+        else
+          amount = 86400 * v2;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v495 = v3->uPlayerID_2;
+        v496 = v3->spellnum;
+        v497 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v496, v495);
+        v498 = v3->uPlayerID_2;
+        if ( !(HIDWORD(pParty->pPlayers[v498].pConditions[7]) | LODWORD(pParty->pPlayers[v498].pConditions[7]))
+          && !(HIDWORD(pParty->pPlayers[v498].pConditions[9]) | LODWORD(pParty->pPlayers[v498].pConditions[9]))
+          && !(HIDWORD(pParty->pPlayers[v498].pConditions[11]) | LODWORD(pParty->pPlayers[v498].pConditions[11])) )
+          goto LABEL_1056;
+        if ( v731 == 4 )
+        {
+          LODWORD(pParty->pPlayers[v498].pConditions[7]) = v1;
+          HIDWORD(pParty->pPlayers[v498].pConditions[7]) = v1;
+          v499 = v3->uPlayerID_2;
+          LODWORD(pParty->pPlayers[v499].pConditions[9]) = v1;
+          HIDWORD(pParty->pPlayers[v499].pConditions[9]) = v1;
+          v500 = v3->uPlayerID_2;
+          LODWORD(pParty->pPlayers[v500].pConditions[11]) = v1;
+          HIDWORD(pParty->pPlayers[v500].pConditions[11]) = v1;
+        }
+        else
+        {
+          v732 = amount << 7;
+          *(float *)&a2 = (double)(amount << 7) * 0.033333335;
+          pParty->pPlayers[v498].DiscardConditionIfLastsLongerThan(
+            7u,
+            (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+          v473 = (char *)pParty->pPlayers;
+          pParty->pPlayers[v3->uPlayerID_2].DiscardConditionIfLastsLongerThan(
+            9u,
+            (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2));
+          v663 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed - *(float *)&a2);
+          v656 = 11;
+LABEL_937:
+          v325 = (Player *)&v473[6972 * v3->uPlayerID_2];
+LABEL_641:
+          v325->DiscardConditionIfLastsLongerThan(v656, v663);
+        }
+        goto LABEL_1056;
+      case 77:
+        amount = 5 * v2 + 10;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v501 = pParty->pPlayers;
+        do
+        {
+          v502 = v3->spellnum;
+          v503 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v502, v1);
+          v501->Heal(amount);
+          ++v501;
+          ++v1;
+        }
+        while ( (signed int)v501 < (signed int)pParty->pHirelings );
+        goto LABEL_1056;
+      case 80:
+        sRecoveryTime -= v2;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v504 = pGame->GetStru6();
+        pGame->GetStru6()->FadeScreen__like_Turn_Undead_and_mb_Armageddon(0xAFF0Au, 0xC0u);
+        v505 = sub_46A6AC((int)dword_50BF30, 100, 4096);
+        ++a1.uItemType;
+        HIDWORD(v733) = v505;
+        v690 = v1;
+        v689 = v1;
+        v688 = v1;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v506 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        a1.uFacing = v1;
+        v506 *= 8;
+        LOBYTE(v506) = v506 | 4;
+        a1.field_58 = v506;
+        a1.uSoundID = LOWORD(v3->field_10);
+        a2 = v1;
+        if ( SHIDWORD(v733) > v1 )
+        {
+          do
+          {
+            v507 = dword_50BF30[a2];
+            a1.vPosition.x = pActors[v507].vPosition.x;
+            a1.vPosition.y = pActors[v507].vPosition.y;
+            v732 = pActors[v507].uActorHeight;
+            a1.vPosition.z = pActors[v507].vPosition.z - (unsigned int)(signed __int64)((double)v732 * unk_4D8548);
+            v508 = 8 * dword_50BF30[a2];
+            LOBYTE(v508) = v508 | 3;
+            a1.field_5C = v508;
+            v509 = a1.Create(0, v1, v1, v1);
+            v510 = a2;
+            DamageMonsterFromParty(8 * v509 | 2, dword_50BF30[a2], (Vec3_int_ *)&v688);
+            a2 = v510 + 1;
+          }
+          while ( v510 + 1 < SHIDWORD(v733) );
+        }
+        for ( a2 = v1; a2 < SHIDWORD(v733); ++a2 )
+        {
+          v511 = &pActors[dword_50BF30[a2]];
+          a1.vPosition.x = v511->vPosition.x;
+          a1.vPosition.y = v511->vPosition.y;
+          v732 = v511->uActorHeight;
+          a1.vPosition.z = v511->vPosition.z - (unsigned int)(signed __int64)((double)v732 * unk_4D8548);
+          v512 = 8 * dword_50BF30[a2];
+          LOBYTE(v512) = v512 | 3;
+          a1.field_5C = v512;
+          a1.Create(0, v1, v1, v1);
+          v513 = v511->pActorBuffs;
+          v726 = (Player *)22;
+          do
+          {
+            v513->Reset();
+            ++v513;
+            v726 = (Player *)((char *)v726 - 1);
+          }
+          while ( *(float *)&v726 != 0.0 );
+        }
+        goto LABEL_1056;
+      case 82:
+        v514 = v12 - 2;
+        if ( !v514 )
+          goto LABEL_955;
+        v515 = v514 - 1;
+        if ( v515 )
+        {
+          if ( v515 == 1 )
+          {
+            v516 = 900 * v2;
+            amount = 5;
+          }
+          else
+          {
+LABEL_955:
+            v516 = 300 * v2;
+            amount = 1;
+          }
+        }
+        else
+        {
+          v516 = 900 * v2;
+          amount = 3;
+        }
+        v733 = __PAIR__(v1, v516);
+        v517 = 8 * v3->uPlayerID;
+        LOBYTE(v517) = v517 | 4;
+        if ( (signed int)uNumActors > v1 )
+        {
+          v518 = (char *)&pActors[0].uAIState;
+          v726 = (Player *)uNumActors;
+          do
+          {
+            v519 = *(short *)v518;
+            if ( *(short *)v518 != 5 && v519 != 11 && v519 != 19 && v517 == *((int *)v518 + 159) )
+              ++HIDWORD(v733);
+            v518 += 836;
+            v726 = (Player *)((char *)v726 - 1);
+          }
+          while ( *(float *)&v726 != 0.0 );
+        }
+        if ( SHIDWORD(v733) >= amount )
+        {
+          v66 = pGlobalTXT_LocalizationStrings[648];
+          goto LABEL_201;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        sub_44FA4C_spawn_light_elemental(v3->uPlayerID, v731, v733);
+        goto LABEL_1056;
+      case 83:
+        v520 = v12 - 2;
+        if ( !v520 )
+          goto LABEL_973;
+        v521 = v520 - 1;
+        if ( v521 )
+        {
+          if ( v521 == 1 )
+          {
+            LODWORD(v733) = 18000 * v2;
+            v522 = 5 * v2 + 10;
+          }
+          else
+          {
+LABEL_973:
+            LODWORD(v733) = 10800 * v2;
+            v522 = 3 * v2 + 10;
+          }
+        }
+        else
+        {
+          LODWORD(v733) = 14400 * v2;
+          v522 = 4 * v2 + 10;
+        }
+        amount = v522;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v523 = v3->spellnum;
+        v524 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v523, v1);
+        v83 = 1;
+        v525 = v3->spellnum;
+        v526 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v525, 1u);
+        v527 = v3->spellnum;
+        v528 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v527, 2u);
+        v529 = v3->spellnum;
+        v530 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v529, 3u);
+        v673 = v1;
+        v732 = (int)v733 << 7;
+        v662 = v1;
+        v655 = amount;
+        v652 = v731;
+        v183 = (signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v137 = (char *)&pParty->pPartyBuffs[2];
+        goto LABEL_976;
+      case 84:
+        v67 = 2;
+        if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+        {
+          v66 = pGlobalTXT_LocalizationStrings[497];
+          goto LABEL_202;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v531 = sub_46A6AC((int)dword_50BF30, 100, 4096);
+        ++a1.uItemType;
+        v726 = (Player *)v531;
+        v696 = v1;
+        v695 = v1;
+        v694 = v1;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v532 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        a1.uFacing = v1;
+        v532 *= 8;
+        LOBYTE(v532) = v532 | 4;
+        a1.field_58 = v532;
+        a1.uSoundID = LOWORD(v3->field_10);
+        a2 = v1;
+        if ( (signed int)v726 > v1 )
+        {
+          do
+          {
+            v533 = dword_50BF30[a2];
+            a1.vPosition.x = pActors[v533].vPosition.x;
+            a1.vPosition.y = pActors[v533].vPosition.y;
+            v732 = pActors[v533].uActorHeight;
+            a1.vPosition.z = pActors[v533].vPosition.z - (unsigned int)(signed __int64)((double)v732 * unk_4D8548);
+            v534 = 8 * dword_50BF30[a2];
+            LOBYTE(v534) = v534 | 3;
+            a1.field_5C = v534;
+            v535 = a1.Create(0, v1, v1, v1);
+            v536 = a2;
+            DamageMonsterFromParty(8 * v535 | 2, dword_50BF30[a2], (Vec3_int_ *)&v694);
+            a2 = v536 + 1;
+          }
+          while ( v536 + 1 < (signed int)v726 );
+        }
+        v537 = pGame->GetStru6();
+        pGame->GetStru6()->_4A8BFC();
+        goto LABEL_1056;
+      case 85:
+        v538 = v12 - 2;
+        if ( v538 && (v539 = v538 - 1) != 0 && v539 == 1 )
+        {
+          amount = 5 * v2;
+          v540 = 18000 * v2;
+        }
+        else
+        {
+          amount = 4 * v2;
+          v540 = 14400 * v2;
+        }
+        v730 = v540;
+        LODWORD(v733) = v540;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v541 = v3->spellnum;
+        v542 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v541, v1);
+        v543 = v3->spellnum;
+        v544 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v543, 1u);
+        v545 = v3->spellnum;
+        v546 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v545, 2u);
+        v547 = v3->spellnum;
+        v548 = pGame->GetStru6();
+        pGame->GetStru6()->SetPlayerBuffAnim(v547, 3u);
+        v732 = v730 << 7;
+        v549 = (double)(v730 << 7) * 0.033333335;
+        *((float *)&v733 + 1) = v549;
+        v712 = (signed __int64)v549;
+        pParty->pPartyBuffs[ 1].Apply(pParty->uTimePlayed + (signed __int64)v549, v731, amount, v1, v1);
+        pParty->pPartyBuffs[12].Apply(pParty->uTimePlayed + v712, v731, amount, v1, v1);
+        pParty->pPartyBuffs[ 6].Apply(pParty->uTimePlayed + v712, v731, amount, v1, v1);
+        pParty->pPartyBuffs[17].Apply(pParty->uTimePlayed + v712, v731, amount, v1, v1);
+        pParty->pPartyBuffs[ 0].Apply(pParty->uTimePlayed + v712, v731, amount, v1, v1);
+        pParty->pPartyBuffs[ 4].Apply(pParty->uTimePlayed + v712, v731, amount, v1, v1);
+        v550 = v2 + 5;
+        pParty->pPartyBuffs[ 5].Apply(
+          (signed __int64)((double)(signed __int64)pParty->uTimePlayed + *((float *)&v733 + 1)),
+          v731,
+          v550,
+          v1,
+          v1);
+        v668 = v1;
+        v658 = v1;
+        v653 = v550;
+        v651 = v731;
+        v28 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed + *((float *)&v733 + 1));
+LABEL_992:
+        v27 = (char *)&pParty->pPartyBuffs[19];
+        goto LABEL_103;
+      case 86:
+        v551 = v12 - 2;
+        if ( !v551 )
+          goto LABEL_998;
+        v552 = v551 - 1;
+        if ( v552 )
+        {
+          if ( v552 == 1 )
+          {
+            amount = 15;
+            HIDWORD(v733) = 20;
+            goto LABEL_1000;
+          }
+LABEL_998:
+          v678 = 4;
+        }
+        else
+        {
+          v678 = 12;
+        }
+        amount = v678;
+        HIDWORD(v733) = v678;
+LABEL_1000:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        y = (char *)(60 * (v2 * HIDWORD(v733) + 60));
+        v732 = (300 * amount * v2 + 60) << 7;
+        v730 = v2 + 5;
+        v726 = (Player *)v1;
+        v553 = (char *)&pParty->pPlayers[0].pConditions[1];
+        *((float *)&v733 + 1) = (double)v732 * 0.033333335;
+        do
+        {
+          v554 = v3->spellnum;
+          v555 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v554, v1);
+          v556 = v3->spellnum;
+          v557 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v556, 1u);
+          v558 = v3->spellnum;
+          v559 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v558, 2u);
+          v560 = v3->spellnum;
+          v561 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v560, 3u);
+          ((SpellBuff *)(v553 + 6056))->Apply(
+            (signed __int64)((double)(signed __int64)pParty->uTimePlayed + *((float *)&v733 + 1)),
+            v731,
+            v730,
+            v1,
+            v1);
+          if ( *(_QWORD *)v553 )
+            v726 = (Player *)1;
+          v553 += 6972;
+        }
+        while ( (signed int)v553 < (signed int)&pParty->pHirelings[0].uFlags );
+        v562 = v731;
+        pParty->pPartyBuffs[9].Apply(
+          (signed __int64)((double)(signed __int64)pParty->uTimePlayed + *((float *)&v733 + 1)),
+          v731,
+          v730,
+          v1,
+          v1);
+        pParty->pPartyBuffs[14].Apply(
+          (signed __int64)((double)(signed __int64)pParty->uTimePlayed + *((float *)&v733 + 1)),
+          v562,
+          v1,
+          v1,
+          v1);
+        pParty->pPartyBuffs[15].Apply(
+          (signed __int64)((double)(signed __int64)pParty->uTimePlayed + *((float *)&v733 + 1)),
+          v562,
+          v730,
+          v1,
+          v1);
+        if ( v726 != (Player *)v1 )
+          goto LABEL_1056;
+        v668 = v1;
+        v732 = (int)y << 7;
+        v658 = v1;
+        v653 = v730;
+        v651 = v562;
+        v28 = (signed __int64)((double)(signed int)((int)y << 7) * 0.033333335
+                             + (double)(signed __int64)pParty->uTimePlayed);
+        v27 = (char *)&pParty->pPartyBuffs[8];
+        goto LABEL_103;
+      case 88:
+        amount = 3;
+        if ( pPlayer->uNumDivineInterventionCastsThisDay >= 3u )
+          goto LABEL_200;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        a2 = v1;
+        _this = (ItemGen *)&pPlayers[1];
+        do
+        {
+          v563 = 0;
+          do
+          {
+            v564 = _this->uItemID;
+            *(int *)(v563 + _this->uItemID) = v1;
+            v563 += 8;
+            *(int *)(v563 + v564 - 4) = v1;
+          }
+          while ( v563 <= 128 );
+          v565 = ((Player *)_this->uItemID)->GetMaxHealth();
+          v566 = (Player **)_this;
+          *(int *)(_this->uItemID + 6460) = v565;
+          v567 = (*v566)->GetMaxMana();
+          v568 = a2;
+          *(int *)(_this->uItemID + 6464) = v567;
+          v569 = v3->spellnum;
+          v570 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v569, v568);
+          ++a2;
+          _this = (ItemGen *)((char *)_this + 4);
+        }
+        while ( (signed int)this < (signed int)&qword_A750D8 );
+        v571 = pPlayer;
+        v572 = (char *)&pPlayer->sAgeModifier;
+        if ( pPlayer->sAgeModifier + 10 >= 120 )
+          *(short *)v572 = 120;
+        else
+          *(short *)v572 = pPlayer->sAgeModifier + 10;
+        sRecoveryTime += -5 * v2;
+        ++v571->uNumDivineInterventionCastsThisDay;
+        goto LABEL_1056;
+      case 89:
+        v573 = v12 - 2;
+        if ( v573 )
+        {
+          v574 = v573 - 1;
+          if ( v574 )
+          {
+            if ( v574 == 1 )
+              v575 = 5 * v2;
+            else
+              v575 = 2 * v2;
+          }
+          else
+          {
+            v575 = 4 * v2;
+          }
+        }
+        else
+        {
+          v575 = 3 * v2;
+        }
+        amount = v575;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v576 = *(int *)&v3->field_C;
+        if ( v576 == v1 )
+        {
+          v583 = v3->uPlayerID_2;
+          v584 = v3->spellnum;
+          v585 = (char *)&pParty->pPlayers[v3->uPlayerID_2];
+          v586 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v584, v583);
+          if ( *((_QWORD *)v585 + 14) )
+          {
+            ((Player *)v585)->SetCondition(0x11u, 1);
+            v587 = ((Player *)v585)->GetSexByVoice();
+            ReloadPlayerPortraits(v3->uPlayerID_2, (v587 != 0) + 23);
+            *((_QWORD *)v585 + 17) = pParty->uTimePlayed;
+          }
+          goto LABEL_83;
+        }
+        v577 = (Player *)(v576 >> 3);
+        v726 = v577;
+        if ( v577 == (Player *)-1 )
+        {
+          v66 = pGlobalTXT_LocalizationStrings[496];
+          goto LABEL_201;
+        }
+        v578 = (int)&pActors[(int)v577];
+        v721 = v578;
+        if ( *(short *)(v578 + 40) > (signed __int16)v1 || (v579 = *(short *)(v578 + 176), v579 != 5) && v579 != 4 )
+          goto LABEL_200;
+        ++a1.uItemType;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v580 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        v581 = v721;
+        v580 *= 8;
+        LOBYTE(v580) = v580 | 4;
+        a1.uFacing = v1;
+        a1.field_58 = v580;
+        a1.uSoundID = LOWORD(v3->field_10);
+        a1.vPosition.x = *(short *)(v721 + 142);
+        a1.vPosition.y = *(short *)(v721 + 144);
+        v732 = *(short *)(v721 + 138);
+        v582 = 8 * (int)v726;
+        a1.vPosition.z = *(short *)(v721 + 146) - (unsigned int)(signed __int64)((double)v732 * unk_4D8548);
+        LOBYTE(v582) = 8 * (char)v726 | 3;
+        a1.field_5C = v582;
+        a1.Create(0, v1, v1, v1);
+        if ( *(char *)(v581 + 52) > amount )
+          goto LABEL_83;
+        Actor::Resurrect((unsigned int)v726);
+        *(char *)(v581 + 61) = 0;
+        *(char *)(v581 + 53) = 0;
+        *(char *)(v581 + 54) = 0;
+        *(char *)(v581 + 55) = 0;
+        *(char *)(v581 + 56) = 0;
+        *(char *)(v581 + 57) = 0;
+        *(int *)(v581 + 712) = 9999;
+        *(char *)(v581 + 38) &= 0xF7u;
+        *(int *)(v581 + 708) = v1;
+        ((SpellBuff *)(v581 + 356))->Reset();
+        ((SpellBuff *)(v581 + 228))->Reset();
+        ((SpellBuff *)(v581 + 404))->Reset();
+        if ( *(short *)(v581 + 40) > 10 * amount )
+          *(short *)(v581 + 40) = 10 * amount;
+        goto LABEL_1056;
+      case 91:
+        v588 = v12 - 1;
+        amount = 16;
+        if ( v588 && (v589 = v588 - 1) != 0 && (v590 = v589 - 1) != 0 )
+        {
+          if ( v590 == 1 )
+            LODWORD(v733) = v1;
+        }
+        else
+        {
+          LODWORD(v733) = 3600 * v2;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        HIDWORD(v733) = (int)(char *)&pParty + 6972 * v3->uPlayerID_2 + 36 * a2 + 3040;
+        v732 = (signed int)&pItemsTable->pItems[*(int *)HIDWORD(v733)].pIconName;
+        ((ItemGen *)HIDWORD(v733))->UpdateTempBonus(pParty->uTimePlayed);
+        if ( *(int *)HIDWORD(v733) >= 64 && *(int *)HIDWORD(v733) <= 65
+          || *(char *)(HIDWORD(v733) + 20) & 2
+          || *(int *)(HIDWORD(v733) + 12) != v1
+          || *(int *)(HIDWORD(v733) + 4) != v1
+          || (v591 = *(char *)(v732 + 28)) != 0 && v591 != 1 && v591 != 2
+          || pItemsTable->_456D5E_is_some_material((ItemGen *)HIDWORD(v733)) )
+          goto LABEL_199;
+        v592 = HIDWORD(v733);
+        v14 = v731 == 4;
+        *(int *)(HIDWORD(v733) + 12) = 16;
+        if ( !v14 )
+        {
+          v732 = (int)v733 << 7;
+          *(_QWORD *)(v592 + 28) = pParty->uTimePlayed
+                                 + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+          *(int *)(v592 + 20) |= 8u;
+        }
+        *(char *)(v592 + 20) |= 0x80u;
+        goto LABEL_1055;
+      case 93:
+        v593 = v12 - 2;
+        if ( !v593 )
+          goto LABEL_1062;
+        v594 = v593 - 1;
+        if ( v594 )
+        {
+          if ( v594 == 1 )
+            amount = 9;
+          else
+LABEL_1062:
+            amount = 5;
+        }
+        else
+        {
+          amount = 7;
+        }
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v726 = (Player *)((signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360);
+        v732 = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360 / (amount - 1);
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.vPosition.x = pParty->vPosition.x;
+        a1.vPosition.y = pParty->vPosition.y;
+        a1.uAttributes = v1;
+        a1.vPosition.z = pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2;
+        a1.uSectorID = pIndoor->GetSector(
+                         pParty->vPosition.x,
+                         pParty->vPosition.y,
+                         pParty->vPosition.z + (signed int)pParty->uPartyHeight / 2);
+        a1.uSpriteFrameID = v1;
+        v595 = 8 * v3->uPlayerID;
+        LOBYTE(v595) = v595 | 4;
+        a1.field_58 = v595;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uSoundID = LOWORD(v3->field_10);
+        if ( pParty->bTurnBasedModeOn == 1 )
+          LOBYTE(a1.uAttributes) |= 4u;
+        v596 = (signed int)v726 / -2;
+        y = (char *)((signed int)v726 / 2);
+        if ( (signed int)v726 / -2 <= (signed int)v726 / 2 )
+        {
+          v597 = v715.uYawAngle;
+          do
+          {
+            a1.uFacing = v596 + v597;
+            if ( a1.Create(
+                   v596 + v597,
+                   v715.uPitchAngle,
+                   pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
+                   v3->uPlayerID + 1) != -1
+              && pParty->bTurnBasedModeOn == 1 )
+              ++pTurnEngine->field_1C;
+            v596 += v732;
+          }
+          while ( v596 <= (signed int)y );
+        }
+        goto LABEL_1056;
+      case 94:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( v731 == 1 || v731 == 2 )
+        {
+          v598 = 180 * v2;
+          goto LABEL_1081;
+        }
+        if ( v731 == 3 )
+        {
+          v598 = 300 * v2;
+LABEL_1081:
+          LODWORD(v733) = v598;
+          goto LABEL_1082;
+        }
+        if ( v731 == 4 )
+          LODWORD(v733) = 29030400;
+LABEL_1082:
+        v599 = a2 >> 3;
+        if ( (a2 & 7) != 3 )
+          goto LABEL_1056;
+        v730 = 836 * v599;
+        if ( !MonsterStats::BelongsToSupertype(pActors[v599].pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD) )
+          goto LABEL_83;
+        if ( !stru_50C198.GetMagicalResistance((Actor *)((char *)pActors + v730), 0xAu) )
+          goto LABEL_200;
+        ((SpellBuff *)((char *)&pActors[0].pActorBuffs[9] + v730))->Reset();
+        ((SpellBuff *)((char *)&pActors[0].pActorBuffs[1] + v730))->Reset();
+        v732 = (int)v733 << 7;
+        ((SpellBuff *)((char *)&pActors[0].pActorBuffs[12] + v730))->Apply(
+          pParty->uTimePlayed + (signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335),
+          v731,
+          v1,
+          v1,
+          v1);
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        v60 = pObjectList->ObjectIDByItemID(a1.uItemType);
+        v61 = v730;
+LABEL_1086:
+        v600 = *(__int16 *)((char *)&pActors[0].vPosition.y + v61);
+        v601 = *(__int16 *)((char *)&pActors[0].vPosition.x + v61);
+        a1.uObjectDescID = v60;
+        a1.vPosition.x = v601;
+        v602 = *(unsigned __int16 *)((char *)&pActors[0].uActorHeight + v61);
+        v603 = *(__int16 *)((char *)&pActors[0].vPosition.z + v61);
+        a1.vPosition.y = v600;
+        v676 = v603 + v602;
+        v665 = v600;
+        a1.vPosition.z = v603 + v602;
+        v657 = v601;
+LABEL_1087:
+        a1.uAttributes = v1;
+        a1.uSectorID = pIndoor->GetSector(v657, v665, v676);
+        a1.uSpriteFrameID = v1;
+        v604 = 8 * v3->uPlayerID;
+        LOBYTE(v604) = v604 | 4;
+        a1.field_58 = v604;
+        a1.field_5C = a2;
+        a1.field_60_distance_related_prolly_lod = LOBYTE(v715.uDistance);
+        a1.uFacing = LOWORD(v715.uYawAngle);
+        LOWORD(v604) = LOWORD(v3->field_10);
+        LOBYTE(a1.uAttributes) |= 0x80u;
+        a1.uSoundID = v604;
+        a1.Create(0, v1, v1, v3->uPlayerID + 1);
+        goto LABEL_1056;
+      case 96:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        HIDWORD(v733) = v1;
+        memset(&pStru179, v1, 0xFA0u);
+        _this = (ItemGen *)v1;
+        v605 = (char *)pParty->pHirelings;
+        do
+        {
+          if ( *(int *)v605 != v1 )
+          {
+            v606 = HIDWORD(v733)++;
+            pStru179->field_0[v606] = (int)((char *)&_this->uItemID + 1);
+          }
+          _this = (ItemGen *)((char *)_this + 1);
+          v605 += 76;
+        }
+        while ( (signed int)v605 < (signed int)&pParty->pPickedItem );
+        _this = (ItemGen *)v1;
+        if ( (signed int)pNPCStats->uNumNewNPCs > v1 )
+        {
+          v730 = (int)pNPCStats->pNewNPCData;
+          HIDWORD(v733) = 4 * HIDWORD(v733) + 6043152;
+          do
+          {
+            if ( *(char *)(v730 + 8) & 0x80
+              && (pParty->pHirelings[0].pName == (char *)v1 || strcmp(*(const char **)v730, pParty->pHirelings[0].pName))
+              && (pParty->pHirelings[1].pName == (char *)v1 || strcmp(*(const char **)v730, pParty->pHirelings[1].pName)) )
+            {
+              v607 = HIDWORD(v733);
+              HIDWORD(v733) += 4;
+              *(int *)v607 = (int)_this + 3;
+            }
+            _this = (ItemGen *)((char *)_this + 1);
+            v730 += 76;
+          }
+          while ( (signed int)this < (signed int)pNPCStats->uNumNewNPCs );
+        }
+        v608 = v3->uPlayerID_2;
+        if ( v608 != 4 && v608 != 5
+          || (v609 = (signed int)*(&pFontCChar + v608 + (unsigned __int8)pParty->field_709), v609 <= v1)
+          || v609 >= 3 )
+          goto LABEL_200;
+        v610 = 76 * v609;
+        *((int *)&pParty->pPlayers[3].pInstalledBeacons[4].uBeaconTime + 19 * v609) = v1;
+        v611 = pIconsFrameTable->FindIcon("spell96");
+        *(int *)((char *)&pParty->pPlayers[3].pInstalledBeacons[4].uBeaconTime + v610 + 4) = pIconsFrameTable->GetIconAnimLength(
+                                                                                                 v611);
+        v232 = 1;
+        *(int *)((char *)&pParty->pPlayers[3].pInstalledBeacons[3].field_18 + v610) = 1;
+        v612 = (char *)pParty->pPlayers;
+        do
+        {
+          *((int *)v612 + 1615) = ((Player *)v612)->GetMaxHealth();
+          *((int *)v612 + 1616) = ((Player *)v612)->GetMaxMana();
+          v612 += 6972;
+        }
+        while ( (signed int)v612 < (signed int)pParty->pHirelings );
+        v613 = (char *)&pOutdoor->ddm;
+        if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor)
+          v613 = (char *)&pIndoor->dlv;
+        *((int *)v613 + 2) += 15;
+        if ( *((int *)v613 + 2) > 10000 )
+          *((int *)v613 + 2) = 10000;
+LABEL_1112:
+        LODWORD(v727) = v232;
+        goto LABEL_83;
+      case 95:
+        if ( v12 <= v1 )
+          goto LABEL_1119;
+        if ( v12 <= 3 )
+        {
+          v614 = 300 * (v2 + 12);
+        }
+        else
+        {
+          if ( v12 != 4 )
+            goto LABEL_1119;
+          v614 = 900 * (v2 + 4);
+        }
+        LODWORD(v733) = v614;
+LABEL_1119:
+        v615 = v2 + 5;
+        amount = v615;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        if ( v731 != 3 && v731 != 4 )
+        {
+          v616 = v3->uPlayerID_2;
+          v617 = v3->spellnum;
+          v618 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v617, v616);
+          v668 = v1;
+          v658 = v716;
+          v732 = (int)v733 << 7;
+          v653 = v615;
+          v651 = v731;
+          v28 = pParty->uTimePlayed + (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+          v27 = (char *)&pParty->pPlayers[v3->uPlayerID_2].pPlayerBuffs[10];
+          goto LABEL_103;
+        }
+        a2 = v1;
+        v732 = (int)v733 << 7;
+        v717 = (signed int)(signed __int64)((double)(signed int)((int)v733 << 7) * 0.033333335);
+        v619 = &pParty->pPlayers[0].pPlayerBuffs[10];
+        do
+        {
+          v620 = a2;
+          v621 = v3->spellnum;
+          v622 = pGame->GetStru6();
+          pGame->GetStru6()->SetPlayerBuffAnim(v621, v620);
+          v619->Apply(pParty->uTimePlayed + v717, v731, amount, v716, v1);
+          ++a2;
+          v619 = (SpellBuff *)((char *)v619 + 6972);
+        }
+        while ( (signed int)v619 < (signed int)&pParty->field_871C[504] );
+        goto LABEL_1056;
+      case 99:
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        v726 = (Player *)v1;
+        pGame->GetIndoorCamera();
+        v623 = (signed __int64)GetPickDepth();
+        HIDWORD(v733) = sub_46A6AC((int)dword_50BF30, 100, v623);
+        v709 = v1;
+        v708 = v1;
+        v707 = v1;
+        a1.stru_24.Reset();
+        a1.field_48 = v3->spellnum;
+        a1.field_4C = v2;
+        a1.field_50 = v731;
+        a1.uObjectDescID = pObjectList->ObjectIDByItemID(a1.uItemType);
+        a1.uAttributes = v1;
+        a1.uSectorID = v1;
+        a1.uSpriteFrameID = v1;
+        v624 = v3->uPlayerID;
+        a1.field_60_distance_related_prolly_lod = 0;
+        a1.uFacing = v1;
+        v624 *= 8;
+        LOBYTE(v624) = v624 | 4;
+        a1.field_58 = v624;
+        a1.uSoundID = LOWORD(v3->field_10);
+        a2 = v1;
+        if ( SHIDWORD(v733) > v1 )
+        {
+          v726 = (Player *)(HIDWORD(v733) * (7 * v2 + 25));
+          do
+          {
+            v625 = dword_50BF30[a2];
+            a1.vPosition.x = pActors[v625].vPosition.x;
+            a1.vPosition.y = pActors[v625].vPosition.y;
+            v732 = pActors[v625].uActorHeight;
+            a1.vPosition.z = pActors[v625].vPosition.z - (unsigned int)(signed __int64)((double)v732 * unk_4D8548);
+            v626 = 8 * dword_50BF30[a2];
+            LOBYTE(v626) = v626 | 3;
+            a1.field_5C = v626;
+            v627 = a1.Create(0, v1, v1, v1);
+            v628 = a2;
+            DamageMonsterFromParty(8 * v627 | 2, dword_50BF30[a2], (Vec3_int_ *)&v707);
+            a2 = v628 + 1;
+          }
+          while ( v628 + 1 < SHIDWORD(v733) );
+        }
+        v730 = v1;
+        v629 = 1;
+        do
+        {
+          v630 = pPlayers[v629];
+          if ( !v630->pConditions[2]
+            && !v630->pConditions[12]
+            && !v630->pConditions[13]
+            && !v630->pConditions[14]
+            && !v630->pConditions[15]
+            && !v630->pConditions[16] )
+          {
+            v631 = v730++;
+            v681[v631] = v629;
+          }
+          ++v629;
+        }
+        while ( v629 <= 4 );
+        v732 = (signed __int64)((double)(signed int)v726 / (double)v730);
+        HIDWORD(v733) = v1;
+        if ( v730 > v1 )
+        {
+          do
+          {
+            v632 = 4 * v681[HIDWORD(v733)] + 10965188;
+            v633 = pPlayers[v681[HIDWORD(v733)]];
+            v633->sHealth += v732;
+            v726 = *(Player **)v632;
+            v634 = v726->GetMaxHealth();
+            if ( v726->sHealth > v634 )
+              *(int *)(*(int *)v632 + 6460) = v726->GetMaxHealth();
+            v635 = HIDWORD(v733);
+            v636 = WORD2(v733);
+            v637 = v3->spellnum;
+            v638 = pGame->GetStru6();
+            pGame->GetStru6()->SetPlayerBuffAnim(v637, v636);
+            HIDWORD(v733) = v635 + 1;
+          }
+          while ( v635 + 1 < v730 );
+        }
+        v639 = pGame->GetStru6();
+        pGame->GetStru6()->FadeScreen__like_Turn_Undead_and_mb_Armageddon(v1, 0x40u);
+        goto LABEL_1056;
+      case 98:
+        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+        {
+          v66 = pGlobalTXT_LocalizationStrings[499];
+          goto LABEL_201;
+        }
+        v640 = v12 - 2;
+        if ( !v640 || (v641 = v640 - 1) == 0 || (amount = 4, v641 != 1) )
+          amount = 3;
+        if ( pPlayer->uNumArmageddonCasts >= amount || pParty->field_1613C > v1 )
+          goto LABEL_200;
+        if ( !pPlayer->CanCastSpell(uRequiredMana) )
+          goto LABEL_83;
+        pParty->field_1613C = 256;
+        pParty->field_16140 = v2;
+        ++pPlayer->uNumArmageddonCasts;
+        if ( pParty->bTurnBasedModeOn == 1 )
+          ++pTurnEngine->field_1C;
+        v726 = (Player *)50;
+        do
+        {
+          v642 = rand() % 4096 - 2048;
+          v643 = rand();
+          v721 = v642 + pParty->vPosition.x;
+          y = (char *)(pParty->vPosition.y + v643 % 4096 - 2048);
+          v732 = GetTerrainHeightsAroundParty2(v642 + pParty->vPosition.x, (int)y, (int *)&v710, v1);
+          v644 = rand();
+          sub_42F7EB_DropItemAt(0xFE6u, v721, (int)y, v732 + 16, v644 % 500 + 500, 1, v1, v1, (ItemGen *)v1);
+          v726 = (Player *)((char *)v726 - 1);
+        }
+        while ( *(float *)&v726 != 0.0 );
+        goto LABEL_1056;
+      default:
+        goto LABEL_83;
+    }
+    while ( 2 )
+    {
+      if ( v731 == 4 )
+      {
+        if ( *((_QWORD *)v222 + 2) )
+        {
+          *((int *)v222 + 4) = v1;
+          *((int *)v222 + 5) = v1;
+          goto LABEL_439;
+        }
+      }
+      else
+      {
+        v732 = amount << 7;
+        v223 = ((Player *)v222)->DiscardConditionIfLastsLongerThan(
+                 2u,
+                 pParty->uTimePlayed - (signed int)(signed __int64)((double)(amount << 7) * 0.033333335));
+        v222 = (char *)HIDWORD(v733);
+        if ( v223 )
+LABEL_439:
+          ((Player *)v222)->PlaySound(103, v1);
+      }
+      v222 += 6972;
+      HIDWORD(v733) = (int)v222;
+      if ( (signed int)v222 >= (signed int)pParty->pHirelings )
+        goto LABEL_1056;
+      continue;
+    }
+  }
+  if ( pParty->bTurnBasedModeOn == v1 )
+  {
+    v646 = pPlayer;
+    pPlayer->SetRecoveryTime((signed __int64)(flt_6BE3A4_debug_recmod1 * 213.3333333333333));
+    v647 = n;
+  }
+  else
+  {
+    v647 = n;
+    v646 = pPlayer;
+    v648 = sRecoveryTime;
+    v649 = pPlayer;
+    pParty->pTurnBasedPlayerRecoveryTimes[v711[n].uPlayerID] = 100;
+    v649->SetRecoveryTime(v648);
+    pTurnEngine->_40471C();
+  }
+  ShowStatusBarString(pGlobalTXT_LocalizationStrings[428], 2u);
+  pAudioPlayer->PlaySound(SOUND_PlayerCantCastSpell, v1, v1, -1, v1, v1, v1, v1);
+  v711[v647].spellnum = v1;
+  v646->sMana -= uRequiredMana;
+}
+//----- (0042EB42) --------------------------------------------------------
+__int16 ObjectList::ObjectIDByItemID(unsigned __int16 uItemID)
+{
+  unsigned int v2; // edx@1
+  signed int v3; // eax@1
+  char *v4; // ecx@2
+
+  v2 = this->uNumObjects;
+  v3 = 0;
+  if ( (signed int)this->uNumObjects <= 0 )
+  {
+LABEL_5:
+    LOWORD(v3) = 0;
+  }
+  else
+  {
+    v4 = (char *)&this->pObjects->uObjectID;
+    while ( uItemID != *(short *)v4 )
+    {
+      ++v3;
+      v4 += 56;
+      if ( v3 >= (signed int)v2 )
+        goto LABEL_5;
+    }
+  }
+  return v3;
+}
+
+
+
+//----- (0042EB78) --------------------------------------------------------
+int IconFrameTable::GetIconAnimLength(unsigned int uIconID)
+{
+  return 8 * this->pIcons[uIconID].uAnimLength;
+}
+
+//----- (0042EB8D) --------------------------------------------------------
+void GUIMessageQueue::SendMessage(UIMessageType msg, int param, unsigned int a4)
+{
+  if (uNumMessages < 40)
+  {
+    pMessages[uNumMessages].eType = msg;
+    pMessages[uNumMessages].param = param;
+    pMessages[uNumMessages++].field_8 = a4;
+  }
+}
+
+//----- (0042EBBE) --------------------------------------------------------
+int __fastcall sub_42EBBE(int a1, int a2)
+{
+  return (unsigned __int64)(a2 * (signed __int64)a1) >> 16;
+}
+// 42EBBE: using guessed type int __fastcall sub_42EBBE(int, int);
+
+//----- (0042EBDB) --------------------------------------------------------
+int stru193_math::_42EBDB(int angle)
+{
+  return SinCos(angle - this->uIntegerHalfPi);
+}
+
+//----- (0042ECB5) --------------------------------------------------------
+bool __cdecl _42ECB5_PlayerAttacksActor()
+{
+  unsigned int v0; // ebx@1
+  Player *v1; // esi@1
+  bool result; // eax@1
+  int v3; // edi@2
+  unsigned int v4; // eax@7
+  char *v5; // eax@8
+  int v6; // ecx@9
+  signed int v7; // eax@16
+  Actor *v8; // edi@20
+  unsigned int v9; // ecx@21
+  char *v10; // eax@26
+  char *v11; // eax@26
+  unsigned int v12; // eax@47
+  char *v13; // eax@47
+  char *v14; // eax@47
+  unsigned int v15; // ebx@54
+  int v16; // [sp-10h] [bp-4Ch]@24
+  int v17; // [sp-10h] [bp-4Ch]@44
+  unsigned int v18; // [sp-Ch] [bp-48h]@24
+  unsigned int v19; // [sp-Ch] [bp-48h]@44
+  __int16 v20; // [sp-8h] [bp-44h]@24
+  __int16 v21; // [sp-8h] [bp-44h]@44
+  int v22; // [sp-4h] [bp-40h]@24
+  int v23; // [sp-4h] [bp-40h]@44
+  SoundID v24; // [sp-4h] [bp-40h]@58
+  Vec3_int_ a3; // [sp+Ch] [bp-30h]@19
+  unsigned int a2; // [sp+18h] [bp-24h]@20
+  unsigned int v27; // [sp+1Ch] [bp-20h]@1
+  char *v28; // [sp+20h] [bp-1Ch]@9
+  int v29; // [sp+24h] [bp-18h]@16
+  int v30; // [sp+28h] [bp-14h]@16
+  int v31; // [sp+2Ch] [bp-10h]@4
+  int v32; // [sp+30h] [bp-Ch]@7
+  int v33; // [sp+34h] [bp-8h]@7
+  int v34; // [sp+38h] [bp-4h]@17
+
+  v0 = uActiveCharacter;
+  v27 = 6972 * uActiveCharacter;
+  v1 = (Player *)&stru_AA1058[3].pSounds[6972 * uActiveCharacter + 40552];
+  result = ((Player *)&stru_AA1058[3].pSounds[6972 * uActiveCharacter + 40552])->CanAct();
+  if ( result )
+  {
+    pStru277->_427D48(v0);
+    v3 = 0;
+    if ( (signed __int64)pParty->pPartyBuffs[11].uExpireTime > 0 )
+      pParty->pPartyBuffs[11].Reset();
+    v31 = v1->pEquipment.uBow;
+    if ( v31 && v1->field_1F5[36 * v31 + 15] & 2 )
+      v31 = 0;
+    v4 = v1->pEquipment.uMainHand;
+    v32 = 0;
+    v33 = 0;
+    if ( v4 )
+    {
+      v5 = (char *)v1 + 36 * v4;
+      if ( !(v5[516] & 2) )
+      {
+        v28 = v5 + 496;
+        v6 = *((int *)v5 + 124);
+        if ( pItemsTable->pItems[v6].uEquipType == 12 )
+        {
+          if ( *((int *)v5 + 128) <= 0 )
+          {
+            *(int *)v28 = 0;
+            v1->pEquipment.uMainHand = 0;
+          }
+          else
+          {
+            v32 = *((int *)v5 + 124);
+          }
+        }
+        else
+        {
+          if ( v6 == 64 || v6 == 65 )
+            v33 = *((int *)v5 + 124);
+        }
+      }
+    }
+    v30 = 0;
+    v29 = 0;
+    v28 = 0;
+    v7 = pMouse->uPointingObjectID;
+    if ( (pMouse->uPointingObjectID & 7) != 3 || (v34 = pMouse->uPointingObjectID, !pActors[v7 >> 3].CanAct()) )
+      v34 = stru_50C198.FindClosesActor(5120, 0, 0);
+    a3.z = 0;
+    a3.y = 0;
+    a3.x = 0;
+    if ( (v34 & 7) == 3 )
+    {
+      a2 = v34 >> 3;
+      v8 = &pActors[v34 >> 3];
+      v34 = sub_452A9E((v8->vPosition.x - pParty->vPosition.x) * (v8->vPosition.x - pParty->vPosition.x) + (v8->vPosition.y - pParty->vPosition.y) * (v8->vPosition.y - pParty->vPosition.y) + (v8->vPosition.z - pParty->vPosition.z) * (v8->vPosition.z - pParty->vPosition.z))
+          - v8->uActorRadius;
+      if ( v34 >= 0 )
+      {
+        v9 = 0;
+      }
+      else
+      {
+        v9 = 0;
+        v34 = 0;
+      }
+      if ( v33 != v9 )
+      {
+        v28 = (char *)1;
+        v22 = v0 + 8;
+        v20 = v9;
+        v18 = v9;
+        v16 = 102;
+LABEL_34:
+        _42777D_CastSpell_UseWand_ShootArrow(v16, v0 - 1, v18, v20, v22);
+LABEL_28:
+        v3 = 0;
+        goto LABEL_29;
+      }
+      if ( v32 != v9 )
+      {
+        v29 = 1;
+        _42777D_CastSpell_UseWand_ShootArrow(
+          *((int *)&pSpellDatas[66].field_8
+          + *(int *)(&stru_AA1058[3].pSounds[36 * *(int *)&pParty->pArtifactsFound[v27 + 22] + 41048] + v27)),
+          v0 - 1,
+          8u,
+          v9,
+          v0 + 8);
+        v10 = &v1->field_1F5[36 * v1->pEquipment.uMainHand + 11];
+        --*(int *)v10;
+        v11 = (char *)v1 + 36 * v1->pEquipment.uMainHand;
+        if ( *((int *)v11 + 128) <= 0 )
+        {
+          *((int *)v11 + 124) = 0;
+          v1->pEquipment.uMainHand = 0;
+        }
+        goto LABEL_28;
+      }
+      if ( (double)v34 <= 407.2 )
+      {
+        a3.x = v8->vPosition.x - pParty->vPosition.x;
+        a3.y = v8->vPosition.y - pParty->vPosition.y;
+        a3.z = v8->vPosition.z - pParty->vPosition.z;
+        Vec3_int_::Normalize(&a3.x, &a3.y, &a3.z);
+        DamageMonsterFromParty((8 * v0 - 8) | 4, a2, &a3);
+        if ( v1->WearsItem(506, 1) || v1->WearsItem(506, 0) )
+          _42FA66_do_explosive_impact(
+            v8->vPosition.x,
+            v8->vPosition.y,
+            v8->vPosition.z + v8->uActorHeight / 2,
+            0,
+            512,
+            v0);
+      }
+      else
+      {
+        if ( v31 != v9 )
+        {
+          v30 = 1;
+          v22 = 0;
+          v20 = 0;
+          v18 = 0;
+          v16 = 100;
+          goto LABEL_34;
+        }
+      }
+      v3 = 0;
+      goto LABEL_39;
+    }
+    if ( v33 )
+    {
+      v28 = (char *)1;
+      v23 = v0 + 8;
+      v21 = 0;
+      v19 = 0;
+      v17 = 102;
+    }
+    else
+    {
+      if ( v32 )
+      {
+        v12 = v1->pEquipment.uMainHand;
+        v29 = 1;
+        _42777D_CastSpell_UseWand_ShootArrow(
+          *((int *)&pSpellDatas[66].field_8 + *(int *)&v1->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v12 + 5]),
+          v0 - 1,
+          8u,
+          0,
+          v0 + 8);
+        v13 = &v1->field_1F5[36 * v1->pEquipment.uMainHand + 11];
+        --*(int *)v13;
+        v14 = (char *)v1 + 36 * v1->pEquipment.uMainHand;
+        if ( *((int *)v14 + 128) <= 0 )
+        {
+          *((int *)v14 + 124) = 0;
+          v1->pEquipment.uMainHand = 0;
+        }
+LABEL_29:
+        v34 = v3;
+        if ( v30 == v3 )
+        {
+          if ( v29 != v3 )
+            return 1;
+          if ( v28 == (char *)v3 )
+          {
+            v15 = v1->pEquipment.uMainHand;
+            if ( v1->HasItemEquipped(EQUIP_TWO_HANDED) )
+              v34 = pItemsTable->pItems[*(int *)&v1->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5]].uSkillType;
+            pTurnEngine->_40471C();
+          }
+          else
+          {
+            v34 = 7;
+          }
+        }
+        else
+        {
+          v34 = 5;
+          v1->PlaySound(50, v3);
+        }
+        switch ( v34 )
+        {
+          case 0:
+            v24 = (SoundID)81;
+            goto LABEL_66;
+          case 1:
+            v24 = (SoundID)84;
+            goto LABEL_66;
+          case 2:
+            v24 = (SoundID)85;
+            goto LABEL_66;
+          case 3:
+            v24 = (SoundID)78;
+            goto LABEL_66;
+          case 4:
+            v24 = (SoundID)80;
+            goto LABEL_66;
+          case 5:
+            v24 = (SoundID)71;
+            goto LABEL_66;
+          case 6:
+            v24 = (SoundID)83;
+            goto LABEL_66;
+          case 7:
+            v24 = (SoundID)67;
+LABEL_66:
+            pAudioPlayer->PlaySound(v24, v3, v3, -1, v3, v3, v3, v3);
+            break;
+          default:
+            return 1;
+        }
+        return 1;
+      }
+      if ( !v31 )
+      {
+LABEL_39:
+        v31 = v1->GetAttackRecoveryTime(v3);
+        if ( v31 < 30 )
+          v31 = 30;
+        if ( pParty->bTurnBasedModeOn == v3 )
+          v1->SetRecoveryTime((signed __int64)(flt_6BE3A4_debug_recmod1 * (double)v31 * 2.133333333333333));
+        goto LABEL_29;
+      }
+      v23 = 0;
+      v21 = 0;
+      v19 = 0;
+      v30 = 1;
+      v17 = 100;
+    }
+    _42777D_CastSpell_UseWand_ShootArrow(v17, v0 - 1, v19, v21, v23);
+    goto LABEL_29;
+  }
+  return result;
+}
+
+//----- (0042F184) --------------------------------------------------------
+int stru319::FindClosesActor(int a2, int a3, int a4)
+{
+  int v4; // edi@1
+  stru319 *v5; // esi@1
+  int v6; // eax@2
+  int v7; // eax@4
+  int result; // eax@5
+  int *v9; // edx@8
+  signed int v10; // ebx@10
+  int v11; // edi@11
+  Actor *v12; // esi@12
+  unsigned __int16 v13; // ax@12
+  int v14; // eax@22
+  char v15; // zf@30
+  int v16; // esi@32
+  int v17; // ecx@34
+  stru319 *v18; // eax@39
+  int v19; // edx@39
+  int v20; // ecx@41
+  unsigned __int16 v21; // ax@42
+  unsigned int v22; // [sp+8h] [bp-24h]@11
+  unsigned int v23; // [sp+Ch] [bp-20h]@7
+  stru319 *v24; // [sp+10h] [bp-1Ch]@1
+  unsigned int v25; // [sp+14h] [bp-18h]@8
+  int *v26; // [sp+18h] [bp-14h]@8
+  int v27; // [sp+1Ch] [bp-10h]@10
+  int *v28; // [sp+20h] [bp-Ch]@10
+  unsigned int v29; // [sp+24h] [bp-8h]@7
+  int v30; // [sp+28h] [bp-4h]@6
+  int i; // [sp+38h] [bp+Ch]@33
+  signed int v32; // [sp+3Ch] [bp+10h]@32
+
+  v4 = 0;
+  v5 = this;
+  v24 = this;
+  if ( pRenderer->pRenderD3D )
+  {
+    v6 = a3 != 0;
+    if ( a4 )
+      LOBYTE(v6) = v6 | 8;
+    v7 = pGame->pVisInstance->_4C1944(3, a2, v6, 657456, -1);
+    if ( v7 != -1 )
+      return (unsigned __int16)v7;
+  }
+  else
+  {
+    v30 = 0;
+    if ( pRenderer->pActiveZBuffer )
+    {
+      v29 = viewparams->uScreenX;
+      v23 = viewparams->uScreenZ;
+      if ( (signed int)viewparams->uScreenY < (signed int)viewparams->uScreenW )
+      {
+        v25 = viewparams->uScreenW - viewparams->uScreenY;
+        v9 = &pRenderer->pActiveZBuffer[viewparams->uScreenX + 640 * viewparams->uScreenY];
+        v26 = &pRenderer->pActiveZBuffer[viewparams->uScreenX + 640 * viewparams->uScreenY];
+        do
+        {
+          if ( (signed int)v29 < (signed int)v23 )
+          {
+            v28 = v9;
+            v10 = v4;
+            v27 = v23 - v29;
+            do
+            {
+              v22 = *v28;
+              v11 = *v28 & 0xFFFF;
+              if ( (*(char *)v28 & 7) == 3 )
+              {
+                v12 = &pActors[(unsigned int)v11 >> 3];
+                v13 = v12->uAIState;
+                if ( v13 != 5 )
+                {
+                  if ( v13 != 4
+                    && v13 != 11
+                    && v13 != 19
+                    && v13 != 17
+                    && (!a3 || pActors[(unsigned int)v11 >> 3].GetActorsRelation(0)) )
+                  {
+                    if ( (!a4 || MonsterStats::BelongsToSupertype(v12->pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD))
+                      && v22 <= a2 << 16 )
+                    {
+                      v14 = 0;
+                      if ( v10 > 0 )
+                      {
+                        do
+                        {
+                          if ( dword_50BDA0[v14] == v11 )
+                            break;
+                          ++v14;
+                        }
+                        while ( v14 < v30 );
+                      }
+                      if ( v14 == v30 && v10 < 100 )
+                      {
+                        ++v30;
+                        dword_50BC10[v10] = v22;
+                        dword_50BDA0[v10] = v11;
+                        ++v10;
+                      }
+                    }
+                  }
+                }
+              }
+              ++v28;
+              --v27;
+            }
+            while ( v27 );
+            v4 = v30;
+            v5 = v24;
+          }
+          v9 = v26 + 640;
+          v15 = v25-- == 1;
+          v26 += 640;
+        }
+        while ( !v15 );
+      }
+      if ( v4 > 0 )
+      {
+        v32 = 1;
+        v16 = (int)dword_50BC10;
+        do
+        {
+          for ( i = v32; i < v4; ++i )
+          {
+            v17 = dword_50BC10[i];
+            if ( v17 < *(int *)v16 )
+            {
+              dword_50BC10[i] = *(int *)v16;
+              *(int *)v16 = v17;
+            }
+          }
+          ++v32;
+          v16 += 4;
+        }
+        while ( v32 - 1 < v4 );
+        v5 = v24;
+        if ( v4 > 0 )
+        {
+          v18 = v24;
+          v19 = v4;
+          do
+          {
+            *(int *)&v18->field_0 = (*(int *)&v18[(char *)dword_50BC10 - (char *)v24].field_0 >> 3) & 0x1FFF;
+            v18 += 4;
+            --v19;
+          }
+          while ( v19 );
+        }
+      }
+      v20 = 0;
+      for ( *(int *)&v5[2000].field_0 = v4; v20 < v4; ++v20 )
+      {
+        v21 = pActors[*(int *)&v5[4 * v20].field_0].uAIState;
+        if ( v21 != 4 && v21 != 5 )
+          break;
+      }
+      if ( v20 != v4 )
+      {
+        result = 8 * *(int *)&v5[4 * v20].field_0;
+        LOBYTE(result) = result | 3;
+        return result;
+      }
+    }
+  }
+  return 0;
+}
+
+
+//----- (0042F3D6) --------------------------------------------------------
+void InitializeTurnBasedAnimations(void *_this)
+{
+  unsigned int *v1; // edi@1
+
+  pIconIDs_Turn[0] = pIconsFrameTable->FindIcon("turn0");
+  pIconIDs_Turn[1] = pIconsFrameTable->FindIcon("turn1");
+  pIconIDs_Turn[2] = pIconsFrameTable->FindIcon("turn2");
+  pIconIDs_Turn[3] = pIconsFrameTable->FindIcon("turn3");
+  pIconIDs_Turn[4] = pIconsFrameTable->FindIcon("turn4");
+  uIconID_TurnStop = pIconsFrameTable->FindIcon("turnstop");
+  uIconID_TurnHour = pIconsFrameTable->FindIcon("turnhour");
+  uIconID_TurnStart = pIconsFrameTable->FindIcon("turnstart");
+  uIconID_CharacterFrame = pIconsFrameTable->FindIcon("aframe1");
+  uSpriteID_Spell11 = pSpriteFrameTable->FastFindSprite("spell11");
+  v1 = pIconIDs_Turn;
+  do
+  {
+    pIconsFrameTable->InitializeAnimation(*v1);
+    ++v1;
+  }
+  while ( (signed int)v1 < (signed int)&uIconID_TurnStop );
+  pIconsFrameTable->InitializeAnimation(uIconID_TurnHour);
+  pIconsFrameTable->InitializeAnimation(uIconID_TurnStop);
+  pIconsFrameTable->InitializeAnimation(uIconID_TurnStart);
+  pIconsFrameTable->InitializeAnimation(uIconID_CharacterFrame);
+}
+
+//----- (0042F4DA) --------------------------------------------------------
+signed int __cdecl sub_42F4DA()
+{
+  signed int v0; // edi@1
+  char *v1; // esi@4
+  int v2; // ebx@5
+  int v3; // eax@5
+  int v4; // ebx@5
+  unsigned int v5; // ecx@5
+  int v6; // edx@6
+  unsigned int v7; // edx@8
+  unsigned int v8; // edx@10
+  __int16 v9; // ax@12
+  signed int result; // eax@20
+  int v11; // [sp+Ch] [bp-10h]@5
+  int v12; // [sp+10h] [bp-Ch]@5
+  signed int v13; // [sp+14h] [bp-8h]@3
+
+  v0 = 5120;
+  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor)
+    v0 = 2560;
+  v13 = 0;
+  if ( (signed int)uNumActors <= 0 )
+  {
+LABEL_20:
+    result = 0;
+  }
+  else
+  {
+    v1 = (char *)&pActors[0].uAIState;
+    while ( 1 )
+    {
+      v2 = abs(*((short *)v1 - 17) - pParty->vPosition.x);
+      v11 = abs(*((short *)v1 - 16) - pParty->vPosition.y);
+      v12 = abs(*((short *)v1 - 15) - pParty->vPosition.z);
+      v3 = v2;
+      v4 = v11;
+      v5 = v12;
+      if ( v3 < v11 )
+      {
+        v6 = v3;
+        v3 = v11;
+        v4 = v6;
+      }
+      if ( v3 < v12 )
+      {
+        v7 = v3;
+        v3 = v12;
+        v5 = v7;
+      }
+      if ( v4 < (signed int)v5 )
+      {
+        v8 = v5;
+        v5 = v4;
+        v4 = v8;
+      }
+      if ( (signed int)(((unsigned int)(11 * v4) >> 5) + (v5 >> 2) + v3) < v0 )
+      {
+        v9 = *(short *)v1;
+        if ( *(short *)v1 != 5 )
+        {
+          if ( v9 != 4
+            && v9 != 11
+            && v9 != 19
+            && v9 != 17
+            && (*(v1 - 138) & 8 || ((Actor *)nullptr)->GetActorsRelation( (Actor *)(v1 - 176))) )
+            break;
+        }
+      }
+      ++v13;
+      v1 += 836;
+      if ( v13 >= (signed int)uNumActors )
+        goto LABEL_20;
+    }
+    result = 1;
+  }
+  return result;
+}
+
+//----- (0042F5ED) --------------------------------------------------------
+int LayingItem::Create(int yaw, int pitch, int a4, int a5)
+{
+  LayingItem *v5; // eax@1
+  signed int v6; // ebx@2
+  char *v7; // ecx@2
+  signed int result; // eax@6
+  LayingItem *v9; // ebx@7
+  int v10; // edx@11
+  int v11; // edi@18
+  __int16 v12; // ax@18
+  int v13; // ST2C_4@20
+  int v14; // eax@20
+  int v15; // [sp-28h] [bp-38h]@14
+  int v16; // [sp-24h] [bp-34h]@11
+  Vec3_int_ v17; // [sp-20h] [bp-30h]@11
+  int *v18; // [sp-14h] [bp-24h]@11
+  int *v19; // [sp-10h] [bp-20h]@11
+  int *v20; // [sp-Ch] [bp-1Ch]@11
+  signed int v21; // [sp+8h] [bp-8h]@2
+  int angle; // [sp+Ch] [bp-4h]@1
+  int a4a; // [sp+1Ch] [bp+Ch]@20
+  int a4b; // [sp+1Ch] [bp+Ch]@20
+  int a5a; // [sp+20h] [bp+10h]@20
+
+  auto a1 = this;
+  angle = yaw;
+  v5 = a1;
+  if ( !a1->uObjectDescID )
+    return -1;
+  v6 = 0;
+  v7 = (char *)&pLayingItems[0].uObjectDescID;
+  v21 = 0;
+  do
+  {
+    if ( !*(short *)v7 )
+      break;
+    v7 += 112;
+    ++v6;
+    v21 = v6;
+  }
+  while ( (signed int)v7 < (signed int)((char *)&pObjectList->uNumObjects + 2) );
+  if ( v6 >= 1000 )
+    return -1;
+  *(int *)&v5->field_62[2] = v5->vPosition.x;
+  *(int *)&v5->field_62[6] = v5->vPosition.y;
+  v9 = &pLayingItems[v6];
+  *(int *)&v5->field_62[10] = v5->vPosition.z;
+  memcpy(v9, v5, 0x70u);
+  if ( a5 == 1 )
+  {
+    v20 = &v9->vPosition.z;
+    v19 = &v9->vPosition.y;
+    v18 = (int *)&v9->vPosition;
+    v17.z = v5->vPosition.z;
+    *(_QWORD *)&v17.x = *(_QWORD *)&v5->vPosition.x;
+    v16 = 0;
+    v10 = stru_5C6E00->uIntegerHalfPi + v9->uFacing;
+    goto LABEL_16;
+  }
+  if ( a5 == 2 )
+  {
+    v20 = &v9->vPosition.z;
+    v19 = &v9->vPosition.y;
+    v18 = (int *)&v9->vPosition;
+    v17.z = v5->vPosition.z;
+    *(_QWORD *)&v17.x = *(_QWORD *)&v5->vPosition.x;
+    v16 = 0;
+    v10 = stru_5C6E00->uIntegerHalfPi + v9->uFacing;
+    goto LABEL_14;
+  }
+  if ( a5 == 3 )
+  {
+    v20 = &v9->vPosition.z;
+    v19 = &v9->vPosition.y;
+    v18 = (int *)&v9->vPosition;
+    v17.z = v5->vPosition.z;
+    *(_QWORD *)&v17.x = *(_QWORD *)&v5->vPosition.x;
+    v16 = 0;
+    v10 = v9->uFacing - stru_5C6E00->uIntegerHalfPi;
+LABEL_14:
+    v15 = 8;
+LABEL_17:
+    Vec3_int_::Rotate(v15, v10, v16, v17, v18, v19, v20);
+    goto LABEL_18;
+  }
+  if ( a5 == 4 )
+  {
+    v20 = &v9->vPosition.z;
+    v19 = &v9->vPosition.y;
+    v18 = (int *)&v9->vPosition;
+    v17.z = v5->vPosition.z;
+    *(_QWORD *)&v17.x = *(_QWORD *)&v5->vPosition.x;
+    v16 = 0;
+    v10 = v9->uFacing - stru_5C6E00->uIntegerHalfPi;
+LABEL_16:
+    v15 = 24;
+    goto LABEL_17;
+  }
+LABEL_18:
+  v11 = a4;
+  v12 = 0;
+  if ( a4 )
+  {
+    a4a = stru_5C6E00->SinCos(angle);
+    v13 = (unsigned __int64)(a4a * (signed __int64)stru_5C6E00->SinCos(pitch)) >> 16;
+    a4b = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
+    a5a = (unsigned __int64)(a4b * (signed __int64)stru_5C6E00->SinCos(pitch)) >> 16;
+    v14 = stru_5C6E00->SinCos(pitch - stru_5C6E00->uIntegerHalfPi);
+    v9->vVelocity.x = (unsigned int)(v13 * v11) >> 16;
+    v9->vVelocity.y = (unsigned int)(a5a * v11) >> 16;
+    v12 = (unsigned int)(v14 * v11) >> 16;
+  }
+  else
+  {
+    v9->vVelocity.y = 0;
+    v9->vVelocity.x = 0;
+  }
+  v9->vVelocity.z = v12;
+  result = v21;
+  if ( v21 >= (signed int)uNumLayingItems )
+    uNumLayingItems = v21 + 1;
+  return result;
+}
+
+//----- (0042F7EB) --------------------------------------------------------
+bool __fastcall sub_42F7EB_DropItemAt(unsigned int uSpriteID, int x, int y, int z, int a4, int count, int a7, unsigned __int16 attributes, ItemGen *a9)
+{
+  unsigned int v9; // edi@1
+  signed int v10; // edx@3
+  char *v11; // ecx@4
+  unsigned __int16 v12; // ax@7
+  unsigned int v13; // edx@9
+  char *v14; // ecx@10
+  int v15; // esi@17
+  int v16; // eax@18
+  int v17; // edi@20
+  int v18; // esi@20
+  //LayingItem a1a; // [sp+Ch] [bp-78h]@1
+  int v21; // [sp+7Ch] [bp-8h]@1
+  unsigned int v22; // [sp+80h] [bp-4h]@1
+
+  v9 = uSpriteID;
+  v21 = x;
+  v22 = uSpriteID;
+
+  LayingItem a1a; // [sp+Ch] [bp-78h]@1
+  //LayingItem::LayingItem(&a1a);
+  a1a.stru_24.Reset();
+
+  if ( a9 )
+  {
+    memcpy(&a1a.stru_24, a9, sizeof(a1a.stru_24));
+    v9 = v22;
+  }
+  v10 = 0;
+  a1a.field_50 = 0;
+  a1a.field_4C = 0;
+  a1a.field_48 = 0;
+  a1a.field_54 = 0;
+  a1a.uItemType = v9;
+  if ( (signed int)pObjectList->uNumObjects <= 0 )
+  {
+LABEL_7:
+    v12 = 0;
+  }
+  else
+  {
+    v11 = (char *)&pObjectList->pObjects->uObjectID;
+    while ( (short)v9 != *(short *)v11 )
+    {
+      ++v10;
+      v11 += 56;
+      if ( v10 >= (signed int)pObjectList->uNumObjects )
+        goto LABEL_7;
+    }
+    v12 = v10;
+  }
+  a1a.uObjectDescID = v12;
+  a1a.vPosition.z = z;
+  a1a.vPosition.x = v21;
+  a1a.vPosition.y = y;
+  a1a.uSoundID = 0;
+  a1a.uAttributes = attributes;
+  a1a.uSectorID = pIndoor->GetSector(v21, y, z);
+  a1a.uSpriteFrameID = 0;
+  a1a.field_58 = 0;
+  a1a.field_5C = 0;
+  if ( !(a1a.uAttributes & 0x10) )
+  {
+    v13 = 0;
+    if ( (signed int)pItemsTable->pItems[0].uItemID > 0 )
+    {
+      v14 = (char *)&pItemsTable->pItems[0].uSpriteID;
+      while ( *(short *)v14 != v9 )
+      {
+        ++v13;
+        v14 += 48;
+        if ( (signed int)v13 >= (signed int)pItemsTable->pItems[0].uItemID )
+          goto LABEL_16;
+      }
+      a1a.stru_24.uItemID = v13;
+    }
+  }
+LABEL_16:
+  if ( a7 )
+  {
+    v15 = count;
+    if ( count > 0 )
+    {
+      do
+      {
+        a1a.uFacing = rand() % (signed int)stru_5C6E00->uIntegerDoublePi;
+        v16 = rand();
+        a1a.Create(
+          (signed __int16)a1a.uFacing,
+          ((signed int)stru_5C6E00->uIntegerHalfPi >> 1) + (v16 % (signed int)stru_5C6E00->uIntegerHalfPi >> 1),
+          a4,
+          0);
+        --v15;
+      }
+      while ( v15 );
+    }
+  }
+  else
+  {
+    v17 = count;
+    v18 = stru_5C6E00->uIntegerHalfPi;
+    a1a.uFacing = 0;
+    if ( count > 0 )
+    {
+      do
+      {
+        a1a.Create((signed __int16)a1a.uFacing, v18, a4, 0);
+        --v17;
+      }
+      while ( v17 );
+    }
+  }
+  return 1;
+}
+
+//----- (0042F960) --------------------------------------------------------
+void __fastcall sub_42F960_create_object(int x, int y, int z)
+{
+  int v3; // ebx@1
+  int v4; // edi@1
+  signed int v5; // edx@1
+  char *v6; // ecx@2
+  unsigned __int16 v7; // ax@5
+  signed int v8; // eax@6
+  signed int v9; // eax@7
+  //LayingItem a1; // [sp+Ch] [bp-70h]@1
+
+  v3 = x;
+  v4 = y;
+  
+  LayingItem a1; // [sp+Ch] [bp-70h]@1
+  //LayingItem::LayingItem(&a1);
+  a1.stru_24.Reset();
+
+  v5 = 0;
+  a1.field_50 = 0;
+  a1.field_4C = 0;
+  a1.field_48 = 0;
+  a1.field_54 = 0;
+  a1.uItemType = 800;
+  if ( (signed int)pObjectList->uNumObjects <= 0 )
+  {
+LABEL_5:
+    v7 = 0;
+  }
+  else
+  {
+    v6 = (char *)&pObjectList->pObjects->uObjectID;
+    while ( *(short *)v6 != 800 )
+    {
+      ++v5;
+      v6 += 56;
+      if ( v5 >= (signed int)pObjectList->uNumObjects )
+        goto LABEL_5;
+    }
+    v7 = v5;
+  }
+  a1.uObjectDescID = v7;
+  a1.vPosition.x = v3;
+  a1.vPosition.y = v4;
+  a1.vPosition.z = z;
+  a1.uSoundID = 0;
+  a1.uAttributes = 0;
+  a1.uSectorID = pIndoor->GetSector(v3, v4, z);
+  a1.uSpriteFrameID = 0;
+  a1.field_58 = 0;
+  a1.field_5C = 0;
+  v8 = a1.Create(0, 0, 0, 0);
+  if ( v8 != -1 )
+  {
+    v9 = 8 * v8;
+    LOBYTE(v9) = v9 | 2;
+    pAudioPlayer->PlaySound((SoundID)(SOUND_GoldReceived|0x14), v9, 0, -1, 0, 0, 0, 0);
+  }
+}
+
+//----- (0042FA22) --------------------------------------------------------
+char *__cdecl sub_42FA22_mess_with_laying_item_list()
+{
+  size_t v0; // edx@1
+  int v1; // ebp@1
+  char *result; // eax@1
+  void *v3; // ebx@1
+
+  v0 = 0;
+  v1 = 0;
+  result = (char *)&pLayingItems[0].uObjectDescID;
+  v3 = pLayingItems;
+  do
+  {
+    if ( *(short *)result )
+    {
+      if ( v1 != v0 )
+      {
+        memcpy(v3, result - 2, 0x70u);
+        *(short *)result = 0;
+      }
+      ++v0;
+      v3 = (char *)v3 + 112;
+    }
+    result += 112;
+    ++v1;
+  }
+  while ( (signed int)result < (signed int)((char *)&pObjectList->uNumObjects + 2) );
+  uNumLayingItems = v0;
+  return result;
+}
+
+//----- (0042FA66) --------------------------------------------------------
+int __fastcall _42FA66_do_explosive_impact(int a1, int a2, int a3, int a4, __int16 a5, signed int a6)
+{
+  int v6; // edi@1
+  int v7; // esi@1
+  char *v8; // ecx@2
+  unsigned __int16 v9; // ax@5
+  int v10; // eax@10
+  signed int result; // eax@11
+  __int16 v12; // ax@12
+  //LayingItem a1a; // [sp+Ch] [bp-74h]@1
+  int v14; // [sp+7Ch] [bp-4h]@1
+
+  v6 = a1;
+  v7 = a2;
+  LayingItem a1a; // [sp+Ch] [bp-74h]@1
+  //LayingItem::LayingItem(&a1a);
+  a1a.uItemType = 600;
+  a1a.stru_24.Reset();
+
+  a1a.field_48 = 6;
+  a1a.field_4C = 8;
+  a1a.field_50 = 3;
+  v14 = 0;
+  if ( (signed int)pObjectList->uNumObjects <= 0 )
+  {
+LABEL_5:
+    v9 = 0;
+  }
+  else
+  {
+    v8 = (char *)&pObjectList->pObjects->uObjectID;
+    while ( (short)a1a.uItemType != *(short *)v8 )
+    {
+      ++v14;
+      v8 += 56;
+      if ( v14 >= (signed int)pObjectList->uNumObjects )
+        goto LABEL_5;
+    }
+    v9 = v14;
+  }
+  a1a.uObjectDescID = v9;
+  a1a.vPosition.x = v6;
+  a1a.vPosition.y = v7;
+  a1a.vPosition.z = a3;
+  a1a.uAttributes = 0;
+  a1a.uSectorID = pIndoor->GetSector(v6, v7, a3);
+  a1a.uSpriteFrameID = 0;
+  a1a.field_5C = 0;
+  a1a.field_60_distance_related_prolly_lod = 0;
+  a1a.uFacing = 0;
+  a1a.uSoundID = 0;
+  if ( a6 >= 1 || a6 <= 4 )
+  {
+    v10 = 8 * a6 - 8;
+    LOBYTE(v10) = v10 | 4;
+    a1a.field_58 = v10;
+  }
+  else
+  {
+    a1a.field_58 = 0;
+  }
+  result = a1a.Create(0, 0, 0, 0);
+  if ( result != -1 )
+  {
+    v12 = 8 * result;
+    LOBYTE(v12) = v12 | 2;
+    result = stru_50FE08.Add(
+               v12,
+               a5,
+               SLOWORD(a1a.vPosition.x),
+               SLOWORD(a1a.vPosition.y),
+               SLOWORD(a1a.vPosition.z),
+               0,
+               0);
+  }
+  return result;
+}
+
+
+
+//----- (0042FB5C) --------------------------------------------------------
+bool __fastcall sub_42FB5C(signed int a1)
+{
+  int v1; // ecx@3
+  int v2; // ecx@4
+  int v3; // ecx@5
+  int v4; // ecx@6
+  int v5; // ecx@7
+  int v6; // ecx@8
+  char v7; // zf@9
+
+  if ( a1 > 39 )
+  {
+    if ( a1 > 77 )
+    {
+      if ( a1 == 80 )
+        return 0;
+      if ( a1 > 84 )
+      {
+        if ( a1 <= 86 )
+          return 0;
+        v7 = a1 == 95;
+        goto LABEL_20;
+      }
+    }
+    else
+    {
+      if ( a1 == 77 )
+        return 0;
+      if ( a1 >= 46 )
+      {
+        if ( a1 <= 47 || a1 == 51 )
+          return 0;
+        v7 = a1 == 73;
+        goto LABEL_20;
+      }
+    }
+    return 1;
+  }
+  if ( a1 == 39 || (v1 = a1 - 2) == 0 )
+    return 1;
+  v2 = v1 - 3;
+  if ( !v2 )
+    return 0;
+  v3 = v2 - 1;
+  if ( !v3 || (v4 = v3 - 3) == 0 )
+    return 1;
+  v5 = v4 - 8;
+  if ( !v5 )
+    return 0;
+  v6 = v5 - 1;
+  if ( !v6 )
+    return 1;
+  v7 = v6 == 20;
+LABEL_20:
+  if ( !v7 )
+    return 1;
+  return 0;
+}
+
+//----- (0042FBDD) --------------------------------------------------------
+void __cdecl sub_42FBDD()
+{
+  pAudioPlayer->PlaySound((SoundID)75, 0, 0, -1, 0, 0, 0, 0);
+  pRenderer->DrawTextureTransparent(pBtn_YES->uX, pBtn_YES->uY, pBtn_YES->pTextures[0]);
+  pRenderer->Present();
+}
+
+//----- (0042FC15) --------------------------------------------------------
+void __cdecl sub_42FC15()
+{
+  pAudioPlayer->PlaySound((SoundID)75, -2, 0, -1, 0, 0, 0, 0);
+  pRenderer->DrawTextureTransparent(pBtn_ExitCancel->uX, pBtn_ExitCancel->uY, pBtn_ExitCancel->pTextures[0]);
+  pRenderer->Present();
+}
+
+//----- (0042FC4E) --------------------------------------------------------
+void __cdecl ProcessInputActions()
+{
+  ActionQueue *pActionQueue; // esi@7
+  Keyboard *v3; // ecx@8
+  char v4; // al@9
+  ActionQueue *v5; // ecx@19
+  Player *v6; // ecx@86
+  Player *v7; // esi@100
+  char v8; // bl@100
+  unsigned __int16 v9; // ax@102
+  int v10; // eax@103
+  unsigned int v11; // eax@127
+  signed int v12; // esi@157
+  Keyboard *v13; // ecx@158
+  char v14; // al@159
+  unsigned int v15; // eax@168
+  void *v16; // esi@177
+  int v17; // [sp-14h] [bp-1Ch]@8
+  PartyAction partyAction; // [sp-14h] [bp-1Ch]@20
+  PartyAction partyAction_; // [sp-14h] [bp-1Ch]@54
+  __int16 v20; // [sp-14h] [bp-1Ch]@60
+  int v21; // [sp-14h] [bp-1Ch]@68
+  int v22; // [sp-Ch] [bp-14h]@158
+  InputAction inputAction; // [sp+0h] [bp-8h]@7
+  int v24; // [sp+4h] [bp-4h]@87
+
+  pGame->pKeyboardInstance->EnterCriticalSection();
+  auto pKeyboard = pGame->pKeyboardInstance;
+  if (!bAlwaysRun)
+  {
+    if (pKeyboard->IsShiftHeld())
+      pParty->uFlags2 |= PARTY_FLAGS_2_RUNNING;
+    else
+      pParty->uFlags2 &= ~PARTY_FLAGS_2_RUNNING;
+   }
+  else
+  {
+    if (pKeyboard->IsShiftHeld())
+      pParty->uFlags2 &= ~PARTY_FLAGS_2_RUNNING;
+    else
+      pParty->uFlags2 |= PARTY_FLAGS_2_RUNNING;
+  }
+
+  pParty->uFlags2 |= PARTY_FLAGS_2_RUNNING;
+LABEL_6:
+  if ( !pEventTimer->bPaused )
+  {
+    inputAction = (InputAction)0;
+    pActionQueue = pPartyActionQueue;
+    while ( 1 )
+    {
+      v3 = pGame->pKeyboardInstance;
+      v17 = pKeyActionMap->pVirtualKeyCodesMapping[inputAction];
+      if ( pKeyActionMap->pToggleTypes[inputAction] )
+        v4 = v3->WasKeyPressed(v17);
+      else
+        v4 = v3->IsKeyBeingHeld(v17);
+      if ( v4 )
+      {
+        switch ( inputAction )
+        {
+          case INPUT_MoveForward:
+            if ( pCurrentScreen )
+              break;
+            if (!pParty->bTurnBasedModeOn)
+              goto _do_move_forward;
+            if (pTurnEngine->field_4 != 1 && pTurnEngine->field_4 != 2 && pTurnEngine->uActionPointsLeft > 0 )
+            {
+              pTurnEngine->uActionPointsLeft -= 26;
+_do_move_forward:
+              v5 = pActionQueue;
+              if ( pParty->uFlags2 & 2 )
+                partyAction = PARTY_RunForward;
+              else
+                partyAction = PARTY_WalkForward;
+              goto _add_action_and_continue;
+            }
+            break;
+          case INPUT_MoveBackwards:
+            __debugbreak();
+            if ( pCurrentScreen )
+              break;
+            if (!pParty->bTurnBasedModeOn)
+              goto _do_move_backwards;
+            if ( pTurnEngine->field_4 != 1 && pTurnEngine->field_4 != 2 && pTurnEngine->uActionPointsLeft > 0 )
+            {
+              pTurnEngine->uActionPointsLeft -= 26;
+_do_move_backwards:
+              v5 = pActionQueue;
+              if ( pParty->uFlags2 & 2 )
+                partyAction = PARTY_RunBackward;
+              else
+                partyAction = PARTY_WalkBackward;
+              goto _add_action_and_continue;
+            }
+            break;
+          case INPUT_StrafeLeft:
+            __debugbreak();
+            if ( pCurrentScreen )
+              break;
+            if (!pParty->bTurnBasedModeOn)
+              goto _do_strafe_left;
+            if ( pTurnEngine->field_4 == 1 || pTurnEngine->field_4 == 2 || pTurnEngine->uActionPointsLeft <= 0 )
+              break;
+            pTurnEngine->uActionPointsLeft -= 26;
+_do_strafe_left:
+            partyAction = PARTY_StrafeLeft;
+            goto _add_action_and_continue_;
+          case INPUT_StrafeRight:
+            __debugbreak();
+            if ( pCurrentScreen )
+              break;
+            if (!pParty->bTurnBasedModeOn)
+              goto _do_strafe_right;
+            if ( pTurnEngine->field_4 == 1 || pTurnEngine->field_4 == 2 || pTurnEngine->uActionPointsLeft <= 0 )
+              break;
+            pTurnEngine->uActionPointsLeft -= 26;
+_do_strafe_right:
+            partyAction = PARTY_StrafeRight;
+            goto _add_action_and_continue_;
+          case INPUT_TurnLeft:
+            if ( pCurrentScreen )
+              break;
+            if ( GetAsyncKeyState(VK_CONTROL) ) // strafing
+            {
+              if (pParty->bTurnBasedModeOn)
+              {
+                if ( pTurnEngine->field_4 == 1 || pTurnEngine->field_4 == 2 || pTurnEngine->uActionPointsLeft <= 0 )
+                  break;
+                pTurnEngine->uActionPointsLeft -= 26;
+              }
+              partyAction_ = PARTY_StrafeLeft;
+            }
+            else
+            {
+              if ( pParty->uFlags2 & 2 )
+                partyAction_ = PARTY_FastTurnLeft;
+              else
+                partyAction_ = PARTY_TurnLeft;
+            }
+            pActionQueue->Add(partyAction_);
+            if (uCurrentlyLoadedLevelType == LEVEL_Outdoor && pWeather->bRenderSnow)
+            {
+              v20 = 10;
+              goto LABEL_75;
+            }
+            break;
+          case INPUT_TurnRight:
+            if ( pCurrentScreen )
+              break;
+            if ( GetAsyncKeyState(17) )         // strafing
+            {
+              if (pParty->bTurnBasedModeOn)
+              {
+                if ( pTurnEngine->field_4 == 1 || pTurnEngine->field_4 == 2 || pTurnEngine->uActionPointsLeft <= 0 )
+                  break;
+                pTurnEngine->uActionPointsLeft -= 26;
+              }
+              v21 = 4;
+            }
+            else
+            {
+              if ( pParty->uFlags2 & 2 )
+                v21 = 19;
+              else
+                v21 = 2;
+            }
+            pActionQueue->Add((PartyAction)v21);
+            if (uCurrentlyLoadedLevelType == LEVEL_Outdoor && pWeather->bRenderSnow)
+            {
+              v20 = -10;
+LABEL_75:
+              pWeather->_4C2F0B(v20);
+            }
+            break;
+          case INPUT_Jump:
+            __debugbreak();
+            if ( pCurrentScreen
+              || pParty->bTurnBasedModeOn)
+              break;
+            partyAction = (PartyAction)12;
+            goto _add_action_and_continue_;
+          case INPUT_Yell:
+            __debugbreak();
+            if ( !pCurrentScreen
+              && uActiveCharacter )
+            {
+              pParty->Yell();
+              pPlayers[uActiveCharacter]->PlaySound(65, 0);
+            }
+            break;
+          case INPUT_Pass:
+            __debugbreak();
+            if ( pCurrentScreen )
+              break;
+            if (pParty->bTurnBasedModeOn && pTurnEngine->field_4 == 3)
+              goto LABEL_118;
+            if ( uActiveCharacter )
+            {
+              v6 = pPlayers[uActiveCharacter];
+              if ( !v6->uTimeToRecovery )
+              {
+                v24 = v6->GetAttackRecoveryTime(0);
+                if ( !pParty->bTurnBasedModeOn )
+                  pPlayers[uActiveCharacter]->SetRecoveryTime(
+                    (signed __int64)(flt_6BE3A4_debug_recmod1 * (double)v24 * 2.133333333333333));
+                pStru277->_427D48(uActiveCharacter);
+                pTurnEngine->_40471C();
+              }
+            }
+            break;
+          case INPUT_Combat:
+            __debugbreak();
+            if ( !pCurrentScreen )
+            {
+              if (pParty->bTurnBasedModeOn)
+              {
+                if ( pTurnEngine->field_4 == 3 || (pTurnEngine->pQueue[0].uPackedID & 7) == 4 )
+                {
+                  pParty->bTurnBasedModeOn = 0;
+                  pTurnEngine->End(true);
+                }
+              }
+              else
+              {
+                pTurnEngine->Start();
+                pParty->bTurnBasedModeOn = true;
+              }
+            }
+            break;
+          case INPUT_CastReady:
+            __debugbreak();
+            if ( pCurrentScreen )
+              break;
+            if (pParty->bTurnBasedModeOn && pTurnEngine->field_4 == 3)
+              goto LABEL_118;
+            if ( !uActiveCharacter )
+              break;
+            v7 = pPlayers[uActiveCharacter];
+            v8 = v7->uQuickSpell;
+            if ( !v8
+              || bUnderwater
+              || ((v9 = v7->pActiveSkills[(unsigned __int8)v8 / 11 + 12], !(HIBYTE(v9) & 1)) ? ((v9 & 0x80u) == 0 ? (!(v9 & 0x40) ? (v10 = *(&pSpellDatas[0].uNormalLevelMana + 10 * (unsigned __int8)v8)) : (v10 = *(&pSpellDatas[0].uExpertLevelMana + 10 * (unsigned __int8)v8))) : (v10 = *(&pSpellDatas[0].uMasterLevelMana + 10 * (unsigned __int8)v8))) : (v10 = *(&pSpellDatas[0].uMagisterLevelMana + 10 * (unsigned __int8)v8)),
+                  v10 > v7->sMana) )
+            {
+              pActionQueue = pPartyActionQueue;
+LABEL_120:
+              if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
+              {
+                pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)23;
+                goto _send_message;
+              }
+            }
+            else
+            {
+              pActionQueue = pPartyActionQueue;
+              if ( dword_50C9E8 < 40 )
+              {
+                dword_50C9EC[3 * dword_50C9E8] = 25;
+                dword_50C9F0[3 * dword_50C9E8] = 0;
+                *(&dword_50C9E8 + 3 * dword_50C9E8 + 3) = 0;
+                ++dword_50C9E8;
+              }
+            }
+            break;
+          default:
+            __debugbreak();
+            break;
+          case INPUT_Attack:
+            __debugbreak();
+            if ( pCurrentScreen )
+              break;
+            if (!pParty->bTurnBasedModeOn || pTurnEngine->field_4 != 3)
+              goto LABEL_120;
+LABEL_118:
+            pTurnEngine->field_18 |= 8u;
+            break;
+          case INPUT_EventTrigger:
+            if ( !pCurrentScreen )
+            {
+              if ( (signed int)pMessageQueue_50CBD0->uNumMessages >= 40 )
+                break;
+              pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)404;
+              goto _send_message;
+            }
+            if ( pCurrentScreen == 4 )
+            {
+              v11 = pMessageQueue_50CBD0->uNumMessages;
+              if ( pMessageQueue_50CBD0->uNumMessages )
+              {
+                if ( pMessageQueue_50CBD0->pMessages[0].field_8 )
+                {
+                  v11 = 1;
+                  pMessageQueue_50CBD0->uNumMessages = 1;
+LABEL_132:
+                  pMessageQueue_50CBD0->pMessages[v11].eType = (UIMessageType)113;
+_send_message:
+                  pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+                  *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+                  ++pMessageQueue_50CBD0->uNumMessages;
+                  break;
+                }
+                v11 = 0;
+                pMessageQueue_50CBD0->uNumMessages = 0;
+              }
+              if ( (signed int)v11 < 40 )
+                goto LABEL_132;
+            }
+            break;
+          case INPUT_CharCycle:
+            __debugbreak();
+            if ( pCurrentScreen == 8
+              || dword_50C9E8 >= 40 )
+              break;
+            dword_50C9EC[3 * dword_50C9E8] = 176;
+            goto LABEL_155;
+          case INPUT_LookUp:
+            __debugbreak();
+            if ( pEventTimer->bPaused )
+              break;
+            partyAction = (PartyAction)7;
+            goto _add_action_and_continue_;
+          case INPUT_CenterView:
+            __debugbreak();
+            if ( pEventTimer->bPaused )
+              break;
+            partyAction = (PartyAction)9;
+            goto _add_action_and_continue_;
+          case INPUT_LookDown:
+            __debugbreak();
+            if ( pEventTimer->bPaused )
+              break;
+            partyAction = (PartyAction)8;
+            goto _add_action_and_continue_;
+          case INPUT_FlyUp:
+            __debugbreak();
+            if ( pCurrentScreen
+              || pEventTimer->bPaused )
+              break;
+            partyAction = (PartyAction)13;
+            goto _add_action_and_continue_;
+          case INPUT_Land:
+            __debugbreak();
+            if ( pCurrentScreen
+              || pEventTimer->bPaused )
+              break;
+            partyAction = (PartyAction)15;
+            goto _add_action_and_continue_;
+          case INPUT_FlyDown:
+            __debugbreak();
+            if ( !pCurrentScreen
+              && !pEventTimer->bPaused )
+            {
+              partyAction = (PartyAction)14;
+_add_action_and_continue_:
+              v5 = pActionQueue;
+_add_action_and_continue:
+              v5->Add(partyAction);
+            }
+            break;
+          case INPUT_ZoomIn:
+            __debugbreak();
+            if ( dword_50C9E8 >= 40 )
+              break;
+            dword_50C9EC[3 * dword_50C9E8] = 367;
+            goto LABEL_155;
+          case INPUT_ZoomOut:
+            __debugbreak();
+            if ( dword_50C9E8 < 40 )
+            {
+              dword_50C9EC[3 * dword_50C9E8] = 368;
+LABEL_155:
+              dword_50C9F0[3 * dword_50C9E8] = 0;
+              *(&dword_50C9E8 + 3 * dword_50C9E8 + 3) = 0;
+              ++dword_50C9E8;
+            }
+            break;
+          case INPUT_AlwaysRun:
+            bAlwaysRun = bAlwaysRun == 0;
+            break;
+        }
+      }
+      inputAction = (InputAction)((int)inputAction + 1);
+      if ( (signed int)inputAction >= 30 )
+        goto LABEL_176;
+    }
+  }
+  v12 = 0;
+  do
+  {
+    v22 = pKeyActionMap->pVirtualKeyCodesMapping[v12];
+    v13 = pGame->pKeyboardInstance;
+    if ( pKeyActionMap->pToggleTypes[v12] )
+      v14 = v13->WasKeyPressed(v22);
+    else
+      v14 = v13->IsKeyBeingHeld(v22);
+    if ( v14 && v12 == 9 )
+    {
+      if ( !pCurrentScreen )
+      {
+        if ( (signed int)pMessageQueue_50CBD0->uNumMessages >= 40 )
+          goto LABEL_175;
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = (UIMessageType)404;
+        goto LABEL_174;
+      }
+      if ( pCurrentScreen == 4
+        || pCurrentScreen == 19 )
+      {
+        v15 = pMessageQueue_50CBD0->uNumMessages;
+        if ( pMessageQueue_50CBD0->uNumMessages )
+        {
+          v15 = 0;
+          if ( pMessageQueue_50CBD0->pMessages[0].field_8 )
+          {
+            v15 = 1;
+            pMessageQueue_50CBD0->uNumMessages = 1;
+            goto LABEL_173;
+          }
+          pMessageQueue_50CBD0->uNumMessages = 0;
+        }
+        if ( (signed int)v15 >= 40 )
+          goto LABEL_175;
+LABEL_173:
+        pMessageQueue_50CBD0->pMessages[v15].eType = (UIMessageType)113;
+LABEL_174:
+        pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
+        *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
+        ++pMessageQueue_50CBD0->uNumMessages;
+        goto LABEL_175;
+      }
+    }
+LABEL_175:
+    ++v12;
+  }
+  while ( v12 < 30 );
+LABEL_176:
+  if (pGame->pKeyboardInstance->bUsingAsynKeyboard)
+  {
+    AsyncKeyboard::LeaveCriticalSection();
+    v16 = pAsyncKeyboard;
+    AsyncKeyboard::EnterCriticalSection();
+    memset((char *)v16 + 521, 0, 0x100u);
+    AsyncKeyboard::LeaveCriticalSection();
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mm7_data.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1817 @@
+#include "mm7_data.h"
+
+#include "NPC.h"
+
+
+
+
+void ErrHR(HRESULT hr, const char *pAPI, const char *pFunction, const char *pFile, int line)
+{
+  if (SUCCEEDED(hr))
+    return;
+
+  char msg[4096];
+  sprintf(msg, "%s error (%08X) in\n\t%s\nin\n\t%s:%u",
+          pAPI, hr, pFunction, pFile, line);
+
+  char caption[1024];
+  sprintf(caption, "%s error", pAPI);
+
+  MessageBoxA(nullptr, msg, caption, MB_ICONEXCLAMATION);
+}
+
+
+
+
+#include "Math.h"
+struct stru193_math *stru_5C6E00 = new stru193_math;
+
+#include "MapInfo.h"
+struct MapStats *pMapStats;
+
+#include "TurnEngine.h"
+struct stru262_TurnBased *pTurnEngine = new stru262_TurnBased;
+
+#include "stru277.h"
+stru277 pStru277[10];
+stru277 stru_50CDB4; // idb
+
+#include "Viewport.h"
+struct Viewport *pViewport = new Viewport;
+struct ViewingParams *viewparams = new ViewingParams;
+
+#include "stru272.h"
+stru272 array_4FAC10[10];
+
+
+#include "stru279.h"
+stru279 stru_51076C;
+
+#include "stru157.h"
+stru157 stru_F93E1C; // weak
+stru157 stru_F93E30; // weak
+stru157 a5; // idb
+stru157 a4; // idb
+stru157 a3; // idb
+
+#include "stru179.h"
+stru179 *pStru179;
+
+#include "stru123.h"
+stru123 stru_5E4C90;
+
+#include "stru298.h"
+stru298 stru_50FE08; // weak
+
+#include "stru287.h"
+stru287 stru_5E4C50;
+
+#include "Autonotes.h"
+Autonote stru_723720[195]; // weak
+
+#include "Awards.h"
+Award pAwards[104];
+
+#include "stru159.h"
+stru159 pAnimatedRooms[196];
+
+#include "stru160.h"
+stru160 array_4EB8B8[66] =
+{
+  stru160( 0.0000000f,  0.0000000f,  1.0000000f),
+  stru160( 0.0000000f,  0.3826830f,  0.9238799f),
+  stru160( 0.3826830f,  0.0000000f,  0.9238799f),
+  stru160( 0.4082480f,  0.4082480f,  0.8164970f),
+  stru160( 0.0000000f,  0.7071070f,  0.7071070f),
+  stru160( 0.7071070f,  0.0000000f,  0.7071070f),
+  stru160( 0.4082480f,  0.8164970f,  0.4082480f),
+  stru160( 0.8164970f,  0.4082480f,  0.4082480f),
+  stru160( 0.7071070f,  0.7071070f,  0.0000000f),
+  stru160( 0.0000000f,  0.9238799f,  0.3826830f),
+  stru160( 0.3826830f,  0.9238799f,  0.0000000f),
+  stru160( 0.0000000f,  1.0000000f,  0.0000000f),
+  stru160( 0.9238799f,  0.3826830f,  0.0000000f),
+  stru160( 0.9238799f,  0.0000000f,  0.3826830f),
+  stru160( 1.0000000f,  0.0000000f,  0.0000000f),
+  stru160( 0.0000000f, -0.3826830f,  0.9238799f),
+  stru160( 0.4082480f, -0.4082480f,  0.8164970f),
+  stru160( 0.0000000f, -0.7071070f,  0.7071070f),
+  stru160( 0.8164970f, -0.4082480f,  0.4082480f),
+  stru160( 0.4082480f, -0.8164970f,  0.4082480f),
+  stru160( 0.7071070f, -0.7071070f,  0.0000000f),
+  stru160( 0.9238799f, -0.3826830f,  0.0000000f),
+  stru160( 0.3826830f, -0.9238799f,  0.0000000f),
+  stru160( 0.0000000f, -0.9238799f,  0.3826830f),
+  stru160( 0.0000000f, -1.0000000f,  0.0000000f),
+  stru160(-0.3826830f,  0.0000000f,  0.9238799f),
+  stru160(-0.4082480f, -0.4082480f,  0.8164970f),
+  stru160(-0.7071070f,  0.0000000f,  0.7071070f),
+  stru160(-0.4082480f, -0.8164970f,  0.4082480f),
+  stru160(-0.8164970f, -0.4082480f,  0.4082480f),
+  stru160(-0.7071070f, -0.7071070f,  0.0000000f),
+  stru160(-0.3826830f, -0.9238799f,  0.0000000f),
+  stru160(-0.9238799f, -0.3826830f,  0.0000000f),
+  stru160(-0.9238799f,  0.0000000f,  0.3826830f),
+  stru160(-1.0000000f,  0.0000000f,  0.0000000f),
+  stru160(-0.4082480f,  0.4082480f,  0.8164970f),
+  stru160(-0.8164970f,  0.4082480f,  0.4082480f),
+  stru160(-0.4082480f,  0.8164970f,  0.4082480f),
+  stru160(-0.7071070f,  0.7071070f,  0.0000000f),
+  stru160(-0.9238799f,  0.3826830f,  0.0000000f),
+  stru160(-0.3826830f,  0.9238799f,  0.0000000f),
+  stru160( 0.0000000f,  0.0000000f, -1.0000000f),
+  stru160( 0.0000000f,  0.3826830f, -0.9238799f),
+  stru160( 0.3826830f,  0.0000000f, -0.9238799f),
+  stru160( 0.4082480f,  0.4082480f, -0.8164970f),
+  stru160( 0.0000000f,  0.7071070f, -0.7071070f),
+  stru160( 0.7071070f,  0.0000000f, -0.7071070f),
+  stru160( 0.4082480f,  0.8164970f, -0.4082480f),
+  stru160( 0.8164970f,  0.4082480f, -0.4082480f),
+  stru160( 0.0000000f,  0.9238799f, -0.3826830f),
+  stru160( 0.9238799f,  0.0000000f, -0.3826830f),
+  stru160( 0.0000000f, -0.3826830f, -0.9238799f),
+  stru160( 0.4082480f, -0.4082480f, -0.8164970f),
+  stru160( 0.0000000f, -0.7071070f, -0.7071070f),
+  stru160( 0.8164970f, -0.4082480f, -0.4082480f),
+  stru160( 0.4082480f, -0.8164970f, -0.4082480f),
+  stru160( 0.0000000f, -0.9238799f, -0.3826830f),
+  stru160(-0.3826830f,  0.0000000f, -0.9238799f),
+  stru160(-0.4082480f, -0.4082480f, -0.8164970f),
+  stru160(-0.7071070f,  0.0000000f, -0.7071070f),
+  stru160(-0.4082480f, -0.8164970f, -0.4082480f),
+  stru160(-0.8164970f, -0.4082480f, -0.4082480f),
+  stru160(-0.9238799f,  0.0000000f, -0.3826830f),
+  stru160(-0.4082480f,  0.4082480f, -0.8164970f),
+  stru160(-0.8164970f,  0.4082480f, -0.4082480f),
+  stru160(-0.4082480f,  0.8164970f, -0.4082480f)
+};
+stru160 array_4EBBD0[128];
+__int32 array_4EBBD0_x[128*3] =
+{
+  0x00000000, 0x00000001, 0x00000002, 0x00000001,
+  0x00000003, 0x00000002, 0x00000001, 0x00000004,
+  0x00000003, 0x00000003, 0x00000005, 0x00000002,
+  0x00000004, 0x00000006, 0x00000003, 0x00000006,
+  0x00000007, 0x00000003, 0x00000006, 0x00000008,
+  0x00000007, 0x00000007, 0x00000005, 0x00000003,
+  0x00000004, 0x00000009, 0x00000006, 0x00000009,
+  0x0000000A, 0x00000006, 0x00000009, 0x0000000B,
+  0x0000000A, 0x0000000A, 0x00000008, 0x00000006,
+  0x00000008, 0x0000000C, 0x00000007, 0x0000000C,
+  0x0000000D, 0x00000007, 0x0000000C, 0x0000000E,
+  0x0000000D, 0x0000000D, 0x00000005, 0x00000007,
+  0x00000000, 0x00000002, 0x0000000F, 0x00000002,
+  0x00000010, 0x0000000F, 0x00000002, 0x00000005,
+  0x00000010, 0x00000010, 0x00000011, 0x0000000F,
+  0x00000005, 0x00000012, 0x00000010, 0x00000012,
+  0x00000013, 0x00000010, 0x00000012, 0x00000014,
+  0x00000013, 0x00000013, 0x00000011, 0x00000010,
+  0x00000005, 0x0000000D, 0x00000012, 0x0000000D,
+  0x00000015, 0x00000012, 0x0000000D, 0x0000000E,
+  0x00000015, 0x00000015, 0x00000014, 0x00000012,
+  0x00000014, 0x00000016, 0x00000013, 0x00000016,
+  0x00000017, 0x00000013, 0x00000016, 0x00000018,
+  0x00000017, 0x00000017, 0x00000011, 0x00000013,
+  0x00000000, 0x0000000F, 0x00000019, 0x0000000F,
+  0x0000001A, 0x00000019, 0x0000000F, 0x00000011,
+  0x0000001A, 0x0000001A, 0x0000001B, 0x00000019,
+  0x00000011, 0x0000001C, 0x0000001A, 0x0000001C,
+  0x0000001D, 0x0000001A, 0x0000001C, 0x0000001E,
+  0x0000001D, 0x0000001D, 0x0000001B, 0x0000001A,
+  0x00000011, 0x00000017, 0x0000001C, 0x00000017,
+  0x0000001F, 0x0000001C, 0x00000017, 0x00000018,
+  0x0000001F, 0x0000001F, 0x0000001E, 0x0000001C,
+  0x0000001E, 0x00000020, 0x0000001D, 0x00000020,
+  0x00000021, 0x0000001D, 0x00000020, 0x00000022,
+  0x00000021, 0x00000021, 0x0000001B, 0x0000001D,
+  0x00000000, 0x00000019, 0x00000001, 0x00000019,
+  0x00000023, 0x00000001, 0x00000019, 0x0000001B,
+  0x00000023, 0x00000023, 0x00000004, 0x00000001,
+  0x0000001B, 0x00000024, 0x00000023, 0x00000024,
+  0x00000025, 0x00000023, 0x00000024, 0x00000026,
+  0x00000025, 0x00000025, 0x00000004, 0x00000023,
+  0x0000001B, 0x00000021, 0x00000024, 0x00000021,
+  0x00000027, 0x00000024, 0x00000021, 0x00000022,
+  0x00000027, 0x00000027, 0x00000026, 0x00000024,
+  0x00000026, 0x00000028, 0x00000025, 0x00000028,
+  0x00000009, 0x00000025, 0x00000028, 0x0000000B,
+  0x00000009, 0x00000009, 0x00000004, 0x00000025,
+  0x00000029, 0x0000002A, 0x0000002B, 0x0000002A,
+  0x0000002C, 0x0000002B, 0x0000002A, 0x0000002D,
+  0x0000002C, 0x0000002C, 0x0000002E, 0x0000002B,
+  0x0000002D, 0x0000002F, 0x0000002C, 0x0000002F,
+  0x00000030, 0x0000002C, 0x0000002F, 0x00000008,
+  0x00000030, 0x00000030, 0x0000002E, 0x0000002C,
+  0x0000002D, 0x00000031, 0x0000002F, 0x00000031,
+  0x0000000A, 0x0000002F, 0x00000031, 0x0000000B,
+  0x0000000A, 0x0000000A, 0x00000008, 0x0000002F,
+  0x00000008, 0x0000000C, 0x00000030, 0x0000000C,
+  0x00000032, 0x00000030, 0x0000000C, 0x0000000E,
+  0x00000032, 0x00000032, 0x0000002E, 0x00000030,
+  0x00000029, 0x0000002B, 0x00000033, 0x0000002B,
+  0x00000034, 0x00000033, 0x0000002B, 0x0000002E,
+  0x00000034, 0x00000034, 0x00000035, 0x00000033,
+  0x0000002E, 0x00000036, 0x00000034, 0x00000036,
+  0x00000037, 0x00000034, 0x00000036, 0x00000014,
+  0x00000037, 0x00000037, 0x00000035, 0x00000034,
+  0x0000002E, 0x00000032, 0x00000036, 0x00000032,
+  0x00000015, 0x00000036, 0x00000032, 0x0000000E,
+  0x00000015, 0x00000015, 0x00000014, 0x00000036,
+  0x00000014, 0x00000016, 0x00000037, 0x00000016,
+  0x00000038, 0x00000037, 0x00000016, 0x00000018,
+  0x00000038, 0x00000038, 0x00000035, 0x00000037,
+  0x00000029, 0x00000033, 0x00000039, 0x00000033,
+  0x0000003A, 0x00000039, 0x00000033, 0x00000035,
+  0x0000003A, 0x0000003A, 0x0000003B, 0x00000039,
+  0x00000035, 0x0000003C, 0x0000003A, 0x0000003C,
+  0x0000003D, 0x0000003A, 0x0000003C, 0x0000001E,
+  0x0000003D, 0x0000003D, 0x0000003B, 0x0000003A,
+  0x00000035, 0x00000038, 0x0000003C, 0x00000038,
+  0x0000001F, 0x0000003C, 0x00000038, 0x00000018,
+  0x0000001F, 0x0000001F, 0x0000001E, 0x0000003C,
+  0x0000001E, 0x00000020, 0x0000003D, 0x00000020,
+  0x0000003E, 0x0000003D, 0x00000020, 0x00000022,
+  0x0000003E, 0x0000003E, 0x0000003B, 0x0000003D,
+  0x00000029, 0x00000039, 0x0000002A, 0x00000039,
+  0x0000003F, 0x0000002A, 0x00000039, 0x0000003B,
+  0x0000003F, 0x0000003F, 0x0000002D, 0x0000002A,
+  0x0000003B, 0x00000040, 0x0000003F, 0x00000040,
+  0x00000041, 0x0000003F, 0x00000040, 0x00000026,
+  0x00000041, 0x00000041, 0x0000002D, 0x0000003F,
+  0x0000003B, 0x0000003E, 0x00000040, 0x0000003E,
+  0x00000027, 0x00000040, 0x0000003E, 0x00000022,
+  0x00000027, 0x00000027, 0x00000026, 0x00000040,
+  0x00000026, 0x00000028, 0x00000041, 0x00000028,
+  0x00000031, 0x00000041, 0x00000028, 0x0000000B,
+  0x00000031, 0x00000031, 0x0000002D, 0x00000041
+};
+
+#include "stru220.h"
+stru220 stru_76E5C8[16384];
+
+#include "stru176.h"
+stru176 array_5B5928[100];
+
+#include "ObjectList.h"
+struct ObjectList *pObjectList;
+
+#include "IconFrameTable.h"
+struct IconFrameTable *pIconsFrameTable;
+
+struct
+{
+  struct UIAnimation _pUIAnim_Food;
+  struct UIAnimation _pUIAnim_Gold;
+  struct UIAnimation _pUIAnum_Torchlight;
+  struct UIAnimation _pUIAnim_WizardEye;
+} _uianim;
+
+struct UIAnimation *pUIAnim_Food = &_uianim._pUIAnim_Food;
+struct UIAnimation *pUIAnim_Gold = &_uianim._pUIAnim_Gold;
+struct UIAnimation *pUIAnum_Torchlight = &_uianim._pUIAnum_Torchlight;
+struct UIAnimation *pUIAnim_WizardEye = &_uianim._pUIAnim_WizardEye;
+
+struct UIAnimation *pUIAnims[4] =
+{
+  &_uianim._pUIAnim_Food,
+  &_uianim._pUIAnim_Gold,
+  &_uianim._pUIAnum_Torchlight,
+  &_uianim._pUIAnim_WizardEye
+};
+
+
+
+#include "PlayerFrameTable.h"
+struct PlayerFrameTable *pPlayerFrameTable; // idb
+
+#include "MM7.h"
+stru161 stru_4ECBB8[6];
+stru289 stru_6BE158;
+stru329 array_4E4C30[4];
+stru332 stru_511698;
+stru333 stru_511718;
+stru334 array_4E2940[26];
+stru348 stru_4E1890[13];
+
+
+
+
+namespace zlib
+{
+  #include "lib\zlib\zlib.h"
+  int MemUnzip(void *dest, unsigned int *destLen, const void *source, unsigned int sourceLen)
+  {
+    //return uncompress((zlib::Bytef *)dest, (zlib::uLongf *)destLen, (zlib::Bytef *)source, sourceLen);
+    return uncompress((Bytef *)dest, (uLongf *)destLen, (Bytef *)source, sourceLen);
+    return 0;
+  }
+
+  int MemZip(void *dest, unsigned int *destLen, void *source, unsigned int sourceLen)
+  {
+    //return compress((zlib::Bytef *)dest, (zlib::uLongf *)destLen, (zlib::Bytef *)source, sourceLen);
+    return compress((Bytef *)dest, (uLongf *)destLen, (Bytef *)source, sourceLen);
+    return 0;
+  }
+};
+
+
+
+#include "stru314.h"
+
+
+
+
+//-------------------------------------------------------------------------
+// Data declarations
+
+int (__cdecl *sprintfex)(char *a1, const char *a2, ...) = nullptr;
+
+int pWindowList_at_506F50_minus1_indexing[1];
+int dword_4C9890[10]; // weak
+int dword_4C9920[16]; // weak
+_UNKNOWN unk_4D8548; // weak
+char byte_4D864C; // weak
+float flt_4D86CC = 1.0f; // weak
+int dword_4D86D8; // weak
+int dword_4DAFCC; // weak
+int (__stdcall *off_4DAFDC)(char); // weak
+char asc_4DB724[777]; // idb
+int dword_4DBD94; // weak
+int dword_4DF380[777]; // weak
+int dword_4DF390; // weak
+char Str2[777]; // idb
+int dword_4DF3A4; // weak
+char byte_4E185C; // weak
+char am_byte_4E185D; // weak
+char byte_4E185E; // weak
+int amuint_4E1860; // weak
+int amuint_4E1864; // weak
+int amuint_4E1868; // weak
+int amuint_4E186C; // weak
+int amuint_4E1870; // weak
+int dword_4E1874; // weak
+int dword_4E1878; // weak
+float flt_4D84E8 = 0.0f;
+int dword_4E187C; // weak
+int dword_4E1880; // weak
+int dword_4E1884; // weak
+int dword_4E1888; // weak
+char pArcomagePlayer2Name[8];
+char pArcomagePlayer1Name[8];
+char pDeckMaster[12];
+char aIxf[4]; // idb
+_UNKNOWN unk_4E19FC; // weak
+char pAreYouSureWishToLeave[32];
+char asc_4E1A28[4]; // idb
+char aUsxfs[13];
+char aLayout_pcx[11]; // weak
+char aSprites_pcx[12]; // weak
+char aProblemInBlit_[777]; // idb
+char aEWorkMsdevMm7M[777]; // idb
+char aProblemInBli_0[777]; // idb
+char aD[777]; // idb
+char asc_4E1AB0[777]; // idb
+char aWb_0[777]; // idb
+char a24bitPcxOnly[777]; // idb
+char Mode[777]; // idb
+char a16bitPcx[777]; // idb
+char aUnableToLoadS[777]; // idb
+char aBitmaps[777]; // idb
+char aIcons[777]; // idb
+char aPending[777]; // idb
+char aCanTFindS[777]; // idb
+char pDayMoonPhase[28];
+char *spellbook_texture_filename_suffices[8]; // weak
+__int16 word_4E1D3A[777]; // weak
+__int16 pTownPortalBook_xs[6];
+__int16 pTownPortalBook_ys[6];
+__int16 pTownPortalBook_ws[6];
+__int16 pTownPortalBook_hs[6];
+int dword_4E20D0[777]; // idb
+char byte_4E2430[777]; // weak
+char byte_4E2431[777]; // weak
+unsigned int pLloydsBeaconsPreviewXs[5] = {61, 281,  61, 281, 171};
+unsigned int pLloydsBeaconsPreviewYs[5] = {84,  84, 228, 228, 155};
+unsigned int pLloydsBeacons_SomeXs[5] = {59, 279, 59, 279, 169};
+unsigned int pLloydsBeacons_SomeYs[5] = {82, 82, 226, 226, 153};
+char aSbwb00[7]; // weak
+char aW[2]; // idb
+char aA[2]; // idb
+char aSD[777]; // idb
+char aSS03d03dS000S0[777]; // idb
+char aLuS[777]; // idb
+char aS_1[777]; // idb
+char aSbSc02d[777]; // idb
+char aSbSs02d[777]; // idb
+char aTabDb[777]; // idb
+char aTabDa[777]; // idb
+char aIbM6D[777]; // idb
+char aIbM6U[777]; // idb
+char aIbM5D[777]; // idb
+char aIbM5U[777]; // idb
+char aPagemask[777]; // idb
+char aBook[777]; // idb
+char aSpell_fnt[777]; // idb
+char aAutonote_fnt[777]; // idb
+char aBook2_fnt[777]; // idb
+char pFontFile[777]; // idb
+char aFontpal[777]; // idb
+char aMapbordr[777]; // idb
+char aLloydDD_pcx[777]; // idb
+char aDataLloydDD_pc[777]; // idb
+char aLb_bordr[777]; // idb
+char aTphell[777]; // idb
+char aTpheaven[777]; // idb
+char aTpisland[777]; // idb
+char aTpwarlock[777]; // idb
+char aTpelf[777]; // idb
+char aTpharmndy[777]; // idb
+char aTownport[777]; // idb
+char aSbquiknot[777]; // idb
+char aTabAn8a[777]; // idb
+char aTabAn8b[777]; // idb
+char aTabAn4a[777]; // idb
+char aTabAn4b[777]; // idb
+char aTabAn5a[777]; // idb
+char aTabAn5b[777]; // idb
+char aTabAn3a[777]; // idb
+char aTabAn3b[777]; // idb
+char aTabAn2a[777]; // idb
+char aTabAn2b[777]; // idb
+char aTabAn1a[777]; // idb
+char aTabAn1b[777]; // idb
+char aDivbar[777]; // idb
+char aSbautnot[777]; // idb
+char aTabwoff[777]; // idb
+char aTabwon[777]; // idb
+char aTabeoff[777]; // idb
+char aTabeon[777]; // idb
+char aTabsoff[777]; // idb
+char aTabson[777]; // idb
+char aTabnoff[777]; // idb
+char aTabnon[777]; // idb
+char aZootOff[777]; // idb
+char aZoomOff[777]; // idb
+char aZootOn[777]; // idb
+char aZoomOn[777]; // idb
+char aSbmap[777]; // idb
+char aMoon_ful[777]; // idb
+char aMoon_2[777]; // idb
+char aMoon_4[777]; // idb
+char aMoon_new[777]; // idb
+char aSbdateTime[777]; // idb
+char aTabAn7a[777]; // idb
+char aTabAn6a[777]; // idb
+char aTabAn7b[777]; // idb
+char aTabAn6b[777]; // idb
+char aSbplayrnot[777]; // idb
+char aPending_0[777]; // idb
+char aUnknown[8]; // weak
+char aS100110S[777]; // idb
+char aS100110D[777]; // idb
+char aS100110DS[777]; // idb
+char aS100110D02dSS[777]; // idb
+int pCurrentScreen; // weak
+char byte_4E28FC; // weak
+unsigned int uGammaPos;
+int dword_4E2910[777]; // weak
+__int16 RightClickPortraitXmin[4];
+__int16 RightClickPortraitXmax[4];
+void *off_4E2A12; // weak
+int dword_4E2A18[5];
+int dword_4E2A2C[9];
+int dword_4E2A50[12];
+int _4E2A80_skills[9];
+unsigned __int8 pAwardsTextColors[20];
+unsigned int pHealthBarPos[4] = {22, 137, 251, 366};
+unsigned int pManaBarPos[4] = {102, 217, 331, 447};
+char _4E2AD8_ui_colors[72];
+char _4E2B21_buff_spell_tooltip_colors[80];
+char byte_4E2B70[777]; // weak
+char byte_4E2BC8; // weak
+int pChestSmthn1ByType[8];
+int pChestSmthn2ByType[8];
+int pChestWidthsByType[8];
+int pChestHeightsByType[8];
+char aSS[777]; // idb
+char ascii_4E2C54[6];
+char ascii_4E2C5C[7];
+char ascii_4E2C68[8];
+char ascii_4E2C70[9];
+char ascii_4E2C7C[8];
+char ascii_4E2C84[11];
+char ascii_4E2C90[12];
+char ascii_4E2C9C[8];
+char ascii_4E2CA4[7];
+char ascii_4E2CB0[12];
+char ascii_4E2CBC[12];
+char ascii_4E2CC8[12];
+char ascii_4E2CD4[6];
+char ascii_4E2CDC[11];
+char ascii_4E2CE8[8];
+char ascii_4E2CF0[12];
+char ascii_4E2CFC[6];
+char ascii_4E2D04[8];
+char ascii_4E2D0C[8];
+char ascii_4E2D14[6];
+char ascii_4E2D1C[12];
+char ascii_4E2D28[8];
+char ascii_4E2D30[7];
+char ascii_4E2D38[5];
+char ascii_4E2D40[8];
+char ascii_4E2D48[6];
+char ascii_4E2D50[12];
+char ascii_4E2D5C[7];
+char aMakingItemNumb[777]; // idb
+char aNpc03d[777]; // idb
+char format_4E2D80[16];
+char format_4E2D90[8];
+char aS03d03dS000_0[777]; // idb
+char aS03d03dS000[777]; // idb
+char format_4E2DC8[8];
+char aS[777]; // idb
+char aLuSLuS[777]; // idb
+char byte_4E2DE8; // idb
+char asc_4E2DFC[3]; // idb
+char format_4E2E00[2]; // idb
+char format_4E2E10[28]; // weak
+char aS100S_0[777]; // idb
+char aS100S[777]; // idb
+char aS100D[777]; // idb
+char aS180[6]; // idb
+char format_4E2E68[28]; // weak
+char aS_6[2]; // idb
+char aSS_0[777]; // idb
+char aS_5[4]; // idb
+_UNKNOWN unk_4E2EB8; // weak
+char string_4E3294[8];
+char Format[777]; // idb
+char aMem03i_txt[777]; // idb
+char aMemory[777]; // idb
+char aIdSSizeI[16]; // idb
+__int16 word_4E3C66[777]; // idb
+int dword_4E455C; // weak
+int dword_4E4560[6];
+int dword_4E4578[6];
+int dword_4E4590[6];
+int dword_4E45A8[6];
+char aDDSDDS[777]; // idb
+char asc_4E45DC[777]; // idb
+char aD02dSSDSD[777]; // idb
+char aButtexi1[777]; // idb
+char aCanTJumpToThat[777]; // idb
+char aNoMapFoundForS[777]; // idb
+char global_a2[777]; // idb
+char aSSS[777]; // idb
+char aNotInMapStats[17]; // weak
+char aD47_blv[777]; // idb
+char aOut15_odm[777]; // idb
+char Delim[777]; // idb
+char aGamma_pcx[777];
+char aQuit1[777]; // idb
+char aControls1[777]; // idb
+char aSave1[777]; // idb
+char aLoad1[777]; // idb
+char aNew1[777]; // idb
+char aOptions[777]; // idb
+char aGammapos[9]; // weak
+char aBloodsplats[777]; // idb
+char aTinting[777]; // idb
+char aColoredLights[777]; // idb
+char aTurndelta[777]; // idb
+char aFliponexit[777]; // idb
+char pKey[777]; // idb
+char aGraphicsmode[777]; // idb
+char aShowdamage[777]; // idb
+char aWalksound[777]; // idb
+char aCharvoices[777]; // idb
+char aMusicflag[777]; // idb
+char aSoundflag[777]; // idb
+char aOpvdgTn[777]; // idb
+char aOpvdgCl[777]; // idb
+char aOpvdgBs[777]; // idb
+char aOpvdhTn[777]; // idb
+char aOpvdhCl[777]; // idb
+char aOpvdhBs[777]; // idb
+char aOptvid[777]; // idb
+char aOptkb_2[777]; // idb
+char aOptkb_1[777]; // idb
+char aResume1[777]; // idb
+char aOptkb_h[777]; // idb
+char aOptkb[777]; // idb
+char aOption01[777]; // idb
+char aOption02[777]; // idb
+char aOption03[777]; // idb
+char aOption04[777]; // idb
+char aConvol90[777]; // idb
+char aConvol80[777]; // idb
+char aConvol70[777]; // idb
+char aConvol60[777]; // idb
+char aConvol50[777]; // idb
+char aConvol40[777]; // idb
+char aConvol30[777]; // idb
+char aConvol20[777]; // idb
+char aConvol10[777]; // idb
+char aConvol00[777]; // idb
+char aCon_smoo[777]; // idb
+char aCon_arrr[777]; // idb
+char aCon_arrl[777]; // idb
+char aCon_32x[777]; // idb
+char aCon_16x[777]; // idb
+char aControlbg[777]; // idb
+char aTitle_pcx[10]; // weak
+char aEWorkMsdevMm_0[777]; // idb
+char aDraw_debug_lin[777]; // idb
+char aGenuineintel[13]; // weak
+char asc_4E4938[13]; // weak
+int dword_4E4948[777]; // weak
+int dword_4E494C[777]; // weak
+int dword_4E49D0[777]; // weak
+_UNKNOWN dword_4E49D4; // idb
+int dword_4E4A18[777]; // weak
+int dword_4E4A1C[777]; // weak
+int dword_4E4A40[777]; // weak
+int dword_4E4A44[777]; // weak
+char aCentaurhauls[13]; // weak
+char aCyrixinstead[13]; // weak
+char aAuthenticamd[13]; // weak
+float flt_4E4A80[10];
+char aInvalidPlayerI[777]; // idb
+char aEWorkMsdevMm_1[777]; // idb
+char aEWorkMsdevMm_2[777]; // idb
+char aErrorNoKeyboar[25]; // weak
+char aInvalidDeviceP[777]; // idb
+char aInvalidDevic_0[777]; // idb
+char aEWorkMsdevMm_3[777]; // idb
+char aErrorNoMouseFo[22]; // weak
+int papredoll_4E4C28; // weak
+int paperdoll_4E4C2C; // weak
+int paperdoll_array_4E4E30[4][17][2];
+int dword_4E5050[8];
+int dword_4E5270[8];
+int dword_4E5490[4][7][2];
+int paredoll_array_4E54B8[3][14];
+int paperdoll_array_4E5570[4][10][2];
+int dword_4E56B0; // weak
+int dword_4E56B4; // weak
+int dword_4E57F0[4][7][2];
+int dword_4E58D0[777]; // weak
+int dword_4E58D4[777]; // weak
+int dword_4E5AD0[777]; // weak
+int dword_4E5AD4[777]; // weak
+int dword_4E5AE0[8];
+int pPaperdollLeftHand[8];
+int pPaperdollRightHand[8];
+int pPaperdollLeftEmptyHand[8];
+int dword_4E5C1C[6];
+int dword_4E5C34[6];
+char aItem092v3[777]; // idb
+char aIbCd5D[777]; // idb
+char aAr_dn_dn[777]; // idb
+char aAr_dn_up[777]; // idb
+char aAr_up_dn[777]; // idb
+char aAr_up_up[777]; // idb
+char aItem281pc02d[777]; // idb
+char aPc02dbrd[777]; // idb
+char aPc23vDlhu[777]; // idb
+char aPc23vDlh[777]; // idb
+char aPc23vDrh[777]; // idb
+char aPc23vDlau[777]; // idb
+char aPc23vDlad[777]; // idb
+char aPc23vDbod[777]; // idb
+char aBackhand[777]; // idb
+char aBackdoll[777]; // idb
+char aMagnifB[777]; // idb
+char aItem3_3dvDa2[777]; // idb
+char aItem3_3dvDa1[15]; // weak
+char aItem3_3dvD[13]; // weak
+char aItem64v1[9]; // weak
+char aEffpar01[777]; // idb
+int pPartySpellbuffsUI_XYs[14][2];
+char byte_4E5DD8[777]; // weak
+unsigned __int8 pPartySpellbuffsUI_smthns[14];
+char aSpell27[777]; // idb
+char aSpell21[777]; // idb
+char aIsn02d[777]; // idb
+char aBardataB[777]; // idb
+char aBardata[8]; // weak
+char aBardataC[10]; // weak
+char aLoadprog[777]; // idb
+char aLoadingD_pcx[777]; // idb
+int _4E5E50_transui_x; // idb
+int dword_4E5EC8[777]; // weak
+int _4E5EE0_transui_y; // idb
+const char *pHouse_ExitPictures[11];
+char *_4E6BDC_loc_names[11];
+char aOutside[777]; // idb
+char aMer[777]; // idb
+char aMir[777]; // idb
+char aSel[777]; // idb
+char aEle[777]; // idb
+char aDar[777]; // idb
+char aLig[777]; // idb
+char aBod[777]; // idb
+char aMin[777]; // idb
+char aSpi[777]; // idb
+char aEar[777]; // idb
+char aWat[777]; // idb
+char aAir[777]; // idb
+char aFir[777]; // idb
+char aBan[777]; // idb
+char aTav[777]; // idb
+char aTow[777]; // idb
+char aTra[777]; // idb
+char aTem[777]; // idb
+char aBoa[777]; // idb
+char aSta[777]; // idb
+char aAlc[777]; // idb
+char aMag[777]; // idb
+char aArm[777]; // idb
+char aWea[777]; // idb
+char asc_4E7BD4[2]; // idb
+char a2devents_txt[777]; // idb
+char aFileSSizeLuBuf[777]; // idb
+char aGlobal_evt[777]; // idb
+char aMax_event_text[777]; // idb
+char aS_str[777]; // idb
+char aS_evt[777]; // idb
+char aNoMazeInfoForT[36]; // weak
+char aC[777]; // idb
+char aB[3]; // weak
+char aEvt02d[777]; // idb
+char aNoTransitionTe[777]; // idb
+char aEWorkMsdevMm_4[777]; // idb
+char asc_4E7CD4[777]; // idb
+char aSS_1[777]; // idb
+char aNpcIdExceedsMa[777]; // idb
+char aNpc03u[777]; // idb
+char aPcout01[777]; // idb
+char aArbiterEvil[777]; // idb
+char aArbiterGood[777]; // idb
+char a0[777]; // idb
+char aPartyStart[777]; // idb
+char aNorthStart[12]; // weak
+char aSouthStart[12]; // weak
+char aEastStart[11]; // weak
+char aWestStart[11]; // weak
+char aUnableToFindDo[777]; // idb
+char aNwc_blv[777]; // idb
+char aUnableToOpenS[777]; // idb
+char aInvalidStringP[777]; // idb
+char aEWorkMsdevMm_5[777]; // idb
+char aNull[777]; // idb
+char aInvalidStrin_0[777]; // idb
+char aSI[777]; // idb
+char aS7[4]; // weak
+char aS6[777]; // idb
+char aS5[4]; // weak
+char aS1[777]; // idb
+char aS3[4]; // weak
+char aS0[777]; // idb
+char aS2[4]; // weak
+char aS4[4]; // weak
+char aUnableToSaveDs[777]; // idb
+char aDataDsft_bin[777]; // idb
+char aPFrames[777]; // idb
+char aEFrames[777]; // idb
+char aSFrames[777]; // idb
+char aMirror7[777]; // idb
+char aMirror6[777]; // idb
+char aMirror5[777]; // idb
+char aMirror4[777]; // idb
+char aMirror3[777]; // idb
+char aMirror2[777]; // idb
+char aMirror1[777]; // idb
+char aMirror0[777]; // idb
+char aLuminous[777]; // idb
+char a1[777]; // idb
+char aNew[777]; // idb
+char pMessag[777]; // idb
+char aCspriteframeta[777]; // idb
+char aR[777]; // idb
+char aNew_0[777]; // idb
+char aUnableToSaveDt[777]; // idb
+char aDataDtft_bin[777]; // idb
+char aTxtFrames[777]; // idb
+char aCtexturefram_1[777]; // idb
+char aCtexturefram_0[777]; // idb
+char aCtextureframet[777]; // idb
+int bWinNT4_0; // weak
+char aEWorkMsdevMm_6[777]; // idb
+char aTheVisObjectPo[777]; // idb
+char aSpriteOutlineC[777]; // idb
+char aUndefinedCobje[777]; // idb
+char aEWorkMsdevMm_7[777]; // idb
+char aGammaControlNo[777]; // idb
+__int16 word_4E8152[11] = {0, 0, 0, 90, 8, 2, 70, 20, 10, 50, 30};
+char byte_4E8168[116];
+char aD3dTextureName[777]; // idb
+char aLogd3d_txt[777]; // idb
+char byte_4E8394[204] =
+{
+  0, 0, 0, 0, 1, 1, 2, 3, 0, 4, 5, 6, 7, 8, 10, 9, 1, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
+  1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,  0, 0, 0, 0, 1, 0, 1, 1, 1,
+  0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,  0, 0, 0, 0, 1, 1, 1, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,  1, 1, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,  0, 0, 0, 1, 1, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 3, 3, 3, 3, 3, 3, 1,
+  1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,  2, 0, 0, 0, 0, 0
+};
+stru355 stru_4E82A4 = {0x20, 0x41, 0, 0x20, 0xFF0000, 0xFF00, 0xFF, 0xFF000000};
+stru355 stru_4EFCBC = {0x20, 0x41, 0, 0x10, 0x7C00, 0x3E0, 0x1F, 0x8000};
+char byte_4E94D0 = 5; // weak
+char byte_4E94D1 = 9; // weak
+char _4E94D2_light_type = 6; // weak
+char byte_4E94D3 = 10; // weak
+unsigned int saveload_dlg_xs[2] = {82, 0};
+unsigned int saveload_dlg_ys[2] = {60, 0};
+unsigned int saveload_dlg_zs[2] = {460, 640};
+unsigned int saveload_dlg_ws[2] = {344, 480};
+int dword_4E98BC_bApplicationActive; // weak
+char *off_4EB080; // idb
+char *pTransitionStrings[464];
+char aAwards_txt[777]; // idb
+char aScroll_txt[777]; // idb
+char aMerchant_txt[777]; // idb
+char aTrans_txt[777]; // idb
+char aTeacher[777]; // idb
+char aObelisk[777]; // idb
+char aSeer[777]; // idb
+char aStat[777]; // idb
+char aPotion[777]; // idb
+char aAutonote_txt[777]; // idb
+char aQuests_txt[777]; // idb
+char aNpcdist_txt[777]; // idb
+char aNpctopic_txt[777]; // idb
+char aNpctext_txt[777]; // idb
+char aNpcnews_txt[777]; // idb
+char aNpcgroup_txt[777]; // idb
+char aNpcgreet_txt[777]; // idb
+char aNpcdata_txt[777]; // idb
+char aNpcprof_txt[777]; // idb
+char aNpcnames_txt[777]; // idb
+char aD3dVersionOfRe[777]; // idb
+char aEWorkMsdevM_16[777]; // idb
+char aLevels_0[777]; // idb
+char aDmap[777]; // idb
+char aAmap[777]; // idb
+char aTmap[777]; // idb
+char aHmap[777]; // idb
+int dword_4EC268[777]; // weak
+int dword_4EC28C[777]; // weak
+int dword_4EC2A8; // weak
+int dword_4EC2AC; // weak
+char aInvalidGroundT[777]; // idb
+char aInvalidSkyTexH[777]; // idb
+char aIdlist[777]; // idb
+char aOmap[777]; // idb
+char aCmap[777]; // idb
+char aMm6OutdoorV1_0[777]; // idb
+char aI6_odm[777]; // idb
+char aBlank[777]; // idb
+char aHm005[777]; // idb
+char aSky043[777]; // idb
+char aDefault_odm[777]; // idb
+char aPlansky3[777]; // idb
+char aPlanskyD[777]; // idb
+char a_ddm[5]; // weak
+char aCanTLoadFile[777]; // idb
+char aEWorkMsdevM_17[777]; // idb
+char a_odm[777]; // idb
+char aUnableToFindSI[777]; // idb
+char aSpawn[777]; // idb
+char aBddata[777]; // idb
+char aTernorm[777]; // idb
+char aGrastyl[777]; // idb
+char aOut09_odm[777]; // idb
+char aNewedges[777]; // idb
+char aSurfs[777]; // idb
+char aEdges[777]; // idb
+char aSpans[777]; // idb
+char aTheTextureFram[777]; // idb
+char aEWorkMsdevM_18[777]; // idb
+char aWtrtyla[777]; // idb
+char aWtrtyl[777]; // idb
+char aUnableToSave_1[777]; // idb
+char aDataDtile_bin[777]; // idb
+char aTileDescrip[777]; // idb
+char aTtattr_transit[777]; // idb
+char aTtattr_nodraw[777]; // idb
+char aTtattr_wave[777]; // idb
+char aTtattr_flat[777]; // idb
+char aTtattr_repulse[777]; // idb
+char aTtattr_block[777]; // idb
+char aTtattr_water2[777]; // idb
+char aTtattr_water[777]; // idb
+char aTtattr_burn[777]; // idb
+char aTtsect_dnw[777]; // idb
+char aTtsect_dse[777]; // idb
+char aTtsect_dne[777]; // idb
+char aTtsect_dsw[777]; // idb
+char aTtsect_de[777]; // idb
+char aTtsect_dw[777]; // idb
+char aTtsect_ds[777]; // idb
+char aTtsect_dn[777]; // idb
+char aTtsect_wcap[777]; // idb
+char aTtsect_scap[777]; // idb
+char aTtsect_ecap[777]; // idb
+char aTtsect_ncap[777]; // idb
+char aTtsect_ew_s[777]; // idb
+char aTtsect_ew_n[777]; // idb
+char aTtsect_ns_w[777]; // idb
+char aTtsect_ns_e[777]; // idb
+char aTtsect_s_w[777]; // idb
+char aTtsect_s_e[777]; // idb
+char aTtsect_n_w[777]; // idb
+char aTtsect_n_e[777]; // idb
+char aTtsect_ew[777]; // idb
+char aTtsect_ns[777]; // idb
+char aTtsect_cros[777]; // idb
+char aTtsect_xsw1[777]; // idb
+char aTtsect_xse1[777]; // idb
+char aTtsect_xnw1[777]; // idb
+char aTtsect_xne1[777]; // idb
+char aTtsect_s1[777]; // idb
+char aTtsect_n1[777]; // idb
+char aTtsect_w1[777]; // idb
+char aTtsect_e1[777]; // idb
+char aTtsect_sw1[777]; // idb
+char aTtsect_se1[777]; // idb
+char aTtsect_nw1[777]; // idb
+char aTtsect_ne1[777]; // idb
+char aTtsect_speci_6[777]; // idb
+char aTtsect_speci_5[777]; // idb
+char aTtsect_speci_4[777]; // idb
+char aTtsect_speci_3[777]; // idb
+char aTtsect_speci_2[777]; // idb
+char aTtsect_speci_1[777]; // idb
+char aTtsect_speci_0[777]; // idb
+char aTtsect_special[777]; // idb
+char aTtsect_base4[777]; // idb
+char aTtsect_base3[777]; // idb
+char aTtsect_base2[777]; // idb
+char aTtsect_base1[777]; // idb
+char aTtsect_start[777]; // idb
+char aTtsect_null[777]; // idb
+char aTttype_roadcit[777]; // idb
+char aTttype_roads_2[777]; // idb
+char aTttype_roadsno[777]; // idb
+char aTttype_roadt_0[777]; // idb
+char aTttype_roadtro[777]; // idb
+char aTttype_roads_1[777]; // idb
+char aTttype_roadswa[777]; // idb
+char aTttype_roadv_0[777]; // idb
+char aTttype_roadvol[777]; // idb
+char aTttype_roads_0[777]; // idb
+char aTttype_roadsan[777]; // idb
+char aTttype_roadc_0[777]; // idb
+char aTttype_roadcra[777]; // idb
+char aTttype_roadg_0[777]; // idb
+char aTttype_roadgra[777]; // idb
+char aTttype_city[777]; // idb
+char aTttype_swamp[777]; // idb
+char aTttype_tropica[777]; // idb
+char aTttype_water[777]; // idb
+char aTttype_dirt[777]; // idb
+char aTttype_volcano[777]; // idb
+char aTttype_sand[777]; // idb
+char aTttype_snow[777]; // idb
+char aTttype_cracked[777]; // idb
+char aTttype_grass[777]; // idb
+char aTttype_start[777]; // idb
+char aTttype_null[777]; // idb
+char aTiletableLoadO[777]; // idb
+char aTiletableLoadU[777]; // idb
+char byte_4ECA93[777]; // weak
+char byte_4ECACF[777]; // weak
+char byte_4ECB0C[64]; // idb
+char aError_0[777]; // idb
+char aCouldnTLoadMap[777]; // idb
+char aOut02d_odm[777]; // idb
+char aOut14_odm[777]; // idb
+char aOut[777]; // idb
+char aLunSun[777]; // idb
+char aLunfull[777]; // idb
+char aLun34[777]; // idb
+char aLun12[777]; // idb
+char aLun14[777]; // idb
+char aPal03i[777]; // idb
+const char *pPlayerPortraitsNames[25] =
+{
+  "pc01-", "pc02",  "pc03", "pc04",  "pc05-",
+  "pc06",  "pc07",  "pc08", "pc09-", "pc10",
+  "pc11-", "pc12",  "pc13", "pc14",  "pc15",
+  "pc16",  "pc17-", "pc18", "pc19",  "pc20",
+  "pc21-", "pc22-", "pc23", "pc24-", "pc25-"
+};
+
+const char *dlad_texnames_by_face[25] =
+{
+  "pc01lad", "pc02lad", "pc03lad", "pc04lad", "pc05lad", "pc06lad",
+  "pc07lad", "pc08lad", "pc09lad", "pc10lad", "pc11lad", "pc12lad",
+  "pc13lad", "pc14lad", "pc15lad", "pc16lad", "pc17lad", "pc18lad",
+  "pc19lad", "pc20lad", "pc21lad", "pc22lad", "pc23lad", "pc24lad",
+  "pc25lad"
+};
+const char *dlau_texnames_by_face[25] =
+{
+  "pc01lau", "pc02lau", "pc03lau", "pc04lau", "pc05lau", "pc06lau",
+  "pc07lau", "pc08lau", "pc09lau", "pc10lau", "pc11lau", "pc12lau",
+  "pc13lau", "pc14lau", "pc15lau", "pc16lau", "pc17lau", "pc18lau",
+  "pc19lau", "pc20lau", "pc21lau", "pc22lau", "pc23lau", "pc24lau",
+  "pc25lau"
+};
+const char *dbod_texnames_by_face[25] =
+{
+  "pc01bod", "pc02bod", "pc03bod", "pc04bod", "pc05bod", "pc06bod",
+  "pc07bod", "pc08bod", "pc09bod", "pc10bod", "pc11bod", "pc12bod",
+  "pc13bod", "pc14bod", "pc15bod", "pc16bod", "pc17bod", "pc18bod",
+  "pc19bod", "pc20bod", "pc21bod", "pc22bod", "pc23bod", "pc24bod",
+  "pc25bod"
+};
+const char *drh_texnames_by_face[25] =
+{
+
+  "pc01rh", "pc02rh", "pc03rh", "pc04rh", "pc05rh", "pc06rh",
+  "pc07rh", "pc08rh", "pc09rh", "pc10rh", "pc11rh", "pc12rh",
+  "pc13rh", "pc14rh", "pc15rh", "pc16rh", "pc17rh", "pc18rh",
+  "pc19rh", "pc20rh", "pc21rh", "pc22rh", "pc23rh", "pc24rh",
+  "pc25rh"
+};
+const char *dlh_texnames_by_face[25] =
+{
+  "pc01lh", "pc02lh", "pc03lh", "pc04lh", "pc05lh", "pc06lh",
+  "pc07lh", "pc08lh", "pc09lh", "pc10lh", "pc11lh", "pc12lh",
+  "pc13lh", "pc14lh", "pc15lh", "pc16lh", "pc17lh", "pc18lh",
+  "pc19lh", "pc20lh", "pc21lh", "pc22lh", "pc23lh", "pc24lh",
+  "pc25lh"
+};
+const char *dlhu_texnames_by_face[25] =
+{
+  "pc01lhu", "pc02lhu", "pc03lhu", "pc04lhu", "pc05lhu", "pc06lhu",
+  "pc07lhu", "pc08lhu", "pc09lhu", "pc10lhu", "pc11lhu", "pc12lhu",
+  "pc13lhu", "pc14lhu", "pc15lhu", "pc16lhu", "pc17lhu", "pc18lhu",
+  "pc19lhu", "pc20lhu", "pc21lhu", "pc22lhu", "pc23lhu", "pc24lhu",
+  "pc25lhu"
+};
+short SoundSetAction[192]=
+{
+	0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 37, 38, 45, 0, 0, 37, 0, 0, 47, 53, 0, 0, 0, 2, 0, 0, 25, 0, 0, 0, 0, 1, 0, 0, 47, 0,
+	0, 0, 0, 3, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 5, 0, 0, 21, 22, 23, 24, 45, 6, 0, 0, 47, 0, 0, 0, 0, 7, 0,
+	0, 43, 48, 0, 0, 0, 8, 0, 0, 38, 0, 0, 0, 0, 9, 0, 0, 39, 0, 0, 0, 0, 13, 0, 0, 37, 38, 0, 0, 0, 23, 0, 0, 25, 0, 0, 0,
+	0, 0, 0, 0, 37, 38, 45, 0, 0, 25, 0, 0, 25, 0, 0, 0, 0, 26, 0, 0, 38, 47, 0, 0, 0, 27, 0, 0, 41, 42, 0, 0, 0, 28, 0, 0,
+	25, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 30, 0, 0, 25, 0, 0, 0, 0, 29, 0, 0, 27, 0, 0, 0, 0, 32, 33, 0, 37, 38, 0, 0, 0,
+	34, 0, 0, 53, 0, 0, 0, 0
+}; // weak
+unsigned char byte_4ED498 = 15; // weak
+__int16 pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[4] = {34, 149, 264, 379};
+char byte_4ED970_skill_learn_ability_by_class_table[32][37];
+int dword_4EDEA0[777]; // weak
+int dword_4EDEB4[777]; // weak
+int dword_4EDEC4[777]; // weak
+__int16 word_4EDED8[16] = {100, 90, 60, 100, 80, 100, 80, 30, 10, 10, 20, 30, 100, 0, 0, 0};
+_UNKNOWN unk_4EDF40; // weak
+unsigned int pHiredNPCsIconsOffsetsX[2] = {489, 559};
+unsigned int pHiredNPCsIconsOffsetsY[2] = {152, 152};
+int dword_4EE07C[2]; // weak
+_UNKNOWN unk_4EE084; // weak
+__int16 word_4EE088_sound_ids[100] =
+{
+      0, 10000, 10010, 10020, 10030, 10040, 10050, 10060, 10070, 10080,
+  10090, 10100, 11000, 11010, 11020, 11030, 11040, 11050, 11060, 11070,
+  11080, 11090, 11100, 12000, 12010, 12020, 12030, 12040, 12050, 12060,
+  12070, 12080, 12090, 12100, 13000, 13010, 13020, 13030, 13040, 13050,
+  13060, 13070, 13080, 13090, 13100, 14000, 14010, 14020, 14030, 14040,
+  14050, 14060, 14070, 14080, 14090, 14100, 15000, 15010, 15020, 15030,
+  15040, 15050, 15060, 15070, 15080, 15090, 15100, 16000, 16010, 16020,
+  16030, 16040, 16050, 16060, 16070, 16080, 16090, 16100, 17000, 17010,
+  17020, 17030, 17040, 17050, 17060, 17070, 17080, 17090, 17100, 18000,
+  18010, 18020, 18030, 18040, 18050, 18060, 18070, 18080, 18090, 18100
+};
+short word_4EE150[28] =
+{
+   1,  2,  3,  4,  5,  7, 32, 33, 36, 37, 38, 40, 41, 42, 43, 45, 46,
+  47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 60
+};
+
+int dword_4EED78; // weak
+_UNKNOWN unk_4EED80; // weak
+int dword_4EFA80; // weak
+int dword_4EFA84; // weak
+void *off_4EFDB0; // weak
+int dword_4F031C[777]; // weak
+const char *off_4F03B8[] =
+{
+  "",         "WEPNTABL", "ARMORY",   "MAGSHELF",
+  "MAGSHELF", "MAGSHELF", "MAGSHELF", "MAGSHELF",
+  "MAGSHELF", "MAGSHELF", "MAGSHELF", "MAGSHELF",
+  "MAGSHELF", "MAGSHELF", "MAGSHELF", "MAGSHELF",
+  "MAGSHELF"
+};
+__int16 word_4F03FE[777]; // weak
+__int16 word_4F0400[777]; // weak
+__int16 word_4F0498[777]; // weak
+__int16 word_4F0576[777]; // weak
+__int16 word_4F0578[777]; // weak
+__int16 word_4F05AE[777]; // weak
+char _4F063C_smthn_by_2da_uType[777]; // weak
+__int16 word_4F063E[290];
+__int16 word_4F06D8[22];
+__int16 word_4F0704[40];
+__int16 word_4F0754[49];
+__int16 word_4F07B6[88];
+__int16 word_4F0866[14];
+__int16 _4F0882_evt_VAR_PlayerItemInHands_vals[53];
+int dword_4F08EC[777]; // weak
+char byte_4F09B0[777]; // weak
+char byte_4F09B1[777]; // weak
+char byte_4F09B8[777]; // weak
+int dword_4F09CC[192];
+char byte_4F0CCF[777]; // weak
+char _4F0D38_TravelInfo[777]; // weak
+int dword_4F0E10[32];
+Vec2_int_ pMonsterArenaPlacements[20];
+__int16 word_4F0F30[777]; // weak
+char aS03d[777]; // idb
+char byte_4F0F98; // idb
+char sz[777]; // idb
+char aSSSSSS[777]; // idb
+char aSDS[777]; // idb
+char aSS_3[777]; // idb
+char aSSSS[777]; // idb
+char aS_2[777]; // idb
+char aErrorlog_txt[777]; // idb
+char aUnsupportedPix[777]; // idb
+char aSmackerError[777]; // idb
+char aCS[777]; // idb
+char aAnimsMagic7_vi[777]; // idb
+char aVideoFileError[777]; // idb
+char aCanTOpenFileAn[777]; // idb
+char aAnimsMight7_vi[777]; // idb
+char aCanTLoadS[777]; // idb
+char aS_smk[777]; // idb
+char aUnsupportedBin[27]; // weak
+char aEWorkMsdevM_29[777]; // idb
+char aFailedToOpenBl[777]; // idb
+char aCanTAllocateMe[33]; // weak
+char aCanTLoadFileAn[777]; // idb
+char aS_bik[777]; // idb
+char aMm7_win_pcx[777]; // idb
+char aLuSLuSLuS[777]; // idb
+char aEndgame_fnt[777]; // idb
+char aWinbg_pcx[10]; // weak
+char aDefaultCaseRea[777]; // idb
+char aUnsupportedExc[71]; // weak
+char aEWorkMsdevM_30[777]; // idb
+char aUndefinedTypeR[777]; // idb
+char aUnknownPointer[777]; // idb
+char a1_1_3[6]; // weak
+double dbl_4F2870; // weak
+int dword_4F288C; // weak
+double dbl_4F5372; // weak
+int dword_4F5428[777]; // weak
+int dword_4F542C[777]; // weak
+_UNKNOWN crtunk_4F54B8; // weak
+int dword_4F5B24_ys[777]; // idb
+int dword_4F5BF4_xs[777]; // idb
+int dword_4F5CC4_ys[777]; // idb
+int dword_4F5D98_xs[777]; // idb
+int ai_array_4F5E68[500];
+int ai_array_4F6638_actor_ids[500];
+int dword_4F6E08[500];
+int ai_arrays_size; // weak
+int ai_array_4F75E0[500];
+unsigned int ai_array_4F7DB0_actor_ids[500];
+int dword_4F8580[182]; // weak
+int dword_4FA9B0[777]; // weak
+int dword_4FA9B4[777]; // weak
+char byte_4FAA00; // weak
+__int16 am_sounds[12];
+_UNKNOWN unk_4FAA20; // weak
+char byte_4FAA24; // weak
+HWND dword_4FAA28; // idb
+char byte_4FAA2C; // weak
+char byte_4FAA2D; // weak
+char byte_4FAA2E; // weak
+int amuint_4FAA34; // weak
+int amuint_4FAA38; // weak
+int amuint_4FAA3C_blt_xy[2];
+int am_uint_4FAA44_blt_xy[2];
+int amuint_4FAA4C; // weak
+unsigned int uCardID; // idb
+int amuint_4FAA54_blt_xy[2];
+int amuint_4FAA5C_blt_xy[2];
+int dword_4FAA64; // weak
+int dword_4FAA68; // weak
+int amuint_4FAA6C; // idb
+int dword_4FAA70; // weak
+char byte_4FAA74; // weak
+char am_byte_4FAA75; // weak
+char am_byte_4FAA76; // weak
+char am_byte_4FAA77; // weak
+int amuint_4FAA78[777]; // weak
+char am_byte_4FAA7C[777]; // weak
+int amuint_4FAA80[777]; // weak
+int amuint_4FAA84[777]; // weak
+int amuint_4FAA88[777]; // weak
+int amuint_4FAA8C[777]; // weak
+int amuint_4FAA90[777][2];
+int dword_4FABB8; // weak
+signed int dword_4FABBC; // idb
+unsigned int amuint_4FABC0; // idb
+int amuint_4FABC4; // weak
+int dword_4FABC8; // weak
+char byte_4FABD0[777]; // weak
+char byte_4FABD1[777]; // weak
+_UNKNOWN unk_4FABD4; // weak
+int dword_4FABD8[777]; // weak
+int dword_4FABDC[777]; // weak
+int dword_4FABE0[777]; // weak
+int dword_4FABE4[777]; // weak
+int dword_4FABE8[777]; // weak
+int dword_4FABEC[777]; // weak
+int dword_4FABF0[777]; // weak
+int dword_4FABF4[777]; // weak
+int dword_4FABF8[777]; // weak
+int dword_4FABFC[777]; // weak
+int dword_4FAC00[777]; // weak
+int dword_4FAC04[777]; // weak
+int dword_4FAC08[777]; // weak
+int dword_4FAC0C[777]; // weak
+_UNKNOWN unk_5052C8; // weak
+int dword_505314[777]; // weak
+char byte_5054C8[32]; // idb
+char byte_5054E8[108];
+int dword_505554[777]; // weak
+_UNKNOWN unk_505704; // weak
+char byte_505880; // weak
+char byte_505881; // weak
+int amuint_505884; // weak
+int amuint_505888; // weak
+int amuint_50588C; // weak
+int dword_505890; // weak
+unsigned int pSRZBufferLineOffsets[480];
+int areWeLoadingTexture; // weak
+char byte_506130[777]; // weak
+int dword_506338; // weak
+int dword_50633C; // idb
+signed int sRecoveryTime; // idb
+unsigned int uRequiredMana; // idb
+int _506348_current_lloyd_playerid; // weak
+__int64 qword_506350; // weak
+char byte_506360; // weak
+int dword_506364; // weak
+int dword_506408[777]; // weak
+int dword_50640C[777]; // weak
+unsigned int uTextureID_506438;
+int dword_50651C; // weak
+int dword_506520; // weak
+int dword_506524; // weak
+int dword_506528; // weak
+int dword_50652C; // weak
+int dword_506530; // weak
+int dword_506534; // weak
+int dword_506538; // weak
+int dword_50653C; // weak
+int dword_506540; // weak
+int dword_506544; // weak
+int dword_506548; // weak
+int dword_50654C; // weak
+char byte_506550; // weak
+char *aMoonPhaseNames[5];
+int dword_506568; // weak
+char bRecallingBeacon; // weak
+int uLastPointedObjectID; // weak
+//unsigned __int8 bMonsterInfoUI_bDollInitialized;
+char *aSpellNames[44];
+int dword_506978; // weak
+char byte_50697C; // weak
+int dword_506980; // weak
+int dword_506984; // weak
+int dword_506988; // weak
+int dword_50698C; // weak
+int dword_506E68; // weak
+__int16 word_506E6C[18]; // weak
+unsigned int pPrevVirtualCidesMapping[27];
+int dword_506F08; // weak
+int dword_506F0C[777]; // idb
+int uRestUI_FoodRequiredToRest;
+int dword_506F14; // weak
+int _506F18_num_hours_to_sleep; // weak
+int dword_506F1C; // weak
+int pVisibleWindowsIdxs[20]; // weak
+int uNumVisibleWindows;
+char bFlashHistoryBook; // weak
+char bFlashAutonotesBook; // weak
+char bFlashQuestBook; // weak
+int dword_507960; // weak
+int dword_507964; // weak
+int dword_507968; // weak
+int dword_50796C; // weak
+int dword_507974; // weak
+int dword_5079B4; // weak
+int dword_5079C8; // weak
+int dword_5079CC; // weak
+int dword_5079D0; // weak
+int dword_5079D8; // weak
+struct GUIButton *dword_507A14; // idb
+struct GUIButton *dword_507A18; // idb
+unsigned int uGameUIFontShadow;
+unsigned int uGameUIFontMain;
+int dword_507B00_spell_info_to_draw_in_popup; // weak
+char *aMonthNames[12];
+char *aDayNames[7];
+char *aSpellSchoolNames[9];
+char *aAttributeNames[7];
+int dword_507B94; // weak
+int dword_507B98_ctrl_pressed; // weak
+unsigned int uActiveCharacter;
+int dword_507BF0_is_there_popup_onscreen; // weak
+int dword_507C08; // weak
+int dword_507C0C; // weak
+int dword_507CBC; // weak
+int dword_507CC0; // weak
+__int64 qword_507CC8; // weak
+int _507CD4_RestUI_hourglass_anim_controller; // weak
+int dword_507CD8; // weak
+int dword_50B570[777]; // weak
+int dword_50B638[777]; // weak
+int dword_50B700; // weak
+int dword_50B738[777]; // idb
+int _50B744_view_transformed_ys[43];
+int dword_50B828[777];
+int _50B834_view_transformed_zs[43];
+int dword_50B918[777];
+int _50B924_view_transformed_xs[43];
+int unk_50B9D4[777]; // idb
+int dword_50B9D8_ys[777];
+int dword_50B9E0_ys[777]; // idb
+int dword_50B9EC[777]; // idb
+int dword_50B9F0[2]; // idb
+int dword_50BAE8_xs[777];
+int dword_50BAF4_xs[777];
+int dword_50B9F8[777]; // idb
+int dword_50BA08[777]; // idb
+int dword_50BAC4[777]; // weak
+int dword_50BAC8[777]; // idb
+int dword_50BAD0[777]; // weak
+int dword_50BAD4[777]; // weak
+int dword_50BADC_xs[777]; // weak
+int dword_50BAE0[777]; // weak
+int dword_50BAE8[777]; // weak
+int dword_50BAEC_xs[777]; // weak
+int dword_50BAF4[777]; // weak
+int dword_50BAF8_xs[777]; // weak
+int dword_50BC10[777]; // weak
+int dword_50BDA0[777]; // weak
+int dword_50BF30[777]; // weak
+char byte_50C0C0; // weak
+int some_active_character; // weak
+_UNKNOWN unk_50C190; // weak
+int dword_50C968; // weak
+unsigned int pIconIDs_Turn[5];
+unsigned int uIconID_TurnStop;
+unsigned int uIconID_TurnHour;
+int uIconID_CharacterFrame; // idb
+int dword_50C98C; // weak
+unsigned int uIconID_TurnStart;
+int dword_50C994; // weak
+int dword_50C998_turnbased_icon_1A; // weak
+int uSpriteID_Spell11; // idb
+_UNKNOWN unk_50C9A0; // weak
+int dword_50C9A8; // weak
+int dword_50C9AC; // weak
+int dword_50C9D0; // weak
+int dword_50C9D4; // weak
+int dword_50C9D8; // weak
+int dword_50C9DC; // weak
+struct NPCData *ptr_50C9E0;
+int dword_50C9E8; // idb
+int dword_50C9EC[777]; // weak
+int dword_50C9F0[120]; // idb
+int dword_50CDC8; // weak
+int dword_50CDCC; // weak
+int bProcessorIsNotIntel; // weak
+Vec3_int_ layingitem_vel_50FDFC;
+char pStartingMapName[777]; // idb
+unsigned __int8 IsPlayerWearingWatersuit[5];
+char byte_5111C0[54];
+char byte_5111F6[18];
+unsigned int papredoll_dbrds[16];
+unsigned int papredoll_drhs[4];
+unsigned int papredoll_dlhus[4];
+unsigned int papredoll_dlhs[4];
+unsigned int papredoll_dbods[5];
+int paperdoll_array_511290[4][17][3];
+unsigned int papredoll_dlaus[5];
+unsigned int papredoll_dlads[4];
+int papredoll_flying_feet[777]; // idb
+int dword_511638[4][6];
+int dword_511788[777]; // weak
+int dword_51179C; // weak
+int dword_5117A0; // weak
+int dword_5117A4; // weak
+int dword_5117A8; // weak
+int dword_5117AC; // weak
+int paperdoll_array_511828[4][10];
+int bRingsShownInCharScreen; // weak
+int _unused000; // weak
+
+unsigned __int16 _56EFD8_minimap[117][137];
+unsigned int uNumBlueFacesInBLVMinimap;
+unsigned __int16 pBlueFacesInBLVMinimapIDs[50];
+int pTextureIDs_isns[14];
+unsigned int uIconIdx_Spell21;
+unsigned int uIconIdx_Spell27;
+int dword_576E28; // weak
+int dword_576E2C; // weak
+__int64 _5773B8_event_timer; // weak
+int dword_5773C0; // weak
+
+int dword_591080; // weak
+int dword_591084; // weak
+struct Actor *pDialogue_SpeakingActor;
+unsigned int uDialogueType;
+unsigned int uDialogue_SpeakingActorNPC_ID;
+struct LevelDecoration *_591094_decoration;
+char byte_591098[200]; // idb
+int uCurrentHouse_Animation; // weak
+char *dword_591164_teleport_map_name; // idb
+int dword_591168_teleport_speedz; // weak
+int dword_59116C_teleport_directionx; // weak
+int dword_591170_teleport_directiony; // weak
+int dword_591174_teleportz; // weak
+int dword_591178_teleporty; // weak
+int dword_59117C_teleportx; // weak
+char byte_591180[600]; // idb
+struct NPCData *array_5913D8[12];
+struct Texture *pDialogueNPCPortraits[6];
+int uNumDialogueNPCPortraits; // weak
+struct Texture *pTexture_591428;
+struct Texture *pTexture_outside; // idb
+struct Texture *pTexture_Dialogue_Background;
+_UNKNOWN unk_597F10; // weak
+int dword_597F18; // weak
+char byte_5B0938[2000];
+int dword_5B5920; // weak
+int dword_5B5924; // weak
+int _5B65A8_npcdata_uflags_or_other; // weak
+int _5B65AC_npcdata_fame_or_other; // weak
+int _5B65B0_npcdata_rep_or_other; // weak
+int _5B65B4_npcdata_loword_house_or_other; // weak
+int _5B65B8_npcdata_hiword_house_or_other; // weak
+int dword_5B65BC; // weak
+int dword_5B65C0; // weak
+int dword_5B65C4; // weak
+int dword_5B65C8; // weak
+int dword_5B65CC; // weak
+int dword_5B65D0_dialogue_actor_npc_id; // weak
+int dword_5C3418; // weak
+int dword_5C341C; // weak
+char byte_5C3427[777]; // weak
+char GameUI_StatusBar_TimedString[200];
+char pStatusBarString[200];
+unsigned int GameUI_StatusBar_TimedStringTimeLeft;
+int bForceDrawStatusBar; // weak
+int dword_5C35C0; // weak
+int bDialogueUI_InitializeActor_NPC_ID; // weak
+int dword_5C35C8; // weak
+char *p2DEventsTXT_Raw;
+int uHouse_ExitPic; // weak
+int dword_5C35D4; // weak
+char *aAMPMNames[2];
+char byte_5C45AF[777]; // weak
+char pTmpBuf3[2048];
+char pFinalMessage[4096]; // idb
+char pTmpBuf[2000];
+char pTmpBuf2[2000];
+char byte_5C6D50[777]; // weak
+int ui_current_text_color; // weak
+__int64 qword_5C6DF0; // weak
+int dword_5C6DF8; // weak
+char item__getname_buffer[104]; // idb
+char *pClassDescriptions[36];
+char *pAttributeDescriptions[7];
+char *pGrandSkillDesc[38];
+char *pMasterSkillDesc[38];
+char *pExpertSkillDesc[38];
+char *pNormalSkillDesc[38];
+char *pSkillDesc[38];
+char *pHealthPointsAttributeDescription;
+char *pSpellPointsAttributeDescription;
+char *pArmourClassAttributeDescription;
+char *pPlayerConditionAttributeDescription; // idb
+char *pFastSpellAttributeDescription;
+char *pPlayerAgeAttributeDescription;
+char *pPlayerLevelAttributeDescription;
+char *pPlayerExperienceAttributeDescription;
+char *pAttackBonusAttributeDescription;
+char *pAttackDamageAttributeDescription;
+char *pMissleBonusAttributeDescription;
+char *pMissleDamageAttributeDescription;
+char *pFireResistanceAttributeDescription;
+char *pAirResistanceAttributeDescription;
+char *pWaterResistanceAttributeDescription;
+char *pEarthResistanceAttributeDescription;
+char *pMindResistanceAttributeDescription;
+char *pBodyResistanceAttributeDescription;
+char *pSkillPointsAttributeDescription;
+char *pClassTXT_Raw;
+char *pStatsTXT_Raw;
+char *pSkillDescTXT_Raw;
+struct StorylineText *pStorylineText;
+struct FactionTable *pFactionTable;
+char byte_5C8D1A[777]; // weak
+char *pGlobalTXT_LocalizationStrings[677];
+char byte_5E4C15[777]; // weak
+char *pSomeItemsNames[14];
+char *pGlobalTXT_Raw;
+char *pMonstersTXT_Raw;
+char *pMonsterPlacementTXT_Raw;
+char *pSpellsTXT_Raw;
+char *pMapStatsTXT_Raw;
+char *pHostileTXT_Raw;
+char *pPotionsTXT_Raw;
+char *pPotionNotesTXT_Raw;
+char *pHistoryTXT_Raw;
+int _6807B8_level_decorations_ids[777]; // idb
+int _6807E0_num_decorations_with_sounds_6807B8; // weak
+int _6807E8_level_decorations_ids[777]; // idb
+int _6836C8_num_decorations_6807E8; // weak
+int dword_69B010[64];
+float flt_69B138_dist; // weak
+char byte_69BD41_unused; // weak
+unsigned int uTextureID_x_u;
+unsigned int uTextureID_LS_saveU;
+unsigned int uTextureID_LS_loadU;
+unsigned int uTextureID_AR_DN_DN;
+unsigned int uTextureID_AR_UP_DN;
+unsigned int uTextureID_LS_;
+unsigned int uTextureID_x_d;
+unsigned int uTextureID_save_up;
+unsigned int uTextureID_load_up;
+unsigned int uTextureID_loadsave;
+_UNKNOWN _69FBB4_ptr_iterator_end; // weak
+_UNKNOWN unk_6A0758; // weak
+int dword_6A0C9C; // weak
+unsigned int uLoadGameUI_SelectedSlot;
+HWND hInsertCDWindow; // idb
+int uCPUSpeed; // weak
+char cMM7GameCDDriveLetter; // idb
+void *ptr_6A0D08;
+int _6A0D0C_txt_lod_loading; // weak
+int _6A0D10_txt_lod_loading__unused; // weak
+MENU_STATE uCurrentMenuID;
+unsigned int uGameState;
+int uDefaultTravelTime_ByFoot; // weak
+int day_attrib; // weak
+int day_fogrange_1; // weak
+int day_fogrange_2; // weak
+struct TileTable *pTileTable; // idb
+int texmapping_terrain_subdivsize; // weak
+int texmapping_terrain_subdivpow2; // weak
+int texmapping_building_subdivsize; // weak
+int texmapping_building_subdivpow2; // weak
+int unnamed_6BE060[2] = {0, 1};
+int mipmapping_building_mm1; // weak
+int mipmapping_building_mm2; // weak
+int mipmapping_building_mm3; // weak
+int mipmapping_terrain_mm1; // weak
+int mipmapping_terrain_mm2; // weak
+int mipmapping_terrain_mm3; // weak
+int outdoor_grid_band_1; // idb
+int outdoor_grid_band_2; // idb
+int outdoor_grid_band_3; // idb
+char outdoor_day_top_r; // weak
+char outdoor_day_top_g; // weak
+char outdoor_day_top_b; // weak
+char outdoor_day_bottom_r; // weak
+char outdoor_day_bottom_g; // weak
+char outdoor_day_bottom_b; // weak
+char outdoor_night_top_r; // weak
+char outdoor_night_top_g; // weak
+char outdoor_night_top_b; // weak
+char outdoor_night_bottom_r; // weak
+char outdoor_night_bottom_g; // weak
+char outdoor_night_bottom_b; // weak
+char pDefaultSkyTexture[777]; // idb
+char byte_6BE124_cfg_textures_DefaultGroundTexture[16]; // idb
+int _6BE134_odm_main_tile_group; // weak
+int dword_6BE138; // weak
+int dword_6BE13C_uCurrentlyLoadedLocationID; // weak
+float fWalkSpeedMultiplier = 1.0f; // weak
+float fBackwardWalkSpeedMultiplier = 1.0f; // weak
+float fTurnSpeedMultiplier = 1.0f; // weak
+float flt_6BE150_look_up_down_dangle = 1.0f; // weak
+HWND hWnd; // idb
+int uWindowWidth; // idb
+int uWindowHeight; // idb
+int uWindowX; // idb
+int uWindowY; // idb
+LONG uWindowStyle; // idb
+HMENU hOSMenu; // idb
+int dword_6BE340; // weak
+char pCurrentMapName[20]; // idb
+unsigned int uLevelMapStatsID;
+int uLevel_StartingPointType; // weak
+int dword_6BE364_game_settings_1 = 0; // weak
+int dword_6BE368_debug_settings_2 = 0; // weak
+unsigned __int8 bUseLoResSprites = false;
+unsigned __int8 bUseRegistry = true;
+unsigned __int8 bCanLoadFromCD = false;
+int bShowDamage; // idb
+unsigned int bAlwaysRun;
+unsigned int bFlipOnExit;
+int dword_6BE384_2dacceloff; // weak
+char byte_6BE388_graphicsmode; // weak
+unsigned int uTurnSpeed;
+float flt_6BE3A0; // weak
+float flt_6BE3A4_debug_recmod1;
+float flt_6BE3A8_debug_recmod2;
+float flt_6BE3AC_debug_recmod1_x_1_6;
+char byte_6BE3B0[20]; // idb
+char bUnderwater = false; // weak
+char bNoNPCHiring = false; // weak
+int _702AC0_unused = 0; // weak
+int _702AC4_unused = 0; // weak
+char _702ACC_unused = 0; // weak
+int bDebugResouces; // weak
+unsigned int bNoVideo = false;
+bool bNoIntro = false;
+bool bNoLogo = false;
+bool bNoCD = false;
+bool bNoSound = false;
+int aborting_app; // weak
+int dword_720020_zvalues[100];
+int dword_7201B0_zvalues[299];
+int dword_72065C[777]; // weak
+int dword_720660[777]; // idb
+int dword_7207EC[777]; // weak
+int dword_7207F0[777]; // idb
+int uTextureID_720980; // weak
+int _720984_unused; // weak
+char _72098C_unused; // weak
+__int16 word_7209A0_intercepts_ys_plus_ys[104];
+__int16 word_720A70_intercepts_xs_plus_xs[104];
+__int16 word_720B40_intercepts_zs[104];
+__int16 word_720C10_intercepts_xs[102];
+int dword_720CDC;
+__int16 word_720CE0_ys[777]; // idb
+__int16 word_720DB0_xs[777]; // idb
+int dword_720E80[20];
+int dword_720ED0[20];
+int dword_720F20[20];
+__int16 word_720F70[777]; // idb
+__int16 word_721040[777]; // idb
+int dword_721110[777]; // idb
+int dword_721160[777]; // idb
+int dword_7211B0[777]; // idb
+int dword_721200[777]; // idb
+int dword_7212C8[777]; // idb
+__int16 word_721390[104]; // idb
+__int16 word_721460[104]; // idb
+int blv_prev_party_x; // weak
+int blv_prev_party_z; // weak
+int blv_prev_party_y; // weak
+char *dword_721660; // idb
+char *dword_721664; // idb
+NPCTopic pNPCTopics[789];
+char *dword_722F10; // idb
+const char *pQuestTable[512];
+_UNKNOWN unk_723714; // weak
+char *dword_723718_autonote_related; // idb
+int dword_72371C[777]; // weak
+const char *pScrolls[82];
+int dword_723E80_award_related[777]; // weak
+int dword_723E84[777]; // weak
+int dword_7241C8; // weak
+struct NPCStats *pNPCStats = nullptr;
+char *aNPCProfessionNames[59];
+char *pAwardsTXT_Raw;
+char *pScrollsTXT_Raw;
+char *pMerchantsTXT_Raw;
+const char *pMerchantsBuyPhrases[7];
+const char *pMerchantsSellPhrases[7];
+const char *pMerchantsRepairPhrases[7];
+const char *pMerchantsIdentifyPhrases[7];
+char *pTransitionsTXT_Raw;
+char *pAutonoteTXT_Raw;
+char *pQuestsTXT_Raw;
+unsigned int uNumTerrainNormals;
+int pTerrainSomeOtherData[32768];
+unsigned __int16 pTerrainNormalIndices[32768];
+struct Vec3_float_ *pTerrainNormals;
+int dword_76D518_terrain_cell_world_pos_around_party_y; // weak
+int dword_76D51C_terrain_cell_world_pos_around_party_y; // weak
+int dword_76D520_terrain_cell_world_pos_around_party_y; // weak
+int dword_76D524_terrain_cell_world_pos_around_party_y; // weak
+int dword_76D528_terrain_cell_world_pos_around_party_z; // weak
+int dword_76D52C_terrain_cell_world_pos_around_party_z; // weak
+int dword_76D530_terrain_cell_world_pos_around_party_z; // weak
+int dword_76D534_terrain_cell_world_pos_around_party_z; // weak
+int dword_76D538_terrain_cell_world_pos_around_party_x; // weak
+int dword_76D53C_terrain_cell_world_pos_around_party_x; // weak
+int dword_76D540_terrain_cell_world_pos_around_party_x; // weak
+int dword_76D544_terrain_cell_world_pos_around_party_x; // weak
+int dword_76D548_terrain_cell_world_pos_around_party_y; // weak
+int dword_76D54C_terrain_cell_world_pos_around_party_y; // weak
+int dword_76D550_terrain_cell_world_pos_around_party_y; // weak
+int dword_76D554_terrain_cell_world_pos_around_party_y; // weak
+int dword_76D558_terrain_cell_world_pos_around_party_z; // weak
+int dword_76D55C_terrain_cell_world_pos_around_party_z; // weak
+int dword_76D560_terrain_cell_world_pos_around_party_z; // weak
+int dword_76D564_terrain_cell_world_pos_around_party_z; // weak
+int dword_76D568_terrain_cell_world_pos_around_party_x; // weak
+int dword_76D56C_terrain_cell_world_pos_around_party_x; // weak
+int dword_76D570_terrain_cell_world_pos_around_party_x; // weak
+int dword_76D574_terrain_cell_world_pos_around_party_x; // weak
+int terrain_76D5C8[128];
+int terrain_76D7C8[128];
+int terrain_76D9C8[128];
+int terrain_76DBC8[128];
+int terrain_76DDC8[128];
+int terrain_76DFC8[128];
+int terrain_76E1C8[128];
+int terrain_76E3C8[128];
+_UNKNOWN unk_801A00; // weak
+_UNKNOWN unk_801A0C; // weak
+char byte_80AA10; // weak
+int dword_80AA14; // weak
+int dword_80AA18; // weak
+int dword_80AA1C; // weak
+int dword_80AA20; // weak
+unsigned int uNumElementsIn80AA28;
+struct stru148 *ptr_80AA28[2000];
+struct Edge *pNewEdges;
+struct Surf *pSurfs;
+struct Edge *pEdges;
+struct Span *pSpans;
+struct Edge *ptr_80C978_Edges;
+struct Surf *ptr_80C97C_Surfs;
+struct Edge *ptr_80CA10[480];
+_UNKNOWN unk_80D190; // weak
+int dword_A74C88; // weak
+unsigned int uPlayerCreationUI_SkySliderPos;
+int uPlayerCreationUI_ArrowAnim;
+unsigned int uPlayerCreationUI_SelectedCharacter;
+int dword_A74CDC; // weak
+struct Texture *pTexture_PlayerFaceMask;
+struct Texture *pTexture_PlayerFaceEradicated;
+struct Texture *pTexture_PlayerFaceDead;
+struct Texture *pTextures_PlayerFaces[4][56];
+int dword_A75070; // weak
+struct Player *pPlayers[5];
+__int64 qword_A750D8; // weak
+__int16 word_A750E0; // weak
+__int16 word_A750E2; // weak
+char *pClassNames[36];
+char *aCharacterConditionNames[19];
+char *pSkillNames[38];
+char byte_AE3368[777]; // weak
+char byte_AE3369; // weak
+char byte_AE336A; // weak
+char byte_AE336B; // weak
+int dword_AE336C; // weak
+int dword_AE3370; // weak
+char byte_AE5B91; // weak
+int dword_F1B430[32]; // weak
+int dword_F8B144; // idb
+char byte_F8B148[16];
+__int16 word_F8B158[777]; // weak
+struct Texture *dword_F8B164; // idb
+struct Texture *dword_F8B168[12];
+int dword_F8B198; // weak
+int dword_F8B19C; // weak
+__int16 word_F8B1A0; // weak
+const char *dword_F8B1A4; // idb
+int dword_F8B1A8; // weak
+int dword_F8B1AC_something_todo_with_awards; // idb
+int dword_F8B1B0; // weak
+int dword_F8B1B4; // weak
+char *pShopOptions[4];
+_UNKNOWN unk_F8B1C8; // weak
+int dword_F8B1D8; // weak
+int dword_F8B1DC; // weak
+int dword_F8B1E0; // weak
+int dword_F8B1E4; // weak
+const char *ptr_F8B1E8; // idb
+char byte_F8B1EC; // weak
+char byte_F8B1EF[777]; // weak
+char byte_F8B1F0[4];
+int dword_F8B1F4; // weak
+_UNKNOWN unk_F8B1F8; // weak
+_UNKNOWN unk_F8B5E0; // weak
+_UNKNOWN unk_F8B668; // weak
+_UNKNOWN unk_F8BA50; // weak
+char byte_F8BC0C; // weak
+int bGameoverLoop = 0; // weak
+__int16 word_F8BC48_displaced_face_intersect_plane_coords_a; // idb
+__int16 word_F8BD18_displaced_face_intersect_plane_coords_b; // idb
+int dword_F93F20; // weak
+int dword_F93F70; // weak
+
+//int crt_F94004; // weak
+//int crtdword_F9400C; // weak
+FARPROC lpfn; // idb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mm7_data.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,2386 @@
+#pragma once
+#include <string>
+#include "OSAPI.h"
+
+#include "VectorTypes.h"
+
+typedef char _UNKNOWN;
+
+
+typedef unsigned int uint;
+/*
+#define LOWORD(a) (*((unsigned short *)&a))
+#define SLOWORD(a) (__debugbreak(), *((signed short *)&a))
+#define HIWORD(a) (*((unsigned short *)&a + 1))
+#define SHIWORD(a) (*((short *)&a + 1))
+
+#define LODWORD(a) (*((unsigned int *)&a))
+#define HIDWORD(a) (*((unsigned int *)&a + 1))
+#define SLODWORD(a) (*((int *)&a))
+#define SHIDWORD(a) (*((int *)&a + 1))
+
+#define LOBYTE(a) (*((unsigned char *)&a))
+#define SLOBYTE(a) (*((signed char *)&a))
+
+#define HIBYTE(a) (*((unsigned char *)&a + sizeof(a) - 1))
+
+#define BYTE1(a) (*((unsigned char *)&a + 1))
+#define SBYTE1(a) (*((signed char *)&a + 1))
+
+#define BYTE2(a) (*((unsigned char *)&a + 2))
+#define BYTE3(a) (*((unsigned char *)&a + 3))
+
+#define WORD2(a) (__debugbreak(), *(unsigned short *)((char *)&a + 4))
+
+#define __OFSUB__(a, b) (unsigned __int8)((a) == (b))
+
+
+typedef unsigned __int16 _WORD;
+typedef unsigned __int64 _QWORD;
+*/
+
+
+
+
+
+#define COERCE_UNSIGNED_INT64(a) (__debugbreak(), a)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if defined(__GNUC__)
+  typedef          long long ll;
+  typedef unsigned long long ull;
+  #define __int64 long long
+  #define __int32 int
+  #define __int16 short
+  #define __int8  char
+  #define MAKELL(num) num ## LL
+  #define FMT_64 "ll"
+#elif defined(_MSC_VER)
+  typedef          __int64 ll;
+  typedef unsigned __int64 ull;
+  #define MAKELL(num) num ## i64
+  #define FMT_64 "I64"
+#elif defined (__BORLANDC__)
+  typedef          __int64 ll;
+  typedef unsigned __int64 ull;
+  #define MAKELL(num) num ## i64
+  #define FMT_64 "L"
+#else
+  #error "unknown compiler"
+#endif
+typedef unsigned int uint;
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+
+typedef          char   int8;
+typedef   signed char   sint8;
+typedef unsigned char   uint8;
+typedef          short  int16;
+typedef   signed short  sint16;
+typedef unsigned short  uint16;
+typedef          int    int32;
+typedef   signed int    sint32;
+typedef unsigned int    uint32;
+typedef ll              int64;
+typedef ll              sint64;
+typedef ull             uint64;
+
+// Partially defined types:
+#define _BYTE  uint8
+#define _WORD  uint16
+#define _DWORD uint32
+#define _QWORD uint64
+#if !defined(_MSC_VER)
+#define _LONGLONG __int128
+#endif
+
+#ifndef _WINDOWS_
+typedef int8 BYTE;
+typedef int16 WORD;
+typedef int32 DWORD;
+typedef int32 LONG;
+#endif
+typedef int64 QWORD;
+#ifndef __cplusplus
+typedef int bool;       // we want to use bool in our C programs
+#endif
+
+// Some convenience macros to make partial accesses nicer
+// first unsigned macros:
+#define LOBYTE(x)   (*((_BYTE*)&(x)))   // low byte
+#define LOWORD(x)   (*((_WORD*)&(x)))   // low word
+#define LODWORD(x)  (*((_DWORD*)&(x)))  // low dword
+#define HIBYTE(x)   (*((_BYTE*)&(x)+1))
+#define HIWORD(x)   (*((_WORD*)&(x)+1))
+#define HIDWORD(x)  (*((_DWORD*)&(x)+1))
+#define BYTEn(x, n)   (*((_BYTE*)&(x)+n))
+#define WORDn(x, n)   (*((_WORD*)&(x)+n))
+#define BYTE1(x)   BYTEn(x,  1)         // byte 1 (counting from 0)
+#define BYTE2(x)   BYTEn(x,  2)
+#define BYTE3(x)   BYTEn(x,  3)
+#define BYTE4(x)   BYTEn(x,  4)
+#define BYTE5(x)   BYTEn(x,  5)
+#define BYTE6(x)   BYTEn(x,  6)
+#define BYTE7(x)   BYTEn(x,  7)
+#define BYTE8(x)   BYTEn(x,  8)
+#define BYTE9(x)   BYTEn(x,  9)
+#define BYTE10(x)  BYTEn(x, 10)
+#define BYTE11(x)  BYTEn(x, 11)
+#define BYTE12(x)  BYTEn(x, 12)
+#define BYTE13(x)  BYTEn(x, 13)
+#define BYTE14(x)  BYTEn(x, 14)
+#define BYTE15(x)  BYTEn(x, 15)
+#define WORD1(x)   WORDn(x,  1)
+#define WORD2(x)   WORDn(x,  2)         // third word of the object, unsigned
+#define WORD3(x)   WORDn(x,  3)
+#define WORD4(x)   WORDn(x,  4)
+#define WORD5(x)   WORDn(x,  5)
+#define WORD6(x)   WORDn(x,  6)
+#define WORD7(x)   WORDn(x,  7)
+
+// now signed macros (the same but with sign extension)
+#define SLOBYTE(x)   (*((int8*)&(x)))
+#define SLOWORD(x)   (*((int16*)&(x)))
+#define SLODWORD(x)  (*((int32*)&(x)))
+#define SHIBYTE(x)   (*((int8*)&(x)+1))
+#define SHIWORD(x)   (*((int16*)&(x)+1))
+#define SHIDWORD(x)  (*((int32*)&(x)+1))
+#define SBYTEn(x, n)   (*((int8*)&(x)+n))
+#define SWORDn(x, n)   (*((int16*)&(x)+n))
+#define SBYTE1(x)   SBYTEn(x,  1)
+#define SBYTE2(x)   SBYTEn(x,  2)
+#define SBYTE3(x)   SBYTEn(x,  3)
+#define SBYTE4(x)   SBYTEn(x,  4)
+#define SBYTE5(x)   SBYTEn(x,  5)
+#define SBYTE6(x)   SBYTEn(x,  6)
+#define SBYTE7(x)   SBYTEn(x,  7)
+#define SBYTE8(x)   SBYTEn(x,  8)
+#define SBYTE9(x)   SBYTEn(x,  9)
+#define SBYTE10(x)  SBYTEn(x, 10)
+#define SBYTE11(x)  SBYTEn(x, 11)
+#define SBYTE12(x)  SBYTEn(x, 12)
+#define SBYTE13(x)  SBYTEn(x, 13)
+#define SBYTE14(x)  SBYTEn(x, 14)
+#define SBYTE15(x)  SBYTEn(x, 15)
+#define SWORD1(x)   SWORDn(x,  1)
+#define SWORD2(x)   SWORDn(x,  2)
+#define SWORD3(x)   SWORDn(x,  3)
+#define SWORD4(x)   SWORDn(x,  4)
+#define SWORD5(x)   SWORDn(x,  5)
+#define SWORD6(x)   SWORDn(x,  6)
+#define SWORD7(x)   SWORDn(x,  7)
+
+
+
+
+// Generate a reference to pair of operands
+template<class T>  int16 __PAIR__( int8  high, T low) { return ((( int16)high) << sizeof(high)*8) | uint8(low); }
+template<class T>  int32 __PAIR__( int16 high, T low) { return ((( int32)high) << sizeof(high)*8) | uint16(low); }
+template<class T>  int64 __PAIR__( int32 high, T low) { return ((( int64)high) << sizeof(high)*8) | uint32(low); }
+template<class T> uint16 __PAIR__(uint8  high, T low) { return (((uint16)high) << sizeof(high)*8) | uint8(low); }
+template<class T> uint32 __PAIR__(uint16 high, T low) { return (((uint32)high) << sizeof(high)*8) | uint16(low); }
+template<class T> uint64 __PAIR__(uint32 high, T low) { return (((uint64)high) << sizeof(high)*8) | uint32(low); }
+
+// rotate left
+template<class T> T __ROL__(T value, uint count)
+{
+  const uint nbits = sizeof(T) * 8;
+  count %= nbits;
+
+  T high = value >> (nbits - count);
+  value <<= count;
+  value |= high;
+  return value;
+}
+
+// rotate right
+template<class T> T __ROR__(T value, uint count)
+{
+  const uint nbits = sizeof(T) * 8;
+  count %= nbits;
+
+  T low = value << (nbits - count);
+  value >>= count;
+  value |= low;
+  return value;
+}
+
+// carry flag of left shift
+template<class T> int8 __MKCSHL__(T value, uint count)
+{
+  const uint nbits = sizeof(T) * 8;
+  count %= nbits;
+
+  return (value >> (nbits-count)) & 1;
+}
+
+// carry flag of right shift
+template<class T> int8 __MKCSHR__(T value, uint count)
+{
+  return (value >> (count-1)) & 1;
+}
+
+// sign flag
+template<class T> int8 __SETS__(T x)
+{
+  if ( sizeof(T) == 1 )
+    return int8(x) < 0;
+  if ( sizeof(T) == 2 )
+    return int16(x) < 0;
+  if ( sizeof(T) == 4 )
+    return int32(x) < 0;
+  return int64(x) < 0;
+}
+
+// overflow flag of subtraction (x-y)
+template<class T, class U> int8 __OFSUB__(T x, U y)
+{
+  if ( sizeof(T) < sizeof(U) )
+  {
+    U x2 = x;
+    int8 sx = __SETS__(x2);
+    return (sx ^ __SETS__(y)) & (sx ^ __SETS__(x2-y));
+  }
+  else
+  {
+    T y2 = y;
+    int8 sx = __SETS__(x);
+    return (sx ^ __SETS__(y2)) & (sx ^ __SETS__(x-y2));
+  }
+}
+
+// overflow flag of addition (x+y)
+template<class T, class U> int8 __OFADD__(T x, U y)
+{
+  if ( sizeof(T) < sizeof(U) )
+  {
+    U x2 = x;
+    int8 sx = __SETS__(x2);
+    return ((1 ^ sx) ^ __SETS__(y)) & (sx ^ __SETS__(x2+y));
+  }
+  else
+  {
+    T y2 = y;
+    int8 sx = __SETS__(x);
+    return ((1 ^ sx) ^ __SETS__(y2)) & (sx ^ __SETS__(x+y2));
+  }
+}
+
+// carry flag of subtraction (x-y)
+template<class T, class U> int8 __CFSUB__(T x, U y)
+{
+  int size = sizeof(T) > sizeof(U) ? sizeof(T) : sizeof(U);
+  if ( size == 1 )
+    return uint8(x) < uint8(y);
+  if ( size == 2 )
+    return uint16(x) < uint16(y);
+  if ( size == 4 )
+    return uint32(x) < uint32(y);
+  return uint64(x) < uint64(y);
+}
+
+// carry flag of addition (x+y)
+template<class T, class U> int8 __CFADD__(T x, U y)
+{
+  int size = sizeof(T) > sizeof(U) ? sizeof(T) : sizeof(U);
+  if ( size == 1 )
+    return uint8(x) > uint8(x+y);
+  if ( size == 2 )
+    return uint16(x) > uint16(x+y);
+  if ( size == 4 )
+    return uint32(x) > uint32(x+y);
+  return uint64(x) > uint64(x+y);
+}
+
+
+
+//-------------------------------------------------------------------------
+// Data declarations
+extern int (__cdecl *sprintfex)(char *a1, const char *a2, ...);
+
+extern int pWindowList_at_506F50_minus1_indexing[1];
+extern int dword_4C9890[10]; // weak
+extern int dword_4C9920[16]; // weak
+extern _UNKNOWN unk_4D8548; // weak
+extern char byte_4D864C; // weak
+extern float flt_4D86CC; // weak
+extern int dword_4D86D8; // weak
+extern int dword_4DAFCC; // weak
+extern int (__stdcall *off_4DAFDC)(char); // weak
+extern char asc_4DB724[]; // idb
+extern int dword_4DBD94; // weak
+extern int dword_4DF380[]; // weak
+extern int dword_4DF390; // weak
+extern char Str2[]; // idb
+extern int dword_4DF3A4; // weak
+extern char byte_4E185C; // weak
+extern char am_byte_4E185D; // weak
+extern char byte_4E185E; // weak
+extern int amuint_4E1860; // weak
+extern int amuint_4E1864; // weak
+extern int amuint_4E1868; // weak
+extern int amuint_4E186C; // weak
+extern int amuint_4E1870; // weak
+extern int dword_4E1874; // weak
+extern int dword_4E1878; // weak
+extern float flt_4D84E8;
+extern int dword_4E187C; // weak
+extern int dword_4E1880; // weak
+extern int dword_4E1884; // weak
+extern int dword_4E1888; // weak
+extern char pArcomagePlayer2Name[8];
+extern char pArcomagePlayer1Name[8];
+extern char pDeckMaster[12];
+extern char aIxf[4]; // idb
+extern _UNKNOWN unk_4E19FC; // weak
+extern char pAreYouSureWishToLeave[32];
+extern char asc_4E1A28[4]; // idb
+extern char aUsxfs[13];
+extern char aLayout_pcx[11]; // weak
+extern char aSprites_pcx[12]; // weak
+extern char aProblemInBlit_[]; // idb
+extern char aEWorkMsdevMm7M[]; // idb
+extern char aProblemInBli_0[]; // idb
+extern char aD[]; // idb
+extern char asc_4E1AB0[]; // idb
+extern char aWb_0[]; // idb
+extern char a24bitPcxOnly[]; // idb
+extern char Mode[]; // idb
+extern char a16bitPcx[]; // idb
+extern char aUnableToLoadS[]; // idb
+extern char aBitmaps[]; // idb
+extern char aIcons[]; // idb
+extern char aPending[]; // idb
+extern char aCanTFindS[]; // idb
+extern char pDayMoonPhase[28];
+extern char *spellbook_texture_filename_suffices[8]; // weak
+extern __int16 word_4E1D3A[]; // weak
+extern __int16 pTownPortalBook_xs[6];
+extern __int16 pTownPortalBook_ys[6];
+extern __int16 pTownPortalBook_ws[6];
+extern __int16 pTownPortalBook_hs[6];
+extern int dword_4E20D0[]; // idb
+extern char byte_4E2430[]; // weak
+extern char byte_4E2431[]; // weak
+extern unsigned int pLloydsBeaconsPreviewXs[5];
+extern unsigned int pLloydsBeaconsPreviewYs[5];
+extern unsigned int pLloydsBeacons_SomeXs[5];
+extern unsigned int pLloydsBeacons_SomeYs[5]; // idb
+extern char aSbwb00[7]; // weak
+extern char aW[2]; // idb
+extern char aA[2]; // idb
+extern char aSD[]; // idb
+extern char aSS03d03dS000S0[]; // idb
+extern char aLuS[]; // idb
+extern char aS_1[]; // idb
+extern char aSbSc02d[]; // idb
+extern char aSbSs02d[]; // idb
+extern char aTabDb[]; // idb
+extern char aTabDa[]; // idb
+extern char aIbM6D[]; // idb
+extern char aIbM6U[]; // idb
+extern char aIbM5D[]; // idb
+extern char aIbM5U[]; // idb
+extern char aPagemask[]; // idb
+extern char aBook[]; // idb
+extern char aSpell_fnt[]; // idb
+extern char aAutonote_fnt[]; // idb
+extern char aBook2_fnt[]; // idb
+extern char pFontFile[]; // idb
+extern char aFontpal[]; // idb
+extern char aMapbordr[]; // idb
+extern char aLloydDD_pcx[]; // idb
+extern char aDataLloydDD_pc[]; // idb
+extern char aLb_bordr[]; // idb
+extern char aTphell[]; // idb
+extern char aTpheaven[]; // idb
+extern char aTpisland[]; // idb
+extern char aTpwarlock[]; // idb
+extern char aTpelf[]; // idb
+extern char aTpharmndy[]; // idb
+extern char aTownport[]; // idb
+extern char aSbquiknot[]; // idb
+extern char aTabAn8a[]; // idb
+extern char aTabAn8b[]; // idb
+extern char aTabAn4a[]; // idb
+extern char aTabAn4b[]; // idb
+extern char aTabAn5a[]; // idb
+extern char aTabAn5b[]; // idb
+extern char aTabAn3a[]; // idb
+extern char aTabAn3b[]; // idb
+extern char aTabAn2a[]; // idb
+extern char aTabAn2b[]; // idb
+extern char aTabAn1a[]; // idb
+extern char aTabAn1b[]; // idb
+extern char aDivbar[]; // idb
+extern char aSbautnot[]; // idb
+extern char aTabwoff[]; // idb
+extern char aTabwon[]; // idb
+extern char aTabeoff[]; // idb
+extern char aTabeon[]; // idb
+extern char aTabsoff[]; // idb
+extern char aTabson[]; // idb
+extern char aTabnoff[]; // idb
+extern char aTabnon[]; // idb
+extern char aZootOff[]; // idb
+extern char aZoomOff[]; // idb
+extern char aZootOn[]; // idb
+extern char aZoomOn[]; // idb
+extern char aSbmap[]; // idb
+extern char aMoon_ful[]; // idb
+extern char aMoon_2[]; // idb
+extern char aMoon_4[]; // idb
+extern char aMoon_new[]; // idb
+extern char aSbdateTime[]; // idb
+extern char aTabAn7a[]; // idb
+extern char aTabAn6a[]; // idb
+extern char aTabAn7b[]; // idb
+extern char aTabAn6b[]; // idb
+extern char aSbplayrnot[]; // idb
+extern char aPending_0[]; // idb
+extern char aUnknown[8]; // weak
+extern char aS100110S[]; // idb
+extern char aS100110D[]; // idb
+extern char aS100110DS[]; // idb
+extern char aS100110D02dSS[]; // idb
+extern int pCurrentScreen; // weak
+extern char byte_4E28FC; // weak
+extern unsigned int uGammaPos;
+extern int dword_4E2910[]; // weak
+extern __int16 RightClickPortraitXmin[4];
+extern __int16 RightClickPortraitXmax[4];
+extern void *off_4E2A12; // weak
+extern int dword_4E2A18[5];
+extern int dword_4E2A2C[9];
+extern int dword_4E2A50[12];
+extern int _4E2A80_skills[9];
+extern unsigned __int8 pAwardsTextColors[20];
+extern unsigned int pHealthBarPos[4];
+extern unsigned int pManaBarPos[4];
+extern char _4E2AD8_ui_colors[72];
+extern char _4E2B21_buff_spell_tooltip_colors[80];
+extern char byte_4E2B70[]; // weak
+extern char byte_4E2BC8; // weak
+extern int pChestSmthn1ByType[8];
+extern int pChestSmthn2ByType[8];
+extern int pChestWidthsByType[8];
+extern int pChestHeightsByType[8];
+extern char aSS[]; // idb
+extern char ascii_4E2C54[6];
+extern char ascii_4E2C5C[7];
+extern char ascii_4E2C68[8];
+extern char ascii_4E2C70[9];
+extern char ascii_4E2C7C[8];
+extern char ascii_4E2C84[11];
+extern char ascii_4E2C90[12];
+extern char ascii_4E2C9C[8];
+extern char ascii_4E2CA4[7];
+extern char ascii_4E2CB0[12];
+extern char ascii_4E2CBC[12];
+extern char ascii_4E2CC8[12];
+extern char ascii_4E2CD4[6];
+extern char ascii_4E2CDC[11];
+extern char ascii_4E2CE8[8];
+extern char ascii_4E2CF0[12];
+extern char ascii_4E2CFC[6];
+extern char ascii_4E2D04[8];
+extern char ascii_4E2D0C[8];
+extern char ascii_4E2D14[6];
+extern char ascii_4E2D1C[12];
+extern char ascii_4E2D28[8];
+extern char ascii_4E2D30[7];
+extern char ascii_4E2D38[5];
+extern char ascii_4E2D40[8];
+extern char ascii_4E2D48[6];
+extern char ascii_4E2D50[12];
+extern char ascii_4E2D5C[7];
+extern char aMakingItemNumb[]; // idb
+extern char aNpc03d[]; // idb
+extern char format_4E2D80[16];
+extern char format_4E2D90[8];
+extern char aS03d03dS000_0[]; // idb
+extern char aS03d03dS000[]; // idb
+extern char format_4E2DC8[8];
+extern char aS[]; // idb
+extern char aLuSLuS[]; // idb
+extern char byte_4E2DE8; // idb
+extern char asc_4E2DFC[3]; // idb
+extern char format_4E2E00[2]; // idb
+extern char format_4E2E10[28]; // weak
+extern char aS100S_0[]; // idb
+extern char aS100S[]; // idb
+extern char aS100D[]; // idb
+extern char aS180[6]; // idb
+extern char format_4E2E68[28]; // weak
+extern char aS_6[2]; // idb
+extern char aSS_0[]; // idb
+extern char aS_5[4]; // idb
+extern _UNKNOWN unk_4E2EB8; // weak
+extern char string_4E3294[8];
+extern char Format[]; // idb
+extern char aMem03i_txt[]; // idb
+extern char aMemory[]; // idb
+extern char aIdSSizeI[16]; // idb
+extern __int16 word_4E3C66[]; // idb
+extern int dword_4E455C; // weak
+extern int dword_4E4560[6];
+extern int dword_4E4578[6];
+extern int dword_4E4590[6];
+extern int dword_4E45A8[6];
+extern char aDDSDDS[]; // idb
+extern char asc_4E45DC[]; // idb
+extern char aD02dSSDSD[]; // idb
+extern char aButtexi1[]; // idb
+extern char aCanTJumpToThat[]; // idb
+extern char aNoMapFoundForS[]; // idb
+extern char global_a2[]; // idb
+extern char aSSS[]; // idb
+extern char aNotInMapStats[17]; // weak
+extern char aD47_blv[]; // idb
+extern char aOut15_odm[]; // idb
+extern char Delim[]; // idb
+extern char aGamma_pcx[];
+extern char aQuit1[]; // idb
+extern char aControls1[]; // idb
+extern char aSave1[]; // idb
+extern char aLoad1[]; // idb
+extern char aNew1[]; // idb
+extern char aOptions[]; // idb
+extern char aGammapos[9]; // weak
+extern char aBloodsplats[]; // idb
+extern char aTinting[]; // idb
+extern char aColoredLights[]; // idb
+extern char aTurndelta[]; // idb
+extern char aFliponexit[]; // idb
+extern char pKey[]; // idb
+extern char aGraphicsmode[]; // idb
+extern char aShowdamage[]; // idb
+extern char aWalksound[]; // idb
+extern char aCharvoices[]; // idb
+extern char aMusicflag[]; // idb
+extern char aSoundflag[]; // idb
+extern char aOpvdgTn[]; // idb
+extern char aOpvdgCl[]; // idb
+extern char aOpvdgBs[]; // idb
+extern char aOpvdhTn[]; // idb
+extern char aOpvdhCl[]; // idb
+extern char aOpvdhBs[]; // idb
+extern char aOptvid[]; // idb
+extern char aOptkb_2[]; // idb
+extern char aOptkb_1[]; // idb
+extern char aResume1[]; // idb
+extern char aOptkb_h[]; // idb
+extern char aOptkb[]; // idb
+extern char aOption01[]; // idb
+extern char aOption02[]; // idb
+extern char aOption03[]; // idb
+extern char aOption04[]; // idb
+extern char aConvol90[]; // idb
+extern char aConvol80[]; // idb
+extern char aConvol70[]; // idb
+extern char aConvol60[]; // idb
+extern char aConvol50[]; // idb
+extern char aConvol40[]; // idb
+extern char aConvol30[]; // idb
+extern char aConvol20[]; // idb
+extern char aConvol10[]; // idb
+extern char aConvol00[]; // idb
+extern char aCon_smoo[]; // idb
+extern char aCon_arrr[]; // idb
+extern char aCon_arrl[]; // idb
+extern char aCon_32x[]; // idb
+extern char aCon_16x[]; // idb
+extern char aControlbg[]; // idb
+extern char aTitle_pcx[10]; // weak
+extern char aEWorkMsdevMm_0[]; // idb
+extern char aDraw_debug_lin[]; // idb
+extern char aGenuineintel[13]; // weak
+extern char asc_4E4938[13]; // weak
+extern int dword_4E4948[]; // weak
+extern int dword_4E494C[]; // weak
+extern int dword_4E49D0[]; // weak
+extern _UNKNOWN dword_4E49D4; // idb
+extern int dword_4E4A18[]; // weak
+extern int dword_4E4A1C[]; // weak
+extern int dword_4E4A40[]; // weak
+extern int dword_4E4A44[]; // weak
+extern char aCentaurhauls[13]; // weak
+extern char aCyrixinstead[13]; // weak
+extern char aAuthenticamd[13]; // weak
+extern float flt_4E4A80[10];
+extern char aInvalidPlayerI[]; // idb
+extern char aEWorkMsdevMm_1[]; // idb
+extern char aEWorkMsdevMm_2[]; // idb
+extern char aErrorNoKeyboar[25]; // weak
+extern char aInvalidDeviceP[]; // idb
+extern char aInvalidDevic_0[]; // idb
+extern char aEWorkMsdevMm_3[]; // idb
+extern char aErrorNoMouseFo[22]; // weak
+extern int papredoll_4E4C28; // weak
+extern int paperdoll_4E4C2C; // weak
+extern int paperdoll_array_4E4E30[4][17][2];
+extern int dword_4E5050[8];
+extern int dword_4E5270[8];
+extern int dword_4E5490[4][7][2];
+extern int paredoll_array_4E54B8[3][14];
+extern int paperdoll_array_4E5570[4][10][2];
+extern int dword_4E56B0; // weak
+extern int dword_4E56B4; // weak
+extern int dword_4E57F0[4][7][2];
+extern int dword_4E58D0[]; // weak
+extern int dword_4E58D4[]; // weak
+extern int dword_4E5AD0[]; // weak
+extern int dword_4E5AD4[]; // weak
+extern int dword_4E5AE0[8];
+extern int pPaperdollLeftHand[8];
+extern int pPaperdollRightHand[8];
+extern int pPaperdollLeftEmptyHand[8];
+extern int dword_4E5C1C[6];
+extern int dword_4E5C34[6];
+extern char aItem092v3[]; // idb
+extern char aIbCd5D[]; // idb
+extern char aAr_dn_dn[]; // idb
+extern char aAr_dn_up[]; // idb
+extern char aAr_up_dn[]; // idb
+extern char aAr_up_up[]; // idb
+extern char aItem281pc02d[]; // idb
+extern char aPc02dbrd[]; // idb
+extern char aPc23vDlhu[]; // idb
+extern char aPc23vDlh[]; // idb
+extern char aPc23vDrh[]; // idb
+extern char aPc23vDlau[]; // idb
+extern char aPc23vDlad[]; // idb
+extern char aPc23vDbod[]; // idb
+extern char aBackhand[]; // idb
+extern char aBackdoll[]; // idb
+extern char aMagnifB[]; // idb
+extern char aItem3_3dvDa2[]; // idb
+extern char aItem3_3dvDa1[15]; // weak
+extern char aItem3_3dvD[13]; // weak
+extern char aItem64v1[9]; // weak
+extern char aEffpar01[]; // idb
+extern int pPartySpellbuffsUI_XYs[14][2];
+extern char byte_4E5DD8[]; // weak
+extern unsigned __int8 pPartySpellbuffsUI_smthns[14];
+extern char aSpell27[]; // idb
+extern char aSpell21[]; // idb
+extern char aIsn02d[]; // idb
+extern char aBardataB[]; // idb
+extern char aBardata[8]; // weak
+extern char aBardataC[10]; // weak
+extern char aLoadprog[]; // idb
+extern char aLoadingD_pcx[]; // idb
+extern int _4E5E50_transui_x; // idb
+extern int dword_4E5EC8[]; // weak
+extern int _4E5EE0_transui_y; // idb
+extern const char *pHouse_ExitPictures[11];
+extern char *_4E6BDC_loc_names[11];
+extern char aOutside[]; // idb
+extern char aMer[]; // idb
+extern char aMir[]; // idb
+extern char aSel[]; // idb
+extern char aEle[]; // idb
+extern char aDar[]; // idb
+extern char aLig[]; // idb
+extern char aBod[]; // idb
+extern char aMin[]; // idb
+extern char aSpi[]; // idb
+extern char aEar[]; // idb
+extern char aWat[]; // idb
+extern char aAir[]; // idb
+extern char aFir[]; // idb
+extern char aBan[]; // idb
+extern char aTav[]; // idb
+extern char aTow[]; // idb
+extern char aTra[]; // idb
+extern char aTem[]; // idb
+extern char aBoa[]; // idb
+extern char aSta[]; // idb
+extern char aAlc[]; // idb
+extern char aMag[]; // idb
+extern char aArm[]; // idb
+extern char aWea[]; // idb
+extern char asc_4E7BD4[2]; // idb
+extern char a2devents_txt[]; // idb
+extern char aFileSSizeLuBuf[]; // idb
+extern char aGlobal_evt[]; // idb
+extern char aMax_event_text[]; // idb
+extern char aS_str[]; // idb
+extern char aS_evt[]; // idb
+extern char aNoMazeInfoForT[36]; // weak
+extern char aC[]; // idb
+extern char aB[3]; // weak
+extern char aEvt02d[]; // idb
+extern char aNoTransitionTe[]; // idb
+extern char aEWorkMsdevMm_4[]; // idb
+extern char asc_4E7CD4[]; // idb
+extern char aSS_1[]; // idb
+extern char aNpcIdExceedsMa[]; // idb
+extern char aNpc03u[]; // idb
+extern char aPcout01[]; // idb
+extern char aArbiterEvil[]; // idb
+extern char aArbiterGood[]; // idb
+extern char a0[]; // idb
+extern char aPartyStart[]; // idb
+extern char aNorthStart[12]; // weak
+extern char aSouthStart[12]; // weak
+extern char aEastStart[11]; // weak
+extern char aWestStart[11]; // weak
+extern char aUnableToFindDo[]; // idb
+extern char aNwc_blv[]; // idb
+extern char aUnableToOpenS[]; // idb
+extern char aInvalidStringP[]; // idb
+extern char aEWorkMsdevMm_5[]; // idb
+extern char aNull[]; // idb
+extern char aInvalidStrin_0[]; // idb
+extern char aSI[]; // idb
+extern char aS7[4]; // weak
+extern char aS6[]; // idb
+extern char aS5[4]; // weak
+extern char aS1[]; // idb
+extern char aS3[4]; // weak
+extern char aS0[]; // idb
+extern char aS2[4]; // weak
+extern char aS4[4]; // weak
+extern char aUnableToSaveDs[]; // idb
+extern char aDataDsft_bin[]; // idb
+extern char aPFrames[]; // idb
+extern char aEFrames[]; // idb
+extern char aSFrames[]; // idb
+extern char aMirror7[]; // idb
+extern char aMirror6[]; // idb
+extern char aMirror5[]; // idb
+extern char aMirror4[]; // idb
+extern char aMirror3[]; // idb
+extern char aMirror2[]; // idb
+extern char aMirror1[]; // idb
+extern char aMirror0[]; // idb
+extern char aLuminous[]; // idb
+extern char a1[]; // idb
+extern char aNew[]; // idb
+extern char pMessag[]; // idb
+extern char aCspriteframeta[]; // idb
+extern char aR[]; // idb
+extern char aNew_0[]; // idb
+extern char aUnableToSaveDt[]; // idb
+extern char aDataDtft_bin[]; // idb
+extern char aTxtFrames[]; // idb
+extern char aCtexturefram_1[]; // idb
+extern char aCtexturefram_0[]; // idb
+extern char aCtextureframet[]; // idb
+extern int bWinNT4_0; // weak
+extern char aEWorkMsdevMm_6[]; // idb
+extern char aTheVisObjectPo[]; // idb
+extern char aSpriteOutlineC[]; // idb
+extern char aUndefinedCobje[]; // idb
+extern char aEWorkMsdevMm_7[]; // idb
+extern char aGammaControlNo[]; // idb
+extern __int16 word_4E8152[11];
+extern char byte_4E8168[116];
+extern char aD3dTextureName[]; // idb
+extern char aLogd3d_txt[]; // idb
+extern char byte_4E8394[]; // weak
+#include "Texture.h"
+extern stru355 stru_4E82A4;// = {0x20, 0x41, 0, 0x20, 0xFF0000, 0xFF00, 0xFF, 0xFF000000};
+extern stru355 stru_4EFCBC;// = {0x20, 0x41, 0, 0x10, 0x7C00, 0x3E0, 0x1F, 0x8000};
+extern char byte_4E94D0; // weak
+extern char _4E94D2_light_type; // weak
+extern char byte_4E94D3; // weak
+extern unsigned int saveload_dlg_xs[2];
+extern unsigned int saveload_dlg_ys[2];
+extern unsigned int saveload_dlg_zs[2];
+extern unsigned int saveload_dlg_ws[2];
+extern int dword_4E98BC_bApplicationActive; // weak
+extern char *off_4EB080; // idb
+extern char *pTransitionStrings[464];
+extern char aAwards_txt[]; // idb
+extern char aScroll_txt[]; // idb
+extern char aMerchant_txt[]; // idb
+extern char aTrans_txt[]; // idb
+extern char aTeacher[]; // idb
+extern char aObelisk[]; // idb
+extern char aSeer[]; // idb
+extern char aStat[]; // idb
+extern char aPotion[]; // idb
+extern char aAutonote_txt[]; // idb
+extern char aQuests_txt[]; // idb
+extern char aNpcdist_txt[]; // idb
+extern char aNpctopic_txt[]; // idb
+extern char aNpctext_txt[]; // idb
+extern char aNpcnews_txt[]; // idb
+extern char aNpcgroup_txt[]; // idb
+extern char aNpcgreet_txt[]; // idb
+extern char aNpcdata_txt[]; // idb
+extern char aNpcprof_txt[]; // idb
+extern char aNpcnames_txt[]; // idb
+extern char aD3dVersionOfRe[]; // idb
+extern char aEWorkMsdevM_16[]; // idb
+extern char aLevels_0[]; // idb
+extern char aDmap[]; // idb
+extern char aAmap[]; // idb
+extern char aTmap[]; // idb
+extern char aHmap[]; // idb
+extern int dword_4EC268[]; // weak
+extern int dword_4EC28C[]; // weak
+extern int dword_4EC2A8; // weak
+extern int dword_4EC2AC; // weak
+extern char aInvalidGroundT[]; // idb
+extern char aInvalidSkyTexH[]; // idb
+extern char aIdlist[]; // idb
+extern char aOmap[]; // idb
+extern char aCmap[]; // idb
+extern char aMm6OutdoorV1_0[]; // idb
+extern char aI6_odm[]; // idb
+extern char aBlank[]; // idb
+extern char aHm005[]; // idb
+extern char aSky043[]; // idb
+extern char aDefault_odm[]; // idb
+extern char aPlansky3[]; // idb
+extern char aPlanskyD[]; // idb
+extern char a_ddm[5]; // weak
+extern char aCanTLoadFile[]; // idb
+extern char aEWorkMsdevM_17[]; // idb
+extern char a_odm[]; // idb
+extern char aUnableToFindSI[]; // idb
+extern char aSpawn[]; // idb
+extern char aBddata[]; // idb
+extern char aTernorm[]; // idb
+extern char aGrastyl[]; // idb
+extern char aOut09_odm[]; // idb
+extern char aNewedges[]; // idb
+extern char aSurfs[]; // idb
+extern char aEdges[]; // idb
+extern char aSpans[]; // idb
+extern char aTheTextureFram[]; // idb
+extern char aEWorkMsdevM_18[]; // idb
+extern char aWtrtyla[]; // idb
+extern char aWtrtyl[]; // idb
+extern char aUnableToSave_1[]; // idb
+extern char aDataDtile_bin[]; // idb
+extern char aTileDescrip[]; // idb
+extern char aTtattr_transit[]; // idb
+extern char aTtattr_nodraw[]; // idb
+extern char aTtattr_wave[]; // idb
+extern char aTtattr_flat[]; // idb
+extern char aTtattr_repulse[]; // idb
+extern char aTtattr_block[]; // idb
+extern char aTtattr_water2[]; // idb
+extern char aTtattr_water[]; // idb
+extern char aTtattr_burn[]; // idb
+extern char aTtsect_dnw[]; // idb
+extern char aTtsect_dse[]; // idb
+extern char aTtsect_dne[]; // idb
+extern char aTtsect_dsw[]; // idb
+extern char aTtsect_de[]; // idb
+extern char aTtsect_dw[]; // idb
+extern char aTtsect_ds[]; // idb
+extern char aTtsect_dn[]; // idb
+extern char aTtsect_wcap[]; // idb
+extern char aTtsect_scap[]; // idb
+extern char aTtsect_ecap[]; // idb
+extern char aTtsect_ncap[]; // idb
+extern char aTtsect_ew_s[]; // idb
+extern char aTtsect_ew_n[]; // idb
+extern char aTtsect_ns_w[]; // idb
+extern char aTtsect_ns_e[]; // idb
+extern char aTtsect_s_w[]; // idb
+extern char aTtsect_s_e[]; // idb
+extern char aTtsect_n_w[]; // idb
+extern char aTtsect_n_e[]; // idb
+extern char aTtsect_ew[]; // idb
+extern char aTtsect_ns[]; // idb
+extern char aTtsect_cros[]; // idb
+extern char aTtsect_xsw1[]; // idb
+extern char aTtsect_xse1[]; // idb
+extern char aTtsect_xnw1[]; // idb
+extern char aTtsect_xne1[]; // idb
+extern char aTtsect_s1[]; // idb
+extern char aTtsect_n1[]; // idb
+extern char aTtsect_w1[]; // idb
+extern char aTtsect_e1[]; // idb
+extern char aTtsect_sw1[]; // idb
+extern char aTtsect_se1[]; // idb
+extern char aTtsect_nw1[]; // idb
+extern char aTtsect_ne1[]; // idb
+extern char aTtsect_speci_6[]; // idb
+extern char aTtsect_speci_5[]; // idb
+extern char aTtsect_speci_4[]; // idb
+extern char aTtsect_speci_3[]; // idb
+extern char aTtsect_speci_2[]; // idb
+extern char aTtsect_speci_1[]; // idb
+extern char aTtsect_speci_0[]; // idb
+extern char aTtsect_special[]; // idb
+extern char aTtsect_base4[]; // idb
+extern char aTtsect_base3[]; // idb
+extern char aTtsect_base2[]; // idb
+extern char aTtsect_base1[]; // idb
+extern char aTtsect_start[]; // idb
+extern char aTtsect_null[]; // idb
+extern char aTttype_roadcit[]; // idb
+extern char aTttype_roads_2[]; // idb
+extern char aTttype_roadsno[]; // idb
+extern char aTttype_roadt_0[]; // idb
+extern char aTttype_roadtro[]; // idb
+extern char aTttype_roads_1[]; // idb
+extern char aTttype_roadswa[]; // idb
+extern char aTttype_roadv_0[]; // idb
+extern char aTttype_roadvol[]; // idb
+extern char aTttype_roads_0[]; // idb
+extern char aTttype_roadsan[]; // idb
+extern char aTttype_roadc_0[]; // idb
+extern char aTttype_roadcra[]; // idb
+extern char aTttype_roadg_0[]; // idb
+extern char aTttype_roadgra[]; // idb
+extern char aTttype_city[]; // idb
+extern char aTttype_swamp[]; // idb
+extern char aTttype_tropica[]; // idb
+extern char aTttype_water[]; // idb
+extern char aTttype_dirt[]; // idb
+extern char aTttype_volcano[]; // idb
+extern char aTttype_sand[]; // idb
+extern char aTttype_snow[]; // idb
+extern char aTttype_cracked[]; // idb
+extern char aTttype_grass[]; // idb
+extern char aTttype_start[]; // idb
+extern char aTttype_null[]; // idb
+extern char aTiletableLoadO[]; // idb
+extern char aTiletableLoadU[]; // idb
+extern char byte_4ECA93[]; // weak
+extern char byte_4ECACF[]; // weak
+extern char byte_4ECB0C[64]; // idb
+extern char aError_0[]; // idb
+extern char aCouldnTLoadMap[]; // idb
+extern char aOut02d_odm[]; // idb
+extern char aOut14_odm[]; // idb
+extern char aOut[]; // idb
+extern char aLunSun[]; // idb
+extern char aLunfull[]; // idb
+extern char aLun34[]; // idb
+extern char aLun12[]; // idb
+extern char aLun14[]; // idb
+extern char aPal03i[]; // idb
+extern const char *pPlayerPortraitsNames[25];
+extern const char *dlad_texnames_by_face[25];
+extern const char *dlau_texnames_by_face[25];
+extern const char *dbod_texnames_by_face[25];
+extern const char *drh_texnames_by_face[25];
+extern const char *dlh_texnames_by_face[25];
+extern const char *dlhu_texnames_by_face[25];
+extern short SoundSetAction[192]; // weak
+extern unsigned char byte_4ED498; // weak
+extern __int16 pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[4];
+extern char byte_4ED970_skill_learn_ability_by_class_table[32][37];
+extern int dword_4EDEA0[]; // weak
+extern int dword_4EDEB4[]; // weak
+extern int dword_4EDEC4[]; // weak
+extern __int16 word_4EDED8[]; // weak
+extern _UNKNOWN unk_4EDF40; // weak
+extern unsigned int pHiredNPCsIconsOffsetsX[2];
+extern unsigned int pHiredNPCsIconsOffsetsY[2];
+extern int dword_4EE07C[2]; // weak
+extern _UNKNOWN unk_4EE084; // weak
+extern __int16 word_4EE088_sound_ids[]; // weak
+extern short word_4EE150[];
+extern int dword_4EED78; // weak
+extern _UNKNOWN unk_4EED80; // weak
+extern int dword_4EFA80; // weak
+extern int dword_4EFA84; // weak
+extern void *off_4EFDB0; // weak
+extern int dword_4F031C[]; // weak
+extern const char *off_4F03B8[]; // idb
+extern __int16 word_4F03FE[]; // weak
+extern __int16 word_4F0400[]; // weak
+extern __int16 word_4F0498[]; // weak
+extern __int16 word_4F0576[]; // weak
+extern __int16 word_4F0578[]; // weak
+extern __int16 word_4F05AE[]; // weak
+extern char _4F063C_smthn_by_2da_uType[]; // weak
+extern __int16 word_4F063E[290];
+extern __int16 word_4F06D8[22];
+extern __int16 word_4F0704[40];
+extern __int16 word_4F0754[49];
+extern __int16 word_4F07B6[88];
+extern __int16 word_4F0866[14];
+extern __int16 _4F0882_evt_VAR_PlayerItemInHands_vals[53];
+extern int dword_4F08EC[]; // weak
+extern char byte_4F09B0[]; // weak
+extern char byte_4F09B1[]; // weak
+extern char byte_4F09B8[]; // weak
+extern int dword_4F09CC[192];
+extern char byte_4F0CCF[]; // weak
+extern char _4F0D38_TravelInfo[]; // weak
+extern int dword_4F0E10[32];
+extern Vec2_int_ pMonsterArenaPlacements[20];
+extern __int16 word_4F0F30[]; // weak
+extern char aS03d[]; // idb
+extern char byte_4F0F98; // idb
+extern char sz[]; // idb
+extern char aSSSSSS[]; // idb
+extern char aSDS[]; // idb
+extern char aSS_3[]; // idb
+extern char aSSSS[]; // idb
+extern char aS_2[]; // idb
+extern char aErrorlog_txt[]; // idb
+extern char aUnsupportedPix[]; // idb
+extern char aSmackerError[]; // idb
+extern char aCS[]; // idb
+extern char aAnimsMagic7_vi[]; // idb
+extern char aVideoFileError[]; // idb
+extern char aCanTOpenFileAn[]; // idb
+extern char aAnimsMight7_vi[]; // idb
+extern char aCanTLoadS[]; // idb
+extern char aS_smk[]; // idb
+extern char aUnsupportedBin[27]; // weak
+extern char aEWorkMsdevM_29[]; // idb
+extern char aFailedToOpenBl[]; // idb
+extern char aCanTAllocateMe[33]; // weak
+extern char aCanTLoadFileAn[]; // idb
+extern char aS_bik[]; // idb
+extern char aMm7_win_pcx[]; // idb
+extern char aLuSLuSLuS[]; // idb
+extern char aEndgame_fnt[]; // idb
+extern char aWinbg_pcx[10]; // weak
+extern char aDefaultCaseRea[]; // idb
+extern char aUnsupportedExc[71]; // weak
+extern char aEWorkMsdevM_30[]; // idb
+extern char aUndefinedTypeR[]; // idb
+extern char aUnknownPointer[]; // idb
+extern char a1_1_3[6]; // weak
+extern double dbl_4F2870; // weak
+extern int dword_4F288C; // weak
+extern double dbl_4F5372; // weak
+extern int dword_4F5428[]; // weak
+extern int dword_4F542C[]; // weak
+extern _UNKNOWN crtunk_4F54B8; // weak
+extern int dword_4F5B24_ys[]; // idb
+extern int dword_4F5BF4_xs[]; // idb
+extern int dword_4F5CC4_ys[]; // idb
+extern int dword_4F5D98_xs[]; // idb
+extern int ai_array_4F5E68[500];
+extern int ai_array_4F6638_actor_ids[500];
+extern int dword_4F6E08[500];
+extern int ai_arrays_size; // weak
+extern int ai_array_4F75E0[500];
+extern unsigned int ai_array_4F7DB0_actor_ids[500];
+extern int dword_4F8580[]; // weak
+extern int dword_4FA9B0[]; // weak
+extern int dword_4FA9B4[]; // weak
+extern char byte_4FAA00; // weak
+extern __int16 am_sounds[12];
+extern _UNKNOWN unk_4FAA20; // weak
+extern char byte_4FAA24; // weak
+extern HWND dword_4FAA28; // idb
+extern char byte_4FAA2C; // weak
+extern char byte_4FAA2D; // weak
+extern char byte_4FAA2E; // weak
+extern int amuint_4FAA34; // weak
+extern int amuint_4FAA38; // weak
+extern int amuint_4FAA3C_blt_xy[2];
+extern int am_uint_4FAA44_blt_xy[2];
+extern int amuint_4FAA4C; // weak
+extern unsigned int uCardID; // idb
+extern int amuint_4FAA54_blt_xy[2];
+extern int amuint_4FAA5C_blt_xy[2];
+extern int dword_4FAA64; // weak
+extern int dword_4FAA68; // weak
+extern int amuint_4FAA6C; // idb
+extern int dword_4FAA70; // weak
+extern char byte_4FAA74; // weak
+extern char am_byte_4FAA75; // weak
+extern char am_byte_4FAA76; // weak
+extern char am_byte_4FAA77; // weak
+extern int amuint_4FAA78[777]; // weak
+extern char am_byte_4FAA7C[777]; // weak
+extern int amuint_4FAA80[777]; // weak
+extern int amuint_4FAA84[777]; // weak
+extern int amuint_4FAA88[777]; // weak
+extern int amuint_4FAA8C[777]; // weak
+extern int amuint_4FAA90[777][2];
+extern int dword_4FABB8; // weak
+extern signed int dword_4FABBC; // idb
+extern unsigned int amuint_4FABC0; // idb
+extern int amuint_4FABC4; // weak
+extern int dword_4FABC8; // weak
+extern char byte_4FABD0[]; // weak
+extern char byte_4FABD1[]; // weak
+extern _UNKNOWN unk_4FABD4; // weak
+extern int dword_4FABD8[]; // weak
+extern int dword_4FABDC[]; // weak
+extern int dword_4FABE0[]; // weak
+extern int dword_4FABE4[]; // weak
+extern int dword_4FABE8[]; // weak
+extern int dword_4FABEC[]; // weak
+extern int dword_4FABF0[]; // weak
+extern int dword_4FABF4[]; // weak
+extern int dword_4FABF8[]; // weak
+extern int dword_4FABFC[]; // weak
+extern int dword_4FAC00[]; // weak
+extern int dword_4FAC04[]; // weak
+extern int dword_4FAC08[]; // weak
+extern int dword_4FAC0C[]; // weak
+extern _UNKNOWN unk_5052C8; // weak
+extern int dword_505314[]; // weak
+extern char byte_5054C8[32]; // idb
+extern char byte_5054E8[108];
+extern int dword_505554[]; // weak
+extern _UNKNOWN unk_505704; // weak
+extern char byte_505880; // weak
+extern char byte_505881; // weak
+extern int amuint_505884; // weak
+extern int amuint_505888; // weak
+extern int amuint_50588C; // weak
+extern int dword_505890; // weak
+extern unsigned int pSRZBufferLineOffsets[480];
+extern int areWeLoadingTexture; // weak
+extern char byte_506130[]; // weak
+extern int dword_506338; // weak
+extern int dword_50633C; // idb
+extern signed int sRecoveryTime; // idb
+extern unsigned int uRequiredMana; // idb
+extern int _506348_current_lloyd_playerid; // weak
+extern __int64 qword_506350; // weak
+extern char byte_506360; // weak
+extern int dword_506364; // weak
+extern int dword_506408[]; // weak
+extern int dword_50640C[]; // weak
+extern unsigned int uTextureID_506438;
+extern int dword_50651C; // weak
+extern int dword_506520; // weak
+extern int dword_506524; // weak
+extern int dword_506528; // weak
+extern int dword_50652C; // weak
+extern int dword_506530; // weak
+extern int dword_506534; // weak
+extern int dword_506538; // weak
+extern int dword_50653C; // weak
+extern int dword_506540; // weak
+extern int dword_506544; // weak
+extern int dword_506548; // weak
+extern int dword_50654C; // weak
+extern char byte_506550; // weak
+extern char *aMoonPhaseNames[5];
+extern int dword_506568; // weak
+extern char bRecallingBeacon; // weak
+extern int uLastPointedObjectID; // weak
+//extern unsigned __int8 bMonsterInfoUI_bDollInitialized;
+extern char *aSpellNames[44];
+extern int dword_506978; // weak
+extern char byte_50697C; // weak
+extern int dword_506980; // weak
+extern int dword_506984; // weak
+extern int dword_506988; // weak
+extern int dword_50698C; // weak
+extern int dword_506E68; // weak
+extern __int16 word_506E6C[18]; // weak
+extern unsigned int pPrevVirtualCidesMapping[27];
+extern int dword_506F08; // weak
+extern int dword_506F0C[]; // idb
+extern int uRestUI_FoodRequiredToRest;
+extern int dword_506F14; // weak
+extern int _506F18_num_hours_to_sleep; // weak
+extern int dword_506F1C; // weak
+extern int pVisibleWindowsIdxs[20]; // weak
+extern int uNumVisibleWindows;
+extern char bFlashHistoryBook; // weak
+extern char bFlashAutonotesBook; // weak
+extern char bFlashQuestBook; // weak
+extern int dword_507960; // weak
+extern int dword_507964; // weak
+extern int dword_507968; // weak
+extern int dword_50796C; // weak
+extern int dword_507974; // weak
+extern int dword_5079B4; // weak
+extern int dword_5079C8; // weak
+extern int dword_5079CC; // weak
+extern int dword_5079D0; // weak
+extern int dword_5079D8; // weak
+extern struct GUIButton *dword_507A14; // idb
+extern struct GUIButton *dword_507A18; // idb
+extern unsigned int uGameUIFontShadow;
+extern unsigned int uGameUIFontMain;
+extern int dword_507B00_spell_info_to_draw_in_popup; // weak
+extern char *aMonthNames[12];
+extern char *aDayNames[7];
+extern char *aSpellSchoolNames[9];
+extern char *aAttributeNames[7];
+extern int dword_507B94; // weak
+extern int dword_507B98_ctrl_pressed; // weak
+extern unsigned int uActiveCharacter;
+extern int dword_507BF0_is_there_popup_onscreen; // weak
+extern int dword_507C08; // weak
+extern int dword_507C0C; // weak
+extern int dword_507CBC; // weak
+extern int dword_507CC0; // weak
+extern __int64 qword_507CC8; // weak
+extern int _507CD4_RestUI_hourglass_anim_controller; // weak
+extern int dword_507CD8; // weak
+extern int dword_50B570[]; // weak
+extern int dword_50B638[]; // weak
+extern int dword_50B700; // weak
+extern int dword_50B738[]; // idb
+extern int _50B744_view_transformed_ys[43];
+extern int dword_50B828[];
+extern int _50B834_view_transformed_zs[43];
+extern int dword_50B918[];
+extern int _50B924_view_transformed_xs[43];
+extern int unk_50B9D4[]; // idb
+extern int dword_50B9D8_ys[];
+extern int dword_50B9E0_ys[]; // idb
+extern int dword_50B9EC[]; // idb
+extern int dword_50B9F0[2]; // idb
+extern int dword_50BAE8_xs[];
+extern int dword_50BAF4_xs[];
+extern int dword_50B9F8[]; // idb
+extern int dword_50BA08[]; // idb
+extern int dword_50BAC4[]; // weak
+extern int dword_50BAC8[]; // idb
+extern int dword_50BAD0[]; // weak
+extern int dword_50BAD4[]; // weak
+extern int dword_50BADC_xs[]; // weak
+extern int dword_50BAE0[]; // weak
+extern int dword_50BAE8[]; // weak
+extern int dword_50BAEC_xs[]; // weak
+extern int dword_50BAF4[]; // weak
+extern int dword_50BAF8_xs[]; // weak
+extern int dword_50BC10[]; // weak
+extern int dword_50BDA0[]; // weak
+extern int dword_50BF30[]; // weak
+extern char byte_50C0C0; // weak
+extern int some_active_character; // weak
+extern _UNKNOWN unk_50C190; // weak
+extern int dword_50C968; // weak
+extern unsigned int pIconIDs_Turn[5];
+extern unsigned int uIconID_TurnStop;
+extern unsigned int uIconID_TurnHour;
+extern int uIconID_CharacterFrame; // idb
+extern int dword_50C98C; // weak
+extern unsigned int uIconID_TurnStart;
+extern int dword_50C994; // weak
+extern int dword_50C998_turnbased_icon_1A; // weak
+extern int uSpriteID_Spell11; // idb
+extern _UNKNOWN unk_50C9A0; // weak
+extern int dword_50C9A8; // weak
+extern int dword_50C9AC; // weak
+extern int dword_50C9D0; // weak
+extern int dword_50C9D4; // weak
+extern int dword_50C9D8; // weak
+extern int dword_50C9DC; // weak
+extern struct NPCData *ptr_50C9E0;
+extern int dword_50C9E8; // idb
+extern int dword_50C9EC[]; // weak
+extern int dword_50C9F0[120]; // idb
+extern int dword_50CDC8; // weak
+extern int dword_50CDCC; // weak
+extern int bProcessorIsNotIntel; // weak
+extern Vec3_int_ layingitem_vel_50FDFC;
+extern char pStartingMapName[]; // idb
+extern unsigned __int8 IsPlayerWearingWatersuit[5];
+extern char byte_5111C0[54];
+extern char byte_5111F6[18];
+extern unsigned int papredoll_dbrds[16];
+extern unsigned int papredoll_drhs[4];
+extern unsigned int papredoll_dlhus[4];
+extern unsigned int papredoll_dlhs[4];
+extern unsigned int papredoll_dbods[5];
+extern int paperdoll_array_511290[4][17][3];
+extern unsigned int papredoll_dlaus[5];
+extern unsigned int papredoll_dlads[4];
+extern int papredoll_flying_feet[]; // idb
+extern int dword_511638[4][6];
+extern int dword_511788[]; // weak
+extern int dword_51179C; // weak
+extern int dword_5117A0; // weak
+extern int dword_5117A4; // weak
+extern int dword_5117A8; // weak
+extern int dword_5117AC; // weak
+extern int paperdoll_array_511828[4][10];
+extern int bRingsShownInCharScreen; // weak
+extern int _unused000; // weak
+
+extern unsigned __int16 _56EFD8_minimap[117][137];
+extern unsigned int uNumBlueFacesInBLVMinimap;
+extern unsigned __int16 pBlueFacesInBLVMinimapIDs[50];
+extern int pTextureIDs_isns[14];
+extern unsigned int uIconIdx_Spell21;
+extern unsigned int uIconIdx_Spell27;
+extern int dword_576E28; // weak
+extern int dword_576E2C; // weak
+extern __int64 _5773B8_event_timer; // weak
+extern int dword_5773C0; // weak
+
+extern int dword_591080; // weak
+extern int dword_591084; // weak
+extern struct Actor *pDialogue_SpeakingActor;
+extern unsigned int uDialogueType;
+extern unsigned int uDialogue_SpeakingActorNPC_ID;
+extern struct LevelDecoration *_591094_decoration;
+extern char byte_591098[200]; // idb
+extern int uCurrentHouse_Animation; // weak
+extern char *dword_591164_teleport_map_name; // idb
+extern int dword_591168_teleport_speedz; // weak
+extern int dword_59116C_teleport_directionx; // weak
+extern int dword_591170_teleport_directiony; // weak
+extern int dword_591174_teleportz; // weak
+extern int dword_591178_teleporty; // weak
+extern int dword_59117C_teleportx; // weak
+extern char byte_591180[600]; // idb
+extern struct NPCData *array_5913D8[12];
+extern struct Texture *pDialogueNPCPortraits[6];
+extern int uNumDialogueNPCPortraits; // weak
+extern struct Texture *pTexture_591428;
+extern struct Texture *pTexture_outside; // idb
+extern struct Texture *pTexture_Dialogue_Background;
+extern _UNKNOWN unk_597F10; // weak
+extern int dword_597F18; // weak
+extern char byte_5B0938[2000];
+extern int dword_5B5920; // weak
+extern int dword_5B5924; // weak
+extern int _5B65A8_npcdata_uflags_or_other; // weak
+extern int _5B65AC_npcdata_fame_or_other; // weak
+extern int _5B65B0_npcdata_rep_or_other; // weak
+extern int _5B65B4_npcdata_loword_house_or_other; // weak
+extern int _5B65B8_npcdata_hiword_house_or_other; // weak
+extern int dword_5B65BC; // weak
+extern int dword_5B65C0; // weak
+extern int dword_5B65C4; // weak
+extern int dword_5B65C8; // weak
+extern int dword_5B65CC; // weak
+extern int dword_5B65D0_dialogue_actor_npc_id; // weak
+extern int dword_5C3418; // weak
+extern int dword_5C341C; // weak
+extern char byte_5C3427[]; // weak
+extern char GameUI_StatusBar_TimedString[200];
+extern char pStatusBarString[200];
+extern unsigned int GameUI_StatusBar_TimedStringTimeLeft;
+extern int bForceDrawStatusBar; // weak
+extern int dword_5C35C0; // weak
+extern int bDialogueUI_InitializeActor_NPC_ID; // weak
+extern int dword_5C35C8; // weak
+extern char *p2DEventsTXT_Raw;
+extern int uHouse_ExitPic; // weak
+extern int dword_5C35D4; // weak
+extern char *aAMPMNames[2];
+extern char byte_5C45AF[]; // weak
+extern char pTmpBuf3[2048];
+extern char pFinalMessage[4096]; // idb
+extern char pTmpBuf[2000];
+extern char pTmpBuf2[2000];
+extern char byte_5C6D50[]; // weak
+extern int ui_current_text_color; // weak
+extern __int64 qword_5C6DF0; // weak
+extern int dword_5C6DF8; // weak
+extern char item__getname_buffer[104]; // idb
+extern char *pClassDescriptions[36];
+extern char *pAttributeDescriptions[7];
+extern char *pGrandSkillDesc[38];
+extern char *pMasterSkillDesc[38];
+extern char *pExpertSkillDesc[38];
+extern char *pNormalSkillDesc[38];
+extern char *pSkillDesc[38];
+extern char *pHealthPointsAttributeDescription;
+extern char *pSpellPointsAttributeDescription;
+extern char *pArmourClassAttributeDescription;
+extern char *pPlayerConditionAttributeDescription; // idb
+extern char *pFastSpellAttributeDescription;
+extern char *pPlayerAgeAttributeDescription;
+extern char *pPlayerLevelAttributeDescription;
+extern char *pPlayerExperienceAttributeDescription;
+extern char *pAttackBonusAttributeDescription;
+extern char *pAttackDamageAttributeDescription;
+extern char *pMissleBonusAttributeDescription;
+extern char *pMissleDamageAttributeDescription;
+extern char *pFireResistanceAttributeDescription;
+extern char *pAirResistanceAttributeDescription;
+extern char *pWaterResistanceAttributeDescription;
+extern char *pEarthResistanceAttributeDescription;
+extern char *pMindResistanceAttributeDescription;
+extern char *pBodyResistanceAttributeDescription;
+extern char *pSkillPointsAttributeDescription;
+extern char *pClassTXT_Raw;
+extern char *pStatsTXT_Raw;
+extern char *pSkillDescTXT_Raw;
+extern struct StorylineText *pStorylineText;
+extern struct FactionTable *pFactionTable;
+extern char byte_5C8D1A[]; // weak
+extern char *pGlobalTXT_LocalizationStrings[677];
+extern char byte_5E4C15[]; // weak
+extern char *pSomeItemsNames[14];
+extern char *pGlobalTXT_Raw;
+extern char *pMonstersTXT_Raw;
+extern char *pMonsterPlacementTXT_Raw;
+extern char *pSpellsTXT_Raw;
+extern char *pMapStatsTXT_Raw;
+extern char *pHostileTXT_Raw;
+extern char *pPotionsTXT_Raw;
+extern char *pPotionNotesTXT_Raw;
+extern char *pHistoryTXT_Raw;
+extern int _6807B8_level_decorations_ids[]; // idb
+extern int _6807E0_num_decorations_with_sounds_6807B8; // weak
+extern int _6807E8_level_decorations_ids[]; // idb
+extern int _6836C8_num_decorations_6807E8; // weak
+extern int dword_69B010[64];
+extern float flt_69B138_dist; // weak
+extern char byte_69BD41_unused; // weak
+extern unsigned int uTextureID_x_u;
+extern unsigned int uTextureID_LS_saveU;
+extern unsigned int uTextureID_LS_loadU;
+extern unsigned int uTextureID_AR_DN_DN;
+extern unsigned int uTextureID_AR_UP_DN;
+extern unsigned int uTextureID_LS_;
+extern unsigned int uTextureID_x_d;
+extern unsigned int uTextureID_save_up;
+extern unsigned int uTextureID_load_up;
+extern unsigned int uTextureID_loadsave;
+extern _UNKNOWN _69FBB4_ptr_iterator_end; // weak
+extern _UNKNOWN unk_6A0758; // weak
+extern int dword_6A0C9C; // weak
+extern unsigned int uLoadGameUI_SelectedSlot;
+extern HWND hInsertCDWindow; // idb
+extern int uCPUSpeed; // weak
+extern char cMM7GameCDDriveLetter; // idb
+extern void *ptr_6A0D08;
+extern int _6A0D0C_txt_lod_loading; // weak
+extern int _6A0D10_txt_lod_loading__unused; // weak
+extern enum MENU_STATE uCurrentMenuID;
+extern unsigned int uGameState;
+extern int uDefaultTravelTime_ByFoot; // weak
+extern int day_attrib; // weak
+extern int day_fogrange_1; // weak
+extern int day_fogrange_2; // weak
+extern struct TileTable *pTileTable; // idb
+extern int texmapping_terrain_subdivsize; // weak
+extern int texmapping_terrain_subdivpow2; // weak
+extern int texmapping_building_subdivsize; // weak
+extern int texmapping_building_subdivpow2; // weak
+extern int unnamed_6BE060[2];
+extern int mipmapping_building_mm1; // weak
+extern int mipmapping_building_mm2; // weak
+extern int mipmapping_building_mm3; // weak
+extern int mipmapping_terrain_mm1; // weak
+extern int mipmapping_terrain_mm2; // weak
+extern int mipmapping_terrain_mm3; // weak
+extern int outdoor_grid_band_1; // idb
+extern int outdoor_grid_band_2; // idb
+extern int outdoor_grid_band_3; // idb
+extern char outdoor_day_top_r; // weak
+extern char outdoor_day_top_g; // weak
+extern char outdoor_day_top_b; // weak
+extern char outdoor_day_bottom_r; // weak
+extern char outdoor_day_bottom_g; // weak
+extern char outdoor_day_bottom_b; // weak
+extern char outdoor_night_top_r; // weak
+extern char outdoor_night_top_g; // weak
+extern char outdoor_night_top_b; // weak
+extern char outdoor_night_bottom_r; // weak
+extern char outdoor_night_bottom_g; // weak
+extern char outdoor_night_bottom_b; // weak
+extern char pDefaultSkyTexture[]; // idb
+extern char byte_6BE124_cfg_textures_DefaultGroundTexture[16]; // idb
+extern int _6BE134_odm_main_tile_group; // weak
+extern int dword_6BE138; // weak
+extern int dword_6BE13C_uCurrentlyLoadedLocationID; // weak
+extern float fWalkSpeedMultiplier; // weak
+extern float fBackwardWalkSpeedMultiplier; // weak
+extern float fTurnSpeedMultiplier; // weak
+extern float flt_6BE150_look_up_down_dangle; // weak
+//extern char pMM7WindowClassName[]; // idb
+//extern HINSTANCE hInstance; // idb
+//extern char *pCmdLine;
+extern HWND hWnd; // idb
+extern int uWindowWidth; // idb
+extern int uWindowHeight; // idb
+extern int uWindowX; // idb
+extern int uWindowY; // idb
+extern LONG uWindowStyle; // idb
+extern HMENU hOSMenu; // idb
+extern int dword_6BE340; // weak
+extern char pCurrentMapName[20]; // idb
+extern unsigned int uLevelMapStatsID;
+extern int uLevel_StartingPointType; // weak
+extern int dword_6BE364_game_settings_1; // weak
+extern int dword_6BE368_debug_settings_2; // weak
+extern unsigned __int8 bUseLoResSprites;
+extern unsigned __int8 bUseRegistry;
+extern unsigned __int8 bCanLoadFromCD;
+extern int bShowDamage; // idb
+extern unsigned int bAlwaysRun;
+extern unsigned int bFlipOnExit;
+extern int dword_6BE384_2dacceloff; // weak
+extern char byte_6BE388_graphicsmode; // weak
+extern unsigned int uTurnSpeed;
+extern float flt_6BE3A0; // weak
+extern float flt_6BE3A4_debug_recmod1;
+extern float flt_6BE3A8_debug_recmod2;
+extern float flt_6BE3AC_debug_recmod1_x_1_6;
+extern char byte_6BE3B0[20]; // idb
+extern char bUnderwater; // weak
+extern char bNoNPCHiring; // weak
+extern int _702AC0_unused; // weak
+extern int _702AC4_unused; // weak
+extern char _702ACC_unused; // weak
+extern int bDebugResouces; // weak
+extern unsigned int bNoVideo;
+extern bool bNoIntro;
+extern bool bNoLogo;
+extern bool bNoCD;
+extern bool bNoSound;
+extern int aborting_app; // weak
+extern int dword_720020_zvalues[100];
+extern int dword_7201B0_zvalues[299];
+extern int dword_72065C[]; // weak
+extern int dword_720660[]; // idb
+extern int dword_7207EC[]; // weak
+extern int dword_7207F0[]; // idb
+extern int uTextureID_720980; // weak
+extern int _720984_unused; // weak
+extern char _72098C_unused; // weak
+extern __int16 word_7209A0_intercepts_ys_plus_ys[104];
+extern __int16 word_720A70_intercepts_xs_plus_xs[104];
+extern __int16 word_720B40_intercepts_zs[104];
+extern __int16 word_720C10_intercepts_xs[102];
+extern int dword_720CDC;
+extern __int16 word_720CE0_ys[]; // idb
+extern __int16 word_720DB0_xs[]; // idb
+extern int dword_720E80[20];
+extern int dword_720ED0[20];
+extern int dword_720F20[20];
+extern __int16 word_720F70[]; // idb
+extern __int16 word_721040[]; // idb
+extern int dword_721110[]; // idb
+extern int dword_721160[]; // idb
+extern int dword_7211B0[]; // idb
+extern int dword_721200[]; // idb
+extern int dword_7212C8[]; // idb
+extern __int16 word_721390[]; // idb
+extern __int16 word_721460[]; // idb
+extern int blv_prev_party_x; // weak
+extern int blv_prev_party_z; // weak
+extern int blv_prev_party_y; // weak
+extern char *dword_721660; // idb
+extern char *dword_721664; // idb
+extern char *dword_722F10; // idb
+extern const char *pQuestTable[512];
+extern _UNKNOWN unk_723714; // weak
+extern char *dword_723718_autonote_related; // idb
+extern int dword_72371C[]; // weak
+extern const char *pScrolls[82];
+extern int dword_723E80_award_related[]; // weak
+extern int dword_723E84[]; // weak
+extern int dword_7241C8; // weak
+extern struct NPCStats *pNPCStats;
+extern char *aNPCProfessionNames[59];
+extern char *pAwardsTXT_Raw;
+extern char *pScrollsTXT_Raw;
+extern char *pMerchantsTXT_Raw;
+extern const char *pMerchantsBuyPhrases[7];
+extern const char *pMerchantsSellPhrases[7];
+extern const char *pMerchantsRepairPhrases[7];
+extern const char *pMerchantsIdentifyPhrases[7];
+extern char *pTransitionsTXT_Raw;
+extern char *pAutonoteTXT_Raw;
+extern char *pQuestsTXT_Raw;
+extern unsigned int uNumTerrainNormals;
+extern int pTerrainSomeOtherData[32768];
+extern unsigned __int16 pTerrainNormalIndices[32768];
+extern struct Vec3_float_ *pTerrainNormals;
+extern int dword_76D518_terrain_cell_world_pos_around_party_y; // weak
+extern int dword_76D51C_terrain_cell_world_pos_around_party_y; // weak
+extern int dword_76D520_terrain_cell_world_pos_around_party_y; // weak
+extern int dword_76D524_terrain_cell_world_pos_around_party_y; // weak
+extern int dword_76D528_terrain_cell_world_pos_around_party_z; // weak
+extern int dword_76D52C_terrain_cell_world_pos_around_party_z; // weak
+extern int dword_76D530_terrain_cell_world_pos_around_party_z; // weak
+extern int dword_76D534_terrain_cell_world_pos_around_party_z; // weak
+extern int dword_76D538_terrain_cell_world_pos_around_party_x; // weak
+extern int dword_76D53C_terrain_cell_world_pos_around_party_x; // weak
+extern int dword_76D540_terrain_cell_world_pos_around_party_x; // weak
+extern int dword_76D544_terrain_cell_world_pos_around_party_x; // weak
+extern int dword_76D548_terrain_cell_world_pos_around_party_y; // weak
+extern int dword_76D54C_terrain_cell_world_pos_around_party_y; // weak
+extern int dword_76D550_terrain_cell_world_pos_around_party_y; // weak
+extern int dword_76D554_terrain_cell_world_pos_around_party_y; // weak
+extern int dword_76D558_terrain_cell_world_pos_around_party_z; // weak
+extern int dword_76D55C_terrain_cell_world_pos_around_party_z; // weak
+extern int dword_76D560_terrain_cell_world_pos_around_party_z; // weak
+extern int dword_76D564_terrain_cell_world_pos_around_party_z; // weak
+extern int dword_76D568_terrain_cell_world_pos_around_party_x; // weak
+extern int dword_76D56C_terrain_cell_world_pos_around_party_x; // weak
+extern int dword_76D570_terrain_cell_world_pos_around_party_x; // weak
+extern int dword_76D574_terrain_cell_world_pos_around_party_x; // weak
+extern int terrain_76D5C8[128];
+extern int terrain_76D7C8[128];
+extern int terrain_76D9C8[128];
+extern int terrain_76DBC8[128];
+extern int terrain_76DDC8[128];
+extern int terrain_76DFC8[128];
+extern int terrain_76E1C8[128];
+extern int terrain_76E3C8[128];
+extern _UNKNOWN unk_801A00; // weak
+extern _UNKNOWN unk_801A0C; // weak
+extern char byte_80AA10; // weak
+extern int dword_80AA14; // weak
+extern int dword_80AA18; // weak
+extern int dword_80AA1C; // weak
+extern int dword_80AA20; // weak
+extern unsigned int uNumElementsIn80AA28;
+extern struct stru148 *ptr_80AA28[2000];
+extern struct Edge *pNewEdges;
+extern struct Surf *pSurfs;
+extern struct Edge *pEdges;
+extern struct Span *pSpans;
+extern struct Edge *ptr_80C978_Edges;
+extern struct Surf *ptr_80C97C_Surfs;
+extern struct Edge *ptr_80CA10[480];
+extern _UNKNOWN unk_80D190; // weak
+extern int dword_A74C88; // weak
+extern unsigned int uPlayerCreationUI_SkySliderPos;
+extern int uPlayerCreationUI_ArrowAnim;
+extern unsigned int uPlayerCreationUI_SelectedCharacter;
+extern int dword_A74CDC; // weak
+extern struct Texture *pTexture_PlayerFaceMask;
+extern struct Texture *pTexture_PlayerFaceEradicated;
+extern struct Texture *pTexture_PlayerFaceDead;
+extern struct Texture *pTextures_PlayerFaces[4][56];
+extern int dword_A75070; // weak
+extern struct Player *pPlayers[5];
+extern __int64 qword_A750D8; // weak
+extern __int16 word_A750E0; // weak
+extern __int16 word_A750E2; // weak
+extern char *pClassNames[36];
+extern char *aCharacterConditionNames[19];
+extern char *pSkillNames[38];
+extern char byte_AE3368[]; // weak
+extern char byte_AE3369; // weak
+extern char byte_AE336A; // weak
+extern char byte_AE336B; // weak
+extern int dword_AE336C; // weak
+extern int dword_AE3370; // weak
+extern char byte_AE5B91; // weak
+extern int dword_F1B430[32]; // weak
+extern int dword_F8B144; // idb
+extern char byte_F8B148[16];
+extern __int16 word_F8B158[]; // weak
+extern struct Texture *dword_F8B164; // idb
+extern struct Texture *dword_F8B168[12];
+extern int dword_F8B198; // weak
+extern int dword_F8B19C; // weak
+extern __int16 word_F8B1A0; // weak
+extern const char *dword_F8B1A4; // idb
+extern int dword_F8B1A8; // weak
+extern int dword_F8B1AC_something_todo_with_awards; // idb
+extern int dword_F8B1B0; // weak
+extern int dword_F8B1B4; // weak
+extern char *pShopOptions[4];
+extern _UNKNOWN unk_F8B1C8; // weak
+extern int dword_F8B1D8; // weak
+extern int dword_F8B1DC; // weak
+extern int dword_F8B1E0; // weak
+extern int dword_F8B1E4; // weak
+extern const char *ptr_F8B1E8; // idb
+extern char byte_F8B1EC; // weak
+extern char byte_F8B1EF[]; // weak
+extern char byte_F8B1F0[4];
+extern int dword_F8B1F4; // weak
+extern _UNKNOWN unk_F8B1F8; // weak
+extern _UNKNOWN unk_F8B5E0; // weak
+extern struct FrameTableTxtLine stru_F8B5E8; // weak
+extern _UNKNOWN unk_F8B668; // weak
+extern _UNKNOWN unk_F8BA50; // weak
+extern char byte_F8BC0C; // weak
+extern int bGameoverLoop; // weak
+extern __int16 word_F8BC48_displaced_face_intersect_plane_coords_a; // idb
+extern __int16 word_F8BD18_displaced_face_intersect_plane_coords_b; // idb
+//extern _UNKNOWN unk_F8EA04; // weak
+//extern _UNKNOWN unk_F8F8F8; // weak
+extern int dword_F93F20; // weak
+extern int dword_F93F70; // weak
+
+//extern int crt_F94004; // weak
+//extern int crtdword_F9400C; // weak
+extern FARPROC lpfn; // idb
+//extern int crt_F944EC; // weak
+//extern int crtdword_F944F0; // weak
+//extern void *crt_F944F4; // idb
+//extern int crtdword_F944F8; // weak
+//extern LPVOID crt_lpMem; // idb
+//extern int crt_F94500; // weak
+//extern HANDLE crt_hHeap; // idb
+//extern int crt_F94508; // weak
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//-------------------------------------------------------------------------
+// Function declarations
+
+#define __thiscall __cdecl // Test compile in C mode
+
+void __stdcall mm7__vector_constructor(void *a1, int objSize, int numObjs, int (__thiscall *constructor)(int));
+int __cdecl ODM_4014E6_AI();
+int __cdecl BLV_4016FA_AI();
+void __cdecl sub_401A91_AI();
+bool __fastcall sub_4070EF_prolly_collide_objects(unsigned int uObjID, unsigned int uObj2ID);
+bool __fastcall sub_4075DB(int a1, int a2, int a3, struct BLVFace *a4);
+bool __fastcall sub_4077F1(int a1, int a2, int a3, struct ODMFace *a4, struct BSPVertexBuffer *a5);
+bool __fastcall sub_407A1C(int x, int z, int y, struct Vec3_int_ v); // idb
+void InitializeActors();
+void InitializeLayingItems();
+int __fastcall sub_4088E9(int a1, int a2, int a3, int a4, int a5, int a6);
+unsigned int __thiscall SearchAliveActors(unsigned int *pTotalActors);
+unsigned int __fastcall SearchActorByMonsterID(unsigned int *pTotalActors, int uMonsterID);
+unsigned int __fastcall SearchActorByGroup(unsigned int *pTotalActors, unsigned int uGroup);
+unsigned int __fastcall SearchActorByID(unsigned int *pTotalActors, unsigned int a2);
+// char __usercall am_408BB4<al>(int a1<ecx>, int a2<ebp>);
+void __cdecl sub_409BE8();
+void __cdecl PrepareArcomage();
+char __cdecl am_409FE9();
+char __cdecl am_40A198();
+int __fastcall am_40A255(int a1, int a2);
+int __fastcall am_40A283(int a1, int a2);
+signed int __fastcall am_40A324(int a1);
+int __fastcall am_40A346(int a1);
+void __cdecl am_40A383();
+bool __cdecl am_40A514();
+char __thiscall am_40A560(unsigned int _this);
+void __thiscall am_blts(int a1); // idb
+void __cdecl am_40AA4E();
+void __cdecl am_chroma_blts();
+void __cdecl am_DrawUI();
+void __fastcall am_40B102(int a1, char *a2, int *pXY); // idb
+void __fastcall am_40B17E(int a1, int a2, int *pXY); // idb
+void __fastcall am_40B1F3(int a1, int a2, int a3);
+void __fastcall am_40B268(int a1, char *a2, int *pXY); // idb
+void __cdecl am_chroma_and_copy_blts();
+void __cdecl am_chroma_blt();
+void __cdecl am_40B4B9();
+void __fastcall am_40B76F(int a1);
+int __fastcall am_40BB49(int a1);
+signed int __fastcall am_40BB67(int a1);
+char __fastcall am_40BCFB(int a1, signed int a2);
+bool __fastcall am_40BE0E(int a1, signed int a2);
+bool __fastcall am_40BF15(int a1, int a2);
+void __fastcall am_40BF77(int a1, unsigned int uCardID); // idb
+int __fastcall am_40D2B4(struct Vec2_int_ *, int); // weak
+int __fastcall am_40D402(int, int); // weak
+int __cdecl am_40D444();
+struct GUIWindow *__fastcall ModalWindow(const char *pStr, int a4);
+char __fastcall pPrimaryWindow_draws_text(int a1, const char *pText, int *pXY);
+void __thiscall am_BeginScene(unsigned __int16 *pPcxPixels, int a2, int a3); // idb
+void __fastcall Blt_Chroma(struct ArcomageRect *pSrcXYZW, int *pTargetXY, int a3, int a4);
+void __fastcall Blt_Copy(struct ArcomageRect *pSrcXYZW, int *pTargetXY, int a3);
+void __cdecl am_EndScene();
+void __fastcall DrawRect(struct Vec4_int_ *pXYZW, unsigned __int16 uColor, char bSolidFill); // idb
+int __fastcall rand_interval(int a, int b); // idb
+char *__fastcall inv_strcat(const char *Source, char *Dest);
+char *__fastcall inv_strcpy(const char *Source, char *Dest);
+void __fastcall intToString(int val, char *pOut);
+// int __cdecl crt_retnull_sub();
+unsigned int __stdcall R8G8B8_to_TargetFormat(int uColor); // idb
+unsigned int __fastcall GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(unsigned __int16 r, unsigned __int16 g, unsigned __int16 b); // idb
+void __cdecl CallRenderPresent();
+void __thiscall DoBlt_Copy(unsigned __int16 *pPixels); // idb
+int __stdcall retzero_sub_40DFA7(int); // weak
+int loc_40E4FC(); // weak
+void __fastcall ZBuffer_Fill(int *pZBuffer, int uTextureId, int iZValue);
+__int16 __fastcall sub_40F845(int a1, int a2, int a3, int a4, int a5, __int16 a6, int a7);
+void __fastcall ZBuffer_DoFill(int *pZBuffer, Texture *pTex, int uZValue);
+void __fastcall sub_40F92A(int *pZBuffer, struct Texture *a2, int a3); // idb
+void __cdecl SetMoonPhaseNames();
+void __thiscall DrawSpellDescriptionPopup(void *_this);
+signed int __fastcall sub_410D99_get_map_index(int a1);
+unsigned int __cdecl DrawLloydBeaconsScreen();
+char *__cdecl DrawTownPortalScreen();
+struct Texture *__fastcall LoadSpellbook(unsigned int uID); // idb
+struct GUIWindow *__cdecl sub_41140B();
+void __cdecl sub_411473();
+void __cdecl OnCloseSpellook();
+void __cdecl InitializeBookTextures();
+void __cdecl InitializeBookFonts();
+void __fastcall LoadThumbnailLloydTexture(unsigned int uSlot, unsigned int uPlayer);
+void __cdecl sub_412AF9();
+void __cdecl sub_412B58();
+char __cdecl sub_412E85();
+void __cdecl DrawSpellbook_Quests();
+void __cdecl DrawSpellbook_Autonotes();
+char *__cdecl DrawSpellbook_Map();
+void __thiscall DrawSpellbook(unsigned int uBook); // idb
+char *__cdecl GetDayPart();
+char __cdecl DrawSpellbook_Calendar();
+void __cdecl SetAttributeNames();
+void __cdecl uGameUIFontMain_initialize();
+void __cdecl uGameUIFontShadow_initialize();
+void __cdecl sub_41420D_press_esc();
+void __cdecl sub_41426F();
+char __cdecl GameMenuUI_DrawKeyBindings();
+unsigned int __thiscall sub_414D24(int _this);
+void __cdecl GameMenuUI_DrawVideoOptions();
+void __cdecl sub_414F82_DrawGameOptions();
+void __fastcall DrawPopupWindow(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight); // idb
+char *__cdecl DrawCopyrightWindow();
+void __cdecl GUI_UpdateWindows();
+void __cdecl identify_item();
+void __thiscall sub_416B01(void *_this);
+void __thiscall sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(struct Vec2_int_ *_this);
+void __thiscall UI_OnMouseLeftClick(int *pXY); // idb
+void __thiscall sub_417871(int *pXY);
+void __cdecl sub_4178C4();
+void __cdecl sub_4178E1();
+unsigned int __fastcall UI_GetHealthManaStringColor(signed int a1, signed int a2);
+signed int __thiscall GetConditionDrawColor(unsigned int uConditionIdx); // idb
+char __fastcall sub_4179BC_draw_tooltip(const char *a1, const char *a2); // idb
+unsigned int __fastcall sub_417AD4(unsigned int uPlayerClass, enum PLAYER_SKILL_TYPE uPlayerSkillType, signed int a3);
+const char *__fastcall CharacterUI_GetSkillDescText(unsigned int uPlayerID, enum PLAYER_SKILL_TYPE uPlayerSkillType);
+char __cdecl CharacterUI_SkillsTab_ShowHint();
+char __cdecl CharacterUI_StatsTab_ShowHint();
+char __fastcall CharacterUI_StatsTab_Draw(unsigned int uPlayerID); // idb
+int __cdecl sub_419100();
+void __cdecl sub_419220();
+void __cdecl sub_419379();
+void __cdecl sub_419401();
+void __cdecl sub_4196A0();
+char __fastcall CharacterUI_SkillsTab_Draw(unsigned int uPlayerID); // idb
+unsigned int __fastcall CharacterUI_AwardsTab_Draw(unsigned int uPlayerID); // idb
+unsigned int __fastcall GetSizeInInventorySlots(unsigned int uNumPixels);
+void __fastcall CharacterUI_InventoryTab_Draw(unsigned int uPlayerID, char a2);
+void __cdecl draw_leather();
+char __cdecl QuickRefDraw();
+void __thiscall CharacterUI_CharacterScreen_Draw(unsigned int uPlayerIdx); // idb
+void __cdecl GameUI_DrawRightPanelItems();
+void __cdecl GameUI_DrawFoodAndGold();
+void __cdecl GameUI_DrawLifeManaBars();
+void __cdecl draw_right_panel();
+void __cdecl GameUI_DrawRightPanelFrames();
+struct GUIButton *__fastcall GUI_HandleHotkey(unsigned __int8 uHotkey); // idb
+int __fastcall GUI_ReplaceHotkey(unsigned __int8 uOldHotkey, unsigned __int8 uNewHotkey, char bFirstCall);
+void __cdecl MainMenuUI_LoadFontsAndSomeStuff();
+void __cdecl MainMenuUI_Create();
+void __cdecl GameUI_DrawStatusBar_2();
+void __thiscall sub_41C0B8_set_status_string(const char *pStr); // idb
+void __cdecl GameUI_DrawStatusBar();
+bool __thiscall sub_41CD4F(unsigned int _this);
+char __fastcall sub_41D20D_buff_remaining_time_string(int ecx0, struct GUIWindow *edx0, __int64 a3, struct GUIFont *a2);
+void __thiscall GameUI_DrawItemInfo(struct ItemGen *_this); // idb
+char *__fastcall MonsterPopup_Draw(unsigned int uActorID, struct GUIWindow *edx0);
+void __cdecl nullsub_3(); // idb
+void __cdecl LoadActualSkyFrame();
+void __cdecl Sleep6Hours();
+void __cdecl RestUI_Initialize();
+void __cdecl RestUI_Draw(); // idb
+void __cdecl sub_42038D();
+void __fastcall sub_420B13(int a1, int a2);
+void __fastcall party_finds_gold(unsigned int uNumGold, int _1_dont_share_with_followers___2_the_same_but_without_a_message__else_normal); // idb
+void __cdecl sub_420E01();
+void __cdecl GameUI_WritePointedObjectStatusString();
+struct GUIWindow *__thiscall GameUI_InitializeCharacterWindow(unsigned int _this);
+struct GUIWindow *__thiscall sub_4219BE(void *a4);
+bool __cdecl sub_421B2C_PlaceInInventory_or_DropPickedItem();
+void __fastcall GameUI_OnPlayerPortraitLeftClick(unsigned int uPlayerID); // idb
+void __cdecl sub_421EA6_OnInventoryLeftClick();
+void __cdecl OnGameViewportClick();
+bool __cdecl sub_4226C2();
+void __fastcall SetUserInterface(int a1, bool bReplace);
+void __cdecl reset_some_strus_flt_2Cs();
+void __cdecl j_sub_423B4A();
+void __cdecl sub_423B4A();
+int __fastcall sub_423B5D(unsigned int uFaceID);
+signed int __fastcall sub_424579(int uFaceID, struct stru320 *a2);
+bool sub_424829(int a1, struct BspRenderer_stru2 *a2, struct BspRenderer_stru2 *a3, int a4);
+signed int __fastcall sr_424CD7(unsigned int uVertexID); // idb
+signed int __fastcall sr_424EE0_MakeFanFromTriangle(unsigned int uVertexID); // idb
+signed int __fastcall sr_4250FE(unsigned int uVertexID); // idb
+signed int __fastcall sr_4252E8(unsigned int uVertexID);
+int __fastcall sr_4254D2(signed int a1);
+bool __thiscall sr_42620A(struct RenderVertexSoft *p);
+int __fastcall _4268E3_smthn_to_a1r5g5b5(unsigned int uColor); // idb
+int __fastcall _42690D_colors_cvt(unsigned int a1);
+void __cdecl sub_426947();
+int __fastcall sub_4269A2_GivePartyExp(unsigned int a1);
+bool __fastcall sub_427769_spell(unsigned int uSpellID);
+bool __fastcall _42777D_CastSpell_UseWand_ShootArrow(int a1, unsigned int uPlayerID, unsigned int a4, __int16 a5, int a6);
+int __fastcall sub_42EBBE(int, int); // weak
+bool __cdecl _42ECB5_PlayerAttacksActor();
+void __thiscall InitializeTurnBasedAnimations(void *);
+signed int __cdecl sub_42F4DA();
+bool __fastcall sub_42F7EB_DropItemAt(unsigned int uSpriteID, int x, int y, int z, int a4, int count, int a7, unsigned __int16 attributes, ItemGen *a9);
+void __fastcall sub_42F960_create_object(int x, int y, int z); // idb
+char *__cdecl sub_42FA22_mess_with_laying_item_list();
+signed int __fastcall _42FA66_do_explosive_impact(int a1, int a2, int a3, int a4, __int16 a5, signed int a6);
+bool __fastcall sub_42FB5C(signed int a1);
+// int __cdecl crt_sub_42FBB7();
+// void __cdecl crt_construct_50CDB4();
+void __cdecl sub_42FBDD();
+void __cdecl sub_42FC15();
+void __cdecl ProcessInputActions();
+void __cdecl GameUI_MsgProc();
+void __cdecl back_to_game();
+void __cdecl GUI_MainMenuMessageProc();
+double __cdecl get_shading_dist_mist();
+double __cdecl GetPickDepth();
+void Vec3_short__to_RenderVertexSoft(struct RenderVertexSoft *_this, struct Vec3_short_ *a2);
+void __cdecl nullsub_4(); // idb
+void __cdecl nullsub_5(); // idb
+void __cdecl nullsub_6(); // idb
+__int16 __thiscall sub_4382BC(int _this);
+int __cdecl sub_4383ED();
+__int16 __cdecl sub_43847A();
+void __cdecl _438F8F_area_of_effect__damage_evaluate();
+void __fastcall DamagePlayerFromMonster(unsigned int uObjID, int a2, struct Vec3_int_ *pPos, unsigned int a4);
+void __fastcall sub_43A97E(unsigned int uLayingItemID, signed int a2); // idb
+double __fastcall sub_43AE12(signed int a1);
+int __fastcall _43AFE3_calc_spell_damage(int a1, int a2, signed int a3, int a4);
+void __fastcall sub_43B057(unsigned int uObjID, unsigned int uActorID, struct Vec3_int_ *pVelocity);
+__int16 __fastcall sub_43B1B0(signed int a1, unsigned int a2, struct Vec3_int_ *pVelocity, signed int a4);
+int __stdcall DirectInputKeyboard_enumerator_43B9B9(int, int); // weak
+void Software_ResetNewEdges();
+// int __cdecl crt_deconstruct_43B9E3();
+int __stdcall DirectInputMouse_enumerator(int, int); // weak
+int __cdecl CharacterUI_LoadPaperdollTextures();
+int __fastcall _43C91D_FormItemTextureFilename(char *a1, signed int a2, int a3, int a4);
+void __fastcall CharacterUI_DrawPaperdoll(unsigned int uPlayerID); // idb
+void __fastcall CharacterUI_DrawPaperdollWithRingOverlay(unsigned int uPlayerID); // idb
+bool _43ED6F_check_party_races(bool b);
+bool __thiscall sub_43EDB9_get_some_race_sex_relation_2(unsigned int _this);
+bool __fastcall sub_43EE15_player_has_item(unsigned int uItemID, struct Player *pPlayer, char a3);
+bool __fastcall sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(signed int a1);
+void __fastcall WetsuitOn(unsigned int uPlayerID); // idb
+unsigned int __fastcall WetsuitOff(unsigned int uPlayerID);
+void __fastcall PrepareDrawLists_BLV(struct IndoorLocation_drawstru *_this);
+int /*__usercall*/ sr_sub_4D6FB0/*<eax>*/(struct stru315 *a1/*<ebp>*/);
+int /*__usercall*/ sr_sub_4D705A/*<eax>*/(struct stru315 *a1/*<ebp>*/);
+void __cdecl MessWithBillboards_BLV();
+int __fastcall _43F55F_get_billboard_light_level(struct RenderBillboard *a1, int uBaseLightLevel);
+int __fastcall _43F5C8_get_point_light_level_with_respect_to_lights(unsigned int uBaseLightLevel, int uSectorID, float x, float y, float z);
+void PrepareBspRenderList_BLV();
+void __fastcall PrepareDecorationsRenderList_BLV(unsigned int uDecorationID, unsigned int uSectorID);
+void PrepareActorRenderList_BLV();
+void PrepareItemsRenderList_BLV();
+void __fastcall sub_440639(int a1);
+void __fastcall sub_4406BC(int a1, unsigned int uFirstNode); // idb
+void __fastcall sub_440BED(struct IndoorLocation_drawstru *_this);
+bool sub_44100D();
+void GameUI_DrawTorchlightAndWizardEye();
+void GameUI_DrawCharacterSelectionFrame();
+void Load_isn_spells_21_27();
+void GameUI_DrawPartySpells();
+__int16 __fastcall sub_441A4E(int a1);
+void GameUI_DrawMinimap(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW, unsigned int uZoom, unsigned int flags);
+int __fastcall DrawSpellbook_Map_sub(unsigned int x, unsigned int y, unsigned int a4, int a5, int _48074); // idb
+int __cdecl Initialize2DA();
+unsigned int __fastcall LoadEventsToBuffer(const char *pContainerName, char *a2, unsigned int uBufferSize);
+void __cdecl Initialize_GlobalEVT();
+void __cdecl LoadLevel_InitializeLevelStr();
+void __cdecl LoadLevel_InitializeLevelEvt();
+void __cdecl OnMapLeave();
+void /*__usercall*/ OnMapLoad();
+void __thiscall Level_LoadEvtAndStr(const char *pLevelName);
+char *__cdecl _4443D5_GetMinimapRightClickText();
+const char *__cdecl sub_444564();
+char *__thiscall _444732_GetEventHintString(unsigned int uEventID); // idb
+unsigned int __fastcall sub_444839_move_map(unsigned int a1, int a2, int x, int y, int z, int directiony, int directionx, int a8, const char *pLocationName); // idb
+char *__cdecl TransitionUI_Draw();
+struct GUIWindow *__cdecl UI_CreateTravelDialogue();
+signed int __cdecl GetTravelTime();
+void __cdecl TravelUI_Draw();
+void __cdecl DrawBranchlessDialogueUI();
+void __fastcall sub_4451A8_press_any_key(int a1, int a2, int a4);
+void __cdecl sub_4452BB();
+const char *__fastcall sub_445308(int a1);
+void __cdecl DrawDialogueUI();
+struct NPCData *__fastcall GetNPCData(unsigned int npcid);
+struct NPCData *__fastcall GetNewNPCData(signed int npcid, int a2);
+int __fastcall sub_445C8B(signed int a1);
+void __cdecl sub_44603D();
+int __fastcall PrepareHouse(unsigned int uHouseID); // idb
+bool __fastcall EnterHouse(enum HOUSE_TYPE uHouseID);
+int sub_4465DF_check_season(int a1);
+int __fastcall IsActorAlive(unsigned int uType, unsigned int uParam, unsigned int uNumAlive); // idb
+// void __cdecl crt_construct_5773C4();
+bool __thiscall sub_4466C4(void *_this);
+void __fastcall EventProcessor(int a1, int a2, int a3);
+void __fastcall sub_448518_npc_set_item(int npc, unsigned int item, int a3);
+void __fastcall sub_44861E_set_texture(unsigned int uFaceCog, const char *pFilename);
+void __fastcall SetDecorationSprite(unsigned int uCog, int a2, const char *pFileName); // idb
+void __fastcall sub_44892E_set_faces_bit(int sCogNumber, int bit, int on);
+void __fastcall ToggleActorGroupFlag(unsigned int uGroupID, unsigned int uFlag, unsigned int bToggle);
+void __thiscall GameUI_StatusBar_UpdateTimedString(unsigned int bForceHide); // idb
+void __thiscall OnTimer(int a1);
+void __fastcall sub_448CF4_spawn_monsters(__int16 typeindex, __int16 level, int count, int x, int y, int z, int group, unsigned int uUniqueName);
+void __fastcall sub_448DF8_cast_spell(int spellnum, int rank, int level, int fromx, int fromy, int fromz, int tox, int toy, int toz);
+char *__fastcall sub_44987B(const char *pMapName, unsigned int uStartingPointType); // idb
+void __thiscall TeleportToStartingPoint(unsigned int uPointType); // idb
+__int16 __fastcall sub_449A49_door_switch_animation(unsigned int uDoorID, int a2); // idb
+unsigned int __fastcall _449B57_test_bit(unsigned __int8 *a1, __int16 a2);
+unsigned char *_449B7E_toggle_bit(unsigned char *pArray, __int16 a2, unsigned __int16 bToggle); // idb
+void __cdecl sub_44A56A();
+void __fastcall ShowStatusBarString(const char *pString, unsigned int uNumSeconds);
+void __cdecl ShowNothingHereStatus();
+signed int __cdecl const_2();
+bool __cdecl sub_44C28F_open_nwc_dungeon();
+// int __cdecl crt_deconstruct_44C42C();
+struct GUIFont *LoadFont(const char *pFontFile, const char *pFontPalette, ...);
+char *__fastcall FitTextInAWindow(const char *pInString, GUIFont *pFont, GUIWindow *pWindow, unsigned int uX, int a5);
+void SpawnEncounter(struct MapInfo *pMapInfo, struct SpawnPointMM7 *spawn, int a3, int a4, int a5);
+int __fastcall sub_44FA4C_spawn_light_elemental(int a1, int a2, int a3);
+void __cdecl sub_450218_prolly_generate_chests_loot();
+signed int __fastcall sub_450521_ProllyDropItemAt(int ecx0, signed int a2, int a3, int a4, int a5, unsigned __int16 a6);
+int __fastcall sub_45063B(struct MapInfo *a1, int a2);
+void RespawnGlobalDecorations();
+bool __fastcall SpawnActor(unsigned int uMonsterID);
+int __cdecl GetAlertStatus();
+unsigned int __fastcall sub_452442(unsigned __int16 a1, unsigned __int16 a2, int a3, int a4);
+signed int __fastcall sub_452A9E(signed int a1);
+int __fastcall MakeColorMaskFromBitDepth(int a1);
+void __fastcall fill_pixels_fast(unsigned int a1, unsigned __int16 *pPixels, unsigned int uNumPixels);
+int __fastcall GetDiceResult(unsigned int uNumDice, unsigned int uDiceSides); // idb
+inline void __fastcall memset32(void *ptr, unsigned __int32 value, int count)
+{
+  auto p = (unsigned __int32 *)ptr;
+  for ( int i=0; i < count; i++ )
+    *p++ = value;
+}
+inline void __fastcall j_memset32(int a2, void *a1, unsigned int a3) {memset32(a1, a2, a3);}
+// int __cdecl crt_452B74();
+int __cdecl j_SetSomeItemsNames();
+void __cdecl SetSomeItemsNames();
+char *RemoveQuotes(char *Str);
+void __cdecl InitializeGameText();
+unsigned int __fastcall ParseSpellType(struct FrameTableTxtLine *, int a2);
+int __thiscall ParseAttackType(unsigned __int8 *_this);
+char __fastcall ParseDamage(const char *Str, int a2, int a3, int a4);
+int __fastcall ParseMissleAttackType(const char *Str1);
+unsigned int __fastcall SkillToMastery(unsigned __int16 a1);
+unsigned int __fastcall GetSpellColor(signed int a1);
+void *__thiscall unknown_vdtor_6(void *_this, bool a2);
+unsigned __int16 *__fastcall MakeScreenshot(signed int width, signed int height);
+void __thiscall SaveScreenshot(const char *pFilename);
+void __fastcall GameUI_DrawLoadMenu(unsigned int uDialogueType); // idb
+void __cdecl GameUI_DrawSaveMenu();
+void __fastcall LoadGame(unsigned int uSlot); // idb
+int __fastcall SaveGame(int a1, __int16 *a2);
+void __fastcall DoSavegame(unsigned int uSlot); // idb
+void GameUI_MainMenu_DoDrawLoad(int a1);
+void GameUI_MainMenu_DrawLoad();
+void __cdecl sub_4606FE();
+void __cdecl TryLoadLevelFromLOD();
+void __cdecl sub_46080D();
+bool __cdecl Initialize_GamesLOD_NewLOD();
+bool Autosave();
+void __thiscall PrepareToLoadBLV(unsigned int bLoading);
+void __fastcall PrepareToLoadODM(unsigned int bLoading, struct OutdoorCamera *a2);
+void __cdecl sub_461103();
+int __cdecl sub_4613C4();
+int __fastcall sub_4621DA(signed int a1, signed int a2, signed int a3);
+int __cdecl sub_46224A();
+int __cdecl crt_init_globals_462620();
+void __cdecl crt_init_globals_462659();
+void __cdecl crt_init_globals_46269B();
+void __cdecl crt_init_globals_46271C();
+void __cdecl MainMenu_Loop();
+char __cdecl sub_4637E0_is_there_popup_onscreen();
+void __cdecl ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
+void __thiscall PrepareWorld(unsigned int _this);
+void __thiscall Game_DeinitializeAndTerminate(int exitCode); // idb
+void __cdecl FinalInitialization();
+char __cdecl Is_out15odm_underwater();
+void __cdecl SetUnderwaterFog();
+void __fastcall DoPrepareWorld(unsigned int bLoading, int a2);
+int __fastcall ReadWindowsRegistryInt(const char *pKey, int uDefValue); // idb
+void __fastcall WriteWindowsRegistryString(const char *pKey, const char *pString);
+void __fastcall ReadWindowsRegistryString(const char *pKeyName, char *pOutString, int uBufLen, const char *pDefaultValue);
+void __fastcall WriteWindowsRegistryInt(const char *pKey, int val);
+bool __fastcall CheckMM7CD(char c);
+int loc_465CC8(); // weak
+void __cdecl SecondaryInitialization();
+void __cdecl CreateAsyncMouse();
+void __cdecl CreateAsyncKeyboard();
+void __cdecl MM6_Initialize(const wchar_t *pIniFilename);
+void __cdecl MM7Initialization();
+int __cdecl AbortWithError();
+void Abortf(const char *Format, ...);
+void FreeSavegameThumbnails();
+void SetCurrentMenuID(enum MENU_STATE); // idb
+enum MENU_STATE GetCurrentMenuID();
+void *__thiscall output_debug_string(void *_this, std::string a2, const char *a3, int a4);
+std::string *__fastcall _4678E2_make_error_string(std::string *a1, int line, std::string file);
+int __thiscall sub_467D5D(int _this);
+void __thiscall sub_467E7F_EquipBody(unsigned int uEquipType); // idb
+void __fastcall sub_467F48(signed int a1);
+void __cdecl free_book_subwindow();
+char __cdecl sub_467FB6();
+void __cdecl OnPaperdollLeftClick();
+int __thiscall UnprojectX(int x);
+int __thiscall UnprojectY(int _this);
+char __cdecl OnPressSpace();
+char __fastcall DoInteractionWithTopmostZObject(int a1, int a2);
+int __fastcall sub_46A6AC(int a1, int a2, int a3);
+int __fastcall sub_46A7C8(int a1, int a2, signed int a3);
+int __fastcall sub_46A89E(int a1, int a2, signed int a3);
+int __cdecl sub_46A99B();
+void *__thiscall unknown_libname_8(void *_this, char a2);
+unsigned int __cdecl GetGravityStrength();
+void __cdecl sub_46BDC0_UpdateUserInput_and_MapSpecificStuff();
+void __cdecl BLV_UpdateUserInputAndOther();
+void __cdecl ODM_UpdateUserInputAndOther();
+bool __fastcall _46BFFA_check_object_intercept(unsigned int uLayingItemID, signed int a2);
+void __cdecl _46CC4B_check_event_triggers();
+int _46CEC3_get_floor_level(int x, int y, int z, unsigned int uSectorID, unsigned int *pFaceID);
+int __fastcall sub_46D49E_prolly_get_world_y_under_party(int a1, signed int a2, int a3, int a4, int *a5, int *a6, int a7);
+int __fastcall sub_46D8E3(int a1, signed int a2, int a3, int a4);
+signed __int64 __fastcall _46DCC8_get_gravity_direction_outdoor(int a1, int a2, Vec3_int_ *a3);
+unsigned int __fastcall sub_46DEF2(signed int a2, unsigned int uLayingItemID);
+int __fastcall _46DF1A_collide_against_actor(int, int); // weak
+void __cdecl _46E0B2_collide_against_decorations();
+void __fastcall _46E26D_collide_against_sprites(signed int a1, signed int a2);
+int __thiscall _46E44E_collide_against_faces_and_portals(unsigned int b1); // idb
+int __fastcall _46E889_collide_against_bmodels(unsigned int ecx0);
+int _46ED1B_collide_against_floor(int x, int y, int z, unsigned int *pSectorID, unsigned int *pFaceID); // idb
+void __fastcall _46ED8A_collide_against_layingItems(unsigned int _this);
+int __thiscall _46EF01_collision_chech_player(int a1); // idb
+signed int __cdecl _46F04E_collide_against_portals();
+void __cdecl BLV_UpdateDoors();
+void __cdecl UpdateActors_BLV();
+void __cdecl UpdateActors_ODM();
+void __cdecl UpdateObjects();
+int _47272C_collide_agains_some_secotors_floors(int x, int y, int z, unsigned int *pSectorID, unsigned int *pFaceID); // idb
+void __cdecl BLV_ProcessPartyActions();
+void __cdecl ODM_ProcessPartyActions();
+bool __fastcall sub_47531C(int a1, int *a2, int a3, int a4, int a5, int a6, int a7, int a8, BLVFace *a9, int a10);
+bool __fastcall sub_4754BF(int a1, int *a2, int a3, int a4, int a5, int a6, int a7, int a8, BLVFace *a9, int a10, int a11);
+signed int __thiscall sub_475665(BLVFace *_this, int a2, __int16 a3);
+bool __fastcall sub_4759C9(BLVFace *a1, int a2, int a3, __int16 a4);
+bool __fastcall sub_475D85(Vec3_int_ *a1, Vec3_int_ *a2, int *a3, BLVFace *a4);
+bool __fastcall sub_475F30(int *a1, BLVFace *a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);
+bool __cdecl sub_476387();
+bool __thiscall CheckHiredNPCSpeciality(unsigned int uProfession);
+void __cdecl InitializeAwards();
+void __cdecl InitializeScrolls();
+void __cdecl InitializeMerchants();
+void __cdecl InitializeTransitions();
+void __cdecl InitializeAutonotes();
+void __cdecl InitializeQuests();
+int __fastcall const_1(int, int); // weak
+int __cdecl GetPartyReputation();
+void __cdecl sub_4783FA_construct_global_73D150();
+void __cdecl loc_4789D4(); // idb
+void __cdecl loc_47907F(); // idb
+bool __fastcall IsBModelVisible(unsigned int uModelID, int *unused);
+void __fastcall _479A53_draw_some_blv_poly(unsigned int uNumVertices, unsigned int uFaceID); // idb
+void __thiscall ODM_LoadAndInitialize(const char *pLevelFilename, struct OutdoorCamera *thisa);
+unsigned __int16 *__fastcall GetBillboardPalette(struct RenderBillboard *a1, int a2, signed int a3, int a4);
+int __fastcall sr_sub_47BEB1(signed int a1, stru148 *a2, int terrain_gamma, int a4, int *a5, int *a6, int a7, int a8);
+void *__fastcall sr_sub_47C178(signed int a1, stru148 *a2, int terrain_gamma, int a4);
+void *__fastcall sr_sub_47C1CA(stru148 *a1, char a2, int a3, signed int a4);
+unsigned __int16 *__fastcall sr_sub_47C24C_get_palette(BLVFace *a1, int a2, int a3, char a4);
+char *__fastcall sr_sub_47C28C_get_palette(stru148 *a1, char a2, signed int a3, signed int a4);
+unsigned int __cdecl GetLevelFogColor();
+int __fastcall sub_47C3D7_get_fog_related_stuff(int a1, int a2, float a3);
+signed int __fastcall GetActorTintColor(int a1, int a2, float a3, int a4, struct RenderBillboard *a5);
+int __stdcall WorldPosToGridCellX(int); // weak
+int __stdcall WorldPosToGridCellZ(int); // weak
+int __stdcall GridCellToWorldPosX(int); // weak
+int __stdcall GridCellToWorldPosZ(int); // weak
+void __fastcall sub_47F4D3(int band1, int band2, int band3);
+void __cdecl loc_481185(); // idb
+void __cdecl loc_48118F(); // idb
+void __cdecl loc_481199(); // idb
+char __fastcall sr_sub_481DB2(RenderVertexSoft *a1, signed int a2, stru148 *a3);
+void __cdecl ResetStru148s();
+void __cdecl sub_481ED9_MessWithOutdoorCamera();
+bool __fastcall sub_481EFA(RenderVertexSoft *a1, RenderVertexSoft *a2, RenderVertexSoft *a3, RenderVertexSoft *a4, int a5);
+signed int __fastcall sub_481FC9(RenderVertexSoft *_ECX, RenderVertexSoft *a2, RenderVertexSoft *a3, stru148 *a4);
+bool __fastcall GetTerrainHeightsAroundParty(int a1, int a2);
+int __fastcall GetTerrainHeightsAroundParty2(int a1, int a2, int *a3, int a4);
+struct stru148 *__fastcall sr_sub_4829B9(RenderVertexSoft *a1, RenderVertexSoft *a2, RenderVertexSoft *a3, stru148 *a4, int a5);
+signed int __cdecl const_1_0();
+signed int __thiscall sr_sub_482A94(struct Span *_this);
+signed int __fastcall sr_sub_482E07(struct Span *a1, unsigned __int16 *pRenderTarget); // idb
+signed int __fastcall sr_sub_4839BD(struct Span *a1, unsigned __int16 *pTargetSurface); // idb
+signed int __thiscall sr_sub_48408A_prolly_odm_water_no_waves(struct Span *_this);
+signed int __thiscall sr_sub_484442(struct Span *_this);
+signed int __thiscall sr_sub_4847EB(struct Span *_this);
+signed int __fastcall sr_sub_485407_prolly_odm_water_wavy(struct Span *a1);
+signed int __fastcall sr_sub_48585C_mb_DrawSpan(struct Span *a1, unsigned __int16 *pRenderTarget, int a3); // idb
+struct stru315 *__fastcall sr_sub_485975(struct stru315 *a1, struct stru315 *a2);
+struct stru315 *__fastcall sr_sub_485A24(struct stru315 *a1, struct stru315 *a2);
+struct stru315 *__fastcall sr_sub_485AFF(struct stru315 *a1, struct stru316 *a2);
+struct stru315 *__fastcall sr_sub_485BAE(struct stru315 *a1, struct stru316 *a2);
+struct stru315 *__fastcall sr_sub_485C89(struct stru315 *a1, struct stru316 *a2);
+struct stru315 *__fastcall sr_sub_485D3E(struct stru315 *a1, struct stru316 *a2);
+void *__fastcall sr_sub_485E1F(struct stru316 *a1, Span *a2, int a3, struct stru148 *a4, int a5, unsigned __int8 a6, char a7);
+void __thiscall sub_485F53(struct Vec2_int_ *v); // idb
+char __fastcall sr_sub_486B4E_push_outdoor_edges(struct RenderVertexSoft *a1, int *a2, int *a3, stru148 *a4);
+void __cdecl sr_sub_486F92_MessWithEdgesAndSpans();
+void __cdecl sub_487DA9();
+double __thiscall GetFogDensityByTime(struct OutdoorLocation *_this);
+int __stdcall loc_489BB3(struct stru320 *a2, int thisa, unsigned int uNumVertices, RenderVertexSoft *a5, float a6, char uClipFlag); // weak
+bool __fastcall HSV2RGB(float *a1, float *a2, float *a3, float a4, float a5, float a6);
+void __fastcall RGB2HSV(float *a1, float *a2, float a3, float a4, float a5, float *a6);
+unsigned int ReplaceHSV(unsigned int uColor, float a2, float gamma, float a4);
+int _48B561_mess_with_scaling_along_z(/*int a1, */float a2);
+signed int __cdecl sub_4908DE();
+signed int __cdecl PlayerCreation_ComputeAttributeBonus();
+void __cdecl LoadPlayerPortraintsAndVoices();
+int __fastcall ReloadPlayerPortraits(int, int); // weak
+void __cdecl sub_491E3A();
+void __cdecl DrawHiredNPCs();
+void __thiscall GameUI_DrawPortraits(unsigned int _this);
+signed int __thiscall CycleCharacter(unsigned int _this);
+void __fastcall Rest(unsigned int uHoursToSleep);
+int __cdecl _493938_regenerate();
+int __thiscall sub_493F79(struct stru351 *_this, __int64 a2);
+void __cdecl _494035_timed_effects__water_walking_damage__etc();
+unsigned int __fastcall sub_494820(unsigned int a1);
+char *__fastcall sub_495366(unsigned __int8 a1, unsigned __int8 a2);
+char *__fastcall GetReputationString(signed int a1);
+char *__fastcall sub_495461(char *lpsz, unsigned __int8 uPlayerID, struct ItemGen *a3, char *a4, int a5, __int64 *a6);
+void __cdecl PlayerCreationUI_Draw();
+void __cdecl PlayerCreationUI_Initialize();
+void __cdecl DeleteCCharFont();
+bool __cdecl PlayerCreationUI_Loop();
+void __cdecl loc_49B785(); // idb
+unsigned int __fastcall GetMaxMipLevels(unsigned int uDim);
+bool __cdecl CheckTextureStages();
+bool __cdecl AreRenderSurfacesOk();
+int __fastcall sub_4A19D8(unsigned int, unsigned int); // weak
+void __cdecl DoRenderBillboards_D3D();
+int __fastcall sr_4A46E6_draw_particle_segment(unsigned int x, signed int y, signed int z, int a4, unsigned int lightColor);
+void __cdecl Present_ColorKey();
+void __cdecl Present_NoColorKey();
+int __thiscall sub_4A7063(unsigned int uDiffuse, float a2); // idb
+struct SoundHeader *__fastcall FindSound_BinSearch(unsigned int uStart, unsigned int uEnd, const char *pName);
+struct SoundData *LoadSound(const char *pSoundName, struct SoundData *pOutBuff, unsigned int uID);
+int __fastcall sub_4AAEA6_transform(RenderVertexSoft *a1);
+int __fastcall sub_4AB66C(int, int); // weak
+int __fastcall GetSoundStrengthByDistanceFromParty(int a1, int a2, int a3);
+struct _DIG_DRIVER *Audio_GetFirstHardwareDigitalDriver(void);
+void __cdecl PlayLevelMusic();
+int __thiscall sub_4AC1C9(unsigned int _this, Vec4_int_ *a2);
+struct Vec4_int_ *__thiscall sub_4AC277(unsigned int _this, Vec4_int_ *a2);
+struct Vec4_int_ *__thiscall sub_4AC33A_get_cpu_clocks_QPC(int _this, Vec4_int_ *a1);
+struct Vec4_int_ *__thiscall sub_4AC4FD_get_cpu_clocks_rdtsc(int _this, Vec4_int_ *a1);
+int __fastcall sub_4AD504(unsigned int uFaceID);
+void __fastcall sub_4ADD1D(int uFaceID);
+int __fastcall sub_4AE1E7(int a1, int a2, int a3);
+int __fastcall sub_4AE313(int viewport_space_x, int viewport_space_y, struct stru337_stru0 *p);
+int __fastcall sub_4AE491(int, int); // weak
+void __fastcall sub_4AE5F1(unsigned int uFaceID); // idb
+int __cdecl sub_4AF412();
+void __cdecl stru170_sub_4B0967();
+void __cdecl loc_4B0DFB(); // idb
+void __cdecl nullsub_18(); // idb
+void __cdecl nullsub_19(); // idb
+unsigned int __fastcall sub_4B0E07(unsigned int uFaceID); // idb
+void __cdecl nullsub_20(); // idb
+void __cdecl nullsub_21(); // idb
+struct Player *__fastcall sub_4B1447_party_fine(int a1, int a2, int a3);
+char *__thiscall sub_4B1523(int *_this);
+bool __cdecl sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win();
+void __cdecl sub_4B1A2D();
+void __stdcall RestAndHeal(__int64 uNumMinutes); // idb
+void __cdecl sub_4B1D27();
+void __fastcall HousePlaySomeSound(unsigned int uHouseID, int a2); // idb
+void __cdecl sub_4B1ECE();
+void __fastcall sub_4B2001(signed int a1);
+char *__thiscall _4B254D_SkillMasteryTeacher(int _this);
+const char *__fastcall sub_4B29F2(int a1);
+char __cdecl sub_4B2A74();
+struct GUIButton *__fastcall sub_4B36CC(int a1, unsigned int a2);
+int __thiscall sub_4B3703(void *_this);
+int __thiscall sub_4B3A72(int a1); // idb
+int __fastcall sub_4B3AD4(signed int a1);
+int __fastcall sub_4B3B42(signed int a1);
+void __cdecl sub_4B3E1E();
+void __fastcall sub_4B3EF0(int a4);
+void __fastcall sub_4B3FE5(int a4);
+void __cdecl sub_4B40E6();
+struct GUIButton *__thiscall _4B4224_UpdateNPCTopics(int _this);
+char __fastcall sub_4B46A5(const char *Str, int a5);
+int __fastcall sub_4B46F8(int a1);
+int __cdecl ui_training();
+char *__cdecl sub_4B4F4F();
+int __cdecl ui_shop_teachers();
+int __cdecl sub_4B5D7C();
+int __cdecl sub_4B6478();
+bool __fastcall sub_4B68EA(int a1);
+void __cdecl TravelByTransport();
+int __cdecl sub_4B705E();
+void __cdecl sub_4B7911();
+void __cdecl _4B7D7E_bank();
+void __cdecl sub_4B8285_prolly_draw_arcomage_result();
+void *__cdecl GenerateShopItems();
+void *__cdecl sub_4B8F94();
+char *__cdecl sub_4B910F();
+POINT *__cdecl sub_4B9CC6();
+void __cdecl sub_4BA928();
+signed int __fastcall sub_4BB756(signed int a1);
+const char *sub_4BBA85_bounties();
+void __cdecl sub_4BBCDD();
+void __fastcall _4BBF61_summon_actor(int a1, __int16 x, int y, int z); // idb
+void __cdecl ArenaFight();
+void __thiscall sub_4BC49B(unsigned int _this);
+struct Texture *__cdecl sub_4BC8D5();
+struct GUIButton *__cdecl sub_4BCA33();
+void __fastcall sub_4BCACC_bounties(signed int a1);
+signed int __cdecl sub_4BD8B5();
+bool __fastcall sub_4BDAAF(ItemGen *a1, int _2da_idx);
+void __cdecl sub_4BDB56_buy_skill____();
+struct FrameTableTxtLine *__thiscall texture_frame_table_txt_parser(const char *_this, FrameTableTxtLine *a2);
+struct FrameTableTxtLine *__thiscall frame_table_txt_parser(const char *pString, FrameTableTxtLine *a2);
+int __fastcall sub_4BE571(int a1, int *a2, int a3, int a4);
+void __cdecl ShowIntroVideo_and_LoadingScreen();
+unsigned int __thiscall GameOverMenu(void *ecx0);
+bool __thiscall BinkLockBuffer(struct _BINKBUF *_this);
+void __thiscall BinkUnlockBuffer(struct _BINKBUF *_this);
+void __cdecl loc_4C0D27(); // idb
+void __cdecl vis_nullsub_22(); // idb
+void __cdecl vis_nullsub_23(); // idb
+void __cdecl vis_loc_4C19F7(); // idb
+int __cdecl sr_sub_4D714C(struct stru315 *a1);
+int __cdecl sr_sub_4D71F8(struct stru315 *a1);
+void __cdecl sr_sub_4D754B(struct stru315 *a1, struct stru316 *a2);
+void __cdecl sr_sub_4D7630(struct stru315 *a1, struct stru316 *a2);
+void __cdecl sr_sub_4D76ED(struct stru315 *a1, struct stru316 *a2);
+void __cdecl sr_sub_4D77D2(struct stru315 *a1, struct stru316 *a2);
+void __cdecl sr_sub_4D789A(struct stru315 *a1, struct stru316 *a2);
+int __cdecl sub_4D798C(int a1, int a2, int a3, int a4);
+int __cdecl sub_4D79CF(int a1, int a2, int a3, int a4);
+int __cdecl sub_4D79FD(int a1, int a2, int a3, int a4);
+int __cdecl sub_4D7A10(int a1, int a2, int a3, int a4);
+int /*__usercall*/ sr_sub_4D72EC/*<eax>*/(int a1/*<ebp>*/);
+int /*__usercall*/ sr_sub_4D73DF/*<eax>*/(int a1/*<ebp>*/);
+signed int __fastcall SpawnRandomTreasure(struct MapInfo *a1, struct SpawnPointMM7 *a2);
+bool __fastcall DamageMonsterFromParty(signed int a1, unsigned int uActorID_Monster, struct Vec3_int_ *pVelocity);
+
+
+#define ErrD3D(hr) do {extern void ErrHR(HRESULT, const char *, const char *, const char *, int); ErrHR(hr, "Direct3D", __FUNCTION__, __FILE__, __LINE__);} while(0)
+
+
+namespace zlib
+{
+  int MemZip(void *dest, unsigned int *destLen, void *source, unsigned int sourceLen);
+  int MemUnzip(void *dest, unsigned int *destLen, const void *source, unsigned int sourceLen);
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/resource.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Might and Magic Trilogy.rc
+
+// Ñëåäóþùèå ñòàíäàðòíûå çíà÷åíèÿ äëÿ íîâûõ îáúåêòîâ
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru10.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,938 @@
+#include "stru10.h"
+#include "Render.h"
+#include "Indoor.h"
+#include "Game.h"
+#include "Party.h"
+
+#include "mm7_data.h"
+
+
+
+
+//----- (0049CE9E) --------------------------------------------------------
+void stru10::_49CE9E(BLVFace *pFace, RenderVertexSoft *a2, signed int a3, RenderVertexSoft *a4)
+{
+  char *v5; // eax@1
+  signed int v6; // edx@1
+  unsigned int v7; // eax@3
+  signed int v8; // ecx@11
+  signed int v9; // esi@11
+  RenderVertexSoft *v10; // edx@12
+  double v11; // st6@14
+  RenderVertexSoft *v12; // edx@19
+  signed int v13; // ecx@19
+  signed int v14; // esi@19
+  RenderVertexSoft *v15; // edi@20
+  double v16; // st6@22
+  signed int v17; // ecx@27
+  signed int v18; // edi@27
+  char *v19; // esi@28
+  double v20; // st6@30
+  signed int v21; // ecx@35
+  signed int v22; // edi@35
+  char *v23; // esi@36
+  double v24; // st7@38
+  signed int v25; // ecx@45
+  signed int v26; // esi@45
+  RenderVertexSoft *v27; // edx@46
+  double v28; // st6@48
+  signed int v29; // ecx@53
+  signed int v30; // esi@53
+  RenderVertexSoft *v31; // edi@54
+  double v32; // st6@56
+  signed int v33; // ecx@61
+  signed int v34; // edi@61
+  char *v35; // esi@62
+  double v36; // st6@64
+  signed int v37; // edi@69
+  char *v38; // esi@70
+  double v39; // st7@72
+  RenderVertexSoft *v40; // esi@77
+  signed int v41; // ecx@79
+  signed int v42; // esi@79
+  char *v43; // edx@80
+  double v44; // st6@82
+  RenderVertexSoft *v45; // eax@87
+  signed int v46; // ecx@87
+  signed int v47; // edi@87
+  char *v48; // esi@88
+  double v49; // st6@90
+  signed int v50; // ecx@96
+  signed int v51; // edi@96
+  char *v52; // esi@97
+  double v53; // st6@99
+  signed int v54; // ecx@105
+  signed int v55; // edi@105
+  char *v56; // esi@106
+  double v57; // st7@108
+  RenderVertexSoft a2a[64]; // [sp+0h] [bp-C18h]@1
+  float v59; // [sp+C00h] [bp-18h]@4
+  float v60; // [sp+C04h] [bp-14h]@9
+  float v61; // [sp+C08h] [bp-10h]@4
+  float v62; // [sp+C0Ch] [bp-Ch]@9
+  float v63; // [sp+C10h] [bp-8h]@4
+  float v64; // [sp+C14h] [bp-4h]@4
+  float a1a; // [sp+C20h] [bp+8h]@11
+  float a1b; // [sp+C20h] [bp+8h]@19
+  float a1c; // [sp+C20h] [bp+8h]@27
+  float a1d; // [sp+C20h] [bp+8h]@35
+  float a1e; // [sp+C20h] [bp+8h]@45
+  float a1f; // [sp+C20h] [bp+8h]@53
+  float a1g; // [sp+C20h] [bp+8h]@61
+  float a1h; // [sp+C20h] [bp+8h]@69
+  float a1i; // [sp+C20h] [bp+8h]@79
+  float a1j; // [sp+C20h] [bp+8h]@87
+  float a1k; // [sp+C20h] [bp+8h]@96
+  float a1l; // [sp+C20h] [bp+8h]@105
+
+  v5 = (char *)&a2a[0].flt_2C;
+  v6 = 64;
+  do
+  {
+    *(float *)v5 = 0.0;
+    v5 += 48;
+    --v6;
+  }
+  while ( v6 );
+  stru10::CalcPolygonBoundingBox(pFace, a2a);
+  v7 = pFace->uAttributes;
+  if ( v7 & 0x100 )
+  {
+    v63 = a2a[0].vWorldPosition.x;
+    v59 = a2a[2].vWorldPosition.x;
+    v61 = a2a[1].vWorldPosition.y;
+    v64 = a2a[3].vWorldPosition.y;
+    goto LABEL_10;
+  }
+  if ( v7 & 0x200 )
+  {
+    v63 = a2a[0].vWorldPosition.x;
+    v59 = a2a[2].vWorldPosition.x;
+  }
+  else
+  {
+    if ( !(v7 & 0x400) )
+      goto LABEL_10;
+    v61 = a2a[0].vWorldPosition.y;
+    v64 = a2a[2].vWorldPosition.y;
+  }
+  v62 = a2a[1].vWorldPosition.z;
+  v60 = a2a[3].vWorldPosition.z;
+LABEL_10:
+  if ( v7 & 0x100 )
+  {
+    v8 = -1;
+    a1a = 3.4028235e38;
+    v9 = 0;
+    if ( a3 > 0 )
+    {
+      v10 = a2;
+      do
+      {
+        if ( v10->vWorldPosition.x <= (double)v63 )
+          v11 = v63 - v10->vWorldPosition.x;
+        else
+          v11 = v10->vWorldPosition.x - v63;
+        if ( v11 < a1a )
+        {
+          a1a = v11;
+          v8 = v9;
+        }
+        ++v9;
+        ++v10;
+      }
+      while ( v9 < a3 );
+    }
+    v12 = a4;
+    a1b = 3.4028235e38;
+    memcpy(a4, &a2[v8], 0x30u);
+    v13 = -1;
+    v14 = 0;
+    if ( a3 > 0 )
+    {
+      v15 = a2;
+      do
+      {
+        if ( v15->vWorldPosition.x <= (double)v59 )
+          v16 = v59 - v15->vWorldPosition.x;
+        else
+          v16 = v15->vWorldPosition.x - v59;
+        if ( v16 < a1b )
+        {
+          a1b = v16;
+          v13 = v14;
+        }
+        ++v14;
+        ++v15;
+      }
+      while ( v14 < a3 );
+    }
+    a1c = 3.4028235e38;
+    memcpy(&a4[2], &a2[v13], sizeof(a4[2]));
+    v17 = -1;
+    v18 = 0;
+    if ( a3 > 0 )
+    {
+      v19 = (char *)&a2->vWorldPosition.y;
+      do
+      {
+        if ( *(float *)v19 <= (double)v61 )
+          v20 = v61 - *(float *)v19;
+        else
+          v20 = *(float *)v19 - v61;
+        if ( v20 < a1c )
+        {
+          a1c = v20;
+          v17 = v18;
+        }
+        ++v18;
+        v19 += 48;
+      }
+      while ( v18 < a3 );
+    }
+    a1d = 3.4028235e38;
+    memcpy(&a4[1], &a2[v17], sizeof(a4[1]));
+    v21 = -1;
+    v22 = 0;
+    if ( a3 > 0 )
+    {
+      v23 = (char *)&a2->vWorldPosition.y;
+      do
+      {
+        if ( *(float *)v23 <= (double)v64 )
+          v24 = v64 - *(float *)v23;
+        else
+          v24 = *(float *)v23 - v64;
+        if ( v24 < a1d )
+        {
+          a1d = v24;
+          v21 = v22;
+        }
+        ++v22;
+        v23 += 48;
+      }
+      while ( v22 < a3 );
+    }
+LABEL_77:
+    v40 = &a2[v21];
+    goto LABEL_115;
+  }
+  if ( v7 & 0x200 )
+  {
+    v25 = -1;
+    a1e = 3.4028235e38;
+    v26 = 0;
+    if ( a3 > 0 )
+    {
+      v27 = a2;
+      do
+      {
+        if ( v27->vWorldPosition.x <= (double)v63 )
+          v28 = v63 - v27->vWorldPosition.x;
+        else
+          v28 = v27->vWorldPosition.x - v63;
+        if ( v28 < a1e )
+        {
+          a1e = v28;
+          v25 = v26;
+        }
+        ++v26;
+        ++v27;
+      }
+      while ( v26 < a3 );
+    }
+    v12 = a4;
+    a1f = 3.4028235e38;
+    memcpy(a4, &a2[v25], 0x30u);
+    v29 = -1;
+    v30 = 0;
+    if ( a3 > 0 )
+    {
+      v31 = a2;
+      do
+      {
+        if ( v31->vWorldPosition.x <= (double)v59 )
+          v32 = v59 - v31->vWorldPosition.x;
+        else
+          v32 = v31->vWorldPosition.x - v59;
+        if ( v32 < a1f )
+        {
+          a1f = v32;
+          v29 = v30;
+        }
+        ++v30;
+        ++v31;
+      }
+      while ( v30 < a3 );
+    }
+    a1g = 3.4028235e38;
+    memcpy(&a4[2], &a2[v29], sizeof(a4[2]));
+    v33 = -1;
+    v34 = 0;
+    if ( a3 > 0 )
+    {
+      v35 = (char *)&a2->vWorldPosition.z;
+      do
+      {
+        if ( *(float *)v35 <= (double)v62 )
+          v36 = v62 - *(float *)v35;
+        else
+          v36 = *(float *)v35 - v62;
+        if ( v36 < a1g )
+        {
+          a1g = v36;
+          v33 = v34;
+        }
+        ++v34;
+        v35 += 48;
+      }
+      while ( v34 < a3 );
+    }
+    a1h = 3.4028235e38;
+    memcpy(&a4[1], &a2[v33], sizeof(a4[1]));
+    v21 = -1;
+    v37 = 0;
+    if ( a3 > 0 )
+    {
+      v38 = (char *)&a2->vWorldPosition.z;
+      do
+      {
+        if ( *(float *)v38 <= (double)v60 )
+          v39 = v60 - *(float *)v38;
+        else
+          v39 = *(float *)v38 - v60;
+        if ( v39 < a1h )
+        {
+          a1h = v39;
+          v21 = v37;
+        }
+        ++v37;
+        v38 += 48;
+      }
+      while ( v37 < a3 );
+    }
+    goto LABEL_77;
+  }
+  if ( !(v7 & 0x400) )
+    return;
+  v41 = -1;
+  a1i = 3.4028235e38;
+  v42 = 0;
+  if ( a3 > 0 )
+  {
+    v43 = (char *)&a2->vWorldPosition.y;
+    do
+    {
+      if ( *(float *)v43 <= (double)v61 )
+        v44 = v61 - *(float *)v43;
+      else
+        v44 = *(float *)v43 - v61;
+      if ( v44 < a1i )
+      {
+        a1i = v44;
+        v41 = v42;
+      }
+      ++v42;
+      v43 += 48;
+    }
+    while ( v42 < a3 );
+  }
+  v45 = a2;
+  v12 = a4;
+  a1j = 3.4028235e38;
+  memcpy(a4, &a2[v41], 0x30u);
+  v46 = -1;
+  v47 = 0;
+  if ( a3 > 0 )
+  {
+    v48 = (char *)&a2->vWorldPosition.y;
+    do
+    {
+      if ( *(float *)v48 <= (double)v64 )
+        v49 = v64 - *(float *)v48;
+      else
+        v49 = *(float *)v48 - v64;
+      if ( v49 < a1j )
+      {
+        a1j = v49;
+        v46 = v47;
+      }
+      ++v47;
+      v48 += 48;
+    }
+    while ( v47 < a3 );
+    v45 = a2;
+  }
+  a1k = 3.4028235e38;
+  memcpy(&a4[2], &v45[v46], sizeof(a4[2]));
+  v50 = -1;
+  v51 = 0;
+  if ( a3 > 0 )
+  {
+    v52 = (char *)&v45->vWorldPosition.z;
+    do
+    {
+      if ( *(float *)v52 <= (double)v62 )
+        v53 = v62 - *(float *)v52;
+      else
+        v53 = *(float *)v52 - v62;
+      if ( v53 < a1k )
+      {
+        a1k = v53;
+        v50 = v51;
+      }
+      ++v51;
+      v52 += 48;
+    }
+    while ( v51 < a3 );
+    v45 = a2;
+  }
+  a1l = 3.4028235e38;
+  memcpy(&a4[1], &v45[v50], sizeof(a4[1]));
+  v54 = -1;
+  v55 = 0;
+  if ( a3 > 0 )
+  {
+    v56 = (char *)&v45->vWorldPosition.z;
+    do
+    {
+      if ( *(float *)v56 <= (double)v60 )
+        v57 = v60 - *(float *)v56;
+      else
+        v57 = *(float *)v56 - v60;
+      if ( v57 < a1l )
+      {
+        a1l = v57;
+        v54 = v55;
+      }
+      ++v55;
+      v56 += 48;
+    }
+    while ( v55 < a3 );
+    v45 = a2;
+  }
+  v40 = &v45[v54];
+LABEL_115:
+  memcpy(&v12[3], v40, sizeof(v12[3]));
+}
+
+//----- (0049D379) --------------------------------------------------------
+void stru10::CalcPolygonBoundingBox(BLVFace *pFace, RenderVertexSoft *pOutVertices)
+{
+  struct
+  {
+    float x;
+    float y;
+    int c;
+  } v46[40]; //[sp+0C];
+
+  if (pFace->uAttributes & 0x0100)
+  {
+    for (uint i = 0; i < pFace->uNumVertices; ++i)
+    {
+      v46[i].x = pIndoor->pVertices[pFace->pVertexIDs[i]].x + pFace->pXInterceptDisplacements[i];
+      v46[i].y = pIndoor->pVertices[pFace->pVertexIDs[i]].y + pFace->pYInterceptDisplacements[i];
+      v46[i].c = i;
+    }
+  }
+  if (pFace->uAttributes & 0x0200)
+  {
+    for (uint i = 0; i < pFace->uNumVertices; ++i)
+    {
+      v46[i].x = pIndoor->pVertices[pFace->pVertexIDs[i]].x + pFace->pXInterceptDisplacements[i];
+      v46[i].y = pIndoor->pVertices[pFace->pVertexIDs[i]].y + pFace->pZInterceptDisplacements[i];
+      v46[i].c = i;
+    }
+  }
+  if (pFace->uAttributes & 0x0400)
+  {
+    for (uint i = 0; i < pFace->uNumVertices; ++i)
+    {
+      v46[i].x = pIndoor->pVertices[pFace->pVertexIDs[i]].x + pFace->pYInterceptDisplacements[i];
+      v46[i].y = pIndoor->pVertices[pFace->pVertexIDs[i]].y + pFace->pZInterceptDisplacements[i];
+      v46[i].c = i;
+    }
+  }
+
+  float x_min = FLT_MAX;
+  uint  x_min_idx = 0;
+
+  float x_max = FLT_MIN;
+  uint  x_max_idx = 0;
+
+  float y_min = FLT_MAX;
+  uint  y_min_idx = 0;
+
+  float y_max = FLT_MIN;
+  uint  y_max_idx = 0;
+
+  for (uint i = 0; i < pFace->uNumVertices; ++i)
+  {
+    if (v46[i].x < x_min)
+    {
+      x_min = v46[i].x;
+      x_min_idx = v46[i].c;
+    }
+    if (v46[i].x > x_max)
+    {
+      x_max = v46[i].x;
+      x_max_idx = v46[i].c;
+    }
+
+    if (v46[i].y < y_min)
+    {
+      y_min = v46[i].y;
+      y_min_idx = v46[i].c;
+    }
+    if (v46[i].y > y_max)
+    {
+      y_max = v46[i].y;
+      y_max_idx = v46[i].c;
+    }
+  }
+
+
+
+  auto p1 = &pIndoor->pVertices[pFace->pVertexIDs[x_min_idx]];
+  RenderVertexSoft v1; // [sp+30Ch] [bp-54h]@24
+  v1.vWorldPosition.x = (float)p1->x;
+  v1.vWorldPosition.y = (float)p1->y;
+  v1.vWorldPosition.z = (float)p1->z;
+  memcpy(pOutVertices + 0, &v1, sizeof(RenderVertexSoft));
+
+  auto p2 = &pIndoor->pVertices[pFace->pVertexIDs[y_min_idx]];
+  RenderVertexSoft v2; // [sp+30Ch] [bp-54h]@24
+  v2.vWorldPosition.x = (float)p2->x;
+  v2.vWorldPosition.y = (float)p2->y;
+  v2.vWorldPosition.z = (float)p2->z;
+  memcpy(pOutVertices + 1, &v2, sizeof(RenderVertexSoft));
+
+  auto p3 = &pIndoor->pVertices[pFace->pVertexIDs[x_max_idx]];
+  RenderVertexSoft v3; // [sp+30Ch] [bp-54h]@24
+  v3.vWorldPosition.x = (float)p3->x;
+  v3.vWorldPosition.y = (float)p3->y;
+  v3.vWorldPosition.z = (float)p3->z;
+  memcpy(pOutVertices + 2, &v3, sizeof(RenderVertexSoft));
+
+  auto p4 = &pIndoor->pVertices[pFace->pVertexIDs[y_max_idx]];
+  RenderVertexSoft v4; // [sp+30Ch] [bp-54h]@24
+  v4.vWorldPosition.x = (double)p4->x;
+  v4.vWorldPosition.y = (double)p4->y;
+  v4.vWorldPosition.z = (double)p4->z;
+  memcpy(pOutVertices + 3, &v4, sizeof(RenderVertexSoft));
+}
+
+
+//----- (0049C9E3) --------------------------------------------------------
+bool stru10::_49C9E3(BLVFace *pFace, RenderVertexSoft *pFaceBounding, unsigned int uNumVertices, RenderVertexSoft *arg0)
+{
+  //IndoorCameraD3D *v6; // edi@1
+  //PolygonType v7; // al@1
+  //unsigned int v8; // edx@7
+  //char v10; // zf@10
+  //float v13; // ST14_4@20
+  //stru10 *v15; // ecx@21
+  //RenderVertexSoft *v16; // ST0C_4@21
+  //bool result; // eax@21
+  //float v18; // ST14_4@24
+  //stru10 *v19; // edi@29
+  //float v20; // ST14_4@30
+  //float v21; // ST14_4@30
+  //float v22; // ST14_4@30
+  //float v23; // ST14_4@30
+  //float v24; // ST14_4@31
+  //RenderVertexSoft v25; // [sp+10h] [bp-90h]@24
+  //RenderVertexSoft v26; // [sp+40h] [bp-60h]@20
+  //IndoorCameraD3D *thisa; // [sp+70h] [bp-30h]@1
+  //stru10 *v31; // [sp+84h] [bp-1Ch]@1
+  float v32; // [sp+88h] [bp-18h]@8
+  Vec3_float_ a1; // [sp+8Ch] [bp-14h]@1
+  float v35; // [sp+9Ch] [bp-4h]@8
+
+  //auto a3 = pFace;
+  //auto arg4 = pFaceBounding;
+
+  //_ESI = a3;
+  //v31 = this;
+  //v6 = pGame->pIndoorCameraD3D;
+  //v7 = a3->uPolygonType;
+
+  a1.x = 0.0f;
+  a1.y = 0.0f;
+  a1.z = 0.0f;
+
+  float var_28;
+  float var_24;
+  if (pFace->uPolygonType == POLYGON_VerticalWall)
+  {
+    a1.x = -pFace->pFacePlane.vNormal.y;
+    a1.y = pFace->pFacePlane.vNormal.x;
+    a1.z = 0.0f;
+    a1.Normalize();
+
+    var_28 = 0;
+    var_24 = 1;
+  }
+  else if (pFace->uPolygonType == POLYGON_Floor ||
+           pFace->uPolygonType == POLYGON_Ceiling)
+  {
+    a1.x = 1;
+    a1.y = 0;
+    a1.z = 0.0f;
+
+    var_28 = 1;
+    var_24 = 0;
+  }
+
+
+  float arg_4;
+  float var_18;
+  float var_4;
+  float a3;
+  float var_8;
+  //v8 = _ESI->uAttributes;
+  //_ECX = pFaceBounding;
+  //__asm { fld     0.5 }
+  if (pFace->uAttributes & 0x0100)
+  {
+    arg_4 = (pFaceBounding[0].vWorldPosition.x + pFaceBounding[2].vWorldPosition.x) / 2;
+    var_18 = (pFaceBounding[3].vWorldPosition.y + pFaceBounding[1].vWorldPosition.y) / 2;
+    var_4 = (pFaceBounding[0].vWorldPosition.z + pFaceBounding[2].vWorldPosition.z) / 2;
+
+    a3 = arg_4 - pFaceBounding[0].vWorldPosition.x;
+    var_8 = var_18 - pFaceBounding[1].vWorldPosition.y;
+  }
+  if (pFace->uAttributes & 0x0200)
+  {
+    arg_4 = (pFaceBounding[0].vWorldPosition.x + pFaceBounding[2].vWorldPosition.x) / 2;
+    var_18 = (pFaceBounding[0].vWorldPosition.y + pFaceBounding[2].vWorldPosition.y) / 2;
+    var_4 = (pFaceBounding[1].vWorldPosition.z + pFaceBounding[3].vWorldPosition.z) / 2;
+
+    a3 = arg_4 - pFaceBounding[0].vWorldPosition.x;
+    var_8 = var_4 - pFaceBounding[1].vWorldPosition.z;
+
+    if (pFace->uPolygonType == POLYGON_VerticalWall)
+      a3 /= a1.x;
+  }
+  if (pFace->uAttributes & 0x0400)
+  {
+    arg_4 = (pFaceBounding[0].vWorldPosition.x + pFaceBounding[2].vWorldPosition.x) / 2;
+    var_18 = (pFaceBounding[0].vWorldPosition.y + pFaceBounding[2].vWorldPosition.y) / 2;
+    var_4 = (pFaceBounding[1].vWorldPosition.z + pFaceBounding[3].vWorldPosition.z) / 2;
+
+    a3 = var_18 - pFaceBounding[0].vWorldPosition.y;
+    var_8 = var_4 - pFaceBounding[1].vWorldPosition.z;
+                                       // [0.5]
+    if (pFace->uPolygonType == POLYGON_VerticalWall)
+    {
+      if (a1.x != 1.0f)
+        a3 /= a1.y;
+    }
+  }
+
+
+  if ( byte_4D864C && pGame->uFlags & 8 )
+  {
+    RenderVertexSoft v26; // [sp+40h] [bp-60h]@20
+    v26.vWorldPosition.x = arg_4;
+    v26.vWorldPosition.y = v32;
+    v26.vWorldPosition.z = v35;
+
+    pGame->pIndoorCameraD3D->do_draw_debug_line_sw(pFaceBounding, 0xFF00u, &v26, 0xFF0000u, 0, 0);
+  }
+
+  //_EBX = arg0;
+  //v15 = v31;
+  //v16 = arg0;
+  float var_20 = var_8 * var_24;
+  var_8 = a3 * a1.z;
+  float arg_0 = var_8 + var_4;
+
+  arg0[0].vWorldPosition.x = arg_4 - a3 * a1.x + var_8 * flt_4D84E8;
+  arg0[0].vWorldPosition.y = var_18 - a3 * a1.y + var_8 * var_28;
+  arg0[0].vWorldPosition.z = var_4 - var_8 + var_8 * var_24;
+  arg0[1].vWorldPosition.x = arg_4 - a3 * a1.x - var_8 * flt_4D84E8;
+  arg0[1].vWorldPosition.y = var_18 - a3 * a1.y - var_8 * var_28;
+  arg0[1].vWorldPosition.z = (var_4 - var_8) - var_8 * var_24;
+  arg0[2].vWorldPosition.x = a3 * a1.x + arg_4 - var_8 * flt_4D84E8;
+  arg0[2].vWorldPosition.y = a3 * a1.y + var_18 - var_8 * var_28;
+  arg0[2].vWorldPosition.z = var_8 + var_4 - var_20;
+  arg0[3].vWorldPosition.x = (a3 * a1.x + arg_4) + var_8 * flt_4D84E8;
+  arg0[3].vWorldPosition.y = a3 * a1.y + var_18 + var_8 * var_28;
+  arg0[3].vWorldPosition.z = arg_0 + var_20;
+
+  a3 = (var_4 - var_8);
+  a3 = (a3 * a1.x + arg_4);
+
+  a1.x = 0.0f;
+  a1.y = 0.0f;
+  a1.z = 0.0f;
+
+  if (!_49C8DC(arg0, &a1, &a3))
+    return false;
+
+
+  if ( byte_4D864C )
+  {
+      if ( pGame->uFlags & 8 )
+      {
+        RenderVertexSoft v25; // [sp+10h] [bp-90h]@20
+        RenderVertexSoft v26; // [sp+40h] [bp-60h]@20
+
+        v25.vWorldPosition.x = arg_4;
+        v25.vWorldPosition.y = v32;
+        v25.vWorldPosition.z = v35;
+
+        v26.vWorldPosition.x = a1.x * 30.0f;
+        v26.vWorldPosition.y = a1.y * 30.0f;
+        v26.vWorldPosition.z = a1.z * 30.0f;
+
+        pGame->pIndoorCameraD3D->do_draw_debug_line_sw(&v25, 0xFFFFFFFFu, &v26, 0xFFFF00u, 0, 0);
+      }
+  }
+
+
+  RenderVertexSoft v25; // [sp+10h] [bp-90h]@20
+  memcpy(&v25, arg0, sizeof(RenderVertexSoft));
+
+  float _dp = (v25.vWorldPosition.x - pBLVRenderParams->vPartyPos.x) * a1.x +
+              (v25.vWorldPosition.y - pBLVRenderParams->vPartyPos.y) * a1.y +
+              (v25.vWorldPosition.z - pBLVRenderParams->vPartyPos.z) * a1.z;
+  if (fabs(_dp) < 1e-6f)
+  {
+    memcpy(&v25, arg0 + 1, sizeof(RenderVertexSoft));
+    memcpy(arg0 + 1, arg0 + 3, sizeof(RenderVertexSoft));
+    memcpy(arg0 + 3, &v25, sizeof(RenderVertexSoft));
+  }
+
+    if ( byte_4D864C && pGame->uFlags & 8 )
+    {
+      RenderVertexSoft v26; // [sp+40h] [bp-60h]@20
+      if ( !LOBYTE(field_4) )
+      {
+        v26.vWorldPosition.x = pParty->vPosition.x;
+        v26.vWorldPosition.y = pParty->vPosition.y;
+        v26.vWorldPosition.z = pParty->vPosition.z + pParty->sEyelevel;
+
+        pGame->pIndoorCameraD3D->do_draw_debug_line_sw(&v26, 0xFF0000u, arg0, 0xFF0000u, 0, 0);
+        pGame->pIndoorCameraD3D->do_draw_debug_line_sw(&v26, 0xFF00u, arg0 + 1, 0xFF00u, 0, 0);
+        pGame->pIndoorCameraD3D->do_draw_debug_line_sw(&v26, 0xFFu, arg0 + 2, 0xFFu, 0, 0);
+        pGame->pIndoorCameraD3D->do_draw_debug_line_sw(&v26, 0xFFFFFFu, arg0 + 3, 0xFFFFFFu, 0, 0);
+        LOBYTE(field_4) = 1;
+      }
+      pGame->pIndoorCameraD3D->debug_outline_sw(arg0, uNumVertices, 0x1EFF1Eu, 0.00019999999);
+    }
+  return true;
+}
+
+
+
+//----- (0049C5B0) --------------------------------------------------------
+stru10::stru10()
+{
+  LOBYTE(this->field_4) = 0;
+}
+
+//----- (0049C5BD) --------------------------------------------------------
+stru10::~stru10()
+{
+}
+
+//----- (0049C5DA) --------------------------------------------------------
+char stru10::_49C5DA(BLVFace *a2, RenderVertexSoft *a3, int *a4, IndoorCameraD3D_Vec4 *a5, RenderVertexSoft *a6)
+{
+  stru10 *v6; // edi@1
+  char *v7; // eax@1
+  signed int v8; // ecx@1
+  IndoorCameraD3D *v9; // esi@3
+  char result; // al@6
+  RenderVertexSoft a4a[4]; // [sp+Ch] [bp-C0h]@1
+
+  v6 = this;
+  v7 = (char *)&a4a[0].flt_2C;
+  v8 = 4;
+  do
+  {
+    *(float *)v7 = 0.0;
+    v7 += 48;
+    --v8;
+  }
+  while ( v8 );
+  v9 = pGame->pIndoorCameraD3D;
+  _49CE9E(a2, a3, *a4, a4a);
+  if ( byte_4D864C && pGame->uFlags & 8 )
+    pGame->pIndoorCameraD3D->debug_outline_sw(a4a, 4u, 0xFF1E1Eu, 0.000099999997);
+  result = _49C9E3(a2, a4a, 4u, a6);
+  if ( result )
+    result = _49C720(a6, a5);
+  return result;
+}
+// 4D864C: using guessed type char byte_4D864C;
+
+//----- (0049C681) --------------------------------------------------------
+char stru10::_49C681_DrawDebugStuff(BLVFace *pFace, IndoorCameraD3D_Vec4 *a3, RenderVertexSoft *pArrayOf4)
+{
+  RenderVertexSoft pBounding[4]; // [sp+Ch] [bp-C0h]@1
+
+  CalcPolygonBoundingBox(pFace, pBounding);
+  if ( byte_4D864C && pGame->uFlags & 8 )
+    pGame->pIndoorCameraD3D->debug_outline_sw(pBounding, 4, 0xFF1E1E, 0.000099999997);
+  if (_49C9E3(pFace, pBounding, 4, pArrayOf4))
+    return _49C720(pArrayOf4, a3);
+  return false;
+}
+// 4D864C: using guessed type char byte_4D864C;
+
+//----- (0049C720) --------------------------------------------------------
+char stru10::_49C720(RenderVertexSoft *a2, IndoorCameraD3D_Vec4 *a4)
+{
+  char result; // al@2
+  Vec3_float_ a3; // [sp+4h] [bp-34h]@1
+  float v5; // [sp+30h] [bp-8h]@1
+  stru10 *thisa; // [sp+34h] [bp-4h]@1
+
+  v5 = 0.0;
+  a3.x = (double)pBLVRenderParams->vPartyPos.x;
+  a3.y = (double)pBLVRenderParams->vPartyPos.y;
+  thisa = this;
+  a3.z = (double)pBLVRenderParams->vPartyPos.z;
+  if ( _49C7C5(a2, a2 + 1, &a3, a4)
+    && _49C7C5(a2 + 1, a2 + 2, &a3, a4 + 1)
+    && _49C7C5(a2 + 2, a2 + 3, &a3, a4 + 2) )
+    result = _49C7C5(a2 + 3, a2, &a3, a4 + 3) != 0;
+  else
+    result = 0;
+  return result;
+}
+
+//----- (0049C7C5) --------------------------------------------------------
+bool stru10::_49C7C5(RenderVertexSoft *a1, RenderVertexSoft *a2, Vec3_float_ *a3, IndoorCameraD3D_Vec4 *a4)
+{
+  double v5; // st7@1
+  double v6; // st6@1
+  double v7; // st5@1
+  Vec3_float_ *result; // eax@1
+  __int16 v9; // fps@3
+  char v10; // c0@3
+  char v11; // c2@3
+  char v12; // c3@3
+  float v13; // ecx@5
+  double v14; // st7@5
+  double v15; // st6@5
+  Vec3_float_ v1; // [sp+4h] [bp-48h]@1
+  Vec3_float_ v2; // [sp+10h] [bp-3Ch]@1
+  float v18; // [sp+20h] [bp-2Ch]@1
+  float v19; // [sp+24h] [bp-28h]@1
+  Vec3_float_ v20; // [sp+28h] [bp-24h]@1
+  Vec3_float_ v21; // [sp+34h] [bp-18h]@1
+  Vec3_float_ a1a; // [sp+40h] [bp-Ch]@1
+
+  a1a.x = 0.0;
+  a1a.y = 0.0;
+  a1a.z = 0.0;
+  v21.x = a3->x;
+  v21.y = a3->y;
+  v21.z = a3->z;
+  v5 = a1->vWorldPosition.x;
+  v6 = a1->vWorldPosition.y;
+  v2.z = a1->vWorldPosition.z;
+  v7 = a2->vWorldPosition.x;
+  v18 = a2->vWorldPosition.y;
+  v19 = a2->vWorldPosition.z;
+  v20.x = v5 - v21.x;
+  v20.y = v6 - v21.y;
+  v20.z = v2.z - v21.z;
+  LODWORD(v1.x) = (int)v20.x;
+  v1.y = v20.y;
+  v1.z = v20.z;
+  v20.x = v7 - v5;
+  v20.y = v18 - v6;
+  v20.z = v19 - v2.z;
+  result = Vec3_float_::Cross(&v1, &v2, v20.x, v20.y, v20.z);
+  a1a.x = result->x;
+  a1a.y = result->y;
+  a1a.z = result->z;
+  if ( a1a.x != 0.0
+    || a1a.y != 0.0
+    || (/*UNDEF(v9),*/ v10 = a1a.z < 0.0, v11 = 0, v12 = a1a.z == 0.0, BYTE1(result) = HIBYTE(v9), a1a.z != 0.0) )
+  {
+    a1a.Normalize();
+    result = (Vec3_float_ *)a4;
+    v13 = a1a.y;
+    a4->x = a1a.x;
+    v14 = v21.z * a1a.z;
+    v15 = v21.y * a1a.y;
+    a4->y = v13;
+    a4->z = a1a.z;
+    a4->dot = v14 + v15 + v21.x * a1a.x;
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+    LOBYTE(result) = 0;
+  }
+  return (bool)result;
+}
+
+//----- (0049C8DC) --------------------------------------------------------
+bool stru10::_49C8DC(RenderVertexSoft *arg0, Vec3_float_ *a2, float *a3)
+{
+  double v4; // st7@1
+  double v5; // st6@1
+  double v6; // st5@1
+  Vec3_float_ *result; // eax@1
+  __int16 v8; // fps@3
+  char v9; // c0@3
+  char v10; // c2@3
+  char v11; // c3@3
+  float v12; // ecx@5
+  double v13; // st7@5
+  double v14; // st6@5
+  Vec3_float_ v1; // [sp+8h] [bp-3Ch]@1
+  Vec3_float_ v2; // [sp+14h] [bp-30h]@1
+  float v17; // [sp+24h] [bp-20h]@1
+  float v18; // [sp+28h] [bp-1Ch]@1
+  float v19; // [sp+2Ch] [bp-18h]@1
+  float v20; // [sp+30h] [bp-14h]@1
+  float v21; // [sp+34h] [bp-10h]@1
+  Vec3_float_ a1; // [sp+38h] [bp-Ch]@1
+
+  v19 = arg0->vWorldPosition.x;
+  v20 = arg0->vWorldPosition.y;
+  v21 = arg0->vWorldPosition.z;
+  v4 = arg0[1].vWorldPosition.x;
+  v5 = arg0[1].vWorldPosition.y;
+  v2.z = arg0[1].vWorldPosition.z;
+  v6 = arg0[2].vWorldPosition.x;
+  v17 = arg0[2].vWorldPosition.y;
+  v18 = arg0[2].vWorldPosition.z;
+  a1.x = v4 - v19;
+  a1.y = v5 - v20;
+  a1.z = v2.z - v21;
+  LODWORD(v1.x) = (int)a1.x;
+  v1.y = a1.y;
+  v1.z = a1.z;
+  a1.x = v6 - v4;
+  a1.y = v17 - v5;
+  a1.z = v18 - v2.z;
+  result = Vec3_float_::Cross(&v1, &v2, a1.x, a1.y, a1.z);
+  a1.x = result->x;
+  a1.y = result->y;
+  a1.z = result->z;
+  if ( a1.x != 0.0
+    || a1.y != 0.0
+    || (/*UNDEF(v8),*/ v9 = a1.z < 0.0, v10 = 0, v11 = a1.z == 0.0, /*BYTE1(result) = HIBYTE(v8),*/ a1.z != 0.0) )
+  {
+    a1.Normalize();
+    v12 = a1.y;
+    a2->x = a1.x;
+    v13 = v21 * a1.z;
+    v14 = v20 * a1.y;
+    a2->y = v12;
+    a2->z = a1.z;
+    result = (Vec3_float_ *)a3;
+    *a3 = -(v13 + v14 + v19 * a1.x);
+    return true;
+  }
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru10.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,23 @@
+#pragma once
+
+
+/*  127 */
+#pragma pack(push, 1)
+struct stru10
+{
+  stru10();
+  virtual ~stru10();
+  char _49C5DA(struct BLVFace *a2, struct RenderVertexSoft *a3, int *a4, struct IndoorCameraD3D_Vec4 *a5, struct RenderVertexSoft *a6);
+  char _49C681_DrawDebugStuff(struct BLVFace *pFace, struct IndoorCameraD3D_Vec4 *a3, struct RenderVertexSoft *pArrayOf4);
+  char _49C720(struct RenderVertexSoft *a2, struct IndoorCameraD3D_Vec4 *a4);
+  bool _49C7C5(struct RenderVertexSoft *a1, struct RenderVertexSoft *a2, struct Vec3_float_ *a3, struct IndoorCameraD3D_Vec4 *a4);
+  bool _49C8DC(struct RenderVertexSoft *arg0, struct Vec3_float_ *a2, float *a3);
+  bool _49C9E3(struct BLVFace *a3, struct RenderVertexSoft *arg4, unsigned int uNumVertices, struct RenderVertexSoft *arg0);
+  void CalcPolygonBoundingBox(struct BLVFace *pFace, struct RenderVertexSoft pOutVertices[4]);
+  void _49CE9E(struct BLVFace *pFace, struct RenderVertexSoft *a2, signed int a3, RenderVertexSoft *a4);
+
+
+  void (__thiscall ***vdestructor_ptr)(stru10 *, bool);
+  int field_4;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru11.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,89 @@
+#pragma once
+
+
+/*  128 */
+#pragma pack(push, 1)
+struct stru11
+{
+  //----- (00438526) --------------------------------------------------------
+  stru11()
+  {
+  stru11 *v1; // esi@1
+  signed int v2; // eax@1
+  char *v3; // edx@1
+
+  v1 = this;
+  v2 = 0;
+  this->cpuid_00000000_eax_numops = 0;
+  this->cpuid_00000001_eax = 0;
+  this->cpuid_00000001_edx = 0;
+  this->field_38 = 0;
+  this->field_3C = 0;
+  this->cpuid_80000000_edx = 0;
+  this->cpuid_80000001_eax = 0;
+  this->cpuid_80000001_edx = 0;
+  this->cpuid_80000005_ebx = 0;
+  this->cpuid_80000005_ecx = 0;
+  this->cpuid_80000005_edx = 0;
+  this->cpuid_80000006_ecx = 0;
+  this->field_AC = 0;
+  this->uProcessorManufacturer = 0;
+  LOBYTE(this->cpuid_80000002_registers2[0]) = 0;
+  v3 = (char *)&this->cpuid_00000002_eax;
+  do
+  {
+    if ( v2 < 3 )
+      *((int *)v3 - 9) = 0;
+    if ( v2 < 4 )
+      *(int *)v3 = 0;
+    if ( v2 < 12 )
+      *((int *)v3 + 17) = 0;
+    if ( v2 < 13 )
+      this->pCPUString[v2] = 0;
+    if ( v2 < 30 )
+      *((char *)this->field_40 + v2) = 0;
+    *((char *)&this->cpuid_80000002_registers2[0] + v2++ + 1) = 0;
+    v3 += 4;
+  }
+  while ( v2 < 48 );
+  CheckCPU();
+  }
+
+  void CheckCPU();
+  void RunCPUID();
+  void RunCPUID_op1();
+  void RunCPUID_op2();
+  void RunCPUID_ext2_3_4();
+
+  int cpuid_00000000_eax_numops;
+  int cpuid_00000000_ebx_vendorstr1;
+  int cpuid_00000000_edx_vendorstr2;
+  int cpuid_00000000_ecx_vendorstr3;
+  char pCPUString[16];
+  int cpuid_00000001_eax;
+  int cpuid_00000001_edx;
+  int cpuid_00000002_eax;
+  int cpuid_00000002_ebx;
+  int cpuid_00000002_ecx;
+  int cpuid_00000002_edx;
+  int field_38;
+  int field_3C;
+  int field_40[8];
+  int cpuid_80000000_edx;
+  int cpuid_80000001_eax;
+  int cpuid_80000001_edx;
+  int cpuid_80000002_registers[4];
+  int cpuid_80000003_registers[4];
+  int cpuid_80000004_registers[4];
+  int cpuid_80000005_ebx;
+  int cpuid_80000005_ecx;
+  int cpuid_80000005_edx;
+  int cpuid_80000006_ecx;
+  int field_AC;
+  int uProcessorManufacturer;
+  int cpuid_80000002_registers2[4];
+  int cpuid_80000003_registers2[4];
+  int cpuid_80000004_registers2[4];
+  int field_E4;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru12.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,37 @@
+#pragma once
+
+
+/*  130 */
+#pragma pack(push, 1)
+struct stru12_MemoryBlock
+{
+  stru12_MemoryBlock(int a2);
+  ~stru12_MemoryBlock();
+  
+
+  void *pAlignedBlock;
+  void *pBlockBase;
+};
+#pragma pack(pop)
+
+/*  129 */
+#pragma pack(push, 1)
+struct stru12
+{
+   stru12(stru11 *pStru11);
+  ~stru12();
+
+  void _4898E6();
+
+  void (__thiscall *vdestructor_ptr)(stru12 *);
+  int field_4[16];
+  int field_44;
+  int field_48;
+  int field_4C;
+  int field_50;
+  int field_54;
+  int field_58;
+  stru12_MemoryBlock *pMemBlocks[12];
+  int field_8C;
+};
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru123.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,12 @@
+#pragma once
+
+
+/*   62 */
+#pragma pack(push, 1)
+struct stru123
+{
+  char field_0[75];
+  char _decor_events[125];
+};
+#pragma pack(pop)
+extern stru123 stru_5E4C90;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru157.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,19 @@
+#pragma once
+
+
+/*  150 */
+#pragma pack(push, 1)
+struct stru157
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+};
+#pragma pack(pop)
+extern stru157 stru_F93E1C; // weak
+extern stru157 stru_F93E30; // weak
+extern stru157 a5; // idb
+extern stru157 a4; // idb
+extern stru157 a3; // idb
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru159.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,15 @@
+#pragma once
+
+
+
+/*  152 */
+#pragma pack(push, 1)
+struct stru159
+{
+  char *field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+};
+#pragma pack(pop)
+extern stru159 pAnimatedRooms[196];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru160.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,26 @@
+#pragma once
+
+
+/*  153 */
+#pragma pack(push, 1)
+struct stru160
+{
+  inline stru160() {}
+  inline stru160(float a, float b, float c): field_0(a), field_4(b), field_8(c) {}
+
+  float field_0;
+  float field_4;
+  float field_8;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct stru16x: public stru160
+{
+  float field_C;
+};
+#pragma pack(pop)
+
+extern stru160 array_4EB8B8[66];
+extern stru160 array_4EBBD0[128];
+extern __int32 array_4EBBD0_x[128*3];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru176.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,25 @@
+#pragma once
+
+
+/*  169 */
+#pragma pack(push, 1)
+struct stru176
+{
+  int field_0;
+  int field_4;
+  __int16 field_8;
+  __int16 field_A;
+  __int16 field_C;
+  __int16 field_E;
+  __int16 field_10;
+  __int16 field_12;
+  __int16 field_14;
+  __int16 field_16;
+  __int16 field_18;
+  __int16 field_1A;
+  __int16 field_1C;
+  __int16 field_1E;
+};
+#pragma pack(pop)
+extern stru176 array_5B5928[100];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru179.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,12 @@
+#pragma once
+
+
+/*  172 */
+#pragma pack(push, 1)
+struct stru179
+{
+  int field_0[1000];
+};
+#pragma pack(pop)
+
+extern struct stru179 *pStru179;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru220.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,14 @@
+#pragma once
+
+
+
+/*  210 */
+#pragma pack(push, 1)
+struct stru220
+{
+  __int16 field_0;//char field_0;
+  //char field_1;
+  __int16 distance;
+};
+#pragma pack(pop)
+extern stru220 stru_76E5C8[16384];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru272.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,57 @@
+#pragma once
+
+
+
+/*  270 */
+#pragma pack(push, 1)
+struct stru272_stru0
+{
+  int _40DFFE();
+  int _40E01A(int a2);
+  int _40E0F5(char a2, char a3);
+  int _40E133();
+  int _40E2A7();
+
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+  int field_1C;
+  int field_20;
+  int field_24;
+  float field_28;
+  float field_2C;
+  float field_30;
+  int field_34;
+  int field_38;
+  int field_3C;
+  int field_40;
+  int field_44;
+  int field_48;
+  int field_4C;
+  int field_50;
+  int field_54;
+  char field_58;
+  char field_59;
+  char field_5A;
+  char field_5B;
+};
+#pragma pack(pop)
+
+
+/*  266 */
+#pragma pack(push, 1)
+struct stru272
+{
+  void _40DFD1();
+
+  struct stru272_stru0 *ptr_0;
+  char field_4[4264];
+};
+#pragma pack(pop)
+
+
+extern stru272 array_4FAC10[10];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru277.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,39 @@
+#pragma once
+
+
+
+/*  271 */
+#pragma pack(push, 1)
+struct stru277
+{
+  //----- (00426987) --------------------------------------------------------
+  inline stru277()
+  {
+  this->field_8 = 0;
+  this->spellnum = 0;
+  this->field_6 = 0;
+  this->uPlayerID_2 = 0;
+  this->uPlayerID = 0;
+  this->field_10 = 0;
+  }
+
+  void _427D48(unsigned int uPlayerID);
+  unsigned int PushStru277(__int16 a2, __int16 uPlayerID, __int16 a4, __int16 a5, int a6);
+  struct GUIWindow *sub_4219BE();
+  void _427E01_cast_spell();
+
+  __int16 spellnum;
+  unsigned __int16 uPlayerID;
+  __int16 uPlayerID_2;
+  __int16 field_6;
+  __int16 field_8;
+  __int16 field_A;
+  __int16 field_C;
+  __int16 field_E;
+  int field_10;
+};
+#pragma pack(pop)
+
+
+extern stru277 pStru277[10];
+extern stru277 stru_50CDB4; // idb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru279.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,28 @@
+#pragma once
+
+
+/*  273 */
+#pragma pack(push, 1)
+struct stru279
+{
+  //----- (0043B506) --------------------------------------------------------
+  stru279()
+  {
+  this->field_4 = 0;
+  this->field_8 = 0;
+  this->field_C = 0;
+  this->field_10 = 0;
+  this->field_14 = 0;
+  this->registry_debug_flags = 0;
+  }
+
+
+  int registry_debug_flags;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+};
+#pragma pack(pop)
+extern stru279 stru_51076C;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru287.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,12 @@
+#pragma once
+
+
+
+/*  281 */
+#pragma pack(push, 1)
+struct stru287
+{
+  char field_0[24];
+};
+#pragma pack(pop)
+extern stru287 stru_5E4C50;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru298.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,22 @@
+#pragma once
+#include "VectorTypes.h"
+
+/*  303 */
+#pragma pack(push, 1)
+struct stru298
+{
+  int Add(__int16 uID, __int16 a3, __int16 x, __int16 y, __int16 z, char a7, char a8);
+
+  int count;
+  __int16 pIDs[100];
+  __int16 pXs[100];
+  __int16 pYs[100];
+  __int16 pZs[100];
+  __int16 field_324[100];
+  char field_3EC[100];
+  char field_450[100];
+  Vec3_int_ vec_4B4;
+};
+#pragma pack(pop)
+
+extern stru298 stru_50FE08; // weak
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru314.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,34 @@
+#pragma once
+
+
+/*  179 */
+#pragma pack(push, 1)
+struct stru314
+{
+  //----- (00489B60) --------------------------------------------------------
+  stru314()
+  {
+    this->field_4.x = 0.0;
+    this->field_4.y = 0.0;
+    this->field_4.z = 0.0;
+    this->field_10.x = 0.0;
+    this->field_10.y = 0.0;
+    this->field_10.z = 0.0;
+    this->field_1C.x = 0.0;
+    this->field_1C.y = 0.0;
+    this->field_1C.z = 0.0;
+    //this->vdestructor_ptr = &stru314_pvdtor;
+  }
+  
+  //----- (00489B96) --------------------------------------------------------
+  inline ~stru314()
+  {}
+
+
+  void (__fastcall ***vdestructor_ptr)(stru314 *, bool);
+  Vec3_float_ field_4;
+  Vec3_float_ field_10;
+  Vec3_float_ field_1C;
+  float dist;
+};
+#pragma pack(pop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru351.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,16 @@
+#pragma once
+
+
+/*  391 */
+#pragma pack(push, 1)
+struct stru351
+{
+  int field_0;
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  int field_14;
+  int field_18;
+};
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru6.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,1811 @@
+#include "stru6.h"
+#include "LayingItem.h"
+#include "IndoorCameraD3D.h"
+#include "ParticleEngine.h"
+#include "Game.h"
+#include "LOD.h"
+#include "Sprites.h"
+#include "DecalBuilder.h"
+#include "ObjectList.h"
+#include "Actor.h"
+#include "Random.h"
+#include "Spells.h"
+#include "IconFrameTable.h"
+#include "Time.h"
+#include "Viewport.h"
+#include "PaletteManager.h"
+#include "Overlays.h"
+#include "stru160.h"
+
+
+
+
+
+
+//----- (00478211) --------------------------------------------------------
+void stru6_stru1_indoor_sw_billboard::Initialize(int a2)
+{
+  uNumVec4sInArray1 = 66;
+  pArray1 = new stru16x[66];
+
+  uNumVec3sInArray2 = 128;
+  pArray2 = new stru160[128];
+
+  for (uint i = 0; i < uNumVec4sInArray1; ++i)
+  {
+    pArray1[i].field_0 = array_4EB8B8[i].field_0;
+    pArray1[i].field_4 = array_4EB8B8[i].field_4;
+    pArray1[i].field_8 = array_4EB8B8[i].field_8;
+    pArray1[i].field_C = a2;
+  }
+  memcpy(pArray2, array_4EBBD0_x/*array_4EBBD0*/, uNumVec3sInArray2 * sizeof(stru160));
+}
+
+//----- (0047829F) --------------------------------------------------------
+void stru6_stru1_indoor_sw_billboard::_47829F_fireball_collision(float arg0, float a3, float a4, float a5, int a2)
+{
+  stru6_stru1_indoor_sw_billboard *v6; // esi@1
+  int v7; // edi@1
+  char *v8; // eax@2
+  signed int v9; // ecx@2
+  int v10; // edx@3
+  signed int i; // [sp+8h] [bp-4h]@1
+
+  auto a1 = this;
+
+  v6 = a1;
+  v7 = 0;
+  for ( i = 0; i < (signed int)v6->uNumVec3sInArray2; ++i )
+  {
+    v8 = (char *)&v6->field_14[1];
+    v9 = 3;
+    do
+    {
+      *((float *)v8 - 1) = a5 * *(&v6->pArray1->field_0 + 4 * *(int *)((char *)&v6->pArray2->field_0 + v7)) + arg0;
+      *(float *)v8 = a5 * *(&v6->pArray1->field_4 + 4 * *(int *)((char *)&v6->pArray2->field_0 + v7)) + a3;
+      v8 += 16;
+      *((float *)v8 - 3) = a5 * *(&v6->pArray1->field_8 + 4 * *(int *)((char *)&v6->pArray2->field_0 + v7)) + a4;
+      v10 = *(int *)((char *)&v6->pArray2->field_0 + v7);
+      v7 += 4;
+      --v9;
+      *((int *)v8 - 2) = *((int *)&v6->pArray1[1].field_0 + 4 * v10);
+    }
+    while ( v9 );
+    v6->field_10 = 3;
+    if ( v6->sub_477C61() && v6->sub_477F63() )
+    {
+      if ( v6->sub_47802A() )
+        pRenderer->_4A4CC9(v6, a2);
+    }
+  }
+}
+
+
+
+
+//----- (004A71FE) --------------------------------------------------------
+void stru6::DoAddProjectile(float srcX, float srcY, float srcZ, float dstX, float dstY, float dstZ, unsigned int uTextureID)
+{
+  int v8; // eax@1
+
+  v8 = uNumProjectiles;
+  if ( v8 != 32 )
+  {
+    pProjectiles[v8].srcX = srcX;
+    *((float *)&this->array_0[0].uSpellAnimLength + 7 * (uNumProjectiles + 21)) = srcY;
+    pProjectiles[uNumProjectiles].srcZ = srcZ;
+    pProjectiles[uNumProjectiles].dstX = dstX;
+    pProjectiles[uNumProjectiles].dstY = dstY;
+    pProjectiles[uNumProjectiles].dstZ = dstZ;
+    pProjectiles[uNumProjectiles++].uTextureID = uTextureID;
+  }
+}
+
+//----- (004A7298) --------------------------------------------------------
+void stru6::DrawProjectiles()
+{
+  float v10; // ST1C_4@8
+  float v11; // ST0C_4@8
+  IDirect3DTexture2 *v12; // [sp+20h] [bp-78h]@6
+  RenderVertexSoft v[2]; // [sp+30h] [bp-68h]@1
+  
+  for (uint i = 0; i < uNumProjectiles; ++i)
+  {
+    auto p = pProjectiles + i;
+
+    v[0].vWorldPosition.x = p->srcX;
+    v[0].vWorldPosition.y = p->srcY;
+    v[0].vWorldPosition.z = p->srcZ;
+    v[1].vWorldPosition.x = p->dstX;
+    v[1].vWorldPosition.y = p->dstY;
+    v[1].vWorldPosition.z = p->dstZ;
+    pGame->pIndoorCameraD3D->ViewTransform(v, 2);
+
+    sr_42620A(v);
+
+    pGame->pIndoorCameraD3D->Project(v, 2, 0);
+
+    if (p->uTextureID != -1)
+      v12 = pBitmaps_LOD->pHardwareTextures[p->uTextureID];
+    else
+      v12 = 0;
+
+    v10 = pGame->pIndoorCameraD3D->fov_x / v[1].vWorldViewPosition.x * 20.0;
+    v11 = pGame->pIndoorCameraD3D->fov_x / v[0].vWorldViewPosition.x * 20.0;
+    pRenderer->DrawProjectile(
+        v[0].vWorldViewProjX,
+        v[0].vWorldViewProjY,
+        v[0].vWorldViewPosition.x,
+         v11,
+        v[1].vWorldViewProjX,
+        v[1].vWorldViewProjY,
+        v[1].vWorldViewPosition.x,
+         v10,
+         v12);
+   }
+}
+
+//----- (004A73AA) --------------------------------------------------------
+void stru6::_4A73AA_hanging_trace_particles___like_fire_strike_ice_blast_etc(LayingItem *a2, unsigned int uDiffuse, unsigned int uTextureID)
+{
+  stru6 *v4; // edi@1
+  LayingItem *v5; // esi@1
+  int v6; // eax@1
+  stru6_stru2 *v7; // eax@2
+  double v8; // st7@2
+  double v9; // st6@2
+  double v10; // st7@3
+  Particle_ local_0; // [sp+8h] [bp-68h]@1
+  float x; // [sp+78h] [bp+8h]@2
+
+  v4 = this;
+  memset(&local_0, 0, 0x68u);
+  v5 = a2;
+  v6 = a2->field_54;
+  if ( v6 )
+  {
+    v7 = &v4->array_0[v6 & 0x1F];
+    x = ((double)a2->vPosition.x - v7->flt_4) * 0.5 + v7->flt_4;
+    v8 = ((double)v5->vPosition.y - v7->flt_8) * 0.5 + v7->flt_8;
+    v9 = ((double)v5->vPosition.z - v7->flt_C) * 0.5 + v7->flt_C;
+    local_0.bFree = 1036;
+    local_0.uDiffuse = uDiffuse;
+    local_0.x = x + 4.0;
+    local_0.y = v8;
+    local_0.z = v9;
+    local_0.flt_10 = 0.0;
+    local_0.flt_14 = 0.0;
+    local_0.flt_18 = 0.0;
+    local_0.timeToLive = (rand() & 0x40) + 96;
+    local_0.uTextureID = uTextureID;
+    local_0.flt_28 = 1.0;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    local_0.x = x - 4.0;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    local_0.x = (double)v5->vPosition.x + 4.0;
+    local_0.y = (double)v5->vPosition.y;
+    local_0.z = (double)v5->vPosition.z;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    local_0.x = (double)v5->vPosition.x - 4.0;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    v4->array_0[v5->field_54 & 0x1F].flt_4 = (double)v5->vPosition.x;
+    v4->array_0[v5->field_54 & 0x1F].flt_8 = (double)v5->vPosition.y;
+    v4->array_0[v5->field_54 & 0x1F].flt_C = (double)v5->vPosition.z;
+  }
+  else
+  {
+    a2->field_54 = v4->array_0[0].uSpellAnimLength++;
+    v4->array_0[a2->field_54 & 0x1F].flt_4 = (double)a2->vPosition.x;
+    v4->array_0[a2->field_54 & 0x1F].flt_8 = (double)a2->vPosition.y;
+    v4->array_0[a2->field_54 & 0x1F].flt_C = (double)a2->vPosition.z;
+    v10 = (double)a2->vPosition.x;
+    local_0.bFree = 1036;
+    local_0.uDiffuse = uDiffuse;
+    local_0.x = v10 + 4.0;
+    local_0.y = (double)a2->vPosition.y;
+    local_0.z = (double)a2->vPosition.z;
+    local_0.flt_10 = 0.0;
+    local_0.flt_14 = 0.0;
+    local_0.flt_18 = 0.0;
+    local_0.flt_28 = 1.0;
+    local_0.timeToLive = (rand() & 0x7F) + 128;
+    local_0.uTextureID = uTextureID;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    local_0.x = (double)a2->vPosition.x - 4.0;
+    pGame->pParticleEngine->AddParticle(&local_0);
+  }
+}
+
+//----- (004A75CC) --------------------------------------------------------
+void stru6::_4A75CC_single_spell_collision_particle(LayingItem *a1, unsigned int uDiffuse, unsigned int uTextureID)
+{
+  double v4; // st7@1
+  signed int v5; // edi@1
+  Particle_ local_0; // [sp+8h] [bp-68h]@1
+
+  memset(&local_0, 0, 0x68u);
+  local_0.bFree = 1029;
+  local_0.x = (double)a1->vPosition.x;
+  local_0.y = (double)a1->vPosition.y;
+  v4 = (double)a1->vPosition.z;
+  local_0.uDiffuse = uDiffuse;
+  local_0.z = v4;
+  v5 = 10;
+  local_0.timeToLive = (rand() & 0x7F) + 128;
+  local_0.uTextureID = uTextureID;
+  local_0.flt_28 = 1.0;
+  do
+  {
+    local_0.flt_10 = (double)(rand() & 0x1FF) - 255.0;
+    local_0.flt_14 = (double)(rand() & 0x1FF) - 255.0;
+    local_0.flt_18 = (double)(rand() & 0x1FF) - 255.0;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    --v5;
+  }
+  while ( v5 );
+}
+
+//----- (004A7688) --------------------------------------------------------
+void stru6::_4A7688_fireball_collision_particle(LayingItem *a2)
+{
+  LayingItem *v2; // esi@1
+  double v3; // st7@1
+  double v4; // st7@2
+  double v5; // st7@4
+  int v6; // eax@6
+  float v7; // ST0C_4@6
+  float v8; // ST08_4@6
+  float v9; // ST04_4@6
+  float v10; // ST00_4@6
+  Particle_ local_0; // [sp+1Ch] [bp-7Ch]@1
+  stru6 *v12; // [sp+84h] [bp-14h]@1
+  float v13; // [sp+88h] [bp-10h]@1
+  double v14; // [sp+8Ch] [bp-Ch]@5
+  float v15; // [sp+94h] [bp-4h]@4
+  signed int i; // [sp+A0h] [bp+8h]@4
+  signed int a2b; // [sp+A0h] [bp+8h]@6
+
+  v12 = this;
+  memset(&local_0, 0, 0x68u);
+  v2 = a2;
+  v3 = (double)a2->uSpriteFrameID / (double)pObjectList->pObjects[a2->uObjectDescID].uLifetime;
+  v13 = 512.0 * v3;
+  if ( v3 >= 0.75 )
+    v4 = (1.0 - v3) * 4.0;
+  else
+    v4 = v3 * 1.333333333333333;
+  v15 = v4;
+  v5 = (double)a2->vPosition.x;
+  local_0.bFree = 1029;
+  local_0.uDiffuse = 0xFF3C1Eu;
+  local_0.x = v5;
+  local_0.y = (double)a2->vPosition.y;
+  local_0.z = (double)a2->vPosition.z;
+  local_0.timeToLive = (rand() & 0x7F) + 128;
+  local_0.uTextureID = pBitmaps_LOD->LoadTexture("effpar01", TEXTURE_DEFAULT);
+  i = 10;
+  local_0.flt_28 = 1.0;
+  do
+  {
+    HIDWORD(v14) = rand() & 0x1FF;
+    local_0.flt_10 = (double)SHIDWORD(v14) - 255.0;
+    HIDWORD(v14) = rand() & 0x1FF;
+    local_0.flt_14 = (double)SHIDWORD(v14) - 255.0;
+    WORD2(v14) = rand() & 0x1FF;
+    HIDWORD(v14) = WORD2(v14);
+    local_0.flt_18 = (double)WORD2(v14) - 255.0;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    --i;
+  }
+  while ( i );
+  v14 = v13 + 6.7553994e15;
+  a2b = LODWORD(v14);
+  v6 = sub_4A7063(0xFF3C1Eu, v15);
+  v7 = (double)a2b;
+  v8 = (double)v2->vPosition.z;
+  v9 = (double)v2->vPosition.y;
+  v10 = (double)v2->vPosition.x;
+  v12->pStru1->_47829F_fireball_collision(v10, v9, v8, v7, v6);
+}
+
+//----- (004A77FD) --------------------------------------------------------
+void stru6::_4A77FD_some_stuff_d3d(LayingItem *a1)
+{
+  LayingItem *v2; // esi@1
+  stru6 *v3; // edi@1
+  double v4; // st7@1
+  double v5; // st7@2
+  double v6; // ST1C_8@4
+  int v7; // eax@4
+  float v8; // ST0C_4@4
+  float v9; // ST08_4@4
+  float v10; // ST04_4@4
+  float v11; // ST00_4@4
+  float v12; // [sp+28h] [bp-4h]@1
+  float a1a; // [sp+34h] [bp+8h]@4
+
+  v2 = a1;
+  v3 = this;
+  v4 = (double)a1->uSpriteFrameID / (double)pObjectList->pObjects[a1->uObjectDescID].uLifetime;
+  v12 = 512.0 - v4 * 512.0;
+  if ( v4 >= 0.75 )
+    v5 = v4 * 4.0;
+  else
+    v5 = v4 * 1.333333333333333;
+  a1a = v5;
+  v6 = v12 + 6.7553994e15;
+  v7 = sub_4A7063(0x7E7E7Eu, a1a);
+  v8 = (double)SLODWORD(v6);
+  v9 = (double)v2->vPosition.z;
+  v10 = (double)v2->vPosition.y;
+  v11 = (double)v2->vPosition.x;
+  v3->pStru1->_47829F_fireball_collision(v11, v10, v9, v8, v7);
+}
+
+//----- (004A78AE) --------------------------------------------------------
+void stru6::_4A78AE_sparks_spell(LayingItem *a1)
+{
+  ObjectDesc *v2; // esi@1
+  unsigned int v3; // eax@1
+  double v4; // st7@1
+  Particle_ local_0; // [sp+8h] [bp-68h]@1
+
+  v2 = &pObjectList->pObjects[a1->uObjectDescID];
+  memset(&local_0, 0, 0x68u);
+  v3 = a1->uSpriteFrameID;
+  local_0.x = (double)a1->vPosition.x;
+  v4 = (double)a1->vPosition.y;
+  local_0.bFree = 2048;
+  local_0.uDiffuse = 0x7F7F7Fu;
+  local_0.timeToLive = 1;
+  local_0.y = v4;
+  local_0.z = (double)a1->vPosition.z;
+  local_0.flt_10 = 0.0;
+  local_0.flt_14 = 0.0;
+  local_0.flt_18 = 0.0;
+  local_0.uTextureID = pSpriteFrameTable->GetFrame(v2->uSpriteID, v3)->pHwSpriteIDs[0];
+  LODWORD(local_0.flt_28) = 0x40000000u;
+  pGame->pParticleEngine->AddParticle(&local_0);
+}
+
+//----- (004A7948) --------------------------------------------------------
+void stru6::_4A7948_mind_blast_after_effect(LayingItem *a1)
+{
+  ObjectDesc *v2; // esi@1
+  unsigned int v3; // eax@1
+  double v4; // st7@1
+  char v5; // al@1
+  signed int v6; // edi@1
+  Particle_ Dst; // [sp+8h] [bp-68h]@1
+
+  v2 = &pObjectList->pObjects[a1->uObjectDescID];
+  memset(&Dst, 0, 0x68u);
+  v3 = a1->uSpriteFrameID;
+  Dst.x = (double)a1->vPosition.x;
+  v4 = (double)a1->vPosition.y;
+  Dst.bFree = 2053;
+  Dst.uDiffuse = 0x7F7F7Fu;
+  Dst.y = v4;
+  Dst.z = (double)a1->vPosition.z;
+  Dst.uTextureID = pSpriteFrameTable->GetFrame(v2->uSpriteID, v3)->pHwSpriteIDs[0];
+  v5 = rand();
+  v6 = 10;
+  Dst.flt_28 = 1.0;
+  Dst.timeToLive = (v5 & 0x7F) + 128;
+  do
+  {
+    Dst.flt_10 = (double)(rand() & 0x1FF) - 255.0;
+    Dst.flt_14 = (double)(rand() & 0x1FF) - 255.0;
+    Dst.flt_18 = (double)(rand() & 0x1FF) - 255.0;
+    pGame->pParticleEngine->AddParticle(&Dst);
+    --v6;
+  }
+  while ( v6 );
+}
+
+//----- (004A7A27) --------------------------------------------------------
+bool stru6::AddMobileLight(LayingItem *a1, unsigned int uDiffuse, int uRadius)
+{
+  return pMobileLightsStack->AddLight(
+           a1->vPosition.x,
+           a1->vPosition.y,
+           a1->vPosition.z,
+           a1->uSectorID,
+           uRadius,
+           (uDiffuse & 0x00FF0000) >> 16,
+           (uDiffuse & 0x0000FF00) >> 8,
+           uDiffuse & 0x000000FF,
+           byte_4E94D3);
+}
+// 4E94D3: using guessed type char byte_4E94D3;
+
+//----- (004A7A66) --------------------------------------------------------
+void stru6::_4A7A66_miltiple_spell_collision_partifles___like_after_sparks_or_lightning(LayingItem *a1, unsigned int uDiffuse, unsigned int uTextureID, float a4)
+{
+  int v5; // eax@1
+  char v6; // al@1
+  double v7; // st6@1
+  double v8; // st6@1
+  double v9; // st7@1
+  double v10; // st6@1
+  Particle_ local_0; // [sp+0h] [bp-6Ch]@1
+  float v12; // [sp+68h] [bp-4h]@1
+  float a1a; // [sp+74h] [bp+8h]@1
+  float uDiffusea; // [sp+78h] [bp+Ch]@1
+  float uTextureIDa; // [sp+7Ch] [bp+10h]@1
+
+  memset(&local_0, 0, 0x68u);
+  local_0.bFree = 1029;
+  local_0.x = (double)a1->vPosition.x;
+  v5 = a1->vPosition.z;
+  local_0.y = (double)a1->vPosition.y;
+  local_0.uDiffuse = uDiffuse;
+  local_0.z = (double)(v5 + 32);
+  v6 = rand();
+  local_0.flt_28 = 1.0;
+  v7 = 0.0 * a4;
+  local_0.timeToLive = (v6 & 0x7F) + 128;
+  local_0.uTextureID = uTextureID;
+  a1a = v7;
+  local_0.flt_10 = v7;
+  local_0.flt_14 = a4;
+  local_0.flt_18 = a4;
+  pGame->pParticleEngine->AddParticle(&local_0);
+  v8 = 0.70710677 * a4;
+  uDiffusea = v8;
+  local_0.flt_10 = v8;
+  local_0.flt_14 = v8;
+  local_0.flt_18 = a4;
+  pGame->pParticleEngine->AddParticle(&local_0);
+  local_0.flt_14 = a1a;
+  local_0.flt_10 = a4;
+  local_0.flt_18 = a4;
+  pGame->pParticleEngine->AddParticle(&local_0);
+  local_0.flt_10 = uDiffusea;
+  local_0.flt_18 = a4;
+  v9 = -uDiffusea;
+  uTextureIDa = v9;
+  local_0.flt_14 = v9;
+  pGame->pParticleEngine->AddParticle(&local_0);
+  v10 = -1.0 * a4;
+  local_0.flt_10 = a1a;
+  v12 = v10;
+  local_0.flt_14 = v10;
+  local_0.flt_18 = a4;
+  pGame->pParticleEngine->AddParticle(&local_0);
+  local_0.flt_18 = a4;
+  local_0.flt_10 = uTextureIDa;
+  local_0.flt_14 = uTextureIDa;
+  pGame->pParticleEngine->AddParticle(&local_0);
+  local_0.flt_10 = v12;
+  local_0.flt_14 = a1a;
+  local_0.flt_18 = a4;
+  pGame->pParticleEngine->AddParticle(&local_0);
+  local_0.flt_10 = uTextureIDa;
+  local_0.flt_14 = uDiffusea;
+  local_0.flt_18 = a4;
+  pGame->pParticleEngine->AddParticle(&local_0);
+}
+
+//----- (004A7C07) --------------------------------------------------------
+void stru6::_4A7C07(LayingItem *a2)
+{
+  stru6 *v2; // edi@1
+  LayingItem *v3; // esi@1
+  int v4; // eax@1
+  ObjectDesc *v5; // ebx@1
+  stru6_stru2 *v6; // eax@2
+  double v7; // st6@2
+  double v8; // st5@2
+  double v9; // st4@2
+  char v10; // al@2
+  double v11; // st7@2
+  double v12; // st7@3
+  Particle_ local_0; // [sp+Ch] [bp-68h]@1
+  float a2a; // [sp+7Ch] [bp+8h]@2
+
+  v2 = this;
+  memset(&local_0, 0, 0x68u);
+  v3 = a2;
+  v4 = a2->field_54;
+  v5 = &pObjectList->pObjects[a2->uObjectDescID];
+  if ( v4 )
+  {
+    v6 = &v2->array_0[v4 & 0x1F];
+    v7 = ((double)a2->vPosition.x - v6->flt_4) * 0.5 + v6->flt_4;
+    v8 = ((double)a2->vPosition.y - v6->flt_8) * 0.5 + v6->flt_8;
+    v9 = ((double)a2->vPosition.z - v6->flt_C) * 0.5 + v6->flt_C;
+    local_0.bFree = 2048;
+    local_0.uDiffuse = 0xFFFFFFu;
+    a2a = v9;
+    local_0.x = v7;
+    local_0.z = a2a;
+    local_0.y = v8;
+    local_0.flt_10 = 0.0;
+    local_0.flt_14 = 0.0;
+    local_0.flt_18 = 0.0;
+    v10 = rand();
+    LODWORD(local_0.flt_28) = 0x40400000u;
+    local_0.timeToLive = (v10 & 0x3F) + 64;
+    local_0.uTextureID = pSpriteFrameTable->GetFrame(v5->uSpriteID, v3->uSpriteFrameID)->pHwSpriteIDs[0];
+    pGame->pParticleEngine->AddParticle(&local_0);
+    v11 = (double)v3->vPosition.x;
+    LODWORD(local_0.flt_28) = 0x40800000u;
+    local_0.x = v11;
+    local_0.y = (double)v3->vPosition.y;
+    local_0.z = (double)v3->vPosition.z;
+    local_0.timeToLive = (rand() & 0x3F) + 64;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    v2->array_0[v3->field_54 & 0x1F].flt_4 = (double)v3->vPosition.x;
+    v2->array_0[v3->field_54 & 0x1F].flt_8 = (double)v3->vPosition.y;
+    v2->array_0[v3->field_54 & 0x1F].flt_C = (double)v3->vPosition.z;
+  }
+  else
+  {
+    a2->field_54 = v2->array_0[0].uSpellAnimLength++;
+    v2->array_0[a2->field_54 & 0x1F].flt_4 = (double)a2->vPosition.x;
+    v2->array_0[a2->field_54 & 0x1F].flt_8 = (double)a2->vPosition.y;
+    v2->array_0[a2->field_54 & 0x1F].flt_C = (double)a2->vPosition.z;
+    v12 = (double)a2->vPosition.x;
+    local_0.bFree = 2048;
+    local_0.uDiffuse = 0xFFFFFFu;
+    LODWORD(local_0.flt_28) = 0x40000000u;
+    local_0.x = v12;
+    local_0.y = (double)a2->vPosition.y;
+    local_0.z = (double)a2->vPosition.z;
+    local_0.flt_10 = 0.0;
+    local_0.flt_14 = 0.0;
+    local_0.flt_18 = 0.0;
+    local_0.timeToLive = (rand() & 0x3F) + 64;
+    local_0.uTextureID = pSpriteFrameTable->GetFrame(v5->uSpriteID, a2->uSpriteFrameID)->pHwSpriteIDs[0];
+    pGame->pParticleEngine->AddParticle(&local_0);
+  }
+}
+
+//----- (004A7E05) --------------------------------------------------------
+void stru6::AddProjectile(LayingItem *a2, int a3, unsigned int uTextureID)
+{
+  int v4; // edx@1
+  float v5; // ST14_4@2
+  float v6; // ST10_4@2
+  float v7; // ST0C_4@2
+
+  v4 = a2->field_54;
+  if ( v4 )
+  {
+    v5 = (double)a2->vPosition.z;
+    v6 = (double)a2->vPosition.y;
+    v7 = (double)a2->vPosition.x;
+    DoAddProjectile(
+      this->array_0[v4 & 0x1F].flt_4,
+      this->array_0[v4 & 0x1F].flt_8,
+      this->array_0[v4 & 0x1F].flt_C,
+      v7,
+      v6,
+      v5,
+      uTextureID);
+  }
+  else
+  {
+    a2->field_54 = this->array_0[0].uSpellAnimLength++;
+    this->array_0[a2->field_54 & 0x1F].flt_4 = (double)a2->vPosition.x;
+    this->array_0[a2->field_54 & 0x1F].flt_8 = (double)a2->vPosition.y;
+    this->array_0[a2->field_54 & 0x1F].flt_C = (double)a2->vPosition.z;
+  }
+}
+
+//----- (004A7E89) --------------------------------------------------------
+int stru6::_4A7E89_sparkles_on_actor_after_it_casts_buff(Actor *pActor, unsigned int uDiffuse)
+{
+  Actor *v3; // edi@1
+  int v4; // ebx@3
+  int result; // eax@5
+  Particle_ Dst; // [sp+Ch] [bp-6Ch]@1
+  int v7; // [sp+74h] [bp-4h]@2
+  signed int pActora; // [sp+80h] [bp+8h]@1
+
+  memset(&Dst, 0, 0x68u);
+  Dst.bFree = 1036;
+  Dst.timeToLive = (rand() & 0x7F) + 128;
+  v3 = pActor;
+  Dst.uTextureID = pBitmaps_LOD->LoadTexture("effpar02", TEXTURE_DEFAULT);
+  pActora = 50;
+  Dst.flt_28 = 1.0;
+  do
+  {
+    v7 = (unsigned __int8)rand() + v3->vPosition.x - 127;
+    Dst.x = (double)v7;
+    v7 = (unsigned __int8)rand() + v3->vPosition.y - 127;
+    Dst.y = (double)v7;
+    v7 = v3->vPosition.z + (unsigned __int8)rand();
+    Dst.z = (double)v7;
+    if ( uDiffuse )
+    {
+      Dst.uDiffuse = uDiffuse;
+    }
+    else
+    {
+      v4 = rand() << 16;
+      Dst.uDiffuse = rand() | v4;
+    }
+    pGame->pParticleEngine->AddParticle(&Dst);
+    --pActora;
+  }
+  while ( pActora );
+  return result;
+}
+
+//----- (004A7F74) --------------------------------------------------------
+void stru6::_4A7F74(int x, int y, int z)
+{
+  stru6 *v4; // esi@1
+  char v5; // al@1
+  signed int v6; // edi@1
+  unsigned int v7; // eax@1
+  double v8; // st7@2
+  double v9; // st7@2
+  Particle_ local_0; // [sp+8h] [bp-78h]@1
+  double v11; // [sp+70h] [bp-10h]@1
+  double v12; // [sp+78h] [bp-8h]@1
+  float z1; // [sp+88h] [bp+8h]@2
+
+  v4 = this;
+  memset(&local_0, 0, 0x68u);
+  local_0.bFree = 1029;
+  local_0.uDiffuse = 0x7E7E7Eu;
+  v5 = rand();
+  local_0.flt_28 = 1.0;
+  v6 = 8;
+  local_0.timeToLive = (v5 & 0x7F) + 128;
+  v7 = v4->uTextureID_effpar1;
+  v12 = (double)x;
+  local_0.uTextureID = v7;
+  v11 = (double)y;
+  do
+  {
+    v8 = pRnd->GetRandom();
+    local_0.x = v8 * 40.0 - 20.0 + v12;
+    v9 = pRnd->GetRandom();
+    z1 = (double)z;
+    local_0.z = z1;
+    local_0.y = v9 * 40.0 - 20.0 + v11;
+    local_0.flt_10 = pRnd->GetRandom() * 400.0 - 200.0;
+    local_0.flt_14 = pRnd->GetRandom() * 400.0 - 200.0;
+    local_0.flt_18 = pRnd->GetRandom() * 150.0 + 50.0;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    --v6;
+  }
+  while ( v6 );
+}
+
+//----- (004A806F) --------------------------------------------------------
+int stru6::_4A806F(Actor *pActor)
+{
+  int v2; // ecx@1
+  unsigned int v3; // eax@1
+  double v4; // st7@2
+  float v5; // ST00_4@6
+
+  v2 = (int)pActor;
+  v3 = LODWORD(pActor->pActorBuffs[10].uExpireTime) - pMiscTimer->uTotalGameTimeElapsed;
+  if ( (signed int)v3 <= 64 )
+  {
+    if ( (v3 & 0x80000000u) != 0 )
+    {
+      pActor->pActorBuffs[10].uExpireTime = 0i64;
+      v4 = 1.0;
+    }
+    else
+    {
+      v2 = v3 * v3;
+      v4 = 1.0 - (double)(signed int)(v3 * v3) * 0.0001953125;
+    }
+  }
+  else
+  {
+    v2 = (v3 - 64) * (v3 - 64);
+    v4 = (double)v2 * 0.0001953125 + 0.2;
+  }
+  v5 = v4;
+  return _48B561_mess_with_scaling_along_z(/*v2, */v5);
+}
+
+//----- (004A80DC) --------------------------------------------------------
+void stru6::_4A80DC_some_stuff_sw(LayingItem *a2)
+{
+  stru6 *v2; // esi@1
+  signed int v3; // ebx@1
+  Particle_ local_0; // [sp+Ch] [bp-68h]@1
+
+  v2 = this;
+  memset(&local_0, 0, 0x68u);
+  local_0.bFree = 1029;
+  local_0.uDiffuse = 0x7E7E7Eu;
+  local_0.timeToLive = (rand() & 0x7F) + 128;
+  local_0.uTextureID = v2->uTextureID_effpar1;
+  v3 = 8;
+  local_0.flt_28 = 1.0;
+  do
+  {
+    local_0.x = pRnd->GetRandom() * 40.0 + (double)a2->vPosition.x - 20.0;
+    local_0.y = pRnd->GetRandom() * 40.0 + (double)a2->vPosition.y - 20.0;
+    local_0.z = (double)a2->vPosition.z;
+    local_0.flt_10 = pRnd->GetRandom() * 800.0 - 400.0;
+    local_0.flt_14 = pRnd->GetRandom() * 800.0 - 400.0;
+    local_0.flt_18 = pRnd->GetRandom() * 350.0 + 50.0;
+    pGame->pParticleEngine->AddParticle(&local_0);
+    --v3;
+  }
+  while ( v3 );
+}
+
+//----- (004A81CA) --------------------------------------------------------
+bool stru6::_4A81CA(LayingItem *a2)
+{
+  stru6 *v2; // ebx@1
+  int result; // eax@1
+  int v4; // eax@27
+  unsigned int diffuse; // esi@41
+  int v6; // ecx@49
+  int v7; // eax@54
+  int v8; // eax@55
+  char v9; // zf@56
+  int v10; // eax@59
+  int v11; // eax@61
+  int v12; // eax@85
+  int v13; // eax@86
+  int v14; // eax@96
+  int v15; // eax@111
+  int v16; // eax@118
+  int v17; // eax@139
+  int v18; // eax@140
+  int v19; // eax@141
+  int v20; // eax@151
+  unsigned int v21; // [sp-8h] [bp-20h]@66
+  LayingItem *v22; // [sp-8h] [bp-20h]@81
+  unsigned int v23; // [sp-4h] [bp-1Ch]@4
+  unsigned int v24; // [sp-4h] [bp-1Ch]@5
+  unsigned int v25; // [sp-4h] [bp-1Ch]@30
+  unsigned int v26; // [sp-4h] [bp-1Ch]@57
+  unsigned int v27; // [sp-4h] [bp-1Ch]@66
+  int v28; // [sp-4h] [bp-1Ch]@81
+  unsigned int v29; // [sp+0h] [bp-18h]@4
+  unsigned int v30; // [sp+0h] [bp-18h]@5
+  int v31; // [sp+0h] [bp-18h]@30
+  unsigned int v32; // [sp+0h] [bp-18h]@45
+  float v33; // [sp+0h] [bp-18h]@57
+  float v34; // [sp+0h] [bp-18h]@66
+  signed int v35; // [sp+0h] [bp-18h]@81
+  char pContainer[7]; // [sp+10h] [bp-8h]@81
+
+  v2 = this;
+  result = a2->uItemType;
+  if ( result <= 545 )
+  {
+    if ( result != 545 )
+    {
+      result -= 500;
+      switch ( result )
+      {
+        case 0:
+        case 30:
+          v29 = this->uTextureID_effpar1;
+          v23 = 0xAAAFFu;
+          goto LABEL_8;
+        case 1:
+        case 31:
+          v30 = this->uTextureID_effpar1;
+          v24 = 0xAAAFFu;
+          goto LABEL_32;
+        case 5:
+          v29 = this->uTextureID_effpar1;
+          v23 = 0x5C310Eu;
+          goto LABEL_8;
+        case 10:
+          v29 = this->uTextureID_effpar1;
+          v23 = 0xFF3C1Eu;
+          goto LABEL_8;
+        case 15:
+          v29 = this->uTextureID_effpar1;
+          v23 = 0x62D0u;
+          goto LABEL_8;
+        case 16:
+          v30 = this->uTextureID_effpar1;
+          v24 = 0x62D0u;
+          goto LABEL_32;
+        case 20:
+          v29 = this->uTextureID_effpar1;
+          v23 = 0xAB450u;
+          goto LABEL_8;
+        case 21:
+          v30 = this->uTextureID_effpar1;
+          v24 = 0xAB450u;
+          goto LABEL_32;
+        case 25:
+          v29 = this->uTextureID_effpar1;
+          v23 = 0xC8C805u;
+          goto LABEL_8;
+        case 26:
+          v30 = this->uTextureID_effpar1;
+          v24 = 0xC8C805u;
+          goto LABEL_32;
+        case 35:
+          v29 = this->uTextureID_effpar1;
+          v23 = 0xFFFFFFu;
+          goto LABEL_8;
+        case 36:
+          v30 = this->uTextureID_effpar1;
+          goto LABEL_154;
+        case 40:
+          goto LABEL_17;
+        case 11:
+          goto LABEL_31;
+        case 6:
+          goto LABEL_115;
+        case 41:
+          goto LABEL_164;
+        default:
+          goto LABEL_168;
+      }
+      goto LABEL_168;
+    }
+    goto LABEL_34;
+  }
+  if ( result <= 4051 )
+  {
+    if ( result != 4051 )
+    {
+      if ( result <= 2031 )
+      {
+        if ( result != 2031 )
+        {
+          if ( result <= 1051 )
+          {
+            if ( result == 1051 )
+            {
+              result = AddMobileLight(a2, 0xFF3C1Eu, 256);// fireball hit
+              if ( pRenderer->pRenderD3D )
+              {
+                result = a2->field_58 & 7;
+                if ( result != 3 )
+                {
+                  if ( result != 2 )
+                  {
+                    result = (bool)&v2->field_204;
+                    v6 = v2->field_204;
+                    if ( v6 != 4 )
+                    {
+                      *(int *)result = v6 + 1;
+                      _4A7688_fireball_collision_particle(a2);
+                    }
+                    goto LABEL_168;
+                  }
+                }
+              }
+              goto LABEL_34;
+            }
+            if ( result <= 600 )
+            {
+              if ( result == 600 )
+              {
+                result = AddMobileLight(a2, 0xFF3C1Eu, 256);
+                goto LABEL_34;
+              }
+              result -= 550;
+              if ( !result )
+              {
+LABEL_34:
+                LOBYTE(result) = 1;
+                return result;
+              }
+              v4 = result - 1;
+              if ( v4 )
+              {
+                result = v4 - 4;
+                if ( !result )
+                  goto LABEL_34;
+                --result;
+                if ( !result )
+                {
+                  v31 = 256;
+                  v25 = 0xFF0000u;
+LABEL_144:
+                  result = AddMobileLight(a2, v25, v31);
+                  goto LABEL_168;
+                }
+                goto LABEL_168;
+              }
+              goto LABEL_31;
+            }
+            if ( result < 811 )
+              goto LABEL_168;
+            if ( result <= 814 )
+              goto LABEL_34;
+            if ( result == 1010 )
+              goto LABEL_41;                    // fire strike
+            if ( result != 1011 )
+            {
+              if ( result != 1050 )
+                goto LABEL_168;
+LABEL_41:
+              diffuse = 0xFF3C1Eu;
+LABEL_42:
+              _4A73AA_hanging_trace_particles___like_fire_strike_ice_blast_etc(
+                a2,
+                diffuse,
+                this->uTextureID_effpar1);
+LABEL_43:
+              v31 = 256;
+LABEL_44:
+              v25 = diffuse;
+              goto LABEL_144;
+            }
+            v32 = this->uTextureID_effpar1;
+            diffuse = 0xFF3C1Eu;
+LABEL_146:
+            _4A75CC_single_spell_collision_particle(a2, diffuse, v32);
+            goto LABEL_43;
+          }
+          if ( result <= 1081 )
+          {
+            if ( result == 1081 )
+            {
+              diffuse = 0xFF3C1Eu;
+              _4A7A66_miltiple_spell_collision_partifles___like_after_sparks_or_lightning(
+                a2,
+                0xFF3C1Eu,
+                this->uTextureID_effpar1,
+                300.0);
+              _4A7A66_miltiple_spell_collision_partifles___like_after_sparks_or_lightning(
+                a2,
+                0xFF3C1Eu,
+                v2->uTextureID_effpar1,
+                250.0);
+              v33 = 200.0;
+              v26 = v2->uTextureID_effpar1;
+            }
+            else
+            {
+              result -= 1060;
+              if ( !result )
+                goto LABEL_34;
+              v7 = result - 1;
+              if ( v7 )
+              {
+                v8 = v7 - 9;
+                if ( !v8 )
+                {
+LABEL_31:
+                  v30 = this->uTextureID_effpar1;
+                  v24 = 0xFF3C1Eu;
+                  goto LABEL_32;
+                }
+                result = v8 - 10;
+                v9 = result == 0;
+LABEL_129:
+                if ( v9 )
+                  goto LABEL_34;
+                goto LABEL_168;
+              }
+              diffuse = 0xFF3C1Eu;
+              v33 = 250.0;
+              v26 = this->uTextureID_effpar1;
+            }
+LABEL_84:
+            _4A7A66_miltiple_spell_collision_partifles___like_after_sparks_or_lightning(a2, diffuse, v26, v33);
+            goto LABEL_43;
+          }
+          v10 = result - 1090;
+          if ( v10 )
+          {
+            result = v10 - 10;
+            if ( !result )
+              goto LABEL_34;
+            v11 = result - 1;
+            if ( !v11 )
+            {
+              diffuse = 0xFF3C1Eu;
+              _4A75CC_single_spell_collision_particle(a2, 0xFF3C1Eu, this->uTextureID_effpar1);
+              v32 = v2->uTextureID_effpar1;
+              goto LABEL_146;
+            }
+            result = v11 - 929;
+            if ( result )
+              goto LABEL_168;
+LABEL_63:
+            if ( !pRenderer->pRenderD3D )
+              goto LABEL_34;
+            _4A78AE_sparks_spell(a2);
+            v31 = 128;
+            v25 = 0x64640Fu;
+            goto LABEL_144;
+          }
+          v34 = 250.0;
+          v27 = this->uTextureID_effpar1;
+          v21 = 0xFF3C1Eu;
+LABEL_117:
+          _4A7A66_miltiple_spell_collision_partifles___like_after_sparks_or_lightning(a2, v21, v27, v34);
+          goto LABEL_168;
+        }
+        goto LABEL_67;
+      }
+      if ( result <= 3060 )
+      {
+        if ( result == 3060 )
+          goto LABEL_171;                       // acid burst
+        if ( result <= 2101 )
+        {
+          if ( result == 2101 )
+          {
+            v33 = 200.0;
+            v26 = this->uTextureID_effpar1;
+            goto LABEL_83;
+          }
+          if ( result != 2060 )
+          {
+            if ( result != 2061 )
+            {
+              if ( result <= 2079 )
+                goto LABEL_168;
+              if ( result <= 2081 )
+              {
+                if ( pRenderer->pRenderD3D )
+                  _4A77FD_some_stuff_d3d(a2);
+                else
+                  _4A80DC_some_stuff_sw(a2);
+                goto LABEL_168;
+              }
+              v9 = result == 2100;
+              goto LABEL_129;
+            }
+LABEL_67:
+            v33 = 200.0;
+            v26 = this->uTextureID_effpar2;
+LABEL_83:
+            diffuse = (unsigned int)&pDecalBuilder->std__vector_pDecals[557].pVertices[57].vWorldViewPosition.y;
+            goto LABEL_84;
+          }
+          if ( !pRenderer->pRenderD3D )
+            goto LABEL_34;
+          memcpy(pContainer, "sp18h1", 7);
+          pRnd->SetRange(1, 6);
+          pContainer[5] = pRnd->GetInRange() + '0';
+          v35 = pBitmaps_LOD->LoadTexture(pContainer, TEXTURE_DEFAULT);
+          v28 = 100;
+          v22 = a2;
+LABEL_157:
+          AddProjectile(v22, v28, v35);
+          goto LABEL_168;
+        }
+        v12 = result - 3010;
+        if ( !v12 )
+        {
+LABEL_171:
+          diffuse = 0xAB450u;
+          goto LABEL_42;
+        }
+        v13 = v12 - 1;
+        if ( !v13 )
+        {
+          v32 = this->uTextureID_effpar1;
+          diffuse = 0xAB450u;
+          goto LABEL_146;
+        }
+        result = v13 - 19;
+        if ( !result )
+          goto LABEL_34;
+        --result;
+        if ( result )
+          goto LABEL_168;
+LABEL_89:
+        v32 = this->uTextureID_effpar1;
+        diffuse = 0x9EB9F1u;
+        goto LABEL_146;
+      }
+      if ( result > 4000 )
+      {
+        result -= 4030;
+        if ( !result || (--result, !result) )
+          goto LABEL_34;
+        result -= 19;
+        v9 = result == 0;
+        goto LABEL_129;
+      }
+      if ( result == 4000 )
+      {
+        if ( !pRenderer->pRenderD3D )
+          goto LABEL_34;
+        _4A7C07(a2);
+        goto LABEL_168;
+      }
+      result -= 3061;
+      if ( !result || (result -= 29) == 0 )
+        goto LABEL_34;
+      v14 = result - 1;
+      if ( !v14 )
+        goto LABEL_89;
+      result = v14 - 1;
+      if ( result )
+        goto LABEL_168;
+      v29 = this->uTextureID_effpar1;
+      v23 = 0x9EB9F1u;
+LABEL_8:
+      _4A73AA_hanging_trace_particles___like_fire_strike_ice_blast_etc(a2, v23, v29);
+      goto LABEL_168;
+    }
+    goto LABEL_122;
+  }
+  if ( result <= 7090 )
+  {
+    if ( result == 7090 )
+      goto LABEL_34;
+    if ( result > 6030 )
+    {
+      if ( result > 6091 )
+      {
+        result -= 6100;
+        if ( !result )
+          goto LABEL_34;
+        result -= 930;
+        if ( result )
+        {
+          --result;
+          if ( result )
+            goto LABEL_168;
+          v30 = this->uTextureID_effpar1;
+          v24 = 0xF00000u;
+          goto LABEL_32;
+        }
+        goto LABEL_63;
+      }
+      if ( result != 6091 )
+      {
+        result -= 6040;
+        if ( !result || (result -= 20) == 0 || (result -= 10) == 0 )
+          goto LABEL_34;
+        result -= 20;
+        v9 = result == 0;
+        goto LABEL_129;
+      }
+    }
+    else
+    {
+      if ( result == 6030 )
+        goto LABEL_34;
+      if ( result <= 4091 )
+      {
+        if ( result != 4091 )
+        {
+          result -= 4070;
+          if ( !result )
+            goto LABEL_34;
+          v15 = result - 1;
+          if ( v15 )
+          {
+            result = v15 - 9;
+            if ( !result )
+              goto LABEL_34;
+            result -= 10;
+            if ( !result )
+            {
+              _4A73AA_hanging_trace_particles___like_fire_strike_ice_blast_etc(
+                a2,
+                0x7E7E7Eu,
+                this->uTextureID_effpar1);
+              goto LABEL_34;
+            }
+            goto LABEL_168;
+          }
+LABEL_115:
+          v30 = this->uTextureID_effpar1;
+          v24 = 0x5C310Eu;
+LABEL_32:
+          _4A75CC_single_spell_collision_particle(a2, v24, v30);
+          goto LABEL_168;
+        }
+        v34 = 200.0;
+        v27 = this->uTextureID_effpar1;
+        v21 = 0x7E7E7Eu;
+        goto LABEL_117;
+      }
+      v16 = result - 4092;
+      if ( !v16 )
+      {
+LABEL_17:
+        v29 = this->uTextureID_effpar1;
+        v23 = 0x7E7E7Eu;
+        goto LABEL_8;
+      }
+      result = v16 - 8;
+      if ( !result )
+        goto LABEL_168;
+      result -= 1910;
+      if ( !result )
+        goto LABEL_34;
+      --result;
+      if ( result )
+        goto LABEL_168;
+    }
+LABEL_122:
+    _4A7948_mind_blast_after_effect(a2);
+    goto LABEL_168;
+  }
+  if ( result <= 9000 )
+  {
+    if ( result == 9000 )
+      goto LABEL_34;
+    if ( result <= 8030 )
+    {
+      if ( result == 8030 )
+        goto LABEL_34;
+      v17 = result - 7091;
+      if ( v17 )
+      {
+        v18 = v17 - 909;
+        if ( !v18 )
+        {
+          diffuse = 0xFFFFFFu;
+          _4A73AA_hanging_trace_particles___like_fire_strike_ice_blast_etc(
+            a2,
+            0xFFFFFFu,
+            this->uTextureID_effpar3);
+          v31 = 128;
+          goto LABEL_44;
+        }
+        v19 = v18 - 1;
+        if ( v19 )
+        {
+          result = v19 - 9;
+          if ( !result )
+          {
+            v31 = 64;
+            v25 = 0xFFFFFFu;
+            goto LABEL_144;
+          }
+          goto LABEL_168;
+        }
+        v32 = this->uTextureID_effpar2;
+        diffuse = 0xFFFFFFu;
+      }
+      else
+      {
+        v32 = this->uTextureID_effpar1;
+        diffuse = 0xF00000u;
+      }
+      goto LABEL_146;
+    }
+    result -= 8040;
+    if ( !result || (result -= 20) == 0 )
+      goto LABEL_34;
+    v20 = result - 30;
+    if ( v20 )
+    {
+      result = v20 - 1;
+      if ( result )
+        goto LABEL_168;
+      v30 = this->uTextureID_effpar3;
+LABEL_154:
+      v24 = 16777215;
+      goto LABEL_32;
+    }
+    result = AddMobileLight(a2, 0xFFFFFFu, 128);
+    if ( !pRenderer->pRenderD3D )
+      goto LABEL_34;
+    v35 = -1;
+    v28 = 100;
+    v22 = a2;
+    goto LABEL_157;
+  }
+  if ( result > 9050 )
+  {
+    result -= 9070;
+    if ( !result || (result -= 10) == 0 || (--result, !result) )
+      goto LABEL_34;
+    goto LABEL_168;
+  }
+  if ( result == 9050 || (result -= 9010) == 0 || (result -= 20) == 0 || (result -= 10) == 0 )
+    goto LABEL_34;
+  --result;
+  if ( !result )
+  {
+LABEL_164:
+    v30 = this->uTextureID_effpar1;
+    v24 = 0x7E7E7Eu;
+    goto LABEL_32;
+  }
+LABEL_168:
+  LOBYTE(result) = 0;
+  return result;
+}
+
+//----- (004A89BD) --------------------------------------------------------
+int stru6::SetPlayerBuffAnim(unsigned __int16 uSpellID, unsigned __int16 uPlayerID)
+{
+  stru6 *v3; // edi@1
+  PlayerBuffAnim *v4; // esi@1
+  int result; // eax@1
+  const char *v6; // [sp-4h] [bp-10h]@2
+
+  v3 = this;
+  v4 = (PlayerBuffAnim *)((char *)this + 16 * (signed __int16)uPlayerID);
+  v4[32].uSpellIconID_ = 0;
+  v4[32].uSpellID = uSpellID;
+  result = (signed __int16)uSpellID - 3;
+  switch ( uSpellID )
+  {
+    case (SPELL_WATER_PROTECTION_FROM_WATER|0x80):
+      v6 = "zapp";
+      goto LABEL_24;
+    case SPELL_AIR_FEATHER_FALL:
+    case SPELL_SPIRIT_DETECT_LIFE:
+    case SPELL_SPIRIT_DOOM:
+    case 0x96u:
+      v6 = "spboost1";
+      goto LABEL_24;
+    case SPELL_AIR_SHIELD|0x2:
+    case SPELL_WATER_WATER_WALK:
+    case SPELL_SPIRIT_PRESERVE:
+    case 0x97u:
+      v6 = "spboost2";
+      goto LABEL_24;
+    case SPELL_BODY_CURE_WEAKNESS|0x10:
+    case SPELL_BODY_FIRST_AID|SPELL_AIR_SHIELD:
+    case 0x56u:
+    case SPELL_BODY_CURE_POISON|0x10:
+    case 0x98u:
+      v6 = "spboost3";
+      goto LABEL_24;
+    case (SPELL_AIR_SHIELD|0x20):
+    case SPELL_MIND_REMOVE_FEAR:
+    case SPELL_BODY_CURE_WEAKNESS:
+      v6 = "spheal1";
+      goto LABEL_24;
+    case SPELL_SPIRIT_PRESERVE|0x4:
+    case SPELL_MIND_CURE_PARALYSIS:
+    case 0x40u:
+    case SPELL_BODY_FIRST_AID:
+    case SPELL_BODY_CURE_POISON:
+    case SPELL_BODY_CURE_DISEASE:
+    case 0x60u:
+      v6 = "spheal2";
+      goto LABEL_24;
+    case SPELL_BODY_HAMMERHANDS|0x4:
+    case SPELL_BODY_CURE_WEAKNESS|0x20:
+      v6 = "spheal3";
+      goto LABEL_24;
+    case SPELL_FIRE_PROTECTION_FROM_FIRE:
+    case SPELL_FIRE_FIRE_RING:
+      v6 = "spell03";
+      goto LABEL_24;
+    case SPELL_FIRE_HASTE:
+      v6 = "spell05";
+      goto LABEL_24;
+    case SPELL_AIR_PROTECTION_FROM_AIR:
+      v6 = "spell14";
+      goto LABEL_24;
+    case SPELL_AIR_SHIELD:
+      v6 = "spell17";
+      goto LABEL_24;
+    case SPELL_WATER_PROTECTION_FROM_WATER:
+      v6 = "spell25";
+      goto LABEL_24;
+    case SPELL_EARTH_PROTECTION_FROM_EARTH:
+      v6 = "spell36";
+      goto LABEL_24;
+    case SPELL_EARTH_STONESKIN:
+      v6 = "spell38";
+      goto LABEL_24;
+    case SPELL_SPIRIT_BLESS:
+      v6 = "spell46";
+      goto LABEL_24;
+    case SPELL_SPIRIT_HEROISM:
+      v6 = "spell51";
+      goto LABEL_24;
+    case SPELL_SPIRIT_HEROISM|0x4:
+      v6 = "spell55";
+      goto LABEL_24;
+    case SPELL_MIND_PROTECTION_FROM_MIND:
+      v6 = "spell58";
+      goto LABEL_24;
+    case SPELL_BODY_FIRST_AID|0x1:
+      v6 = "spell69";
+      goto LABEL_24;
+    case SPELL_BODY_FIRST_AID|SPELL_FIRE_PROTECTION_FROM_FIRE:
+      v6 = "spell71";
+      goto LABEL_24;
+    case SPELL_BODY_HAMMERHANDS:
+      v6 = "spell73";
+      goto LABEL_24;
+    case SPELL_BODY_PROTECTION_FROM_MAGIC:
+      v6 = "spell75";
+LABEL_24:
+      result = pIconsFrameTable->FindIcon(v6);
+      v4[33].uSpellIconID = result;
+      break;
+    default:
+      v4[32].uSpellID = 0;
+      break;
+  }
+  if ( v4[32].uSpellID )
+  {
+    result = 8 * pIconsFrameTable->pIcons[v4[33].uSpellIconID].uAnimLength;
+    v3->array_0[(signed __int16)uPlayerID + 33].uSpellAnimLength = result;
+  }
+  return result;
+}
+
+//----- (004A8BDF) --------------------------------------------------------
+void stru6::FadeScreen__like_Turn_Undead_and_mb_Armageddon(unsigned int uDiffuseColor, unsigned int uFadeTime)
+{
+  this->uFadeTime = uFadeTime;
+  this->uFadeTime2 = uFadeTime;
+  this->uFadeColor = uDiffuseColor;
+}
+
+//----- (004A8BFC) --------------------------------------------------------
+int stru6::_4A8BFC()
+{
+  stru6 *v1; // esi@1
+  int result; // eax@1
+
+  v1 = this;
+  result = 8
+         * pSpriteFrameTable->pSpriteSFrames[pSpriteFrameTable->FastFindSprite("spell84")].uAnimLength;
+  v1->uAnimLength = result;
+  return result;
+}
+
+//----- (004A8C27) --------------------------------------------------------
+void stru6::RenderSpecialEffects()
+{
+  double v4; // st7@4
+  double v5; // st6@4
+  double v6; // st7@4
+  float v7; // ST14_4@6
+  unsigned int v8; // ST14_4@8
+  unsigned int v9; // eax@8
+  SpriteFrame *v10; // eax@8
+  int v11; // edi@8
+  double v12; // st7@9
+  double v13; // st7@9
+  double v14; // st7@9
+  double v15; // st6@9
+  HRESULT v16; // eax@9
+  HRESULT v17; // eax@9
+  signed __int64 v18; // qtt@10
+  const char *v19; // [sp+4h] [bp-E8h]@0
+  int v20; // [sp+8h] [bp-E4h]@0
+  unsigned int v21; // [sp+Ch] [bp-E0h]@0
+  RenderBillboardTransform_local0 vsr; // [sp+10h] [bp-DCh]@10
+  RenderVertexD3D3 vd3d[4]; // [sp+60h] [bp-8Ch]@9
+  int v24; // [sp+E0h] [bp-Ch]@10
+  SpriteFrame *v70; // [sp+E4h] [bp-8h]@8
+  unsigned int v26; // [sp+E8h] [bp-4h]@3
+
+  if (uNumProjectiles)
+  {
+    DrawProjectiles();
+    uNumProjectiles = 0;
+  }
+
+  field_204 = 0;
+  v26 = uFadeTime;
+  if ( v26 > 0 )
+  {
+    v4 = (double)(signed int)v26 / (double)uFadeTime2;
+    v5 = 1.0 - v4 * v4;
+    v6 = v5;
+    if ( v5 > 0.9 )
+      v6 = 1.0 - (v5 - 0.9) * 10.0;
+    v7 = v6;
+    pRenderer->_4A52F1(uFadeColor, v7);
+    uFadeTime -= pEventTimer->uTimeElapsed;
+  }
+
+  if (uAnimLength > 0)
+  {
+    v8 = 8
+       * pSpriteFrameTable->pSpriteSFrames[pSpriteFrameTable->FastFindSprite("spell84")].uAnimLength
+       - uAnimLength;
+    v9 = pSpriteFrameTable->FastFindSprite("spell84");
+    v10 = pSpriteFrameTable->GetFrame(v9, v8);
+    v11 = v10->pHwSpriteIDs[0];
+    v70 = v10;
+    uAnimLength -= pEventTimer->uTimeElapsed;
+    if ( pRenderer->pRenderD3D )
+    {
+      v12 = (double)(signed int)pViewport->uViewportX;
+      vd3d[0].pos.x = v12;
+      vd3d[1].pos.x = v12;
+      v13 = (double)(signed int)pViewport->uViewportZ;
+      v26 = pViewport->uViewportW + 1;
+      vd3d[0].diffuse = 0x7F7F7Fu;
+      vd3d[1].diffuse = 0x7F7F7Fu;
+      vd3d[2].pos.x = v13;
+      vd3d[3].pos.x = v13;
+      v14 = (double)(signed int)pViewport->uViewportY;
+      vd3d[2].diffuse = 0x7F7F7Fu;
+      vd3d[3].diffuse = 0x7F7F7Fu;
+      vd3d[0].specular = 0;
+      vd3d[1].specular = 0;
+      vd3d[0].pos.y = v14;
+      v15 = (double)(pViewport->uViewportW + 1);
+      vd3d[2].specular = 0;
+      vd3d[3].specular = 0;
+      vd3d[1].pos.y = v15;
+      vd3d[2].pos.y = v15;
+      vd3d[3].pos.y = v14;
+      vd3d[0].pos.z = 0.0;
+      vd3d[1].pos.z = 0.0;
+      vd3d[2].pos.z = 0.0;
+      vd3d[3].pos.z = 0.0;
+      vd3d[0].rhw = 1.0;
+      vd3d[1].rhw = 1.0;
+      vd3d[2].rhw = 1.0;
+      vd3d[3].rhw = 1.0;
+      vd3d[0].texcoord.x = 0.0;
+      vd3d[1].texcoord.x = 0.0;
+      vd3d[2].texcoord.x = 1.0;
+      vd3d[3].texcoord.x = 1.0;
+      vd3d[0].texcoord.y = 0.0;
+      vd3d[1].texcoord.y = 1.0;
+      vd3d[2].texcoord.y = 1.0;
+      vd3d[3].texcoord.y = 0.0;
+      pRenderer->pRenderD3D->pDevice->SetTexture(
+        0,
+        pSprites_LOD->pHardwareSprites[v11].pTexture);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 2u);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 0);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, 8u);
+      pRenderer->pRenderD3D->pDevice->DrawPrimitive(
+        D3DPT_TRIANGLEFAN,
+        D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+        vd3d,
+        4,
+        28);
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2),
+                  "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\seffects.cpp:1348");
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1),
+                  "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\seffects.cpp:1349");
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, true);
+      pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, 2);
+    }
+    else
+    {
+      vsr.pTarget = pRenderer->pTargetSurface;
+      vsr.uParentBillboardID = -1;
+      vsr.pTargetZ = pRenderer->pActiveZBuffer;
+      vsr.uScreenSpaceX = (signed int)(pViewport->uViewportZ - pViewport->uViewportX) / 2;
+      vsr.uScreenSpaceY = pViewport->uViewportW;
+      v24 = 16777216;
+      LODWORD(v18) = 0;
+      HIDWORD(v18) = (signed __int16)(LOWORD(pViewport->uViewportZ) - LOWORD(pViewport->uViewportX));
+      vsr.field_10 = v18 / 16777216;
+      LODWORD(v18) = 0;
+      HIDWORD(v18) = (signed __int16)(LOWORD(pViewport->uViewportW) - LOWORD(pViewport->uViewportY));
+      v26 = v18 / 16777216;
+      vsr.field_14 = v18 / 16777216;
+      vsr.pPalette = PaletteManager::Get_Dark_or_Red_LUT(v70->uPaletteIndex, 0, 1);
+      vsr.uTargetPitch = pRenderer->uTargetSurfacePitch;
+      vsr.uParentBillboardID = -1;
+      vsr.uViewportX = pViewport->uViewportX;
+      vsr.uViewportZ = pViewport->uViewportZ;
+      vsr.uViewportY = pViewport->uViewportY;
+      vsr.sZValue = 0;
+      vsr.uViewportW = pViewport->uViewportW;
+      vsr.uFlags = 0;
+      if ( v11 >= 0 )
+        pSprites_LOD->pSpriteHeaders[v11]._4ACC38(&vsr, 1);
+    }
+  }
+}
+
+//----- (004A902A) --------------------------------------------------------
+void stru6::DrawPlayerBuffAnims()
+{
+  __int16 *v1; // edi@1
+  char *v2; // esi@1
+  unsigned int v3; // eax@3
+  unsigned __int8 v4; // zf@3
+  char v5; // sf@3
+  unsigned __int8 v6; // of@3
+  IconFrame *v7; // eax@4
+
+  uint _it = 0;
+  v1 = pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing;
+  v2 = (char *)&this->pPlayerBuffs[0].uSpellIconID;
+  do
+  {
+    if ( *((short *)v2 - 2) )
+    {
+      v3 = pEventTimer->uTimeElapsed + *(int *)v2;
+      v6 = __OFSUB__(v3, *((int *)v2 + 1));
+      v4 = v3 == *((int *)v2 + 1);
+      v5 = ((v3 - *((int *)v2 + 1)) & 0x80000000u) != 0;
+      *(int *)v2 = v3;
+      if ( (unsigned __int8)(v5 ^ v6) | v4 )
+      {
+        v7 = pIconsFrameTable->GetFrame(*((int *)v2 + 2), v3);
+        pRenderer->DrawTextureTransparent(*v1, 0x181u, &pIcons_LOD->pTextures[v7->uTextureID]);
+        pOtherOverlayList->field_3EC = 1;
+      }
+      else
+      {
+        *((short *)v2 - 2) = 0;
+      }
+    }
+    v2 += 16;
+    ++v1;
+  }
+  //while ( (signed int)v1 < (signed int)pBaseHealthByClass );
+  while (++_it != 4);
+}
+
+//----- (004A90A0) --------------------------------------------------------
+void stru6::LoadAnimations()
+{
+  stru6 *v1; // esi@1
+  unsigned int v2; // eax@1
+  unsigned int v3; // eax@1
+  unsigned int v4; // eax@1
+  unsigned int v5; // eax@1
+  unsigned int v6; // eax@1
+  unsigned int v7; // eax@1
+  unsigned int v8; // eax@1
+  unsigned int v9; // eax@1
+  unsigned int v10; // eax@1
+  unsigned int v11; // eax@1
+  unsigned int v12; // eax@1
+  unsigned int v13; // eax@1
+  unsigned int v14; // eax@1
+  unsigned int v15; // eax@1
+  unsigned int v16; // eax@1
+  unsigned int v17; // eax@1
+  unsigned int v18; // eax@1
+  unsigned int v19; // eax@1
+  unsigned int v20; // eax@1
+  unsigned int v21; // eax@1
+  unsigned int v22; // eax@1
+  unsigned int v23; // eax@1
+  unsigned int v24; // eax@1
+  unsigned int v25; // eax@1
+  unsigned int v26; // eax@1
+  unsigned int v27; // eax@1
+  unsigned int v28; // eax@1
+  unsigned int v29; // eax@1
+  unsigned int v30; // eax@1
+  unsigned int v31; // eax@1
+  unsigned int v32; // eax@1
+  unsigned int v33; // eax@1
+  unsigned int v34; // eax@1
+  unsigned int v35; // eax@1
+  unsigned int v36; // eax@1
+  unsigned int v37; // eax@1
+  unsigned int v38; // eax@1
+  unsigned int v39; // eax@1
+  unsigned int v40; // eax@1
+  unsigned int v41; // eax@1
+  unsigned int v42; // eax@1
+  unsigned int v43; // eax@1
+  unsigned int v44; // eax@1
+  unsigned int v45; // eax@1
+  unsigned int v46; // eax@1
+  unsigned int v47; // eax@1
+  unsigned int v48; // eax@1
+  unsigned int v49; // eax@1
+  unsigned int v50; // eax@1
+  unsigned int v51; // eax@1
+
+  v1 = this;
+  uTextureID_effpar1 = pBitmaps_LOD->LoadTexture("effpar01", TEXTURE_DEFAULT);
+  uTextureID_effpar2 = pBitmaps_LOD->LoadTexture("effpar02", TEXTURE_DEFAULT);
+  uTextureID_effpar3 = pBitmaps_LOD->LoadTexture("effpar03", TEXTURE_DEFAULT);
+  uSpriteID_sp57c = pSprites_LOD->LoadSprite("sp57c", 6);
+  v2 = pIconsFrameTable->FindIcon("zapp");
+  pIconsFrameTable->InitializeAnimation(v2);
+  v3 = pIconsFrameTable->FindIcon("spheal1");
+  pIconsFrameTable->InitializeAnimation(v3);
+  v4 = pIconsFrameTable->FindIcon("spheal2");
+  pIconsFrameTable->InitializeAnimation(v4);
+  v5 = pIconsFrameTable->FindIcon("spheal3");
+  pIconsFrameTable->InitializeAnimation(v5);
+  v6 = pIconsFrameTable->FindIcon("spboost1");
+  pIconsFrameTable->InitializeAnimation(v6);
+  v7 = pIconsFrameTable->FindIcon("spboost2");
+  pIconsFrameTable->InitializeAnimation(v7);
+  v8 = pIconsFrameTable->FindIcon("spboost3");
+  pIconsFrameTable->InitializeAnimation(v8);
+  v9 = pIconsFrameTable->FindIcon("spell03");
+  pIconsFrameTable->InitializeAnimation(v9);
+  v10 = pIconsFrameTable->FindIcon("spell05");
+  pIconsFrameTable->InitializeAnimation(v10);
+  v11 = pIconsFrameTable->FindIcon("spell14");
+  pIconsFrameTable->InitializeAnimation(v11);
+  v12 = pIconsFrameTable->FindIcon("spell17");
+  pIconsFrameTable->InitializeAnimation(v12);
+  v13 = pIconsFrameTable->FindIcon("spell21");
+  pIconsFrameTable->InitializeAnimation(v13);
+  v14 = pIconsFrameTable->FindIcon("spell25");
+  pIconsFrameTable->InitializeAnimation(v14);
+  v15 = pIconsFrameTable->FindIcon("spell27");
+  pIconsFrameTable->InitializeAnimation(v15);
+  v16 = pIconsFrameTable->FindIcon("spell36");
+  pIconsFrameTable->InitializeAnimation(v16);
+  v17 = pIconsFrameTable->FindIcon("spell38");
+  pIconsFrameTable->InitializeAnimation(v17);
+  v18 = pIconsFrameTable->FindIcon("spell46");
+  pIconsFrameTable->InitializeAnimation(v18);
+  v19 = pIconsFrameTable->FindIcon("spell51");
+  pIconsFrameTable->InitializeAnimation(v19);
+  v20 = pIconsFrameTable->FindIcon("spell55");
+  pIconsFrameTable->InitializeAnimation(v20);
+  v21 = pIconsFrameTable->FindIcon("spell58");
+  pIconsFrameTable->InitializeAnimation(v21);
+  v22 = pIconsFrameTable->FindIcon("spell69");
+  pIconsFrameTable->InitializeAnimation(v22);
+  v23 = pIconsFrameTable->FindIcon("spell71");
+  pIconsFrameTable->InitializeAnimation(v23);
+  v24 = pIconsFrameTable->FindIcon("spell73");
+  pIconsFrameTable->InitializeAnimation(v24);
+  v25 = pIconsFrameTable->FindIcon("spell75");
+  pIconsFrameTable->InitializeAnimation(v25);
+  v26 = pIconsFrameTable->FindIcon("spell96");
+  pIconsFrameTable->InitializeAnimation(v26);
+
+  v27 = pSpriteFrameTable->FastFindSprite("spell01");
+  pSpriteFrameTable->InitializeSprite(v27);
+  v28 = pSpriteFrameTable->FastFindSprite("spell02");
+  pSpriteFrameTable->InitializeSprite(v28);
+  v29 = pSpriteFrameTable->FastFindSprite("spell03");
+  pSpriteFrameTable->InitializeSprite(v29);
+  v30 = pSpriteFrameTable->FastFindSprite("spell09");
+  pSpriteFrameTable->InitializeSprite(v30);
+  v31 = pSpriteFrameTable->FastFindSprite("spell11");
+  pSpriteFrameTable->InitializeSprite(v31);
+  v32 = pSpriteFrameTable->FastFindSprite("spell18");
+  pSpriteFrameTable->InitializeSprite(v32);
+  v33 = pSpriteFrameTable->FastFindSprite("spell22");
+  pSpriteFrameTable->InitializeSprite(v33);
+  v34 = pSpriteFrameTable->FastFindSprite("spell26");
+  pSpriteFrameTable->InitializeSprite(v34);
+  v35 = pSpriteFrameTable->FastFindSprite("spell29");
+  pSpriteFrameTable->InitializeSprite(v35);
+  v36 = pSpriteFrameTable->FastFindSprite("spell39");
+  pSpriteFrameTable->InitializeSprite(v36);
+  v37 = pSpriteFrameTable->FastFindSprite("spell39c");
+  pSpriteFrameTable->InitializeSprite(v37);
+  v38 = pSpriteFrameTable->FastFindSprite("spell41");
+  pSpriteFrameTable->InitializeSprite(v38);
+  v39 = pSpriteFrameTable->FastFindSprite("spell57c");
+  pSpriteFrameTable->InitializeSprite(v39);
+  v40 = pSpriteFrameTable->FastFindSprite("spell62");
+  pSpriteFrameTable->InitializeSprite(v40);
+  v41 = pSpriteFrameTable->FastFindSprite("spell65");
+  pSpriteFrameTable->InitializeSprite(v41);
+  v42 = pSpriteFrameTable->FastFindSprite("spell66");
+  pSpriteFrameTable->InitializeSprite(v42);
+  v43 = pSpriteFrameTable->FastFindSprite("spell70");
+  pSpriteFrameTable->InitializeSprite(v43);
+  v44 = pSpriteFrameTable->FastFindSprite("spell76");
+  pSpriteFrameTable->InitializeSprite(v44);
+  v45 = pSpriteFrameTable->FastFindSprite("spell84");
+  pSpriteFrameTable->InitializeSprite(v45);
+  v46 = pSpriteFrameTable->FastFindSprite("spell90");
+  pSpriteFrameTable->InitializeSprite(v46);
+  v47 = pSpriteFrameTable->FastFindSprite("spell92");
+  pSpriteFrameTable->InitializeSprite(v47);
+  v48 = pSpriteFrameTable->FastFindSprite("spell93");
+  pSpriteFrameTable->InitializeSprite(v48);
+  v49 = pSpriteFrameTable->FastFindSprite("spell97");
+  pSpriteFrameTable->InitializeSprite(v49);
+  v50 = pSpriteFrameTable->FastFindSprite("spell97c");
+  pSpriteFrameTable->InitializeSprite(v50);
+  v51 = pSpriteFrameTable->FastFindSprite("spell97c");
+  pSpriteFrameTable->InitializeSprite(v51);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru6.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,164 @@
+#pragma once
+#include "Render.h"
+
+
+/*  120 */
+#pragma pack(push, 1)
+struct stru6_stru1_indoor_sw_billboard
+{
+  //----- (004775B1) --------------------------------------------------------
+  inline stru6_stru1_indoor_sw_billboard()
+  {
+    field_10 = 0;
+    uNumVec4sInArray1 = 0;
+    uNumVec3sInArray2 = 0;
+    pArray1 = nullptr;
+    pArray2 = nullptr;
+  }
+
+  //----- (004775C4) --------------------------------------------------------
+  virtual ~stru6_stru1_indoor_sw_billboard()
+  {
+    if (pArray1)
+      delete [] pArray1;
+    pArray1 = nullptr;
+
+    if (pArray2)
+      delete [] pArray2;
+    pArray2 = nullptr;
+  }
+
+  int _4775ED(float a2);
+  int _477927(float a2);
+  int sub_477C61();
+  bool sub_477F63();
+  int sub_47802A();
+  void Initialize(int a2);
+  void _47829F_fireball_collision(float arg0, float a3, float a4, float a5, int a2);
+
+
+  unsigned int uNumVec4sInArray1;
+  struct stru16x *pArray1;
+  unsigned int uNumVec3sInArray2;
+  struct stru160 *pArray2;
+  int field_10;
+  int field_14[80];
+};
+#pragma pack(pop)
+
+
+/*  122 */
+#pragma pack(push, 1)
+struct PlayerBuffAnim
+{
+  __int16 bRender;
+  __int16 field_2;
+  int uSpellIconID;
+  __int16 uSpellID;
+  __int16 field_A;
+  int uSpellIconID_;
+};
+#pragma pack(pop)
+
+
+/*  307 */
+#pragma pack(push, 1)
+struct ProjectileAnim
+{
+  float srcX;
+  float srcY;
+  float srcZ;
+  float dstX;
+  float dstY;
+  float dstZ;
+  int uTextureID;
+};
+#pragma pack(pop)
+
+
+/*  306 */
+#pragma pack(push, 1)
+struct stru6_stru2
+{
+  int uSpellAnimLength;
+  float flt_4;
+  float flt_8;
+  float flt_C;
+};
+#pragma pack(pop)
+
+
+
+/*  121 */
+#pragma pack(push, 1)
+struct stru6
+{
+  //----- (004A7155) --------------------------------------------------------
+  stru6()
+  {
+    this->pPlayerBuffs[0].bRender = 0;
+    this->pPlayerBuffs[1].bRender = 0;
+    this->pPlayerBuffs[2].bRender = 0;
+    this->pPlayerBuffs[3].bRender = 0;
+    this->field_204 = 0;
+    this->uFadeTime = 0;
+    this->uNumProjectiles = 0;
+    this->array_0[0].uSpellAnimLength = 0;
+
+    pStru1 = new stru6_stru1_indoor_sw_billboard;
+    pStru1->Initialize(0xFF3C1Eu);
+  }
+  //----- (004A71DC) --------------------------------------------------------
+  ~stru6()
+  {
+    if (pStru1)
+      delete pStru1;
+    pStru1 = nullptr;
+  }
+
+  void DoAddProjectile(float srcX, float srcY, float srcZ, float dstX, float dstY, float dstZ, unsigned int uTextureID);
+  void DrawProjectiles();
+  void _4A73AA_hanging_trace_particles___like_fire_strike_ice_blast_etc(struct LayingItem *a2, unsigned int uDiffuse, unsigned int uTextureID);
+  void _4A75CC_single_spell_collision_particle(struct LayingItem *a1, unsigned int uDiffuse, unsigned int uTextureID);
+  void _4A7688_fireball_collision_particle(struct LayingItem *a2);
+  void _4A77FD_some_stuff_d3d(struct LayingItem *a1);
+  void _4A78AE_sparks_spell(struct LayingItem *a1);
+  void _4A7948_mind_blast_after_effect(struct LayingItem *a1);
+  bool AddMobileLight(struct LayingItem *a1, unsigned int uDiffuse, int uRadius);
+  void _4A7A66_miltiple_spell_collision_partifles___like_after_sparks_or_lightning(LayingItem *a1, unsigned int uDiffuse, unsigned int uTextureID, float a4);
+  void _4A7C07(struct LayingItem *a2);
+  void AddProjectile(struct LayingItem *a2, int a3, unsigned int uTextureID);
+  int _4A7E89_sparkles_on_actor_after_it_casts_buff(struct Actor *pActor, unsigned int uDiffuse);
+  void _4A7F74(int x, int y, int z);
+  int _4A806F(struct Actor *pActor);
+  void _4A80DC_some_stuff_sw(struct LayingItem *a2);
+  bool _4A81CA(struct LayingItem *a2);
+  int SetPlayerBuffAnim(unsigned __int16 uSpellID, unsigned __int16 uPlayerID);
+  void FadeScreen__like_Turn_Undead_and_mb_Armageddon(unsigned int uDiffuseColor, unsigned int uFadeTime);
+  int _4A8BFC();
+  void RenderSpecialEffects();
+  void DrawPlayerBuffAnims();
+  void LoadAnimations();
+
+
+  stru6_stru2 array_0[32];
+  int field_200;
+  int field_204;
+  PlayerBuffAnim pPlayerBuffs[4];
+  ProjectileAnim pProjectiles[32];
+  int uNumProjectiles;
+  stru6_stru1_indoor_sw_billboard *pStru1;
+  int field_5D0;
+  int uAnimLength;
+  int uFadeTime;
+  int uFadeTime2;
+  int uFadeColor;
+  unsigned int uTextureID_effpar1;
+  unsigned int uTextureID_effpar2;
+  unsigned int uTextureID_effpar3;
+  unsigned int uSpriteID_sp57c;
+  int field_5F4;
+};
+#pragma pack(pop)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru9.cpp	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,437 @@
+#include "stru9.h"
+#include "IndoorCameraD3D.h"
+
+#include "mm7_data.h"
+
+
+
+//----- (00498377) --------------------------------------------------------
+bool stru9::_498377(struct RenderVertexSoft *a1, unsigned int uNumVertices, struct IndoorCameraD3D_Vec4 *a3, struct RenderVertexSoft *pVertices, unsigned int *pOutNumVertices)
+{
+  bool result; // eax@7
+  unsigned int *v7; // ebx@7
+  char *v8; // esi@8
+  RenderVertexSoft *v9; // ecx@9
+  double v10; // st7@12
+  double v11; // st6@12
+  RenderVertexSoft *v12; // esi@13
+  int v13; // ecx@25
+  VertexBuffer *v14; // edx@26
+  char *v15; // eax@26
+  unsigned int i; // ecx@26
+  bool v17; // [sp+0h] [bp-28h]@9
+  char *v18; // [sp+10h] [bp-18h]@8
+  RenderVertexSoft *v19; // [sp+14h] [bp-14h]@0
+  RenderVertexSoft *v20; // [sp+18h] [bp-10h]@0
+  signed int v21; // [sp+1Ch] [bp-Ch]@7
+  RenderVertexSoft *a2; // [sp+20h] [bp-8h]@8
+  stru9 *thisa; // [sp+24h] [bp-4h]@1
+  signed int a3a; // [sp+38h] [bp+10h]@12
+  int a3b; // [sp+38h] [bp+10h]@25
+
+  __debugbreak();
+
+  thisa = this;
+
+  static RenderVertexSoft static_AE3FB4;
+  static bool __init_flag1 = false;
+  if (!__init_flag1)
+  {
+    __init_flag1 = true;
+
+    static_AE3FB4.flt_2C = 0.0;
+  }
+
+  static stru312 static_AE3FA4; // idb
+  static bool __init_flag2 = false;
+  if (!__init_flag2)
+  {
+    __init_flag2 = true;
+
+    //stru312::stru312(&static_AE3FA4);
+  }
+
+  static VertexBuffer static_AE33A0; // idb
+  static bool __init_flag3 = false;
+  if (!__init_flag3)
+  {
+    __init_flag3 = true;
+
+    //VertexBuffer::VertexBuffer(&static_AE33A0);
+  }
+
+  result = 0;
+  v7 = pOutNumVertices;
+  v21 = 0;
+  if ( (signed int)uNumVertices <= 0 )
+    goto LABEL_32;
+  a2 = a1;
+  v8 = (char *)&a3->y;
+  v18 = (char *)&a3->y;
+  do
+  {
+    v17 = result + 1;
+    v9 = &a1[(result + 1) % (signed int)uNumVertices];
+    if ( a2->vWorldPosition.x != v9->vWorldPosition.x
+      || a2->vWorldPosition.y != v9->vWorldPosition.y
+      || a2->vWorldPosition.z != v9->vWorldPosition.z )
+    {
+      v10 = *((float *)v8 + 1);
+      v11 = *(float *)v8;
+      ++v21;
+      result = 0;
+      static_AE3FA4.x = *((float *)v8 - 1);
+      static_AE33A0.uNumVertices = 0;
+      a3a = 0;
+      static_AE3FA4.y = v11;
+      static_AE3FA4.z = v10;
+      if ( (signed int)*v7 <= 0 )
+        goto LABEL_32;
+      do
+      {
+        v12 = &pVertices[result];
+        if ( result )
+        {
+          if ( _4989E1(v20, &pVertices[result], a2, &static_AE3FA4)
+            && _498774(v20, v12, a2, &static_AE3FA4, &static_AE3FB4) )
+            AddVertex(&static_AE33A0, &static_AE3FB4);
+        }
+        else
+        {
+          v19 = &pVertices[result];
+        }
+        v20 = v12;
+        if ( AreVectorsCollinear(v12, a2, &static_AE3FA4) )
+          AddVertex(&static_AE33A0, v12);
+        v7 = pOutNumVertices;
+        result = a3a++ + 1;
+      }
+      while ( a3a < (signed int)*pOutNumVertices );
+      if ( !static_AE33A0.uNumVertices )
+        goto LABEL_32;
+      if ( _4989E1(v12, v19, a2, &static_AE3FA4)
+        && _498774(v12, v19, a2, &static_AE3FA4, &static_AE3FB4) )
+        AddVertex(&static_AE33A0, &static_AE3FB4);
+      v13 = static_AE33A0.uNumVertices;
+      a3b = 0;
+      if ( static_AE33A0.uNumVertices > 0 )
+      {
+        v14 = &static_AE33A0;
+        v15 = (char *)&pVertices->vWorldPosition.y;
+        for ( i = (char *)&static_AE33A0.pVertices[0].vWorldPosition.y - (char *)pVertices;
+              ;
+              i = (char *)&static_AE33A0.pVertices[0].vWorldPosition.y - (char *)pVertices )
+        {
+          ++a3b;
+          *((int *)v15 - 1) = *(unsigned int *)(&v14->pVertices[0].vWorldPosition.x);
+          v14 = (VertexBuffer *)((char *)v14 + 48);
+          *(float *)v15 = *(float *)&v15[(char *)&static_AE33A0 - (char *)pVertices];
+          *((float *)v15 + 1) = *(float *)&v15[i];
+          *((float *)v15 + 8) = *(float *)&v15[(char *)&static_AE33A0.pVertices[0].flt_20 - (char *)pVertices];
+          *((float *)v15 + 9) = *(float *)&v15[(char *)&static_AE33A0.pVertices[0].u - (char *)pVertices];
+          v13 = static_AE33A0.uNumVertices;
+          v15 += 48;
+          if ( a3b >= static_AE33A0.uNumVertices )
+            break;
+        }
+      }
+      v7 = pOutNumVertices;
+      v8 = v18;
+      *pOutNumVertices = v13;
+    }
+    result = v17;
+    ++a2;
+    v8 += 24;
+    v18 = v8;
+  }
+  while ( v17 < (signed int)uNumVertices );
+  if ( v21 < 3 )
+LABEL_32:
+    *v7 = 0;
+  return 1;
+}
+// AE3FE4: using guessed type char static_init_flag__AE3FB4_bit1__AE3FA4_bit2__AE33A0_bit3;
+
+//----- (004985FB) --------------------------------------------------------
+bool stru9::_4985FB(struct RenderVertexSoft *a1, signed int a2, struct RenderVertexSoft *a3, unsigned int *pOutNumVertices, struct Vec3_float_ *a5, float a6, char *a7, int unused)
+{
+  RenderVertexSoft *v9; // ecx@1
+  Vec3_float_ *v10; // esi@1
+  //char *v11; // ebx@1
+  RenderVertexSoft *v12; // edi@1
+  double v13; // st7@1
+  //bool result; // eax@4
+  signed int v15; // edx@9
+  RenderVertexSoft *v16; // ecx@9
+  double v17; // st7@9
+  double v18; // st6@12
+  signed int v19; // [sp+Ch] [bp-Ch]@7
+  float v20; // [sp+10h] [bp-8h]@1
+  bool v21; // [sp+14h] [bp-4h]@2
+
+  v9 = a1;
+  v10 = a5;
+  //v11 = (char *)&a1->vWorldPosition.z;
+  auto v11 = a1;
+  v12 = a3;
+  v13 = a1->vWorldPosition.y * a5->y + a5->x * a1->vWorldPosition.x + a1->vWorldPosition.z * a5->z;
+  v20 = v13;
+  v21 = v13 >= a6;
+
+  *pOutNumVertices = 0;
+  if ( a2 <= 0 )
+    return false;
+  v19 = 1;
+  while ( 1 )
+  {
+    if ( v21 )
+    {
+      ++a3;
+      memcpy(v12, v11, sizeof(RenderVertexSoft));
+      ++*pOutNumVertices;
+      v10 = a5;
+      v12 = a3;
+      v9 = a1;
+    }
+    v15 = 0;
+    v16 = &v9[v19 % a2];
+    v17 = v16->vWorldPosition.z * v10->z + v16->vWorldPosition.y * v10->y + v10->x * v16->vWorldPosition.x;
+    if ( v17 >= a6 )
+      v15 = 1;
+    if ( v21 != v15 )
+    {
+      v18 = (a6 - v20) / (v17 - v20);
+      v12->vWorldPosition.x = (v16->vWorldPosition.x - v11->vWorldPosition.x) * v18 + v11->vWorldPosition.x;
+      v12->vWorldPosition.y = (v16->vWorldPosition.y - v11->vWorldPosition.y) * v18 + v11->vWorldPosition.y;
+      v12->vWorldPosition.z = (v16->vWorldPosition.z - v11->vWorldPosition.z) * v18 + v11->vWorldPosition.z;
+      v12->u = (v16->u - v11->u) * v18 + v11->u;
+      v12->v = (v16->v - v11->v) * v18 + v11->v;
+      ++v12;
+      a3 = v12;
+      ++*pOutNumVertices;
+      *a7 = 1;
+    }
+
+    v11++;
+    v21 = v15;
+    v20 = v17;
+    if ( v19 >= a2 )
+      break;
+    v9 = a1;
+    v19++;
+  }
+
+  return *pOutNumVertices >= 3;
+}
+
+//----- (00498737) --------------------------------------------------------
+void stru9::AddVertex(struct VertexBuffer *pVertexBuffer, struct RenderVertexSoft *pVertex)
+{
+  __debugbreak();
+  RenderVertexSoft *v3; // eax@1
+
+  v3 = &pVertexBuffer->pVertices[pVertexBuffer->uNumVertices];
+  v3->vWorldPosition.x = pVertex->vWorldPosition.x;
+  v3->vWorldPosition.y = pVertex->vWorldPosition.y;
+  v3->vWorldPosition.z = pVertex->vWorldPosition.z;
+  v3->u = pVertex->u;
+  v3->v = pVertex->v;
+  ++pVertexBuffer->uNumVertices;
+}
+
+//----- (00498774) --------------------------------------------------------
+bool stru9::_498774(struct RenderVertexSoft *a1, struct RenderVertexSoft *a2, struct RenderVertexSoft *a3, struct stru312 *a4, struct RenderVertexSoft *a5)
+{
+  RenderVertexSoft *v6; // ecx@5
+  bool result; // eax@5
+  double v8; // st7@5
+  __int16 v9; // fps@5
+  double v10; // st7@6
+  double v11; // st6@8
+  double v12; // st6@18
+  char v13; // c0@24
+  char v14; // c2@24
+  char v15; // c3@24
+  float a1a; // [sp+10h] [bp+8h]@5
+
+  __debugbreak();
+  
+  static stru312 static_AE3388;
+  static stru312 static_AE3378;
+
+  v6 = a1;
+  static_AE3378.x = a1->vWorldPosition.x - a3->vWorldPosition.x;
+  static_AE3378.y = a1->vWorldPosition.y - a3->vWorldPosition.y;
+  HIWORD(result) = HIWORD(a4);
+  static_AE3378.z = a1->vWorldPosition.z - a3->vWorldPosition.z;
+  static_AE3388.x = a2->vWorldPosition.x - a1->vWorldPosition.x;
+  static_AE3388.y = a2->vWorldPosition.y - a1->vWorldPosition.y;
+  static_AE3388.z = a2->vWorldPosition.z - a1->vWorldPosition.z;
+  a1a = static_AE3388.x * a4->x + static_AE3388.z * a4->z + static_AE3388.y * a4->y;
+  v8 = static_AE3378.x * a4->x + static_AE3378.z * a4->z + static_AE3378.y * a4->y;
+  //UNDEF(v9);
+  if ( a1a != 0.0 )
+  {
+    v10 = -(v8 / a1a);
+    if ( a1a <= 0.0 )
+    {
+      if ( v10 <= 0.0 )
+        v12 = 0.0;
+      else
+        v12 = v10;
+      if ( v12 <= 1.0 )
+      {
+        if ( v10 <= 0.0 )
+          v10 = (float)0.0;
+      }
+      else
+      {
+        v10 = 1.0;
+      }
+    }
+    else
+    {
+      if ( v10 >= 1.0 )
+        v11 = 1.0;
+      else
+        v11 = v10;
+      if ( v11 >= 0.0 )
+      {
+        if ( v10 >= 1.0 )
+          v10 = (float)1.0;
+      }
+      else
+      {
+        v10 = 0.0;
+      }
+    }
+    result = (bool)a5;
+    a5->vWorldPosition.x = (a2->vWorldPosition.x - v6->vWorldPosition.x) * v10 + v6->vWorldPosition.x;
+    a5->vWorldPosition.y = (a2->vWorldPosition.y - v6->vWorldPosition.y) * v10 + v6->vWorldPosition.y;
+    a5->vWorldPosition.z = (a2->vWorldPosition.z - v6->vWorldPosition.z) * v10 + v6->vWorldPosition.z;
+    a5->u = (a2->u - v6->u) * v10 + v6->u;
+    a5->v = (a2->v - v6->v) * v10 + v6->v;
+    goto LABEL_15;
+  }
+  v13 = v8 < 0.0;
+  v14 = 0;
+  v15 = v8 == 0.0;
+  BYTE1(result) = HIBYTE(v9);
+  if ( v8 < 0.0 )
+  {
+LABEL_15:
+    LOBYTE(result) = 1;
+    return result;
+  }
+  LOBYTE(result) = 0;
+  return result;
+}
+// AE3398: using guessed type char static_init_flag__AE3388_bit1__AE3378_bit2;
+
+//----- (0049895A) --------------------------------------------------------
+bool stru9::AreVectorsCollinear(struct RenderVertexSoft *a1, struct RenderVertexSoft *a2, struct stru312 *a3)
+{
+  static stru312 static_F942A0;
+
+  static_F942A0.x = a1->vWorldPosition.x - a2->vWorldPosition.x;
+  static_F942A0.y = a1->vWorldPosition.y - a2->vWorldPosition.y;
+  static_F942A0.z = a1->vWorldPosition.z - a2->vWorldPosition.z;
+
+  static float flt_F942B4 = static_F942A0.z * a3->z + static_F942A0.y * a3->y + static_F942A0.x * a3->x;
+  if (flt_F942B4 >= 0)
+    return true;
+  return false;
+}
+
+
+//----- (004989E1) --------------------------------------------------------
+bool stru9::_4989E1(struct RenderVertexSoft *a1, struct RenderVertexSoft *a2, struct RenderVertexSoft *a3, struct stru312 *a4)
+{
+  bool r1;
+  bool r2;
+
+  r1 = AreVectorsCollinear(a1, a3, a4);
+  r2 = AreVectorsCollinear(a2, a3, a4);
+  return !r1 && r2 == 1 ||
+         r1 == 1 && !r2;
+}
+
+//----- (004980B9) --------------------------------------------------------
+bool stru9::_4980B9(RenderVertexSoft *a1, unsigned int uNumVertices, float a3, float a4, float a5, RenderVertexSoft *pOutVertices, unsigned int *pOutNumVertices)
+{
+  RenderVertexSoft *v12; // ecx@9
+  double v13; // st7@12
+  double v14; // st6@12
+  double v15; // st5@12
+  signed int v25; // [sp+18h] [bp-Ch]@7
+
+  static RenderVertexSoft stru_AE4BFC;
+  static stru312 static_sub_4980B9_stru_AE4BEC; // idb
+  static VertexBuffer static_sub_4980B9_stru_AE3FE8; // idb
+
+  v25 = 0;
+  if (uNumVertices <= 0)
+  {
+    *pOutNumVertices = 0;
+    return true;
+  }
+
+  for (uint i = 0; i < uNumVertices; ++i)
+  {
+    v12 = &a1[(i + 1) % uNumVertices];
+    if (a1[i].vWorldPosition.x != v12->vWorldPosition.x ||
+        a1[i].vWorldPosition.y != v12->vWorldPosition.y ||
+        a1[i].vWorldPosition.z!= v12->vWorldPosition.z)
+    {
+      v13 = v12->vWorldPosition.x - a1[i].vWorldPosition.x;
+      v14 = v12->vWorldPosition.y - a1[i].vWorldPosition.y;
+      v15 = v12->vWorldPosition.z - a1[i].vWorldPosition.z;
+      ++v25;
+
+      static_sub_4980B9_stru_AE3FE8.uNumVertices = 0;
+      static_sub_4980B9_stru_AE4BEC.x = a4 * v15 - v14 * a5;
+      static_sub_4980B9_stru_AE4BEC.y = v13 * a5 - v15 * a3;
+      static_sub_4980B9_stru_AE4BEC.z = v14 * a3 - v13 * a4;
+      if (*pOutNumVertices == 0)
+        return true;
+
+      for (uint j = 0; j < *pOutNumVertices; ++j)
+      {
+        if (j)
+        {
+          if (_4989E1(&pOutVertices[j - 1], &pOutVertices[j], &a1[i], &static_sub_4980B9_stru_AE4BEC) &&
+              _498774(&pOutVertices[j - 1], &pOutVertices[j], &a1[i], &static_sub_4980B9_stru_AE4BEC, &stru_AE4BFC))
+              AddVertex(&static_sub_4980B9_stru_AE3FE8, &stru_AE4BFC);
+        }
+
+        if (AreVectorsCollinear(&pOutVertices[j], &a1[i], &static_sub_4980B9_stru_AE4BEC))
+          AddVertex(&static_sub_4980B9_stru_AE3FE8, &pOutVertices[j]);
+      }
+
+      if (!static_sub_4980B9_stru_AE3FE8.uNumVertices)
+      {
+        *pOutNumVertices = 0;
+        return true;
+      }
+      if (_4989E1(&pOutVertices[*pOutNumVertices - 1], &pOutVertices[0], &a1[i], &static_sub_4980B9_stru_AE4BEC) &&
+          _498774(&pOutVertices[*pOutNumVertices - 1], &pOutVertices[0], &a1[i], &static_sub_4980B9_stru_AE4BEC, &stru_AE4BFC) )
+        AddVertex(&static_sub_4980B9_stru_AE3FE8, &stru_AE4BFC);
+
+      for (uint j = 0; j < static_sub_4980B9_stru_AE3FE8.uNumVertices; ++j)
+      {
+          pOutVertices[j].vWorldPosition.y = static_sub_4980B9_stru_AE3FE8.pVertices[j].vWorldPosition.x;
+          pOutVertices[j].vWorldPosition.y = static_sub_4980B9_stru_AE3FE8.pVertices[j].vWorldPosition.y;
+          pOutVertices[j].vWorldPosition.z = static_sub_4980B9_stru_AE3FE8.pVertices[j].vWorldPosition.z;
+          pOutVertices[j].u = static_sub_4980B9_stru_AE3FE8.pVertices[j].u;
+          pOutVertices[j].v = static_sub_4980B9_stru_AE3FE8.pVertices[j].v;
+      }
+      *pOutNumVertices = static_sub_4980B9_stru_AE3FE8.uNumVertices;
+    }
+  }
+
+  if (v25 < 3)
+    *pOutNumVertices = 0;
+
+  return true;
+}
+// AE4C2C: using guessed type char static_sub_4980B9_byte_AE4C2C_init_flag;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stru9.h	Sat Jan 12 09:45:18 2013 +0600
@@ -0,0 +1,63 @@
+#pragma once
+#include "Render.h"
+
+/*  341 */
+#pragma pack(push, 1)
+struct VertexBuffer
+{
+  //----- (0049835A) --------------------------------------------------------
+  inline VertexBuffer()
+  {
+    for (unsigned int i = 0; i < 64; ++i)
+      pVertices[i].flt_2C = 0.0f;
+
+    uNumVertices = 0;
+  }
+
+
+  RenderVertexSoft pVertices[64];
+  int uNumVertices;
+};
+#pragma pack(pop)
+
+
+
+
+/*  342 */
+#pragma pack(push, 1)
+struct stru312
+{
+  //----- (004BE6D1) --------------------------------------------------------
+  inline stru312()
+  {
+  }
+
+  float x;
+  float y;
+  float z;
+  char field_C;
+  char pad[3];
+};
+#pragma pack(pop)
+
+
+
+/*  126 */
+#pragma pack(push, 1)
+struct stru9
+{
+  //----- (00498093) --------------------------------------------------------
+  inline stru9()
+  {}
+
+  bool _4980B9(struct RenderVertexSoft *a1, unsigned int uNumVertices, float a3, float a4, float a5, struct RenderVertexSoft *pOutVertices, unsigned int *pOutNumVertices);
+  bool _498377(struct RenderVertexSoft *a1, unsigned int uNumVertices, struct IndoorCameraD3D_Vec4 *a3, struct RenderVertexSoft *pVertices, unsigned int *pOutNumVertices);
+  bool _4985FB(struct RenderVertexSoft *a1, signed int a2, struct RenderVertexSoft *a3, unsigned int *pOutNumVertices, struct Vec3_float_ *a5, float a6, char *a7, int unused);
+  void AddVertex(struct VertexBuffer *pVertexBuffer, struct RenderVertexSoft *pVertex);
+  bool _498774(struct RenderVertexSoft *a1, struct RenderVertexSoft *a2, struct RenderVertexSoft *a3, struct stru312 *a4, struct RenderVertexSoft *a5);
+  bool AreVectorsCollinear(struct RenderVertexSoft *a1, struct RenderVertexSoft *a2, struct stru312 *a3);
+  bool _4989E1(struct RenderVertexSoft *a1, struct RenderVertexSoft *a2, struct RenderVertexSoft *a3, struct stru312 *a4);
+
+  void (__thiscall ***vdestructor_ptr)(stru9 *, bool);
+};
+#pragma pack(pop)
\ No newline at end of file